Is it possible to delay the jQuery UI drag and drop plugins from being initialized until a movement or click is made? Not sure if this is possible. I have a ton of cells using the drag and drop, like an Excel grid, and performance isnt great.
I went this route and it seems to work.
$.fn.liveDraggable = function (opts) {
this.one("mouseover", function () {
if (!$(this).data("init")) {
$(this).data("init", true).draggable(opts);
}
});
return this;
};
You could use either delay or distance.
$( ".selector" ).draggable({ delay: 300 });
$( ".selector" ).draggable({ distance: 10 });
From the API documentation:
Delay
Time in milliseconds after mousedown until dragging should start. This
option can be used to prevent unwanted drags when clicking on an
element.
Distance
Distance in pixels after mousedown the mouse must move before dragging should start. This option can be used to prevent
unwanted drags when clicking on an element.
Update:
To keep a more standard functionality and only initialize draggable when needed, try using a hover function like so:
Working Example
$('div').hover(function () {
$(this).addClass('selector');
$(".selector").draggable({
//options
});
},
function () {
$('div').removeClass('selector');
});
Related
I want to use jQuery UI Draggable Module and Position Widget simultaneously to create Responsive content.
However, I could not find any usage examples. I've created a simple demo => jsfiddle.net/1ecg2jnc
The problem is; How do I update the offset of the elements when I drag.
<div class="element"
data-x="right"
data-y="top"
data-offset-x="-25"
data-offset-y="+45" >Draggable Element</div>
You can attach a listener to the drag event which updates your offsets. Something like this:
$(this).draggable({
containment: "#zone",
cursor: 'move',
drag: function(event, ui) {
$(event.target).data('offset-x', "+" + ui.offset.left);
$(event.target).data('offset-y', "+" + ui.offset.top);
}
});
$('#ac').autocomplete({
source: '/url',
appendTo: $('#ac').closest('.popupWindow'),
select: function (event, ui) {
// do stuff
}
});
in IE9 first time everything works fine, but when i type text is second time, elements don`t reacts on clicks
error appears only when using appendTo option
solve it: on one of parent elements was click event handler with e.stopPropagation()
I create a new jQuery element after the mouse is in a down position and before it is released. (After mousedown).
I would like to programmatically trigger dragging on the new element using jQuery UI, so that it will automatically begin dragging with my mouse movement. I don't want to have to release and then click the mouse again.
I have tried the following...
var element = $("<div />");
element.appendTo("body").draggable().trigger("mousedown");
...however this does not work.
Does anyone have any suggestions on how to accomplish this?
UPDATE: After some searching the poster of this question has the identical problem. However the suggested solution, which boils down to...
$("body").on("mousedown", function(e) {
$("<div />").draggable().appendTo("body").trigger(e);
});
...no longer works in the latest versions jQuery and jQuery-UI, and instead generates a Maximum Call Stack Exceeded error.
The draggable plugin expects its mousedown events to use its namespace and to point to the draggable object as the target. Modifying these fields in the event works with jQuery 1.8.3 and jQuery UI 1.9.2.
$("body").on("mousedown", function(e) {
var div = $("<div />").draggable().appendTo("body");
e.type = "mousedown.draggable";
e.target = div[0];
div.trigger(e);
});
Demo here: http://jsfiddle.net/maCmB/1/
UPDATE:
See fuzzyBSc's answer below. It's the proper way to do this.
This is totally a hack, but it seems to do the trick:
var myDraggable = $('#mydraggable').draggable();
// Yeah... we're going to hack the widget
var widget = myDraggable.data('ui-draggable');
var clickEvent = null;
myDraggable.click(function(event){
if(!clickEvent){
widget._mouseStart(event);
clickEvent = event;
}
else {
widget._mouseUp(event);
clickEvent = null;
}
});
$(document).mousemove(function(event){
console.log(event);
if(clickEvent){
// We need to set this to our own clickEvent, otherwise
// it won't position correctly.
widget._mouseDownEvent = clickEvent;
widget._mouseMove(event);
}
});
Here's the plunker
My example uses an element that already exists instead of creating one, but it should work similarly.
Create your draggable function on mouseover
$('#futureDragableElement').mouseover(function() {
$(this).draggable();
});
As the draggable initialization has already be done, your first mouse click will be taken into account
You have to bind the mousedown event to the element in question, then you can trigger the event.
From http://api.jquery.com/trigger/
Any event handlers attached with .bind() or one of its shortcut
methods are triggered when the corresponding event occurs. They can be
fired manually, however, with the .trigger() method. A call to
.trigger() executes the handlers in the same order they would be if
the event were triggered naturally by the user:
$('#foo').bind('click', function() {
alert($(this).text());
});
$('#foo').trigger('click');
Hacks are not needed if you are creating the element during the event and that element is not too complicated. You can simply set draggable to the element that mousedown occurs and use draggable helper property to create a helper that is going to be your new element. On dragStop clone the helper to the location in dom you want.
$('body').draggable({
helper: function() {
return '<div>your newly created element being dragged</div>';
},
stop: function (e,ui) {
ui.helper.clone().appendTo('body');
}
});
Of course you would need to set position for the helper, so mouse is on it. This is just a very basic example.
On a web page, I want to display a small div with text in it that is cut off and displayed with ellipses and when there is a mouse-over it should expand to a larger size such that all the text is visible. I then want to be able to use jqueryui drag and drop to move the text box onto a grid. When it is being dragged and placed, I want it to be the small size again.
I have attempted to do this like so:
Mouseover function:
$(function() {
$( ".ui-widget-content" ).mouseover(function(){
$(this).css("width", "200px");
$(this).css("height", "200px");
}).mouseout(function(){
$(this).css("width", "100px");
$(this).css("height", "40px");
})
})
Draggable function:
$(function() {
$( ".ui-widget-content" ).draggable({ snap: "td.chart:not(:first-child)", snapMode: "inner", revert: "invalid", snapTolerance: 40, stack: ".ui-widget-content",
drag: function( event, ui ) {
$(this).css("width", "100px");
$(this).css("height", "40px");
}
});
});
Droppable function:
$(function() {
$( "td.chart:not(:first-child)" ).droppable({
accept: ".ui-widget-content",
drop: function( event, ui ) {
$("#" + ui.draggable.attr("id") ).css("background-color","#D7F970");
}
});
});
Div that is getting dragged and dropped:
Lorem Ipsum
I thought that by using the above, when someone went to drag the div, first the mouse over would be triggered, enlargening the div, then the dragstart would shrink it and it would be fine. However, I am placing it on a table (see selector "td.chart:not(:first-child)" in droppable function), and while it works for the first three rows of the table, the div no longer snaps and gets dropped on the fourth and fifth rows. This problem does not occur if I remove the mouse-over function. Anyone understand what is going on here?
It would maybe help to take a look at your html.
It's just a hunch but maybe it's only a matter of the size of your draggable being too big and being over more than one droppable item.
I would advise trying to change the tolerance of your droppable element to see if it helps :
$( ".selector" ).droppable({ tolerance: "pointer" });
jQuery Documentation states :
Tolerance specifies which mode to use for testing whether a draggable is 'over' a droppable. Possible values:
fit: draggable overlaps the droppable entirely
intersect: draggable overlaps the droppable at least 50%
pointer: mouse pointer overlaps the droppable
touch: draggable overlaps the droppable any amount
I have the following bit of jquery:
http://jsfiddle.net/tad604/Ck2qk/10/
I want the foo div's click handler to not fire, when you click and drag. I've tried doing all sorts of things inside the stop/start events of the drag (event.stopPropagation() etc) all to no avail. The click handler is fired after the drag event regardless.
It's annoying, but the only fix is to remove the event on drag start and put it back on drag stop. Try this:
$(".foo").click(function(){
alert("blah");
});
$(".bar").draggable({
stop: function(event) { setTimeout(function() {
$(".foo").click(function(){
alert("blah");
}); }, 100)},
start: function(event) { $('.foo').unbind('click'); }
});
Now there is still the problem that your click events are probably a bit more complicated than this, and you probably don't want to have to rewrite them. You can save the events for later using jquery data like this:
var events = $('#test').data("events");
Alternatively, you can use jquery live function to attach the click event so the event will only ever be binded to an element that matches that selector. That means if you change the class while dragging, so that it no longer matches that selector, it would no longer have that click event. Something like this might work:
$(".bar .foo").live('click', function(){
alert("blah");
});
$(".bar").draggable({
stop: function(event) { setTimeout(function() {
$(".draggableBar").removeClass('draggableBar').addClass('bar');
}, 100)},
start: function(event) { $(this).removeClass('bar').addClass('draggableBar'); }
});
You'd also have to update the css so draggablebar gets the same style as bar.