Tag: PHP

Generate Dummy Placeholder Images in the WordPress Export File Instantly

It’s a common problem for the theme developers who sell their themes in the marketplaces and ships a data file with it, that contains exported data from the demo WordPress site. The problem is, this content file contains links to the images used in the demo. And those images, which the author uses to decorate his demo sites, may not be freely distributable.

So, theme developers have to create another site with placeholder images and then export data from this site. It’s a double work. It’s a boring work as well.

To save from this pain, I’ve created a site called DimgX which is available at http://dimgx.net that can deliver placeholder images on the fly. Using this service is pretty straight forward. If your image url is http://abcd.com/image.jpg all you have to do is add a dimgx.net at the end of the image domain, like http://abcd.com.dimgx.net/image.jpg

So if the url of the original image is http://d13yacurqjgara.cloudfront.net/users/6014/screenshots/2262615/coverdribbble.png which displays like this Artwork By Greg Christman

It’s placeholder image’s url will be http://d13yacurqjgara.cloudfront.net.dimgx.net/users/6014/screenshots/2262615/coverdribbble.png and it will show like this – Tada! You don’t have to worry about the original image’s dimension or anything. Everything will be handled by DimgX on the fly.

Using this feature, DimgX allows you to upload the exported content file from your WordPress site, which has an xml extension, and then download a modified content file having all the attachment urls replaced using dimgx.net. It’s pretty handy

DimgX replaces all the <guid> and <wp:attachment_url> in the export file, which contains links to the image files, and adds .dimgx.net at the end of those domain names in those image urls.

While creating a placeholder image, DimgX needs to calculate the size of the original image, to properly draw a placeholder with the same dimension. And in PHP, you know the only way to do it using getImageSize() function. People usually download whole image and then calculate these dimensions but that’s is a pretty expensive process when you have to download lots of bigger images. Fortunately, all these popular image formats contains these dimension in the first few KB in their header. So DimX doesn’t download the whole image but only a chunk of it. And then it uses that chunk of the header data to calculate this size. It makes the whole process fast, and less resource extensive. And while doing this, it also saves a good amount of bandwidth. To feed your appetite, here’s a part of that routine

[code lang=php]
switch ($extension) {
case "jpg" :
case "jpeg" :
$range = "0-50000";
break;
case "png":
$range = "0-10000";
break;
case "gif":
$range = "0-10";
break;
default:
$range = "0-15000";
break;
}

$ch = curl_init ($url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_BINARYTRANSFER,1);
curl_setopt($ch, CURLOPT_RANGE, $range);
[/code]

And here is the regular expression pattern that gets this complex URL replacement job beautifully done

[code lang=php]
$pattern1 = "/<guid([^>]+)>http://([^/]+)/([S]+)(.jpg|png|gif)</guid>/";
$pattern2 = "/<wp:attachment_url>http://([^/]+)/([S]+)(.jpg|png|gif)</wp:attachment_url>/";
$new_data = preg_replace($pattern1,'<guid${1}>http://${2}.dimgx.net/${3}${4}</guid>',$data);
$new_data = preg_replace($pattern2,'<wp:attachment_url>http://${1}.dimgx.net/${2}${3}</wp:attachment_url>',$new_data);
[/code]

Anyway, feel free to use DimgX at http://dimgx.net and let me know how you feel about this service. Right now, it can convert image urls that is served using http://, because wildcard SSLs are not cheap. But it’s in our roadmap. Stay tuned 🙂

Delegating Events Instead of Direct Binding in DOM

tumblr_n1rr53o21A1tubinno1_1280

When it comes to attaching event listeners, be it a particular element in the DOM, or a group of elements via CSS selectors, most of us bind the event listener directly to the elements. Direct binding is fine when you’re doing for a PARTICULAR element, but it may create problems for a group of elements if you’re not taking extra care while event binding. To understand the issue, let’s have a look at the following code block (Here’s a live example)

[sourcecode language=”html”]
<!– index.html –>
<div class="container" style="margin-bottom:50px;"></div>
<input type="button" value="Add More Buttons" id="addmore" />
[/sourcecode]

And we added the following javascript (depends on jQuery)

[sourcecode language=”javascript”]
;(function($){
$(document).ready(function(){
$("#addmore").on("click",function(){

var l = $(".container button").length+1;
$("<button/>").html("Click Me "+l).appendTo($(".container"));
$(".container button").on("click",function(){
alert("Clicked");
});

});
});
})(jQuery);
[/sourcecode]

Now if you add more and more buttons, you can see that it repeatedly attaching events. See the effect in the following animation

dom-1

To avoid these repeated bindings, you can modify your code like this and detach all the event listeners which were attached previously to these buttons.

[sourcecode language=”javascript”]
$(".container button").off("click");
$(".container button").on("click",function(){
alert("Clicked");
});
[/sourcecode]

This is boring, lengthy and sometime risky because you have to manually detach events everytime a new DOM element which satisfies your CSS selector rule adds in the container. And if you forgot to do that, chances are higher to break something somewhere.

Now, to save from this pain, jQuery had introduced event delegation which doesn’t bind the event listener to the dom elements but it delegates the event from their parent. This way, you will never have to worry about detaching previous attached event listeners anymore. Let’s have a look at our final code block, and here is a live example too

[sourcecode language=”javascript”]
;(function($){
$(document).ready(function(){

//event delegation
$(".container").on("click","button",function(){
alert("Clicked");
});

$("#addmore").on("click",function(){

var l = $(".container button").length+1;
$("<button/>").html("Click Me "+l).appendTo($(".container"));

});
});
})(jQuery);
[/sourcecode]

In the above example see how we have delegated the click event to every “button” in the container div. Once the delegation is done, it doesn’t matter whenever a new dom element (in this case, a “button”) inserts in the container. It will always capture the “click” event because the parent div “.container” will delegate that event to it properly. All you have to do is select a parent element, and then delegate the event to childrens (via CSS selector) belonging to it. It’s the same .on() method, just takes an extra parameter in the middle which represents the CSS selector to which the event will be delegated.

[sourcecode language=”javascript”]
//event delegation
$(".container").on("click","button",function(){
alert("Clicked");
});
[/sourcecode]

By using event delegation in jQuery for a group of DOM elements, you can avoid risks, keep your code cleaner and save yourself from some overkill every time. Hope you’ve liked this article 🙂

Manipulating browser URL using Javascript without refreshing the page

In modern browsers, one of the most interesting feature is that you can change the browser url without refreshing the page. During this process you can store the state of the history so that you can pull the necessary data when someone hits the back-button in the browser and then take necessary action based on that. It’s not as complicated as it may sound now. Let’s write some code to see how it works.

[sourcecode language=”javascript”]
var stateObject = {};
var title = "Wow Title";
var newUrl = "/my/awesome/url";
history.pushState(stateObject,title,newUrl);
[/sourcecode]

History objects pushState() method takes three parameter as you can see in the above example. First one, a json object, is very important. Because this is where you will be storing arbitrary data related to the current url. Second parameter will be the title of the document, and third one is the new url. You will see your browser’s address bar is updated with the new url, but the page was not refreshed 🙂

Let’s see another example where we will be storing some arbitrary data against each url.

[sourcecode language=”javascript”]
for(i=0;i<5;i++){
var stateObject = {id: i};
var title = "Wow Title "+i;
var newUrl = "/my/awesome/url/"+i;
history.pushState(stateObject,title,newUrl);
}
[/sourcecode]

Now run and hit the browser back button to see how the url is being changed. For each time the url is changed, it is storing a history state object with the value “id”. But how can retrieve the history state and do something based on that. We need to add an event listener for “popstate” event which is fired everytime the history object’s state is changed.

[sourcecode language=”javascript”]
for(i=0;i<5;i++){
var stateObject = {id: i};
var title = "Wow Title "+i;
var newUrl = "/my/awesome/url/"+i;
history.pushState(stateObject,title,newUrl);
alert(i);
}

window.addEventListener(‘popstate’, function(event) {
readState(event.state);
});

function readState(data){
alert(data.id);
}
[/sourcecode]

Now you can see whenever you hit the back button, a “popstate” event is fired. Our event listener then retrieves the history state object which was associated with that url and prompt the value of “id”.

It’s easy and pretty interesting, eh?

LAMP Training for GrameenPhone: Download the course materials

Last November, 2009 I conducted the course on Basic LAMP in GrameenPhone and it was really fun. It was a 7 days course. You can download the complete course materials from the following link

Download LAMP Course Materials for GrameenPhone

Just in case you are interested to know what was covered in those 7 days, here you go

Day 1: Basic Linux and PHP Primer (Sorry, no slide for that day)
Day 2: MySQL Primer
Day 3: More Database, File upload and OOP
Day 4: Day 4: String, DateTime, Parsing XML, Regular Expression, Javascript and Ajax
Day 5: Introduction to Zend Framework
Day 6: Introduction to CodeIgniter
Day 7: Chart and Graphs, Google Translation, Visualisaion and Security

If u find it interesting, you can download from the following link. There might be some typo, please overlook them 🙂
Download LAMP Course Materials for GrameenPhone

Bug in twitter prevents you from updating your status

I’ve found it last night while trying to update my status in twitter. these days I am too much twittering and I was redirected to an url while exploring twitter. while trying to update my status, it failed repeatedly and then i’ve found that bug – lol

the url that reproduces the bug is http://explore.twitter.com/home – which looks similar to your actual twitter home (http://twitter.com/home) and it also shows you a twit box to update your status. but you cannot update your status from http://explore.twitter.com/home

check what was returned after the ajax request (u have firebug, right? do it yourself)

403 Forbidden: The server understood the request, but is refusing to fulfill it. If you are posting from an API tool please ensure that the HTTP_REFERER header is not set.

try before they fix it 🙂 interesting usability bug indeed.

What a day!!

……….

……..zzzzzzzzzzzzz…….

whoops!! it is 11 AM

trying to restore apache2 when it was corrupted after a system update last evening

grrrrrrrrrrr – what the hell!! – mod-php5 is not working at all!

grrrrrrrrrrrrrrrrr

…zzzzzzzzzzzzzzz….

…whoops its 5PM

raju came with his new laptop, failed to setup his EST-610U EDGE card on Ubuntu, Modprobe was not working with even a vendor and a product id

its 6PM – went to north tower and had some mango juice

around 6:30 PM, ahsan and anupom came and gave me a copy of their new book, CakePHP

7:30 manzil, junal, ahsan and anupom came and we enjoyed the movie “Death Sentence” together

10 PM, I went to Omi Azad‘s apartment with Ayesha and Afif – had two scoops of icecream…. yummy!!

11PM – came to home and start setting up xampp – found that xampp is set to use it’s own mysql socket instead of the system default. so edited the bundled php.ini and set the following line to use my previous mysql installation properly
mysql.default_socket = /var/run/mysqld/mysqld.sock

sometime later 11PM, xampp is now working, setup postgreSQL addon and mod_python. the python addon was not working becoz of the version conflict of mod_python.so. So I’ve installed “libapache2-mod-python” and copied the /usr/lib/apache2/modules/mod_python.so to /opt/lampp/modules/ folder – python is now working

around 12, Ayesha and I had our dinner.

1AM to 3AM, playing with GPG and setup a new key pair. My new public key is 2FD0F9E9

3:08AM – wrote this blog post and preparing to sleep. must be a busy day tomorrow!

whoops!!