desandro / draggabilly

:point_down: Make that shiz draggable

Home Page:https://draggabilly.desandro.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

How to manually stop dragging?

subversivo58 opened this issue · comments

How to leave the event if a given condition is reached?

example:

$('#element').draggabilly({
   containment: true,
   axis: 'x'
}).on('dragMove', function() {
   let containerWidth = $(this).parent().width()
   let buttonWidth = $(this).outerWidth()
   let max = (containerWidth - buttonWidth) - 1 // count border right (1px)
   // condiction
   if ( $(this).position().left >= max ) {
       console.log('limit reached')
       return false // escape here!!! don't escaped!
   }
}).on('dragEnd', function() {
   let containerWidth = $(this).parent().width()
   let buttonWidth = $(this).outerWidth()
   let max = (containerWidth - buttonWidth) - 1 // count border right (1px)
   // confirm condiction
   if ( $(this).position().left >= max ) {
       // do stuff...
   } else {
       // do stuff...
   }
}).on('click', function() {
   //...
})

I'm assuming that return on "move" would trigger "end"? Is there a correct method?

Thanks for reporting this issue. Could you back up and describe what kind of behavior you are trying to achieve?

I'm trying to get out of the event after reaching a given condition.

In the above example I am using a button inside a container in a form trying to create a "slide to submit" function ... so I am computing the measure taken in "dragMove" to see if the button has reached the end.

slide

Using as an example jQuery UI (draggable) and return false inside the "drag" event makes it possible to drop into "stop"... example:

$( "#element" ).draggable({
    cancel: false,
    containment: 'parent',
    axis: 'x',
    start: function(event, ui) {
        console.log('start')
    },
    drag: function(event, ui) {
        let containerWidth = $(this).parent().width()
        let buttonWidth = $(this).outerWidth()
        let max = (containerWidth - buttonWidth) - 1 // count border right (1px)
        // condiction
        if ( $(this).position().left >= max ) {
            console.log('limit reached')
            return false // escape here!!! 
        }
    },
    stop: function(event, ui) {
        console.log('end')
    }
}).on("click", function(evt) {
    // prevent event submit
    evt.preventDefault()
})
/**
  assuming that the move has occurred and the "drag" event has been
  triggered the output will be something like:

  > start
  > limit reached
  > end
 */

I can just test case in this PEN

Using return false in Draggabilly within the "dragMove" event is not falling on "dragEnd" and the observer (the event handler) is not being disabled.

$('#element').draggabilly({
   containment: true,
   axis: 'x'
}).on('dragStart', function() {
   console.log('start')
}).on('dragMove', function() {
   let containerWidth = $(this).parent().width()
   let buttonWidth = $(this).outerWidth()
   let max = (containerWidth - buttonWidth) - 1 // count border right (1px)
   // condiction
   if ( $(this).position().left >= max ) {
       console.log('limit reached')
       return false // escape here!!! don't escaped!
   }
}).on('dragEnd', function() {
   console.log('end')
}).on('click', function(evt) {
   //...
   evt.preventDefault()
})
/**
  assuming that the move has occurred and the "drag" event has been
  triggered the output will be something like:

  > start
  > limit reached

  // this only occurs at the end of the "click" is not being triggered with "return false"
  > end
 */

View this PEN ... on reaching the end (the button) is being used return false but is not terminating the "dragMove" event.

I'm currently using a code snippet written in Vanilla to get the result I want but I have no intention of "reinventing the wheel" ... I liked this library it is much more compact than jQuery Ui and it allows to observe numerous events.

Maybe I did not understand the correct functioning of the library but I think my question is logical. No?

Thank you in advance for your attention and patience.

Thanks so much for you description and CodePens!

Bad news there is no good API to manually stop dragging. Good news is that you can hack it by calling a private method _pointerUp within dragMove:

var $submitBtn = $('#submit-btn').draggabilly({
   containment: true,
   axis: 'x'
})

var draggie = $submitBtn.data('draggabilly');

$submitBtn.on('dragMove', function( event, pointer ) {
   let containerWidth = $(this).parent().width()
   let buttonWidth = $(this).outerWidth()
   let max = (containerWidth - buttonWidth) - 1 // count border right (1px)
   // condition
   if ( draggie.position.x >= max ) {
       draggie._pointerUp( event.originalEvent, pointer );
   }
})

See demo https://codepen.io/desandro/pen/RxJrra/


Add a 👍 reaction to this issue if you would like to see Draggabilly get a dragStop method added. Do not add +1 comments — They will be deleted.

Great.

I really liked the approach, thank you for your attention, that solves the issue.

This helped with my containment issue...thanks!

Draggabilly v3 has been released with revised dragEnd method. Use it to stop dragging

// jQuery
$draggable.draggabilly('dragEnd')
// vanilla JS
draggie.dragEnd()

Unfortunately, v3 + dragEnd still buggy. Does not restore position after dragEnd call. I return back to _pointerUp hack and v2.

@rawthriver Can you put together a CodePen showing what behavior you would like?

Here it is https://codepen.io/rawthriver/pen/qBPGGbM
Try to drag item 2 on stamped item 1.
Using v3 we have item 2 stuck over item 1. Using v2 with _pointerUp it works fine, item 2 goes back.