最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - jquery event firing twice on single click - Stack Overflow

programmeradmin0浏览0评论

I am working with a web application where I am re-ordering HTML table rows and am seeing when an item with a class is clicked. The event is firing twice but I do not see how.

I would be grateful if anyone would be able to let me know how I can stop this behavior as this will be creating an AJAX call and passing the array back to the code behind but I only need and want it to fire once.

$('table').on('click', ".up,.down,.top,.bottom", function() {

  console.log("up or down arrow clicked");

  var row = $(this).parents("tr:first");
  if ($(this).is(".up")) {
    if (row[0].rowIndex > 1) {
      row.insertBefore(row.prev());
    }
  } else if ($(this).is(".down")) {
    row.insertAfter(row.next());
  } else if ($(this).is(".top")) {
    row.insertBefore($("table tr:first"));
    row.insertAfter(row.next());
  } else {
    row.insertAfter($("table tr:last"));
  }

  //... more code here

});
<script src=".1.1/jquery.min.js"></script>
<link rel="stylesheet" href=".7.0/css/font-awesome.min.css" />
<table>
  <tr id="sectionRow_1010_M_TR" style="border: 1px solid black;">
    <td style="padding: 0px; width: 15px;">
      <input class="collapse" id="btnMinus0_1010" style="padding: 0px; width: 15px; height: 20px; text-align: center; vertical-align: top; display: none;" onclick="collapse('0_1010')" type="button" value="-">
      <input class="expand" id="btnPlus0_1010" style="padding: 0px; width: 15px; height: 20px; text-align: center; vertical-align: top;" onclick="expand('0_1010')" type="button" value="+">
    </td>
    <td style="padding: 0px; width: 100%; text-align: left; background-color: gray;">
      <span>Engine, Fuel and Cooling Systems</span>
    </td>
    <td>
      <a class="up" href="#"><i class="fa fa-angle-up" aria-hidden="true"></i></a>
      <a class="down" href="#"><i class="fa fa-angle-down" aria-hidden="true"></i></a>
    </td>
  </tr>
</table>

I am working with a web application where I am re-ordering HTML table rows and am seeing when an item with a class is clicked. The event is firing twice but I do not see how.

I would be grateful if anyone would be able to let me know how I can stop this behavior as this will be creating an AJAX call and passing the array back to the code behind but I only need and want it to fire once.

$('table').on('click', ".up,.down,.top,.bottom", function() {

  console.log("up or down arrow clicked");

  var row = $(this).parents("tr:first");
  if ($(this).is(".up")) {
    if (row[0].rowIndex > 1) {
      row.insertBefore(row.prev());
    }
  } else if ($(this).is(".down")) {
    row.insertAfter(row.next());
  } else if ($(this).is(".top")) {
    row.insertBefore($("table tr:first"));
    row.insertAfter(row.next());
  } else {
    row.insertAfter($("table tr:last"));
  }

  //... more code here

});
<script src="https://ajax.googleapis./ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn./font-awesome/4.7.0/css/font-awesome.min.css" />
<table>
  <tr id="sectionRow_1010_M_TR" style="border: 1px solid black;">
    <td style="padding: 0px; width: 15px;">
      <input class="collapse" id="btnMinus0_1010" style="padding: 0px; width: 15px; height: 20px; text-align: center; vertical-align: top; display: none;" onclick="collapse('0_1010')" type="button" value="-">
      <input class="expand" id="btnPlus0_1010" style="padding: 0px; width: 15px; height: 20px; text-align: center; vertical-align: top;" onclick="expand('0_1010')" type="button" value="+">
    </td>
    <td style="padding: 0px; width: 100%; text-align: left; background-color: gray;">
      <span>Engine, Fuel and Cooling Systems</span>
    </td>
    <td>
      <a class="up" href="#"><i class="fa fa-angle-up" aria-hidden="true"></i></a>
      <a class="down" href="#"><i class="fa fa-angle-down" aria-hidden="true"></i></a>
    </td>
  </tr>
</table>

Share Improve this question edited Jul 14, 2017 at 12:39 Nathan Arthur 9,1267 gold badges64 silver badges83 bronze badges asked Jul 14, 2017 at 12:33 Simon PriceSimon Price 3,2716 gold badges45 silver badges106 bronze badges 4
  • 1 Stack Snippets are for runnable examples. When I try to run this one, I get Uncaught ReferenceError: expand is not defined Edit: Ah, that's when I click the [+], but the question is about the arrows. Fair enough. – T.J. Crowder Commented Jul 14, 2017 at 12:36
  • 3 After creating a snippet I only see one triggered when I click the arrows – mplungjan Commented Jul 14, 2017 at 12:36
  • Only triggering once here... Perhaps your code is being loaded twice. – Abdul Sadik Yalcin Commented Jul 14, 2017 at 12:38
  • Are you sure you're not calling the handler twice? – StudioTime Commented Jul 14, 2017 at 12:39
Add a ment  | 

2 Answers 2

Reset to default 4

Your symptom doesn't match your code, but the three most likely reasons for your symptom are (I lean toward #3):

  1. You have an .up, .down, .bottom, or .top element inside an .up, .down, .bottom, or .top element. So since click propagates (and jQuery faithfully replicates that when doing event delegation), it's firing for the innermost match, and also for the outermost match.

    If so, target the handler more directly at the elements in question.

    or

  2. You're running your code twice, and thus setting up two handlers, each of which is firing.

    If so, er, don't do that. :-)

    or

  3. Your table is inside another table, so $("table") matches both of them, and again because click propagates (at the DOM level this time), you get a response from both tables.

    If so, target just the table you want these handlers hooked up in.

Since your code doesn't replicate it, here's a simplified example of #1:

$("table").on("click", ".up, .down", function() {
  console.log(this.className + " clicked");
});
<table>
  <tbody>
    <tr class="up">
      <td class="down">Click me</td>
    </tr>
  </tbody>
</table>
<script src="https://ajax.googleapis./ajax/libs/jquery/2.1.1/jquery.min.js"></script>

...and of #2:

$(document).ready(setup);
$(window).load(setup);
function setup() {
  $("table").on("click", ".up, .down", function() {
    console.log(this.className + " clicked");
  });
}
<table>
  <tbody>
    <tr>
      <td class="down">Click me</td>
    </tr>
  </tbody>
</table>
<script src="https://ajax.googleapis./ajax/libs/jquery/2.1.1/jquery.min.js"></script>

...and of #3:

$("table").on("click", ".up, .down", function() {
  console.log(this.className + " clicked");
});
<table>
  <tbody>
    <tr>
      <td>
        <table>
          <tbody>
            <tr>
              <td class="down">Click me</td>
            </tr>
        </tbody>
      </table>
    </td>
  </tr>
<script src="https://ajax.googleapis./ajax/libs/jquery/2.1.1/jquery.min.js"></script>

1) It may be happening as you are assigning the same handler to click event multiple times. I suggest, you kindly check the line where you assign the handler. I guess it is being called multiple times. A solution could be a call to unbind first then bind, like this:

$('table').unbind("click").click('.up,.down,.top,.bottom') {
     //Do Stuff
});

$('table').off("click").on('click', ".up,.down,.top,.bottom", function() {
     //Do Stuff
});

2) if in any case, if you find that .off() .unbind() or .stopPropagation() can't fix your issue, please use .stopImmediatePropagation(). It usually works great in these kind of situations when you just want your event to be handled without any bubbling and without effecting any other events already being handled. Something like:

$("table").click(function(event) {
  event.stopImmediatePropagation();
  //Do Stuff
});

which does the trick always!

发布评论

评论列表(0)

  1. 暂无评论