javascript 将 Range 或 DocumentFragment 转换为字符串
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4896944/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Converting Range or DocumentFragment to string
提问by SamGoody
Is there a way to get the html string of a JavaScript Range Object in W3C compliant browsers?
有没有办法在符合 W3C 的浏览器中获取 JavaScript 范围对象的 html 字符串?
For example, let us say the user selects the following: Hello <b>World</b>
It is possible to get "Hello World" as a string using the Range.toString()method.
(In Firefox, it is also possible using the document's getSelectionmethod.)
例如,假设用户选择以下内容:Hello <b>World</b>
可以使用该Range.toString()方法将“Hello World”作为字符串获取。(在 Firefox 中,也可以使用document的getSelection方法。)
But I can't seem to find a way to get the inner HTML.
但我似乎找不到获取内部 HTML 的方法。
After some searching, I've found that the range can be converted to a DocumentFragmentObject.
经过一番搜索,我发现范围可以转换为DocumentFragment对象。
But DocumentFragmentshave no innerHTMLproperty (at least in Firefox; have not tried Webkit or Opera).
Which seems odd to me: It would seem obvious that there should be some way to acces the selected items.
但是DocumentFragments没有innerHTML属性(至少在 Firefox 中;没有尝试过 Webkit 或 Opera)。
这对我来说似乎很奇怪:很明显应该有某种方法来访问所选项目。
I realize that I can create a documentFragment, append the document fragment to another element, and then get the innerHTMLof that element.
But that method will auto close any open tags within the area I select.
Besides that there surely is an obvious "better way" than attaching it to the dom just to get it as a string.
我意识到我可以创建一个documentFragment,将文档片段附加到另一个元素,然后获取该innerHTML元素的 。
但该方法将自动关闭我选择的区域内的所有打开标签。
除此之外,肯定有一个明显的“更好的方法”,而不是将它附加到 dom 只是为了将它作为一个字符串。
So, how to get the string of the html of a Range or DocFrag?
那么,如何获取 Range 或 DocFrag 的 html 字符串呢?
采纳答案by Tim Down
No, that is the only way of doing it. The DOM Level 2 specs from around 10 years ago had almost nothing in terms of serializing and deserializing nodes to and from HTML text, so you're forced to rely on extensions like innerHTML.
不,这是唯一的方法。大约 10 年前的 DOM Level 2 规范在节点与 HTML 文本之间的序列化和反序列化方面几乎没有任何内容,因此您不得不依赖innerHTML.
Regarding your comment that
关于你的评论
But that method will auto close any open tags within the area I select.
但该方法将自动关闭我选择的区域内的所有打开标签。
... how else could it work? The DOM is made up of nodes arranged in a tree. Copying content from the DOM can only create another tree of nodes. Element nodes are delimited in HTML by a start and sometimes an end tag. An HTML representation of an element that requires an end tag must have an end tag, otherwise it is not valid HTML.
……不然怎么办?DOM 由排列在树中的节点组成。从 DOM 复制内容只能创建另一个节点树。元素节点在 HTML 中由开始标记(有时是结束标记)分隔。需要结束标记的元素的 HTML 表示必须有结束标记,否则它不是有效的 HTML。
回答by Brian M. Hunt
FWIW, the jQuery way:
FWIW,jQuery 方式:
$('<div>').append(fragment).html()
回答by yuvilio
To spell out an example from here:
从这里拼出一个例子:
//Example setup of a fragment
var frag = document.createDocumentFragment(); //make your fragment
var p = document.createElement('p'); //create <p>test</p> DOM node
p.textContent = 'test';
frag.appendChild( p );
//Outputting the fragment content using a throwaway intermediary DOM element (div):
var div = document.createElement('div');
div.appendChild( frag.cloneNode(true) );
console.log(div.innerHTML); //output should be '<p>test</p>'
回答by Patrick Dark
So, how to get the string of the html of a Range or DocFrag?
那么,如何获取 Range 或 DocFrag 的 html 字符串呢?
Contrary to the other responses, it ispossible to directly turn a DocumentFragmentobject into a DOMStringusing the XMLSerializer.prototype.serializeToStringmethod described at https://w3c.github.io/DOM-Parsing/#the-xmlserializer-interface.
违背其他响应,它是可以直接把一个DocumentFragment对象到DOMString使用XMLSerializer.prototype.serializeToString在描述的方法https://w3c.github.io/DOM-Parsing/#the-xmlserializer-interface。
To get the DOMStringof a Rangeobject, simply convert it to a DocumentFragmentusing either of the Range.prototype.cloneContentsor Range.prototype.extractContentsmethods and then follow the procedure for a DocumentFragmentobject.
为了得到DOMString一个的Range对象,只需将其转换为DocumentFragment使用的两种Range.prototype.cloneContents或Range.prototype.extractContents方法,然后按照一个程序DocumentFragment对象。
I've attached a demo, but the gist of it is in these two lines:
我附上了一个演示,但它的要点在这两行中:
const serializer = new XMLSerializer();
const document_fragment_string = serializer.serializeToString(document_fragment);
(() => {
"use strict";
const HTML_namespace = "http://www.w3.org/1999/xhtml";
document.addEventListener("DOMContentLoaded", () => {
/* Create Hypothetical User Range: */
const selection = document.defaultView.getSelection();
const user_range_paragraph = document.getElementById("paragraph");
const user_range = document.createRange();
user_range.setStart(user_range_paragraph.firstChild, 0);
user_range.setEnd(user_range_paragraph.lastChild, user_range_paragraph.lastChild.length || user_range_paragraph.lastChild.childNodes.length);
selection.addRange(user_range);
/* Clone Hypothetical User Range: */
user_range.setStart(selection.anchorNode, selection.anchorOffset);
user_range.setEnd(selection.focusNode, selection.focusOffset);
const document_fragment = user_range.cloneContents();
/* Serialize the User Range to a String: */
const serializer = new XMLSerializer();
const document_fragment_string = serializer.serializeToString(document_fragment);
/* Output the Serialized User Range: */
const output_paragraph = document.createElementNS(HTML_namespace, "p");
const output_paragraph_code = document.createElementNS(HTML_namespace, "code");
output_paragraph_code.append(document_fragment_string);
output_paragraph.append(output_paragraph_code);
document.body.append(output_paragraph);
}, { "once": true });
})();
<p id="paragraph">Hello <b>World</b></p>
回答by waterplea
Another way to do it would be to iterate over childNodes:
另一种方法是迭代 childNodes:
Array.prototype.reduce.call(
documentFragment.childNodes,
(result, node) => result + (node.outerHTML || node.nodeValue),
''
);
Wouldn't work for inlined SVG, but something could be done to get it to work. It also helps if you need to dome some chained manipulation with the nodes and get an html string as a result.
不适用于内联 SVG,但可以采取一些措施使其工作。如果您需要对节点进行一些链式操作并因此获得 html 字符串,它也会有所帮助。
回答by y.c
Could DocumentFragment.textContent give you what you need?
DocumentFragment.textContent 能满足您的需求吗?
var frag = document.createRange().createContextualFragment("Hello <b>World</b>.");
console.log(frag.textContent)

