Time for populating a UI dynamically increases linearly, with each try?

Viewed 42

Requirement:

  1. User will enter "Number of Containers" and "Number of Controls"
  2. Random input elements (numeric, checkbox, etc) will be created and equally distributed among the containers.
  3. When user clicks on "Create" again, the input elements shown in the UI will be deleted and new set of random input elements will be populated again. Sample UI with Controls Populated

Issue: Every time I create new set of input elements, the time taken for creating increases linearly up to a point then decreases little and increases again Time Log example

I use the below code to empty the div that accommodates the containers and create input elements

Emptying the overall div

node.innerHTML = ""

Creating a numeric control with label

function createNumber(display) {
  let controlWrap = document.createElement("div");
  let label = document.createElement("label")
  let control = document.createElement("input")
  control.type = "number";
  label.append("Numeric Input");
  label.append(control);
  controlWrap.append(label);
  controlWrap.style.display = display;
  controlWrap.classList.add("ctrl");
  return controlWrap;
}

Find the entire code below,

//Constands
const CTRL_DISPLAY_TYPE = "block"

//Selection
const numOfContainers = document.querySelector("#numOfContainers");
const numOfControls = document.querySelector("#numOfControls");
const createContainersBtn = document.querySelector("#create");
const containerWrapper = document.querySelector(".containerWrapper");
const controlHeading = document.querySelectorAll(".ctrlHeading");

//Event Listeners
createContainersBtn.addEventListener("click",createContainers);
controlHeading.forEach(element => element.addEventListener("click"),expandControl);

//Support-functions
function createControl(newControlContainer){
    let newControlWrapper = document.createElement("div")
    newControlWrapper.classList.add("ctrlWrapper");

    let newControl = createNumber(CTRL_DISPLAY_TYPE);
    newControlWrapper.appendChild(newControl);
    newControlContainer.appendChild(newControlWrapper);

}

function createNumber(display){
    let controlWrap = document.createElement("div");
    let label = document.createElement("label")
    let control = document.createElement("input")
    control.type = "number";
    label.append("Numeric Input");
    label.append(control);
    controlWrap.append(label);
    controlWrap.style.display = display;
    controlWrap.classList.add("ctrl");
    return controlWrap;
}

function calculateControlPerContainer(numOfContainers,numOfControls,maxLimit){
    let controlsPerContainer = []
    let pendingControls = numOfControls%numOfContainers
    let controlPerContainerNum = Math.floor(numOfControls/numOfContainers)
    for (let i=0;i<numOfContainers;i++){
        if (pendingControls>0){
            newControlsPerContainer=controlPerContainerNum+1;
            controlsPerContainer.push(newControlsPerContainer);
            --pendingControls;
        }
        else{
            controlsPerContainer.push(controlPerContainerNum);
        }
    }
    return controlsPerContainer
}

function expandControl(event){
    const control = event.currentTarget.nextElementSibling;
    if (control.style.display === "none"){
        control.style.display = "block";
    }
    else {
        control.style.display = "none"
    }
}

//utility-functions
function removeChild(node){
    while(node.firstChild){
        node.removeChild(node.firstChild);
    }
}

function clearNodeData(node){
    node.innerHTML = ""
}

//main-Functions
function createContainers(event){
    console.time("Deleting controls");
    const controlsPerContainer = calculateControlPerContainer(parseInt(numOfContainers.value),parseInt(numOfControls.value));
    clearNodeData(containerWrapper);
    //removeChild(containerWrapper);
    console.timeEnd("Deleting controls");  
    console.time("populating controls");
    controlsPerContainer.forEach(num=>{        
        let newControlContainer = document.createElement("div")
        newControlContainer.classList.add("ctrlContainer");
        for(let j=0;j<num;j++){
            createControl(newControlContainer);
        }
        containerWrapper.appendChild(newControlContainer);
    }) 
    console.timeEnd("populating controls");   
}
* {
    box-sizing: border-box;
}

html, body {
    margin: 0;
    padding: 0;
    border: 0;
    height:100%
}

.containerWrapper{
    display:flex;
    flex-direction: row;
    height: 90%;
}

.ctrlContainer{
    /* flex-grow:1; */
    flex-shrink: 0;
    border-style: solid;
    border-width: 0.5px;
    margin:0 2px;
    flex-basis: calc(25% - 4px);
    align-items: stretch;
    display:flex;
    flex-direction: column;
    overflow: auto;
}

.ctrlWrapper{
    border-style: solid;
    border-width: .5px;
    margin:2px
}

.ctrlHeading{
    display:block;
    width: 100%;
    text-align: left;
    border: 0;
}

.ctrl{
    display:none;
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Dynamic Controls</title>
    <link rel="stylesheet" href="style/main.css">
</head>
<body>
    <label for="numOfContainers">Number of Containers</label>
    <input type="number" id="numOfContainers" name="numOfContainers" min="1" max="500" value="100">
    <label for="numOfControls">Number of Controls</label>
    <input type="number" id="numOfControls" name="numOfControls" min="1" max="1500" value="1500"><br>
    <button id="create">Create</button>
    <div class="containerWrapper">
        <!-- <div class="ctrlContainer">
            <div class="ctrlWrapper">
                <button class="ctrlHeading">Checkbox</button>
                <input class="ctrl" type="checkbox">
            </div>
            <div class="ctrlWrapper">
                <button class="ctrlHeading">Checkbox</button>
                <input class="ctrl" type="checkbox">
            </div>
        </div>
        <div class="ctrlContainer">2</div>
        <div class="ctrlContainer">3</div> -->
    </div>
    <script type="module" src="scripts/MainBackup.js"></script>
</body>
</html>

I tried analyzing using chrome developer tools and could see "append" function is taking more total time. Please let me know if I am doing something wrong in deleting or adding controls and how to avoid this time build up with every run.

More Information after some more exploration:

  1. I am seeing this behavior only in chrome. In firefox and edge, there is no time buildup. Firefox: Time for populating controls in firefox
  2. This occurs only in my system. Others are not able to replicate.
  3. The time build-up occurs in portion of code in which I append inputs to the label to assign it to the input without using id. If I directly append the input to container, the time buildup doesn't happen Appending input to label
0 Answers
Related