Reputation: 3707
My intent is to have a series of folders and sub items (like a directory tree) and drag and drop the items to rearrange. When I simply click on a folder (a list item with a child ul) it should either slide open or slide close.
The problem is : I want to prevent the click event when I cancel a drag.
By cancel - I mean I start to drag the element, and then release the mouse without dropping it on top of any droppables.
My first guess was using event.stopImmediatePropagation()
and event.stopPropagation()
. This indeed prevents the click event when I cancel drags on list items that have no ul children.
However, when I cancel drag on li's that have ul children, the default click behavior occurs (which in this case is slideToggle).
How do I prevent the click event when I cancel drag of an li with ul children?
$("li").click(function (event) {
console.log($(this).attr("class"));
if ($(this).children("ul").length > 0) $(this).children("ul").slideToggle();
event.stopPropagation();
event.stopImmediatePropagation();
event.preventDefault();
})
$("li").draggable({
rever: false,
helper: "clone",
cursorAt: {
top: -1,
left: -1
},
stop: function (event) {
event.stopPropagation();
event.stopImmediatePropagation();
}
});
$("span").droppable({
hoverClass: "ui-state-active",
greedy: true,
tolerance: "pointer",
drop: function (event, ui) {
var dragged = ui.draggable
var target = $(this).parent()
if (target.children("ul").length == 1) {
dragged.appendTo(target.children("ul"));
} else {
// depends upon whether I'm dragging from above or from below
if (dragged.prev().is(target)) // dragging from below
dragged.insertBefore(target)
else dragged.insertAfter(target)
}
event.stopPropagation();
},
});
Full code in JSFiddle
Upvotes: 1
Views: 1163
Reputation: 43156
One way to get around is to use separate elements to trigger both the actions.
For example, we use the handle
option.
If specified, restricts dragging from starting unless the mousedown occurs on the specified element(s). Only elements that descend from the draggable element are permitted
To trigger the dragging, and a separate <span>
element to trigger the toggle functionality.
Updated Fiddle (Click the text for dragging and +
/-
for toggling)
Another hackish work around is to keep track of a boolean flag -
We can set a boolean
to true
when dragging starts, and set it back to false
after a tiny timeout inside the stop callback.
The click event will be triggered immediately when we release the mouse - So if the click is triggered by a drag, the boolean flag will still be true
since we'll only reset it after a short timeout. If it is a normal click - the flag will be false.
var dragging = false;
$("li").click(function (event) {
event.stopPropagation();
$this = $(this);
console.log(dragging);
if (!dragging) {
if ($this.children("ul").length > 0) $this.children("ul").slideToggle();
}
});
$("li").draggable({
revert: false,
helper: "clone",
cursorAt: {
top: -1,
left: -1
},
start: function (event) {
dragging = true;
},
stop: function (event) {
setTimeout(function () {
dragging = false;
}, 10);
}
});
$("span").droppable({
hoverClass: "ui-state-active",
greedy: true,
tolerance: "pointer",
drop: function (event, ui) {
var dragged = ui.draggable
var target = $(this).parent()
if (target.children("ul").length == 1) {
dragged.appendTo(target.children("ul"));
} else {
// depends upon whether I'm dragging from above or from below
if (dragged.prev().is(target)) // dragging from below
dragged.insertBefore(target)
else dragged.insertAfter(target)
}
event.stopPropagation();
},
});
.ui-state-active {
background-color : red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://code.jquery.com/ui/1.10.3/jquery-ui.js"></script>
<ul>
<li><span>Test 1</span>
</li>
<li> <span>Test 2</span>
<ul>
<li class="A"><span>Test A</span>
</li>
<li class="B"><span>Test B</span>
</li>
<li class="C"><span>Test C</span>
</li>
</ul>
</li>
<li><span>Test 3</span>
</li>
<li> <span>Test 4</span>
<ul>
<li><span>Test X</span>
</li>
<li><span>Test Y</span>
<ul>
<li><span>F</span>
</li>
<li><span>G</span>
</li>
<li><span>H</span>
</li>
</ul>
</li>
<li><span>Test Z</span>
</li>
</ul>
</li>
</ul>
Upvotes: 1