JSFiddle - React, Tailwind, and code Playground
by Michael Prosser
HTML
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<div class="dynamic-layout">
<table class="layout">
<tbody>
<tr><td data-width="50" data-height="100" width="50%">CELL 1</td><td data-width="50" data-height="100" width="50%">CELL 2</td></tr>
</tbody>
</table>
<table class="layout">
<tbody>
<tr><td data-width="33" data-height="100" width="33%">CELL 1</td><td data-width="33" data-height="100" width="33%">CELL 2</td><td data-width="33" data-height="100" width="33%">CELL 3</td></tr>
</tbody>
</table>
</div>
CSS
.dynamic-layout{
margin-top:150px;
max-width:600px;
}
table.layout{
border-spacing: 10px;
width: 100%;
}
table.layout td{
outline: dashed 2px green;
height: 100px;
position:relative;
vertical-align: top;
}
.cell-ui{
background-color:#ccc;
color:#333;
position: absolute;
bottom: calc(100% + 2px);
left:-2px;
right:-2px;
font-family: helvetica;
font-size: 10px;
padding:4px;
border-radius: 4px;
line-height:22px;
padding-left:8px;
width: 140px;
}
.cell-ui input{
width:35px;
font-size: 10px;
background-color:#666;
color:#fff;
border:none;
border-radius: 4px;
padding:3px;
}
.cell-ui span{
width:40px;
display:inline-block;
}
.cell-ui>button.closeButton{
width:20px;
height:20px;
background-color: #666;
color:#fff;
border:none;
position: absolute;
right:3px;
top:3px;
border-radius: 3px;
cursor: pointer;
}
.cell-ui>button.removeButton{
background-color: #444;
color:#fff;
border:none;
margin-top:2px;
border-radius: 3px;
font-size: 10px;
padding: 3px;
padding-left:12px;
padding-right: 12px;
cursor: pointer;
}
JavaScript
function layoutNodes(){
this.setConfiguration = function(jsonString){
var html = '<table class="layout">';
for(var i=0;i<jsonString.length;i++){
html += '<tbody><tr>';
for(var ii=0;ii<jsonString[i].length;ii++){
html += '<td data-width="' + jsonString[i][ii].width + '" data-height="' + jsonString[i][ii].height + '" width="' + jsonString[i][ii].width + '%"></td>';
}
html += '</tr></tbody>';
}
html += '</table>';
return html;
}
this.getConfiguration = function(){
var layouts = [];
$(".layout").each(function(){
$(this).find("tr").each(function(){
var row = [];
$(this).find("td").each(function(){
row.push({
width: $(this).attr('data-width'),
height: $(this).attr('data-height')
});
});
layouts.push(row);
});
});
return layouts;
}
$(".layout").children('tbody')
.children('tr').sortable({
connectWith: '.layout tr',
revert: true,
helper: "clone",
receive: function(e,ui){
var t = $(this);
var c = 1;
var l = t.find('td').length;
var wid = 0;
t.find('td').each(function(){
if(c == l){
$(this).attr('data-width',parseFloat(100-wid));
$(this).css('width',parseFloat(100-wid) + '%');
} else {
wid+=parseFloat($(this).attr('data-width'));
}
c++;
});
},
stop: function(e,ui){
var t = $(this);
var c = 1;
var l = t.find('td').length;
var wid = 0;
t.find('td').each(function(){
if(c == l){
...