JSFiddle - React, Tailwind, and code Playground
HTML
<body>
<div class="container">
<div class="editor">
<nav class="aside">
</nav>
<div class="editor--wrapper">
<div class="editor--container" data-component-type="container"></div>
</div>
</div>
</div>
</body>
CSS
* {
box-sizing: border-box;
}
.container {
height: 600px;
}
.editor {
display: flex;
height: 100%;
align-content: stretch;
}
nav {
width: 200px;
border: 1px solid black;
}
.editor--wrapper {
flex: 1;
display: flex;
flex-direction: column;
border: 1px solid black;
}
.editor--toolbar {
}
.editor--container {
flex: 1;
border: 1px solid red;
}
[contenteditable=true]:empty:before{
content: attr(placeholder);
display: block; /* For Firefox */
}
[contenteditable=true] {
border: 1px dashed #AAA;
padding: 5px;
}
/* Draggable elements */
[draggable] {
-moz-user-select: none;
-khtml-user-select: none;
-webkit-user-select: none;
user-select: none;
-khtml-user-drag: element;
-webkit-user-drag: element;
}
.editor__item {
height: 90px;
width: 90px;
float: left;
border: 2px solid #666666;
background-color: #ccc;
margin-right: 5px;
text-align: center;
cursor: move;
}
JavaScript
var editor = (function(w, d, c) {
var draggingElement,
placeholder,
components = [],
options;
function _init() {
var master,
elements;
options = {
componentListClass: 'aside',
editorViewClass: 'editor--container',
draggingClass: 'dragging-item',
placeHolderClass: 'placeholder-item'
};
master = d.getElementsByClassName(options.editorViewClass)[0];
elements = master.getElementsByTagName("*");
c.log(master);
// TODO: combine both arrays
_on(master, 'dragenter', _handleDragEnter);
_on(master, 'dragover', _handleDragOver);
_on(master, 'dragleave', _handleDragLeave);
_on(master, 'drop', _handleDrop);
if (elements.length) {
_on(elements, 'dragenter', _handleDragEnter);
_on(elements, 'dragover', _handleDragOver);
_on(elements, 'dragleave', _handleDragLeave);
_on(elements, 'drop', _handleDrop);
}
[].forEach.call(components, function(component) {
_initComponent(component);
});
placeholder = d.createElement('div');
placeholder.setAttribute('style', 'height: 25px; background-color: red;');
}
function _initComponent(component) {
var element = d.createElement('div');
element.innerHTML = 'component ' + component.name;
_attr(element, 'class', 'editor__item');
_attr(element, 'draggable', 'true');
_attr(element, 'data-component-type', component.type);
_on(element, 'dragstart', _handleDragStart);
_on(element, 'dragend', _handleDragEnd);
d.getElementsByClassName(options.componentListClass)[0].appendChild(element);
}
function _on(element, event, callback) {
if (element instanceof Array) {
for (var i = 0; i < element.length; i++) {
_on(element[i], event, callback);
}
return;
}
element.addEventListener(event, callback);
}
function _off(element, event, callback) {
if (element instanceof Array) {
for (var i = 0; i < element.length; i++) {
...