First and last

by Dominic Myers

HTML

<table>
  <tbody id="body"></tbody>
</table>
<div id="formula"><hr/></div>

CSS

body {
  font-family: "Open Sans", sans-serif;
  line-height: 1.25;
}
table {
  border: 1px solid #ccc;
  border-collapse: collapse;
  margin: 0;
  padding: 0;
  width: 100%;
  table-layout: fixed;
}
table tr {
  background: #f8f8f8;
  border: 1px solid #ddd;
  padding: .35em;
}
table th,
table td {
  padding: .625em;
  text-align: center;
}
td.active{
  background: #eeeeee;
}

hr{
	border-top: 1px solid #8c8b8b;
}

JavaScript

const generateCell = (text, active) => {
	const cell = document.createElement("td");
  cell.textContent = text;
  active && cell.classList.add("active");
  return cell;
}
const generateRow = (f, a, b) => {
	const row = document.createElement("tr");
  row.append(generateCell("⇤", a === 1));
  row.append(generateCell("←", a === 1));
  for(let i = f; i < (f + b); i++){
  	row.append(generateCell(i, i === a));
  }
  row.append(generateCell("→", a === total));
  row.append(generateCell("⇥", a === total));
	return row;
};
const total = 12;
const table = document.getElementById("body");
const buttons = 5;
for(let active = 1; active <= total; active++){
	let first = (active <= Math.ceil(buttons / 2))  // =IF(LTE(A?, CEILING(DIVIDE(D2, 2))),
  ? 1                                             //   1,
  : (active + Math.floor(buttons / 2) > total)    //   IF(GT(ADD(A?, FLOOR(DIVIDE(D2, 2))), A14),
  	? (total - buttons) + 1                       //     ADD(MINUS(A14, D2), 1),
    : active - Math.floor(buttons / 2);           //     MINUS(A?, FLOOR(DIVIDE(D2,2)))))
	table.append(generateRow(first, active, buttons));
}

const formula = document.getElementById("formula");
for(let i = 3; i <= 14; i++){
	const pre = document.createElement("pre");
  pre.textContent = `=IF(LTE(A${i}, CEILING(DIVIDE(D2, 2))), 
  1, 
  IF(GT(ADD(A${i}, FLOOR(DIVIDE(D2, 2))), A14), 
    ADD(MINUS(A14, D2), 1), 
    MINUS(A${i}, FLOOR(DIVIDE(D2,2)))))`;
  formula.append(pre);
  formula.append(document.createElement("hr"));
}