【问题标题】:How can I save a range object (from getSelection) so that I can reproduce it on a different page load?如何保存范围对象(来自 getSelection),以便在不同的页面加载时重现它?
【发布时间】:2014-05-05 18:46:48
【问题描述】:

我正在尝试制作一个 Web 应用程序,它允许用户在页面上选择一些文本,然后单击另一个按钮突出显示它。当用户返回页面时,我希望突出显示也显示在同一位置。

所以我已经做到了:

var selectedRange = document.getSelection().getRangeAt(0);
highlightRange(selectedRange);

其中 highlightRange 是一个突出显示范围的函数。到目前为止,这有效。

问题是,我需要一种方法将 selectedRange 保存到数据库中,以便以后可以再次获取它。之后,我需要根据这些数据重新创建范围并再次突出显示它。我找到了这个方法:

document.createRange();

来自此页面:https://developer.mozilla.org/en-US/docs/Web/API/range

但我不太确定如何完成这项工作

更新:

我知道之后我需要从头开始重新创建范围。为此,我将使用如下内容:

var range = document.createRange();

range.setStart(startNode,startOffset);
range.setEnd(endNode,endOffset);

我可以轻松存储 startOffset 和 endOffset,因为它们只是数字。但是 startNode 和 endNode 是节点对象。我不知道如何将其存储在数据库中?

更具体地说,我需要将 reference 存储到数据库中的节点。

【问题讨论】:

  • @JayBlanchard 我已经更详细地更新了我的帖子,谢谢。

标签: javascript jquery html dom


【解决方案1】:

我通过将范围内的 5 条信息保存到数据库中解决了这个问题:

var saveNode = range.startContainer;

var startOffset = range.startOffset;  // where the range starts
var endOffset = range.endOffset;      // where the range ends

var nodeData = saveNode.data;                       // the actual selected text
var nodeHTML = saveNode.parentElement.innerHTML;    // parent element innerHTML
var nodeTagName = saveNode.parentElement.tagName;   // parent element tag name

然后从数据库构建范围,我有这个功能:

function buildRange(startOffset, endOffset, nodeData, nodeHTML, nodeTagName){
    var cDoc = document.getElementById('content-frame').contentDocument;
    var tagList = cDoc.getElementsByTagName(nodeTagName);
    
    // find the parent element with the same innerHTML
    for (var i = 0; i < tagList.length; i++) {
        if (tagList[i].innerHTML == nodeHTML) {
            var foundEle = tagList[i];
        }
    }

    // find the node within the element by comparing node data
    var nodeList = foundEle.childNodes;
    for (var i = 0; i < nodeList.length; i++) {
        if (nodeList[i].data == nodeData) {
            var foundNode = nodeList[i];
        }
    }

    // create the range
    var range = cDoc.createRange();

    range.setStart(startNode, startOffset);
    range.setEnd(endNode, endOffset);
    return range;
}

从那里,我可以再次使用我的highlightRange 函数来突出显示文本。

2022 年 1 月更新

不知道这实际上仍在使用。我想我不妨就这两个 for 循环以及我们如何使用现代语法改进它们给出两分钱:

const foundEle = tagList.find(x => x.innerHTML === nodeHTML);
const foundNode = nodeList.find(x => x.data === nodeData);

【讨论】:

  • @Amitraj 这会阻止它跨平台吗?
  • 你从哪里得到 startNode 和 endNote 变量?您还将 foundNode 和 foundEle 置于范围之外。
  • 我知道buildRange() 函数中的startNodeendNode 是未定义的。我错过了什么吗?
  • 对于阅读此答案的任何人,这是有效的,startNodeendNodefoundNode 变量。
【解决方案2】:

当用户选择文本时运行以下脚本

let sel = window.getSelection();
let range = sel.getRangeAt(0);
let startNode = range.startContainer;
let endNode = range.endContainer;

if (startNode.nodeType == 3) {
  var startIsText = true;
  var startFlag = startNode.parentNode;
  startNode = startNode.nodeValue;
} else {
  var startIsText = false;
  var startFlag = startNode;
}
if (endNode.nodeType == 3) {
  var endIsText = true;
  var endFlag = endNode.parentNode;
  endNode = endNode.nodeValue;
} else {
  var endIsText = false;
  var endFlag = endNode;
}

let startOffset = range.startOffset; 
let endOffset = range.endOffset; 

let startTagName = startFlag.nodeName;
let startHTML = startFlag.innerHTML;

let endTagName = endFlag.nodeName;
let endHTML = endFlag.innerHTML;

//you can store this in database and use it
let rInfo = {
  startNode: startNode,
  startOffset: startOffset,
  startIsText: startIsText,
  startTagName: startTagName,
  startHTML: startHTML,

  endNode: endNode,
  endOffset: endOffset,
  endIsText: endIsText,
  endTagName: endTagName,
  endHTML: endHTML
};
window.localStorage.setItem("r", JSON.stringify(rInfo));

然后当用户返回页面时使用以下脚本

function findEle(tagName, innerHTML) {
  let list = document.getElementsByTagName(tagName);
  for (let i = 0; i < list.length; i++) {
    if (list[i].innerHTML == innerHTML) {
      return list[i];
    }
  }
}

function show(startNode,startIsText,startOffset,
          endNode,endIsText,endOffset,sP,eP) {
  var s, e;
  if (startIsText) {
    let childs = sP.childNodes;
    console.log(childs);
    for (let i = 0; i < childs.length; i++) {
      console.log(childs[i].nodeValue);
      console.log(startNode);
      if (childs[i].nodeType == 3 && childs[i].nodeValue == startNode)
        s = childs[i];
      console.log(s);
    }
  } else {
    s = startNode;
  }
  if (endIsText) {
    let childs = eP.childNodes;
    console.log(childs);
    for (let i = 0; i < childs.length; i++) {
      if (childs[i].nodeType == 3 && childs[i].nodeValue == endNode)
        e = childs[i];
      console.log(e);
    }
  } else {
    e = endNode;
  }
  let range = document.createRange();
  range.setStart(s, startOffset);
  range.setEnd(e, endOffset);

  let sel = window.getSelection();
  sel.removeAllRanges();
  sel.addRange(range);
}

function use(obj) {
  let sP = findEle(obj.startTagName, obj.startHTML);
  let eP = findEle(obj.endTagName, obj.endHTML);
  show(
    obj.startNode,
    obj.startIsText,
    obj.startOffset,
    obj.endNode,
    obj.endIsText,
    obj.endOffset,
    sP,
    eP
  );
}
let a = window.localStorage.getItem("r");
use(JSON.parse(a));

【讨论】:

    猜你喜欢
    • 2014-09-20
    • 1970-01-01
    • 2018-03-12
    • 1970-01-01
    • 2013-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多