Question

I seem completely unable to solve this problem. When I run this loop:

for ( var i=0; i < 10; i++ ) {
    var $items = $(balls()); 
    console.log($items);
    $container.imagesLoaded(function(){
        $container.append( $items ).masonry( 'appended', $items, true );
    });
}

The first item, and the last item are fine, they look like:

<div class="box masonry-brick" id="resultBox" style="top: 0px; position: absolute; left: 0px; "><div><p>NAME</p><img src="pathtoimage.jpg"><boxbottom id="boxBottom">NUM%</boxbottom></div></div>

But the other 8 aren't fine, they look like:

<div class="box" id="resultBox""><div><p>NAME</p><img src="pathtoimage.jpg"><boxbottom id="boxBottom">NUM%</boxbottom></div></div>

So there's no 'masonry-brick' class being applied, which means they aren't getting processed by masonry.

Also relevant is:

function balls(){
    var boxes = [];
    $iterator -= 1;
    var box = document.createElement('div'),
        spacerdiv = document.createElement('div'),
        para = document.createElement('p'),
        img = document.createElement('img'),
        boxBottom = document.createElement('boxBottom'),
        name = document.createTextNode( $test[$iterator][1][2]['name'] ),
        percentage = document.createTextNode(Math.floor($test[$iterator][0]*100)+'%');

    box.className = 'box';
    box.id = 'resultBox';
    img.src= 'scripts/php/timthumb.php?src='+$test[$iterator][2]+'&q=100&w=300';
    boxBottom.id='boxBottom';

    box.appendChild( spacerdiv );
    spacerdiv.appendChild( para);
    para.appendChild(name);
    spacerdiv.appendChild( img );
    spacerdiv.appendChild(boxBottom);
    boxBottom.appendChild(percentage);
    // add box DOM node to array of new elements
    return box;
}

I think there's something odd going on with the DOM model here, perhaps because the elements are being created dynamically?
I've been at this all day, and I'm getting burned out...

Was it helpful?

Solution

I assume each invocation of .imagesLoaded() is binding your callback function to be run later, asynchronously, after images are in fact loaded. If so, you could change your code to something like this:

for ( var i=0; i < 10; i++ ) {
   (function() {
       var $items = $(balls()); 
       console.log($items);
       $container.imagesLoaded(function(){
           $container.append( $items ).masonry( 'appended', $items, true );
       });
   })();
}

...because JS doesn't have block scope, it has only function scope. So even though you placed the var statement inside the loop your $items variable isn't actually limited in scope to the loop and when the callbacks setup with .imagesLoaded() are executed they all reference the same $items - which will hold the value as at the end of the loop. By wrapping your code in a function (in this case an anonymous function expression that is immediately executed - note the () on the end) a new $items variable is created for every iteration of the loop and thus each of your .imagesLoaded() callbacks references the correct $items.

More efficient version (because it doesn't create a new function on each iteration):

function addBalls() {
   var $items = $(balls()); 
   console.log($items);
   $container.imagesLoaded(function(){
       $container.append( $items ).masonry( 'appended', $items, true );
   });
}
for ( var i=0; i < 10; i++ )
    addBalls();

Either way, if you actually need to reference the loop index i within the loop you'd just pass it as a parameter to the function.

OTHER TIPS

Very likely something strange is happening here:

boxBottom = document.createElement('boxBottom'), 

The argument for createElement should be a valid tag name.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top