Как определить, является ли выбор в contenteditable DIV слева направо или справа налево

Внутри contenteditable DIV я хочу определить, сделал ли пользователь выбор слева направо или справа налево. У кого-нибудь есть решение Javascript для браузеров Firefox, Chrome, Safari, Opera? И когда возможно, еще и для IE?

<div id="editor" contenteditable>
Selection from Cursor end | here <strong>over bold</strong> to Cursor start | here.
</div>

Я подготовил код в jsFiddle здесь: http://jsfiddle.net/ecUka/

Заранее спасибо :-)


person Max    schedule 29.09.2012    source источник


Ответы (1)


Вот функция, которая использует тот факт, что установка конца диапазона DOM в более раннюю точку документа, чем начало диапазона, приведет к свертыванию диапазона.

Демонстрация: http://jsfiddle.net/97MDR/17/

Код:

function isSelectionBackwards() {
    var backwards = false;
    if (window.getSelection) {
        var sel = window.getSelection();
        if (!sel.isCollapsed) {
            var range = document.createRange();
            range.setStart(sel.anchorNode, sel.anchorOffset);
            range.setEnd(sel.focusNode, sel.focusOffset);
            backwards = range.collapsed;
        }
    }
    return backwards;
}

Он работает во всех основных браузерах, кроме IE ‹ 9, который не поддерживает те же API Range и Selection, что и другие браузеры.

Для IE ‹ 9 в API выбора просто нет ничего, что могло бы рассказать вам о направлении выбора. Лучшее, что я могу предложить, это использовать selectionchange< /a>, чтобы отслеживать ранее выбранный диапазон и видеть, какой конец изменился каждый раз, когда он срабатывает. Кажется, он работает в следующем примере, но кроме этого не тестировался, поэтому используйте его на свой страх и риск.

Демонстрация: http://jsfiddle.net/97MDR/18/

Дополнительный код:

var selectedRange, selectionBackwards;

document.onselectionchange = function(evt) {
    evt = evt || window.event;
    var sel = document.selection;
    if (sel && sel.type !== "Control") {
        if (sel.type == "Text") {
            // Selection is not collapsed, so compare range end points
            var newRange = sel.createRange();
            if (selectedRange) {
                var startChanged = (newRange.compareEndPoints("StartToStart", selectedRange) != 0);
                var endChanged = (newRange.compareEndPoints("EndToEnd", selectedRange) != 0);

                if (startChanged && !endChanged) {
                    selectionBackwards = true;
                } else if (endChanged && !startChanged) {
                    selectionBackwards = false;
                } else if (startChanged && endChanged) {
                    // Both ends have changed, which is confusing.
                    // I suspect this can happen when the selection snaps
                    // to words. In this case we can tell nothing, so leave
                    // selectionBackwards alone.
                } else {
                    // Neither end has changed, so we can tell nothing.
                }
            }

            selectedRange = newRange;
        } else {
            // Selection is collapsed
            selectionBackwards = false;
        }
    }
};
person Tim Down    schedule 29.09.2012
comment
Спасибо, это именно то, что я ищу :-) Есть ли у кого-нибудь решение для Internet Explorer версий 6, 7 и 8? - person Max; 30.09.2012
comment
@Max: Если нет чего-то очень неясного, чего я так и не нашел после некоторого поиска, это невозможно в 6-8. В JavaScript API просто нет ничего, что можно было бы использовать для получения направления выбора. - person Tim Down; 30.09.2012
comment
@Max: вы можете что-то сделать, соблюдая selectionchange (например, отслеживание ранее выбранного диапазона и просмотр того, какой конец изменился) - person Tim Down; 30.09.2012
comment
@Max: я придумал кое-что, что, кажется, работает в очень ограниченном тестовом примере, на котором я это пробовал. Смотрите мой обновленный ответ. - person Tim Down; 30.09.2012
comment
Проверка range.collapsed выглядит проще, чем compareDocumentPosition. - person webprogrammer; 17.04.2020