JavaScript - 获取contentEditable div中当前行的HTML

18

我已经获得了我的contentEditablediv

div {
  width: 200px;
  height: 300px;
  border: 1px solid black;
}
<div contenteditable="true" spellcheck="false" style="font-family: Arial;">
    <b>Lorem ipsum</b> dolor sit amet, <u>consectetur adipiscing elit. 
    Morbi sagittis</u> <s>mauris porta arcu auctor, vel aliquam ligula ornare.</s> 
    Sed at <span id="someId">semper neque, et dapibus metus. 
    Maecenas dignissim est non nunc feugiat</span> 
    sollicitudin. Morbi consequat euismod consectetur. Mauris orci 
    risus, <b>porta quis erat ac, malesuada</b> fringilla odio.
</div>
    
<button>Get current line HTML</button>

我希望创建一个按钮,它可以为我提供当前行的HTML代码。例如:
当我的光标在第二行时,我想要获取:

amet, <u>consectetur</u>

或者在第七行:

<span id="someId">dapibus metus. Maecenas</span>

我尝试使用Rangy来实现,但没有成功。我怎样才能使用JavaScript和/或JQuery来做到这一点?
感谢帮助。


2
这样做可能有些困难,因为在渲染输出中,所有这些行都是一行。 - James Douglas
这个答案可能会对你有所帮助:https://dev59.com/AXRA5IYBdhLWcg3w6SXZ#31985040 - Mohamed Abbas
点击第五行应该输出vel aliquam ligula ornare。</s>?(明天之前没有时间处理这个问题,但可能有一些方法可以解决) - Kaiido
2个回答

9

8
这个解决方案基于Mozilla在Selection.modify()中提出的示例,但使用了lineboundary粒度,并且通过改变moveextend参数来实现。为了保留插入符位置,选择范围被存储或恢复。更改内容的width,编辑代码段并查看效果。你已经得到了你的HTML。

function getSelectionHtml() {
  var selection = window.document.selection,
    range, oldBrowser = true;

  if (!selection) {
    selection = window.getSelection();
    range = selection.getRangeAt(0);
    oldBrowser = false;
  } else
    range = document.selection.createRange();

  selection.modify("move", "backward", "lineboundary");
  selection.modify("extend", "forward", "lineboundary");

  if (oldBrowser) {
    var html = document.selection.createRange().htmlText;
    range.select();
    return html;
  }

  var html = document.createElement("div");

  for (var i = 0, len = selection.rangeCount; i < len; ++i) {
    html.appendChild(selection.getRangeAt(i).cloneContents());
  }

  selection.removeAllRanges();
  selection.addRange(range);
  return html.innerHTML;
}

document.getElementById("content").onmouseup = function(e) {
  var html = getSelectionHtml();
  document.getElementById("text").innerHTML = html;
  document.getElementById("code").textContent = html;
};
h4,
p {
  margin: 0;
}

#code {
  width: 100%;
  min-height: 30px;
}

#content {
  margin: 15px;
  padding: 2px;
  width: 200px;
  height: 300px;
  border: 1px solid black;
}
<textarea id="code"></textarea>
<div id="text"></div>

<div contenteditable="true" id="content" spellcheck="false" style="font-family: Arial;">
  <b>Lorem ipsum</b> dolor sit amet, <u>consectetur adipiscing elit. 
    Morbi sagittis</u> <s>mauris porta arcu auctor, vel aliquam ligula ornare.</s> Sed at <span id="someId">semper neque, et dapibus metus. 
    Maecenas dignissim est non nunc feugiat</span> sollicitudin. Morbi consequat euismod consectetur. Mauris orci risus, <b>porta quis erat ac, malesuada</b> fringilla odio.
</div>


1
我认为很接近了,但如果我理解正确的话,他也想要 HTML 标签。另外,如果是可编辑内容,改变插入符位置可能不太好,因为如果他想继续编辑,插入符会更改到行而不是位置。也许存储插入符位置,然后在单击之后返回它会解决这个问题。 - JohanSellberg
不确定 OP 真正想要什么,但如果我理解正确的话,点击第三行不应该显示 </a>,因为这是第四行的一部分。(但我再次不确定 OP 的要求)。而且我认为你也错过了 <h4> - Kaiido
@Kaiido选择范围cloneContents返回DOM节点,从而创建有效的HTML,这是一件很好的事情。让我们看看OP真正需要的是包括还是不包括'<h4>'。 - I.G. Pascual
实际上,@Kaiido,如果您查看OP示例,他包括缺失的HTML部分,使其成为有效的标记;) - I.G. Pascual

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接