0

I have the following PHP and JS:

<?php
    // Here's where the array of objects is built
    $depthElements = array(
        array('http://placehold.it/300x300',-150,100,0.8),
        array('http://placehold.it/200x300',-270,458,0.7)
    );
?>
<script>
var depthElems = <?php echo(json_encode($depthElements)); ?>;
</script>

It builds a multi-dimensional PHP array, and then packages them for the JS:

jQuery(document).ready(function($) { 

    // Create and position the elements on the page
    for (element in window.depthElems) {
        var a = window.depthElems[element];
        $('body').append('<img src="' + a[0] +
                         '" style="margin-left: ' + a[1] + 
                         'px; top: ' + a[2] + 
                         'px;" data-velocity="' + a[3] +
                         '" class="depthElem" />'); 
    }

    $(document).scroll(function () {
        var topDist = $(document).scrollTop();
        $('.depthElem').each(function () {
            $(this).css('margin-top', -topDist*($(this).attr('data-velocity')+'px'));
        });
    });
});

This seems to make sense to me, but for some reason there a bunch of extra elements on the page that I didn't ask for:

Exciting mystery elements!

Where are they coming from?

Jezen Thomas
  • 13,619
  • 6
  • 53
  • 91
  • 1
    **Never ever** iterate over an array with `for...in`... that's what you get and you rightly deserve so :P See https://developer.mozilla.org/en/JavaScript/Reference/Statements/for...in – Felix Kling Jul 25 '12 at 20:16
  • Ah, I see. I originally tried with a regular `for` loop, [but was advised against it](http://stackoverflow.com/questions/11655940/looping-through-an-object-with-incremental-property-names). – Jezen Thomas Jul 25 '12 at 20:22
  • 1
    For objects, `for...in` is safe as long as you wrap the entire inner block with a `hasOwnProperty()` check, to be sure you aren't using inherited properties. For arrays, a regular for loop is best. – mwcz Jul 25 '12 at 20:27
  • @JezenThomas: That was different, there you had an "object of arrays", here you have an "array of arrays". – Felix Kling Jul 25 '12 at 20:51

2 Answers2

3

You are using for...in to loop over an array, which is not recommended. As a result, you're probably picking up a bunch of properties you didn't mean to loop over and are getting garbage appends as a result.

Use a regular for loop (for (var i = 0; i < array.length; i++)) instead and it should work as expected.

Community
  • 1
  • 1
jbabey
  • 45,965
  • 12
  • 71
  • 94
1

The for in ... is creating the issue, as it is iterating over the properties of the Array object as well.

Change the for loop to:

$.each(window.depthElems, function(i, a){
    $('body').append('<img src="' + a[0] +
                         '" style="margin-left: ' + a[1] + 
                         'px; top: ' + a[2] + 
                         'px;" data-velocity="' + a[3] +
                         '" class="depthElem" />'); 
});
Chandu
  • 81,493
  • 19
  • 133
  • 134