JQuery Draggable - Center Cursor Vertically

I am working on my first jQuery project and I came across a checkpoint. I am trying to allow reordering of a set of nested lists (ul). Everything works, except for positioning. The goal is to vertically center the drag and drop relative to the cursor (horizontal restriction is limited), so li with elements nested in it can be easily discarded. Here's the corresponding JS:

$(function() { $( ".organizerlink" ).draggable({ axis: "y", containment:"#organizer", scroll: false , helper: "original", revert: "invalid", cursorAt: { top: Math.round($(this).outerHeight() / 2)} }); 

and HTML:

 <ul id="organizer"> <li class="organizerTarget">&nbsp</li> <li class="organizerlink" id="dbid-1">Page <ul><li class="organizerTarget organizerNewParent">&nbsp;</li></ul> </li> <li class="organizerTarget">&nbsp</li> <li class="organizerlink" id="dbid-2">About <ul> <li class='organizerTarget'>&nbsp;</li> <li class='organizerlink' id="dbid-3">Another Page<ul><li class="organizerTarget organizerNewParent">&nbsp;</li></ul></li> <li class='organizerTarget'>&nbsp;</li> <li class='organizerlink' id="dbid-4">Example<ul><li class="organizerTarget organizerNewParent">&nbsp;</li></ul></li> </ul> </li> <li class="organizerTarget">&nbsp</li> <li class="organizerlink" id="dbid-27">Stuff <ul><li class="organizerTarget organizerNewParent">&nbsp;</li></ul> </li> 

Some things I've already tried:

  • setting the cursor At to $ (this) .height () - does not work, I assume that height () extends the css heights, but they are not explicitly defined, so it jumps to 0
  • setting it to outerHeight () gives me the error "elem.style is undefined" in firebug

I know that the externalHeight element exists in jquery and based on the doc API it seems that it can be calculated automatically even if CSS is undefined, so I think this is the right way and maybe $ (this) is just the wrong place for searching.

+6
source share
6 answers

Work on the original issue, see the comment on my original post.

EDIT:

Tolerance Pointer: The mouse pointer overlaps another element.

 $(".sortable").sortable({ containment: "parent", tolerance: "pointer" }); 
+6
source

I also wanted to focus my draggable objects after I pick them up. My decision:

 $(".dragme").draggable({ start: function(event, ui) { $(this).draggable("option", "cursorAt", { left: Math.floor(this.clientWidth / 2), top: Math.floor(this.clientHeight / 2) }); } }); 
+8
source

This works fine if draggable has a helper object. Just put it in the drag start method as shown below.

 start: function(event, ui) { $(this).draggable("option", "cursorAt", { left: Math.floor(ui.helper.width() / 2), top: Math.floor(ui.helper.height() / 2) }); } 
+5
source

I just spent a couple of hours smashing my head against the wall to try and do this work reliably, so I decided to post a solution :)

Question: Draggable cannot set cursorAt to drag "clone" during instance creation for dynamic values ​​(ie Center of draggable proxy of variable size) because ui.helper has not been created yet! You can install it inside the launch handler, but it will not work for the first drag and drop.

Solution: Position the cursor inside the beginning, but ALSO manually override ui.position for the drag event that happens continuously. Using firstRun boolean, you can not run it unnecessarily. You must set the default cursorAt in the upper left corner to move.

Enjoy it!

 $jobs.each( function( index, element ) { var $el = $(element), firstRun = true; /* * jQuery UI Draggable * See @link: http://api.jqueryui.com/draggable/ * * Note that for clone drags, the first drag cannot center the proxy because ui.helper hasn't been created yet * so need to set it manually for first drag. Subsequent drags can use the cursorAt property. * See my @link: */ $el.draggable({ cursorAt : [0, 0], // Set origin then update dynamically drag : function( evt, ui ) { // Fires after start event, and continuously during drag if ( firstRun ) { // Reset proxy position here since cursorAt cannot be set for ui.position.left -= Math.floor( ui.helper.width()/ 2 ); ui.position.top -= Math.floor( ui.helper.height()/ 2 ); }; }, helper : 'clone', start : function( evt, ui ) { // Fires once if ( firstRun ) { // Center proxy relative to cursor for future drags $(this).draggable( 'option', 'cursorAt', { left : Math.floor( ui.helper.width()/ 2 ), top : Math.floor( ui.helper.height()/ 2 ) }); }; // Set cursor ( 'cursor' option just applies style to <body> ) ui.helper.css( 'cursor', 'move' ); }, stop : function( evt, ui ) { // Fires once if ( firstRun ) { firstRun = false; }; } }); 
+5
source

In the case of multiple draggable objects, Goz's answer does not work for me, so here is my solution without using the cursorAt option

 var offsetX = null; var offsetY = null; $(".item").draggable({ helper:"clone", start:function(e,ui){ offsetX=null; offsetY=null; }, drag:function(e,ui){ if(offsetX===null){ offsetX = e.clientX-ui.offset.left; offsetY = e.clientY-ui.offset.top; } ui.position.left += offsetX - Math.floor( ui.helper.outerWidth()/ 2 ); ui.position.top += offsetY - Math.floor( ui.helper.outerHeight()/ 2 ); } }); 
 .desk{ width:300px; height:300px; border:2px dashed gray; } .item { padding:8px; margin:2px; border:1px solid blue; background: rgba(0,0,80,.3); display:inline-block; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script> <div class="desk"> <div class="item">Item 1</div> <div class="item" style="width:100px;">Item 2</div> <div class="item" style="height:50px;">Item 3</div> </div> 
+1
source

@yuri gor:

Your answer worked for me, but you could just start the offset from the beginning:

  var offsetX = null; var offsetY = null; $(".item").draggable({ helper:"clone", start:function(e,ui){ offsetX = e.clientX-ui.offset.left; offsetY = e.clientY-ui.offset.top; }, drag:function(e,ui){ ui.position.left += offsetX - Math.floor( ui.helper.outerWidth()/ 2 ); ui.position.top += offsetY - Math.floor( ui.helper.outerHeight()/ 2 ); } }); 
0
source

Source: https://habr.com/ru/post/886425/


All Articles