Установка позиции каретки для пустого узла внутри элемента contentEditable - PullRequest
17 голосов
/ 31 октября 2010

Моя задача - установить текстовую каретку, которая будет отображаться внутри пустого узла span в пределах contentEditable div.

Следующее не доставляет мне проблем в Firefox 3.6:

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <script type="text/javascript" src="js/jquery-1.4.3.min.js">
        </script>
        <style>
            #multiple {
                border: 1px solid #ccc;
                width: 800px;
                min-height: 20px;
                padding: 5px;
                outline: none;
            }
        </style>
        <script>
            $(document).ready(function(){

    var contentEditable = document.getElementById('multiple');
    var lastItem = contentEditable.getElementsByTagName('span').item(2);

                var selectElementText = function(el, win){
                    win = win || window;
                    var doc = win.document, sel, range;
                    if (win.getSelection && doc.createRange) {                    
                        range = doc.createRange();
                        range.selectNodeContents(el);
                        range.collapse(false);
                        sel = win.getSelection();
                        sel.removeAllRanges();
                        sel.addRange(range);
                    }
                    else 
                        if (doc.body.createTextRange) {
                            range = doc.body.createTextRange();
                            range.moveToElementText(el);
                            range.select();
                        }
                }

                contentEditable.focus();
                selectElementText(lastItem);
            });
        </script>
        <title>Range Selection Tasks (Make Me Want to Cry)</title>
    </head>
    <body>
        <div id="multiple" contentEditable="true">
            <span style="color:red">First</span><span style="color:green">Second</span><span style="color:blue"></span>
        </div>
    </body>
</html>

... но в Webkit и IE фокус устанавливается на предпоследний диапазон. Понятия не имею почему. Это работает, если я помещаю пробел в последний диапазон, но тогда я получаю выборку из одного символа.

Сказав это, допустимо иметь пробелы в последнем узле, если каретка находится в самом начале.

Любая помощь с этим будет принята с благодарностью. Заранее спасибо.

Ответы [ 5 ]

11 голосов
/ 15 сентября 2013

Установите для элемента innerHTML символ нулевой ширины:

('element').innerHTML = '&#200B';

Теперь каррет может идти туда.

5 голосов
/ 31 октября 2010

Модель выбора / диапазона IE основана на индексах в текстовом содержимом, независимо от границ элементов. Я считаю, что может быть невозможно установить фокус ввода внутри встроенного элемента без текста в нем. Конечно, в вашем примере я не могу установить фокус внутри последнего элемента, нажимая клавиши со стрелками.

Это почти работает, если вы установите для каждого диапазона значение display: block, хотя все еще существует довольно странное поведение, зависящее от наличия пробела в родительском элементе. Взламывая дисплей, чтобы он выглядел встроенным с помощью таких хитростей, как float, inline-block и абсолютное положение, IE обрабатывает каждый элемент как отдельный блок редактирования. Относительно расположенные элементы блоков рядом друг с другом работают, но это, вероятно, нецелесообразно.

Если вам станет легче, IE9 наконец исправит эту неприятность и примет стандартную модель диапазона. (Ура!)

допустимо иметь пробелы в последнем узле, если каретка находится в самом начале.

Я бы, наверное, так и сделал, если только эксперт по выбору IE не придумает ничего лучшего. (Зовет Тима!)

2 голосов
/ 06 декабря 2010

Я нашел обходной путь для Webkit, не знаю, нашел ли кто-нибудь это раньше, но вместо того, чтобы программно добавлять пробел нулевой ширины, вы можете сделать то же самое со свойством css3 content в псевдо-селекторе элементов after Вы хотите вставить каретку. Это имеет то преимущество, что дополнительные символы не отображаются в DOM, и пользователь не может перемещаться между кареткой. Так что в основном это не нуждается в очистке.

Чтобы это работало для любого дочернего элемента редактируемого элемента вашего контента, это будет примерно так:

#mycontenteditableelement *:after {
    content: '\200B';
}

Я не проверил полностью, но подозреваю, что это обходной путь.

0 голосов
/ 09 ноября 2015

Для меня установка содержания contenteditable div на <br> работает. Я попытался установить его на nbsp;, но это создает дополнительное пространство символов в div, прежде чем я начну редактировать.

Надеюсь, это поможет.

0 голосов
/ 19 марта 2012

Применение минимальной высоты и минимальной ширины к элементам внутри contenteditable со встроенным блоком может принести некоторую пользу, хотя воздействие имеет непредвиденные побочные эффекты:

#multiple * {
    min-height: 1em;
}
span, b, strong, i, em, a, etc {
    display: inline-block;
    min-width: 1em;
    background-color: hsla(0, 50%, 50%, .5); /* this is only a visual aid; discard @ will */
    vertical-align: middle; /* so elements w/ inline-block align w/ text correctly */ 
}

Вы найдетеЕсть еще проблемы, но если вы готовы пожертвовать некоторыми проблемами ради меньшего набора других, это может быть очень полезно.

...