JSFiddle - React, Tailwind, and code Playground
Editor Layout Experiments
by nilloc
HTML
<container id="editor">
<container id="toolbar">
toolbar
</container>
<container id="drawer">
drawer
</container>
<container id="handle"></container>
<container id="stage"
data-top="toolbar"
data-left="handle"
data-right="0"
data-bottom="0">
stage
<anchor class="top" contenteditable data-setting="toolbar">toolbar</anchor>
<anchor class="left" contenteditable data-setting="handle">handle</anchor>
<anchor class="right" contenteditable data-setting="right">0</anchor>
<anchor class="bottom" contenteditable data-setting="bottom">0</anchor>
</container>
</container>
SCSS
*{
box-sizing:border-box;
}
container{
display:block;
position:relative;
user-select:none;
}
#editor, #drawer, #handle, #stage{
position:absolute;
}
#editor{
background:darkgray;
top:0;
left:0;
bottom:0;
right:0;
$toolbar-height:60px;
$drawer-width:200px;
$handle-width:4px;
#toolbar{
background:lightgray;
height:$toolbar-height;
padding:10px;
}
#drawer{
background:white;
top:$toolbar-height;
left:0;
width:$drawer-width;
bottom:0;
}
#handle{
background:#777;
top:$toolbar-height;
left:$drawer-width;
width:$handle-width;
bottom:0;
cursor:col-resize;
z-index:1000;
}
#stage{
background:#eee;
top:$toolbar-height;
left:$drawer-width+$handle-width;
right:0;
bottom:0;
}
anchor{
display:block;
position:absolute;
height:20px;
width:60px;
background:white;
border:1px solid darkgray;
border-radius:4px;
text-align:center;
outline: none;
overflow:hidden;
&.top, &.bottom{left:calc(50% - 30px);}
&.left, &.right{top:calc(50% - 30px);}
&.top, &.left, &.right{border-radius:0 0 4px 4px;}
&.top{top:0;}
&.bottom{bottom:0; border-radius:4px 4px 0 0;}
&.left{ left:-20px; transform:rotate(-90deg); }
&.right{ right:-20px; transform:rotate(90deg); }
}
}
JavaScript
$('anchor').on("input", function(){
console.log($(this).parent(), "changed:", this.textContent);
var $parent = $(this).parent();
if(this.textContent.indexOf('%') > -1){
$parent.css(this.className, this.textContent); // make %
this.dataset.setting = this.textContent;
}else if(this.textContent == parseFloat(this.textContent)){
$parent.css(this.className, this.textContent+"px"); // make abs
this.dataset.setting = this.textContent;
}else{
// search for id and attach based on edge
var $target = $('container#'+this.textContent);
if($target.length > 0 ){
console.log("found:", $target);
this.dataset.setting = this.textContent;
switch(this.className){
case 'top':
console.log($target.offset().top+$target.outerHeight());
$parent.css('top', $target.offset().top+$target.outerHeight()+"px");
break;
case 'left':
$parent.css('left', $target.offset().left+$target.outerWidth()+"px");
break;
case 'right':
$parent.css('right', $target.offset().left+"px");
break;
case 'bottom':
$parent.css('top', $target.offset().top+"px");
break;
}
}
}
});
$('#handle').on('mousedown', function(){
$('#editor').on('mousemove.handle', function(evt){
//console.log("dragging mouse", evt.pageX);
var handlePos = evt.pageX+'px';
$('#handle').css('left', handlePos);
$('#drawer').css('width', handlePos);
$("anchor[data-setting='handle']").trigger('input');
});
}).on('mouseup', function(){
$('#editor').off('mousemove.handle');
});