jQuery UI draggable has jerky transition on drop - javascript

I have a simple drag and drop functionality that I'm attempting to get working. I have cards that are draggable and can be dropped on top of other cards to swap positions with the other card. Here's a fiddle with the functionality in place: https://jsfiddle.net/vj0a9gp8/1/
The drag and drop code is pretty simple:
$(function() {
$(".card"). draggable({
revert: true
}). droppable({
hoverClass: "card-hover",
drop: function(event, ui) {
swapNodes($(this).get(0), $(ui.draggable).get(0));
}
});
});
function swapNodes(a, b) {
var aparent = a.parentNode;
var asibling = a.nextSibling === b ? a : a.nextSibling;
b.parentNode.insertBefore(a, b);
aparent.insertBefore(b, asibling);
}
Basically when a card is dragged and then dropped onto another, the swapNodes function traverses up the dom and places them where they belong. This all works great. The issue, which you can see in the fiddle, is that when the drop occurs the dropped card kind of jerks off screen before animating in to place and it looks poorly overall. I've tried playing around with draggable.position to address and fix this functionality but all I've managed to do is make it worse. Any ideas?

When you drag your element, it changes the left and top position. When you drop it, you change its position in the DOM, but you never specify a new top and left, so it still keeps the one set when dragging it. The animation is there because you have a revert to true, which puts back the original position and animates it.
Easy solution would be to set revert to 'invalid' (so only if there's no drop) and set the left and top in your swap function. Like this
revert: 'invalid'
...
b.style.left = '';
b.style.top = '';
https://jsfiddle.net/huw2Lkgb/1/

Related

Let draggable do its work only if mouse cursor on a draggable element is default cursor

I have used jQueryUI's draggable method on a div.
var data = '<div> <p> Draggable Div </p> </div>'
$(data).appendTo($(this)).draggable();
It works fine.
My application heavily depends on mouse cursor type.
So, I change cursor every now and then programatically.
Now, I want that:
Draggable class should only be doing its work if the mouse cursor of a draggable element is default cursor.
How can I change this behavior without making changes in jQueryUI.js file if possible.
You can make use of the start event.
$("#data").draggable({
start: function(event, ui) {
if ($(this).css('cursor') === 'auto') { //replace "auto"
event.preventDefault();
}
}
});
I have created a working fiddle here.
I hope this helps.

jQuery ui draggable element gets under other draggable elements

I have a style problem with jQuery Ui draggable elements.
here what i have
FIDDLE
As u can see, i have two droppable areas , in each area elements are draggable, and can drag and drop element from one block to another
The only problem here , that when i am dragging element from top block to below block, the dragging element gets under droppable are elements, but when i am dragging from bottom are to top there is no such problem.
Here is the code for dragging
$(".slide").draggable({
// brings the item back to its place when dragging is over
revert:true,
// once the dragging starts, we decrease the opactiy of other items
// Appending a class as we do that with CSS
start: function(event, ui) { $(this).css("z-index", a++); },
drag:function () {
$(this).removeClass('droped');
},
// adding the CSS classes once dragging is over.
stop:function () {
$(this).addClass('droped');
},
zIndex: 10000,
snapMode: "inner"
});
Can anybody help me please, i am working on it already 2 days, and can't figure out what is the problem, i have tried to change z-index positions of every block, but no result;
I found out that my code only worked the first time - i removed some z-indexes from your JQuery ánd your css, now it is working for me every time:
http://jsfiddle.net/zbo7g5nz/5/
My jFiddle doesnt seem to get updated to share.. Here is working code:
$(".slide").draggable({
// brings the item back to its place when dragging is over
revert:true,
// once the dragging starts, we decrease the opactiy of other items
// Appending a class as we do that with CSS
start: function(event, ui) { $(this).css("z-index", a++); },
drag:function () {
$(this).parent().css('z-index', '10001');
$(this).removeClass('droped');
},
// removing the CSS classes once dragging is over.
stop:function () {
$(this).parent().css('z-index', '10001');
$(this).addClass('droped');
},
zIndex: 10000,
snapMode: "inner"
});
I gave a z-index to the ul holding the li that was higher than the li of the list that was below.
Avoid tricks and go with divs instead of UL or LI for further compatibility.
Also, you don't need to listen to the start event to setup the z-index property. The .draggable() api exposes the zIndex prop for that reason.
Here is the demo working:
http://jsfiddle.net/zbo7g5nz/8/

Can I display:none part of a jQuery UI draggable and still keep the cursor in place somehow?

I have a number of draggables with images in them that I want to drop into folders. To conserve space (and make more draggables visible on the screen at one time), I'm hiding the images with CSS during the drag. How can I keep the mouse on the draggable when the images disappear?
Here's an example of what I'm seeing, just using a simple draggable box:
$( "#draggable" ).draggable({
revert: "invalid",
cursor: "move",
scroll: false,
cursorAt: { top: 5, left: 5 },
start: function(event, ui) {
$('img').addClass('hidden');
},
stop: function(event, ui) {
$('img').removeClass('hidden');
}
});
http://jsfiddle.net/fBPdF/
The hidden class uses display:none; to hide the images. As you can see in the fiddle, dragging the first image works fine, and the mouse tracks along in the upper left-hand corner of the box while you drag. When you drag the second, the mouse floats off to the side because the cursorAt value has already been set when the images get removed.
I'd prefer not to use a helper clone (because that makes the move look more like a copy), but that's the only way I've found so far to make it work. I tried resetting the cursorAt inside a timeout in the start function, but it didn't seem to have an effect.
Is there a way to keep the cursor and the draggable together somehow?
Try to change opacity. The hidden attr get off the element from "index".
.hidden {
opacity: 0;
}
http://jsfiddle.net/eEgTL/

Odd Draggable Behavior After Implementing Auto Scroll

I've implemented drag and drop using the jQuery UI draggable widget.
I'm now implementing auto scroll during drag operations. I set it up so that when you start to drag, gray overlays appear at the top and bottom of the browser window. When you drag into one of these overlays, the browser window starts to auto scroll.
You can see my test page at http://www.softcircuits.com/Client/scrolltest.html. Drag an item by dragging one of the crosshair icons on the left side.
But there's a problem: if you scroll to the bottom of the page, and then drag an item to the top overlay, it will scroll up as expected. However, for me, I get about half way up the page and the draggable helper won't go any higher. There's no way for me to drag all the way to the top of the page.
This most likely seems related to the Draggable widget. Is anyone able to see why this is happening? I'm using Google Chrome on Windows 7.
To be cross-browser compatible and to avoid wird behavior, I would recommend to use all JQueryUI draggable callbacks.
I read some days ago that the last version of Chrome has some really tricky problems with natives HTML5 draggable events.
For example, I have just checked your web page source code and you are using $('.drag-handle').on('drag', function(){...}); => You should use the drag callback.
I would also recommend to not use window as the scrollable container in your case. You should create a div to wrap all the tables contents and use it as a scroll container. I have already done this implementation in the past and it is working.
Don't forget to set the wrapper ID in the containment option durring the draggable widget creation.
If it always not working, you could also try to overwrite the helper position in the drag callback :
//Save the mouse position in global variables
$(document).mousemove(function(e){
window.mouseXPos = e.pageX;
window.mouseYPos = e.pageY;
});
$('[id^="drag-"]').each(function() {
$(this).draggable({
opacity: 0.7,
cursorAt: { top: 15, left: 50 },
scroll: true,
stop: function(){},
drag : function(e,ui){
//Force the helper position
ui.position.left = window.mouseXPos - $(this).draggable('option','cursorAt').left;
ui.position.top = window.mouseYPos- $(this).draggable('option','cursorAt').top;
});
});
Changing the draggable containment option from window to document worked for me.
$('.drag-handle').draggable({
...
containment: "document",
...
});
See: http://docs.jquery.com/UI/Draggable#option-containment

jQuery Draggable: Image Flicker

I've been developing an Image panning tool, and after a kind member directed me to the draggable plugin for jQuery, I have most of it completed. Right now if the user drags the image (contained inside a div of about 300px by 300px), the image will first flicker, then pan. This problems seems to occur after a mouse down event, on the mouse move event. The image will shift into one of the four corners on mouse move, and moving to certain areas will cause another shift. I haven't been able to find anything through google, and I'm relatively new to jQuery still.
I've uploaded the code here, in case my description is too vague:
http://www.studentgroups.ucla.edu/csa/test/zoom.htm
Any ideas or advice is greatly appreciated!
For one, you've made the image draggable both via the jQuery plugin, and your own code. Your code is changing the background-position of the div, and the jQuery plugin is changing the div's actual position. That's bound to cause some problems.
Also, Draggable's containment parameter seems to be designed for draggable items who are smaller than their parent container, not ones who are bigger, like you're trying to do.
Anyways, here's the working code:
$(document).ready(function() {
$(".draggable").draggable().bind('dragstop', function(e, ui) {
if (ui.position.top > 0) {
$(this).css('top', 0);
}
if (ui.position.left > 0) {
$(this).css('left', 0);
}
var bottom = -($(this).height() - $(this).parent().height()),
right = -($(this).width() - $(this).parent().width());
if (ui.position.top < bottom) {
$(this).css('top', bottom);
}
if (ui.position.left < right) {
$(this).css('left', right);
}
});
});
If you don't need edge-snapping, you can get rid of the .bind() function, and just call .draggable().
$(document).ready(function() {
$(".draggable").draggable();
});

Categories