JSFiddle - React, Tailwind, and code Playground
HTML
<h2>Openly configurable:</h2>
<div id="no1"></div>
<div style="min-height: 40px;"></div>
JSON:
<div id="no1JSON"></div>
<h2>Closed configuration:</h2>
<div id="no2"></div>
<div style="min-height: 40px;"></div>
JSON:
<div id="no2JSON"></div>
CSS
.container .spacer, .container .sub_element, .container .numeric_content, .container .string_content {
padding-left: 12px;
position: relative;
}
.container .spacer::before, .container .spacer::after,
.container .sub_element::before, .container .sub_element::after,
.container .numeric_content::before, .container .numeric_content::after,
.container .string_content::before, .container .string_content::after{
content: '';
position: absolute;
left: 0;
}
.container .sub_element::before, .container .numeric_content::before, .container .string_content::before{
border-top: 1px solid #999;
top: 12px;
width: 12px;
height: 0;
}
.container .spacer::after, .container .sub_element::after, .container .numeric_content::after, .container .string_content::after{
border-left: 1px solid #999;
height: 100%;
width: 0px;
top: -12px;
}
.spacer::after, .sub_element::after, .numeric_content::after, .string_content::after{
top: 12px;
}
.sub_element:last-child::after {
height: 24px;
}
.needed {
border-color: red;
border-width: 2;
}
.duplicate {
border-color: green;
border-width: 2;
}
input {
border-width: 0;
background-color: transparent;
padding-left: 5px;
height: 24px;
}
input:disabled {
padding-left: 10px;
}
.spacer {
height: 5px;
}
.additional {
background-color: white;
}
select {
height: 22px;
padding:3px;
margin: 0;
-webkit-border-radius:4px;
-moz-border-radius:4px;
border-radius:4px;
-webkit-box-shadow: 0 3px 0 #ccc, 0 -1px #bbb inset;
-moz-box-shadow: 0 3px 0 #ccc, 0 -1px #bbb inset;
box-shadow: 0 3px 0 #ccc, 0 -1px #bbb inset;
background: #eee;
color:#444;
border:none;
outline:none;
display: inline-block;
-webkit-appearance:none;
-moz-appearance:none;
appearance:none;
cursor:pointer;
}
JavaScript
(function (document, $) {
context = function(container, config) {
var class_names, drop_labels, include_spacers, refreshHandler, modifiable_form
// set configuration variables to config dictionary/object
function resetConfig(config) {
if (!config) {
config = {}
}
class_names = config['class_names']
if (class_names == undefined) {
class_names = {string_content:"string_content",
numeric_content:"numeric_content",
array_content:"array_content",
object_content:"object_content",
sub_element:"sub_element",
content:"content",
container:"container",
spacer:"spacer",
additional:"additional",
needed:"needed",
duplicate:"duplicate",
name_box:"name_box"}
}
drop_labels = config['drop_labels']
if (drop_labels == undefined) {
drop_labels = {None:"",
String:"String",
Number:"Number",
Array:"Array",
Object:"Object"}
}
include_spacers = config['include_spacers']
refreshHandler = config['refreshHandler']
modifiable_form = config['modifiable_form']
if (modifiable_form == undefined) {
modifiable_form = true
}
}
//call it
resetConfig(config)
// manually set the refresh handler hook
function setRefreshHandler(handler) {
refreshHandler = handler
}
// Given the 'content' DOM object of a presumed string...