Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to handle "click" event even if element is moved from beneath the cursor between mousedown and mouseup?

I have an <input> and a <button>.

The input has an onblur event handler that (sometimes) results in the <button> being moved; if, with focus on the <input>, the user goes to click on the <button> (and it is thereby moved from beneath the pointer before the click completes) they must currently move their pointer to the button's new location and click it a second time. This experience is suboptimal.

I would like for users to have to click the <button> only once (but must retain the functionality of the button moving when the <input> loses focus). However, if a user mousedowns over the button and then moves their mouse pointer away (includes switching focus from the application) before mouseup, no click event should be triggered (as normal).

I can't see any approach based on handling onmousedown and/or onmouseup that would not be prone to errors in some edge cases. All that I can think is to forcibly move the cursor in the onblur handler so that the click completes (if indeed it would?)—but this is probably a poor user experience too.

How can this best be handled?

$('button').click(
  $('<li><input></li>')
    .children('input')
      .blur(function(){
        if (!this.value.length)
          this.parentElement.remove();
      })
      .end(),

  function(e){
    e.data.clone(true)
      .appendTo($(this).data('target'))
      .children('input')
        .focus();
  }
);
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
List 1<button data-target="#list1">+</button><ul id="list1"></ul>
List 2<button data-target="#list2">+</button><ul id="list2"></ul>
like image 268
eggyal Avatar asked Nov 01 '22 05:11

eggyal


1 Answers

One approach would be to fade the element out over the course of, say, a second rather than immediately, which gives the user time to complete the click before the button moves:

$(this.parentElement).fadeOut("slow", function() {
    $(this).remove();
});

Live example:

$('button').click(
  $('<li><input></li>')
    .children('input')
      .blur(function(){
        if (!this.value.length)
          $(this.parentElement).fadeOut("slow", function() {
              $(this).remove();
          });
      })
      .end(),

  function(e){
    e.data.clone(true)
      .appendTo($(this).data('target'))
      .children('input')
        .focus();
  }
);
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
List 1<button data-target="#list1">+</button><ul id="list1"></ul>
List 2<button data-target="#list2">+</button><ul id="list2"></ul>

That said, I think I'd try to find a way that the space between the list elements didn't change at all, because this still means things move around, just at a different time — hopefully at a time the user will be less bothered by it, but... Tricky in this case, though, because of the lists being on top of each other — the second list is going to move at some point. If you made it that there was always an input box for the user to type in, then the second list would just move at a different time (when the box does have a value in it and you add a new blank one for the next value). Could be done with a fixed list size and scrolling within, but it depends on the overall design.

like image 100
T.J. Crowder Avatar answered Nov 12 '22 14:11

T.J. Crowder