Удалите все HTML-теги внутри выделения в contenteditable


У меня есть <div />, который является contenteditable и может содержать несколько типов HTML-элементов, таких как <span />, <a />, <b />, <u /> и так далее.

Теперь, когда я выбираю текст в моем contenteditable, я хотел бы иметь кнопку, которая удаляет все стили в пределах выделения.

Пример 1:

Выбор:

Hello <b>there</b>. I am <u>a selection</u>

Станет:

Hello there. I am a selection

Пример 2:

Выбор:

<a href="#">I am a link</a>

Станет:

I am a link

Вы получаете идея...

Я нашел эту полезную функцию https://stackoverflow.com/a/3997896/1503476 , который заменяет текущее выделение пользовательским текстом. Но я просто не могу сначала получить содержимое выборки и удалить теги, прежде чем заменить его. Как я могу это сделать?

4 7

4 ответа:

Способ, которым я бы это сделал, состоит в том, чтобы перебирать узлы внутри выделения и удалять встроенные узлы (возможно, оставляя элементы <br> в покое). Вот пример использования моей библиотекиRangy для удобства. Он работает во всех основных браузерах (включая IE 6), но не совсем совершенен: например, он не разбивает частично выбранные элементы форматирования, что означает, что частично выбранный элемент форматирования полностью удаляется, а не только выбранная часть. Чтобы исправить это было бы больше хитрый.

Демо: http://jsfiddle.net/fQCZT/4/

Код:

var getComputedDisplay = (typeof window.getComputedStyle != "undefined") ?
    function(el) {
        return window.getComputedStyle(el, null).display;
    } :
    function(el) {
        return el.currentStyle.display;
    };

function replaceWithOwnChildren(el) {
    var parent = el.parentNode;
    while (el.hasChildNodes()) {
        parent.insertBefore(el.firstChild, el);
    }
    parent.removeChild(el);
}


function removeSelectionFormatting() {
    var sel = rangy.getSelection();

    if (!sel.isCollapsed) {
        for (var i = 0, range; i < sel.rangeCount; ++i) {
            range = sel.getRangeAt(i);

            // Split partially selected nodes 
            range.splitBoundaries();

            // Get formatting elements. For this example, we'll count any
            // element with display: inline, except <br>s.
            var formattingEls = range.getNodes([1], function(el) {
                return el.tagName != "BR" && getComputedDisplay(el) == "inline";
            });

            // Remove the formatting elements
            for (var i = 0, el; el = formattingEls[i++]; ) {
                replaceWithOwnChildren(el);
            }
        }
    }
}
​

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

var selection = window.getSelection().getRangeAt(0);
var selectedText = selection.cloneContents().childNodes[0]; // This is your selected text.
Теперь вы можете удалить HTML-теги из выбранного текста и заменить их с помощью функции, которую вы уже предоставили в своем вопросе.

Например, вы можете использовать strip_tags() из php.JS project

Я надеюсь, что это ответ на ваш вопрос.

Http://jsfiddle.net/tnyWD/

HTML:

<div class="test">
    Hello <b>there </b><a href="#">I am a link</a>
</div>
<button class="remove">Remove HTML</button>​

JS:

$(document).ready(function(){
    jQuery.fn.stripTags = function() { return this.replaceWith(this.html().replace(/<\/?[^>]+>/gi, '') ); };
$('.remove').click(function(){
    $('.test').stripTags();
});
});​

Это то, что вы ищете?

Http://jsfiddle.net/fQCZT/2/

<div contenteditable="true">
    <p>
        Here is some <b>formatted text</b>. Please select some and watch the formatting
        <i>magically disappear</i>.
        <br>
        Look, some more <u>formatted</u> content.
    </p>
    <p>And <i>another</i> paragraph of it</p>
</div>
<button onmousedown="removeSelectionFormatting()">Change</button>​

Это дубликат одного из приведенных выше ответов, но с кнопкой для изменения текста!