Как получить выделенный текст, но я могу получить окружающий контекст в JavaScript? - PullRequest
2 голосов
/ 02 декабря 2010

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

function getSelected() {
  var userSelection;
  if (window.getSelection) {
      selection = window.getSelection();
  } else if (document.selection) {
      selection = document.selection.createRange();
  }

}

Можно ли получить слова вокруг выбранное слово.

Возьмем, к примеру, такие предложения: «Если вам нужно подставить zartbox, то вы должны купить красный виджет. В противном случае вы можете купить синий виджет и сэкономить немного денег.»скажет мне, если человек выбрал слово "виджет".Но я хотел бы знать, если выбор после «красный» или «синий».Это возможно?Я искал в Интернете некоторые советы, и у меня возникли проблемы с поиском ответа.

спасибо за вашу помощь

Ответы [ 3 ]

2 голосов
/ 02 декабря 2010

Способ сделать это в браузерах, отличных от 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 .

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

Я написал быстрый скрипт, который может идентифицировать деталь до и после выбора внутри одного и того же элемента DIV.

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

В любом случае, вы можете увидеть / скопировать / протестировать код здесь: http://jsfiddle.net/kvHxJ/ просто выберите что-то и увидите предупреждение.

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

0 голосов
/ 02 декабря 2010

IE имеет набор move методов, который уменьшает эту проблему до пары строк, чтобы расширить выделение вперед или назад на любое количество слов (см. http://www.webreference.com/js/column12/trmethods.html). Оттуда, это просто вопрос Сравнение текста с любым произвольным списком значений. Другие браузеры не имеют этой возможности AFAIK. Судьба войн браузеров: один разрабатывает потрясающую функцию, которая игнорируется или запрещается патентом от любых других, поэтому эта функция навсегда теряется и ее избегают как бремя кросс-браузерная поддержка всех этих нововведений неизбежно ложится прямо на дизайнеров сайтов.

Итак, ниже приведена обобщенная функция, позволяющая получить только идентификатор родительского элемента выделенного текста. И, чтобы работать с этим кросс-браузерным решением, вы должны обернуть каждое слово в отдельный элемент с уникальным идентификатором или другим атрибутом. При такой настройке это должен быть относительно безболезненный переход к взгляду вперед и назад на одноуровневых или последовательно идентифицированных / именованных элементов.

Подвох здесь в том, что клиент должен щелкнуть / перетащить от начала слова или фразы до конца, и абсолютно без граничных пробелов. Даже двойной щелчок по слову заставит его ссылаться на следующий элемент (или, в случае IE, родительский DIV). Кроме того, вы должны добавить код, чтобы ограничить границу выделения одним родительским DIV, так как приведенный ниже код может также расширить выбор до окружающих элементов. Но, надеюсь, вы можете исправить это отсюда. В противном случае это зависит от использования векторов для точного определения координат текста по сравнению со всем окружающим текстом.


<script type="text/javascript">

function get_selected_element_id() {
 if (window.getSelection) {
  // FF
  var range = window.getSelection();
  }
 else if (document.selection) {
  // IE
  var range = document.selection.createRange();
  }
 if (range.focusNode) {
  // FF
  var test_value = range.focusNode.parentNode.id;
  }
 else {
  // IE
  var test_value = range.parentElement().id;
  }
 return test_value;
 }


</script>

</head>

<body>

<div id="test_div">
 <span id="test1">test</span> <span id="test2">asdf</span> <span id="test3">test2</span> <span id="test4">bla</span>
 </div>

<button onclick="alert(get_selected_element_id());">go</button>



...