Reasons why I wrote the plugin Jquery Asynchronous Image Loader (JAIL)

04/01/2011 § 13 Comments


The need for a plugin that loads images asynchronously comes from the will of improving the page load time and making the user experience enjoyable/acceptable when there are heavy images
in a page. When there are images on a page, the browser makes HTTP requests to download them and in case there are many of them and they have
large size, it can take a while to load the rest of the page. The user will see the content below the images with some delay and the user experience won’t be that pleasant.
In mobile sites, I find this problem quite critical, as the user will especially feel the effects of this delay.

Deferring the loading of the images can be the solution and that’s what my plugin is about.

Before to have started writing it though, I researched on the net if there was something already that could solve my issue. Well, of course someone else has already thought about this problem and has already implemented something good. That’s what I found:

YUI ImageLoader Utility : utility from YUI3, that delays the loading of the images and
lets you determine triggers and time limits to initiate image loading. You can find more info on their web page and I believe it’s a great utility (like all YUI3 library great code as well)
This utility requires some HTML change, such as leaving out the “src” attribute from the IMG tag.

There are few things about this solution that weren’t good for my purpose though (in order of importance):
a) Disabling JavaScript, the images are not loaded. That was surprising! They didn’t care about progressive enhancement.
b) I can customize a trigger to load the images, but I can’t customize a callback function after the images are loaded.
c) I’ve already got jQuery in my page, I’d like not use another JS library for page performance reasons. (other JS code to download)

Lazy Loading Plugin for jQuery : plugin for jQuery written by Mika Tuupola.
This solution was respecting the progressive enhancement and was solving above a) and c)! It seems the way to go.
Just a couple of things go bad:
a) In the homepage it’s clearly written that the plugin is currently not usable.😦
b) Refreshing the demo page with the Net tab of Firebug opened, the images “below” the fold are loaded.
So something must go wrong at least in my browser FF 3.6 on Mac.

I decided to take notes from this previous solutions and in order to achieve what I needed for the site I was working on, I wrote my own plugin for jQuery, called
JAIL aka Jquery Asynchronous Image Loader. The whole solution respects the concept of progressive enhancement, you can customize a callback function and it requires jQuery of course.

You can find the source on Github and the project homepage here.

It’s lightweight (compressed version is 4Kb), it’s licensed under MIT and GPL v3 and it’s been tested with jQuery 1.3.2+ on FF2+, IE6+, Chrome5+, Opera 10+, Safari3+.

Just some quick notes, this plugin is not for all the cases and it’s not supposed to be applied to all the images. It required some HTML changes so you need to be able
to modify the HTML, and I’d suggest to use it for “heavy” images and for mobile sites.

UPDATE (19/12/2011) : Version 0.7 released. Added support for ‘offset’ configuration

UPDATE (03/04/2011) : Version 0.8 released – jail() function, fixed critical issue on v0.7, resizing function, scrolling fixes

UPDATE (03/08/2011) : Version 0.9.5 released – Issue 14 fixed regarding applying event on container different from ‘window’, filenames changed.

Enumeration in JavaScript

07/12/2010 § Leave a comment


In the previous post, I mentioned that I would have talked about the “FOR-IN loop” in this post, and that’s what I’m about to do. So reading the title, you can gather how “for-in” loop is used for Enumeration in JavaScript.

What does it mean?

It means that if you want to enumerate the properties inside a JavaScript object, you need to use this type of loop. This is an example:

// Object literal
var myObject = {
    field : "myfield",
    mymethod : function(){
        return "hello";
    }
}

// for-in loop
for (i in myObject) {
    console.log(i) //"field", "mymethod"
}

The console will print the properties of the object, so the field and the method.

Coming back to my previous post, one of the issue with this loop is that is taking under consideration even all the objects involved in the prototypal chain, so that if we augment the Object with a new property the for-in loop will consider even this last one.

Object.prototype.newMethod = "string";
// Object literal
var myObject = {
    field : "myfield",
    mymethod : function(){
        return "hello";
    }
}
// for-in loop
for (i in myObject) {
    console.log(i) //"field", "mymethod", "newMethod"
}

To avoid this inconvenient, we can use the method hasOwnProperty() which returns true if the property belongs to the object itself (not considering the prototype), so that:

Object.prototype.newMethod = "string";
// Object literal
var myObject = {
    field : "myfield",
    mymethod : function(){
        return "hello";
    }
}
// for-in loop
for (i in myObject) {
    if(myObject.hasOwnProperty(i)){
        console.log(i) //"field", "mymethod"
    }
}

In this case we get what we possibly were expecting!

In ECMAScript 5, few enhancements have been made and now you can define a property (Object.defineProperty method) and you can use the method Object.keys(obj) to return an array of the properties belonging to that object without the need of using the “dirty” hasOwnProperty(). That’s how you could rewrite the previous code in ECMAScript 5:

"use strict"
var myObject = {
    field : "myfield",
    mymethod : function(){
        return "hello";
    }
}
Object.keys(myObject); //["field", "mymethod"]

Best way to loop through an Array in JavaScript

06/12/2010 § 4 Comments


Last week, a colleague of mine asked me “Why are you using a ‘standard for loop’ rather than the faster ‘for-in loop’ to loop through an Array in JavaScript?” and for this reason I’m going to write a short explanation about that.

First of all, when I talk about the standard “FOR loop“, I mean something like

for (var i=0; i < myArray.length; i++){}

instead the “FOR-IN loop” is something like:

for (var i in myArray){}

for-in loop is faster…just to type, for a lazy developer:) and it’s a common mistake especially for developers coming from Java programming (I’m a Java developer as well, that’s why I know that :P), trying to port Java into JavaScript.

The two main problems with for-in loop are :
1) It enumerates through all the properties even the ones associated to the Object (that can be augmented previously)
2) The order of the elements is not guaranteed.

You may not interested in the order of the elements(even if often you are), but you need to deal with the first issue and that’s what can happen:

var myArray = ["aa", "bb"];
// Object() augmented
Object.prototype.newMethod = "cc";
// for-in loop
for (var i in myArray) {
    console.log(myArray[i]); //"aa", bb", "cc"
}

The console will print not only the two elements from the array, but also the value of the new property in the Object. Remember that array are objects in JavaScript, at the root of the prototypal chain there is always Object and you never know if Object has augmented previously by a library or some script.

The correct way to execute that loop is using the for loop:

var myArray = ["aa", "bb"];
// Object() augmented
Object.prototype.newMethod = "cc";
//for loop
for (var i=0; i < myArray.length; i++) {
    console.log(myArray[i]); //"aa", bb"
}

Actually, we can make a micro-optimization to this, “caching” the length of the array and avoiding every time to calculate the length of the array.

var myArray = ["aa", "bb"];
for (var i=0, tot=myArray.length; i < tot; i++) {
    console.log(myArray[i]); //"aa", bb"
}

Notice that there is a comma between “var i=0” and “tot=myArray.length” as the “for loop” accepts three expressions.

If you find this last way a bit weird, you could do something like:

var myArray = ["aa", "bb"], i=0;
for (tot=myArray.length; i < tot; i++) {
    console.log(myArray[i]); //"aa", bb"
}

So it’s strongly recommended to use the FOR LOOP to loop through an Array and remember that Java and JavaScript are different.

In the next post, I may go through where the “for-in” loop is used.

Understanding WebStorage

22/11/2010 § 2 Comments


WebStorage is one the HTML5 features and it makes the browser capable to store information. Well, we have always been using Cookies, but they have few limitations and let’s see how WebStorage feature can fix these limitations.

Case 1: A user has two different windows opened and he wants to make two transactions on the same site. Using cookies, you could have “leaks” between windows and there is no clear distinction between the windows. WebStorage includes sessionStorage object and each window will have a different copy of this object, making each window being “independent”. As you can tell from the name this object is limited to a session, so as soon as you close your browser window, it will be erased.

Case 2: The site needs to keep information in common across multiple windows and even after the session is closed. Cookies are relative to each request so they can’t handle this case properly. WebStorage includes localStorage object and it’s relative to a specific domain and it lasts even after a session is finished.

Other thing, a cookie can have maximum size of 4Kb, Storage object can have size of 5Mb (quite standardized value in all browsers).

Reading the W3C specs, those are the methods for the Storage objects:

interface Storage {
    readonly attribute unsigned long length;
    getter DOMString key(in unsigned long index);
    getter any getItem(in DOMString key);
    setter creator void setItem(in DOMString key, in any value);
    deleter void removeItem(in DOMString key);
    void clear();
};

Let’s make some examples to understand better this methods:

localStorage.setItem("firstKey", "firstValue");
window.localStorage.getItem("firstKey"); //firstValue

This is really a basic use and show us how to use “setItem” and “getItem” methods. You can notice how you can use either “localStorage” or “window.localStorage”, this is because localStorage is attached to the window object. Also, the key/value are two strings, or better you can even set an object as value but you’d better “stringify” it (transforming it in a string using the stringify JSON method). Let’s see an example first trying to push an object in a Storage object without “stringify”:

localStorage.setItem("secondKey", {id : 1});
localStorage.getItem("secondKey"); // "[object Object]"

“[object Object]” is the String we get but we can’t get the real object. That’s how we can fix it:

localStorage.setItem("secondKey", JSON.stringify({id : 1}));
var a = JSON.parse(localStorage.getItem("secondKey")); // Object {id=1}
a.id; // 1

We used JSON stringify method and JSON parse method, that are useful to transform a JSON object in a string and viceversa. JSON object is now available in HTML5, but it’s not fully supported in all browsers, so you may want to download json.js written by Douglas Crockford, Yahoo JS Architect and in my opinion the maximum expert on JavaScript.

Let’s explore other methods available:

localStorage.removeItem("secondKey")
localStorage.length; // 1
localStorage.key(0); //"firstKey
localStorage.clear();
localStorage.length; //0

they are quite straightforward methods: “removeItem(index)” will remove the key/value, “length” will return the number of key/value, “key(index)” will return the key for that index (0-based), “clear()” will remove all key/value.

Notice that I’ve been using localStorage in those example but I could use sessionStorage as well, as they share the same methods, coming from the same Interface.

You may meet another object called “globalStorage”, but remember that it’s been removed from the specs from Security reasons. It was basically holding different “localStorage” objects depending on the domain. So now “localStorage” for http://www.domain.com is different from “localStorage” for “a.domain.com” or “domain.com”.

Other feature is the “storage” event, which is triggered when the storage has change (using “setItem”, “clear”..). It has few attributes:
– key : key being changed
– oldValue : old value of the key before being changed
– newValue : new value of the key after being changed
– url : url of the document where the storage has been changed
– storageArea : storage object being changed (local or session)

Last thing, it’s supported in all modern browsers..and IE8! Suprising!

You wanna know more?
Have a read here (great writing from Mark Pilgrim) or have a look at the W3C Specs

Understanding Array.prototype.slice.apply(arguments) in JavaScript

12/11/2010 § 10 Comments


If you are a JavaScript developer soon or later you’ll bump into this guy: Array.prototype.slice.apply(arguments) and you’ll ask yourself..what the hell is that??

Well, it’s not that hard to understand actually, it’s just ugly. Anyway, “Array” is the JS class Array, with “Array.prototype” you get its prototype. I assume you know about the prototype, the key concept in JavaScript.

slice” is a method in JavaScript that “selects a part of an array, and returns the new array.” (W3CSchool). It can have two arguments : start_index(required), end_index.
So given:

var a = ["a", "b", "c"];
a.slice(1,2);

It return [“b”], so an array containing the element between index ‘1’ and index ‘2’ in the Array “a”.

var a = ["a", "b", "c"];
a.slice(1);

It return [“b”, “c”], so an array containing the elements between index ‘1’ and last index in the a, which is an Array.

So “a” is an Array of course, what about “arguments” variable?

Ok, arguments, you know, it’s the implicit JS variable created when you invoke a function, containing the arguments of a function. You’re expecting this variable to be an Array, right?
Well, it’s not, it’s similar, but it’s still an object, so:

function f () {
return arguments;
}

given this function f, launching
f("1", "2") instanceof Array

you’ll get FALSE! That means we can’t apply a bunch of stuff we normally do with an Array, such as push, pop, slice..but I need those methods, so what can I do?

There you go Array.prototype.slice.apply(arguments) converts arguments into an ARRAY.

Here we use one of the methods to call a function in JavaScript, the APPLY method, you can learn more about how to call a function in JS here.
So we apply the slice function to the first argument of the apply function(in this case “arguments”) and we know that the slice() method returns always an Array. We got our Array!

So now
Array.prototype.slice.apply(f("1", "2")) instanceof Array

it’ll return TRUE!

PS: In ECMAScript5, we won’t need to use “Array.prototype.slice.apply(arguments)” anymore, but we can easily use arguments.slice()!

How to redirect your site to a mobile version through JavaScript

02/11/2010 § 160 Comments


SCENARIO :

The user needs to be redirected to the mobile version of the site (home page) if it’s trying to access the site from a mobile device.

SOLUTION:

UPDATE 25/07/2011 : Version 0.9.5 released with support for “tablet_url”, “keep_path” and “keep_query” properties. Ipad and other tablet devices have been excluded from the list of mobile devices by default. You can use “tablet_redirection” and “tablet_url” parameters for tablets.

To solve this problem, the best approach is implementing something server-side, and I find a good approach using the WURFL file to check the capabilities and features of mobile devices. Read here to know more about WURFL.

Sometimes, a server-side solution can become difficult to implement especially if we have a CDN or reverse proxy (sitting in front of our Web Server) caching our pages.

Here JavaScript comes to the rescue and I wrote a script that makes the redirection happen called “redirection_mobile.js“.

You can find the source here on Github.

The first thing to keep in mind is that the function implemented checks the User-Agent string from the Navigator object and from there it decides if the redirection needs to happen.

In some cases the user wants to access to the Desktop version of the site from a mobile device (sometimes the desktop version has more functionality). The script handles this situation as well, it checks if the previous page hit was one from the mobile site (we can suppose the user clicked on a link such “Go to full site“) or if there is a specific parameter in the querystring of the URL. In those cases the redirection won’t occur. To keep the user in the desktop version for the whole session, sessionStorage object has been used, specifically an item will be stored to distinguish if we’re browsing through the desktop site.
There is a fallback for old browsers that don’t support sessionStorage, and a cookie will be used. The cookie that makes the access to the desktop version from a mobile device possible will expiry in one hour or you configure the expiry time.

iPhone, iPad, iPod, Android phones support completely sessionStorage, there are still some versions of Blackberry that using IE don’t and so we still need the “cookie” fallback.

The function accepts an argument which is a configuration object with few properties:

mobile_prefix : prefix appended to the hostname, such as “m” to redirect to “m.domain.com”. “m” is the default value if the property is not specified.
mobile_url : mobile url to use for the redirection (without the protocol), such as “whatever.com”/example to redirect to “whatever.com/example”. If “mobile_prefix” is existing as well, “mobile_prefix” will be ignored. Empty string is the default value.
mobile_scheme : url scheme (http/https) of the mobile site domain, such as “https” to redirect to “https://m.domain.com&#8221;. The protocol of the current page is the default value.
noredirection_param – up to version 0.6 param was used: parameter to pass in the querystring of the URL to avoid the redirection (the value must be equal to “true”). Default value is “noredirection”. Eg: http://domain.com?noredirection=true. It’s also the name of the item in the localStorage (or cookie name) used to avoid mobile redirection. Prior version 0.9.5 this parameter was called “redirection_paramName”, but I renamed it to make the meaning clearer.
cookie_hours : number of hours the cookie needs to exist after redirection to desktop site. “1” is the default value.
tablet_redirection : boolean value that enables/disables(default) the redirection for tablet such as iPad, Samsung Galaxy Tab, Kindle or Motorola Xoom. – Default:false. The value needs to be a string (so wrapped in double or single quotes). If ‘tablet_url’ parameter not specified, the user will be redirected to the same URL as for mobile devices.
tablet_url : url to use for the redirection in case the user is using a tablet to access the site. Default value is “”
keep_path : boolean to determine if the destination url needs to keep the path from the original url. Default value is ‘false’
keep_query : boolean to determine if the destination url needs to keep the querystring from the original url. Default value is ‘false’
beforeredirection_callback : if specified, callback launched before the redirection happens. If a falsy value is returned from the callback the redirection doesn’t happen.

To use “redirection_mobile” function, you need to load your script in the HTML of the “desktop” pages and call it as SA.redirection_mobile(config). See the code below:

<!doctype html>
<html>
    <head>
        <title></title>
        <script type="text/javascript" src="/js/redirection_mobile.min.js"/>
        <script type="text/javascript">
            SA.redirection_mobile ({noredirection_param:"noredirection", mobile_prefix : "mobile", cookie_hours : "2" });
        </script>

For instance, in this case, accessing from a mobile device to http://www.domain.com, you’ll be redirected to “http://mobile.domain.com“.
Considering the previous code, from version 0.6, if you hit a page such as “http://domain.com/?noredirection=true” the redirection won’t happen. For all the browser session, if sessionStorage is supported by the browser, the redirection won’t occur. If sessionStorage (HTML5) is not supported, a cookie “noredirection=true” will be stored for 2 hours and it will block the redirection to the mobile site.

If sessionStorage (HTML5) is not supported, a cookie named “noredirection” will be stored for 2 hours and it will block the redirection to the mobile site.

The script from version 0.5 allows you to redirect the user to whatever url. Thus if you need to redirect the user to “https://domain2.com/mobile” now you can invoke the function like this:

    <script type="text/javascript">
        SA.redirection_mobile ({mobile_scheme:"https", mobile_url : "domain2.com/mobile"});
    </script>

Alternatively you can use “redirection_mobile_self.js”, that is it’s an anonyimous self-executing function and it uses it uses the default values for the different properties:

– “mobile_prefix” : “m”
– “redirection_paramName” : “mobile_redirect”
– “cookie_hours” : 1
– “mobile_url” : “”
– “mobile_scheme” : protocol of the current page
– “tablet_redirection” : false
– “beforeredirection_callback” : n/a

It doesn’t need any configuration or any invocation, so you just need to drop it on your webserver and call the script from the HTML of the “desktop” pages . See code below:

<!doctype html>
<html>
    <head>
        <title></title>
        <script type="text/javascript" src="/js/redirection_mobile_self.min.js"/>

in this case, accessing from a mobile device to http://www.domain.com, you’ll be redirected to “http://m.domain.com“.

To redirect to a desktop/standard version of the site from a mobile device, you may need to embed a link in your mobile pages such as

<a href="http://www.domain.com">Go to main site</a>

and the script included in the desktop page will do the rest.

I also created “redirection_mobile_testable.js” that is just a copy from “redirection_mobile.js”, but it’s using few arguments such as “document”, “window”, “navigator” for testing purpose. Test cases have been written, using QUnit, to test this script and they mock “document”, “window” and “navigator” in a rudimentary way.

The scripts have their minified versions (used YUI compressor).

If you want to test the script on different devises within your desktop browser, you can use a plugin for Firefox called User Agent Switcher, that you can download here.

Feel free to fork the project and improve it if necessary.

..and feel free to make a donation from this page

UPDATE 20/12/2010 : Added support for more devices and fixed a critical issue on IE

UPDATE 05/01/2011 : Version 0.5 released with support for “mobile_url” and “mobile_scheme” properties

UPDATE 02/04/2011 : Version 0.8 released with support for “ipad_redirection” and “beforeredirection_callback” properties

You can support me clicking the DONATE button you can find on my site http://www.sebastianoarmelibattana.com/projects/js-redirection

How to update a Basic Asset in Fatwire Content Server

20/10/2010 § Leave a comment


These are the STEPS on how to update a Basic Asset Descriptor File, without causing any side effects:

1 – Update the Asset Descriptor File (from AssetType table)

2 – Launching SQL scripts to update the DB keeping consistency with the ADF

3 – Registering the Assets from the Fatwire Interface (Admin tab):

Initially I was just updating the ADF, without updating the DB (thinking it was done automatically) but it was causing duplication of assets and weird messages for those fields I changed. So, remember to follow these steps and you’ll be safe😉

Where Am I?

You are currently browsing the Web category at Sebastiano Armeli's Tech Blog.

Follow

Get every new post delivered to your Inbox.