Перетаскивание выделенного текста для копирования / перемещения внутри веб-страницы? - PullRequest
1 голос
/ 23 февраля 2020

Я хотел бы повторить поведение перетаскивания выделенного текста, чтобы переместить его в / в текстовый ввод или текстовую область на веб-странице.

Я хотел бы знать, возможно ли это (используя перетаскивание выделенной кнопкой мыши) на:

  1. копирование / перемещение выделенного текста из одного ввода текста в другой
  2. копирование / перемещение выделенного текста в пределах ввод в другую позицию
  3. копирование / перемещение выделенного текста из заголовка / абзаца (т.е. без ввода) во ввод / текстовую область.
  4. заполняет перетаскиваемый текст программно использование javascript
  5. (Бонус: копирование / перемещение выделенного текста во внешнюю программу)

например, зеленая стрелка демонстрирует работающее поведение, однако я бы хотел заставить его работать на веб-странице (красная стрелка).

enter image description here

Все предложения Google, которые я нашел до сих пор, относятся к перетаскивание HTML элементов, а не текста.

Я использую chrome, но бонусные баллы, если это кросс-браузерное решение на. Не против, если решение будет HTML, CSS или javascript.

Аналогичный вопрос , но для визуального кода студии - не веб-страница.

** ОБНОВЛЕНИЕ **

Я чувствую себя глупо (но я буду винить юзабилити). Если я выделю текст, убедится, что мышь не двигается и не щелкнет, ТО затем перетащите мышку , точки 1-3 будут работать, как ожидается, и перетащите выделенный текст. (Моя проблема, которую я подозреваю, состоит в том, что я был нетерпелив, и тонкое движение мыши, прежде чем нажать, чтобы перетащить.) Ответ

@ cjl750 все еще остается. Я изменил вопрос, чтобы сосредоточиться на пункте 4.

1 Ответ

1 голос
/ 23 февраля 2020

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

Есть две части этого. Во-первых, вы можете получить текущий выделенный текст с помощью window.getSelection(). Сложность в том, что вам нужно выяснить, что находится под вашим курсором, когда вы закончите перетаскивать этот текст куда-нибудь. Решение о том, как это сделать, было взято из Решение № 2 для этого ответа .

Мы хотим использовать document.caretPositionFromPoint(), но это новое имя для метода, который так поддерживается только в Firefox. Поэтому, используя простое выражение if / else из MDN , мы можем охватить все, кроме IE, что я и делаю в приведенном ниже фрагменте. Более полное решение, включающее поддержку IE, можно найти в другой ссылке. Стратегия

Basi c:

  1. на mousedown, проверьте выделенный текст
  2. если у нас есть какой-то выделенный текст, прослушайте событие dragend
  3. , предполагая, что мы прекратили перетаскивание поверх текстового узла, проверьте положение курсора в этом узле с помощью document.caretPositionFromPoint() или document.caretRangeFromPoint()
  4. используя позицию каретки из # 3, а также положение выделенного текста в пределах его большей строки, нарежьте наши строки и выведите результат

(() => {
  document.addEventListener('mouseup', checkForSelection);

  let textBeingDragged;
  let originalNode

  function checkForSelection(event) {
    const selection = window.getSelection();
    const selectedText = selection.toString();
    if (selectedText) {
      originalNode = selection.anchorNode.parentNode;
      textBeingDragged = selectedText;
      document.addEventListener('dragend', handleDragEnd);
    }
  }
  
  function handleDragEnd(event) {
    const charRange = getCharPosition(event);
    const elemDrugOver = charRange.endContainer;
    if (elemDrugOver.nodeType === 3) {
      const offset = charRange.startOffset;
      const startText = elemDrugOver.wholeText.slice(0, offset);
      const endText = elemDrugOver.wholeText.slice(offset);
      elemDrugOver.textContent = `${startText}${textBeingDragged}${endText}`;
      
      const origText = originalNode.textContent;
      const indexOfSelection = origText.indexOf(textBeingDragged);
      const origStartText = origText.slice(0, indexOfSelection);
      const origEndText = origText.slice(offset + textBeingDragged.length);
      originalNode.textContent = `${origStartText}${origEndText}`;

      textBeingDragged = undefined;
      originalNode = undefined;
    }
    document.removeEventListener('dragend', handleDragEnd);
  }
  
  function getCharPosition(event) {
    if (document.caretPositionFromPoint) {
      return document.caretPositionFromPoint(event.clientX, event.clientY);
    } else if (document.caretRangeFromPoint) {
      return document.caretRangeFromPoint(event.clientX, event.clientY);
    }
    return false;
  }
})();
<h1>This is a (try to move me) header</h1>
<h2>This is another header</h2>

Я оставлю вам возможность добавлять любые улучшения, которые вы хотите, но это должно дать вам 95% пути как минимум.

...