Posts Tagged ‘context’

jQuery.each() for single objects

Thursday, July 9th, 2009

While refining  jQuery.crossselect.js recently I was briefly faced with a problem which often rears its ugly head, though this time I found a solution.

Consider a function alters_item(), which can be applied to certain DOM elements. Further, consider that it can be triggered in two distinct ways:

  1. By a click (or other event) on the item to be altered, so the DOM element is the context and can be accessed via the pseudo-variable this
  2. Just applied like a normal javascript function, which means the DOM element needs to be passed in as a parameter, i.e. you need to call the function using alters_item(element)

So to have a function usable in both circumstances I would write some conditionals at the start which check if an argument has been passed, if it hasn’t then set var element = this, etc…

But there is another way.

For the second case instead of

alters_item(element)

we can write

$(element).each(alters_item)

because jQuery.each works even on jQueries that return only one object.

Doing this is a bit of a trade off – the second line of code I bet takes measurably longer to execute, but it does mean my functions get to be simpler, so it’s my weapon of choice at the moment.

But it does make me think that jQuery should have a call() method, that runs a function on an object, but also setting the object as the context.

Incidentally, if anyone knows of a better way of dealng with this isue than the one I’ve found, please let me know.

It’s all about context

Saturday, May 30th, 2009

One big selling point of jQuery – so everyone says – is the ability to nest/chain selectors, so that using oen string you can, in theory, pick out any element in the DOM. But this has eluded me somewhat until today; until I realised the usefulness of setting a context for jQuery selectors.

I noticed a few days ago that my new crossSelect plugin was a bit inefficient, in that it queried the DOM far too often. It used to have something like the following code:

$(this).parent().parent().find('.target1').children('li')...
$(this).parent().parent().find('.target2').children('li')...

But the next iteration was going to have something like this instead – far sleeker.

var context = $(this).parent().parent()
$(context).find('.target1').children('li')...
$(context).find('.target2').children('li')...

But it bugged me that I couldn’t pick out the <li>’s with a string selector. This is because context is an object, not a string, and therefore can’t be a part of a selector string. But then I discovered setting the context on selectors (easy to miss as it’s not linked to from the selectors bit of the documentation site). So that led to the following:

$(context).find('.target2').children('li');

is equivalent to

$('.target2', context).children('li');

which can be rewritten

$('.target2 > li', context);

Far more elegant, I think you’ll agree. So it’s jQuery context setting all the way for me. From now on I will only use find when I need to find a child element on the same line that I’ve already done something to the parent; it really has no place at the begining of a line of jQuery code.