1

Main Question:
How can you increment/decrement IDs/Names of dynamic elements when they are added, removed, and/or moved up and down the DOM?

Note:
Please see the code below to understand the situation. The main focus is the script; however, I placed the entire code below to see what I'm talking about.

Context and Intent:
A user will be able to choose a topic from the select drop-down menu, then write about that topic in the corresponding textarea. They can add multiple sections for different topics; they can delete topics (all but the only of its kind); they can move topics up or down as they want for precedence.

The intent is to be able to later reach out to grab the topic (option Selected) and corresponding text in the textarea for each individual section.

My assumption is that I'll have to reference unique ID and/or Name attributes.

How can I best achieve this? I'm open to any feedback.

For all I know, I may be approaching this whole thing from the wrong angle.

Thanks in advance.

Scripts

$(document).ready(function() {

  // ADD SECTION //
  $(document).on("click", "#AddSection", function() {
    var subSection_1_A = '<ul class="subSection_1_A" id=SubSection[] name=subSection[]><li class="buttons"><button type="button" id="AddSection">&#x2795;</button><button type="button" id="DeleteSection">&#10060;</button><button type="button" id="MoveSectionUp">&#9650;</button><button type="button" id="MoveSectionDown">&#9660;</button></li><li class="select"><label for="Topic">Topic:</label><select type="text" id="Topic[]" name="topic[]"><option value="" disabled selected>Select Option...</option><option value="Option_1">Option 1</option><option value="Option_2">Option 2</option><option value="Option_3">Option 3</option></select></li><li class="textArea"><textarea type="text" id="Text[]" name="text[]"></textarea></li></ul>';
    var current = $(this).closest("ul");
    $(current).after(subSection_1_A);
  });

  // DELETE SECTION //
  $(document).on("click", "#DeleteSection", function() {
    var current = $(this).closest("ul");
    if(current.is(":only-of-type")) {
      alert("You can't delete the only sub-section.");
    }
    else {
    if(confirm("Are you sure you want to delete this?")) 
      current.not(":only-of-type").remove();
    }
  });

   // MOVE SECTION UP //
   $(document).on("click", "#MoveSectionUp", function() { 
    var current = $(this).closest("ul");
    var previous = current.prev("ul");
    if(previous.length !== 0) {
    current.insertBefore(previous);
    }
    return false;
  });

  // MOVE SECTION DOWN //
  $(document).on("click", "#MoveSectionDown", function() {     
    var current = $(this).closest("ul");
    var next = current.next("ul");
    if(next.length !== 0) {
    current.insertAfter(next);
    }
    return false;
  }); 

});

Everything Together (HTML, CSS, and jQuery/JavaScript)

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
  <title>Dynamic DOM</title>
</head>

<style type="text/css">
.subSection {
  padding: 1em 0em 0em 0em;
  margin: 0em 0em 0em .5em;
}
ul, li {
  list-style: none;
}
.subSectionContainer {
  padding: 0em 1em 0em 1em;
}
.subSection_1_A {
  width: 1000px;
  padding: 0em 1em 1em 1em; 
}
li.buttons {
  display: flex;
  border-bottom: 1px solid #000000;
}
button {
  width: 6em;
  height: 2em;
  padding: 0em;
  border-width: 1px 1px 0px 1px;
  border-style: solid;
  border-color: #000000;
  margin: 0em;
  background: none;
  cursor: pointer;
}
button:nth-of-type(odd),
button:nth-of-type(even) {
  border-right: none;
}
button:last-of-type {
  border-right: 1px solid #000000;
}
label, select {
  align-self: center;
  padding: 0em .5em 0em 0em;
}
li.select {
  display: flex;
  border-width: 0px 1px 0px 1px;
  border-style: solid;
  padding: .5em 0em .5em .5em;
}
li.textArea {
  padding: 0em 0em .5em 0em;
  border-width: 0px 1px 1px 1px;
  border-style: solid;
  border-color: #000000;
  text-align: center;
}
textarea {
  width: 98%; 
  height: 100%;
  min-height: 200px;    
}
</style>

<body>
  <h1>Dynamic Elements with Dynamic IDs/Names</h1>
  <h1>Moving Elements Up/Down with Dynamic ID/Name Change</h1>
  <div class="subSection">
    <section class="subSectionContainer">
      <ul class="subSection_1_A" id=SubSection[] name=subSection[]>
        <li class="buttons"><button type="button" id="AddSection">&#x2795;</button><button type="button" id="DeleteSection">&#10060;</button><button type="button" id="MoveSectionUp">&#9650;</button><button type="button" id="MoveSectionDown">&#9660;</button></li>
        <li class="select">
          <label for="Topic">Topic:</label>
          <select type="text" id="Topic[]" name="topic[]">
            <option value="" disabled selected>Select Option...</option>
            <option value="Option_1">Option 1</option>
            <option value="Option_2">Option 2</option>
            <option value="Option_3">Option 3</option>
          </select>
        </li>
        <li class="textArea"><textarea type="text" id="Text[]" name="text[]"></textarea></li>
      </ul>
    </section>
  </div>

  <script type="text/javascript">

  $(document).ready(function() {

    // ADD SECTION //
    $(document).on("click", "#AddSection", function() {
      var subSection_1_A = '<ul class="subSection_1_A" id=SubSection[] name=subSection[]><li class="buttons"><button type="button" id="AddSection">&#x2795;</button><button type="button" id="DeleteSection">&#10060;</button><button type="button" id="MoveSectionUp">&#9650;</button><button type="button" id="MoveSectionDown">&#9660;</button></li><li class="select"><label for="Topic">Topic:</label><select type="text" id="Topic[]" name="topic[]"><option value="" disabled selected>Select Option...</option><option value="Option_1">Option 1</option><option value="Option_2">Option 2</option><option value="Option_3">Option 3</option></select></li><li class="textArea"><textarea type="text" id="Text[]" name="text[]"></textarea></li></ul>';
      var current = $(this).closest("ul");
      $(current).after(subSection_1_A);
    });

    // DELETE SECTION //
    $(document).on("click", "#DeleteSection", function() {
      var current = $(this).closest("ul");
      if(current.is(":only-of-type")) {
        alert("You can't delete the only sub-section.");
      }
      else {
      if(confirm("Are you sure you want to delete this?")) 
        current.not(":only-of-type").remove();
      }
    });

     // MOVE SECTION UP //
     $(document).on("click", "#MoveSectionUp", function() { 
      var current = $(this).closest("ul");
      var previous = current.prev("ul");
      if(previous.length !== 0) {
      current.insertBefore(previous);
      }
      return false;
    });

    // MOVE SECTION DOWN //
    $(document).on("click", "#MoveSectionDown", function() {      
      var current = $(this).closest("ul");
      var next = current.next("ul");
      if(next.length !== 0) {
      current.insertAfter(next);
      }
      return false;
    }); 

  });

  </script>

</body>
</html>

1 Answers1

0

What about a global variable?

window.counter = 0;

Then when you add a dynamic element

window.counter++;
  • This is definitely a weak point for me. I'm not sure how to actually implement that. – AmateurAtBest Jun 20 '18 at 17:19
  • Please review this [Plunker](https://plnkr.co/edit/NvEbIvgCcZ8MnHr9jkzw?p=preview) – Jose Luis Berrocal Jun 20 '18 at 17:29
  • This definitely helps me understand the concept of incrementing with 'window.counter'; however, I tested moving the sections up and down the DOM. The sections don't rename themselves (ID & Name attributes) as they're moved. My intent is to pull the data (Topic and Text) from all of the sections, and have it in order as it's viewed on the page/DOM - if the user ultimately has 10 topic sections, but added, deleted, and moved several, I want the IDs/Names to end up in sequential order from the top. I hope that helps show my intent. Either way, I appreciate your feedback and taking your time – AmateurAtBest Jun 20 '18 at 18:38