2013-12-15 5 views
0

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

С помощью двойного щелчка я могу определить текст слова, но я не могу ничего сделать с самим словом на странице. В принципе, я хочу обернуть выделенный текст тегом span, чтобы я мог позиционировать вещи относительно него. Я видел, как это делалось раньше с помощью маркеров, но я не знаю, как это сделать.

Примечание: это должно работать только в Firefox.

+1

Я, вероятно, может помочь, но нужно больше информации. Во-первых, вы хотите добавить эти возможности к существующим веб-страницам или это ваша собственная веб-страница. Конечно, это имеет большое значение;) Кроме того, если вы можете опубликовать скрипку (fiddlejs.net), которая иллюстрирует то, что вы пытаетесь выполнить, это также может помочь. На первый взгляд, кажется, что делегирование событий и ленивая загрузка - ваш друг. –

+0

Это для существующих веб-страниц (это аддон Firefox). – Ian

ответ

3

Вы можете использовать эти функции:

var range = window.getSelection().getRangeAt(0); 
var newNode = document.createElement("b"); 
range.surroundContents(newNode); 

Это окружает ваш выбор би-тег.

+0

Любой способ, которым тег 'b' может иметь класс? – Ian

+1

Кажется, работает как ожидалось 'var range = window.getSelection(). GetRangeAt (0); range.surroundContents ($ (" ", {'class': 'test'}) [0]);' – megawac

+0

'newNode .className = 'foo''. –

1

Это не невозможно с событием mouseover. Вы можете использовать document.caretPositionFromPoint(), который стандартизирован и поддерживается в Firefox 20 и более поздних версиях, и возвращается к собственному эквиваленту WebKit.

http://jsfiddle.net/2zzjL/6/

шаги при обработке события мыши являются:

  • Скрыть слово всплывающее окно, если показано
  • Получить координаты курсора от события
  • Создать диапазон от координаты курсора с использованием document.caretPositionFromPoint() или их эквивалента
  • Если узел контейнера диапазона является текстовым узлом, его смещение является символьным индексом wi тонкий текст текстового узла
  • Оттуда, разверните вперед и назад в текст текстового узла, пока мы не попали белое пространство, чтобы получить слово
  • обновлять ассортимент, чтобы охватить все слово
  • вызова getBoundingClientRect() на диапазоне, чтобы получить координаты слова
  • Позиции всплывающий элемент слова на некотором смещении от этих координат и показать его

Демонстрационные весьма ограничен (например, он не работает с одним словом, которое пересекает элемент границы, определение слова очень грубо и re - множество возможностей для оптимизации), но должно быть достаточно, чтобы вы начали. Он работает в текущих браузерах, кроме IE, который не поддерживает document.caretPositionFromPoint().

Вот ключевой код:

function expandToWord(str, offset) { 
    var start = offset; 
    while (start >= 1 && /\S/.test(str.charAt(start - 1))) { 
     --start; 
    } 

    var end = offset, len = str.length; 
    while (end < len && /\S/.test(str.charAt(end))) { 
     ++end; 
    } 

    return { 
     start: start, 
     end: end, 
     word: str.slice(start, end) 
    }; 
} 

var wordDiv = document.createElement("div"); 
wordDiv.className = "word"; 

var createRangeFromPoint = (function(doc) { 
    // Try standards-based method first 
    if (typeof doc.caretPositionFromPoint != "undefined") { 
     return function(x, y) { 
      var pos = doc.caretPositionFromPoint(x, y); 
      var range = null; 
      if (pos) { 
       range = doc.createRange(); 
       range.setStart(pos.offsetNode, pos.offset); 
       range.collapse(true); 
      } 
      return range; 
     }; 
    } 

    // Now try WebKit's proprietary method 
    else if (typeof doc.caretRangeFromPoint != "undefined") { 
     return function(x, y) { 
      return doc.caretRangeFromPoint(x, y); 
     }; 
    } 

    // Give up 
    else { 
     return function() { return null; }; 
    } 
})(document); 

function mouseEventHandler(e) { 
    if (wordDiv.parentNode) { 
     wordDiv.parentNode.removeChild(wordDiv); 
    } 
    var range = createRangeFromPoint(e.clientX, e.clientY); 
    if (range) { 
     if (range.startContainer.nodeType == 3) { 
      var wordInfo = expandToWord(range.startContainer.data, range.startOffset); 
      if (wordInfo.word) { 
       range.setStart(range.startContainer, wordInfo.start); 
       range.setEnd(range.startContainer, wordInfo.end); 

       var rect = range.getBoundingClientRect(); 

       // Get the difference between client and page coordinates from the event 
       // for positioning the word div 
       var offsetX = e.clientX - e.pageX; 
       var offsetY = e.clientY - e.pageY; 

       wordDiv.style.left = (rect.left + offsetX) + "px"; 
       wordDiv.style.top = (rect.top + offsetY - 20) + "px"; 
       wordDiv.innerHTML = ""; 
       wordDiv.appendChild(document.createTextNode(wordInfo.word)); 

       document.body.appendChild(wordDiv); 
      } 
     } 
    } 
} 

document.onmousemove = mouseEventHandler; 
document.onmouseover = mouseEventHandler; 
document.onmouseout = mouseEventHandler; 
+0

Можете ли вы объяснить этот код? Я обнаруживаю позицию каретки, но как она обнаруживает слово, которое находится под кареткой? – Ian

+0

@Ian: диапазон, который он получает из позиции каретки, имеет ссылку на текстовый узел и смещение в тексте узла, из которого он может экстраполироваться на слово, используя функцию 'expandToWord()' в примере. –

Смежные вопросы