替换 HTML 然后将文档片段添加回 html
Replacing HTML then adding a document fragment back into the html
我正在尝试创建一个像这样工作的荧光笔工具:
- 用户首先select输入一段文本。
- 然后他们单击其中一个颜色按钮,selected 文本的背景会突出显示
- 然后他们 select 另一个文本范围...
- 现在,当他们单击按钮时,所有 html 都将替换为 html 的缓存版本(无突出显示)
- 然后新的 selected 突出显示的文本被追加回新的 html。
这样一次只能突出显示一个范围内的文本。
问题:
我很难理解 Range, Selection and Node API 的
目前我无法将突出显示的文本添加回新 html...我只是将其附加到 document.body。
我目前有:
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 上一个突出显示,
- 找到后删除
为此,请使用属性或 class 标记您的突出显示 <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/
替代方案:
我还尝试了另一种尊重您的 "cached HTML" 逻辑的方法,但发现它过于复杂。该方法的基础知识:
- 检查所选
parentElement
的查询路径
- 存储选择的开始索引和结束索引
- 用缓存的HTML字符串替换HTML
- 通过存储的query-path找到selection新注入的父元素
- 根据选择的开始和结束索引将其
innerText
拆分为 1、2 或 3 textNodes
- 用您的突出显示替换表示选择的 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(" > ");
}
我正在尝试创建一个像这样工作的荧光笔工具:
- 用户首先select输入一段文本。
- 然后他们单击其中一个颜色按钮,selected 文本的背景会突出显示
- 然后他们 select 另一个文本范围...
- 现在,当他们单击按钮时,所有 html 都将替换为 html 的缓存版本(无突出显示)
- 然后新的 selected 突出显示的文本被追加回新的 html。
这样一次只能突出显示一个范围内的文本。
问题:
我很难理解 Range, Selection and Node API 的
目前我无法将突出显示的文本添加回新 html...我只是将其附加到 document.body。
我目前有:
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 上一个突出显示,
- 找到后删除
为此,请使用属性或 class 标记您的突出显示 <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/
替代方案:
我还尝试了另一种尊重您的 "cached HTML" 逻辑的方法,但发现它过于复杂。该方法的基础知识:
- 检查所选
parentElement
的查询路径 - 存储选择的开始索引和结束索引
- 用缓存的HTML字符串替换HTML
- 通过存储的query-path找到selection新注入的父元素
- 根据选择的开始和结束索引将其
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(" > ");
}