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
,endContainer
和endOffset
,这是创建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/
请注意,有些情况下这不起作用,主要问题是用户选择已突出显示的内容中的内容.这些情况可以处理,但您需要更多条件.
您可以使用数组来保存用户的选择!之后,将整个数组保存到数据库中!当用户再次查看该网站时,函数会比较数组中的字母和单词并突出显示它。