Showing posts with label jquery. Show all posts
Showing posts with label jquery. Show all posts

Wednesday, August 31, 2011

jQuery check if dom element exists

When we use jQuery method $("#idName"), we will always get a jQuery object, even the DOM element may not be really existing on the web page. Sometimes we want to check if the returned object by $("#idName") really is an existing DOM element on the page. The easiest way to do this is to check the length property of the object:

var fakeDom = $("#fake");
if (fakeDom.length == 0) {
console.log('i am not an existing DOM);
}

There is another way to do this though:

var fakeDom = $("#fake");
if (fakeDom[0] === undefined) {
console.log('i am not an existing DOM);
}

Why do they work? When we check jQuery source code (v1.6.2), we find this:

// HANDLE: $("#id")
else {
elem = document.getElementById( match[2] );

// Check parentNode to catch when Blackberry 4.6 returns
// nodes that are no longer in the document #6963
if ( elem && elem.parentNode ) {
// Handle the case where IE and Opera return items
// by name instead of ID
if ( elem.id !== match[2] ) {
return rootjQuery.find( selector );
}

// Otherwise, we inject the element directly into the jQuery object
this.length = 1;
this[0] = elem;
}

this.context = document;
this.selector = selector;
return this;
}

As we can see, jQuery gets the DOM element: elem = document.getElementById( match[2] ). And if the DOM element is valid, it will set the length property of jQuery object to 1:

elem = document.getElementById( match[2] );
if ( elem && elem.parentNode ) {
...
this.length = 1;
this[0] = elem;
}
...
return this;

So, if elem is not a valid DOM, this.length will be 0. From the source code, we also find that the valid DOM elem will be assigned to this[0]. Therefore, if the elem is not valid DOM, this[0] should be undefined. So we can also check if this[0] is undefined.  

Wednesday, July 20, 2011

learning jQuery source code (v1.6.2) - 2

Continue from the last post http://hengrui-li.blogspot.com/2011/07/learning-jquery-source-code-v162.html, we know that jQuery object is actually generated by the code below:
var jQuery = function( selector, context ) {
     // The jQuery object is actually just the init constructor 'enhanced'
     return new jQuery.fn.init( selector, context, rootjQuery );
}
Today we will learn how jQuery.fn.init function works. When i look at a function, I always look at the function signature first, and then, try to look at what it returns. At this stage, i don't have to worry about its implementation details.

jQuery.fn = jQuery.prototype = {
            constructor: jQuery,
            init: function( selector, context, rootjQuery ) {
                        ...
                        return jQuery.makeArray( selector, this );
            },
...
} 
Well, jQuery is an excellent js lib, but i still have to say i don't like functions without any annotation at the top.

We see the function takes three parameters. 'selector' probably is the easiest one to understand: when we call $("#id"), "#id" is the selector. Let's leave the other two parameters for now.

We look at what this function will return at the last line: "return jQuery.makeArray( selector, this );". Usually, i look at the last return statement to grab the first impression that what a function could return. However, it is also quite common that a function has multiple return statements. I think it is a good practice that we should try to avoid multiple return statements within one function, but, sometimes, it does make our life easier, so i can accept that. One thing i really insist is the function's return type must be consistent. That means, if a function is supposed to return a boolean value, it should only return true or false. It is bad that it returns true at one place, at another place it returns null, and at another place it returns empty string '' etc. In general, a function should return only one type of data. It is a bad practice that a function could return multiple types. "return jQuery.makeArray( selector, this );" tells us the function could return an array(object). I don't know what jQuery.makeArray really does but it doesn't matter as long as its name is not misleading.

Now let's look at the implementation details step by step.
code 1:
// Handle $(""), $(null), or $(undefined)
if ( !selector ) {
     return this;
}
The comment is quite clear here. if we do $("") kindof stuff, it simply returns this.

code 2:
// Handle $(DOMElement)
if ( selector.nodeType ) {
            this.context = this[0] = selector;
            this.length = 1;
            return this;
}

Again, the comment tells all. To see what it does, we can write some logs in the code, and try:
var dom = document.getElementById('id');
$(dom);

From this code, we can find that jQuery makes this[0] refers to the dom elements we are querying.

code 3:
// The body element only exists once, optimize finding it
if ( selector === "body" && !context && document.body ) {
    this.context = document;
    this[0] = document.body;
    this.selector = selector;
    this.length = 1;
    return this;
}
This simply optimizes the way to find body element.

code 4:
// Handle HTML strings
if ( typeof selector === "string" ) {
...
}
This is the most complex block cause it is handling the most common tasks like $("#id"), $('input[name="name"]'), etc. We will look at it next time.

Tuesday, July 19, 2011

learning jQuery Source Code (v1.6.2)

By its name, jQuery, we can learn something. 'j' means javascript. 'Query' tells us what this library can do or what it is good at. An interesting question is why jQuery becomes so popular even it comes after some other mature javascript libraries like YUI, prototype?

To answer this question, we better open our memory and think what we usually use javascript to do in web development. Mostly, we do these things: 1. search DOM element using getElementById. Once we get the DOM element, we get its value or set its value; 2. Set DOM element's content by setting innerHTML; 3. DOM elemnt event listening, such as 'click'; 4. Using AJAX to get data from backend and update DOM elements' content; 5. Update DOM elements' CSS value.

So most of our tasks are related to DOM elements and these tasks can be divided into two groups: 1. Search/query DOM elements; 2. DOM elements manipulation.

For javascript gurus, writting 'document.getElementById' or 'document.getElementsByTagName' may not be a problem.  Manipulating DOM elements is not hard either. But crossing browsers like IE, mozilla could be a headache to every javascript developer. jQuery doesn't try to do everything. It simply makes DOM manipulation easier and crossing browsers less painful.

We can see the whole jQuery code is wrapped into a self executing function (or immediate function). The obvious benefit of doing this is no global variables would be left behind. So you don't have to wrroy that your library code(temporary variables) may accidently pollute the global space. We can see "window" is passed into this self invoking function as a parameter. In browser environment, window is the top level global object. Everything else are actually properties of window object.
code 1:
(function( window, undefined ) {
...
})(window);

Inside the immediate function, we find another immediate function. This function returns a value to the jQuery variable.
code 2:
var jQuery = (function() {
...
})();

We know that jQuery is the single object we can use straightaway (How about "$"? Well $ is exactly the jQuery object). We can see the last line in code 1:
(function( window, undefined ) {
...
// Expose jQuery to the global object
window.jQuery = window.$ = jQuery;
})(window);

This creates two global objects: jQuery and $. They both refers to a single identical object. So once we include jQuery library, we can use either jQuery or $ to invoke other methods.
Continue looking through code 2:
var jQuery = (function() {
var jQuery = function( selector, context ) {
                                return new jQuery.fn.init( selector, context, rootjQuery );
                },
...
})();

Don't get confused. The second " var jQuery" is simply another local variable. Note that it is inside the immediate function scope? If this can make you clear, you can imagine the code is:
var jQuery = (function() {
var localJquery = function( selector, context ) {
                                ...
                },
...
})();

Next time, we will look through this jQuery.fn.init( selector, context, rootjQuery ) function.

Friday, March 20, 2009

JQuery & Html Entities

htmlentities() is well known for PHP developers. JQuery can do the same thing at client side. Here is the interesting blog : http://debuggable.com/posts/encode-html-entities-with-jquery:480f4dd6-13cc-4ce9-8071-4710cbdd56cb

Actually, it is quite simple: $('#content').text('This is fun & stuff').html(); // evaluates to "This is fun & a m p ; stuff"

However, i have another issue. I send a json data { myValue: 'AT& a m p ;T' } to jquery. And what jquery is supposed to do is $("#myInput").val(myValue). This, however, will display AT & a m p ;T in the input field, instead of AT&T, the one i really want to show.

Instead of writting your own html entities parser, here is a hacky solution:
var realValue =$("#js_temp").html(myValue).text();
$("#myInput").val(realValue);

Tuesday, March 17, 2009

JQuery event functions do not work for dynamic added elements

$("a").click(function () {
alert("I was clicked");
});

<a href="http://www.blogger.com/post-edit.do">click me</a>

If you click the link, a window will popup. However, if you use JQuery dynamicly add some new <a> elements, they won't work with the click function. For example,

$("p").append("<a href='#'>I am added dynamically</a>"), and if you click the link, you will find that the function doesn't work at all.