mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 19:35:51 +00:00
Bug 1462798 - Create a base custom element class that shares the parseXULToFragment helper;r=Paolo
MozReview-Commit-ID: IG84xKxO9Wc --HG-- extra : rebase_source : bc46d1f4dcfee66523a2ede8ec32ef9014cf170c
This commit is contained in:
parent
574e1467e0
commit
5fa9aadc74
@ -84,12 +84,8 @@ MainProcessSingleton.prototype = {
|
||||
const doc = subject;
|
||||
if (doc.nodePrincipal.isSystemPrincipal &&
|
||||
doc.contentType == "application/vnd.mozilla.xul+xml") {
|
||||
for (let script of [
|
||||
"chrome://global/content/elements/stringbundle.js",
|
||||
"chrome://global/content/elements/general.js",
|
||||
]) {
|
||||
Services.scriptloader.loadSubScript(script, doc.ownerGlobal);
|
||||
}
|
||||
Services.scriptloader.loadSubScript(
|
||||
"chrome://global/content/customElements.js", doc.ownerGlobal);
|
||||
}
|
||||
break;
|
||||
|
||||
|
73
toolkit/content/customElements.js
Normal file
73
toolkit/content/customElements.js
Normal file
@ -0,0 +1,73 @@
|
||||
/* 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) {
|
||||
let doc = gXULDOMParser.parseFromString(`
|
||||
<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.firstChild);
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
@ -46,6 +46,7 @@ toolkit.jar:
|
||||
content/global/editMenuOverlay.js
|
||||
#endif
|
||||
content/global/filepicker.properties
|
||||
content/global/customElements.js
|
||||
content/global/globalOverlay.js
|
||||
content/global/mozilla.xhtml
|
||||
content/global/aboutMozilla.css
|
||||
|
@ -101,6 +101,7 @@ skip-if = toolkit == "cocoa"
|
||||
[test_closemenu_attribute.xul]
|
||||
[test_colorpicker_popup.xul]
|
||||
[test_contextmenu_list.xul]
|
||||
[test_custom_element_base.xul]
|
||||
[test_deck.xul]
|
||||
[test_dialogfocus.xul]
|
||||
[test_findbar.xul]
|
||||
|
45
toolkit/content/tests/chrome/test_custom_element_base.xul
Normal file
45
toolkit/content/tests/chrome/test_custom_element_base.xul
Normal file
@ -0,0 +1,45 @@
|
||||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
|
||||
|
||||
<window title="Custom Element Base Class Tests"
|
||||
onload="runTests();"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
|
||||
|
||||
<!-- test results are displayed in the html:body -->
|
||||
<body xmlns="http://www.w3.org/1999/xhtml" style="height: 300px; overflow: auto;"/>
|
||||
|
||||
<!-- test code goes here -->
|
||||
<script type="application/javascript"><![CDATA[
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function runTests() {
|
||||
ok(MozXULElement, "MozXULElement defined on the window");
|
||||
testParseXULToFragment();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function testParseXULToFragment() {
|
||||
ok(MozXULElement.parseXULToFragment, "parseXULToFragment helper exists");
|
||||
|
||||
let frag = MozXULElement.parseXULToFragment(`<deck id='foo' />`);
|
||||
ok(frag instanceof DocumentFragment);
|
||||
|
||||
document.documentElement.appendChild(frag);
|
||||
|
||||
let deck = document.documentElement.lastChild;
|
||||
ok(deck instanceof MozXULElement, "instance of MozXULElement");
|
||||
ok(deck instanceof XULElement, "instance of XULElement");
|
||||
is(deck.id, "foo", "attribute set");
|
||||
is(deck.selectedIndex, "0", "Custom Element is property attached");
|
||||
deck.remove();
|
||||
}
|
||||
|
||||
]]>
|
||||
</script>
|
||||
</window>
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
{
|
||||
|
||||
class MozDeck extends XULElement {
|
||||
class MozDeck extends MozXULElement {
|
||||
set selectedIndex(val) {
|
||||
if (this.selectedIndex == val) return val;
|
||||
this.setAttribute("selectedIndex", val);
|
||||
@ -35,7 +35,7 @@ class MozDeck extends XULElement {
|
||||
|
||||
customElements.define("deck", MozDeck);
|
||||
|
||||
class MozDropmarker extends XULElement {
|
||||
class MozDropmarker extends MozXULElement {
|
||||
connectedCallback() {
|
||||
// Only create the image the first time we are connected
|
||||
if (!this.firstChild) {
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
class MozStringbundle extends XULElement {
|
||||
class MozStringbundle extends MozXULElement {
|
||||
get stringBundle() {
|
||||
if (!this._bundle) {
|
||||
try {
|
||||
|
@ -21,7 +21,7 @@
|
||||
onload="initWizard();"
|
||||
style="&window.size;">
|
||||
<script type="application/javascript"
|
||||
src="chrome://global/content/elements/stringbundle.js"/>
|
||||
src="chrome://global/content/customElements.js"/>
|
||||
|
||||
<stringbundle id="bundle_profileManager"
|
||||
src="chrome://mozapps/locale/profile/profileSelection.properties"/>
|
||||
|
@ -30,7 +30,7 @@
|
||||
buttonlabelcancel="&exit.label;">
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://global/content/elements/stringbundle.js"/>
|
||||
src="chrome://global/content/customElements.js"/>
|
||||
|
||||
<stringbundle id="bundle_profileManager"
|
||||
src="chrome://mozapps/locale/profile/profileSelection.properties"/>
|
||||
|
@ -28,6 +28,7 @@ const rootDir = helpers.rootDir;
|
||||
const EXTRA_SCRIPTS = [
|
||||
"browser/base/content/nsContextMenu.js",
|
||||
"toolkit/content/contentAreaUtils.js",
|
||||
"toolkit/content/customElements.js",
|
||||
"browser/components/places/content/editBookmark.js",
|
||||
"browser/components/downloads/content/downloads.js",
|
||||
"browser/components/downloads/content/indicator.js",
|
||||
|
Loading…
Reference in New Issue
Block a user