Thursday, October 18, 2012

JQuery Basics - Understanding the insight -4

In this article we will go in the details of jquery selectors. JQuery provides $() or jQuery() to select any element. we can pass any selector in it and it will return a jquery object. If there is nothing available on the DOM with matching selector then an empty jquery object is returned.
$() is same as jQuery().

Context in selector -
When we pass any selector in the $() it start looking for the match starting from the root of DOM, but its always possible to put a context in for the search. For example -

<p> This para is outside DIV</p>
<div id="root">
    <div id="child1" class="div1">
        <p>Hi this is 1st para.</p>
        <p>Hi this is 2nd para.</p>
        <p>Hi this is 3rd para.</p>
    </div>  
</div>

In the above example say if we want to have a functionality where if i click on any div element, every paragraph in it should get background as red. If i use the following script -

$(document).ready(function(){
    jQuery("div").click(function(){
        $('p').css("background","blue");
    });
});
It will change the background of every paragraph, but its possible to limit the scope of click only to those paragraphs which are within div element like this -

$(document).ready(function(){
    jQuery("div").click(function(){
        $('p',$(this)).css("background","blue");
    });
});

what will happend in the following scenario -
<p> This para is outside DIV</p>

<div class="root">
    <div id="child1" class="div1">
        <p>Hi this is 1st para.</p>
        <p>Hi this is 2nd para.</p>
        <p>Hi this is 3rd para.</p>
    </div>
    <div id="child2" class="div2">
        <p id="child2Para1">This is another paragraph1 .</p>
        <p id="child2Para2">This is another paragraph2 .</p>
        <p id="child2Para3">This is another paragraph3 .</p>
    </div>
</div>

Now if we execute following script -$('p',$(this)).css("background","blue"); 1st it will change the background of the div we clicked and then it will bubble up to root div and will change the background of every paragraph(including those available in other child as well) in it. If you want to verify it, attach a debugger and check the value of $(this)[0], first run will have its value as the child div and then it will be root div.

The same functionality can also be achieved in the following way -

$(this).find('p').css("background","blue");
putting context in $() does the same thing that find() does. Infect it internally calls find method to do the same thing, hence directly using find() will be faster then using context in selector.

Working With Plain JavaScript Objects-
If we pass any javascript object in $() then it converts it into a jquery object(which is an array).  These are the methods available in jquery object -.data(),.prop(),.bind(), .unbind(), .trigger() and .triggerHandler().

    var localObj = {"key1":"value1", "key2":"value2"};
    var $jqueryObj = $(localObj); // its jquery object
    alert($jqueryObj.prop("key1")); //alerts value1,
    $jqueryObj.prop('key3','value3'); // it adds new property to the object.
.prop() helps us to add new value in the object, but it doesn't mean that original object will also get the new value, that is because once we pass javascript object in $() it creates a copy of it and wraps it into new jquery object.

Saturday, October 13, 2012

JQuery Basics - Understand the insight -3

JQuery provides different  ways to remove any element or its content from the DOM, we will do comparative study to understand the different between those.

Empty() - Remove all child nodes of the set of matched elements from the DOM.
It removes the content of the selector, NOT the node itself.  For example -
<div class="div1">Div1</div>
<div class="div2">Div2</div>
$(".div1").empty();
It will result in following html -

<div class="div1"></div>
<div class="div2">Div2</div>

If we had any child/nested element in it, then those would also been removed.

Remove() -Remove the set of matched elements from the DOM
It removes the complete element itself.
<div class="div1">Div1</div>
<div class="div2">Div2</div>
$(".div1").remove();
It will result in following html -

<div class="div2">Div2</div>
 
Detach() - Remove the set of matched elements from the DOM
detach is very much similar to remove(), except detach keeps all the jquery data like events subscribed, so that once we add this element again with DOM, all that data can be associate with this node again.

JQuery Events- Understand the insight - 2

JQuery provides different methods to attach an event to any element. All those method does the same thing but are different in some aspects like how the event get attached to an element and how does it get fired once an actions take place.
Lets try to understand all the methods provided by JQuery and see how do they differ from each other.

Here is the Html code we will use for all the jquery examples -
<div id="root">
    <div id="child1">
        <p>Hi this is para.</p>
    </div>
    <div id="child2">
        <p id="child2Para">This is another paragraph.</p>
    </div>
    <div class="EmptyDiv">
        Empty Div
    </div>
</div>

Bind() - Attach a handler to an event for the elements. When we use Bind method, the JQuery traverse the whole DOM tree and check if the selector matches, then attach the event with the element. When the action happens(click), the event get fired from the element directly, and bubbles up. 
We can attach multiple events also. Here is the example -
 $(document).ready(function(){
    $("#child2").bind('click',function(){
        alert('child 2 clicked');
    });
});
If we click on child2, then it will alert "child 2 clicked". Following example shows how to attach multiple events -
$(document).ready(function(){
    $("#child2").bind({'click':function(){
        alert('child 2 clicked');
    }, mouseenter: function() {
        alert('Mouse enter to child2');
    }});
});
If there are multiple events that need to be fired on same action, then they will be fired in the sequence of subscription.
Drawback- In this case the subscription can be little expensive for large DOM structure, as the Jquery traverse the whole DOM tree and attaches the event to the element. 

live() - Attach an event handler for all elements which match the current selector, now and in the future.
In case of Bind the handler get attached to the element itself, but in case of live the handler get attached to the document object.
Here is example which demonstrate the behavior -
$(document).ready(function(){
    $("p").live({'click':function(){
        alert('paragraph clicked');
        $(this).after("New Paragraph
");
    }});
});
In the above code if you click on paragraph it will append new paragraph in the page. The new paragraph will also have this event attached. If you replace the live with bind in above code you wont find the event attached with the newly create paragraphs.
Drawback- live() method is no longer recommended.  Because it have performance and chaining related issues. As the live event get attached to document object by default(because no context is mentioned), thus once we click on any element, then the javascript will traverse whole DOM tree to find that element and execute the handler

delegate()- Attach a handler to one or more events for all elements that match the selector, now or in the future, based on a specific set of root elements. It is very much similar to the live() function, except in this case the event get attached to the element(like Bind()) not with the document object.  So the performance hit we get in case of live() wont be applicable in this case.
The above code can be re-written using delegate in the following way -
$(document).ready(function(){
    $("body").delegate("p",{'click':function(){
        alert('paragraph clicked');  
        $(this).after("New Paragraph
");    
    }});
    $("body").delegate("div",{'click': function(){
        alert('div clicked');
    }});
});
Drawback - The drawbacks are very much similar to the one mentioned in Bind, that is if the DOM tree is big then while subscription we might face some performance hit.


On() - Attach an event handler function for one or more events to the selected elements.
It is the combination of delegate and Bind and most recommended event subscription method provided by Jquery. If we pass the selector in the on function then it behave like delegate, and if we skip it, it works like Bind() method. Here are the example -
$(document).ready(function(){
    $("body").on("click", "p", function(){
        alert('paragraph clicked');
        $(this).after("New Paragraph
");
    });
});
Above code works similar to the delegate, and if we remove the "p" as second parameter it will behave like Bind().

Stop Bubbling of Event-
you can return false from the event handler to stop its propogation to the parent elements. Once we do it, it internally calls event.stopPropogation().

JQuery Basics- Understand the insight -1

Lets start understanding basics of JQuery. The syntax if JQuery can be found on its home page or in anyother book, but here we will understand how those APIs are working on top of the JavaScript API. JQuery is built upon JavaScript only. IT wraps the javascript functions in its own wrapper and provide user a sophisticated way of using javascript. Lets start understanding the APIs and how those are different from JavaScript.

$(document).ready Vs window.onload -
There difference between two functions that is the $(document).ready is very much specific to JQuery but the window.onload is JavaScript specific. moreover window.onload waits until all the resources have been loaded, whereas the $(document).ready waits until the DOM is loaded, it wont wait for other resources to load. Here is the code snippet which shows how to use this API -

    $(document).ready(function(){
        alert("Jquery Ready");
    });
    window.onload = windowLoad;
    function windowLoad(){
        alert("Window loaded");
    }
In order to see the difference between these 2, try to load a heavy image and check which event get fired first.

$(this) Vs this -
when we wrap this in the $()then it get converted into JQuery object. Using this we can execute the jquery methods on this object. Internally whenever we put any object inside $(), JQuery converts it into an array, and if we know there is just a single object in it, then we can directly access it using indexer, which means -
$(this)[0] == this will return true.

I ll consider following HTML for all preceding examples -

<div id="root">
    <div id="child1">
        <p>Hi this is para.</p>
    </div>
    <div id="child2">
        <p id="child2Para">This is another paragraph.</p>
    </div>
    <div class="EmptyDiv">
        Empty Div
    </div>
</div>

JQuery Selectors- $() allows you to select element and work on them. Internally its calls different JavaScript APIs like getElementById, ByName etc. to fetch the actual element. But all that dirty code is hidden from user and JQuery have provided really an awesome wrapper to us.
Here are few examples of different kind of selectors available. There are many more ways to select elements in JQuery, but here very basic tricks are covered-
All selectors - "*"
Find every element (including head, body, etc) in the document.
//All selector
$("*").css("background","yellow"); // sets background of all elements to yellow
//ID selection
$("#child2").css("border","5px solid"); // sets the border of element with id child2. It is equivalent to document.getElementById method in JavaScript.
//Class selection
$(".EmptyDiv").css("border","5px solid blue"); // sets the border of (all the)element(s) with class EmptyDiv.
//Element selection
$("p").css("background","blue"); // Sets the background for all paragraphs
//Multiple selection
$("#child1, .EmptyDiv").css("background","green"); // selects multiple element/class/Ids etc. to be worked on
//Hierarchy selection
$("div p").css("border","2px solid red"); // sets border of all paragraph inside every div.
$("#child2 p").css("background","orange"); // Sets background of paragraph inside element with Id child2

width() Vs css('width') -
In JQuery you can access width/height of any element in 2 ways -
    alert($("#child1").width()); // number
    alert($("#child1").css('width')); // number px
The only difference is the return type. width() function returns the width as number, which can be used in any other manupulation if required, whereas the .css('width') returns the width with px as unit in single string, which can be used for further assignment but not in any mathematical manupulations.

HTML() vs innerHtml() -
JQuery Html() method can be used to get any html content of any element(can be selected by jquery selectors).This method internally calls innerHtml javascript function. It is safe to call html() rather then innerhtml(), because if you are calling html() on an element which does not exist, this function will return you undefined object, but the innerhtml will thrown a javascript error. In other words, JQuery have wrapped innerHtml with html() function with proper error handling.

Thursday, October 11, 2012

Cookies in JavaScript

Cookie is one of the most important concept in web design which help you to maintain some state in a stateless environment. Of course there are different views with respect to security of cookie, but it doesn't mean we shouldn't use it. While using we need to make sure that we don't have any sensitive data in the cookie. because its very easy for any hacker to read it from your browser.
Lets start understanding how can we play with cookies in JavaScript, but before that lets have a look at the structure of cookie.If you open browser and check how cookie look like, you will find following content in it-

Name: send
Content: 1342885667964
Host: 107.22.149.124 (Or SomeTimes- Domain : .abc.com)
Path: /
Send For: Any type of connection
Expires: Never Or SomeDate(Thursday, July 20, 2017 9:17:47 PM)

You can use JavaScript to create cookies by using the document.cookie property.
Following code shows how can we set cookie using JavaScript -

    var key = "Cookie-Key";
    var val = "Cookie-Value";
    var myCookie = key + "=" + val;
    document.cookie = myCookie;

We can always add expire date to the cookie like this -

    var key = "Cookie-Key1";
    var val = "Cookie-Value";
    var myCookie = key + "=" + val;
    var date = new Date();
    var numOfMilisecond = 10000;
    date.setTime(date.getTime()+numOfMilisecond)
    var expireDate = date.toGMTString();

    document.cookie = myCookie + ";expires=" + expireDate;

If we execute this code then cookie saved is -

Name: Cookie-Key1
Content: Cookie-Value
Host: localhost
Path: /TestApp/
Send For: Any type of connection
Expires: Thursday, October 11, 2012 10:09:03 PM

In the above code we can get the current date using getDate() function and can add the number of millisecond in it. For example if we want the cookie for 24 hour then the number will be adding is -
24 * 60 * 60 * 1000 = 86400000.
Once we have the current date then we convert it into GMT time and set it into cookie.

If you see currently the cookie is been set for this virtual directory only, but what if we want it ti be for the whole domain. We can do it by explicitly setting the path. Here is the code which demonstrate how to set the path property in the cookie -

    var key = "Cookie-Key3";
    var val = "Cookie-Value";
    var myCookie = key + "=" + val;

    var date = new Date();
    var numOfMilisecond = 10000;
    date.setTime(date.getTime()+numOfMilisecond)
    var expireDate = date.toGMTString();
    var path = ";path=/";

    var myCookie = key + "=" + val + ";expires=" + expireDate + path;
    document.cookie = myCookie + ";expires=" + expireDate;

Once you browse this page you will find the cookie properties as following -

Name: Cookie-Key2
Content: Cookie-Value
Host: localhost
Path: /
Send For: Any type of connection
Expires: Thursday, October 11, 2012 10:20:25 PM

We can always set the domain by using domain = images.mydomain. We can not set the domain out of the domain from where is the content is been served. for example if the page is coming from microsoft.com i can not set the domain as amazon.com.

We can use the "secure" property of cookie to transmit the cookie on secure connection. By setting secure flag in a cookie depicts that the cookie will be sent only when the connection uses SSL, such as an HTTPS connection. in the above code append "secure" in the cookie like this -
var myCookie = key + "=" + val + ";expires=" + expireDate + path + domain + ";secure";

After this if you analyze the cookie then you will find the property "Send For" is changed -
Send For: Encrypted connections only

Reading cookie-
If we want to read existing cookie in JavaScript then we can use the document.cookie to read the cookie. It will return ";" separated cookies.
var cookies = document.cookie.split(";");

Deleting Cookie -
There is not way provided by JavaScript by which you can delete a cookie. If we want to remove any cookie we can always set it expire time as sometime in past.

Saturday, October 6, 2012

Currying in JavaScript

Currying or partial function are very important concepts in functional programming. Most of the time these terms are used interchangeably, but few experts mention slight difference between them.
function returing object - Constructor
object returning object Lets try to understand the concept behind Curry and partial function.

Partial function-
Lets take a simple example of add method.

function add(a,b){
   return a+b;
}
alert(add(5,6)); //11
Now i want to modify the above function, so that i can execute it in the following manner -
add(5,6); //11
add(5)(6); //11
var a = add(5);
a(4); // 9
a(3); //8

If we execute add(5) in the above mentioned definition, then it will return NaN, as b is undefined.
Now if see the requirement properly add(5) should return a function which can take another parameter and finally return the result by adding the first value. lets try to write that function -


function add(a,b){
    if(typeof b == 'undefined'){
        return function(c){
            return a+c;
        };
    }
   return a+b;
}
var b = add(5);
alert(b(3)); //8
alert(add(3,4)); //7
If you see the above example, its returning another function if 2nd parameter is not passed. Moreover the inner function retains the value of passed parameter in the form of closure.

It will be very difficult to scale this functionality, because we will have to write this kind of logic for every function. Say in future another function(multiply) comes and we have to write similar functionality for that as well. So its always possible to create another function say createPartial which an act as a generic solution for this. Have a look-


function partial(fn) {
    var aps = Array.prototype.slice,
            args = aps.call( arguments, 1 );
    return function() {
        return fn.apply( this, args.concat(aps.call( arguments )) );
    };
}
function add( a, b ) {
    return a + b;
}
function multiply(a,b){
    return a*b;
}
var add1 = partial( add, 1 );
add1( 2 );
var multi2 = partial(multiply,3);
multi2(4);

In the above example we have created a reusable partial function, which is used to create a partial function for add as well as multiply.

Curry-
Currying can be described as transforming a function of N arguments in such a way that it can be called as a chain of N functions each with a single argument.
JavaScript does not provide inbuilt Curry function but its always possible to make our own.

function curry(/* n,*/ fn /*, args...*/) {
    var n,
            aps = Array.prototype.slice,
            orig_args = aps.call( arguments, 1 );

    if ( typeof fn === 'number' ) {
        n = fn;
        fn = orig_args.shift();
    } else {
        n = fn.length;
    }
    return function() {
        var args = orig_args.concat( aps.call( arguments ) );

        return args.length < n
                ? curry.apply( this, [ n, fn ].concat( args ) )
                : fn.apply( this, args );
    };
}
var i = 0;
function a( x, y, z ) {
    console.log( ++i + ': ' + x + ' and ' + y + ' or ' + z );
};
a( 'x', 'y', 'z' );     // "1: x and y or z"
var b = curry( a );
b();                    // nothing logged, `a` not invoked ------------(1)
b( 'x' );               // nothing logged, `a` not invoked------------(2)
b( 'x' )( 'y' )( 'z' ); // "2: x and y or z" --------------------------(3)
b( 'x', 'y', 'z' );     // "3: x and y or z"  --------------------------(4)



Lets try to understand the above code. Once we call var b = curry(a); the following function get assigned to b-

 return function() {
        var args = orig_args.concat( aps.call( arguments ) );
        return args.length < n
                ? curry.apply( this, [ n, fn ].concat( args ) )
                : fn.apply( this, args );
    };
If you see here we have passed orig_args in the form of closure, which means the originally passed arguments are intact. In this function we check if the arguments are sufficient or not. In our case the n(expected number of arguments) is 3. If it is sufficient then the function will execute with the parameter passed. If we have not got expected number of inputs the function returns another function along with the parameter passed till now.
In the Above code we have used curry function again and passed n,fn and other arguments. If you see in the Curry function we have checked if fn==number, this is to check if the Curry function is been called in following manner-
curry( expected number of args , function definition , other arguments)
If the format is so, then we treat the first argument as the number of args expected, and use the shift property to get the function definition.
Moreover If you see we have called slice method of Array on argument object that is because arguments is array-like, it is not an array. This means that while it has a .length property and numeric indices, it doesn't have the normal Array.concat or .slice methods. In order to convert the arguments object into an array, the native Array.slice method (Array.prototype.slice) is invoked as if it existed on the arguments object via call.
lets try to see the usecases -
1-b();-> Here is the flow what happens -

1) as number of required args is 3 and we didnt pass any args this call to curry.apply( this, [ n, fn ].concat(args))
2) Call Curry function with arguments as 3 and function definition
If you see the if block fn == 'number' is true , thus n = 3 will be assigned and the function definition is assigned to fn using shift method.If you see orig_args will be empty as there is no arguments left.
With this state the function is returned -
 return function() {
        var args = orig_args.concat( aps.call(arguments) );
        return args.length < n
                ? curry.apply( this, [ n, fn ].concat( args ) )
                : fn.apply( this, args );
    };

There are 4 closures - orig_args, aps,fn and n.

2. b('x')-> The flow will be identical to what is mentioned above except this time orig_args will contain x as one of the parameter passed and this value will be passed to the function in the form of closure.

3. b('x')('y')('z') -> b('x') retuns a function which we mentioned above and in this case that function get execute with input parameter as 'y', which again returns another function(which has values x and y in its orig_args) and then finally once we execute it with input as z, it has all the required parameter in it, and hence give the expected output.

4. n('x','y','z') -> this is very straight forward and returns the output as expected.

Partial function Vs Curry -
Most of the times these terms are used interchangeably, but few experts consider them different in the following way -
Unlike partial application, which invokes the partially applied function whether all of its arguments have been satisfied or not, a curried function will only be invoked once all of its arguments have been satisfied, otherwise a function will be returned.
Example-
var a1 = partial(add,1);
var a2 = curry(add,1);
a1(); --> NaN
a2() --> function

Ref - http://msdn.microsoft.com/en-us/magazine/gg575560.aspx