I am using the jQuery clone()
method to clone a table row, then using the attr()
method to change the name/id of some of the fields. This all works well and good and if I use "view generated source" the names/IDs are getting set properly however when the generated content triggers a JavaScript event it triggers it as if it were the parent element. For example I have an element with the name/id 'slast1' which should trigger the autocomplete method (based on the fact that it is part of the 'slast' class) and that works fine. Unfortunately when I click the same element in the generated row (in this case the element id/name is 'slast2') it triggers the autocomplete method but acts as if it was triggered from the parent element, 'slast1'. I can't seem to find a way around this and am thinking it might be a limitation of using the clone()
method but am hoping I am just missing something.
function fnAddRow(iRow)
{
var iNewRow = iRow+1;
$("#tblAuthors tr:last").clone(true).insertAfter("#tblAuthors tr:last");
$("#tblAuthors tr:last #slast"+iRow).attr("name", "slast"+iNewRow);
$("#tblAuthors tr:last #slast"+iRow).attr("id", "slast"+iNewRow);
$("#slast"+iNewRow).val("");
}
The above code clones the table row and changes the attributes as I mentioned before. The code below is what gets triggered by the keydown
event in the slastX
element but for whatever reason the generated elements are treated开发者_JS百科 as if they were the parent.
$(function()
{
var aEmps =
[
<?php
echo $sEmps;
?>
];
$(".slast").bind( "keydown", function( event ) {
if ( event.keyCode === $.ui.keyCode.TAB &&
$( this ).data( "autocomplete" ).menu.active )
{ event.preventDefault();}
})
.autocomplete({
source: aEmps,
close: function(event, ui)
{
// Split return value and store in array
var aName = this.value.split(", ");
// Get row #
var iRow = this.name[this.name.length-1];
// Populate values
$("#slast"+iRow).val(aName[0]);
$("#sfirst"+iRow).val(aName[1]);
$("#smi"+iRow).val(aName[2]);
}
});
});
As you can see the autocomplete method should be triggered by anything with the slast
class but for reasons I can't figure out $(this) always = the parent ('slast1')
as opposed to slast2
or any other generated content.
Use live
instead of bind
, this should solve the problem for you.
When you are using .clone(true)
you are coping all data()
and all events bound to that element. Which is causing your problems.
If you switch your event binding to use .delegate()
(or .live()
) you should be able to fix your problem of the event being triggered.
var autoCompleteOptions = {
source: aEmps,
close: function(event, ui)
{
// Split return value and store in array
var aName = this.value.split(", ");
// Get row #
var iRow = this.name[this.name.length-1];
// Populate values
$("#slast"+iRow).val(aName[0]);
$("#sfirst"+iRow).val(aName[1]);
$("#smi"+iRow).val(aName[2]);
}
};
$("#tblAuthors").delegate("tr .slast", "keydown", function(event){
if ( event.keyCode === $.ui.keyCode.TAB &&
$( this ).data( "autocomplete" ).menu.active ) {
event.preventDefault();
}
}).autocomplete(autoCompleteOptions);
function fnAddRow(iRow)
{
//....stuff.....
$("#tblAuthors tr:last #slast"+iRow).autocomplete(autoCompleteOptions);
//....stuff.....
}
With using delegate you are binding the event to $("#tblAuthors")
and not the .slast
directly.
Also on a side note, using delegeate
might be able to gain you a bit of performance as well in relation to this answer.
UPDATE: Mark and I went back-and-forth a lot on the solution to this, here is the final code: http://jsfiddle.net/niczak/HjCMh/1/
A helpful tool you may find useful in seeing what event handlers are bound to various elements is Visual Event, it works as a bookmarklet and I find it invaluable at times.
In your case, it should let you see what handlers are bound to the cloned rows, if any.
精彩评论