Discussion about handling div addition on the fly

I have the following code (which is coming from my earlier question posted here where a user PaulOB provided an example) where the blue color boxes on the left text go inside the squares after the button click. The way it is going to work in my actual code is that there will be a dropdown list of some items and I will get the value of the blue boxes (for eg. H1 Text, H2 Text etc) depending upon what is selected by the user from the dropdown. So basically I will be generating the divs related to blue boxes dynamically and the total number of boxes (and the value inside it) depends upon how many values are returned based on selecting an item from the dropdown list. (This part is not shown here and I’ve just hardcoded the blue boxes as this is not relevant to my question).

My question is:

If I want to create additional blue boxes on the fly, is it possible to achieve that? For example, I want to create a blue box with the value F6 Text as value and put it below the blue box where it says G6 Text, is it possible to create one? It will be an addition of a new div like this <div data-id="13"><span data-id="13" class="words">F6 Text</span></div> just below the <div data-id="12"><span data-id="12" class="words">G6 Text</span></div> inside <div id = "phrase">

Also, I would like to create just an empty box without any value so if I have divs up to F6 Text in the div, it will look like <div data-id="14"><span data-id="12" class="words"></span></div>.

I am wondering if I need to have a button somewhere, where I need to show a pop-up dialog asking the user what value is needed and then append the div to the above divs or is there a better way of handling this?

Coming back to the dropdown list explanation I mentioned in the first paragraph, I was initially thinking of having these boxes or just the text shows up in a text area separated by a comma and then the user can just hit the button and the text would move inside the squares but I can’t have divs inside the text area so I think this approach won’t work.

$(".words").draggable({
  revert: function (event, ui) {
    var bRevertingPhrase = this.closest("#drop-em");

    if (!bRevertingPhrase.length) {
      var phraseID = $(this).data("id");
      var phraseHomeID = $(this).parent().data("id");

      //If the child and parent ids don't match, we move the child to the correct parent
      if (phraseID !== phraseHomeID) {
        var correctCell = $("#phrase").find("div[data-id='" + phraseID + "']");
        correctCell.prepend(this);
      }
    }
    return !event;
  }
});
$("#drop-em > div").droppable({
  drop: function (ev, ui) {
    $(ui.draggable)
      .detach()
      .css({ top: 0, left: 0 })
      .appendTo($(this).find(".content:empty"));
    $("#move-text").addClass("disabled");
  }
});
$("#phrase > div").droppable({
  drop: function (ev, ui) {
    $(ui.draggable).detach().css({ top: 0, left: 0 }).prependTo(this);
  }
});

const myButton = document.querySelector("#move-text");
myButton.addEventListener(
  "click",
  () => {
    fill();
  },
  {
    once: true
  }
);

var reOrder = [];
function fill() {
  const cells = document.querySelectorAll("#phrase > div > span");
  var newLoc = "";

  myButton.classList.add("disabled");

  cells.forEach((cell, index) => {
    newLoc = document.querySelector(
      ".item:nth-child(" + reOrder[index] + ") .content "
    );
    newLoc.append(cell);
    newLoc.classList.add("moved");
  });
}
function reArrange() {
  var limit1 = 85;
  var limit2 = 91;

  for (let loop = 0; loop < 8; loop++) {
    for (let i = 0; i < 6; i++) {
      reOrder.push(limit1 + i);
    }
    limit1 = limit1 - 12;
  }
  for (let loop = 0; loop < 8; loop++) {
    for (let j = 0; j < 6; j++) {
      reOrder.push(limit2 + j);
    }
    limit2 = limit2 - 12;
  }
}
reArrange();
html {
  box-sizing: border-box;
}
*,
*:before,
*:after {
  box-sizing: inherit;
}
body {
  counter-reset: columnCount 1 alphaCount cellCount;
}
h1 {
  text-align: center;
}
.wrap {
  display: flex;
  gap: 2rem;
  position:relative;
  padding-left:220px;
}

.grid {
  margin: auto;
  display: grid;
  flex: 1 0 0;
  grid-template-columns: repeat(12, 1fr);
  padding-top: 1.5rem;
}

.item {
  position: relative;
  background-color: #f9f9f9;
  border: 1px solid grey;
  aspect-ratio: 1/1;
  counter-increment: columnCount;
  min-width: 0;
  transition: background 1s ease;
}
.item:nth-of-type(12n + 1) {
  counter-increment: alphaCount;
}
.item:nth-of-type(12n + 1)::before {
  content: counter(alphaCount, upper-alpha);
  position: absolute;
  display: flex;
  align-items: center;
  top: 0;
  bottom: 0;
  left: -1.75rem;
  color: red;
  pointer-events: none;
}
.item:nth-of-type(n + 13)::after {
  display: none;
}
.item::after {
  content: counter(columnCount);
  position: absolute;
  left: 0;
  right: 0;
  text-align: center;
  top: -1.75rem;
  color: red;
  pointer-events: none;
}
.content {
  display: flex;
  flex-direction: column;
  justify-content: center;
  width: 100%;
  height: 100%;
  overflow: auto;
  color: #000;
  padding: 1rem;
  word-wrap: break-word;
  counter-increment: cellCount;
}

.words {
  cursor: move;
  transition: padding 0.5s ease;
}
.content:has(.ui-draggable-dragging) {
  overflow: visible;
}
.ui-droppable-active .content {
  overflow: visible;
}
.words.ui-draggable-dragging {
  background: blue;
  padding: 5px 10px;
  border-radius: 6px;
  z-index: 999;
  color: #fff;
  display: block;
  width: 50px;
  height: 50px;
  overflow: hidden;
}
#phrase {
  position:absolute;
  left:0;
  top:0;
  bottom:0;
  color: #fff;
  width:150px;
  overflow:auto;
  z-index: 2;
  display: flex;
  flex-direction: column;
  margin:1rem 0 .5rem;
}
#phrase > div {
  margin: 0 0 10px;
  width:150px;
  padding: 5px 10px;
  background: #007bff;
  border: 2px solid #007bff;
  border-radius: 6px;
  color: #fff;
}
#phrase > div:empty {
  background: #fff;
  border-style: dashed;
  padding: 0px 25px;
  min-height: 30px;
}

.moved {
  animation: fade 3s ease;
}
@keyframes fade {
  0% {
    opacity: 0;
  }
  50% {
    opacity: 1;
    background: red;
  }
}

.item .content::before {
  content: counter(cellCount);
  position: absolute;
  top: 2px;
  left: 2px;
  font-size: smaller;
  color: #666;
  border-radius: 50%;
  border: 1px solid red;
  background: white;
  width: 1.2rem;
  height: 1, 2rem;
  display: grid;
  place-items: center;
}

#move-text.disabled{
  cursor:none;
  pointer-events:none;
  opacity:0.5;
}
#phrase:has(.ui-droppable-active){
  overflow:visible;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>

<!-- You'd need to set up something different for touch devices though -->
<h1>Drag and drop example </h1>
<button id="move-text" type="button">Move Text Content!</button>
<div class="wrap">
  <div id="phrase">
    <!-- remove whitespace from  inside div html and then we can use :empty in css to change background -->
    <div data-id="1"><span data-id="1" class="words">H1 Text</span></div>
    <div data-id="2"><span data-id="2" class="words">H2 Text</span></div>
    <div data-id="3"><span data-id="3" class="words">H3 Text</span></div>
    <div data-id="4"><span data-id="4" class="words">H4 Text</span></div>
    <div data-id="5"><span data-id="5" class="words">H5 Text</span></div>
    <div data-id="6"><span data-id="6" class="words">H6 Text</span></div>
    <div data-id="7"><span data-id="7" class="words">G1 Text</span></div>
    <div data-id="8"><span data-id="8" class="words">G2 Text</span></div>
    <div data-id="9"><span data-id="9" class="words">G3 Text</span></div>
    <div data-id="10"><span data-id="10" class="words">G4 Text</span></div>
    <div data-id="11"><span data-id="11" class="words">G5 Text</span></div>
    <div data-id="12"><span data-id="12" class="words">G6 Text</span></div>
  </div>

  <div id="drop-em" class="grid">
    <div class="item">
      <div class="content"></div><!-- must have no spaces inside .content -->
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    <div class="item">
      <div class="content"></div>
    </div>
    

  </div>
</div>

document.createElement
HTML DOM Document createElement() Method (w3schools.com)

Note that CSS rules will automatically be applied to all elements entering the DOM; however Javascript bindings to those elements will not; so if you create a new element with class words after you’ve applied the draggable (for example), you will have to make it .draggable as well. (You should already have a reference to that specific element from creating it, so you would just call $(myelem).draggable(...

1 Like