JSFiddle - React, Tailwind, and code Playground

by texinwien

HTML

<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Tree Editor</title>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    </head>
    <body id="body">
        <form method="post" id="theForm">
            <ul class="main-container expanded">
                <li id="uiid0x24667e20" class="element resource">
                    <fieldset>
                        <span class="shrinker">
                            <span class="resource nodename">resource</span>
                            <span class="attribute-container">
                                <label for="id0x24667e20-0000000000">rid: </label>
                                <input type="text" id="id0x24667e20-0000000000" name="rid" value="Test Container" size="20" class="rid">
                            </span>
                            <span class="attribute-container">
                                <label for="id0x24667e20-0000000001">Autocomplete: </label>
                                <input type="text" id="id0x24667e20-0000000001" name="country" value="USA" size="20" class="country autocomplete">
                            </span>
                            <span class="attribute-container">
                                <label for="id0x24667e20-0000000002">label: </label>
                                <input type="text" id="id0x24667e20-0000000002" name="label" value="Test" size="20" class="label">
                            </span>
                            <span class="nodename"></span>
                        </span>
                        <ul class="expanded">
                            <li id="uiid0x24676560" class="element resource">
                                <fieldset>
                                    <span class="shrinker">
                                        <span class="resource nodename">Click Here</span>
                                        <span...

CSS

body {
    font-size:10px;
    font-family: Consolas, Courier;
    overflow-x: hidden;
}
body, form ul, form li{
    border:0; margin:0; padding:0; list-style:none;
}
form {
    width:100%;
    font-size: 1.4em;
    font-family: Consolas;
    /*border: 1px solid #A6A6A6;*/
    margin:0;
    padding:0;
}
fieldset {
    clear:both;
    display: block;
    padding:0;
    margin:0;
    width:99%;    
    border-style:none;
}
fieldset fieldset {
    margin-left:1em;
}
fieldset legend {
    display:none;
    font-weight: bold;
    background-color: #FFF;
    margin-top:1.2em;
    color:blue;
    cursor:pointer;
}
input[type=text], textarea, select {
    font-size:1em;
    font-family: Consolas;
    float:left;
    background:transparent;
    border-style:none;
    margin:0;
    padding:0;
}
input:hover, textarea:hover, select:hover {
    background:#F5F5F5;
}
input:focus, textarea:focus, select:focus {
    background:white;
}
input[type=text], select {
    font-size:1em;
    color:#8000FF;
    font-weight:bold;
}
textarea {
    width:94%;
    height:1em;
}
.comment textarea {
    font-style: italic;
    color:#008000;
}
.text textarea {
    color:#000000;
}
span.expandcollapse {
    display:none;
    position:relative;
    margin-top:.2em;
    z-index:10;
    width:11px;
    height:11px;
    background-image:url(../images/sprite.png);
    background-position:-11px 0px; 
    left:-11px;
    margin-right:-11px;
}
li.resource > fieldset > span.expandcollapse, li.if > fieldset > span.expandcollapse {
    display:inline;
}
span.expandcollapse.collapsed {
    background-position:0px 0px;
}
label, li span, .nodename, .assignment-operator, .double-quotes,
.comment-start, .comment-end, .processing-instruction-start,
.processing-instruction-end    {
    float: left;
    white-space: nowrap;
    display:block;
    cursor:default;
}
fieldset > span.shrinker {width:90%;
    white-space: normal;
}
.compact {height: 1.2em; overflow-y: hidden;}
.hidden{display:none;}
label {
   ...

JavaScript

$().ready(function() {
    var myAutoIncrementingID = 1,
        theForm = $('#theForm'); /* BEGIN:    Element Menu    */

    var elementMenu = document.getElementById('element-menu'),
        allChildLIs = $('#theForm li.element.resource li.element'),
        htmlClipboard = document.createDocumentFragment();

    // Attach function to click on all Node Name Spans to open the menu
    $(allChildLIs).delegate('span.nodename', 'click', function(event) {
        event.stopPropagation();
        var position = $(this).position(),
            height = $(this).height(),
            contextHtmlNodeID = $(this).parents('li:first').attr('id');
        $(elementMenu).css({
            'top': parseInt(position.top + height),
            'left': position.left
        }).toggle();
        $(elementMenu).attr('contextHtmlNodeID', contextHtmlNodeID);
    });

    $('#body').click(function() {
        $(elementMenu).hide();
    });

    function generateNewID() {
        return ++myAutoIncrementingID;
    }

    $('#duplicate-element').click(function() {
        $(elementMenu).toggle();
        var newIDPostfix = generateNewID(),

            //Set HTML Node variables
            contextHtmlNodeID = $(elementMenu).attr('contextHtmlNodeID'),
            contextHtmlNode = document.getElementById(contextHtmlNodeID),
            newHtmlId = contextHtmlNodeID.split('-')[0] + '-' + newIDPostfix,
            duplicateHtmlNode = $(contextHtmlNode).clone();

        $(duplicateHtmlNode).attr('id', newHtmlId);
        //generate Ids for the new nodes
        $(duplicateHtmlNode).find('input:text').each(function() {
            var origHtmlId = $(this).attr('id').split('-');
            origHtmlId[2] = origHtmlId[2] === undefined ? '' : origHtmlId[2];
            var newHtmlId = origHtmlId[0] + '-' + origHtmlId[1] + '-' + origHtmlId[2] + newIDPostfix;
            $(this).attr('id', newHtmlId);
            $(this).siblings('label').attr('for', newHtmlId);
        });
       ...