满意的文本选择不起作用 [英] contenteditable selection of text not working
问题描述
我面临以下问题:当我尝试在 contenteditable
元素中选择文本并且选择的结尾是元素内容的开头时,则没有选择事件被解雇,没有选择
和范围
对象。
有人可以告诉我为什么会出现这种情况或者我如何防止这种情况?
负责获取选择范围的代码:
$('div [contenteditable =true]')。bind(mouseup keyup touchend, function(){lastCaretIndex = getSelectionRange();}); function getSelectionRange(){var sel; if(window.getSelection){sel = window.getSelection();的console.log(SEL); //这不会打印任何事件空字符串if(sel.rangeCount){return sel.getRangeAt(0); } else if(document.selection){return document.createRange(); } return null;}
< div id =main -inputcontenteditable =true> Hello world!< / div>< script type =text / javascriptsrc =https://code.jquery.com/jquery-2.2.4.min.js >< / script>
问题在于您只在 contenteditable
元素上发生特定事件时记录选择更改。更具体地说,你有
$('div [contenteditable =true]')。bind(mouseup keyup touchend ,// ...
特别是 mouseup
事件通常会在选择更改时触发。除非它没有。当你在可编辑的 div
之外释放鼠标时(你在你的例子中做了! ),然后 div
永远不会收到 mouseup
事件,因此永远不会记录选择。
有两种解决方法:
- 监听整个
上的事件正文
。缺点是您收到的更多事件不会影响选择,并且仍然可以在页面外获得mouseup
事件。 - 收听
selectionchange
event。
document.addEventListener('selectionchange',function(event){console.log(event.type);});
< div contenteditable =true> Hello world!< / div>
您当然可以像现在一样进行选择此事件处理程序。每次选择更改时都会触发此事件,因此您可能需要 throttle 它。
完全实现可以在下面找到。
function handler(){//在这里做你想做的任何事情//这显示了选择,它包含了var sel = window.getSelection()的所有范围,ranges = Array(sel.rangeCount).fill(0).map((_,i)=> sel.getRangeAt(i)); ranges = ranges.map((r)=>`$ {r.startOffset} - $ {r.endOffset}`)。join(';'); console.log(`Selection [$ {ranges}:$ {sel.toString()}]`);} function throttle(func){var timeoutId = false,called = false,wrap = function(){if( !叫){clearInterval(timeoutId); timeoutId = false; } else {func(); } called = false; }; return function(){if(timeoutId === false){func(); timeoutId = setInterval(wrap,500); } else {called = true; document.addEventListener('selectionchange',throttle(handler));
< div contenteditable =true> Hello world!< / div>
I am faced with following: when I try to select text in a contenteditable
element and the end of the selection is the start of the element content, then no select event is fired and there are no Selection
and Range
objects.
Could somebody please give me any advice on why this might occur or how I can prevent this?
Code responsible for getting selection range:
$('div[contenteditable="true"]').bind("mouseup keyup touchend", function() {
lastCaretIndex = getSelectionRange();
});
function getSelectionRange() {
var sel;
if (window.getSelection) {
sel = window.getSelection();
console.log(sel); // this doesn't print anything event empty string
if (sel.rangeCount) {
return sel.getRangeAt(0);
}
} else if (document.selection) {
return document.createRange();
}
return null;
}
<div id="main-input" contenteditable="true">Hello world!</div>
<script type="text/javascript" src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
JSFiddle (open your browser console to make sure that selection doesn't get logged).
The issue is that you only log selection changes when specific events occur on the contenteditable
element. More specifically, you have
$('div[contenteditable="true"]').bind("mouseup keyup touchend", // ...
In particular the mouseup
event will normally be triggered when the selection changes. Except when it doesn't. When you release the mouse outside of the editable div
(which you do in your example!), then the div
will never receive a mouseup
event and thus never log the selection.
There are two ways around this:
- Listen for events on the entire
body
. Downsides are that you receive more events that do not influence the selection and that it is still possible to getmouseup
events outside of the page. - Listen for the
selectionchange
event.
document.addEventListener('selectionchange', function(event) {
console.log(event.type);
});
<div contenteditable="true">Hello world!</div>
You can of course still access the selection as you currently do inside this event handler. This event is triggered every time the selection changes, so you may want to throttle it.
Full implementation of that can be found below.
function handler() {
// do whatever you want here
// this shows the selection and all ranges it consists of
var sel = window.getSelection(),
ranges = Array(sel.rangeCount).fill(0).map((_, i) => sel.getRangeAt(i));
ranges = ranges.map((r) => `${r.startOffset}-${r.endOffset}`).join(';');
console.log(`Selection [${ranges}:"${sel.toString()}"]`);
}
function throttle(func) {
var timeoutId = false,
called = false,
wrap = function() {
if (!called) {
clearInterval(timeoutId);
timeoutId = false;
} else {
func();
}
called = false;
};
return function() {
if (timeoutId === false) {
func();
timeoutId = setInterval(wrap, 500);
} else {
called = true;
}
};
}
document.addEventListener('selectionchange', throttle(handler));
<div contenteditable="true">Hello world!</div>
这篇关于满意的文本选择不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!