Как привязать обработчик к изменению выделения в окне?

В основном мне нужно знать, когда window.getSelection() изменилось и привязать обработчик к этому событию. Идеи?

OBS: Обратите внимание, что я не собираюсь связывать изменения выбора на INPUT или TEXTAREA. Я говорю о любом выборе в окне.

3 ответа

Не существует кросс-браузерного способа обнаружения изменений в выборе. IE (начиная с версии 5.5, я думаю) и браузеры WebKit/Blink (например, версии Chrome, Safari и Opera последних двух лет) поддерживают selectionchange событие на document который делает именно то, что вы хотите.

Firefox и pre-Blink Opera не имеют такого события, и все, что вы можете сделать, это обнаружить изменения выбора, сделанные с помощью событий клавиатуры и мыши, что является неудовлетворительным (например, нет способа обнаружить "Выбрать все" из контекстного меню или редактировать меню), или просто опросить Selection объект, возвращенный window.getSelection() (проверка выбора anchorNode, anchorOffset, focusNode а также focusOffset свойства по сравнению с их предыдущими значениями должны быть достаточными).

Для этого не существует кросс-браузерного события.

Тем не менее, существует событие под названием selectionchange, которые срабатывают при каждом изменении выделения в документе, но поддерживаются только в IE и последних версиях WebKit (Chrome/Safari), поэтому нет Firefox/Opera.

Вы можете использовать selectionchange событие как это:

$(document).on('selectionchange', function(e) {
    console.log('selectionchange', e.originalEvent); 
});

пример jsfiddle

Я бы сказал, что selectionchangeсобытие слишком жадное, и вы хотите наблюдать за событиями мыши. Обработчик - самая легкая часть. Возврат выбранных узлов - важная часть! Адаптируя ответ Тима Дауна здесь, я придумал:

    $(document).on('mouseup', function(e) { 
    
            //cool! jQuery object containing all nodes (elements) that were just selected
            var $selNodes = $().getSelectedNodes();
            if ($selNodes.length)
                     alert('user selected something');
            
            //so now I can do work on just the elements I am interested in that were selected
            if($selNodes.filter('.justTheClassIwant').length)
                alert('user selected the elements I want to watch');
        });
    
    jQuery.fn.extend({
    getSelectedNodes: function() {
        if (window.getSelection) {
            var sel = window.getSelection();
            if (!sel.isCollapsed) {
                var range = sel.getRangeAt(0);
                var node = range.startContainer;
                var endNode = range.endContainer;

                // Special case for a range that is contained within a single node
                if (node == endNode) {
                    return [node];
                }

                // Iterate nodes until we hit the end container
                var rangeNodes = [];
                while (node && node != endNode) {
                    if (node.hasChildNodes()) {
                        node = node.firstChild;
                    } 
                    else {
                        while (node && !node.nextSibling) {
                            node = node.parentNode;
                        }
                        node = node.nextSibling;
                    }
    
                    rangeNodes.push(node);
                }

                // Add partially selected nodes at the start of the range
                node = range.startContainer;
                while (node && node != range.commonAncestorContainer) {
                    rangeNodes.unshift(node);
                    node = node.parentNode;
                }

                return jQuery(rangeNodes);
            }
        }
        return jQuery([]);
    }
});

Я думаю, что это поможет

function foo() {
   var selObj = window.getSelection(); 
   alert(selObj);
   var selRange = selObj.getRangeAt(0);
   // work something with selObj
}
Другие вопросы по тегам