替换 HTML,然后将文档片段添加回 html



我正在尝试创建一个高光工具,其工作原理如下:

  • 用户首先选择文本范围。
  • 然后,他们单击其中一个颜色按钮,所选文本的背景将突出显示
  • 然后他们选择另一个范围的文本...
  • 现在,当他们单击按钮时,所有html都将替换为html的缓存版本(无突出显示)
  • 然后,已突出显示的新选定文本将追加回新 html。

这样,一次只能突出显示一个范围的文本。

问题:

我很难理解范围、选择和节点 API

目前我无法将突出显示的文本添加回新的 html 中......我只是将其附加到文档正文中。

到目前为止,我拥有的:

https://jsfiddle.net/4mb39jd6/

(function(){
var highlighter = {
/**
*
*/
init: function(){
this.cacheDOM();
this.bindEvents();
},
/**
*
*/
cacheDOM: function(){
this.$html           = $('.content').html();
this.$content        = $('.content');
this.$highlighter    = $('.highlighter');
},
/**
*
*/
bindEvents: function(){
this.$highlighter.on('mousedown', this.highlightSelection.bind(this));
},
/**
*
*/
highlightSelection: function(e){
var selection = window.getSelection();          // get selection
var text      = selection.toString();           // get selected text
var newNode   = document.createElement('span'); // create node
newNode.style.backgroundColor = $(e.target).css('backgroundColor'); // set node properties
newNode.appendChild(document.createTextNode(text));                 // append selection text to node
var range = selection.getRangeAt(0);      // 2 - get the selected range
range.deleteContents();                   // delete the contents
range.insertNode(newNode);                // insert the new node with the replacement text
documentFragment = range.cloneContents(); // clone the node
this.$content.html(this.$html);              // refresh the content
document.body.appendChild(documentFragment); // add the new highlighted text
},
};
highlighter.init();
})();

问:

如何添加突出显示的节点...看起来像这样<span style="background-color: rgb(255, 255, 131);">some random text</span>回到一个新的 HTML 文档中,以便它处于相同的位置。

如果目标是一次只有一个亮点,我会选择一种不太复杂的方法:

  • 添加突出显示时,
  • 检查 html 中是否有上一个突出显示,
  • 找到后将其删除

为此,请使用属性或类标记突出显示<span>(或者更好的是,存储引用):

newNode.classList.add("js-highlight");

添加一个方法来删除此类元素:

clearHighlight: function() {
var selection = document.querySelector(".js-highlight");
if (selection) {
selection.parentElement.replaceChild(
document.createTextNode(selection.innerText),
selection  
);
}
}

然后,在将range替换为突出显示元素之前,请调用clearHighlight

示例:https://jsfiddle.net/2tqdLfb1/

另一种选择:

我还尝试了另一种尊重您的"缓存 HTML"逻辑的方法,但发现它过于复杂。该方法的基础知识:

  • 检查所选内容parentElement的查询路径
  • 存储所选内容的开始索引和结束索引
  • 将 HTML
  • 替换为缓存的 HTML 字符串
  • 通过存储的查询路径查找所选内容的新注入父元素
  • 根据选择开始和结束索引将其innerText拆分为 1、2 或 3textNodes
  • 代表所选内容的 textNode 替换为突出显示<span>

演示如何存储范围祖先的查询路径的示例:

function getPathUpToSelector(selector, element, path) {
var parent = element.parentElement;
if (parent && !element.matches(selector)) {
var index = Array.from(parent.children).indexOf(element) + 1;
path.push("*:nth-child(" + index + ")");
return getPathUpToSelector(selector, parent, path);
}
return [selector].concat(path).join(" > ");
}

最新更新