开发者

Javascript persistence > logic

Please help me find a solution that uses plain 'ol javascript (I cannot use external frameworks). Also, CSS :hover selector won't work for the real world implementation.

Somethings going on with the registered event sets all calling the last registered events array item.

<body>
        <p>When you hover over &lt;div&gt; tags 0-2, that &lt;div&gt; tag should highlight in red. Why do all of the &lt;div&gt; tags o开发者_如何学Gonly affect the last &lt;div&gt;?</p>

        <div class="test"></div>
        <div class="test"></div>
        <div class="test"></div>

        <p>The same results for &lt;p&gt; tags.</p>

        <p class="test"></p>
        <p class="test"></p>
        <p class="test"></p>

        <script type="text/javascript">
            //create arrays
            var divArr = new Array();
            var pArr = new Array();

            //call function to populate arrays
            divArr = getElementsByClassName('div','test');
            pArr = getElementsByClassName('p','test');

            //call function to register arrays elements events
            registerArrayElementsEvents(divArr,'div');
            registerArrayElementsEvents(pArr,'p');

            //retrieve elements that match the passed tag and class
            function getElementsByClassName(myTag,myClass) {
                //load all elements into array
                var elems = document.getElementsByTagName(myTag);
                //create new array placeholder
                var newArr = new Array();

                //iterate through elements array
                for (var i = 0; i < elems.length; i++) {
                    //check to see if element class matches parameter
                    if (elems[i].className == myClass){
                        //add matched element to new array
                        newArr.push(elems[i]);
                    }
                }

                //return array of matched elements
                return newArr;
            }

            //register events to every element in the passed array
            function registerArrayElementsEvents(arr,type){
                //create object placeholder
                var currentObj = new Object();

                //iterate through the objects array
                for (var i = 0; i < arr.length; i++) {
                    //assign current object corresponding to loop counter

                    currentObj = arr[i];

                    //write element index to element
                    currentObj.innerHTML = 'This is &lt;' + type + '&gt; ' + i;

                    //add mouseover event to element
                    addEvent(currentObj,'mouseover',function(){
                        //set current element color to red
                        currentObj.style.color = '#f00'
                    });

                    //add mouseout event to element
                    addEvent(currentObj,'mouseout',function(){
                        //set current element color to black
                        currentObj.style.color = '#000'
                    });
                }
            }

            //register functions to events for objects
            function addEvent(obj,evt,fn){
                //if not IE
                        if (obj.addEventListener)
                    obj.addEventListener(evt,fn,false);
                //if IE
                else if (obj.attachEvent)
                    obj.attachEvent('on'+evt,fn);
            }
        </script>
    </body>


What's happening is that in currentObj in registerArrayElementsEvents is scoped to registerArrayElementsEvents rather than each event's function. You need to put currentObj into each function's scope as so:

addEvent(currentObj, 'mouseover', (function (obj) {
    return function () { 
        obj.style.color = '#f00';
    };
})(currentObj));

Basically, JavaScript only scopes based on functions, not on blocks. This means that

for (...) { var x = arr[i] }

is exactly the same as:

var x;
for (...) {x = arr[i]}

This means that after the loop is done, x is set to the last element of the array. If you referenced x in a function, when it goes to look x after the loop is done (like after an event) it gets the newest value of x. To overcome this, you can create a closure each time you loop through by using an anonymous function like I did.


        //create arrays
        var divArr = new Array();
        var pArr = new Array();

        //call function to populate arrays
        divArr = getElementsByClassName('div','test');
        pArr = getElementsByClassName('p','test');

By assigning new values to divArr and pArr you over write the arrays originally assigned. That isn't your issue, it just means the original assignment is useless.

TIkhon has one answer, another way is to avoid the closure with this:

addEvent(currentObj, 'mouseover', function () {
        this.style.color = '#f00';
    });

but you will have to modify the addEvent function for attachEvent so set this correctly. I'll add that shortly...

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜