0

I have multiple divs which showcase some of the projects I have worked on(lets call each div's class project) . When project is hovered over(Jquery's MouseOver), a div that is contained within it (lets call each class of this type githublink) which has a link to the GitHub account and the website link for that respective project fades in, and vice versa for mouseleave and fadeout. The design acts exactly as how I expect it to react, however when I hover over any of the five project div's the last project div's githublink is always the one fading in and fading out. I concluded that the reason for this is because of the for loop I am using to assign the mouseOver and MouseLeave Events. I am only going to include this specific javascript code and not the HTML code because I have debugged the javascript code and looked at the Chrome Dev Tools and found that after each iteration of the for loop the right element is being retrieved and assigned, however once the for loop is done all the eventhandlers affect the last GitHubDiv.
Below Is My JS Code

var numprojects=document.getElementsByClassName("project");
    console.log(numprojects.length);
if(numprojects){
    for(i=0; i<=numprojects.length-1; i++){
        console.log(i);
        currentclass=".project:eq("+i+")";
        currentgithublink=".githublink:eq("+i+")";
        if($(currentclass)){
            $(currentclass).mouseover(function(){
                $(currentgithublink).fadeIn("fast","linear");
            })
            $(currentclass).mouseleave(function(){
                $(currentgithublink).fadeOut("fast","linear");

            })
        }
    }
}

How to rewrite the same code using a for loop to save space but at the same time to avoid this issue. I think it has something to do with the anonymous functions, but most importantly WHY and how to fix it.

**UPDATE After reading about closure, I updated my code to do the following now an event isnt triggered at all for any of the projects. **

if(numprojects){
    console.log("entered projects");
    for(i=0; i<=numprojects.length-1; i++){
        console.log("entered loop");
        mouse[i]=".project:eq("+i+")";
        currentgithublink[i]=".githublink:eq("+i+")";

        $(mouse[i]).mouseover=(function(index){
            return function(){
                $(currentgithublink[i]).fadeIn("fast","linear");
            }

        })

        $(mouse[i]).mouseleave=(function(index){
            return function(){
                $(currentgithublink[i]).fadeOut("fast","linear");
            }

        })

    }
}   

2ND UPDATE Tried a different method... Still cant figure out why this wont work

    var currentclass=[];
    mouseover=[];
    mouseleave=[];

if(numprojects){
    for(i=0; i<=numprojects.length-1; i++){
        currentclass[i]=".project:eq("+i+")";
        mouseover[i]=getFadeIn(i);
        mouseleave[i]=getFadeOut(i);
        $(currentclass[i]).mouseover=mouseover[i];
        $(currentclass[i]).mouseleave=mouseleave[i];

    }


}   

function getFadeIn(i){
    currentgithublink=".githublink:eq("+i+")";
        return function(){
            $(currentgithublink).fadeIn("fast","linear");
        }
}
function getFadeOut(i){
    currentgithublink=".githublink:eq("+i+")";
        return function(){
            $(currentgithublink).fadeOut("fast","linear");
        }
}   
vi_ral
  • 369
  • 4
  • 19
  • Need to pay more attention to what you are checking in your `if()` statements. `if($(currentclass))` will always be truthy even if no element matching exists because `$(selector)` always returns an object and objects are truthy. Would use `if($(currentclass).length)` – charlietfl Jan 21 '17 at 15:56
  • There is a closure created in the loop with statements `currentclass=".project:eq("+i+")"; currentgithublink=".githublink:eq("+i+")";` So, i would be the last index always as the value of `i` closes over the loop. – Abhinav Galodha Jan 21 '17 at 15:59
  • `currentgithublink` will always be last index of loop at time event occurs – charlietfl Jan 21 '17 at 15:59
  • @Agalo should say *"there is **no** closure"* – charlietfl Jan 21 '17 at 16:00
  • @charlietfl wouldn't the statement `currentgithublink=".githublink:eq("+i+")";` would always have `i = numprojects.length-1` inside the handlers ? – Abhinav Galodha Jan 21 '17 at 16:03
  • @Agalo how to provide closure? – vi_ral Jan 21 '17 at 16:04
  • @charlietfl why will it always be the last index. I know the issue of my problem. – vi_ral Jan 21 '17 at 16:04
  • @charlietfl just saw that someone posted an answer just like this. Thanks – vi_ral Jan 21 '17 at 16:04
  • Because the loop completes instantly...and each iteration overwrites `currentgithublink` and you don't use that until the event actually occurs. Go through the duplicate link for a thorough understanding – charlietfl Jan 21 '17 at 16:05
  • there is actually one currentgithublink sting that exists on the closure of the anonymous function, add this line outside : items = [] and then replace currentclass=".project:eq("+i+")"; currentgithublink=".githublink:eq("+i+")"; by var item = {currentclass:".project:eq("+i+")", currentgithublink:".githublink:eq("+i+")"} items.push(item) and then in the other lines replace all currentclass by item.currentclass and currentgithublink by item.currentgithublink – challenger Jan 21 '17 at 16:29
  • @challenger Check the most updated code – vi_ral Jan 21 '17 at 16:54
  • @charlietfl Check the most updated code – vi_ral Jan 21 '17 at 16:55
  • @Agalo Check the most updated code – vi_ral Jan 21 '17 at 16:55
  • one simple way is switch out `for` loop with `$.each` in original code....then `i` will be in a closure – charlietfl Jan 21 '17 at 18:08
  • you don't need array of mouseover and mouseleave !!! actually you only need an array of currentgithublink... only those insde the callback function must not be changed in the closure...so it's only one array of currentgithublink, keep the first code with and try var currentgithublink = [] .... Sorry I can't write the code in a comment! – challenger Jan 21 '17 at 19:54
  • I was reading the code and testing it.. I really now understand the problem but I'm not sure how to solve it.. I think it can't be solved for one closure... let say that numprojects.length ==30 , then there must be 30 closures! so you may need to put the for loop out of the anonymous function... I think there is no other solution for! – challenger Jan 21 '17 at 20:24

0 Answers0