summaryrefslogtreecommitdiffstats
path: root/toolkit/content/widgets/popup.xml
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/content/widgets/popup.xml')
-rw-r--r--toolkit/content/widgets/popup.xml650
1 files changed, 650 insertions, 0 deletions
diff --git a/toolkit/content/widgets/popup.xml b/toolkit/content/widgets/popup.xml
new file mode 100644
index 000000000..bb1a5eeee
--- /dev/null
+++ b/toolkit/content/widgets/popup.xml
@@ -0,0 +1,650 @@
+<?xml version="1.0"?>
+<!-- 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/. -->
+
+
+<bindings id="popupBindings"
+ 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="popup-base">
+ <resources>
+ <stylesheet src="chrome://global/skin/popup.css"/>
+ </resources>
+
+ <implementation implements="nsIDOMXULPopupElement">
+ <property name="label" onget="return this.getAttribute('label');"
+ onset="this.setAttribute('label', val); return val;"/>
+ <property name="position" onget="return this.getAttribute('position');"
+ onset="this.setAttribute('position', val); return val;"/>
+ <property name="popupBoxObject">
+ <getter>
+ return this.boxObject;
+ </getter>
+ </property>
+
+ <property name="state" readonly="true"
+ onget="return this.popupBoxObject.popupState"/>
+
+ <property name="triggerNode" readonly="true"
+ onget="return this.popupBoxObject.triggerNode"/>
+
+ <property name="anchorNode" readonly="true"
+ onget="return this.popupBoxObject.anchorNode"/>
+
+ <method name="openPopup">
+ <parameter name="aAnchorElement"/>
+ <parameter name="aPosition"/>
+ <parameter name="aX"/>
+ <parameter name="aY"/>
+ <parameter name="aIsContextMenu"/>
+ <parameter name="aAttributesOverride"/>
+ <parameter name="aTriggerEvent"/>
+ <body>
+ <![CDATA[
+ try {
+ var popupBox = this.popupBoxObject;
+ if (popupBox)
+ popupBox.openPopup(aAnchorElement, aPosition, aX, aY,
+ aIsContextMenu, aAttributesOverride, aTriggerEvent);
+ } catch (e) {}
+ ]]>
+ </body>
+ </method>
+
+ <method name="openPopupAtScreen">
+ <parameter name="aX"/>
+ <parameter name="aY"/>
+ <parameter name="aIsContextMenu"/>
+ <parameter name="aTriggerEvent"/>
+ <body>
+ <![CDATA[
+ try {
+ var popupBox = this.popupBoxObject;
+ if (popupBox)
+ popupBox.openPopupAtScreen(aX, aY, aIsContextMenu, aTriggerEvent);
+ } catch (e) {}
+ ]]>
+ </body>
+ </method>
+
+ <method name="openPopupAtScreenRect">
+ <parameter name="aPosition"/>
+ <parameter name="aX"/>
+ <parameter name="aY"/>
+ <parameter name="aWidth"/>
+ <parameter name="aHeight"/>
+ <parameter name="aIsContextMenu"/>
+ <parameter name="aAttributesOverride"/>
+ <parameter name="aTriggerEvent"/>
+ <body>
+ <![CDATA[
+ try {
+ var popupBox = this.popupBoxObject;
+ if (popupBox)
+ popupBox.openPopupAtScreenRect(aPosition, aX, aY, aWidth, aHeight,
+ aIsContextMenu, aAttributesOverride, aTriggerEvent);
+ } catch (e) {}
+ ]]>
+ </body>
+ </method>
+
+ <method name="showPopup">
+ <parameter name="element"/>
+ <parameter name="xpos"/>
+ <parameter name="ypos"/>
+ <parameter name="popuptype"/>
+ <parameter name="anchoralignment"/>
+ <parameter name="popupalignment"/>
+ <body>
+ <![CDATA[
+ var popupBox = null;
+ var menuBox = null;
+ try {
+ popupBox = this.popupBoxObject;
+ } catch (e) {}
+ try {
+ menuBox = this.parentNode.boxObject;
+ } catch (e) {}
+ if (menuBox instanceof MenuBoxObject)
+ menuBox.openMenu(true);
+ else if (popupBox)
+ popupBox.showPopup(element, this, xpos, ypos, popuptype, anchoralignment, popupalignment);
+ ]]>
+ </body>
+ </method>
+
+ <method name="hidePopup">
+ <parameter name="cancel"/>
+ <body>
+ <![CDATA[
+ var popupBox = null;
+ var menuBox = null;
+ try {
+ popupBox = this.popupBoxObject;
+ } catch (e) {}
+ try {
+ menuBox = this.parentNode.boxObject;
+ } catch (e) {}
+ if (menuBox instanceof MenuBoxObject)
+ menuBox.openMenu(false);
+ else if (popupBox instanceof PopupBoxObject)
+ popupBox.hidePopup(cancel);
+ ]]>
+ </body>
+ </method>
+
+ <property name="autoPosition">
+ <getter>
+ <![CDATA[
+ return this.popupBoxObject.autoPosition;
+ ]]>
+ </getter>
+ <setter>
+ <![CDATA[
+ return this.popupBoxObject.autoPosition = val;
+ ]]>
+ </setter>
+ </property>
+
+ <property name="alignmentPosition" readonly="true">
+ <getter>
+ <![CDATA[
+ return this.popupBoxObject.alignmentPosition;
+ ]]>
+ </getter>
+ </property>
+
+ <property name="alignmentOffset" readonly="true">
+ <getter>
+ <![CDATA[
+ return this.popupBoxObject.alignmentOffset;
+ ]]>
+ </getter>
+ </property>
+
+ <method name="enableKeyboardNavigator">
+ <parameter name="aEnableKeyboardNavigator"/>
+ <body>
+ <![CDATA[
+ this.popupBoxObject.enableKeyboardNavigator(aEnableKeyboardNavigator);
+ ]]>
+ </body>
+ </method>
+
+ <method name="enableRollup">
+ <parameter name="aEnableRollup"/>
+ <body>
+ <![CDATA[
+ this.popupBoxObject.enableRollup(aEnableRollup);
+ ]]>
+ </body>
+ </method>
+
+ <method name="sizeTo">
+ <parameter name="aWidth"/>
+ <parameter name="aHeight"/>
+ <body>
+ <![CDATA[
+ this.popupBoxObject.sizeTo(aWidth, aHeight);
+ ]]>
+ </body>
+ </method>
+
+ <method name="moveTo">
+ <parameter name="aLeft"/>
+ <parameter name="aTop"/>
+ <body>
+ <![CDATA[
+ this.popupBoxObject.moveTo(aLeft, aTop);
+ ]]>
+ </body>
+ </method>
+
+ <method name="moveToAnchor">
+ <parameter name="aAnchorElement"/>
+ <parameter name="aPosition"/>
+ <parameter name="aX"/>
+ <parameter name="aY"/>
+ <parameter name="aAttributesOverride"/>
+ <body>
+ <![CDATA[
+ this.popupBoxObject.moveToAnchor(aAnchorElement, aPosition, aX, aY, aAttributesOverride);
+ ]]>
+ </body>
+ </method>
+
+ <method name="getOuterScreenRect">
+ <body>
+ <![CDATA[
+ return this.popupBoxObject.getOuterScreenRect();
+ ]]>
+ </body>
+ </method>
+
+ <method name="setConstraintRect">
+ <parameter name="aRect"/>
+ <body>
+ <![CDATA[
+ this.popupBoxObject.setConstraintRect(aRect);
+ ]]>
+ </body>
+ </method>
+ </implementation>
+
+ </binding>
+
+ <binding id="popup" role="xul:menupopup"
+ extends="chrome://global/content/bindings/popup.xml#popup-base">
+
+ <content>
+ <xul:arrowscrollbox class="popup-internal-box" flex="1" orient="vertical"
+ smoothscroll="false">
+ <children/>
+ </xul:arrowscrollbox>
+ </content>
+
+ <handlers>
+ <handler event="popupshowing" phase="target">
+ <![CDATA[
+ var array = [];
+ var width = 0;
+ for (var menuitem = this.firstChild; menuitem; menuitem = menuitem.nextSibling) {
+ if (menuitem.localName == "menuitem" && menuitem.hasAttribute("acceltext")) {
+ var accel = document.getAnonymousElementByAttribute(menuitem, "anonid", "accel");
+ if (accel && accel.boxObject) {
+ array.push(accel);
+ if (accel.boxObject.width > width)
+ width = accel.boxObject.width;
+ }
+ }
+ }
+ for (var i = 0; i < array.length; i++)
+ array[i].width = width;
+ ]]>
+ </handler>
+ </handlers>
+ </binding>
+
+ <binding id="panel" role="xul:panel"
+ extends="chrome://global/content/bindings/popup.xml#popup-base">
+ <implementation implements="nsIDOMXULPopupElement">
+ <field name="_prevFocus">0</field>
+ <field name="_dragBindingAlive">true</field>
+ <constructor>
+ <![CDATA[
+ if (this.getAttribute("backdrag") == "true" && !this._draggableStarted) {
+ this._draggableStarted = true;
+ try {
+ let tmp = {};
+ Components.utils.import("resource://gre/modules/WindowDraggingUtils.jsm", tmp);
+ let draghandle = new tmp.WindowDraggingElement(this);
+ draghandle.mouseDownCheck = function () {
+ return this._dragBindingAlive;
+ }
+ } catch (e) {}
+ }
+ ]]>
+ </constructor>
+ </implementation>
+
+ <handlers>
+ <handler event="popupshowing"><![CDATA[
+ // Capture the previous focus before has a chance to get set inside the panel
+ try {
+ this._prevFocus = Components.utils
+ .getWeakReference(document.commandDispatcher.focusedElement);
+ if (this._prevFocus.get())
+ return;
+ } catch (ex) { }
+
+ this._prevFocus = Components.utils.getWeakReference(document.activeElement);
+ ]]></handler>
+ <handler event="popupshown"><![CDATA[
+ // Fire event for accessibility APIs
+ var alertEvent = document.createEvent("Events");
+ alertEvent.initEvent("AlertActive", true, true);
+ this.dispatchEvent(alertEvent);
+ ]]></handler>
+ <handler event="popuphiding"><![CDATA[
+ try {
+ this._currentFocus = document.commandDispatcher.focusedElement;
+ } catch (e) {
+ this._currentFocus = document.activeElement;
+ }
+ ]]></handler>
+ <handler event="popuphidden"><![CDATA[
+ function doFocus() {
+ // Focus was set on an element inside this panel,
+ // so we need to move it back to where it was previously
+ try {
+ let fm = Components.classes["@mozilla.org/focus-manager;1"]
+ .getService(Components.interfaces.nsIFocusManager);
+ fm.setFocus(prevFocus, fm.FLAG_NOSCROLL);
+ } catch (e) {
+ prevFocus.focus();
+ }
+ }
+ var currentFocus = this._currentFocus;
+ var prevFocus = this._prevFocus ? this._prevFocus.get() : null;
+ this._currentFocus = null;
+ this._prevFocus = null;
+
+ // Avoid changing focus if focus changed while we hide the popup
+ // (This can happen e.g. if the popup is hiding as a result of a
+ // click/keypress that focused something)
+ let nowFocus;
+ try {
+ nowFocus = document.commandDispatcher.focusedElement;
+ } catch (e) {
+ nowFocus = document.activeElement;
+ }
+ if (nowFocus && nowFocus != currentFocus)
+ return;
+
+ if (prevFocus && this.getAttribute("norestorefocus") != "true") {
+ // Try to restore focus
+ try {
+ if (document.commandDispatcher.focusedWindow != window)
+ return; // Focus has already been set to a window outside of this panel
+ } catch (ex) {}
+
+ if (!currentFocus) {
+ doFocus();
+ return;
+ }
+ while (currentFocus) {
+ if (currentFocus == this) {
+ doFocus();
+ return;
+ }
+ currentFocus = currentFocus.parentNode;
+ }
+ }
+ ]]></handler>
+ </handlers>
+ </binding>
+
+ <binding id="arrowpanel" extends="chrome://global/content/bindings/popup.xml#panel">
+ <content flip="both" side="top" position="bottomcenter topleft" consumeoutsideclicks="false">
+ <xul:vbox anonid="container" class="panel-arrowcontainer" flex="1"
+ xbl:inherits="side,panelopen">
+ <xul:box anonid="arrowbox" class="panel-arrowbox">
+ <xul:image anonid="arrow" class="panel-arrow" xbl:inherits="side"/>
+ </xul:box>
+ <xul:box class="panel-arrowcontent" xbl:inherits="side,align,dir,orient,pack" flex="1">
+ <children/>
+ </xul:box>
+ </xul:vbox>
+ </content>
+ <implementation>
+ <field name="_fadeTimer">null</field>
+ <method name="sizeTo">
+ <parameter name="aWidth"/>
+ <parameter name="aHeight"/>
+ <body>
+ <![CDATA[
+ this.popupBoxObject.sizeTo(aWidth, aHeight);
+ if (this.state == "open") {
+ this.adjustArrowPosition();
+ }
+ ]]>
+ </body>
+ </method>
+ <method name="moveToAnchor">
+ <parameter name="aAnchorElement"/>
+ <parameter name="aPosition"/>
+ <parameter name="aX"/>
+ <parameter name="aY"/>
+ <parameter name="aAttributesOverride"/>
+ <body>
+ <![CDATA[
+ this.popupBoxObject.moveToAnchor(aAnchorElement, aPosition, aX, aY, aAttributesOverride);
+ ]]>
+ </body>
+ </method>
+ <method name="adjustArrowPosition">
+ <body>
+ <![CDATA[
+ var arrow = document.getAnonymousElementByAttribute(this, "anonid", "arrow");
+
+ var anchor = this.anchorNode;
+ if (!anchor) {
+ return;
+ }
+
+ var container = document.getAnonymousElementByAttribute(this, "anonid", "container");
+ var arrowbox = document.getAnonymousElementByAttribute(this, "anonid", "arrowbox");
+
+ var position = this.alignmentPosition;
+ var offset = this.alignmentOffset;
+
+ this.setAttribute("arrowposition", position);
+
+ if (position.indexOf("start_") == 0 || position.indexOf("end_") == 0) {
+ container.orient = "horizontal";
+ arrowbox.orient = "vertical";
+ if (position.indexOf("_after") > 0) {
+ arrowbox.pack = "end";
+ } else {
+ arrowbox.pack = "start";
+ }
+ arrowbox.style.transform = "translate(0, " + -offset + "px)";
+
+ // The assigned side stays the same regardless of direction.
+ var isRTL = (window.getComputedStyle(this).direction == "rtl");
+
+ if (position.indexOf("start_") == 0) {
+ container.dir = "reverse";
+ this.setAttribute("side", isRTL ? "left" : "right");
+ }
+ else {
+ container.dir = "";
+ this.setAttribute("side", isRTL ? "right" : "left");
+ }
+ }
+ else if (position.indexOf("before_") == 0 || position.indexOf("after_") == 0) {
+ container.orient = "";
+ arrowbox.orient = "";
+ if (position.indexOf("_end") > 0) {
+ arrowbox.pack = "end";
+ } else {
+ arrowbox.pack = "start";
+ }
+ arrowbox.style.transform = "translate(" + -offset + "px, 0)";
+
+ if (position.indexOf("before_") == 0) {
+ container.dir = "reverse";
+ this.setAttribute("side", "bottom");
+ }
+ else {
+ container.dir = "";
+ this.setAttribute("side", "top");
+ }
+ }
+ ]]>
+ </body>
+ </method>
+ </implementation>
+ <handlers>
+ <handler event="popupshowing" phase="target">
+ <![CDATA[
+ var arrow = document.getAnonymousElementByAttribute(this, "anonid", "arrow");
+ arrow.hidden = this.anchorNode == null;
+ document.getAnonymousElementByAttribute(this, "anonid", "arrowbox")
+ .style.removeProperty("transform");
+
+ this.adjustArrowPosition();
+
+ if (this.getAttribute("animate") != "false") {
+ this.setAttribute("animate", "open");
+ }
+
+ // set fading
+ var fade = this.getAttribute("fade");
+ var fadeDelay = 0;
+ if (fade == "fast") {
+ fadeDelay = 1;
+ }
+ else if (fade == "slow") {
+ fadeDelay = 4000;
+ }
+ else {
+ return;
+ }
+
+ this._fadeTimer = setTimeout(() => this.hidePopup(true), fadeDelay, this);
+ ]]>
+ </handler>
+ <handler event="popuphiding" phase="target">
+ let animate = (this.getAttribute("animate") != "false");
+
+ if (this._fadeTimer) {
+ clearTimeout(this._fadeTimer);
+ if (animate) {
+ this.setAttribute("animate", "fade");
+ }
+ }
+ else if (animate) {
+ this.setAttribute("animate", "cancel");
+ }
+ </handler>
+ <handler event="popupshown" phase="target">
+ this.setAttribute("panelopen", "true");
+ </handler>
+ <handler event="popuphidden" phase="target">
+ this.removeAttribute("panelopen");
+ if (this.getAttribute("animate") != "false") {
+ this.removeAttribute("animate");
+ }
+ </handler>
+ <handler event="popuppositioned" phase="target">
+ this.adjustArrowPosition();
+ </handler>
+ </handlers>
+ </binding>
+
+ <binding id="tooltip" role="xul:tooltip"
+ extends="chrome://global/content/bindings/popup.xml#popup-base">
+ <content>
+ <children>
+ <xul:label class="tooltip-label" xbl:inherits="xbl:text=label" flex="1"/>
+ </children>
+ </content>
+
+ <implementation>
+ <field name="_mouseOutCount">0</field>
+ <field name="_isMouseOver">false</field>
+
+ <property name="label"
+ onget="return this.getAttribute('label');"
+ onset="this.setAttribute('label', val); return val;"/>
+
+ <property name="page" onset="if (val) this.setAttribute('page', 'true');
+ else this.removeAttribute('page');
+ return val;"
+ onget="return this.getAttribute('page') == 'true';"/>
+ <property name="textProvider"
+ readonly="true">
+ <getter>
+ <![CDATA[
+ if (!this._textProvider) {
+ this._textProvider = Components.classes["@mozilla.org/embedcomp/default-tooltiptextprovider;1"]
+ .getService(Components.interfaces.nsITooltipTextProvider);
+ }
+ return this._textProvider;
+ ]]>
+ </getter>
+ </property>
+
+ <!-- Given the supplied element within a page, set the tooltip's text to the text
+ for that element. Returns true if text was assigned, and false if the no text
+ is set, which normally would be used to cancel tooltip display.
+ -->
+ <method name="fillInPageTooltip">
+ <parameter name="tipElement"/>
+ <body>
+ <![CDATA[
+ let tttp = this.textProvider;
+ let textObj = {}, dirObj = {};
+ let shouldChangeText = tttp.getNodeText(tipElement, textObj, dirObj);
+ if (shouldChangeText) {
+ this.style.direction = dirObj.value;
+ this.label = textObj.value;
+ }
+ return shouldChangeText;
+ ]]>
+ </body>
+ </method>
+ </implementation>
+
+ <handlers>
+ <handler event="mouseover"><![CDATA[
+ var rel = event.relatedTarget;
+ if (!rel)
+ return;
+
+ // find out if the node we entered from is one of our anonymous children
+ while (rel) {
+ if (rel == this)
+ break;
+ rel = rel.parentNode;
+ }
+
+ // if the exited node is not a descendant of ours, we are entering for the first time
+ if (rel != this)
+ this._isMouseOver = true;
+ ]]></handler>
+
+ <handler event="mouseout"><![CDATA[
+ var rel = event.relatedTarget;
+
+ // relatedTarget is null when the titletip is first shown: a mouseout event fires
+ // because the mouse is exiting the main window and entering the titletip "window".
+ // relatedTarget is also null when the mouse exits the main window completely,
+ // so count how many times relatedTarget was null after titletip is first shown
+ // and hide popup the 2nd time
+ if (!rel) {
+ ++this._mouseOutCount;
+ if (this._mouseOutCount > 1)
+ this.hidePopup();
+ return;
+ }
+
+ // find out if the node we are entering is one of our anonymous children
+ while (rel) {
+ if (rel == this)
+ break;
+ rel = rel.parentNode;
+ }
+
+ // if the entered node is not a descendant of ours, hide the tooltip
+ if (rel != this && this._isMouseOver) {
+ this.hidePopup();
+ }
+ ]]></handler>
+
+ <handler event="popupshowing"><![CDATA[
+ if (this.page && !this.fillInPageTooltip(this.triggerNode)) {
+ event.preventDefault();
+ }
+ ]]></handler>
+
+ <handler event="popuphiding"><![CDATA[
+ this._isMouseOver = false;
+ this._mouseOutCount = 0;
+ ]]></handler>
+ </handlers>
+ </binding>
+
+ <binding id="popup-scrollbars" extends="chrome://global/content/bindings/popup.xml#popup">
+ <content>
+ <xul:hbox class="popup-internal-box" flex="1" orient="vertical" style="overflow: auto;">
+ <children/>
+ </xul:hbox>
+ </content>
+ </binding>
+
+</bindings>