Selection selectfinish/selectend 事件应该如何实现?
How should Selection selectfinish/selectend event be implemented?
我想在用户完成选择时做一些事情——我认为基本上是在每个 selectstart
事件之后的第一个 mouseup
事件上——在页面上。我想采用该选择并将其包装在要通过 CSS 设置样式的元素中。我推测选择 API 为此提供了一个事件;然而,似乎并没有。
我不只是听 mouseup
因为我特别希望它能与浏览器的查找功能产生的选择一起工作(“在此页面中查找...”;⌘+f).
let selContainer = document.createElement('span')
span.classList.add('user-selection')
const wrapSelection = () => {
window.getSelection().getRangeAt(0).surroundContent(selContainer)
}
/* ┏━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ ┃
┃ The Selection API only ┃
┃ affords these events: ┃
┃ ┃
┃ - selectionchange ┃
┃ - selectstart ┏━━━━━┫
┃ ┃issue┃
┗━━━━━━━━━━━━━━━━━━━━┻━━━━━┛
*/document.addEventListener('selectfinish', wrapSelection)/*
┗━━━━┳━━━━━┛
┃
┃
no such
event */
我挑了source code of the hypothes.is web annotation client in an effort to understand how they get their toolbar
to appear on user select action end. It seems to be a matter of employing an observer via zen-observable.
已接受答案的更简单替代方案。
document.addEventListener('mouseup', e => {
var s = document.getSelection();
if (!s.isCollapsed) {
// do sth with selection
}
});
或者更好?
document.addEventListener('selectstart', e => {
document.addEventListener('mouseup', somefunction);
});
function somefunction(e) {
// do sth
document.removeEventListener('mouseup', somefunction);
}
我让它工作的一种方法是跟踪 selectionchange
事件,当 selection 在超过 500 毫秒内没有变化时,我认为 select 结尾。它并不完美,但它可以正常工作并正确触发任何类型的 selection,无论是鼠标、键盘还是 CTRL+F。
let selectionDelay = null, selection = '';
document.addEventListener('selectionchange', () => {
const currentSelection = document.getSelection().toString();
if (currentSelection != selection) {
selection = currentSelection;
if (selectionDelay) {
window.clearTimeout(selectionDelay);
}
selectionDelay = window.setTimeout(() => {
wrapSelection();
selection = '';
selectionDelay = null;
}, 500);
}
});
这比它应该的更棘手。我使用了 element.onselectstart
、element.onmouseup
和 document.onselectionchange
的组合。看看这个demo.
function onSelect(element, callback) {
// console.log(element, callback);
let isSelecting = false;
let selection = null;
function handleSelectStart(event) {
// console.log(event);
isSelecting = true;
}
function handleMouseUp(event) {
// console.log(event, isSelecting);
if (isSelecting && !document.getSelection().isCollapsed) {
callback((selection = document.getSelection()));
isSelecting = false;
}
}
function handleSelectionChange(event) {
// console.log('change', isSelecting);
if (document.getSelection().isCollapsed && null !== selection) {
callback((selection = null));
}
}
element.addEventListener('selectstart', handleSelectStart);
element.addEventListener('mouseup', handleMouseUp);
document.addEventListener('selectionchange', handleSelectionChange);
return function destroy() {
element.removeEventListener('selectstart', handleSelectStart);
element.removeEventListener('mouseup', handleMouseUp);
document.removeEventListener('selectionchange', handleSelectionChange);
};
}
这不会处理非鼠标交互。容纳指针和键盘事件将是一个很好的增强。不过,我认为总体模式成立。
我想在用户完成选择时做一些事情——我认为基本上是在每个 selectstart
事件之后的第一个 mouseup
事件上——在页面上。我想采用该选择并将其包装在要通过 CSS 设置样式的元素中。我推测选择 API 为此提供了一个事件;然而,似乎并没有。
我不只是听 mouseup
因为我特别希望它能与浏览器的查找功能产生的选择一起工作(“在此页面中查找...”;⌘+f).
let selContainer = document.createElement('span')
span.classList.add('user-selection')
const wrapSelection = () => {
window.getSelection().getRangeAt(0).surroundContent(selContainer)
}
/* ┏━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ ┃
┃ The Selection API only ┃
┃ affords these events: ┃
┃ ┃
┃ - selectionchange ┃
┃ - selectstart ┏━━━━━┫
┃ ┃issue┃
┗━━━━━━━━━━━━━━━━━━━━┻━━━━━┛
*/document.addEventListener('selectfinish', wrapSelection)/*
┗━━━━┳━━━━━┛
┃
┃
no such
event */
我挑了source code of the hypothes.is web annotation client in an effort to understand how they get their toolbar
to appear on user select action end. It seems to be a matter of employing an observer via zen-observable.
已接受答案的更简单替代方案。
document.addEventListener('mouseup', e => {
var s = document.getSelection();
if (!s.isCollapsed) {
// do sth with selection
}
});
或者更好?
document.addEventListener('selectstart', e => {
document.addEventListener('mouseup', somefunction);
});
function somefunction(e) {
// do sth
document.removeEventListener('mouseup', somefunction);
}
我让它工作的一种方法是跟踪 selectionchange
事件,当 selection 在超过 500 毫秒内没有变化时,我认为 select 结尾。它并不完美,但它可以正常工作并正确触发任何类型的 selection,无论是鼠标、键盘还是 CTRL+F。
let selectionDelay = null, selection = '';
document.addEventListener('selectionchange', () => {
const currentSelection = document.getSelection().toString();
if (currentSelection != selection) {
selection = currentSelection;
if (selectionDelay) {
window.clearTimeout(selectionDelay);
}
selectionDelay = window.setTimeout(() => {
wrapSelection();
selection = '';
selectionDelay = null;
}, 500);
}
});
这比它应该的更棘手。我使用了 element.onselectstart
、element.onmouseup
和 document.onselectionchange
的组合。看看这个demo.
function onSelect(element, callback) {
// console.log(element, callback);
let isSelecting = false;
let selection = null;
function handleSelectStart(event) {
// console.log(event);
isSelecting = true;
}
function handleMouseUp(event) {
// console.log(event, isSelecting);
if (isSelecting && !document.getSelection().isCollapsed) {
callback((selection = document.getSelection()));
isSelecting = false;
}
}
function handleSelectionChange(event) {
// console.log('change', isSelecting);
if (document.getSelection().isCollapsed && null !== selection) {
callback((selection = null));
}
}
element.addEventListener('selectstart', handleSelectStart);
element.addEventListener('mouseup', handleMouseUp);
document.addEventListener('selectionchange', handleSelectionChange);
return function destroy() {
element.removeEventListener('selectstart', handleSelectStart);
element.removeEventListener('mouseup', handleMouseUp);
document.removeEventListener('selectionchange', handleSelectionChange);
};
}
这不会处理非鼠标交互。容纳指针和键盘事件将是一个很好的增强。不过,我认为总体模式成立。