Подтвердить что ты не робот

JavaScript конвертирует положение мыши в диапазон выбора

Я хотел бы иметь возможность конвертировать текущую позицию мыши в диапазон, в частности, в CKEditor.

CKEditor предоставляет API для установки курсора в соответствии с диапазоном:

var ranges = new CKEDITOR.dom.range( editor.document );
editor.getSelection().selectRanges( [ ranges ] );

Поскольку CKEditor предоставляет этот API, проблему можно упростить, удалив это требование и просто найдя способ создания диапазона от координат мыши по div, содержащему различные элементы HTML.

Однако это не то же самое, что преобразование координаты мыши в позицию курсора в текстовом поле, поскольку в текстовых средах есть фиксированные ширины столбцов и высоты строк, где CKEditor отображает HTML через iframe.

Основываясь на этом, похоже, что диапазон может применяться к элементам.

Как бы вы определили диапазон начала и конца, который ближе всего к текущей позиции мыши?

Изменить: Пример того, как можно использовать API-интерфейс ckeditor для выбора диапазона в событии mouseup.

editor.document.on('mouseup', function(e) {
    this.focus();
    var node = e.data.$.target;

    var range = new CKEDITOR.dom.range( this.document );
    range.setStart(new CKEDITOR.dom.node(node), 0);
    range.collapse();

    var ranges = [];
    ranges.push(range);
    this.getSelection().selectRanges( ranges );
});

Проблема с приведенным выше примером заключается в том, что целевой объект node (e.data. $. target) запускается только для таких узлов, как HTML, BODY или IMG, но не для текстовых узлов. Даже если бы это было так, эти узлы представляли фрагменты текста, которые не поддерживали бы установку курсора на позицию мыши внутри этого фрагмента текста.

4b9b3361

Ответ 1

То, что вы пытаетесь сделать, действительно сложно в браузере. Я не знаком с ckeditor в частности, но обычный javascript позволяет вам выбирать текст, используя диапазон, поэтому я не думаю, что он добавляет ничего особенного. Вы должны найти элемент браузера, который содержит клик, а затем найти символ внутри элемента, который был нажат.

Обнаружение элемента браузера - это простой бит: вам нужно либо зарегистрировать обработчик на каждом элементе, либо использовать целевое поле события. Существует много информации об этом, задайте более конкретный вопрос о stackoverflow, если это связано с тем, с чем вы столкнулись.

Когда у вас есть элемент, вам нужно выяснить, какой символ в элементе был нажат, а затем создать соответствующий диапазон, чтобы поместить туда курсор. Как сообщение, которое вы связали с заявленным, варианты браузера делают это очень трудно. Эта страница немного устарела, но имеет хорошее обсуждение диапазонов: http://www.quirksmode.org/dom/range_intro.html

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

Я никогда не видел полного решения этого в javascript. Несколько лет назад я работал над одним, но я не придумал ответ, которым я был доволен (некоторые действительно тяжелые случаи). Подход, который я использовал, был ужасным взломом: вставка охватывает текст, а затем использует их для выполнения двоичного поиска, пока вы не найдете наименьший возможный диапазон, содержащий щелчок мышью. Пробелы не меняют макет, поэтому вы можете использовать свойства span position_x/y, чтобы узнать, что они содержат щелчок.

например. предположим, что у вас есть следующий текст в node:

<p>Here is some paragraph text.</p>

Мы знаем, что клик был где-то в этом абзаце. Разделите абзац пополам с помощью span:

<p><span>Here is some p</span>aragraph text.</p>

Если диапазон содержит координаты щелчка, продолжайте бинарный поиск в этой половине, в противном случае выполните поиск во второй половине.

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

С тех пор, как я работал над этим браузером, вы намного быстрее. Они, вероятно, достаточно быстр, чтобы добавить вокруг каждого персонажа, затем вокруг каждого двух символов и т.д., Чтобы создать двоичное дерево, которое легко найти. Вы можете попробовать этот подход - это упростит работу над той линией, над которой вы работаете.

TL; DR это очень трудная проблема, и если есть ответ, возможно, вам не стоит придумывать его.

Ответ 2

Есть два способа сделать это, как и каждый WYSIWYG.

Во-первых:  - вы сдаетесь, потому что это слишком сложно, и в конечном итоге это станет убийцей браузера;

Во-вторых:  - вы пытаетесь разобрать текст и помещать его в точное место в полупрозрачной текстовой области или div над оригиналом, но здесь у нас есть две проблемы:

1), как бы вы разобрали динамические куски данных, чтобы получить только текст и убедиться, что вы сопоставили его с точным положением фактического содержимого.

2), как бы вы решили обновление для синтаксического анализа для каждого символа штопа, который вы вводите, или любого действия, которое вы выполняете в редакторе.

В конце концов, это просто "жестокая одиссея на темную сторону дерева DOM", но если вы выберете второй способ, то код из вашего сообщения будет работать как шарм.