保存选择文本,稍后在html和javascript中显示

use*_*659 19 html javascript jquery

我有一个困难的情况与HTML和JavaScript.我的html页面允许用户选择文本并用颜色突出显示.现在我想将状态保存到数据库中以便稍后为该用户显示它.当然,我可以在用户编辑后保存整个html.但我只想保存一些参数,结合原始html显示状态用户上次查看的页面.我们可以使用这个功能:

var index = innerHTML.indexOf(text);
Run Code Online (Sandbox Code Playgroud)

突出显示该索引处的文本.但是如果页面中有很多相同的文本,我想要突出显示之前用户突出显示的文字.

任何人都可以通过javascript告诉我如何实现这一目标?

我非常感谢你的帮助.

Jul*_*ire 10

Range对象并document.execCommand允许很容易地操纵选择.您的主要问题是以文本格式保存范围对象.

基本上,你需要的是得到startContainer,startOffset,endContainerendOffset,这是创建Range对象所需的值.Offsets是数字所以它非常简单.容器是节点,您无法直接将其保存为字符串,因此这是主要问题.您可以做的一件事是为DOM添加密钥并保存密钥.但是,由于在范围容器中是文本节点,因此您需要保存文本节点的索引.这样的东西应该允许使用递归函数用键标记DOM:

function addKey(element) {
  if (element.children.length > 0) {
    Array.prototype.forEach.call(element.children, function(each, i) {
      each.dataset.key = key++;
      addKey(each)
    });
  }
};

addKey(document.body);
Run Code Online (Sandbox Code Playgroud)

完成此操作后,您可以将范围对象转换为可以保存为字符串的对象.像这样:

function rangeToObj(range) {
  return {
    startKey: range.startContainer.parentNode.dataset.key,
    startTextIndex: Array.prototype.indexOf.call(range.startContainer.parentNode.childNodes, range.startContainer),
    endKey: range.endContainer.parentNode.dataset.key,
    endTextIndex: Array.prototype.indexOf.call(range.endContainer.parentNode.childNodes, range.endContainer),
    startOffset: range.startOffset,
    endOffset: range.endOffset
  }
}
Run Code Online (Sandbox Code Playgroud)

使用此选项,您可以将用户创建的每个选择保存到数组中.像这样:

document.getElementById('textToSelect').addEventListener('mouseup', function(e) {
  if (confirm('highlight?')) {
    var range = document.getSelection().getRangeAt(0);
    selectArray.push(rangeToObj(range));
    document.execCommand('hiliteColor', false, 'yellow')
  }
});
Run Code Online (Sandbox Code Playgroud)

要保存突出显示,请将每个对象保存为JSON.要对此进行测试,您只需从范围对象数组中获取JSON字符串即可.像这样(这是使用顶部的get Seletion按钮):

document.getElementById('getSelectionString').addEventListener('click', function() {
  alert('Copy string to save selections: ' + JSON.stringify(selectArray));
});
Run Code Online (Sandbox Code Playgroud)

然后在加载空HTML时,您可以使用反向函数,该函数将使用您在JSON中保存的对象创建范围.像这样:

function objToRange(rangeStr) {
  range = document.createRange();
  range.setStart(document.querySelector('[data-key="' + rangeStr.startKey + '"]').childNodes[rangeStr.startTextIndex], rangeStr.startOffset);
  range.setEnd(document.querySelector('[data-key="' + rangeStr.endKey + '"]').childNodes[rangeStr.endTextIndex], rangeStr.endOffset);
  return range;
}
Run Code Online (Sandbox Code Playgroud)

因此,您可以在字符串中使用转换为对象的范围数组,然后转换为可以添加的Range对象.然后使用execCommand设置一些格式.像这样(这是使用顶部的设置选择按钮,你在刷新小提琴后这样做):

document.getElementById('setSelection').addEventListener('click', function() {
  var selStr = prompt('Paste string');
  var selArr = JSON.parse(selStr);
  var sel = getSelection();
  selArr.forEach(function(each) {
    sel.removeAllRanges();
    sel.addRange(objToRange(each));
    document.execCommand('hiliteColor', false, 'yellow')
  })
});
Run Code Online (Sandbox Code Playgroud)

请参阅:https://jsfiddle.net/sek4tr2f/3/

请注意,有些情况下这不起作用,主要问题是用户选择已突出显示的内容中的内容.这些情况可以处理,但您需要更多条件.


Ash*_*Ash 0

您可以使用数组来保存用户的选择!之后,将整个数组保存到数据库中!当用户再次查看该网站时,函数会比较数组中的字母和单词并突出显示它。

  • 是的。我怀疑,“如何做到这一点”就是问题所在。 (2认同)