1. Advertising
    y u no do it?

    Advertising (learn more)

    Advertise virtually anything here, with CPM banner ads, CPM email ads and CPC contextual links. You can target relevant areas of the site and show ads based on geographical location of the user if you wish.

    Starts at just $1 per CPM or $0.10 per CPC.

I need help to avoid closure in for loop

Discussion in 'JavaScript' started by JonKenneth, May 23, 2010.

  1. #1
    Hello! I have a couple of questions.
    I started out with this code. It's suposed to make a div apear/dissapear when a link is clicked. That didn't work because the function openEdit executed onload instead of being assigned to the onclick event. Can someone explain why that happens.

    function initAll(){			
    	var currNum=1;
    	document.getElementById("rediger_id"+currNum).onclick=openEdit(currNum);			
    }
    
    function openEdit(id){
    	if(document.getElementById("id"+id).style.height!="auto"){
    		document.getElementById("id"+id).style.height="auto";	
    	}
    	else if(document.getElementById("id"+id).style.height=="auto"){
    		document.getElementById("id"+id).style.height="0px";
    	}
    	return false;
    }
    Code (markup):
    I then asked on this forum and got an answer that worked. I had to put openEdit(currNum) inside an anonymous function.

    
    function initAll(){		
    		var currNum=1;
    		document.getElementById("rediger_id"+currNum).onclick=function(){openEdit(currNum); return false;};			
    }
    
    function openEdit(id){
    	if(document.getElementById("id"+id).style.height!="auto"){
    		document.getElementById("id"+id).style.height="auto";	
    	}
    	else if(document.getElementById("id"+id).style.height=="auto"){
    		document.getElementById("id"+id).style.height="0px";
    	}
    	return false;
    }
    
    Code (markup):
    Now i need to place this in a for loop whitch leads to a new problem. The anonymous function creates a closure, so that all the onclick events get assigned with the same value in currNum. I try to understand closures and like many others struggle to understand it. I think i begin to understand how to create a closure, but i don understand how to avoid it in loop cases.
    SEMrush
    
    function initAll(){		
    		
    		for(var currNum=1; document.getElementById("rediger_id"+currNum)!=null; currNum++){			
    				document.getElementById("rediger_id"+currNum).onclick=function(){openEdit(currNum); return false;};			
    		}		
    }
    
    function openEdit(id){
    	if(document.getElementById("id"+id).style.height!="auto"){
    		document.getElementById("id"+id).style.height="auto";	
    	}
    	else if(document.getElementById("id"+id).style.height=="auto"){
    		document.getElementById("id"+id).style.height="0px";
    	}
    	return false;
    }
    
    Code (markup):
    I keep running into this closure/loop problem:(, so if someone could help me with the solution for this it would really make my day, week, month...:D
     
    JonKenneth, May 23, 2010 IP
    SEMrush
  2. Logic Ali

    Logic Ali Active Member

    Messages:
    170
    Likes Received:
    5
    Best Answers:
    0
    Trophy Points:
    58
    #2
    First of all why do you want to avoid it? What value do you want passed to openEdit?

    BTW that function would look better like this:
    
    function openEdit(id)
    {
     var elem = document.getElementById("id"+id);
    
     if( elem )
      elem.style.height = ( elem.style.height != 'auto' ? 'auto' : '0px' );
    
     return false;
    }
    Code (markup):
     
    Logic Ali, May 23, 2010 IP
  3. dimitar christoff

    dimitar christoff Active Member

    Messages:
    882
    Likes Received:
    62
    Best Answers:
    0
    Trophy Points:
    90
    #3
    you need to refactor the onclick a little so it picks variables that are relational to the click object. the problem is not the closure as such but the fact that the value of curNum at the click runtime will always be the last one of the loop. instead, you write the value into the click trigger property rel and read it on the click, it will then be fine. another way to do it would be to do var id = this.id.replace("rediger_", ""); openEdit(id);

    
    for(var currNum=1; document.getElementById("rediger_id"+currNum)!=null; currNum++) {            
        var rediger = document.getElementById("rediger_id"+currNum);
        rediger.setAttribute("rel", currNum); // use element storage
        rediger.onclick = function() {
            openEdit(this.getAttribute("rel"));
            return false;
        };            
    } 
    Code (javascript):
    btw, use
     to start a js code block.
    Code (javascript):
     
    dimitar christoff, May 25, 2010 IP