Search code examples
jqueryclone

problem cloning DIV with functionality... doing a bit of data abstractions


I was looking for a way to create modules that could easily be included in all kinds of projects. I didn't want just the scripting in a separate file, but also template definitions and such. Since div's can not be declared in a separate file I had to look for another way. What I can up with was this:

<head>
<title>DOMtest</title>

<script src='http://code.jquery.com/jquery-1.5.js'></script>

</head>

<body>
<script>

$(document).ready( function() {

    $("#holder").load( "template_link.html", function() {
        $("#test").append( clonelink( 1 ) );
        $("#test").append( clonelink( 2 ) );
        $("#test").append( clonelink( 3 ) );
    });

    $("#testbutton").click( function() {
        $("#test").append( clonelink( 4 ) );
    });


});
</script>

<div id='test' style='border: 1px solid black'>
<input type='button' id='testbutton' value='give me another clone'/>
</div>


<div id='holder' style='border: 1px solid black'>
</div>

</body>
</html>

then, in a separate file called template_link.html I had the following:

<script src='http://code.jquery.com/jquery-1.5.js'></script>

<div id='template_link'>
    This is a template<br />
    Let's see if this works or <span class='link_clicktest'>not</span>!
</div>

<script>

$("span.link_clicktest").click( function() {
    $d = $(this).closest( "div.link" );

    alert( "span " + $d.attr( "id" ) + " was clicked" );
});

function clonelink( $id ) {
    $c = $("#template_link").clone( true );
    $c.attr( "id", $id );
    $c.addClass( 'link' );

    alert( $id + "-" + $c.html() );
    return $c;
}

</script>

At first it seemed to work. I have declared a span in the template. If you click on "not!" you'll get the ID of that span. Cloning the first 3 seems to work, they show up on screen the way they're supposed to. But then...

I clicked the button on there "give me another clone". The clone is indeed created. With the alert in the clonelink-function I can see the ID gets there. But even with the 'true' option enabled in the the .clone()-call it doesn't seem to clone the functionality of the span.

Am I overseeing something or am I trying to do something that can not be done in this way?


Solution

  • I figured out a workaround...

    Instead of putting the functionality in the template I defined the functions for each clone, so the function clonelink changed to:

    function clonelink( $id ) {
        $c = $("#template_link").clone();
        $c.attr( "id", $id );
        $c.addClass( 'link' );
    
        $c.find(span.link_clicktest").click( function() { 
            $d = $(this).closest( "div.link" );
            alert( "span " + $d.attr( "id" ) + " was clicked" );
        });
    
        alert( $id + "-" + $c.html() );
        return $c;
    }
    

    Now for every clone that is created the click function is bound again. The .clone(true) is replaced with a .clone() 'cause the functions bound to it are redefined anyway. This works like a charm, but I'm still puzzled why the first example in the original post didn't work. There is a working DIV on the screen which is cloned with .clone(true) and still the .click-function isn't bound to the defined span...

    If anyone has a more elegant solution I'd be delighted to hear about it. Also, I'd like to know why the first example isn't working correctly...