dynamic list

by Laberwurschd

HTML

<form id="lister">
<ul>
  <li>
    one
    <button name="remove-1" title="remove">remove</button>
  </li>
  <li>
    two
    <button name="remove-2" title="remove">remove</button>
  </li>
  <li>
    <label>
      new list item:
      <input name="new_li">
    </label>
    <button name="add">add</button>
  </li>
</ul>
</form>

CSS

[name^="remove"] {
  background: #fee;
  border: 1px solid red;
  border-radius: 0.2em;
  color: red;
  cursor: pointer;
  opacity: 0.5;
  overflow: hidden;
  padding: 0 0 0 1em;
  position: relative;
  width: 0em;
}

[name^="remove"]:before {
  content: "x";
  position: absolute;
  left: 25%;
}

[name^="remove"]:hover {
  opacity: 1;
}

[name="add"] {
  background: #efe;
  border: 1px solid green;
  border-radius: 0.2em;
  color: green;
  cursor: pointer;
  font-size: 120%;
  font-weight: bold;
  opacity: 0.5;
  overflow: hidden;
  padding: 0 0 0 1em;
  position: relative;
  width: 0em;
}

[name="add"]:before {
  content: "+";
  position: absolute;
  left: 24%;
}

JavaScript

(function () {

  let form = document.getElementById("lister");

  /* collect all remove buttons
   * and determine current counter value */
  let counter = 0;

  [].slice.call(
      document.querySelectorAll('#lister [name^="remove-"]')
  ).forEach(function (el) {
    let c = el.name.replace(/\D/g, "");
console.log("c: "+c);
    if (counter < c) {
        counter = c;
    }
  });

  // make <form> unsubmittable
  form.addEventListener(
      "submit",
    function (ev) {
      ev.stopPropagation();
      ev.preventDefault();
      return false;
    }
  );

  // only react on clicked buttons
  form.addEventListener(
    "click",
    function (ev) {

      // element is a <button>?
      if (ev.target.tagName
        && ev.target.tagName.match(/^button$/i)
      ) {

        // remove button?
        if (ev.target.name.match(/^remove-/)) {
          ev.target // <button>
          .parentNode // <li>
          .parentNode // <ul>
          .removeChild(ev.target.parentNode);
        }

        // add button?
        if (ev.target.name == "add") {
          let button = document.createElement("button");
          let input = form.querySelector('[name="new_li"]');
          let newLi = document.createElement("li");

          // add new <li> before our last one
          input
          .parentNode // <label>
          .parentNode // <li>
          .parentNode // <ul>
          .insertBefore(
            newLi,
            input.parentNode.parentNode
          );

          // insert data into new <li>
          newLi.appendChild(
            document.createTextNode(input.value  + " ")
          );

          button.appendChild(
            document.createTextNode("remove")
          );

          counter++;

          button.setAttribute(
            "name",
            "remove-" + counter
          );

          button.setAttribute(
            "title",
            "remove"
          );

          // insert a remove button
          newLi.appendChild(button);

  ...