9

If I have HTML like this:

<a href="#" class="movieImg"><div class="previewBulk"></div></a>
<a href="#" class="movieImg"><div class="previewBulk"></div></a>

and Javascript like this:

var movie = document.getElementsByClassName("movieImg");
var preview = document.getElementsByClassName("preview");

Is there any way to addEventListener to 2 movie a tag and preview div tag? I try for loop but when I do something like:

for(var i = 0, j=movie.length; i<j; i++){
 movie[i].style.left = 100;
 preview[i].style.left = 100;
}

I get Uncaught TypeError: Cannot read property 'style' of undefined.

After change preview to previewBulk, i still get error, my code actually look like this

(function(){
        var movie = document.getElementsByClassName("movieImg"),
        preview = document.getElementsByClassName("previewBulk");
        //result = [];

        for(var i = 0, j=movie.length; i<j; i++){
            movie[i].addEventListener("mouseover", function(){

                preview[i].style.left = ((movie[i].offsetWidth-preview[i].offsetWidth)/2)+20;
                preview[i].style.top = -(movie[i].offsetHeight+preview[i].offsetHeight);
                preview[i].style.visibility = "visible";
            });

            movie[i].addEventListener("mouseout", function(){
                preview[i].style.visibility = "hidden";
            });
        }
    }());
bitokeev
  • 101
  • 1
  • 1
  • 6
  • 1
    The CSS `left` property (which is accessed through the DOM as per your example) takes a **length** not an integer. Unless the value is 0 **you need a unit**. – Quentin Jul 20 '11 at 13:20
  • Do u mean sting value? like "100px"? – bitokeev Jul 20 '11 at 13:34
  • You can't include a unit without the value being a string. It doesn't have to use pixels. The rules are the same as for CSS applied directly. – Quentin Jul 20 '11 at 13:37

5 Answers5

8

document.getElementsByClassName does not return an array. It returns a node list which is traversed like an XML file.

    <a href="#" class="movie"><div class="previewBulk"></div></a>
    <a href="#" class="movie"><div class="previewBulk"></div></a>

    <script>

    var movie = document.getElementsByClassName("movie");

    for(var i = 0; i<movie.length; i++){
      movie.item(i).style.width = "100px";
    }​

    </script>

See jsfiddle: http://jsfiddle.net/Uy5fk/

Orbiting Eden
  • 1,522
  • 13
  • 16
7
// for each iterates over a list and runs a function for each element
var forEach = Array.prototype.forEach,
    // query selector all runs a CSS selector and returns a list of elements
    // matching the selector
    $$ = document.querySelectorAll.bind(document);

// for each element in the list returned by the CSS selector    
forEach.call($$('.movieImg, .preview'), function(v) {
  // add an event listener to the click event
  v.addEventListener('click', function(e) {
    // and run some event handling code.    
  }, false);
});

Of course there's browser compliance issues. They need to support ES5 & DOM2 events. Use shims for browser compliance.

If you include

It should fix browser support. Of course FF4/ Chrome /safari5/ ie9 / Opera10+ already support these

Edit:

The problem is actually the "closures inside loops problem" as described in the javascript garden

Community
  • 1
  • 1
Raynos
  • 166,823
  • 56
  • 351
  • 396
3

No tags with classname preview so

var preview = document.getElementsByClassName("preview");

will cause that error

this line must be as follows

var preview = document.getElementsByClassName("previewBulk");

and as @raym0nd said the number of div tags must be equal to the number of a tags

EDIT

the problem with your code is you used the index of for loop inside the anonymous function but this function is called with mouseout and mouseover event and after finishing the for loop try the following

var movie = document.getElementsByClassName("movieImg");

    for(var i = 0, j=movie.length; i<j; i++){
        movie[i].addEventListener("mouseover", function(){
        var preview = this.getElementsByClassName("previewBulk")[0];
                          preview.style.left = ((this.offsetWidth-preview.offsetWidth)/2)+20;
            preview.style.top = -(this.offsetHeight+preview.offsetHeight);
            preview.style.visibility = "visible";
        });

        movie[i].addEventListener("mouseout", function(){
            var preview = this.getElementsByClassName("previewBulk")[0];
            preview.style.visibility = "hidden";
        });
    }

or test in jsFiddle

Amir Ismail
  • 3,865
  • 3
  • 20
  • 33
  • still get error after changing from preview to previewBulk, i edit and post my full code on the question, can u help me look for the problem? Thank – bitokeev Jul 20 '11 at 13:35
  • Thank, it work. about the code "var preview = this.getElementsByClassName("previewBulk")[0]" may i know what does the [0] mean? is't an array by accessing the first element? – bitokeev Jul 20 '11 at 16:55
1
for(var i = 0, j=movie.length; i<j; i++){
 movie[i].style.left = 100;
 preview[i].style.left = 100;
}

does preview has the same length as movie? if not this gives you an error.

raym0nd
  • 3,172
  • 7
  • 36
  • 73
1

You have class="previewBulk" and document.getElementsByClassName("preview");

Your code assumes there will be as many elements of the class preview as there are for movieImg, but since you got the class name wrong, there are going to be zero such elements.

Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335