【问题标题】:Get selected text position inside div and persist获取 div 内选定的文本位置并保留
【发布时间】:2018-08-23 23:09:01
【问题描述】:

我正在尝试获取所选文本的位置,将其替换为一些 HTML,然后我想保留所选文本的位置,以便下次渲染 html 时,我想在选定的文字

我在 Div 中显示了一些内容

现在我选择文本“De finibus 的加扰部分”,它位于第 2 行并且从开始的一些偏移量开始。我将此文本替换为文本周围的跨度,例如:

function textSelection() {
  var sel = window.getSelection();
  var range = sel.getRangeAt(0).cloneRange();
  var markerTextChar = range.extractContents();

  var markerEl, markerId = "sel_" + new Date().getTime() + "_" + Math.random().toString().substr(2);
  markerEl = document.createElement("span");
  markerEl.id = markerId;

  markerEl.appendChild(markerTextChar);

  range.insertNode(markerEl);

  markerEl.style.backgroundColor = ' rgba(246,195,66,0.3)';
  markerEl.style.cursor = 'pointer';

}
<div id='page-view' onmouseup='textSelection()'> In publishing and graphic design, lorem ipsum is a filler text or greeking commonly used to demonstrate the textual elements of a graphic document or visual presentation. Replacing meaningful content with placeholder text allows designers to design the
  form of the content before the content itself has been produced. The lorem ipsum text is typically a scrambled section of De finibus bonorum et malorum, a 1st-century BC Latin text by Cicero, with words altered, added, and removed to make it nonsensical,
  improper Latin.
</div>

现在我向这个跨度添加样式以突出显示选择。现在我要做的是保存这个位置,以便下次显示 html 页面时,我想突出显示相同的选择。请注意,在其他位置可能会重复相同的选定文本,因此我不想无意中突出显示错误的位置。

  1. 有什么方法可以实现吗?
  2. 包含 Div 的文本没有“contenteditable”属性
  3. 到目前为止,我所拥有的是获取所选文本的“clientRects”并创建一个 div 并向该 div 添加样式并附加到正文,但我不想这样做
  4. 实际文本的 HTML 是在后端使用 MarkDown 等标记语言解析器生成的

编辑:

让我添加更多细节。像 github wiki 一样,我通过解析内容并根据所选语言模式(如 Markdown/Textile)生成 html 来显示 wiki 的内容。我想要一种在编辑页面时以某种方式将所选文本映射到实际文本行号的方法。单击页面编辑时,使用 codemirror 代码编辑器显示内容。

谢谢

【问题讨论】:

  • 请修复我为您制作的 sn-p - 例如通过添加事件处理程序
  • @mplungjan 谢谢,刚刚更正了 sn-p
  • 反对者:请解释一下..
  • @mplungjan 你对此有什么想法吗?
  • 不超过你得到的。 SO 用户确实希望发布者具有一定程度的能力来接受建议并自定义代码以供自己使用,而不是免费实现您的所有规范。在任何情况下,使用差异类型工具可能会更好地处理您正在尝试做的事情

标签: javascript html markdown codemirror textselection


【解决方案1】:

您还可以从选择范围range.startOffsetrange.endOffset 中提取信息。

更新:

您可以将所选元素作为参数传递,然后从那里,您将知道使用了哪个节点。简单来说,只需为您允许用户进行选择的每个元素设置一个唯一的 id。

// extract page content first because content will be changed after a few selection.
var page_content = document.getElementById('page-view').innerText;

function textSelection(element) {
  console.log('selected on', element.id);
  var sel = window.getSelection();
  //console.log(sel);
  var range = sel.getRangeAt(0).cloneRange();
  console.log("from", range.startOffset, "to", range.endOffset);
  var markerTextChar = range.extractContents();

  var markerEl, markerId = "sel_" + new Date().getTime() + "_" + Math.random().toString().substr(2);
  markerEl = document.createElement("span");
  markerEl.id = markerId;

  markerEl.appendChild(markerTextChar);

  range.insertNode(markerEl);

  markerEl.style.backgroundColor = ' rgba(246,195,66,0.3)';
  markerEl.style.cursor = 'pointer';

}
<div id='page-view' onmouseup='textSelection(this)'> In publishing and graphic design, lorem ipsum is a filler text or greeking commonly used to demonstrate the textual elements of a graphic document or visual presentation. Replacing meaningful content with placeholder text allows designers to design the
  form of the content before the content itself has been produced. The lorem ipsum text is typically a scrambled section of De finibus bonorum et malorum, a 1st-century BC Latin text by Cicero, with words altered, added, and removed to make it nonsensical,
  improper Latin. demonstrate the textual
</div>

【讨论】:

  • 如何在页面刷新时使用此信息再次突出显示文本?我需要进行文本选择的行号。更重要的是,可能有多个段落,其他元素也像列表、锚标签等,就像普通的页面内容一样
  • 对不起,如果我之前不清楚。文本内容在后端使用 Markdown 解析器转换为 html。因此,如果我们有一个类似 "Test content here" 的内容,它会从后端转换为

    Test content here

    并简单地将这个内容呈现在一个 div 中。所以不能有唯一的ID
  • @h-kach 您可以通过一个简单的 API 将选择保存到数据库中,并在页面加载后将其作为 JSON 加载到前端。之后,您可以使用 javascript 从 JSON 数据中重新生成选择。
  • 通过 'Selections' ,您的意思是选定的文本?是的,我可以保存它。但这不会是足够的信息吧?我需要文本的确切位置,以便我可以重新突出显示。如果我只是保存文本,那么如果页面其他部分有类似的内容,那么高亮位置将不正确
【解决方案2】:

首先,您必须获取 div 的内容,然后您可以使用 indexOf 获取所选文本的位置。在将所选文本包装到 span 之前执行此操作。现在您将获得所选文本的索引和长度,使用这些信息您可以随时重建选择。

// extract page content first because content will be changed after a few selection.
var page_content = document.getElementById('page-view').innerText;

function textSelection() {
  var sel = window.getSelection();
  var range = sel.getRangeAt(0).cloneRange();
  var markerTextChar = range.extractContents();

  var selectedIndex = page_content.indexOf(markerTextChar.textContent);
  console.log("selected from ", selectedIndex, "length: ", markerTextChar.textContent.length)
  var markerEl, markerId = "sel_" + new Date().getTime() + "_" + Math.random().toString().substr(2);
  markerEl = document.createElement("span");
  markerEl.id = markerId;

  markerEl.appendChild(markerTextChar);

  range.insertNode(markerEl);

  markerEl.style.backgroundColor = ' rgba(246,195,66,0.3)';
  markerEl.style.cursor = 'pointer';

}
<div id='page-view' onmouseup='textSelection()'> In publishing and graphic design, lorem ipsum is a filler text or greeking commonly used to demonstrate the textual elements of a graphic document or visual presentation. Replacing meaningful content with placeholder text allows designers to design the
  form of the content before the content itself has been produced. The lorem ipsum text is typically a scrambled section of De finibus bonorum et malorum, a 1st-century BC Latin text by Cicero, with words altered, added, and removed to make it nonsensical,
  improper Latin.
  
  demonstrate the textual
</div>

【讨论】:

  • 当我们在 div 中有重复的文本时,它没有提供足够的信息。请看我的补充。问题是如何区分位于不同位置的 2 个相同的文本选择
  • 另外,可能有多个段落,不同种类的元素,比如列表
猜你喜欢
  • 2011-07-07
  • 1970-01-01
  • 2011-07-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-07
  • 1970-01-01
  • 2013-08-28
相关资源
最近更新 更多