diff options
Diffstat (limited to 'toolkit/content/widgets/popup.xml')
-rw-r--r-- | toolkit/content/widgets/popup.xml | 650 |
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> |