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
...