Есть ли способ предотвратить прокрутку элемента contentEditable, когда курсор достигает дна?

Например, у меня есть contentEditable div, и я могу ввести его. Когда текст достигает нижней части div, браузер автоматически прокручивает div так, что конец текста и курсора все еще видны.

Как предотвратить прокрутку div, чтобы введенный текст проходил мимо нижней части div и чтобы вы больше не могли видеть курсор во время ввода?

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

EDIT 2/7/2012 9:27 утра: Это то, что у меня есть прямо сейчас, но выглядит глючным, потому что положение прокрутки отрегулировано ПОСЛЕ события keyup: http://jsfiddle.net/trusktr/hgkak/6/ Итак, перед событием keyup курсор временно помещается в представление (для каждого нажатия клавиши). Я бы хотел, чтобы там не было прыжков, и чтобы курсор оставался под концом зеленого div, когда есть лишний текст без просмотра прыжка (прыжок кажется любительским взломом с моей стороны: D)

Ответы

Ответ 1

Попробуйте взломать:

  • сначала мы пытаемся предотвратить или отменить любую прокрутку
  • всякий раз, когда пользователь нажимает клавишу, мы превращаем свойство overflow в элемент visible, чтобы избежать прокрутки содержимого, но одновременно скройте элемент, установив его opacity равным 0. Сразу же после этого мы переключаем overflow вернуться к hidden и снова показать элемент.
  • Чтобы избежать мерцания, мы создаем клон редактируемого элемента (с overflow: hidden) и показываем этот элемент, пока он не скрыт.

Здесь мы идем (использует jQuery для удобства DOM):

$(function() {

    var editableElement = $('#editable'), clonedElement;

    // Revert any scrolling                    
    editableElement.on("scroll", function(event) {
        editableElement.scrollTop(0);

        // Try to prevent scrolling completely (doesn't seem to work)
        event.preventDefault();
        return false;
    });

    // Switch overflow visibility on and off again on each keystroke.
    // To avoid flickering, a cloned element is positioned below the input area
    // and switched on while we hide the overflowing element.
    editableElement.on("keydown", function() {

        // Create a cloned input element below the original one
        if (!clonedElement) {
            var zIndex = editableElement.css('zIndex');
            if (isNaN(parseInt(zIndex, 10))) {
                zIndex = 10;
                editableElement.css({zIndex: zIndex});
            }    

            clonedElement = editableElement.clone();
            clonedElement.css({
                zIndex: zIndex-1,
                position: 'absolute',
                top: editableElement.offset().top,
                left: editableElement.offset().left,
                overflow: 'hidden',
                // Set pseudo focus highlighting for webkit
                // (needs to be adapted for other browsers)
                outline: 'auto 5px -webkit-focus-ring-color'
            });
            editableElement.before(clonedElement);
        } else {
            // Update contents of the cloned element from the original one
            clonedElement.html(editableElement.html());
        }

        // Here comes the hack:
        //   - set overflow visible but hide element via opactity.
        //   - show cloned element in the meantime
        clonedElement.css({opacity: 1});
        editableElement.css({overflow: 'visible', opacity: 0});

        // Immediately turn of overflow and show element again.
        setTimeout(function() {
            editableElement.css({overflow: 'hidden', opacity: 1});
            clonedElement.css({opacity: 0});
        }, 10);

    });
});

Отметьте этот jsFiddle, чтобы играть с указанным выше кодом.

Обратите внимание, что это может быть не полное решение (я только пробовал его с Safari, Chrome и Firefox еще), но для проверенных браузеров он работает. Вы можете настроить и отполировать свою реализацию (например, выделение фокуса). В примере jsFiddle я также отключил проверку орфографии, чтобы избежать мерцающих меток.

Ответ 2

Вам нужно иметь родительский div (A) с overflow:hidden;position:relative и статическую высоту или минимальную высоту.

Внутри этого родителя у вас есть дети div (B) с contenteditable="true" и style="position:absolute;width:100%;left:0;top:0"

Высота div A должна быть как integer * line-height of div B


После этого вам нужно включить rangy и библиотеку jQuery

Привязка к функции события нажатия клавиши div B {

Используйте rangy для создания в текущем курсоре пустым span.

Получить offset(). top из этого диапазона и сравнить его с offset().top + outerHeight() из div A. Если сначала большой, затем второй → вам нужно прокрутить вниз div B.

Чтобы прокрутить вниз, просто измените текущий css top на += line-height of div B

Уничтожьте пустой диапазон.

(если позиция курсора не удалась → вам нужно предварительно сохранить ее перед созданием пролета и восстановить позицию курсора после разрушения диапазона)

}


Также вам нужно подражать всем клавишам со стрелками. В этом случае вам нужно создать селектор переключателей с event.which на клавиатуре в div B. Коды клавиш .

Прокрутите, если позиция курсора выходит из видимого диапазона в div A (алгоритм, аналогичный тому, что я написал выше)


Да, это не простой способ, но он работает

Ответ 3

Попробуйте установить стиль = "переполнение: скрыто"; на div

Ответ 4

Добавьте Div, который перекрывает нижнюю часть с более высоким z-индексом? Вы можете сделать область редактирования очень высокой, чтобы не иметь значения. Тогда вам нужно будет сделать покрытие div перетаскиваемым.

Ответ 5

Очень просто:

<div id="mydiv" contenteditable="true" style="width: 200px; height: 100px;"></div>


$(document).ready(function(){

    $("#mydiv").height(document.getElementById('mydiv').scrollHeight);

    $("#mydiv").keyup(function(){

        $(this).height(0).height(document.getElementById('mydiv').scrollHeight);

    });

});