Search code examples
javascriptjquerydraggableclickable

jQuery: Finish dragging without triggering click event


I am trying to set up the following page where:

  1. If you click the button, you can see a div.
  2. If you click the div, you can see the next div.
  3. If you move the button, there is no »click« (desired behaviour)

The problem I am having is that if you move the div, the next div appears - this is not what I want. The "next div" should not be displayed after a drag event finishes on it.

Here is my code:

$(function() {
  $("#button").draggable({
    stack: 'div',
    containment: "body"
  });
});

$('#button').on('mouseup', function() {
  if (!$(this).hasClass('ui-draggable-dragging')) {
    // click function
    $("#content").toggle();
  }
});

$(function() {
  $("#content").draggable({
    stack: 'div',
    containment: "body"
  });
});

let containers = $('.trip').hide();
let firstContainer = containers.first().show();

containers.on('click', function() {
  //Get current element and next sibling
  let elem = $(this);
  let next = elem.next('.trip');

  //Does sibling exist?
  if (next.length) {
    next.show();
  } else {
    firstContainer.show();
  }
  elem.hide();
});
body {
  width: 100vw;
  height: 100vh;
  padding: 0;
  margin: 0;
  left: 0;
  top: 0;
  background-color: grey;
}

#button {
  width: 100px;
  height: 100px;
  background-color: cyan;
}

#content {
  display: none;
  cursor: all-scroll;
  top: 10%;
  left: 10%;
  position: absolute;
}

.trip {
  width: 200px;
  height: 200px;
  background-color: blue;
  color: white;
}
<div id="button">Button</div>

<div id="content">
  <div class="trip">div 1</div>
  <div class="trip">div 2</div>
  <div class="trip">div 3</div>
</div>

<script src="https://code.jquery.com/jquery-1.7.2.min.js"></script>
<script src="https://code.jquery.com/ui/1.8.21/jquery-ui.min.js"></script>
<script src="https://raw.githubusercontent.com/furf/jquery-ui-touch-punch/master/jquery.ui.touch-punch.min.js"></script>

Is there a way to solve this? :)
(a possible problem is also that pure JavaScript is mixed with jQuery)
Thanks


Solution

  • The main problem to solve here is in distinguishing a regular click event on #content, from other "click like events" that are also triggered during completion of the element being dragged.

    You're code currently has a method of doing that which you could re purpose for the desired behaviour:

    if (! $(this).hasClass('ui-draggable-dragging')) {
       /* This was a "regular click event"
    }
    

    So in the case of your code, you could revise it as follows:

    $(function() {
    
      /* Combine on ready logic into one place */
    
      $("#button").draggable({
        stack: 'div',
        containment: "body"
      });
      
      $("#content").draggable({
        stack: 'div',
        containment: "body"
      });
      
      /* Hide all trip elements except for first */
      $('.trip', '#content').not(':first').hide();
    });
    
    $('#button').on('mouseup', function() {
      if (!$(this).hasClass('ui-draggable-dragging')) {
        $("#content").toggle();
      }
    });
    
    $('#content').on('mouseup', function() {
    
      /* Reuse same logic in #button mouseup handler */
      if (!$(this).hasClass('ui-draggable-dragging')) {
    
          /* 
          If content element if not dragging, treat mouse up as conclusion
          of click event and rotate visibility of trip elements like this
          */
          let trip = $('.trip:visible', '#content');
          let next = trip.next().length === 0 ? 
              $('.trip:first', '#content') : trip.next();
          
          trip.hide();
          next.show(); 
      }
    });
    body {
      width: 100vw;
      height: 100vh;
      padding: 0;
      margin: 0;
      left: 0;
      top: 0;
      background-color: grey;
    }
    
    #button {
      width: 100px;
      height: 100px;
      background-color: cyan;
    }
    
    #content {
      display: none;
      cursor: all-scroll;
      top: 10%;
      left: 10%;
      position: absolute;
    }
    
    .trip {
      width: 200px;
      height: 200px;
      background-color: blue;
      color: white;
    }
    <div id="button">Button</div>
    
    <div id="content">
      <div class="trip">div 1</div>
      <div class="trip">div 2</div>
      <div class="trip">div 3</div>
    </div>
    
    <script src="https://code.jquery.com/jquery-1.7.2.min.js"></script>
    <script src="https://code.jquery.com/ui/1.8.21/jquery-ui.min.js"></script>
    <script src="https://raw.githubusercontent.com/furf/jquery-ui-touch-punch/master/jquery.ui.touch-punch.min.js"></script>