Определить индекс позиции символа в элементе HTML при нажатии - PullRequest
16 голосов
/ 12 ноября 2011

У меня есть элемент HTML с видимым текстом внутри.Этот пример является элементом <div>, но это может быть элемент <span>, <p> или другой элемент DOM.

<div>This is a simple example.</div>

При нажатии я могу получить положение курсора на поверхности div, но мне нужно определить положение ближайшего символа и / или его индекса в строке div.innerHTML ввремя щелчка.

Я нашел похожую реализацию в методе "getCharNumAtPosition" в текстовых объектах SVG здесь .

Возможно ли реализовать такую ​​функцию вJavaScript, который работает с HTML?

(Решения были бы наиболее полезны, если бы они были переносимыми для большинства современных браузеров, работали с большинством письменных языков и основывались на относительно стабильных стандартах, чтобы впоследствии они не вызывали ошибок).

Ответы [ 4 ]

11 голосов
/ 12 ноября 2011
$('div').click( function () {
  getSelectionPosition (); 
});


function getSelectionPosition () {
  var selection = window.getSelection();
  console.log(selection.focusNode.data[selection.focusOffset]);
  alert(selection.focusOffset);
}

Это работает как с «щелчком», так и с «диапазоном» для большинства браузеров. (selection.type = "caret" / selection.type = "range").

selection.focusOffset() дает вам позицию во внутреннем узле . Если элементы являются вложенными, например, внутри тегов <b> или <span>, это даст вам положение внутри внутреннего элемента, а не полный текст, более или менее. Я не могу "выбрать" первую букву вложенного тега с focusOffset и типом "каретка" (нажмите, а не выберите диапазон). Когда вы нажимаете на первую букву, она дает позицию последнего элемента перед началом тега плюс 1. Когда вы нажимаете на вторую букву, она правильно дает вам «1». Но я не нашел способа получить доступ к первому элементу (смещение 0) подэлемента. Этот материал "выбора / диапазона" кажется ошибочным (или очень не интуитивным для меня). ^^

Но использовать его без вложенных элементов довольно просто! (Отлично работает с вашим <div>)

Вот скрипка

Важное редактирование 2015-01-18:

Этот ответ сработал, когда он был принят, но больше не по причинам, указанным ниже. Другие ответы сейчас наиболее полезны.

  • Общий ответ Мэтью
  • Рабочий пример, предоставленный Дугласом Дасико.

В Firefox и Chrome отлажено поведение window.getSelection(). К сожалению, теперь это бесполезно для этого варианта использования. (Чтение документации, IE 9 и выше, должны вести себя одинаково).

Теперь середина символа используется для определения смещения. Это означает, что нажатие на персонажа может дать 2 результата. 0 или 1 для первого символа, 1 или 2 для второго и т. Д.

Я обновил пример JSFiddle .

Обратите внимание, что если вы измените размер окна ( Ctrl + мышь), поведение в Chrome будет несколько ошибочным для некоторых кликов.

2 голосов
/ 12 ноября 2011

Вы можете, используя JavaScript, разбить каждый символ на собственный тег SPAN и добавить событие onclick для каждого.Затем прочитайте положение x, y из данных события при нажатии кнопки SPAN.

Также у вас будет доступ к персонажу, по которому щелкнул файл event.target.innerHTML

1 голос
/ 02 декабря 2018

Во многих случаях возможным решением может быть добавление символа пробела нулевой ширины (U + 200B) между каждым символом содержимого тега.Затем, используя javascript window.getSelection().focusOffset +, можно выполнить несколько простых вычислений.

Образец HTML-кода (включая символы пробела нулевой ширины):

<div onclick='magic(this)'>T​h​i​s​ ​i​s​ ​a​ ​s​i​m​p​l​e​ ​e​x​a​m​p​l​e​.</div>

Образец кода JavaScript:

<script>
    function magic(e)
    {
        var s, p, c;
        s = e.innerHTML;
        p = window.getSelection().focusOffset;
        c = s.charAt((p >> 1) << 1);
        alert("index:" + (p >> 1) + " char: " + c);
    }
</script>

Кажется, работает широко, даже на Internet Explorer!

jsFidle: http://jsfiddle.net/by1a9pfm/

1 голос
/ 21 января 2017

Этот пример - быстрая загрузка для блоков текста среднего размера, переносимых и надежных.Хотя его элегантность не сразу очевидна, надежность заключается в создании простого однозначного соответствия между международными персонажами и слушателями событий DOM 1 .

Лучше всего полагаться только на широко принятыестандарты кодировки символов, DOM и ECMA, как в этом примере.Другие подходы часто основаны на низкоуровневых целевых атрибутах событий или функциях, таких как getSelection (), которые не стабильны во времени и не переносимы между браузерами и языками 2 .

Пример кода можно изменить вряд способов для конкретных применений.Например, другие механизмы могут быть использованы для выбора того, какие объекты DOM инициализируются для обратных вызовов charClick.Суррогатные пары также могут поддерживаться в цикле i.

  <!DOCTYPE html>
  <html lang="en">
  <head>
      <meta charset="utf-8">
      <title>Character Click Demo</title>
      <script type='text/javascript'>
          var pre = "<div onclick='charClick(this, ";
          var inf = ")'>";
          var suf = "</div>"; 
          function charClick(el, i) {
              var p = el.parentNode.id;
              var s = "para '" + p + "' idx " + i + " click";
              ele = document.getElementById('result');
              ele.innerHTML = s; }
          function initCharClick(ids) {
              var el; var from; var length; var to; var cc;
              var idArray = ids.split(" ");
              var idQty = idArray.length;
              for (var j = 0; j < idQty; ++ j) {
                  el = document.getElementById(idArray[j]);
                  from = unescape(el.innerHTML);
                  length = from.length;
                  to = "";
                  for (var i = 0; i < length; ++ i) {
                      to = to + pre + i + inf + from.charAt(i) + suf;
                  el.innerHTML = to; } }
      </script>
      <style>
          .characters div {
              padding: 0;
              margin: 0;
              display: inline }
      </style>
  </head>
  <body class='characters' onload='initCharClick("h1 p0 p2")'>
      <h1 id='h1'>Character Click Demo</h1>
      <p id='p0'>Test &#xE6;&#x20AC; &ndash; &#xFD7;&#xD8; &mdash; string.</p>
      <p id='p1'>Next ? ?E para.</p>
      <p id='p2'>&copy; 2017</p>
      <hr>
      <p id='result'>&nbsp;</p>
  </body>
  </html>

Рекомендуется провести полное тестирование перед использованием в интернационализированных производственных сценариях.Если найдены ошибки, предложите изменить или добавить комментарии, чтобы можно было добавить уточнения.


Примечания

[1] Эти прослушиватели событий могли быть добавленынапрямую, но потребовалось бы ветвление для переносимости браузера или дополнительный вес библиотек, которые не добавляют никакой конкретной скорости или удобства для этого варианта использования.

[2] См. примечания о событиях выбора на странице событий пользовательского интерфейса W3C.

...