views:

32

answers:

3

If you use append() to insert a new DOM node, is it possible to move the chain context to the new element?

This sample code illustrates the subject:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
                      "http://www.w3.org/TR/html4/loose.dtd"&gt;
<html>
<head><title></title>
<script type="text/javascript" 
        src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"&gt;
</script>
<script type="text/javascript"><!--
$(function(){
    $("<div></div>")
        .appendTo("body")
        .append("<span>Click me</span>")
        .click(function(){
            alert("Clicked on <" + this.tagName + ">, <SPAN> expected");
        });
});
//--></script>
</head>
<body>

</body>
</html>

This code attachs an onclick handler to the <div>, but I want it in the new <span>.

Edit: clarification

I suppose I was thinking about a direct function such as add() or andSelf() that doesn't break the chain flow so much <:-)

Edit: solution summary

For the records: there doesn't seem to be a native findAppended() function. These are some of the alternatives:

Alter creation flow:

$("<span>Click me</span>")
    .appendTo("body")
    .wrap("<div></div>")
    .click(function(){
        alert("Clicked on <" + this.tagName + ">, <SPAN> expected");
    });

Store the new element in a variable:

var span = $("<span>Click me</span>")
    .click(function(){
        alert("Clicked on <" + this.tagName + ">, <SPAN> expected");
    });
$("<div></div>")
    .appendTo("body")
    .append(span);

Start a new subchain:

$("<div></div>")
    .appendTo("body")
    .append(
        $("<span>Click me</span>")
        .click(function(){
            alert("Clicked on <" + this.tagName + ">, <SPAN> expected");
        })
    );

Find the new element after creating it:

$("<div></div>")
    .appendTo("body")
    .append("<span>Click me</span>")
    .find("span:last")
    .click(function(){
        alert("Clicked on <" + this.tagName + ">, <SPAN> expected");
    })
    .end(); // Not necessary here, used to illustrate how to continue the chain

Note: code not tested.

+3  A: 

Might be better to break that up a bit, but you need to start with the element or find it. So you could either:

 $("<div></div>")
        .appendTo("body")
        .append("<span>Click me</span>")
        .find('span')
        .click(function(){
            alert("Clicked on <" + this.tagName + ">, <SPAN> expected");
        });

or

$('<span>Click me</span>')
     .appendTo("body")
     .wrap('<div />')
     .click(function(){
                alert("Clicked on <" + this.tagName + ">, <SPAN> expected");
            });

find and wrap

Edit: regarding OP edit

Keep in mind .add() (http://api.jquery.com/add/) already exists and does what the name implies. Also, something like

var $span = $('<span>click me</span>').click( 
                 function() {
                     alert("Clicked on <" + this.tagName + ">, <SPAN> expected");
                 });
$('<div></div>').append($span).appendTo('body');

will ultimately make your code more manageable and readable

jQuery already has classifying methods to filter and traverse the dom. In your case of the DOM, you could easily use .find('span') to get to the element - or .children('span') - use of good selectors and overall site architecture is important here.

Also, the .end() function is pretty bad-ass:

$('ul').append('<li>test</li><li>test2</li>') // add two li elements
    .children().eq(0).css('background-color', '#ff0000') // change the background of the first child
    .end().css('margin-left', '20px'); //revert to the original data-set (the ul) and change its margin
Dan Heberden
`add()` alters the set of matched elements, not the DOM, so I'd still need to use any of the other methods (alter creation flow, storage element in a variable, start new subchain or find element after creation). Anyway, I'm accepting this answer because it appears that no native function exists and you provide a good oversight of the alternatives.
Álvaro G. Vicario
+1  A: 

This can be done, by redesigning object creation flow a bit. So, create span, configure it, to handle click, and then append it to body. This is possible, thanks to fluent interfaces of jquery.

$(function(){
$("<div></div>")
    .appendTo("body")
    .append(
    $("<span/>")
        .text("Click me")
        .click(function(){
            alert("Clicked on <" + this.tagName + ">, <SPAN> expected");
        }));
});
Valera Kolupaev
+1  A: 
$(function(){
   $("<div></div>")
       .appendTo("body")
       .append($("<span>Click me</span>").click(function(){
           alert("Clicked on <" + this.tagName + ">, <SPAN> expected");
       }));        
});​
jAndy