保存选择文本,稍后在html和javascript中显示 [英] Save selection text and show it later in html and javascript

查看:74
本文介绍了保存选择文本,稍后在html和javascript中显示的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a difficult situation with html and javascript. My html page allows user to select text and highlight it with colors. Now I want to save the state into database to show it later for that user. Of course, I can save whole html after user edited it. But I just ONLY want to save some parameters, combine with original html to show the page in the state user see last time. We can use this function:

var index = innerHTML.indexOf(text);

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

to highlight text at that index. But in case there are many same texts in the page, I want to highlight exactly word user highlighted it before.

任何人都可以通过javascript告诉我如何完成此操作?

Anyone can instruct me how to accomplish this with javascript?

我非常感谢你的帮助。

I appreciate your help a lot.

推荐答案

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

Range objects and document.execCommand allow to manipulate selection pretty easily. The main problem in your case is saving the range object in a text format.

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

Basically what you need is to get the startContainer, startOffset, endContainer and endOffset, which are the values needed to create Range objects. Offsets are number so it's pretty straightforward. Containers are Nodes, which you can't directly save as strings, so that's the main problem. One thing you can do is add keys to your DOM and save the key. But then, since in ranges containers are text nodes, you'll need to save the index of the text node. Something like this should allow to tag the DOM with keys, using a recursive function:

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);

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

Once this is done, you can convert range objects to an object that you can save as a string. Like this:

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
  }
}

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

Using this, you can save each selection that the user creates to an array. Like this:

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')
  }
});

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

To save the highlights, you save each object to JSON. To test this, you can just get the JSON string from your range objects array. Like this (this is using the get Seletion button at the top):

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

然后在加载空HTML时,你可以使用一个反向函数来创建来自你的对象的范围保存在JSON中。像这样:

Then when loading the empty HTML, you can use a reverse function that will create ranges from the objects you saved in JSON. Like this:

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;
}

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

So you could have an array of ranges in strings that you convert to objects, and then convert to Range objects that you can add. Then using execCommand, you set some formatting. Like this (this is using the set selection button at the top, you do this after refreshing the fiddle):

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')
  })
});

参见: https://jsfiddle.net/sek4tr2f/3/

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

Note that there are cases where this won't work, main problematic case is when user selects content in already highlighted content. These cases can be handled, but you'll need more conditions.

这篇关于保存选择文本,稍后在html和javascript中显示的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆