使用 Rangy 保存位置时,插入符号在 Firefox 中消失
Caret disappears in Firefox when saving its position with Rangy
这只发生在 Firefox 中。
重要提示:我用 rangy.saveSelection():
保存插入符号的位置
- 点击内容可编辑div
- 在键盘上
- 将外部 html 元素(作为节点)添加到内容时可编辑 div
我需要通过多种方式不断保存位置,以便能够在点击时插入 html 个元素(我有一些标签)。
当我单击 contentEditable div 并且 div 为空(假设是第一个焦点)时,除非我开始键入,否则我看不到插入符号。如果插入符号在末尾,我也看不到它。
另一个奇怪的行为是我无法使用箭头在 contentEditable 中的文本之间导航 div。
如果我删除(不断)保存插入符号位置(输入、单击等)的功能,插入符号 returns 将恢复正常(插入符号可见)。
当我开始保存插入符号的位置时出现问题。显然,我应该进行某种重置或清除。但据我所知,这些似乎适得其反(据我所知,它们破坏了保存的插入符号位置)。
内容可编辑div
<div class="input__boolean input__boolean--no-focus">
<div
@keydown.enter.prevent
@blur="addPlaceholder"
@keyup="saveCursorLocation($event); fixDelete(); clearHtmlElem($event);"
@input="updateBooleanInput($event); clearHtmlElem($event);"
@paste="pasted"
v-on:click="clearPlaceholder(); saveCursorLocation($event);"
class="input__boolean-content"
ref="divInput"
contenteditable="true">Cuvinte cheie, cautare booleana..</div>
</div>
我的methods/functions
inputLength($event){
this.input_length = $event.target.innerText.length;
if(this.input_length == 0)
this.typed = false;
},
addPlaceholder(){
if(this.input_length == 0 && this.typed == false){
this.$refs.divInput.innerHTML = 'Cuvinte cheie, cautare booleana..'
}
},
clearPlaceholder(){
if(this.input_length == 0 && this.typed == false){
this.$refs.divInput.innerHTML = '';
}
},
updateBooleanInput($event){
this.typed = true;
this.inputLength($event);
},
saveCursorLocation($event){
if($event.which != 8){
if(this.saved_sel)
rangy.removeMarkers(this.saved_sel)
this.saved_sel = rangy.saveSelection();
}
// if(this.input_length == 0 && this.typed == false){
// var div = this.$refs.divInput;
// var sel = rangy.getSelection();
// sel.collapse(div, 0);
// }
},
insertNode: function(node){
var selection = rangy.getSelection();
var range = selection.getRangeAt(0);
range.insertNode(node);
range.setStartAfter(node);
range.setEndAfter(node);
selection.removeAllRanges();
selection.addRange(range);
},
addBooleanTag($event){
// return this.$refs.ChatInput.insertEmoji($event.img);
this.$refs.divInput.focus();
console.log(this.input_length);
if(this.typed == false & this.input_length == 0){
this.$refs.divInput.innerHTML = ''
var space = '';
this.typed = true
this.saveCursorLocation($event);
}
rangy.restoreSelection(this.saved_sel);
var node = document.createElement('img');
node.src = $event.img;
node.className = "boolean-button--img boolean-button--no-margin";
node.addEventListener('click', (event) => {
// event.currentTarget.node.setAttribute('contenteditable','false');
this.$refs.divInput.removeChild(node);
})
this.insertNode(node);
this.saveCursorLocation($event);
},
clearHtmlElem($event){
var i = 0;
var temp = $event.target.querySelectorAll("span, br");
if(temp.length > 0){
for(i = 0; i < temp.length; i++){
if(!temp[i].classList.contains('rangySelectionBoundary')){
if (temp[i].tagName == "br"){
temp[i].parentNode.removeChild(temp[i]);
} else {
temp[i].outerHTML = temp[i].innerHTML;
}
}
}
}
},
pasted($event){
$event.preventDefault();
var text = $event.clipboardData.getData('text/plain');
this.insert(document.createTextNode(text));
this.inputLength($event);
this.typed == true;
},
insert(node){
this.$refs.divInput.focus();
this.insertNode(node);
this.saveCursorLocation($event);
},
正如您在 saveCursorLocation() 中看到的那样,我试图解决您在 contentEditable div 中单击但没有插入符号的情况 - 这让用户感到困惑。
// if(this.input_length == 0 && this.typed == false){
// var div = this.$refs.divInput;
// var sel = rangy.getSelection();
// sel.collapse(div, 0);
// }
这是一个死胡同 - 很可能是因为我对 Rangy 以及我应该如何使用这些功能的理解不足。
Firefox 上的预期行为与实际结果
当我单击 contentEditable div 时,我希望插入符号出现(在后台保存我的位置)。打字时,我希望插入符号出现在最后输入的字符之后,同时也在 keyup 上以保存插入符号的位置。我还希望能够通过 left/right 箭头浏览文本并在这样做时看到插入符号。
所有这些都是由
生成的
v-on:click="..... saveCursorLocation($event);"
和
@keyup="saveCursorLocation($event);....."
如果有人认为这会有所帮助,我可以记录可编辑的内容 div 及其在 Firefox 中的行为。
编辑:我设法找出问题并将其重现到 JSFiddle - https://jsfiddle.net/Darkkz/6Landbj5/13.
要寻找什么?
- 在Firefox中打开fiddle link,然后按其中一个蓝色按钮(SI、SAU、NU),然后查看输入,没有显示插入符号。
- 点击输入,插入符号不显示
- 输入内容时,不显示插入符号。虽然,如果您在内容之间单击 word/in,插入符号将显示
显然,当用户与 contenteditable
交互时,rangy 的 Selection Save and Restore module 不能用于跟踪当前选择。
我深入研究了一下,问题是 rangy 插入隐藏的 <span>
s 作为标记,updates the selection to be after the marker,而不是将其保留在用户的 #text
节点内编辑:
<div contenteditable>
#text [This is something I typed <!-- selection is moved from here -->]
<span class="rangySelectionBoundary"/>
<!-- to here -->
</div>
Firefox 在这种情况下无法显示插入符号(我还没有发现关于这个特定问题的错误,但这里有一个类似的错误 the caret is not displayed when the selection is between two <span>
s)。
注释掉这段代码似乎可以解决插入符号消失的问题。我不清楚为什么需要该代码——它 was added before 1.0 在一个大型提交中,其消息是:"Fixes for save/restore problems with control ranges and multiple range selections. Added demos for save/restore and CSS class applier modules."——所以我不愿意建议在 rangy 中修复它(并且由于它已经有几年没有维护了,所以我对它的作者的意见不抱太大希望)。
所以我试图弄清楚你为什么首先需要这个,建议其他不涉及 rangy.saveSelection
的解决方案(例如,rangy 的 Text Range module provides getSelection().saveCharacterRanges(containerNode)
无需修改 DOM.
您似乎有一个 <div contenteditable>
和一些 "buttons" (<span>
s),单击它们会在插入符号位置插入一些 HTML。您试图解决的问题是,当单击 "buttons" 时,选择从 contenteditable
移动到按钮中,您无法检测到插入位置。
您可以制作按钮 user-select: none
,而不是存储和恢复选择 - 这将使插入符号保持可编辑。
为了测试这一点,我注释掉了所有对 rangy.saveSelection
和 rangy.restoreSelection
的引用,并更改了 "button" 的 onclick
处理程序中的 this.$refs.divInput.focus();
调用到 运行 仅当 contenteditable
尚未通过将其包装在 if (!this.$refs.divInput.contains(document.activeElement))
中获得焦点时。在这个更新的 fiddle:
中查看它是如何工作的
https://jsfiddle.net/fjxsgvm2/
这只发生在 Firefox 中。
重要提示:我用 rangy.saveSelection():
保存插入符号的位置- 点击内容可编辑div
- 在键盘上
- 将外部 html 元素(作为节点)添加到内容时可编辑 div
我需要通过多种方式不断保存位置,以便能够在点击时插入 html 个元素(我有一些标签)。
当我单击 contentEditable div 并且 div 为空(假设是第一个焦点)时,除非我开始键入,否则我看不到插入符号。如果插入符号在末尾,我也看不到它。
另一个奇怪的行为是我无法使用箭头在 contentEditable 中的文本之间导航 div。
如果我删除(不断)保存插入符号位置(输入、单击等)的功能,插入符号 returns 将恢复正常(插入符号可见)。
当我开始保存插入符号的位置时出现问题。显然,我应该进行某种重置或清除。但据我所知,这些似乎适得其反(据我所知,它们破坏了保存的插入符号位置)。
内容可编辑div
<div class="input__boolean input__boolean--no-focus">
<div
@keydown.enter.prevent
@blur="addPlaceholder"
@keyup="saveCursorLocation($event); fixDelete(); clearHtmlElem($event);"
@input="updateBooleanInput($event); clearHtmlElem($event);"
@paste="pasted"
v-on:click="clearPlaceholder(); saveCursorLocation($event);"
class="input__boolean-content"
ref="divInput"
contenteditable="true">Cuvinte cheie, cautare booleana..</div>
</div>
我的methods/functions
inputLength($event){
this.input_length = $event.target.innerText.length;
if(this.input_length == 0)
this.typed = false;
},
addPlaceholder(){
if(this.input_length == 0 && this.typed == false){
this.$refs.divInput.innerHTML = 'Cuvinte cheie, cautare booleana..'
}
},
clearPlaceholder(){
if(this.input_length == 0 && this.typed == false){
this.$refs.divInput.innerHTML = '';
}
},
updateBooleanInput($event){
this.typed = true;
this.inputLength($event);
},
saveCursorLocation($event){
if($event.which != 8){
if(this.saved_sel)
rangy.removeMarkers(this.saved_sel)
this.saved_sel = rangy.saveSelection();
}
// if(this.input_length == 0 && this.typed == false){
// var div = this.$refs.divInput;
// var sel = rangy.getSelection();
// sel.collapse(div, 0);
// }
},
insertNode: function(node){
var selection = rangy.getSelection();
var range = selection.getRangeAt(0);
range.insertNode(node);
range.setStartAfter(node);
range.setEndAfter(node);
selection.removeAllRanges();
selection.addRange(range);
},
addBooleanTag($event){
// return this.$refs.ChatInput.insertEmoji($event.img);
this.$refs.divInput.focus();
console.log(this.input_length);
if(this.typed == false & this.input_length == 0){
this.$refs.divInput.innerHTML = ''
var space = '';
this.typed = true
this.saveCursorLocation($event);
}
rangy.restoreSelection(this.saved_sel);
var node = document.createElement('img');
node.src = $event.img;
node.className = "boolean-button--img boolean-button--no-margin";
node.addEventListener('click', (event) => {
// event.currentTarget.node.setAttribute('contenteditable','false');
this.$refs.divInput.removeChild(node);
})
this.insertNode(node);
this.saveCursorLocation($event);
},
clearHtmlElem($event){
var i = 0;
var temp = $event.target.querySelectorAll("span, br");
if(temp.length > 0){
for(i = 0; i < temp.length; i++){
if(!temp[i].classList.contains('rangySelectionBoundary')){
if (temp[i].tagName == "br"){
temp[i].parentNode.removeChild(temp[i]);
} else {
temp[i].outerHTML = temp[i].innerHTML;
}
}
}
}
},
pasted($event){
$event.preventDefault();
var text = $event.clipboardData.getData('text/plain');
this.insert(document.createTextNode(text));
this.inputLength($event);
this.typed == true;
},
insert(node){
this.$refs.divInput.focus();
this.insertNode(node);
this.saveCursorLocation($event);
},
正如您在 saveCursorLocation() 中看到的那样,我试图解决您在 contentEditable div 中单击但没有插入符号的情况 - 这让用户感到困惑。
// if(this.input_length == 0 && this.typed == false){
// var div = this.$refs.divInput;
// var sel = rangy.getSelection();
// sel.collapse(div, 0);
// }
这是一个死胡同 - 很可能是因为我对 Rangy 以及我应该如何使用这些功能的理解不足。
Firefox 上的预期行为与实际结果
当我单击 contentEditable div 时,我希望插入符号出现(在后台保存我的位置)。打字时,我希望插入符号出现在最后输入的字符之后,同时也在 keyup 上以保存插入符号的位置。我还希望能够通过 left/right 箭头浏览文本并在这样做时看到插入符号。
所有这些都是由
生成的v-on:click="..... saveCursorLocation($event);"
和
@keyup="saveCursorLocation($event);....."
如果有人认为这会有所帮助,我可以记录可编辑的内容 div 及其在 Firefox 中的行为。
编辑:我设法找出问题并将其重现到 JSFiddle - https://jsfiddle.net/Darkkz/6Landbj5/13.
要寻找什么?
- 在Firefox中打开fiddle link,然后按其中一个蓝色按钮(SI、SAU、NU),然后查看输入,没有显示插入符号。
- 点击输入,插入符号不显示
- 输入内容时,不显示插入符号。虽然,如果您在内容之间单击 word/in,插入符号将显示
显然,当用户与 contenteditable
交互时,rangy 的 Selection Save and Restore module 不能用于跟踪当前选择。
我深入研究了一下,问题是 rangy 插入隐藏的 <span>
s 作为标记,updates the selection to be after the marker,而不是将其保留在用户的 #text
节点内编辑:
<div contenteditable>
#text [This is something I typed <!-- selection is moved from here -->]
<span class="rangySelectionBoundary"/>
<!-- to here -->
</div>
Firefox 在这种情况下无法显示插入符号(我还没有发现关于这个特定问题的错误,但这里有一个类似的错误 the caret is not displayed when the selection is between two <span>
s)。
注释掉这段代码似乎可以解决插入符号消失的问题。我不清楚为什么需要该代码——它 was added before 1.0 在一个大型提交中,其消息是:"Fixes for save/restore problems with control ranges and multiple range selections. Added demos for save/restore and CSS class applier modules."——所以我不愿意建议在 rangy 中修复它(并且由于它已经有几年没有维护了,所以我对它的作者的意见不抱太大希望)。
所以我试图弄清楚你为什么首先需要这个,建议其他不涉及 rangy.saveSelection
的解决方案(例如,rangy 的 Text Range module provides getSelection().saveCharacterRanges(containerNode)
无需修改 DOM.
您似乎有一个 <div contenteditable>
和一些 "buttons" (<span>
s),单击它们会在插入符号位置插入一些 HTML。您试图解决的问题是,当单击 "buttons" 时,选择从 contenteditable
移动到按钮中,您无法检测到插入位置。
您可以制作按钮 user-select: none
,而不是存储和恢复选择 - 这将使插入符号保持可编辑。
为了测试这一点,我注释掉了所有对 rangy.saveSelection
和 rangy.restoreSelection
的引用,并更改了 "button" 的 onclick
处理程序中的 this.$refs.divInput.focus();
调用到 运行 仅当 contenteditable
尚未通过将其包装在 if (!this.$refs.divInput.contains(document.activeElement))
中获得焦点时。在这个更新的 fiddle:
中查看它是如何工作的
https://jsfiddle.net/fjxsgvm2/