bzbarsky%mit.edu 16f1f02320 Make getElementsByAttribute be an nsContentList so that it's got that live
DOMNodeList goodness that all nodelists should have.  Change some JS to not
break, and some other JS to be a little more efficient with the new world of
lazy listness.  Bug 240186, r=neil on the JS changes, r=jst on the content
changes, sr=jst


git-svn-id: svn://10.0.0.236/trunk@154907 18797224-902f-48f8-a5cc-f745e15eee43
2004-04-15 01:51:32 +00:00

518 lines
18 KiB
XML

<?xml version="1.0"?>
<bindings id="wizardBindings"
xmlns="http://www.mozilla.org/xbl"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:xbl="http://www.mozilla.org/xbl">
<binding id="wizard-base">
<resources>
<stylesheet src="chrome://global/skin/wizard.css"/>
</resources>
</binding>
<binding id="wizard" extends="chrome://global/content/bindings/wizard.xml#wizard-base">
<content>
<xul:hbox class="wizard-header" anonid="Header"/>
<xul:deck class="wizard-page-box" flex="1" anonid="Deck">
<children includes="wizardpage"/>
</xul:deck>
<children/>
<xul:hbox class="wizard-buttons" anonid="Buttons" xbl:inherits="pagestep,firstpage,lastpage"/>
</content>
<implementation>
<property name="title" onget="return this.getAttribute('title')"
onset="this.setAttribute('title', val);"/>
<property name="canAdvance" onget="return this._canAdvance;"
onset="this._canAdvance=val; this._nextButton.setAttribute('disabled', !val);"/>
<property name="canRewind" onget="return this._canRewind;"
onset="this._canRewind=val; this._backButton.setAttribute('disabled', !val);"/>
<property name="pageStep" onget="return this._pageStack.length"/>
<field name="pageCount">0</field>
<field name="_accessMethod">null</field>
<field name="_pageStack">null</field>
<field name="_currentPage">null</field>
<property name="wizardPages">
<getter>
<![CDATA[
var xulns = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
return this.getElementsByTagNameNS(xulns, "wizardpage");
]]>
</getter>
</property>
<property name="currentPage" onget="return this._currentPage">
<setter>
<![CDATA[
if (!val)
return val;
this._currentPage = val;
// Setting this attribute allows wizard's clients to dynamically
// change the styles of each page based on purpose of the page.
this.setAttribute("currentpageid", val.pageid);
if (this.onFirstPage) {
this.canRewind = false;
this.setAttribute("firstpage", "true");
} else {
this.canRewind = true;
this.setAttribute("firstpage", "false");
}
if (this.onLastPage) {
this.canAdvance = true;
this.setAttribute("lastpage", "true");
} else {
this.setAttribute("lastpage", "false");
}
this._deck.setAttribute("selectedIndex", val.pageIndex);
this._advanceFocusToPage(val);
this._adjustWizardHeader();
this._wizardButtons.onPageChange();
this._fireEvent(val, "pageshow");
return val;
]]>
</setter>
</property>
<property name="pageIndex" onget="return this._pageIndex;">
<setter>
<![CDATA[
if (val < 0 || val >= this.pageCount)
return this._pageIndex;
this.currentPage = this.wizardPages[val];
]]>
</setter>
</property>
<property name="onFirstPage"
onget="return this._pageStack.length == 1;"/>
<property name="onLastPage">
<getter><![CDATA[
var cp = this.currentPage;
return cp && ((this._accessMethod == "sequential" && cp.pageIndex == this.pageCount-1) ||
(this._accessMethod == "random" && cp.next == ""));
]]></getter>
</property>
<method name="getButton">
<parameter name="aDlgType"/>
<body>
<![CDATA[
var btns = this.getElementsByAttribute("dlgtype", aDlgType);
return btns.item(0) ? btns[0] : document.getAnonymousElementByAttribute(this._wizardButtons, "dlgtype", aDlgType);
]]>
</body>
</method>
<field name="_canAdvance"/>
<field name="_canRewind"/>
<field name="_wizardHeader"/>
<field name="_wizardButtons"/>
<field name="_deck"/>
<field name="_backButton"/>
<field name="_nextButton"/>
<field name="_cancelButton"/>
<!-- functions to be added as oncommand listeners to the wizard buttons -->
<field name="_backFunc">(function() { document.documentElement.rewind(); })</field>
<field name="_nextFunc">(function() { document.documentElement.advance(); })</field>
<field name="_finishFunc">(function() { document.documentElement.advance(); })</field>
<field name="_cancelFunc">(function() { document.documentElement.cancel(); })</field>
<field name="_closeHandler">(function(event) {
if (document.documentElement.cancel())
event.preventDefault();
})</field>
<constructor><![CDATA[
this._canAdvance = true;
this._canRewind = false;
this._hasLoaded = false;
this._pageStack = [];
// need to create string bundle manually instead of using <xul:stringbundle/>
// see bug 63370 for details
var localeService = Components.classes["@mozilla.org/intl/nslocaleservice;1"]
.getService(Components.interfaces.nsILocaleService);
var stringBundleService = Components.classes["@mozilla.org/intl/stringbundle;1"].getService(Components.interfaces.nsIStringBundleService);
var bundleURL = "chrome://global/locale/wizard.properties";
this._bundle = stringBundleService.createBundle(bundleURL, localeService.getApplicationLocale());
// get anonymous content references
this._wizardHeader = document.getAnonymousElementByAttribute(this, "anonid", "Header");
this._wizardButtons = document.getAnonymousElementByAttribute(this, "anonid", "Buttons");
this._deck = document.getAnonymousElementByAttribute(this, "anonid", "Deck");
this._initWizardButton("back");
this._initWizardButton("next");
this._initWizardButton("finish");
this._initWizardButton("cancel");
this._initPages();
window.addEventListener("close", this._closeHandler, false);
// start off on the first page
this.pageCount = this.wizardPages.length;
this.advance();
// give focus to the first focusable element in the dialog
window.addEventListener("load", this._setInitialFocus, false);
]]></constructor>
<method name="getPageById">
<parameter name="aPageId"/>
<body><![CDATA[
var els = this.getElementsByAttribute("pageid", aPageId);
return els.item(0);
]]></body>
</method>
<method name="rewind">
<body><![CDATA[
if (!this.canRewind)
return;
if (this.currentPage && !this._fireEvent(this.currentPage, "pagehide"))
return;
if (this.currentPage && !this._fireEvent(this.currentPage, "pagerewound"))
return;
if (!this._fireEvent(this, "wizardback"))
return;
this._pageStack.pop();
this.currentPage = this._pageStack[this._pageStack.length-1];
this.setAttribute("pagestep", this._pageStack.length);
]]></body>
</method>
<method name="advance">
<parameter name="aPageId"/>
<body><![CDATA[
if (!this.canAdvance)
return;
if (this.currentPage && !this._fireEvent(this.currentPage, "pagehide"))
return;
if (this.currentPage && !this._fireEvent(this.currentPage, "pageadvanced"))
return;
if (this.onLastPage) {
if (this._fireEvent(this, "wizardfinish"))
window.setTimeout(function() {window.close();}, 1);
} else {
if (!this._fireEvent(this, "wizardnext"))
return;
var page;
if (aPageId)
page = this.getPageById(aPageId);
else {
if (this.currentPage) {
if (this._accessMethod == "random")
page = this.getPageById(this.currentPage.next);
else
page = this.wizardPages[this.currentPage.pageIndex+1];
} else
page = this.wizardPages[0];
}
if (page) {
this._pageStack.push(page);
this.setAttribute("pagestep", this._pageStack.length);
this.currentPage = page;
}
}
]]></body>
</method>
<method name="goTo">
<parameter name="aPageId"/>
<body><![CDATA[
var page = this.getPageById(aPageId);
if (page) {
this._pageStack[this._pageStack.length-1] = page;
this.currentPage = page;
}
]]></body>
</method>
<method name="cancel">
<body><![CDATA[
if (!this._fireEvent(this, "wizardcancel"))
return true;
window.close();
window.setTimeout(function() {window.close();}, 1);
]]></body>
</method>
<method name="_setInitialFocus">
<parameter name="aEvent"/>
<body>
<![CDATA[
document.documentElement._hasLoaded = true;
var focusInit =
function() {
// give focus to the first focusable element in the dialog
if (!document.commandDispatcher.focusedElement)
document.commandDispatcher.advanceFocusIntoSubtree(document.documentElement);
};
// Give focus after onload completes, see bug 103197.
setTimeout(focusInit, 0);
]]>
</body>
</method>
<method name="_advanceFocusToPage">
<parameter name="aPage"/>
<body>
<![CDATA[
if (!this._hasLoaded)
return;
document.commandDispatcher.advanceFocusIntoSubtree(aPage);
// if advanceFocusIntoSubtree tries to focus one of our
// dialog buttons, then remove it and put it on the root
var focused = document.commandDispatcher.focusedElement;
if (focused && focused.hasAttribute("dlgtype"))
this.focus();
]]>
</body>
</method>
<method name="_initPages">
<body><![CDATA[
var meth = "sequential";
var pages = this.wizardPages;
for (var i = 0; i < pages.length; ++i) {
var page = pages[i];
page.pageIndex = i;
if (page.next != "")
meth = "random";
}
this._accessMethod = meth;
]]></body>
</method>
<method name="_initWizardButton">
<parameter name="aName"/>
<body><![CDATA[
var btn = document.getAnonymousElementByAttribute(this._wizardButtons, "dlgtype", aName);
if (btn) {
btn.addEventListener("command", this["_"+aName+"Func"], false);
btn.setAttribute("label", this._bundle.GetStringFromName("button-"+aName));
this["_"+aName+"Button"] = btn;
}
return btn;
]]></body>
</method>
<method name="_adjustWizardHeader">
<body><![CDATA[
var label = this.currentPage.getAttribute("label");
if (!label && this.onFirstPage)
#ifdef XP_MACOSX
label = this._bundle.GetStringFromName("default-first-title-mac");
#else
label = this._bundle.formatStringFromName("default-first-title", [this.title], 1);
#endif
else if (!label && this.onLastPage)
#ifdef XP_MACOSX
label = this._bundle.GetStringFromName("default-last-title-mac");
#else
label = this._bundle.formatStringFromName("default-last-title", [this.title], 1);
#endif
this._wizardHeader.setAttribute("label", label);
this._wizardHeader.setAttribute("description", this.currentPage.getAttribute("description"));
]]></body>
</method>
<method name="_hitEnter">
<body>
<![CDATA[
// if a button is focused, dispatch its command instead
// of advancing the wizard
var focused = document.commandDispatcher.focusedElement;
if (!(focused && focused.localName == "button" && focused.hasAttribute("dlgtype")))
this.advance();
]]>
</body>
</method>
<method name="_fireEvent">
<parameter name="aTarget"/>
<parameter name="aType"/>
<body>
<![CDATA[
var event = document.createEvent("Events");
event.initEvent(aType, false, true);
// handle dom event handlers
var noCancel = aTarget.dispatchEvent(event);
// handle any xml attribute event handlers
var handler = aTarget.getAttribute("on"+aType);
if (handler != "") {
var fn = new Function("event", handler);
var returned = fn.apply(aTarget, [event]);
if (returned == false)
noCancel = false;
}
return noCancel;
]]>
</body>
</method>
</implementation>
<handlers>
<handler event="keypress" keycode="VK_ENTER" action="this._hitEnter()"/>
<handler event="keypress" keycode="VK_RETURN" action="this._hitEnter()"/>
<handler event="keypress" keycode="VK_ESCAPE" action="this.cancel();"/>
</handlers>
</binding>
<binding id="wizardpage" extends="chrome://global/content/bindings/wizard.xml#wizard-base">
<implementation>
<field name="pageIndex">null</field>
<property name="pageid" onget="return this.getAttribute('pageid');"
onset="this.setAttribute('pageid', val);"/>
<property name="next" onget="return this.getAttribute('next');"
onset="this.setAttribute('next', val);
this.parentNode._accessMethod = 'random';
return val;"/>
</implementation>
</binding>
#ifdef XP_MACOSX
<binding id="wizard-header" extends="chrome://global/content/bindings/wizard.xml#wizard-base">
<content>
<xul:stack class="wizard-header-stack" flex="1">
<xul:vbox class="wizard-header-box-1">
<xul:vbox class="wizard-header-box-2">
<xul:vbox class="wizard-header-box-text">
<xul:label class="wizard-header-label" xbl:inherits="value=label"/>
</xul:vbox>
</xul:vbox>
</xul:vbox>
<xul:hbox class="wizard-header-box-icon">
<xul:spacer flex="1"/>
<xul:image class="wizard-header-icon" xbl:inherits="src=iconsrc"/>
</xul:hbox>
</xul:stack>
</content>
</binding>
<binding id="wizard-buttons" extends="chrome://global/content/bindings/wizard.xml#wizard-base">
<content>
<xul:vbox flex="1">
<xul:hbox class="wizard-buttons-top" xbl:inherits="hidden=hidetoprow">
<xul:spacer flex="1"/>
<xul:button class="wizard-button" dlgtype="cancel"/>
<xul:button class="wizard-button" dlgtype="finish" default="true"/>
</xul:hbox>
<xul:separator class="wizard-buttons-separator groove"/>
<xul:hbox class="wizard-buttons-btm">
<xul:spacer flex="1"/>
<xul:button class="wizard-button wizard-nav-button" dlgtype="back"/>
<xul:hbox class="wizard-label-box" align="center">
<xul:label class="wizard-page-label" xbl:inherits="value=pagestep"/>
</xul:hbox>
<xul:button class="wizard-button wizard-nav-button" dlgtype="next" default="true" xbl:inherits="disabled=lastpage"/>
</xul:hbox>
</xul:vbox>
</content>
<implementation>
<method name="onPageChange">
<body><![CDATA[
this.setAttribute("hidetoprow", !(this.getAttribute("lastpage") == "true"));
]]></body>
</method>
</implementation>
</binding>
#else
<binding id="wizard-header" extends="chrome://global/content/bindings/wizard.xml#wizard-base">
<content>
<xul:hbox class="wizard-header-box-1" flex="1">
<xul:vbox class="wizard-header-box-text" flex="1">
<xul:label class="wizard-header-label" xbl:inherits="value=label"/>
<xul:label class="wizard-header-description" xbl:inherits="value=description"/>
</xul:vbox>
<xul:image class="wizard-header-icon" xbl:inherits="src=iconsrc"/>
</xul:hbox>
</content>
</binding>
<binding id="wizard-buttons" extends="chrome://global/content/bindings/wizard.xml#wizard-base">
<content>
<xul:vbox class="wizard-buttons-box-1" flex="1">
<xul:separator class="wizard-buttons-separator groove"/>
<xul:hbox class="wizard-buttons-box-2">
<xul:spacer flex="1"/>
<xul:button class="wizard-button" dlgtype="back"/>
<xul:deck class="wizard-next-deck" anonid="WizardButtonDeck">
<xul:hbox>
<xul:button class="wizard-button" dlgtype="finish" default="true" flex="1"/>
</xul:hbox>
<xul:hbox>
<xul:button class="wizard-button" dlgtype="next" default="true" flex="1"/>
</xul:hbox>
</xul:deck>
<xul:button class="wizard-button" dlgtype="cancel"/>
</xul:hbox>
</xul:vbox>
</content>
<implementation>
<field name="_wizardButtonDeck" readonly="true">
document.getAnonymousElementByAttribute(this, "anonid", "WizardButtonDeck");
</field>
<method name="onPageChange">
<body><![CDATA[
if (this.getAttribute("lastpage") == "true") {
this._wizardButtonDeck.setAttribute("selectedIndex", 0);
} else {
this._wizardButtonDeck.setAttribute("selectedIndex", 1);
}
]]></body>
</method>
</implementation>
</binding>
#endif
</bindings>