Вставить HTML после выделения - PullRequest
10 голосов
/ 30 августа 2010

Я хочу иметь возможность дважды щелкнуть, чтобы выделить какой-то текст в элементе div, который затем запускает функцию JavaScript, которая вставляет некоторый HTML-код после выделенного текста, очень похоже на функцию «редактировать / ответить» в Google Wave.

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

Ответы [ 3 ]

13 голосов
/ 30 августа 2010

Следующая функция вставит узел DOM (элемент или текстовый узел) в конце выделения во всех основных браузерах (обратите внимание, что Firefox теперь допускает множественный выбор по умолчанию; в следующем случае используется только первый выбор):

function insertNodeAfterSelection(node) {
    var sel, range, html;
    if (window.getSelection) {
        sel = window.getSelection();
        if (sel.getRangeAt && sel.rangeCount) {
            range = sel.getRangeAt(0);
            range.collapse(false);
            range.insertNode(node);
        }
    } else if (document.selection && document.selection.createRange) {
        range = document.selection.createRange();
        range.collapse(false);
        html = (node.nodeType == 3) ? node.data : node.outerHTML;
        range.pasteHTML(html);
    }
}

Если вы предпочитаете вставить строку HTML:

function insertHtmlAfterSelection(html) {
    var sel, range, node;
    if (window.getSelection) {
        sel = window.getSelection();
        if (sel.getRangeAt && sel.rangeCount) {
            range = window.getSelection().getRangeAt(0);
            range.collapse(false);

            // Range.createContextualFragment() would be useful here but is
            // non-standard and not supported in all browsers (IE9, for one)
            var el = document.createElement("div");
            el.innerHTML = html;
            var frag = document.createDocumentFragment(), node, lastNode;
            while ( (node = el.firstChild) ) {
                lastNode = frag.appendChild(node);
            }
            range.insertNode(frag);
        }
    } else if (document.selection && document.selection.createRange) {
        range = document.selection.createRange();
        range.collapse(false);
        range.pasteHTML(html);
    }
}

Обновление от 18 января 2012 года

Наконец, вот версия, которая вставляет HTML и сохраняетвыбор (т. е. расширяет выбор, чтобы включить первоначально выбранный контент плюс вставленный контент).

Демонстрация в реальном времени: http://jsfiddle.net/timdown/JPb75/1/

Код:

function insertHtmlAfterSelection(html) {
    var sel, range, expandedSelRange, node;
    if (window.getSelection) {
        sel = window.getSelection();
        if (sel.getRangeAt && sel.rangeCount) {
            range = window.getSelection().getRangeAt(0);
            expandedSelRange = range.cloneRange();
            range.collapse(false);

            // Range.createContextualFragment() would be useful here but is
            // non-standard and not supported in all browsers (IE9, for one)
            var el = document.createElement("div");
            el.innerHTML = html;
            var frag = document.createDocumentFragment(), node, lastNode;
            while ( (node = el.firstChild) ) {
                lastNode = frag.appendChild(node);
            }
            range.insertNode(frag);

            // Preserve the selection
            if (lastNode) {
                expandedSelRange.setEndAfter(lastNode);
                sel.removeAllRanges();
                sel.addRange(expandedSelRange);
            }
        }
    } else if (document.selection && document.selection.createRange) {
        range = document.selection.createRange();
        expandedSelRange = range.duplicate();
        range.collapse(false);
        range.pasteHTML(html);
        expandedSelRange.setEndPoint("EndToEnd", range);
        expandedSelRange.select();
    }
}
1 голос
/ 30 августа 2010

window.getSelection () вернет вам выделенный текст ( Документация ). Вы можете использовать jQuery.after () ( Documentation ), чтобы вставить новый html после элемента.

При выбранном вами вызове текстовой функции вам придется циклически проходить по всем вашим элементам DOM, проверяя их позиции x & y в текущей позиции курсора - найти ближайший элемент и вставить после или использовать функцию .elementFromPoint (x, y) ( Документация )

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

0 голосов
/ 30 августа 2010

Я не знаю, возможно ли это, но я думаю о частичном решении.

В событии двойного щелчка вы можете получить объект события и получить доступ к свойству target.

Имея целевой элемент, вы можете получить выделенный текст .

Теперь получите html целевого элемента, найдите индекс выделенного текста и его длину, введите html в позицию index + length.

Я думаю, вы уже видели проблему, она может совпадать с текстом в нескольких местах. Чтобы решить эту проблему, вам, возможно, придется найти положение курсора и сравнить с элементом, я не знаю, как это сделать ...

Надеюсь, я смогу немного помочь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...