Reputation: 1733
Perhaps it's by design, but I want the handle to be draggable
rightaway, not after the first mouseup as it currently happens.
<html>
<head>
<link href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.1/themes/base/minified/jquery-ui.min.css" rel="stylesheet" />
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.1/jquery-ui.min.js"></script>
<script>
$(function () {
var handle = $("#handle");
handle.on("mousedown", function () {
// doesn't work
handle.draggable();
});
// works
handle.draggable();
});
</script>
</head>
<body>
<div style="width: 400px; height: 400px; border: 2px solid gray; position: relative;">
<div id="handle" style="width: 50px; height: 50px; position: absolute; top: 100px; left: 100px; background-color: gray;"></div>
</div>
</body>
</html>
Upvotes: 2
Views: 1677
Reputation: 149
You can fire your own mousedown event within the native event. This will continue the mousedown for jQuery draggable. This solution is conceptually similar to the one by Roberto Barra, but firing events has changed since that answer was posted.
const draggableEl = $('#dragEl');
draggableEl.draggable({
helper: 'clone',
revert: 'invalid',
opacity: 0.5,
disabled: true, //init with drag disabled for demo
});
console.log($('#dragEl').draggable('option'));
let initialized = false;
$(document).on('mousedown.myDragScope', function(e) {
if ($(e.target).is($('#dragEl'))) {
if (initialized) {
//do any draggable stuff
$(e.target).css('outline', '2px solid black'); //demo
$(e.target).css('background', 'darkseagreen'); //demo
} else {
//initialize draggable
e.preventDefault(); //pause mousedown event (to allow setting jQuery draggable options)
//change jQuery draggable settings:
$(e.target).draggable('option', 'disabled', false); //enable draggable after click on el for demo
$(e.target).draggable('option', 'axis', 'x'); //demo
// $(e.target).draggable('option', '...', '...');
console.log($('#dragEl').draggable('option'));
initialized = true;
const mousedownEvent = new MouseEvent('mousedown', {
view: window,
cancelable: true,
bubbles: true
});
e.target.dispatchEvent(mousedownEvent); //resume mousedown event to continue drag
}
}
});
#dragEl {
width: fit-content;
outline: 2px dotted black;
background: thistle;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.13.2/jquery-ui.min.js"></script>
<h2>dynamic setting of options on mousedown draggable element</h2>
<div id="dragEl">drag this el</div>
<p>this element has draggable disabled by default</p>
<p>mousedown on the element sets draggable enabled, sets some other draggable options, and then passes another mousedown event to the event for jQuery draggable to grab</p>
<p>mouseup is not handled by this demo, so the draggable remains enabled</p>
Upvotes: 0
Reputation: 25
I have the same need: to setup an element as draggable inside an event listener attached to the event mousedown of this same element. Andthe dragging must start with this mousedown event, I can't ask the user to click twice to be able to drag something!
Why do I need that?
Because when the user drags a box around, this box will drag together some ohter boxes, and I only have infromation of which boxes to drag together when the user clicks on one box.
This is how I did it:
Below is a snippet of my code that do what I describe (and it is working, at least on Chrome...):
$.fn.adjustDragging = function (opts)
{
// bDragNeed2BeAdjusted: if true, indicates that the box isn't draggable yet
this[0].bDragNeed2BeAdjusted = true;
this.mousedown(function(e)
{
if (this.bDragNeed2BeAdjusted)
{
this.bDragNeed2BeAdjusted = false;
// Make box and her sisters draggable
$(this).doAdjustDragging(opts);
e.preventDefault();
// Send a new mousedown event
if (document.createEvent)
{
var evtNew = document.createEvent('MouseEvents');
evtNew.initMouseEvent(
'mousedown',
e.bubbles, e.cancelable, e.view, e.button,
e.screenX, e.screenY, e.clientX, e.clientY,
e.ctrlKey, e.altKey, e.shiftKey, e.metaKey, e.button, this
);
this.dispatchEvent(evtNew);
}
else
{
options.clientX = options.pointerX;
options.clientY = options.pointerY;
var evtNew = document.createEventObject();
evtNew = extend(evt, {clientX: e.pointerX, clientY: e.pointerY});
this.fireEvent('onmousedown', evtNew);
}
return false;
}
});
};
Upvotes: 0
Reputation: 11470
I'm not really sure what you're trying to accomplish but your example demonstrates the correct behaviour.
If you init the .draggable()
in the mousedown
event it just means that the handle
div gets initialized to be draggable when you first click on the div. After that it gets initalized again and again.
So on page load your div
doesn't know it has to be draggable. If you then click on it your mousedown
event triggers and sets the div
to be draggable.
If you want it to be draggable rightaway just use your second - working - example. It's perfectly fine or am I missing something? See this jsfiddle
The Default Functionality example in the jQuery UI documentation shows exactly this.
$(function() {
//element with ID "draggable" is draggable after the DOM has loaded
$( "#draggable" ).draggable();
});
There's simply no need to wrap the .draggable()
in a mousedown event.
Upvotes: 1