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){

      ...