Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/75.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript Contenteditable DIV-如何确定光标是位于内容的开头还是结尾_Javascript_Html_Dom_Contenteditable_Rangy - Fatal编程技术网

Javascript Contenteditable DIV-如何确定光标是位于内容的开头还是结尾

Javascript Contenteditable DIV-如何确定光标是位于内容的开头还是结尾,javascript,html,dom,contenteditable,rangy,Javascript,Html,Dom,Contenteditable,Rangy,我有一个contenteditable div,其中包含典型的wysiwyg编辑器html(粗体、锚定、列表) 我需要确定当前光标是否为onKeyDown,位于div的开始和结束处。原因是,根据光标位置和按下的键,我可能希望在退格中将此div与上一个div合并,或者在回车时创建新的后续div 我一直在摆弄范围,但当您在元素中使用html时,事情变得相当复杂 我希望我一定忽略了一些简单的解决方案 是否有一个相对简单的方法来确定这一点-我愿意使用像Rangy这样的库 谢谢 编辑:我的想法大致如下:

我有一个contenteditable div,其中包含典型的wysiwyg编辑器html(粗体、锚定、列表)

我需要确定当前光标是否为onKeyDown,位于div的开始和结束处。原因是,根据光标位置和按下的键,我可能希望在退格中将此div与上一个div合并,或者在回车时创建新的后续div

我一直在摆弄范围,但当您在元素中使用html时,事情变得相当复杂

我希望我一定忽略了一些简单的解决方案

是否有一个相对简单的方法来确定这一点-我愿意使用像Rangy这样的库

谢谢

编辑:我的想法大致如下:

$('.mycontenteditable').bind('keydown', handle_keydown)

handle_keydown = function(e) {

  range = window.getSelection().getRangeAt(0)
  start_range = document.createRange()
  start_range.selectNodeContents(this.firstChild)
  start_range.collapse(true) // collapse to start
  is_start = start_range.compareBoundaryPoints(Range.START_TO_START,range)
  end_range = document.createRange()
  end_range.selectNodeContents(this.lastChild)
  end_range.collapse(false)
  is_end = end_range.compareBoundaryPoints(Range.END_TO_END,range)
}

我会遇到这样的奇怪问题吗?

我就是这样解决的。我上面提出的解决方案有时有效,但有很多边缘情况,因此我最终考虑光标前后有多少文本,如果是0个字符,那么我就在开始或结束处:

handle_keydown = function(e) {
  // Get the current cusor position
  range = window.getSelection().getRangeAt(0)
  // Create a new range to deal with text before the cursor
  pre_range = document.createRange();
  // Have this range select the entire contents of the editable div
  pre_range.selectNodeContents(this);
  // Set the end point of this range to the start point of the cursor
  pre_range.setEnd(range.startContainer, range.startOffset);
  // Fetch the contents of this range (text before the cursor)
  this_text = pre_range.cloneContents();
  // If the text's length is 0, we're at the start of the div.
  at_start = this_text.textContent.length === 0;
  // Rinse and repeat for text after the cursor to determine if we're at the end.
  post_range = document.createRange();
  post_range.selectNodeContents(this);
  post_range.setStart(range.endContainer, range.endOffset);
  next_text = post_range.cloneContents();
  at_end = next_text.textContent.length === 0;
}

仍然不完全确定是否存在其他边缘情况,因为我不完全确定如何对此进行单元测试,因为它需要鼠标交互-可能在某个地方有一个库来处理此问题。

除了使用
toString()之外,我将使用与您类似的方法
使用
Range
对象而不是
cloneContents()
的方法,以避免不必要的克隆。此外,在IE<9(不支持范围)中,您可以对
TextRange
text
属性使用类似的方法

请注意,如果内容中存在前导和/或尾随换行符,则会出现问题,因为范围的
toString()
方法的工作方式与节点的
textContent
属性类似,只考虑文本节点,因此不考虑

或块元素所隐含的换行符。CSS也没有被考虑在内:例如,通过
display:none
隐藏的元素中的文本被包括在内

下面是一个例子:

现场演示:

代码:


今天我遇到了同样的问题,没有干净的解决方案,所以我开发了以下方法。它只使用
选择
-无
范围
或特定于供应商的功能。它还考虑了内容开头和结尾的换行符

它适用于当前的Chrome、Firefox、Safari和Opera。 Microsoft Edge再次成为异常值,因为当内容的开头或结尾有换行符时,文本选择本身在
contenteditable
div
s中会部分中断。不幸的是,我还没有找到解决这个问题的方法

还值得注意的是,逻辑不仅在浏览器之间不同,而且在
空白
模式(
normal
pre*
)之间也不同,因为浏览器在键入时会为每个模式生成不同的节点

document.addEventListener(“selectionchange”,function()){
UpdateCartInfo(document.getElementById('input-normal'))
UpdateCartInfo(document.getElementById('input-pre'))
});
函数UPDATECARTINFO(输入){
函数isAcceptalNode(节点,侧){
如果(node==input){return true}
const childProperty=side=='start'?'firstChild':'lastChild'
while(node&&node.parentNode&&node.parentNode[childProperty]==node){
if(node.parentNode==输入){
返回真值
}
node=node.parentNode
}
返回错误
}
函数isAcceptableOffset(偏移、节点、边){
如果(侧==‘开始’){
返回偏移量===0
}
if(node.nodeType===node.TEXT\u节点){
返回偏移量>=node.textContent.replace(/\n$/,'').length
}
否则{
返回偏移量>=node.childNodes.length-1
}
}
功能为可接受选择(选择,侧面){
返回选择&&
selection.iscollected&&
isAcceptableNode(selection.anchorNode,侧面)&&
isAcceptableOffset(selection.anchorOffset,selection.anchorNode,side)
}
const selection=document.getSelection()
const isAtStart=isAcceptableSelection(选择“开始”)
常量IsAttend=isAcceptableSelection(选择“结束”)
document.getElementById('start-'+input.id)。innerText=isAtStart?'YES':'no'
document.getElementById('end-'+input.id)。innerText=isattend?'YES':'no'
}
正文{
填充:10px;
}
[id^=“输入-”]{
边框:1px纯黑;
显示:内联块;
边缘底部:10px;
填充物:5px;
}
将插入符号移到这里!
(
空白:正常
) 起始插入符号:否
结尾插入符号:否


将插入符号移到这里! (
空白:预换行
) 起始插入符号:否
结尾插入符号:否

我想出了一个非常一致且简短的方法:

function isAtTextEnd() {
    var sel = window.getSelection(),
      offset = sel.focusOffset;
  sel.modify ("move","forward","character");
  if (offset == sel.focusOffset) return true;
  else {
    sel.modify ("move","backward","character");
    return false;
  }
}
关键:尝试将其向前移动一个字符-如果它实际移动: 不在结尾(向后移动一个字符),如果没有-它在结尾(不需要向后移动,它没有移动)。
实现文本的开头是相反的,是“留给读者的练习”

空洞:

  • MDN标记为“非标准”,但兼容性 表中显示了相当广泛的支持(根据表中所示,测试可在最新的Chrome和Firefox上工作-在Edge中不受支持)。
    我尝试使用更受支持的
    extend()

  • 如果您检查用户启动插入符号移动后(例如,在键盘或鼠标事件处理程序中)-您应该处理该检查强制插入符号以意外方式移动的情况


检查光标/插入符号是否位于
function isAtTextEnd() {
    var sel = window.getSelection(),
      offset = sel.focusOffset;
  sel.modify ("move","forward","character");
  if (offset == sel.focusOffset) return true;
  else {
    sel.modify ("move","backward","character");
    return false;
  }
}
this.$('input').addEventListener('keydown', (e) => {
  if (e.target.selectionEnd == e.target.value.length) {
    // DO SOMETHING
  }
})