November 6, 2012

Clone of a div changing as the original div is being changed

Question by Bhumi Singhal

I have a div “maindiv”. This further has divs inside it including “imagediv”. In jQuery, I write :

$(document).ready(function() {

    ......

    var copydiv = $('#maindiv').clone();
    var number = 1;
    $("body").delegate("#imagediv", "mousedown", function(event) {

        $("#maindiv").attr('id', "changedmain" + number);
        $("#imagediv").attr('id', "changedimage" + number);
        copydiv.insertAfter("#appendafter");
        number = number + 1;
    });
});​

HTML:

<div id="appendafter"></div>
<div id="maindiv">
.
.
.
</div>

For this code, for the first time after copydiv is appended, the clone that is added has id as “maindiv” and all the inner divs have the correct it.But when number is 2, the clone contains “changemain2” instead of maindiv.WHY is this?? Any remedy ????

Answer by Starx

First, Id’s have to unique in a DOM. On this, case where you are appending multiple sets, switch to class selectors.

Next, your variable number is local and redefined and reset to 1 on every mousedown

var copydiv = $('.maindiv').clone();  
var number = 1; // This was redefined and set as 1 on every `mousedown` 
                // So make it global

$("body").delegate(".imagediv","mousedown",function(event){       
    $(".maindiv").attr('class',"changedmain" + number);
    $(".imagediv").attr('class',"changedimage" + number );
    copydiv.insertAfter("#appendafter"); // You might have to change this too 
                                         // depending if this is repeated too
    number = number+1;
}

Also, It is preferable to delegate using a .on() function

$("body").on("mousedown", ".imagediv", function(event){       
    $(".maindiv").attr('class',"changedmain" + number);
    $(".imagediv").attr('class',"changedimage" + number );
    copydiv.insertAfter("#appendafter"); // You might have to change this too 
                                         // depending if this is repeated too
    number = number+1;
}

Solution:

The problem was with the method used. Elements cloned using .clone() will hold the reference, so instead of adding a new element it will keep updating previously referenced objects.

Here is the solution:

var number = 1; //Our Counter Script

function createDiv() {
    //Lets create a new div, 
             // I mean WHY CLONE AT the first place?? 
             // We are delegating events anyway :p

    $("<div />", {
        html : $('#maindiv').html(), // add the HTML of div we are trying to keep
             // ^ Better used cached 
             //   version is not updated regularly

        id : "maindiv-"+number       // add the generate id number 
    }).insertAfter("#appendafter");  // Now insert it
    number++;
}

$("body").on("mousedown", ".imagediv", function(event){
    createDiv(); //Delegating on all elements with `imagediv` class
});

Demo

June 28, 2012

Why can't I animate a cloned element?

Question by markzzz

This is my code :

var newElement=$('.oggetto').eq(0).clone();
newElement.animate({ 'top': '2000px'}, 5000);

<div id="container">
    <div class="oggetto" style="left:0px;">&nbsp;</div>
    <div class="oggetto" style="left:50px;">&nbsp;</div>
</div> 

but seems that “.oggetto” won’t to move after the clone().

In fact, if I just write :

$('.oggetto').eq(0).animate({ 'top': '2000px'}, 5000);

it works as well. Where am I wrong?

Answer by Starx

Because, first the cloned element have to inserted into the DOM and then should be animated.

var newElement=$('.oggetto').eq(0).clone();
$("#container").append(newElement); //add the element 

//Now animate
newElement.animate({ 'top': '2000px'}, 5000);

Demo

...

Please fill the form - I will response as fast as I can!