tags:

views:

325

answers:

5

I have already read this webpage http://docs.jquery.com/Traversing/end but i am still clueless on what .end() actually does. How is it for and how do you use it. I am also reading a jquery book but it lightly glazes over .end() and does not give any examples of what its for. Can someone clearify?

+12  A: 
$("body").find("span").css("border", "2px red solid");

vs

$("body").find("span").end().css("border", "2px red solid");

Execute these statements separately in Firebug console on this exact page, and notice how different the behaviors are. Basically, .end() tells it to go back to body after finding all spans, and apply the border to body, not the spans. If we don't have the .end() there, the jQuery code basically behaves normally and applies the .css() to our span elements inside of body.

BODY > SPAN > APPLY BORDER TO SPANS

with end() it becomes

BODY > SPAN > GO BACK TO BODY > APPLY BORDER TO BODY

The find() is a destructive operation, meaning it changes what elements are inside of your jquery objects array.

$('body')

our current element is body

$('body').find('span')

we used a destructive operation find() which changes our entire objects collection to be populated with spans inside of body, body is no longer in the collection

$('body').find('span').end()

because find is a "destructive" operation it reverts back to before we did .find(), basically un-does or ctrl-Z's the last thing that changed our jquery collection.

meder
It's in his question though.
meder
...you're absolutely right. rescinded. Sheesh.
Skeolan
`find` is not destructive. It just returns a new wrapped set. This new wrapped set has a reference to the original set that created it, that's all.
Crescent Fresh
"we used a destructive operation find() which changes our entire objects collection to be populated with spans inside of body, body is no longer in the collection$('body').find('span').end()because find is a "destructive" operation it reverts back to before we did .find(), basically un-does or ctrl-Z's the last thing that changed our jquery collection."I don't understand these statements.
Josh Pearce
@Josh Pearce - $('body') returns an array with body. $('body').find('span') would return an array with spans. it changed our original return when we used '.find' which is why they label it as a destructive operation.
meder
@Crescent Fresh "A 'destructive' operation is any operation that changes the set of matched jQuery elements, which means any Traversing function that returns a jQuery object - including add, andSelf, children, filter, find, map, next, nextAll, not, parent, parents, prev, prevAll, siblings, and slice - plus the clone, appendTo, prependTo, insertBefore, insertAfter, and replaceAll functions (from Manipulation)"
meder
@meder: fair enough. "destructive" is often vaguely defined at best in discussions. In jQuery `find` calls `pushStack` internally, which used to mutate the wrapped set `this` in the 1.0 days (http://dev.jquery.com/browser/tags/1.0/src/jquery/jquery.js#L748). Now `pushStack` returns a new wrapped set everytime, no longer mutating the elements in `this` (http://dev.jquery.com/browser/tags/1.1/src/jquery/jquery.js#L260).
Crescent Fresh
@Crescent - I'm well aware of what happens internally, however because of the vague definition of `destructive` if I tried to explain what was really going on I would confuse the OP and it would be inconsistent with the API, therefore I didn't.
meder
A: 

It allows the current "scoping" to end and be re-defined. For example, lets say you have some HTML like:

<div id="people">
 <ul>
   <li>A</li>
   <li>B</li>
 </ul>
 <ul>
   <li>C</li>
   <li>D</li>
  </ul>
</div>

You could first select the parent by :

$('#people')

And modify the children ul elements like

#('#people').find('ul').css('border', '1px solid #f00')

But what happened if you wanted to continue to to edit the parent element (#people)? You could start a new finder $('#people') or just chain it to the first line, preceeded with an .end() to notify jQuery that you want to "close" the find() and scope the search back to the preceeding find (implicity the $('#people'), like so)

#('#people').find('ul').css('border', '1px solid #f00').end().css('border', '1px dashed #00f')

So that line would: grab all the child UL of #people, change their borders to red and then change the border of the parent #people element to dashed and blue.

Cody Caughlan
+6  A: 

It basically goes back to the parent set. For example:

$('.tree')
    .find('.branch')
        .find('.leaf')
        .addClass('tacks-onto-leaf')
        .end()
    .addClass('tacks-onto-branch')
    .end()
.addClass('tacks-onto-tree');
wambotron
+1..Good explaination
Luke101
+1  A: 

It backs out the "scope" of a chained JQuery statement to the previous level.

Tags in jQuery object initially [$('P')]: P, P

Tags in jQuery object after find [$('P').find('SPAN')]: SPAN, SPAN, SPAN, SPAN, SPAN

Tags in jQuery object after end [$('P').find('SPAN').end()]: P, P

$('span')              //all <span> tags in the doc
  .find('#foo')          //all <span> with id foo
    .addClass('blinkyRed') //adds class blinkyRed <span id='foo'> 
  .end()                 //reverts scope to all <span> tags
.addClass('Bold')      //adds class Bold to all <span> tags
Skeolan
A: 

The following functions can be used to alter your jQuery selection, typically to make your selection more specific, or inclusive/exclusive:

add, andSelf, children, filter, find, map, next, nextAll, not, parent, parents, prev, prevAll, siblings, slice, clone, appendTo, prependTo, insertBefore, insertAfter, or replaceAll

.end() can be used to reset your selection back to your original set of elements, after having done some manipulation on the extended selection.

JGarrido