stack2

by Julian

HTML

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Word Index Tracker</title>
    <style>
       :root {
  font: 2ch/1.5 "Segoe UI"
}

#toggle {
  margin-bottom: 1rem;
  padding: 5px 10px;
  border-radius: 8px;
  font: inherit;
  cursor: pointer;
  background: 
  radial-gradient(
    ellipse at center,    
    rgba(197,222,234,1) 0%,
    rgba(138,187,215,1) 31%,
    rgba(6,109,171,1) 100%);
}

#toggle::before {
  content: "Edit Mode"
}

#toggle::after {
  content: " ON";
}

#toggle.off {
  color: #fff;
  background: 
  radial-gradient(
    ellipse at center,
    rgba(125, 126, 125, 1) 0%, 
    rgba(14, 14, 14, 1) 100%);
}

#toggle.off::after {
  content: " OFF";
}

.off + #source {
  opacity: 0.7;
  pointer-events: none;
}

#source {
  min-height: 5rem;
  padding: 0.75rem;
  border: 1px solid #ccc;
  border-radius: 4px;
  width: 100%;
  overflow-wrap: break-word;
  white-space: pre-wrap;
}

mark {
  background-color: transparent
}

mark.highlight {
  background: gold;
}
    </style>
</head>
<body>
    <h1>Track Words</h1>
   <form id="indexer">
  <button id="toggle" class="off" type="button"></button>
  <textarea id="source" style="min-height: 5rem; padding: 0.75rem; border: 1px solid #ccc; border-radius: 4px; width: 100%;" placeholder="Enter or paste text here..."></textarea>
  <output id="selected">
    <ol></ol>
  </output>
  <button id="download" type="button">Download JSON</button>
</form>
 </body>
</html>

CSS

:root {
  font: 2ch/1.5 "Segoe UI"
}

#toggle {
  margin-bottom: 1rem;
  padding: 5px 10px;
  border-radius: 8px;
  font: inherit;
  cursor: pointer;
  background: 
  radial-gradient(
    ellipse at center,    
    rgba(197,222,234,1) 0%,
    rgba(138,187,215,1) 31%,
    rgba(6,109,171,1) 100%);
}

#toggle::before {
  content: "Edit Mode"
}

#toggle::after {
  content: " ON";
}

#toggle.off {
  color: #fff;
  background: 
  radial-gradient(
    ellipse at center,
    rgba(125, 126, 125, 1) 0%, 
    rgba(14, 14, 14, 1) 100%);
}

#toggle.off::after {
  content: " OFF";
}

.off + #source {
  opacity: 0.7;
  pointer-events: none;
}

#source {
  min-height: 5rem;
  padding-top: 0.75rem;
  border-radius: 4px;
}

mark {
  background-color: transparent
}

mark.highlight {
  background: gold;
}

JavaScript

// Reference <form>
const form = document.forms.indexer;
/**
 * Reference all form controls of <form>
 * In this layout it is:
 *   - <button>
 *   - <textarea>
 *   - <output>
 */
const io = form.elements;
// Reference <button>
const btn = io.toggle;
const downloadBtn = document.getElementById("download");
// Reference <textarea>
const src = document.getElementById("source");
// Reference <output>
const sel = io.selected;
// Declaration for two arrays (not made yet).
let marked;
let indices;

/**
 * Index each word by extracting the string,
 * converting the string into an array of 
 * substrings, and wrapping each word with
 * a <mark> element. Each <mark> is then 
 * assigned a [data-idx] attribute with the 
 * corresponding index number.
 */
const indexText = () => {
  const text = src.value;
  let marks = text.split(" ");
  marks[0] = `<mark>${marks[0]}`;
  marks[marks.length - 1] = `${marks[marks.length - 1]}</mark>`;
  const outputHTML = marks.join(`</mark> <mark>`).trim();
  const tempDiv = document.createElement("div");
  tempDiv.innerHTML = outputHTML;
  marked = [...tempDiv.querySelectorAll("mark")];
  marked.forEach((mrk, idx) => mrk.dataset.idx = idx);
  src.value = tempDiv.textContent; // Update text area with raw text.
};

/**
 * Handle "click" event when the user clicks
 * button#toggle. Enables indexing for textarea content.
 * @param {object} e - Event object
 */
const editText = (e) => {
  e.target.classList.toggle("off");
  indexText();
};

/**
 * Handle "click" event for the download button.
 * Creates a JSON file containing the highlighted
 * words and their indices and triggers download.
 */
const downloadJSON = () => {
  const data = JSON.stringify(indices, null, 2);
  const blob = new Blob([data], { type: "application/json" });
  const url = URL.createObjectURL(blob);

  const a = document.createElement("a");
  a.href = url;
  a.download = "words_indices.json";
  document.body.appendChild(a);
  a.click();
  document.body.removeChild(a);
 ...