contenteditable div: IE8 недоволен удалением backspace HTML-элемента - PullRequest
7 голосов
/ 03 апреля 2012

Я использую contenteditable div в сочетании с rangy библиотекой Javascript для вставки HTML в позицию курсора.

Конец дня содержимое div обычно выглядит так:

<div contenteditable="true">
    "Hello "
    <button contenteditable="false" data-id="147">@John Smith</button>
    " "
</div>

Пользователи получают подсказки после нажатия «@», а затем их вставляют в виде кнопки при выборе (аля Google Plus). Я также вставляю &nbsp; после этой кнопки.

Кнопка удаляется в Chrome / Safari / Firefox при нажатии клавиши Backspace (после первого удаления &nbsp;), но не в IE8. В IE8 курсор просто перепрыгивает через кнопку, не удаляя ее. Что еще более странно в IE8, если вы оставите &nbsp; рядом с кнопкой - и вместо этого поместите курсор прямо рядом с кнопкой - он удалит кнопку на клавише возврата. Так что это приятно, когда справа от курсора есть &nbsp;.

Кто-нибудь знает, что мне нужно для того, чтобы заставить IE8 работать i.t.o. удаление кнопки после возврата без необходимости &nbsp; справа от курсора? (некоторая информация об этом странном поведении также может помочь)

P.S. Я не тестировал другие версии IE

Ответы [ 2 ]

6 голосов
/ 05 апреля 2012

Я бы предложил сначала проверить, что каретка расположена после нередактируемого узла, и если это так, создать диапазон, который начинается сразу после нередактируемого элемента и заканчивается в позиции каретки.Проверьте, является ли текст в этом диапазоне пустым.Если это так, это означает, что курсор вставляется непосредственно после нередактируемого элемента, поэтому в этом случае удалите элемент.Наконец, поместите каретку там, где было недоступно для редактирования.

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

Код:

document.onkeypress = function(e) {
    e = e || window.event;
    var keyCode = e.which || e.keyCode;
    if (keyCode !== 8) {
        return;
    }

    var sel = rangy.getSelection();
    if (sel.rangeCount === 0) {
        return;
    }

    var selRange = sel.getRangeAt(0);
    if (!selRange.collapsed) {
        return;
    }

    var nonEditable = document.getElementById("nonEditable");
    if (!nonEditable) {
        return;
    }

    // Check the caret is located after the non-editable element
    var range = rangy.createRange();
    range.collapseAfter(nonEditable);

    if (selRange.compareBoundaryPoints(range.START_TO_END, range) == -1) {
        return;
    }

    // Check whether there is any text between the caret and the
    // non-editable element. If not, delete the element and move
    // the caret to where it had been
    range.setEnd(selRange.startContainer, selRange.startOffset);
    if (range.toString() === "") {
        selRange.collapseBefore(nonEditable);
        nonEditable.parentNode.removeChild(nonEditable);
        sel.setSingleRange(selRange);

        // Prevent the default browser behaviour
        return false;
    }
};
1 голос
/ 04 апреля 2012

Я сделал jsfiddle с кратким примером того, как посмотреть диапазон выбора и использовать свойство previousSibling startContainer, чтобы найти кнопку: jsfiddle

Поместите курсор в aaa, и он покажет, что кнопка является предыдущей. поместите его в ccc, и bbb покажет.

Таким образом, вы можете обработать событие keydown для div, проверить, является ли клавиша backspace + предыдущаяSibling - ваша кнопка, и удалить ее с помощью jQuery.

previousSibling равно нулю, если это текстовый узел, просто FYI.

...