reconcile ranges of children

by mindplay

HTML

<ul id="foods"></ul>

<label><input type="radio" name="list" value="fruit" checked>Fruit</label>
<br>
<label><input type="radio" name="list" value="meat">Meat</label>
<br>
<button id="shuffle">Shuffle</button>
<button id="reverse">Reverse</button>
<br>
<button id="rotate-up">Rotate Up</button>
<button id="rotate-down">Rotate Down</button>
<br>
<button id="add-first">Add First</button>
<button id="add-last">Add Last</button>
<button id="add-random">Add Random</button>
<br>
<button id="delete-first">Delete First</button>
<button id="delete-last">Delete Last</button>
<button id="delete-random">Delete Random</button>

JavaScript

const fruit = "Pear|Apple|Cherry|Plum|Peach".split("|").map(newLI);
const meat = "Beef|Chicken|Lamb|Turkey|Fish".split("|").map(newLI);

let children = { fruit, meat };
let anchors = {
	fruit: document.createComment("<end of fruit>"),
  meat: document.createComment("<end of meat>")
}

let list = "fruit";

const parent = document.querySelector("#foods");

fruit.forEach(node => parent.appendChild(node));
parent.appendChild(anchors.fruit);

meat.forEach(node => parent.appendChild(node));
parent.appendChild(anchors.meat);

console.clear();

function newLI(text) {
  let el = document.createElement("li");
  el.innerText = text;
  return el;
}

function shuffle(a) {
  return a.map(n => [Math.random(), n]).sort().map(n => n[1]);
}

function rotate(arr, count) {
  arr = arr.slice();
  count -= arr.length * Math.floor(count / arr.length);
  arr.push.apply(arr, arr.splice(0, count));
  return arr;
}

const splice = (a,index,count,...items) => {
  a = a.slice();
  a.splice(index, count, ...items);
  return a;
}

const reverse = a => {
	a = a.slice();
  return a.reverse();
};

let num = 1000;

const randomIndex = a => Math.floor((a.length-1) * Math.random());

const addFirst = a => [newLI(num++)].concat(...a);
const addLast = a => a.concat(newLI(num++));
const addRandom = a => splice(a, randomIndex(a), 0, newLI(num++));

const deleteFirst = a => splice(a, 0, 1);
const deleteLast = a => splice(a, a.length-1, 1);
const deleteRandom = a => splice(a, randomIndex(a), 1);

const update = fn => () => {
  children[list] = diff(
  	parent,
    children[list],
    fn(children[list]),
    anchors[list]
  );
}

document.querySelectorAll("input[name=list]").forEach(input => {
	input.addEventListener("input", () => { list = input.value })
});
document.querySelector("#shuffle").addEventListener("click", update(shuffle));
document.querySelector("#reverse").addEventListener("click", update(reverse));
document.querySelector("#rotate-up").addEventListener("click", update(a => rotate(a,...