Как привязать обработчик к изменению выделения в окне?
В основном мне нужно знать, когда 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);
});
Я бы сказал, что
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
}