JSFiddle - React, Tailwind, and code Playground
by bgrins
HTML
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.min.js"></script>
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/themes/ui-lightness/jquery-ui.css">
<div id='app'>
<div id='faux' class='faux'>
<div data-width='100' class='slice v'><b></b></div>
<div data-flex='1' class='slice v'><b></b></div>
<div data-height='100' class='slice h'><b></b></div>
<div data-flex='1' class='slice h'><b></b></div>
<div class='rail v'><span>Click to add a column</span><em>Drag to remove</em></div>
<div class='rail h'><span>Click to add a row</span><em>Drag to remove</em></div>
</div>
<div id='actual'>
</div>
</div>
CSS
#app { position:relative; }
#faux, #actual { width: 400px; height: 400px; position:absolute; top: 50px; left:50px; border: 2px solid; padding:0; margin:0; }
#faux{ background: rgba(0, 0, 0, .4); z-index:2; }
#actual{ background: red; z-index:1; }
.rail { position:absolute;
background-color: rgba(0, 0, 0, .1); color:white;
-webkit-transition: background-color .1s linear;
color:transparent; padding:3px; text-align:center;
}
.faux .rail:hover { background-color: rgba(0, 0, 0, .8); color:white; }
body.dragging .rail { background-color: rgba(0, 0, 0, .8); }
body.dragging .faux .rail:hover { background-color: rgba(0, 0, 0, .8); }
body.dragging .rail span { display:none; }
body.dragging em { display:inline; color:white; }
.rail em { display:none; }
.rail.v span { display:block; display:none; position:absolute;width:150px; top:150px;
-webkit-transform: rotate(270deg);
-webkit-transform-origin: 0 0;
}
.rail.v { width: 20px; top:-5px; bottom:-5px; left:-46px;
}
.rail.h { height: 20px; left:-5px; right:-5px; top:-46px; }
.slice { position:absolute; background:rgba(0, 0, 0, .6); }
.slice.active { background: rgba(255, 0, 0, 1); }
.slice b { position:absolute; width: 10px; height:10px; top:-5px; left:-5px; background: #222; border-radius: 5px; }
.slice.active b { background: orange; }
.slice.v { top:-10px; bottom: -10px; width: 2px; }
.slice.v b { width: 40px; left: -20px;}
.slice.h { right:-10px; left: -10px; height: 2px; }
.slice.h b { height: 40px; top: -20px; }
#actual {
display:-webkit-box;
-webkit-box-orient: vertical;
}
JavaScript
$(function() {
$(".rail.h").mousedown(function(e) {
var newHandle = $(getHSlice(e.layerX));
$("#faux").append(newHandle);
initDraggable();
newHandle.find("b").trigger(e);
});
$(".rail.v").mousedown(function(e) {
var newHandle = $(getVSlice(e.layerY));
$("#faux").append(newHandle);
initDraggable();
newHandle.find("b").trigger(e);
});
$(document).bind("mousedown", function() {
$(".slice.active").removeClass("active");
});
$(".faux").bind("mousedown", function(e) {
e.stopPropagation();
});
initDraggable();
buildActual()
});
function getHSlice(coord) {
return "<div style='left: "+coord+"px;' data-flex='1' class='slice v'><b></b></div>"
}
function getVSlice(coord) {
return "<div style='top: "+coord+"px;' data-flex='1' class='slice h'><b></b></div>"
}
function initDraggable() {
$(".slice.h").draggable({
handle: "b",
axis: 'y',
containment: 'parent',
drag: drag,
start: dragStart,
stop: dragStop
});
$(".slice.v").draggable({
handle: "b",
axis: 'x',
containment: 'parent',
drag: drag,
start: dragStart,
stop: dragStop
});
$(".slice b").unbind("mousedown").mousedown(function(e) {
$(".slice").removeClass("active");
$(this).closest(".slice").addClass("active");
});
}
function drag() {
console.log(this, arguments);
}
function dragStart() {
$("body").addClass("dragging");
}
function dragStop() {
$("body").removeClass("dragging");
}
function buildActual() {
var sliceVert = $(".slice.v");
var sliceHoriz = $(".slice.h");
var horiz = sliceHoriz.map(function() {
return {
top: this.offsetTop,
height: $(this).attr("data-height"),
flex:...