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

javascript - Why is jQuery select event listener triggering multiple times? - Stack Overflow

programmeradmin1浏览0评论

Please run this sample in Google Chrome browser.

Stack Snippet

$(function() {
  $(":input").select(function() {
    $("div").text("Something was selected").show().fadeOut(1000);
    alert("Selected");
  });
  $("button").click(function() {
    $(":input").select();
  });
});
<script src=".8.3/jquery.min.js"></script>
<button>Click To Select</button>
<input type="text" value="Some text">
<div></div>

Please run this sample in Google Chrome browser.

Stack Snippet

$(function() {
  $(":input").select(function() {
    $("div").text("Something was selected").show().fadeOut(1000);
    alert("Selected");
  });
  $("button").click(function() {
    $(":input").select();
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<button>Click To Select</button>
<input type="text" value="Some text">
<div></div>

Here why jQuery select event listener is triggering multiple times? Does anyone know the reason behind this? And is there any workaround solution for this without using timeout?

Share Improve this question edited Mar 29, 2016 at 13:35 Michał Perłakowski 92.5k30 gold badges163 silver badges186 bronze badges asked Mar 29, 2016 at 12:26 John RJohn R 2,7912 gold badges15 silver badges33 bronze badges 1
  • 1 jsfiddle.net/arunpjohny/3qkvr5zq/2 - Once it is triggered internally by the select() call, but after the click handler is exited it is called twice which I assume is done by the render operation – Arun P Johny Commented Mar 29, 2016 at 12:37
Add a comment  | 

3 Answers 3

Reset to default 14

The $(":input") selector is selecting the button too, so it causes recursion. Either use just $("input"), or $(":input:not(button)").

I noticed when the three events are fired, the first doesn't have originalEvent property, so we definitely can dismiss it, and the second two has very similar (however not identical) timestamp. You can store the last timestamp in some variable and in event listener compare it with the event's timestamp. If the rounded values of these two are the same, you can dismiss this event.

$(function() {
  var lastTimeStamp;
  $("input").select(function(event) {
    if (!event.originalEvent ||
        lastTimeStamp === Math.round(event.timeStamp)) return;
    lastTimeStamp = Math.round(event.timeStamp);
    $("div").text("Something was selected").show().fadeOut(1000);
    alert("Selected");
  });
  $("button").click(function() {
    $("input").select();
  });
});

See updated JS Fiddle.

It appears the issue is a combination of:

  • the :input selector gets the input and the button, hence multiple events triggered.
  • even when using just input as the selector there is some odd event propagation being triggered on related elements which is raising the select event handler multiple times.

To avoid both of the above, use input as the selector and also use preventDefault() in the event handler. stopPropagation() may also be required, depending on your HTML stucture.

$(function() {
    $('input').select(function(e) {
        // e.stopPropagation(); // optional
        e.preventDefault();
        $('#message').text("Something was selected").show().fadeOut(1000);
        console.log('Selected');
    });

    $('button').click(function() {
        $('input').select();
    });
});

Working example

UPDATE: We were all fooled. The select() function needs a prevent default.

Rory McCrossan figured it out. Well done mate.

Incidentally, I'm not sure what the benefit of select() actually is! Something like focus() or on('focus',) might make more sense. Not Sure what the context is however. The below still follows:

Why waste time using generalised tag/type selectors which may change? Use an ID, and pick out only the one you want.

If you want to detect multiple, use a class. If you want to use multiple, but figure out which one you clicked, use a class and an ID. Bind with the class, and identify using $this.attr('id').

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<button>Click To Select</button>
<input type="text" value="Some text" id="pick-me">
<div></div>
$(function() {
  $("#pick-me").select(function(event) {
    event.preventDefault();
    $("div").text("Something was selected").show().fadeOut(1000);
    alert("Selected");
  });
  $("button").click(function() {
    $("#pick-me").select();
  });
});
发布评论

评论列表(0)

  1. 暂无评论