Как получить выделенный текст, но я могу получить окружающий контекст в JavaScript?
Я могу захватить текст, который пользователь выбрал на веб-странице, используя этот код:
function getSelected() {
var userSelection;
if (window.getSelection) {
selection = window.getSelection();
} else if (document.selection) {
selection = document.selection.createRange();
}
}
это возможно для меня, чтобы получить слова вокруг выбранного слова.
Возьмем, к примеру, такие предложения: "Если вам нужно подставить zartbox, то вы должны купить красный виджет. В противном случае вы можете купить синий виджет и сэкономить немного денег".
Мой код скажет мне, если человек выбрал слово "виджет". Но я хотел бы знать, если выбор после "красный" или "синий". Это возможно? Я искал в Интернете некоторые советы, и у меня возникли проблемы с поиском ответа.
Спасибо за помощь
3 ответа
Я написал быстрый скрипт, который может идентифицировать деталь до и после выбора внутри одного и того же элемента DIV.
Однако, если один и тот же DIV содержит одно и то же слово более одного раза, и вы выбираете только это слово, текущий код, который я написал, не может определить, является ли оно первым или вторым выбранным словом, поэтому нижняя строка не будет отвечать вашим потребностям.
В любом случае, вы можете увидеть / скопировать / протестировать код здесь: http://jsfiddle.net/kvHxJ/ просто выберите что-то и увидите предупреждение, которое появляется.
Если этого все-таки достаточно для ваших нужд, тогда отлично, примите этот ответ и двигайтесь дальше... в противном случае мне нужно знать: можем ли мы предположить, что пользователь выберет только целые слова, только одно слово? Если ответ да, у меня есть идея, как обойти это.
Способ сделать это в браузерах не IE состоит в том, чтобы получить Range
объект из выбора. Диапазон имеет начальную и конечную границы, и каждая граница диапазона выражается как смещение внутри узла; если граница находится внутри текстового узла, это смещение будет смещением символа.
Например, если ниже был текстовый узел, а выделение разделено трубами:
"red |widget| blue widget"
... тогда диапазон, который вы получите из выделения, будет иметь начальное смещение 4 в текстовом узле.
Следующее даст вам Range, представляющий выделение, и предупредит начальную границу:
var sel = window.getSelection();
var selectedRange = sel.rangeCount ? sel.getRangeAt(0) : null;
if (range) {
alert("Offset " + selectedRange.startOffset
+ " in node " + selectedRange.startContainer.nodeName);
}
Диапазоны можно сравнить с другими диапазонами, поэтому, если вы хотите узнать, например, был ли текущий выбор после слова "синий" в вышеприведенном текстовом узле, вы можете создать диапазон, охватывающий слово "синий", и сравнить его с выбранный диапазон:
// Assume the text node is stored in a variable called textNode
var blueRange = document.createRange();
blueRange.setStart(textNode, 11);
blueRange.setEnd(textNode, 15);
var selectionIsAfterBlue =
(selectedRange.compareBoundaryPoints(Range.END_TO_START, blueRange) == 1);
В IE ничего из этого не работает, и все делается по-другому, как правило, с гораздо большими трудностями. Чтобы нормализовать это для единого согласованного интерфейса, вы можете использовать мою библиотеку Rangy.
IE имеет move
набор методов, который уменьшает эту проблему до пары строк, чтобы расширить выделение вперед или назад на любое количество слов (см. http://www.webreference.com/js/column12/trmethods.html). Оттуда, это просто вопрос сравнения текста с любым произвольным списком значений. Другие браузеры не имеют эту функцию AFAIK. Судьба войн браузеров: у каждого развивается удивительная функция, которая игнорируется или запрещается патентом от любой другой, так что эта функция навсегда теряется и ее избегают, поскольку бремя кросс-браузерной поддержки всех этих нововведений неизбежно ложится прямо на дизайнеров веб-сайтов.
Итак, ниже приведена обобщенная функция, позволяющая получить только идентификатор родительского элемента выделенного текста. И, чтобы работать с этим кросс-браузерным решением, вы должны обернуть каждое слово в отдельный элемент с уникальным идентификатором или другим атрибутом. С этой настройкой, это должно быть относительно безболезненным переходом к просмотру вперед и назад в элементах родственного или последовательного идентификатора / именования.
Уловка здесь в том, что клиент должен щелкнуть / перетащить от начала слова или фразы до конца, и абсолютно без граничных пробелов. Даже двойной щелчок по слову заставит его ссылаться на следующий элемент (или, в случае IE, родительский DIV). Кроме того, вы должны добавить код, чтобы ограничить границу выделения одним родительским DIV, так как приведенный ниже код может также расширить выбор до окружающих элементов. Но, надеюсь, вы можете исправить это отсюда. Иначе, это до использования векторов, чтобы точно определить координаты текста по сравнению со всем окружающим текстом.