Есть ли способ предотвратить прокрутку элемента contentEditable, когда курсор достигает дна? - PullRequest
15 голосов
/ 05 февраля 2012

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

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

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

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

Ответы [ 5 ]

13 голосов
/ 13 февраля 2012

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

  • сначала мы пытаемся предотвратить или отменить прокрутку
  • всякий раз, когда пользователь нажимает клавишу, мы превращаем свойство 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 я также отключил проверку орфографии, чтобы избежать мерцания меток.

3 голосов
/ 06 февраля 2012

Вам нужно иметь родительский 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 keyup {

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

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

Для прокрутки вниз просто измените ток css top на += line-height of div B

Уничтожить пустой промежуток.

(если позиция курсора терпит неудачу -> вам необходимо предварительно сохранить его перед созданием диапазона и восстановить позицию курсора после уничтожения диапазона)

}


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

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


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

2 голосов
/ 10 февраля 2012

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

2 голосов
/ 05 февраля 2012

Попробуйте установить style = "overflow: hidden;" на div

0 голосов
/ 30 июня 2014

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

<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);

    });

});
...