0

I'm trying to write a javascript program which show an hidden image.

Here's the html part :

    <!DOCTYPE html>
<html>
        <head>
                <meta charset="utf-8" />
                <title> Exercice 3 </title>
                <link rel="stylesheet" href="style.css" />
        </head>
        <body>
                <header>
                </header>
                <section>
                        <article>
                                <figure>
                                        <img src="images/powsoundeffect.png" alt="image" />
                                        <figcaption>
                                                Image 1
                                        </figcaption>
                                </figure>
                                <figure>
                                        <img src="images/thwack_soundeffect.png" alt="image" />
                                        <figcaption>
                                                Image 2
                                        </figcaption>
                                </figure>
                                <figure>
                                        <img src="images/tophat.png" alt="image" />
                                        <figcaption>
                                                Image 3
                                        </figcaption>
                                </figure>
                                <figure>
                                        <img src="images/1311511622.png" alt="image" />
                                        <figcaption>
                                                Image 4
                                        </figcaption>
                                </figure>
                                <ul>
                                        <li>
                                                <a href="#"> Image 1 </a>
                                        </li>
                                        <li>
                                                <a href="#"> Image 2 </a>
                                        </li>
                                        <li>
                                                <a href="#"> Image 2 </a>
                                        </li>
                                        <li>
                                                <a href="#"> Image 2 </a>
                                        </li>
                                </ul>
                        </article>
                </section>
                <script type="text/Javascript" src="script.js" >
                </script>
        </body>
</html>

The css :

figure {
        width: 20%;
        position: absolute;
        visibility: hidden;
}

ul li {
        border: 1px solid black;
        width: 10%;
}

The script :

var arrayA = document.querySelectorAll('a');
var arrayImg = document.querySelectorAll('figure');

function show_Image(text, img) {
        text.style.fontSize = '2em';
        arrayImg[img].style.visibility = 'visible';
}

for (var i = 0, c = arrayA.length; i < c; i++) {
        arrayA[i].addEventListener('mouseover', function(e) {
                                                        show_Image(e.target, i);
                                                },
                                                false);
}

When I try to run the script the following error occurs on safari :

TypeError: 'undefined' is not an object (evaluating 'arrayImg[img].style')

and on chromium :

Uncaught TypeError: Cannot read property 'style' of undefined 

It seems that the arrayImg is not containing object with the querySelector and I don't see why ... Anyone can help me on this ?

Thanks !

Olivier B.
  • 97
  • 1
  • 2
  • 11
  • possible duplicate of [Javascript closure inside loops - simple practical example](http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example) – Jonathan Lonowski Apr 15 '14 at 22:03
  • 1
    The problem is between `i` and the asynchronous nature of `addEventListener()`. The event will occur and call `show_Image(e.targer, i)` after the loop has finished, when `i` has been assigned to a value that's out of range. – Jonathan Lonowski Apr 15 '14 at 22:05
  • Thank you for your answer, I get it. Do you have some recommandation to make the program works, I'm quite stucked ? Sorry I'm a Javascript beginner. – Olivier B. Apr 15 '14 at 22:14

1 Answers1

0

As Jonathan Lonowski described in its comment, the variable 'i' is increased after the eventListener has been bound - and the anonymous function will use the increased value.

You may go this way:

for (var i = 0, c = arrayImg.length; i < c; i++) {
    arrayA[i].addEventListener('mouseover', (function(i,e) {
        show_Image(e.target, i);
    }).bind(this,i), false);
}

It binds the anonymous function to the scope the binding is executed from and 'i' as a first parameter, that won't change anymore.

Even if that isn't the cleanest way to achieve what you want to do, it's working in the way you want it to.

andred
  • 1,204
  • 1
  • 17
  • 29
  • Thank you, works fine. Just one question, what is, in your opinion, the best way to handle the problem (which is changing the visibility of a bunch of figures only with javascript) ? Thanks. – Olivier B. Apr 15 '14 at 22:28
  • Depends on the situation. Think about the structure in the future - there will be more images and eventually you want to trigger them from other than those five links. You could add a `data-imageover="image1"` to the anchor-elements and the respective `class="image1"` to the figures. Then you bind the event-listener to every element of `document.querySelectorAll("a[data-imageover]")` and let it call a `show_image`-function for any element found by `document.querySelectorAll('.'+e.target.getAttribute("data-imageover"))` Maybe use, for example, jQuery. But as said, depends on the situation. – andred Apr 15 '14 at 22:44