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 divs need to be expressed in percent (to be responsive), and the toplevel divs 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 .hexagons 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