I want to drag a draggable #red
, nested within some parent, to some droppable #green
, which sits a level higher in the div structure.
The dimensions of the div
s need to be expressed in percent
(to be responsive), and the toplevel div
s must be position: relative;
, which might make things more complicated.
For comparison, this all works fine for a the simpler case, where draggable #blue
and droppable #green
are sibling elements, but breaks in the "nephew" scenario (#red
on #green
).
I understand that I need to:
helper: clone
the nephew (#red
) div, as well as to appendTo: "body",
so that I the nephew element can "escape"position: relative;
) to .ui-draggable-dragging
, so that the nephew element's dimensions are calculated with reference to the parent, while in transit.So far so good.
One wrinkle remains: When the nephew is dragged, it jumps sideways, and can't ever be dropped.
What's going on here?
$(function() {
$("#blue").draggable({
snap: ".hexagon",
snapMode: "inner",
snapTolerance: 20,
opacity: 0.7,
addClasses: true,
// stack: ".item",
revert: "invalid"
});
$("#red").draggable({
snap: ".hexagon",
snapMode: "inner",
snapTolerance: 20,
opacity: 0.7,
addClasses: true,
// stack: ".item",
revert: "invalid",
appendTo: "body",
helper: "clone",
});
$("#green").droppable({
accept: ".hexagon",
tolerance: "fit",
drop: function(event, ui) {
$(this)
.addClass("ui-state-highlight")
.find("span")
.html("Dropped!");
}
});
});
.hexagon {
width: 20%;
padding-top: 25%;
overflow: hidden;
-webkit-clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
-webkit-shape-outside: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
float: left;
position: relative;
z-index: 1;
}
.outer {
position: relative;
z-index: 0;
}
.inner {
background-color: red;
z-index: 9999;
position: absolute;
margin: 0 auto;
width: 100%;
top: 0;
bottom: 0;
}
.textstyle {
color: white;
font-family: sans-serif;
top: 25%;
left: 10%;
right: 10%;
bottom: 10%;
text-align: center;
position: absolute;
font-size: 1vw;
}
.green {
background-color: green;
z-index: 1000;
}
.blue {
background-color: blue;
}
.red {
background-color: red;
}
.ui-draggable-dragging {
position: relative;
padding-top: 25%;
width: 20%;
}
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<div id="green" class="hexagon outer green">
<span class="textstyle">
I am the dropzone.
</span>
</div>
<div id="blue" class="hexagon outer blue">
<span class="textstyle">
I drag just fine, because I'm just a sibling element.
</span>
</div>
<div class="hexagon outer">
<div id="red" class="hexagon inner red">
<span class="textstyle">
I am nested, and I make a mess when dragged.
I am the nephew.
</span>
</div>
</div>
It appears that the jQuery draggable plugin is adding a left
value to the clone on the proviso that it is being positioned absolutely, by forcing .ui-draggable-dragging
to position: relative;
the plugin is actually positioning the clone left relative to where the element was positioned initially on the page.
To fix this behaviour add an override to the clone to position it absolutely:
.red.ui-draggable-dragging {
position: absolute;
bottom: auto;
}
Additionally, add bottom: auto;
to override the bottom
value set by .inner
as this will cause the clone to stretch.
This is because of tolerance: "fit"
which according to the documentation:
"fit"
: Draggable overlaps the droppable entirely.
Droppable Widget - (https://api.jqueryui.com/droppable/#option-tolerance)
This still causes problems now that the clone is positioned absolutely as it's width
is not calculated to be the same as the original .hexagon
(the original's width: 20%;
is calculated against the body
width while the clone's width: 20%;
is calculated against the viewport). To mitigate this the default browser margin
on the body
has been suppressed (although this could also be solved by wrapping the .hexagon
s in a container).
If the dragging action does not need to be exact tolerance: "fit"
can be changed to tolerance: "intersect"
which will allow for a bit more leeway.
$(function() {
$("#blue").draggable({
snap: ".hexagon",
snapMode: "inner",
snapTolerance: 20,
opacity: 0.7,
addClasses: true,
// stack: ".item",
revert: "invalid"
});
$("#red").draggable({
snap: ".hexagon",
snapMode: "inner",
snapTolerance: 20,
opacity: 0.7,
addClasses: true,
// stack: ".item",
revert: "invalid",
appendTo: "body",
helper: "clone"
});
$("#green").droppable({
accept: ".hexagon",
tolerance: "fit",
drop: function(event, ui) {
$(this)
.addClass("ui-state-highlight")
.find("span")
.html("Dropped!");
}
});
});
body {
margin: 0;
}
.hexagon {
width: 20%;
padding-top: 25%;
overflow: hidden;
-webkit-clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
-webkit-shape-outside: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
float: left;
position: relative;
z-index: 1;
}
.outer {
position: relative;
z-index: 0;
}
.inner {
background-color: red;
z-index: 9999;
position: absolute;
margin: 0 auto;
width: 100%;
top: 0;
bottom: 0;
}
.textstyle {
color: white;
font-family: sans-serif;
top: 25%;
left: 10%;
right: 10%;
bottom: 10%;
text-align: center;
position: absolute;
font-size: 1vw;
}
.green {
background-color: green;
z-index: 1000;
}
.blue {
background-color: blue;
}
.red {
background-color: red;
}
.ui-draggable-dragging {
position: relative;
padding-top: 25%;
width: 20%;
}
.red.ui-draggable-dragging {
position: absolute;
bottom: auto;
}
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<div id="green" class="hexagon outer green">
<span class="textstyle">
I am the dropzone.
</span>
</div>
<div id="blue" class="hexagon outer blue">
<span class="textstyle">
I drag just fine, because I'm just a sibling element.
</span>
</div>
<div class="hexagon outer">
<div id="red" class="hexagon inner red">
<span class="textstyle">
I am nested, and I make a mess when dragged.
I am the nephew.
</span>
</div>
</div>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With