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>
<div class="ui-node ui-node-inline" data-index="-1" data-node-width="one-half" data-node-type="submit" data-node-html="SUBMIT FORM"><input id="submit-button" type="submit" value="SUBMIT FORM"><button type="button" class="removeButton"><img src="https://agrisphere-portal.com/agGear/assets/trash.png"></button></div>

<div id="output_0" class="ui_output aliveComponents selected" data-index="0" data-component-type="select" data-dropped="true"><label data-component-label="Select"><span data-component-type="select"><span>Select</span></span> <select autocomplete="off" height="80" id="myController0" multiple="true" name="myController0" required="1" size="6" width="200" guid="f9f64507-3735-4199-86b1-debf1d705962"><option value="Option 1">Option 1</option><option value="Option 2">Option 2</option></select></label></div>

CSS

html{
  height: 100%;
}
body{
  background-color: #fff;
  height: 100%;
}

.context-menu{
  position: fixed;
  top: 0px;
  left: 0px;
  width: 180px;
  min-height: 100px;
  background-color: #fff;
  border: solid 1px #ccc;
  padding: 10px;
  font-family: helvetica;
  font-size: 13px;
  box-shadow: 1px 2px 3px rgba(0,0,0,0.6);
}
.context-menu>img{
  width: 100%;
  height: auto;
}
.context-menu ul{
  list-style: none;
  margin: 0px;
  padding: 0px;
}
.context-menu ul > li{
  padding: 9px;
  border-bottom: solid 1px #ccc;
  background-color: #fff;
  cursor: pointer;
}
.context-menu ul > li:hover {
  background-color: #356DB0;
  color: #fff;
}
.context-menu ul > li.disabled{
  pointer-events: none;
  background-color: #eee;
  color: #ccc;
}

JavaScript

function clipboard(){

	var t = this;
  
  t.clipboardData = null;
  
  t.dom = null;
  
  t.target = null;
  
  t.getComponentFromElement = function(){
  
  	for(var i=0;i<window.nodes.length;i++){
		
    	if(window.nodes[i].element === t.target){
      
      	return window.nodes[i];
      
      }
    
    }
  
  }
  
  t.getNodeFromElement = function(){
  
  	for(var i=0;i<window.components.length;i++){
		
      if(window.components[i].component === t.target[0]){
      
      	return window.components[i];
      
      }
    
    }
  
  }
  
  t.getIndexFromComponent = function(){
  
  	for(var i=0;i<window.components.length;i++){
		
      if(window.components[i].component === t.target[0]){
      
      	return i;
      
      }
    
    }
  
  }
  
  t.deleteComponent = function(){
  
  	if(t.targetType == 'component'){
    
    	var i = t.getIndexFromComponent();
      
    	$('nav.alive>a').eq(i).click();
      
      $('nav.alive>a').eq(i).find('button').click();
    
    } else {
    
    	t.target.find('.removeBUtton').click();
    
    }
  	
  }
  
  t.copyComponent = function(){
  
  	if(t.targetType == 'component'){
    
    	t.clipboardData = t.getComponentFromElement(t.target[0]);
    
    } else {
    
    	t.clipboardData = t.getNodeFromElement(t.target[0]);
    
    }
   
  
  }
  
  t.contextMenu = function(e){
  
    $('.context-menu').remove();
  
  	t.dom = document.elementFromPoint(e.clientX, e.clientY);
    
    t.domJQ = $(t.dom);
    
    t.target = null;
    
    t.targetType = null;
    
    if(t.domJQ.hasClass('ui-node')){
    
    	 t.target = t.domJQ;
       t.targetType = 'node';
    
    } else if(t.domJQ.parent().hasClass('ui-node')){
    
    	 t.target = t.domJQ.parent();
       t.targetType = 'node';
    
    } else if(t.domJQ.parent().parent().hasClass('ui-node')){
    
    	 t.target = t.domJQ.parent().parent();
       t.targetType = 'node';
    
    } else if(t.domJQ.hasClass('aliveComponents')){
    
    	 t.target =...