зеркало из https://github.com/mozilla/gecko-dev.git
80 строки
3.0 KiB
JavaScript
80 строки
3.0 KiB
JavaScript
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
"use strict";
|
|
|
|
// This is loaded into all XUL windows. Wrap in a block to prevent
|
|
// leaking to window scope.
|
|
{
|
|
|
|
ChromeUtils.import("resource://gre/modules/Services.jsm");
|
|
|
|
const gXULDOMParser = new DOMParser();
|
|
gXULDOMParser.forceEnableXULXBL();
|
|
|
|
class MozXULElement extends XULElement {
|
|
/**
|
|
* Allows eager deterministic construction of XUL elements with XBL attached, by
|
|
* parsing an element tree and returning a DOM fragment to be inserted in the
|
|
* document before any of the inner elements is referenced by JavaScript.
|
|
*
|
|
* This process is required instead of calling the createElement method directly
|
|
* because bindings get attached when:
|
|
*
|
|
* 1) the node gets a layout frame constructed, or
|
|
* 2) the node gets its JavaScript reflector created, if it's in the document,
|
|
*
|
|
* whichever happens first. The createElement method would return a JavaScript
|
|
* reflector, but the element wouldn't be in the document, so the node wouldn't
|
|
* get XBL attached. After that point, even if the node is inserted into a
|
|
* document, it won't get XBL attached until either the frame is constructed or
|
|
* the reflector is garbage collected and the element is touched again.
|
|
*
|
|
* @param str
|
|
* String with the XML representation of XUL elements.
|
|
*
|
|
* @return DocumentFragment containing the corresponding element tree, including
|
|
* element nodes but excluding any text node.
|
|
*/
|
|
static parseXULToFragment(str, entities = "") {
|
|
let doc = gXULDOMParser.parseFromString(`
|
|
${entities}
|
|
<box xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
|
${str}
|
|
</box>
|
|
`, "application/xml");
|
|
// The XUL/XBL parser is set to ignore all-whitespace nodes, whereas (X)HTML
|
|
// does not do this. Most XUL code assumes that the whitespace has been
|
|
// stripped out, so we simply remove all text nodes after using the parser.
|
|
let nodeIterator = doc.createNodeIterator(doc, NodeFilter.SHOW_TEXT);
|
|
let currentNode = nodeIterator.nextNode();
|
|
while (currentNode) {
|
|
currentNode.remove();
|
|
currentNode = nodeIterator.nextNode();
|
|
}
|
|
// We use a range here so that we don't access the inner DOM elements from
|
|
// JavaScript before they are imported and inserted into a document.
|
|
let range = doc.createRange();
|
|
range.selectNodeContents(doc.querySelector("box"));
|
|
return range.extractContents();
|
|
}
|
|
}
|
|
|
|
// Attach the base class to the window so other scripts can use it:
|
|
window.MozXULElement = MozXULElement;
|
|
|
|
for (let script of [
|
|
"chrome://global/content/elements/stringbundle.js",
|
|
"chrome://global/content/elements/general.js",
|
|
]) {
|
|
Services.scriptloader.loadSubScript(script, window);
|
|
}
|
|
|
|
customElements.setElementCreationCallback("printpreview-toolbar", type => {
|
|
Services.scriptloader.loadSubScript(
|
|
"chrome://global/content/printPreviewToolbar.js", window);
|
|
});
|
|
|
|
}
|