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

Author: Nabin Nepal (Starx)

Hello, I am Nabin Nepal and you can call me Starx. This is my blog where write about my life and my involvements. I am a Software Developer, A Cyclist and a Realist. I hope you will find my blog interesting. Follow me on Google+

...

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