Search code examples
jqueryhtmlclonestructureeach

Jquery: Clone inside iteration (.each) scrambles html structure


I have a snip of code that I cannot seem to fix. Everything works fine if I do not iterate through the function, or if I do not clone. When I put them together, the structure of the divs gets scrambled.

Before any code, I start with:

<div class="origin"></div>

Then I write some script to add html, which should be structured like this: Code:

<div id="id0">
  <div class="scroller">
    <div class="origin"></div>
  </div>
  <a href="#"></a>
</div>
<div class="viewport"></div>
<div id="id1">
  <div class="scroller">
    <div class="origin"></div>
  </div>
  <a href="#"></a>
</div>
<div class="viewport"></div>

It starts fine, but if you uncomment the two lines below, the second div with ID is now inside the previous viewport, instead of wrapped around "origin". I'm trying to copy the images and maybe captions, inside each "origin" to inside its own viewport (with two surrounding divs on the images).

The code:

function writeGallery(i) {
    var startDiv = $("div.origin:eq("+i+")");
    startDiv.wrap('<div class="scroller"></div>');  
    startDiv.parent().wrap ('<div id="id' + i + '" />');
    var horizThumbwrap      = startDiv.parent().parent();
    horizThumbwrap.append ('<a href="#"></a>');
    horizThumbwrap.after ('<div class="viewport" />');

    //var horizViewport        = startDiv.parent().parent().next(".viewport");
    //startDiv.clone().appendTo(horizViewport);
}

$(document).ready(function(){

$("div.origin").each(function(index) {
writeGallery (index);
});

$('#result').text($('#container').html());
});

The code here in fiddle (uncomment 2 lines to see mess): http://jsfiddle.net/AjSnx/

The only thing I can think of is to rewrite it in various ways and just hope I hit on something that works. But since it's my first jQuery project, I'd like to understand what I've done wrong here, too.

Can anyone help? Thanks!


Solution

  • Inside each loop, you are selecting the .origin elements using :eq(). However, in each loop you create another <div class="origin" />. So in the following loop you are selecting the <div> that you just created using .clone() and not the <div> that was there from the beginning. To fix this, use the second argument passed to the function that is called by .each(). It contains the current element that was matched in the beginning (i.e. the element you intended to use inside the loop).

    Please see my update for details. The HTML produced is this:

    <div id="id0">
        <div class="scroller">
            <div class="origin"></div>
        </div>
        <a href="#"></a>
    </div>
    <div class="viewport">
        <div class="origin"></div>
    </div>
    
    <div id="id1">
        <div class="scroller">
            <div class="origin"></div>
        </div>
        <a href="#"></a>
    </div>
    <div class="viewport">
        <div class="origin"></div>
    </div>