JSFiddle - React, Tailwind, and code Playground

by Alexandru Chiculita

HTML

<script id="flow-template" type="template">
    <style>
        .flow-content-{{number}}
        {
            -webkit-flow-into: flow{{number}};
        }

        .flow-region-{{number}}
        {
            -webkit-flow-from: flow{{number}};
            border: 1px solid green;
        }
    </style>

    <h1>Flow {{number}}</h1>
    <button onclick="addFlowIntoElement({{number}})">Add flow-into element</button><br />
    
    <select class="flow-selector-{{number}} insert"></select>
    <button onclick="insertFlowIntoElement({{number}})">Insert flow-into element</button><br />

    <select class="flow-selector-{{number}} remove"></select>
    <button onclick="removeFlowIntoElement({{number}})">Remove one flow-into element</button><br />

    Move <select class="flow-selector-{{number}} change-flow"></select>
    to flow <select class="flow-parent-selector flow-{{number}} change-flow"></select>
    <button onclick="changeFlowItemParent({{number}})">Move element to different flow</button><br />
    
    <button onclick="removeFlowIntoElements({{number}})">Remove flow-into elements</button><br />

    Move <select class="flow-selector-{{number}} move"></select>
    before <select class="flow-selector-{{number}} move-before"></select>
    <button onclick="reorderFlowIntoElements({{number}})">Reorder flow-into elements</button><br />

    <button onclick="removeFlow({{number}})">Remove flow</button>

    <div class="flow-region-{{number}}"></div>
</script>

    <button onclick="createFlow()">Create flow</button>
    <div id="content"></div>

JavaScript

var _nextFlowId = 1;
var _nextId = 1;

function createFlow()
{
    var template = document.getElementById("flow-template").textContent;
    var flowElement = document.createElement("div");
    var flowNumber = _nextFlowId++;
    flowElement.id = "flow-" + flowNumber;
    flowElement.classList.add("flow-parent");
    flowElement.innerHTML = template.replace(/{{number}}/g, flowNumber);
    document.getElementById("content").appendChild(flowElement);
    updateFlowNumbers(false);
}

function removeFlow(flowNumber)
{
    document.getElementById("flow-" + flowNumber).remove();
    updateFlowNumbers(true);
}

function updateFlowNumbers(updateChildren)
{
    var elements = document.getElementsByClassName("flow-parent");
    var selectors = document.getElementsByClassName("flow-parent-selector");
    for (var i = 0; i < selectors.length; ++i) {
        var selector = selectors[i];
        var previousValue = selector.value;
        selector.textContent= "";
        for (var j = 0; j < elements.length; ++j) {
            var element = elements[j];
            var option = document.createElement("option");
            option.textContent = (j + 1) + ". " + element.id;
            option.setAttribute("value", element.id);
            selector.appendChild(option);
        }
        // Restore the selected value, only if the element is still part of the DOM.
        selector.value = previousValue && document.getElementById(previousValue) ? previousValue : selector.firstChild && selector.firstChild.value;
    }
}

function getSelectedFlowNumber(flowNumber, selector)
{
    var selector = document.querySelector(".flow-parent-selector.flow-" + flowNumber + "." + selector);
    return selector.value ? parseInt(selector.value.substr("flow-".length)) : 0;
}

function updateFlowItems(flowNumber)
{
    var elements = document.getElementsByClassName("flow-content-" + flowNumber);
    var selectors = document.getElementsByClassName("flow-selector-" + flowNumber);
    for (var i = 0; i <...