Christian Werther
Christian Werther

Reputation: 346

Chaining events and DOM iteration

Below I've got two jQuery selectors.

The first searches for a DOM element within a cached object and then searches its parents, then it seaches the parents (table) for another dom element. (ex. 2)

The second (2 lines) searches via the cached element. (ex. 1)

    $('element', table.setting.body).on('blur focus', table.focus).parents('parent').find('another element').on('click', function); // ex2

    $('element', table.setting.body).on('blur focus', function); // ex 1
    $('another element', table.setting.body).on('click', function); // ex 1

Which one is faster/best practice?
Ex. 1 would without doubt be faster reffering to jQuery functions, ie. .hide().animate().show() but, when is it when searching for DOM elements?

enter image description here

Upvotes: 8

Views: 153

Answers (3)

Frédéric Hamidi
Frédéric Hamidi

Reputation: 263047

It looks like you are trying to match different descendants from table.setting.body and perform different tasks on these descendants, without having to specify table.setting.body twice.

You can use end() to achieve this. For instance, if table.setting.body is a jQuery object, you can write:

table.setting.body.find("element").on("blur focus", function).end()
                  .find("another element").on("click", function);

(If table.setting.body is a DOM element, you will have to apply $() to it first).

The code above only evaluates the cached object once, performs two calls to find() (slightly faster than your calls to $() with a context argument in my experience), two calls to on() (the same as yours) and a single call to end() (which only pops an item off a stack and should be quite fast).

Upvotes: 0

Christoph
Christoph

Reputation: 51221

In my opinion this is less a question of speed but more a question of maintainability and good coding style.

And that is where Example 1 is far better than Example 2.

Avoid confusion and keep things separated. You want to attach 2 events to 2 different element - write 2 statements. This makes your code far more structured and readable.

Upvotes: 1

Sebastian vom Meer
Sebastian vom Meer

Reputation: 5241

The only difference I see is the usage of parents inside your first approach. jQuery.parents looks for the needed parent using a loop inside the function dir:

parents: function( elem ) {
    return jQuery.dir( elem, "parentNode" );
},

// ...

dir: function( elem, dir, until ) {
    var matched = [],
        cur = elem[ dir ];

    while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
        if ( cur.nodeType === 1 ) {
            matched.push( cur );
        }
        cur = cur[dir];
    }
    return matched;
},

(http://code.jquery.com/jquery-1.8.2.js)

cur = elem[ dir ] means elem["parentNode"] and is repeated for all parents, because until is undefined. There is no shortcut if the wanted parent is given as reference.

Depending on the path length between the first element you are looking for and the document's root the first approach needs more DOM operations.

Therefore I recommend the second approach.

Upvotes: 0

Related Questions