问题
I am trying to add a new row and bind a click event when the row before is selected. The problem is that this create a recursive logic as the click function is bound in itself. So currently the first update works in terms of the click binding but the not the following new rows. Heres the code
$('.new').click(function ()
{
var newrow =" <div class='controls controls-row'><div id='div_id_"+this.id.split('_')[1]+'_'+new String(parseInt(this.id.split('_')[2])+1)+"' class='control-group control span1 m-wrap input-icon' >"+this.id.split('_')[1]+'_'+new String(parseInt(this.id.split('_')[2])+1)+"</div><div id='div_rules_"+this.id.split('_')[1]+'_'+new String(parseInt(this.id.split('_')[2])+1)+"' class='control-group control span5 m-wrap input-icon' ><input type='text' onchange='updateRecord(this)' id='rules_"+this.id.split('_')[1]+'_'+new String(parseInt(this.id.split('_')[2])+1)+"' name='rules_"+this.id.split('_')[1]+'_'+new String(parseInt(this.id.split('_')[2])+1)+"' class='m-wrap span11 new' value=''/></div></div>";
var Parent = document.getElementById('tablediv');
var NewDiv = document.createElement("DIV");
NewDiv.innerHTML = newrow;
Parent.appendChild(NewDiv);
$('.new').click(function ()
{
var newrow =" <div class='controls controls-row'><div id='div_id_"+this.id.split('_')[1]+'_'+new String(parseInt(this.id.split('_')[2])+1)+"' class='control-group control span1 m-wrap input-icon' >"+this.id.split('_')[1]+'_'+new String(parseInt(this.id.split('_')[2])+1)+"</div><div id='div_rules_"+this.id.split('_')[1]+'_'+new String(parseInt(this.id.split('_')[2])+1)+"' class='control-group control span5 m-wrap input-icon' ><input type='text' onchange='updateRecord(this)' id='rules_"+this.id.split('_')[1]+'_'+new String(parseInt(this.id.split('_')[2])+1)+"' name='rules_"+this.id.split('_')[1]+'_'+new String(parseInt(this.id.split('_')[2])+1)+"' class='m-wrap span11 new' value=''/></div></div>";
var Parent = document.getElementById('tablediv');
var NewDiv = document.createElement("DIV");
NewDiv.innerHTML = newrow;
Parent.appendChild(NewDiv);
});
});
How do I create it so that the click event creates a new row and adds the same function click event to the new row. Thanks
回答1:
You can use event delegation using on() for jquery >=1.7 and live() for earlier versions.
$(document).on('click', '.new', function (){
var newrow =" <div class='controls controls-row'><div id='div_id_"+this.id.split('_')[1]+'_'+new String(parseInt(this.id.split('_')[2])+1)+"' class='control-group control span1 m-wrap input-icon' >"+this.id.split('_')[1]+'_'+new String(parseInt(this.id.split('_')[2])+1)+"</div><div id='div_rules_"+this.id.split('_')[1]+'_'+new String(parseInt(this.id.split('_')[2])+1)+"' class='control-group control span5 m-wrap input-icon' ><input type='text' onchange='updateRecord(this)' id='rules_"+this.id.split('_')[1]+'_'+new String(parseInt(this.id.split('_')[2])+1)+"' name='rules_"+this.id.split('_')[1]+'_'+new String(parseInt(this.id.split('_')[2])+1)+"' class='m-wrap span11 new' value=''/></div></div>";
var Parent = document.getElementById('tablediv');
var NewDiv = document.createElement("DIV");
NewDiv.innerHTML = newrow;
Parent.appendChild(NewDiv);
});
Instead of document
bind the event to another parent container that exists in DOM at any given point in time. This makes use of event bubbling and in actuality you are binding the event to the parent element or document head as in my example when you click on the element it matches the selector and its parent as the event bubbles up to where event is bound to and triggers the event on that element
With the way you are binding the events internally with the generic selector .new
it will bind the click event again on to the existing .new elements every time you click, so you end up having the events executed multiple times.
You can also do this as:
$(function(){
$('.new').click(handleClick);
});
function handleClick(){
var newrow =" <div class='controls controls-row'><div id='div_id_"+this.id.split('_')[1]+'_'+new String(parseInt(this.id.split('_')[2])+1)+"' class='control-group control span1 m-wrap input-icon' >"+this.id.split('_')[1]+'_'+new String(parseInt(this.id.split('_')[2])+1)+"</div><div id='div_rules_"+this.id.split('_')[1]+'_'+new String(parseInt(this.id.split('_')[2])+1)+"' class='control-group control span5 m-wrap input-icon' ><input type='text' onchange='updateRecord(this)' id='rules_"+this.id.split('_')[1]+'_'+new String(parseInt(this.id.split('_')[2])+1)+"' name='rules_"+this.id.split('_')[1]+'_'+new String(parseInt(this.id.split('_')[2])+1)+"' class='m-wrap span11 new' value=''/></div></div>";
var Parent = document.getElementById('tablediv');
var NewDiv = document.createElement("DIV");
NewDiv.innerHTML = newrow;
$(Parent).append($(NewDiv).find('.new').click(handleClick).end());
}
Also you can consider using templating to bind the data and clone the element instead of using string concatenation and creating the html dynamically in the click event.
回答2:
use .on() instead. It auto-binds to newly created elements so you don't need the recursion.
来源:https://stackoverflow.com/questions/18903762/jquery-click-event-recursion