Can't loop properly

My alert only works on the last input1 even though there might be a list of 10 input1’s displayed. I know that I am just not looping over the element, but I can’t find the fix because I am already looping over the object. Please be specific with your guidance.


ajax.get('/assets/ajax/partner_review.php?uid=' + uid, function(responce)
			{
				var info = eval('(' + responce + ')');
				var i;
				
				lightbox.show(info[0], function(body)
				{
					
					for (i = 0; i < info[1].length; ++i) 
					{
						var row 		= document.createElement('div');
						var div1 		= document.createElement('div');
						var a			= document.createElement('a');
						var img 		= document.createElement('img');
						var span 		= document.createElement('span');
						var div2		= document.createElement('div');
						var div3		= document.createElement('div');
						var input1		= document.createElement('input');
						var input2		= document.createElement('input');
						var requestform	= document.createElement('form');
						
						input1.type = 'submit';
						input2.type = 'submit';
						
						input1.value = 'Accept';
						input2.value = 'Deny';
						
						input1.name = 'acceptrequest[' + info[1][i].uid + ']';
						input2.name = 'denyrequest[' + info[1][i].uid + ']';
						
						requestform.name = 'requestform';
						requestform.method = 'post';
						requestform.action = 'http://mysite.com/home.php';
						
						a.href = 'http://mysite.com/u/' + info[1][i].username;
						a.setAttribute('target', '_blank');
						
						addClass(row, 'lb_row');
						
						img.src = info[1][i].avatar;
						img.alt = info[1][i].displayName;
						
						row.appendChild(div1);
						
						a.appendChild(img);
						div1.appendChild(a);
						addClass(div1, 'lb_div');
						addClass(div1, 'tdfirst_review');
						addClass(img, 'avatar extrasmall vmiddle');
						
						span.appendChild(document.createTextNode(info[1][i].displayName)) 
						a.appendChild(span);
						addClass(span, 'lb_span');
						
						div2.appendChild(input1);
						row.appendChild(div2);
						addClass(div2, 'lb_div_button');
						addClass(div2, 'lb_align');
						
						div3.appendChild(input2);
						row.appendChild(div3);
						addClass(div3, 'lb_div_button');
						addClass(div3, 'lb_align');
						addClass(div3, 'right');
						
						requestform.appendChild(row);
						body.appendChild(requestform);
							
						requestform.onsubmit = function ()
						{
							input1.onclick = function ()
							{
								alert(input1.name);
							}
							
							return false;
						}
					}
				});

It’s a closure issue with input.name in the onsubmit handler.

I had to do some experimentation myself. Below hopefully goes some way to explaining the issue and a solution.

var liNode = document.createElement('li');
    liNode.idName = 'id1';

// The returned function is wrapped in an auto-executing function
// This creates a namespace and allows us to pass in the element.
// Note: el is the element that's assigned to liNode and not the liNode variable itself.
// The returned function forms a permanent link with this element via it's scope chain.
var test1 = (function(el){
 return function() { // el is kept in closure by this returned function
   console.log("The closure's id name is " + el.idName); 
 }
}(liNode));  // passes in a reference to the li element

// we are not using closure here so just reference liNode and 
// whatever it happens to contain or point to at the time
var test2 = function(){
  console.log('and this id name is ' + liNode.idName);
}

liNode = document.createElement('li'); // liNode get's a new element
liNode.idName = 'id2';

console.log(liNode.idName); // id2
test1(); // id1. Still references the first element not the variable's new element
test2(); // id2

RLM

It’s throwing me a bit the event assignment within an event handler, but try this.

requestform.onsubmit = (function(inp1){
  return function(){
    inp1.onclick = function (){
      alert(inp1.name);
    }
    return false;
  }
}(input1));

It can be helpful to move the function out else-where. With the above code, it’s tempting to naturally think that the inner code has access to the variables of the outer code.

When the function is placed elsewhere, that can help to make things clearer.


var setClickHandler = function (el, handler) {
    return function () {
        el.onclick = handler;
        return false;
    }
};
requestform.onsubmit = setClickHandler(input1, function () {
    alert(this.name);
});

It can be helpful to move the function out else-where. With the above code, it’s tempting to naturally think that the inner code has access to the variables of the outer code.

Thanks. I did have my doubts.

I had also considered ‘this.name’ as an alternative but wrongly assumed that IE would fail to set the context to the element. It seems onclick doesn’t suffer with that issue. It’s only when using attachEvent you need to take the extra measure of binding the handler to the element.

Still learning and forgetting.

Edit: Just checked my version with a simple test and it does work though so it does have access to the outer variables(which makes sense). I do think seperating the code the way you’ve done it is clearer and probably more flexible though.

RLM

Thanks for all of your help guys, but I hate to say it… i’m still stuck. I tried playing around with it some more but man, I’m really bad / new to the JS stuff. I can’t wrap my head around it.

I’ve attached my entire file below. The comments even detail what I want to do. Please help correct my code.


addOnload(function()
{
	var link = document.getElementById('associateRequests');
	var link2 = document.getElementById('associateRequests2');
	
	if (link)
	{
		link.onclick = function()
		{
			var uid = link.href.split('=');
			uid = uid[1];
			
			ajax.get('/assets/ajax/partner_review.php?uid=' + uid, function(responce)
			{
				var info = eval('(' + responce + ')');
				var i;
				
				lightbox.show(info[0], function(body)
				{
					
					for (i = 0; i < info[1].length; ++i) 
					{
						var row 		= document.createElement('div');
						var div1 		= document.createElement('div');
						var a			= document.createElement('a');
						var img 		= document.createElement('img');
						var span 		= document.createElement('span');
						var div2		= document.createElement('div');
						var div3		= document.createElement('div');
						var input1		= document.createElement('input');
						var input2		= document.createElement('input');
						var requestform	= document.createElement('form');
						
						input1.type = 'submit';
						input2.type = 'submit';
						
						input1.value = 'Accept';
						input2.value = 'Deny';
						
						input1.name = 'acceptrequest[' + info[1][i].uid + ']';
						input2.name = 'denyrequest[' + info[1][i].uid + ']';
						
						requestform.name = 'requestform';
						requestform.method = 'post';
						requestform.action = 'http://mysite.com/home.php';
						
						a.href = 'http://mysite.com/u/' + info[1][i].username;
						a.setAttribute('target', '_blank');
						
						addClass(row, 'lb_row');
						
						img.src = info[1][i].avatar;
						img.alt = info[1][i].displayName;
						
						row.appendChild(div1);
						
						a.appendChild(img);
						div1.appendChild(a);
						addClass(div1, 'lb_div');
						addClass(div1, 'tdfirst_review');
						addClass(img, 'avatar extrasmall vmiddle');
						
						span.appendChild(document.createTextNode(info[1][i].displayName)) 
						a.appendChild(span);
						addClass(span, 'lb_span');
						
						div2.appendChild(input1);
						row.appendChild(div2);
						addClass(div2, 'lb_div_button');
						addClass(div2, 'lb_align');
						
						div3.appendChild(input2);
						row.appendChild(div3);
						addClass(div3, 'lb_div_button');
						addClass(div3, 'lb_align');
						addClass(div3, 'right');
						
						requestform.appendChild(row);
						body.appendChild(requestform);
							
						//requestform.onsubmit = function ()
						//{
							/* So what to do here, thats the question
							
							- You want to get the data of the button that has been pressed, if such function exists.
							- Then use AJAX to send the form data to some file that probably doesnt exist yet.
							- Give the PHP a responce, and echot he response to replace the buttons
							
							*/
						//	input1.onclick = function ()
						//	{
						//		alert(input1.name);
						//	}
							
						//	return false;
						//}
					}
					
					var setClickHandler = function (el, handler) {
					    return function () {
					        el.onclick = handler;
					        return false;
					    }
					};
					requestform.onsubmit = setClickHandler(input1, function () {
					    alert(this.name);
					});
				});
			});
		
			return false;
		}
	}
});