简体   繁体   中英

jquery click event fires multiple times :(

i have the following scenario:

i have a table which has trs which all have a "copy" link when the user clicks the "copy" link the parent tr is cloned and appended to the table, now the problem is, first time the click event fires okay, but 2nd time it fires two times, third time it fires three times and so on, and also as i have "cloned" the tr, i want to bind the click function to this cloned tr's "copy" link too, any solutions?

i have tried $('.copy-row-link').unbind('click').click(function() { /* the code */ });

i have read similiar qns but they doesn't seem to solve my problem

my code :

$(".copy-row-link").unbind('click').bind('click', function(e)
{
    var strdata = 'class="viewtext" style="background-color:#FFFFFF;" id="highlight1733" onMouseOver="highlight(\'1733\');" onMouseOut="removehighlight(\'1733\');'
    //var newTr = currTr.clone(true).addClass("viewtext").css( { "backgroundColor" : "#FFFFFF" } ).attr(;

    var id = currTr.attr("id"); // currTr is set previously
    var newId = id.replace("highlight", "");
    //alert( newId );
    newId = parseInt( newId );
    newId += 1;     
    var newTr = currTr.clone()
                    .addClass("viewtext newAddedRow")
                    .css("backgroundColor", "#FFFFFF")
                    .attr('id', "highlight" + newId.toString() )
                    .mouseover(
                        function() {                                
                            highlight( newId );
                        }
                    )
                    .mouseout(
                        function() {                                
                            removehighlight( newId );
                        }
                    );

    //newTr.appendTo( currTb );
    newTr.hide();
    newTr.insertAfter( "#" + id );
    newTr.fadeIn(100);
    newTr.attr('id', newId);
    //e.stopPropagation();
    //e.preventDefault();
    //e.stopImmediatePropagation();
    bindToTr(); // Bind to Tr calls this function again
    return false;
});

You've said

i have a table which has trs which all have a "copy" link

...but then your code is using

 $("#menu-item-copyRow")... 

...to get the copy link. IDs cannot be duplicated within a document, they must be completely unique.

This is a place where jQuery's new delegate feature comes in really handy (but we can easily emulate it on earlier versions; more on that below). Here's a standalone example ( live copy ) of doing this with delegate ; I haven't tried to replicate your code per se because I want to avoid complicating things too much, but it should be easy enough to take the technique and apply it to your code:

HTML:

jQuery(function($) {
  var counter = 0;

  $('#theTable').delegate('a.copyrow', 'click', copyRowClick);

  function copyRowClick() {
    var $this, $tr, $clone, $desc, label, n;

    ++counter;
    $this = $(this);
    $tr = $this.parents("tr");
    $clone = $tr.clone();
    $descr = $clone.find('td.descr');
    label = $descr.text();
    n = label.indexOf(" of ");
    if (n >= 0) {
      label = label.substring(0, n);
    }
    label = "Clone #" + counter + " of " + label;
    $descr.text(label);
        $clone.insertAfter($tr);
    return false;
  }

});​

JavaScript:

 jQuery(function($) { var counter = 0; $('#theTable').delegate('a.copyrow', 'click', copyRowClick); function copyRowClick() { var $this, $tr, $clone, $desc, label, n; ++counter; $this = $(this); $tr = $this.parents("tr"); $clone = $tr.clone(); $descr = $clone.find('td.descr'); label = $descr.text(); n = label.indexOf(" of "); if (n >= 0) { label = label.substring(0, n); } label = "Clone #" + counter + " of " + label; $descr.text(label); $clone.insertAfter($tr); return false; } });​ 

(Ignore the label stuff, it's just so we can tell what's a copy of what.)

Because there are no handlers on the elements being copied, we don't have to worry about attaching/detaching those handlers. The only event handler in the above is on the table element.

delegate is a jQuery 1.4.2+ feature, but with earlier versions you can readily emulate it by hooking the click event on table and then looking at the event.target property to see what was actually clicked. Here's how ( live copy ):

 jQuery(function($) { var counter = 0; $('#theTable').click(copyRowClick); function copyRowClick(event) { var $link, $tr, $clone, $desc, label, n; // Is the target an a.copyrow? $link = $(event.target); if ($link.is('a.copyrow')) { // Yes, handle this click -- other than changing the varname // $this to $link, the below is identical to the `delegate` // handler's version. ++counter; $tr = $link.parents("tr"); $clone = $tr.clone(); $descr = $clone.find('td.descr'); label = $descr.text(); n = label.indexOf(" of "); if (n >= 0) { label = label.substring(0, n); } label = "Clone #" + counter + " of " + label; $descr.text(label); $clone.insertAfter($tr); return false; } } });​ 

Since the Code is not clear, I'm assuming that the above function to be found in all rows/TRs? So here are my comments: 1- Don't use the same ID multiple of times, use class instead: 2- Use the live method, this way all "new" rows will have the same click event:

$(".menu-item-copyRow").live('click', function(e) {
// Code goes here
});

3- You are setting the new ID by incrementing the current clicked one?!

var id = currTr.attr("id"); // currTr is set previously
var newId = id.replace("highlight", "");
newId = parseInt( newId );
newId += 1;

You should count ALL TRs so you can get the new ID, something like this:

var newID = $('tr','#myTable').length + 1;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM