Как выбрать Selection, полученный из вызова .getSelection () после того, как он был сохранен в массиве - PullRequest
0 голосов
/ 24 апреля 2019

Я пытаюсь создать небольшой скрипт, который я мог бы использовать для простой маркировки (выделения) текста на любой странице, которую можно использовать для изучения (цифровая версия выделения текста в книге желтым маркером).

У меня не так много знаний о функции .getSelection () и о том, как поэкспериментировать с выбором и диапазоном, которые вы получаете из нее, поэтому я надеюсь, что кто-то здесь может мне помочь.

Вот некоторые изображения, показывающие и, я надеюсь, объясняющие, что я пытаюсь выполнить.

Первое изображение объяснения

Второе изображение объяснения

Третье объяснительное изображение

Четвертое пояснительное изображение

Вот мой код сценария.Я относительно новичок в кодировании JS, и я делаю это в основном для практики и развлечения, поэтому мне жаль, если какой-то код плохо выглядит:

https://codepen.io/MathiasWP/pen/axREWb

// The pop-up box is created from scratch here in JS
const mainText = `
<p>Export</p>
<h2>Marked elements:</h2>
 <span class="marked"></span>`;

const popup = document.createElement("div");

setTimeout(() => {
  document.body.appendChild(popup);

  // Pop-up box gets some preset text
  popup.innerHTML = mainText;
}, 200);


// Styling of the pop-up box
popup.style.visibility = "hidden";
popup.style.width = "300px";
popup.style.position = "fixed";
popup.style.zIndex = "100";
popup.style.bottom = "0";
popup.style.right = "0";
popup.style.marginRight = "10px";
popup.style.color = "white";
popup.style.backgroundColor = "#282c34";
popup.style.padding = "20px";
popup.style.borderRadius = "15px 15px 0px 0px";
popup.style.maxHeight = "400px";
popup.style.overflowY = "scroll";
popup.style.fontFamily = '"Trebuchet MS", Helvetica, sans-serif';

// The selected text gets set to the variable
let selection = window.getSelection();

// Array where all selected text will be stored
const selected = [];

// Variable that stores all of the text on the entire page as a string
setTimeout(() => {
  const pageText = document.body.innerText.toString();
}, 200);

mouseUp = e => {
  // If nothing is selected, return
  if (selection.isCollapsed) return;
  //Kind of a bug fix, where if the marked text is 100% equal the last selected then it also will return (this fixed a small bug where if you marked a text and clicked on the screen it would be stored again)
  else if (selection.toString() === selected.slice(-1)[0]) {
    return;
  }
  // Here's where all the fun begins
  else {
    // If selected text is just whitespace then nothing happens (just for practical use)
    if (!selection.toString().replace(/\s/g, "").length) return;
    else {
      if (!e) e = window.event;
      // If command/ctrl button is held when text is marked, the function will run the main stuff
      if (e.metaKey) {
        // Just an awkard way to make the popup show up when text has been marked, could find a better way to to this but i'm lazy right now
        popup.style.visibility = "visible";

        // The selected text gets pushed to the selected-text-array
        selected.push([
          selection,
          selection.toString(),
          selection.anchorOffset,
          selection.focusOffset,
          selection.getRangeAt(0)
        ]);

        // Design Mode gets turned on, found this was the easiest way to highlight the selected text on the page
        document.designMode = "on";

        // Where the selected text gets the background-color changed
        // The color of selected text in Google Chrome is #bad6fb. That one can also be used (looks kinda cool).
        document.execCommand("backColor", false, "yellow");

        // Design mode gets turned off
        document.designMode = "off";

        console.log(selection);
        console.log(selection.getRangeAt(0));

        console.log(selected);

        // Runs the function that writes everything in the pop-up box
        updateBox();

      }
    }
  }
};

// Function that removes the chosen element in the list. Could've made everything prettier and easier with for example jQuery, but decided to make everything pure vanilla JS
removeMark = element => {

  let thisElement = [selected[element.id.replace("marked-id-", "")][0], selected[element.id.replace("marked-id-", "")][4]];

  console.log(thisElement);


node = thisElement[1].startContainer;

if (document.body.createTextRange) {
    const range = document.body.createTextRange();
    range.moveToElementText(node);
    range.select();
} else if (window.getSelection) {
    const selection = thisElement[0];
    const range = thisElement[1];
    range.selectNodeContents(node);
    selection.removeAllRanges();
        selection.addRange(range);
} else {
    console.warn("Could not select text in body: Unsupported browser.");
}

  // Desin mode ON
  document.designMode = "on";

  // Removes selected color

  //document.execCommand("backColor", false, "pink");

  // Design mode OFF
  document.designMode = "off";

  // Removes the element from the selected-text array
  selected.splice(thisElement, 1);

  // Runs function that writes what should be in the box (doing this everytime to update the id's of the other elements in the box when something gets removed)
  updateBox();

  // Hides the pop-up box if nothing selected (used to remove the pop-up box if everything in it is removed by the user)
  if (selected.length === 0) {
    popup.style.visibility = "hidden";
  }
};


updateBox = () => {
   // Awkward way to make all the selected text displayed in the pop-up box. First everything gets removed and set to start...
   popup.innerHTML = mainText;

  // ... and then every element gets inserted adjacently after each other
  selected.forEach(el =>
  document
    .querySelector(".marked")
    .insertAdjacentHTML(
      "beforeend",
      `<span><br><b>-</b> ${
        el[1]
      } <p style="color:red;cursor:pointer" id="marked-id-${selected.indexOf(el)}" onclick="removeMark(this); return false;">(remove)</p><br></span>`
    )
);
}

// Part of the script that actually makes everything happen after mouse is no longer held down
window.addEventListener("mouseup", mouseUp);

Я также столкнулся с некоторыми другими проблемами.Например, когда я пытаюсь выделить предыдущий текст (как видно на рисунке 4), иногда выделяется весь абзац.Также еще одна ошибка, с которой я столкнулся, это когда я консольный журнал "thisElement", тогда изменяются переменные baseNode, anchorNode, endContainer и т.д.Я действительно не знаю, почему это изменилось, поскольку оно просто сохраняется в «выбранном» массиве, но, пожалуйста, объясните, почему это происходит, если кто-то знает:)

...