Как обернуть выбранное слово с интервалом

0

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

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

Примечание. Это нужно только в Firefox.

  • 1
    Я, вероятно, могу помочь, но мне нужно больше деталей. Во-первых, хотите ли вы добавить эти возможности к существующим веб-страницам или это ваша собственная веб-страница? Конечно, это очень сильно меняет ситуацию;) Кроме того, если вы можете опубликовать скрипку (fiddlejs.net), которая иллюстрирует то, что вы пытаетесь достичь, это также может очень помочь. На первый взгляд кажется, что делегирование событий и ленивая загрузка - ваш друг.
  • 0
    Это для существующих веб-страниц (это дополнение к Firefox).
Теги:
firefox
selection

2 ответа

3
Лучший ответ

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

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

Это окружает ваш выбор с помощью b-tag.

  • 0
    В любом случае у тега b может быть класс?
  • 1
    Кажется, работает как и ожидалось var range = window.getSelection().getRangeAt(0);range.surroundContents($("<span>", {'class':'test'})[0]);
Показать ещё 2 комментария
1

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

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

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

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

Демонстрация довольно ограничена (например, она не работает со словом, пересекающим границы элементов, определение слова очень грубо и существует множество возможностей для оптимизации), но должно быть достаточно, чтобы вы начали. Он работает в текущих браузерах, кроме 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 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
    Можете ли вы объяснить этот код? Я получаю определение позиции каретки, но как она определяет слово, которое находится под кареткой?
  • 0
    @Ian: диапазон, который он получает из позиции каретки, имеет ссылку на текстовый узел и смещение в тексте узла, из которого он может экстраполироваться на слово с использованием функции expandToWord() в примере.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню