JSFiddle - React, Tailwind, and code Playground
by Josh Pullen
HTML
<ul class="script">
<li class="hat" style="background:#F24927"><!DOCTYPE html></li>
<ul class="c-wrapper">
<li class="c-header" style="background:#F0750A"><body></li>
<ul class="c-content" style="background:#F0750A">
<li class="stack" style="background:#DBB314"><img src="<span contenteditable='true' class="script-input" value="bring-back-breadfish.gif"></span>"></li>
<li class="stack" style="background:#6FB317"><img src="<span contenteditable='true' class="script-input" value="bring-back-breadfish.gif"></span>"></li>
<li class="stack" style="background:#1A9682"><img src="<span contenteditable='true' class="script-input" value="bring-back-breadfish.gif"></span>"></li>
<li class="stack" style="background:#1C4ED9"><img src="<span contenteditable='true' class="script-input" value="bring-back-breadfish.gif"></span>"></li>
<li class="stack" style="background:#6137BD"><img src="<span contenteditable='true' class="script-input" value="bring-back-breadfish.gif"></span>"></li>
<li class="stack" style="background:#C844CF"><img src="<span contenteditable='true' class="script-input" value="bring-back-breadfish.gif"></span>"></li>
<li class="stack" style="background:#B5316C"><img src="<span contenteditable='true' class="script-input" value="bring-back-breadfish.gif"></span>"></li>
</ul>
<li class="c-footer" style="background:#F0750A"></body></li>
</ul>
</ul>
CSS
@import url(http://fonts.googleapis.com/css?family=Source+Code+Pro:400,700);
body {
background-color: gray;
}
* {
font-family:'Source Code Pro';
color:white;
white-space: nowrap;
/* Don't let text to "wrap" to a new line (blocks would look ugly that way) */
-webkit-user-select: none; /* Chrome all / Safari all */
-moz-user-select: none; /* Firefox all */
-ms-user-select: none; /* IE 10+ */
user-select: none; /* Likely future */
cursor: default;
}
.script-input {
font-family:'Source Code Pro';
padding:0 5px;
min-width: 25px;
border-radius:999px;
border:none;
outline:none;
background-color:white;
color: black;
display: inline-block;
text-align: center;
}
.hat {
display:table;
/* Using "block" would result in 100% width, and "inline-block" would result in everything on same line */
background:#C6E44D;
padding:10px;
position:relative;
border-radius:0px 5px 5px 5px;
}
.hat:after {
background:inherit;
display:block;
content:' ';
width:80%;
height:80%;
position:absolute;
top:-35%;
left:0px;
border-radius:50%;
z-index:-999;
}
.stack {
display:table;
background:#914DE4;
padding:10px;
position:relative;
border-radius:5px;
border-left: 1px solid #A9A9A9;
}
.c-wrapper {
padding:0px;
display:table;
border-left: 1px solid #A9A9A9;
}
.c-header, .c-footer {
display:table;
background:#E44D4D;
padding:10px;
position:relative;
border-radius:5px;
min-width:40px;
min-height:20px;
}
.c-content {
background:#E44D4D;
padding:3px 0px 3px 25px;
margin:-3px 0px -3px 0px;
width:4px;
overflow-x: visible;
min-height: 40px;
}
.c-content:empty:after {
width:0px;
height:40px;
content:' ';
display:block;
}
.c-header {
border-top: 1px solid #A9A9A9;
}
.c-footer {
border-bottom: 1px solid #A9A9A9;
}
.drop-area {
...
JavaScript
/* PLEASE SEE
https://github.com/ElementalCode/Elemental/tree/draggy-snappy
* FOR LATEST */
var selected = null, // Object of the element to be moved
x_pos = 0, y_pos = 0, // Stores x & y coordinates of the mouse pointer
x_elem = 0, y_elem = 0; // Stores top, left values (edge) of the element
var SNAP_CLASSES = '.stack, .c-header, .c-footer, .hat';
function isDescendant(parent, child) {
var node = child.parentNode;
while (node != null) {
if (node == parent) {
return true;
}
node = node.parentNode;
}
return false;
}
function closestElem(elem, offset, initial) { //elem is nodelist, offset is own offset
var el = null,
elOffset,
x = offset.x, //x is my own offset
y = offset.y, //y is my own offset
distance,
dx, dy,
minDistance;
elem.each( function(item) {
if(item == selected) {return false;} // I added this -NN
elOffset = getOffset(item); //returns object with offsets
//we'll worry about inside c-blocks later:
/*if (
(x >= elOffset.left) && (x <= elOffset.right) &&
(y >= elOffset.top) && (y <= elOffset.bottom)
) {
el = item;
return false;
}*/
//let's only test the bottom-left corner
dx = elOffset.left - x;
dy = elOffset.bottom - y;
distance = Math.sqrt((dx*dx) + (dy*dy)); //dist to each corner
if (initial != item && !isDescendant(initial, item) && (minDistance === undefined || distance < minDistance)) {
minDistance = distance;
el = item;
}
});
return el;
}
function getOffset( elem ) {
var offsetLeft = (function(elem) {
var offsetLeft = 0;
do {
if ( !isNaN( elem.offsetLeft ) )
{
offsetLeft += elem.offsetLeft;
}
} while( elem = elem.offsetParent );
return offsetLeft;
})(elem);
...