Source code

Revision control

Other Tools

1
<?xml version="1.0"?>
2
<!-- This Source Code Form is subject to the terms of the Mozilla Public
3
- License, v. 2.0. If a copy of the MPL was not distributed with this
4
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
5
6
<bindings id="popupBindings"
10
11
<binding id="panel">
12
<implementation>
13
<field name="_prevFocus">0</field>
14
</implementation>
15
16
<handlers>
17
<handler event="popupshowing"><![CDATA[
18
// Capture the previous focus before has a chance to get set inside the panel
19
try {
20
this._prevFocus = Cu
21
.getWeakReference(document.commandDispatcher.focusedElement);
22
if (this._prevFocus.get())
23
return;
24
} catch (ex) { }
25
26
this._prevFocus = Cu.getWeakReference(document.activeElement);
27
]]></handler>
28
<handler event="popupshown"><![CDATA[
29
// Fire event for accessibility APIs
30
var alertEvent = document.createEvent("Events");
31
alertEvent.initEvent("AlertActive", true, true);
32
this.dispatchEvent(alertEvent);
33
]]></handler>
34
<handler event="popuphiding"><![CDATA[
35
try {
36
this._currentFocus = document.commandDispatcher.focusedElement;
37
} catch (e) {
38
this._currentFocus = document.activeElement;
39
}
40
]]></handler>
41
<handler event="popuphidden"><![CDATA[
42
function doFocus() {
43
// Focus was set on an element inside this panel,
44
// so we need to move it back to where it was previously
45
try {
46
let fm = Cc["@mozilla.org/focus-manager;1"]
47
.getService(Ci.nsIFocusManager);
48
fm.setFocus(prevFocus, fm.FLAG_NOSCROLL);
49
} catch (e) {
50
prevFocus.focus();
51
}
52
}
53
var currentFocus = this._currentFocus;
54
var prevFocus = this._prevFocus ? this._prevFocus.get() : null;
55
this._currentFocus = null;
56
this._prevFocus = null;
57
58
// Avoid changing focus if focus changed while we hide the popup
59
// (This can happen e.g. if the popup is hiding as a result of a
60
// click/keypress that focused something)
61
let nowFocus;
62
try {
63
nowFocus = document.commandDispatcher.focusedElement;
64
} catch (e) {
65
nowFocus = document.activeElement;
66
}
67
if (nowFocus && nowFocus != currentFocus)
68
return;
69
70
if (prevFocus && this.getAttribute("norestorefocus") != "true") {
71
// Try to restore focus
72
try {
73
if (document.commandDispatcher.focusedWindow != window)
74
return; // Focus has already been set to a window outside of this panel
75
} catch (ex) {}
76
77
if (!currentFocus) {
78
doFocus();
79
return;
80
}
81
while (currentFocus) {
82
if (currentFocus == this) {
83
doFocus();
84
return;
85
}
86
currentFocus = currentFocus.parentNode;
87
}
88
}
89
]]></handler>
90
</handlers>
91
</binding>
92
93
<binding id="arrowpanel" extends="chrome://global/content/bindings/popup.xml#panel">
94
<content flip="both" side="top" position="bottomcenter topleft" consumeoutsideclicks="false">
95
<xul:vbox anonid="container" class="panel-arrowcontainer" flex="1"
96
xbl:inherits="side,panelopen">
97
<xul:box anonid="arrowbox" class="panel-arrowbox">
98
<xul:image anonid="arrow" class="panel-arrow" xbl:inherits="side"/>
99
</xul:box>
100
<xul:box class="panel-arrowcontent" xbl:inherits="side,align,dir,orient,pack" flex="1">
101
<children/>
102
</xul:box>
103
</xul:vbox>
104
</content>
105
<implementation>
106
<field name="_fadeTimer">null</field>
107
<method name="adjustArrowPosition">
108
<body>
109
<![CDATA[
110
var anchor = this.anchorNode;
111
if (!anchor) {
112
return;
113
}
114
115
var container = document.getAnonymousElementByAttribute(this, "anonid", "container");
116
var arrowbox = document.getAnonymousElementByAttribute(this, "anonid", "arrowbox");
117
118
var position = this.alignmentPosition;
119
var offset = this.alignmentOffset;
120
121
this.setAttribute("arrowposition", position);
122
123
if (position.indexOf("start_") == 0 || position.indexOf("end_") == 0) {
124
container.orient = "horizontal";
125
arrowbox.orient = "vertical";
126
if (position.indexOf("_after") > 0) {
127
arrowbox.pack = "end";
128
} else {
129
arrowbox.pack = "start";
130
}
131
arrowbox.style.transform = "translate(0, " + -offset + "px)";
132
133
// The assigned side stays the same regardless of direction.
134
var isRTL = (window.getComputedStyle(this).direction == "rtl");
135
136
if (position.indexOf("start_") == 0) {
137
container.dir = "reverse";
138
this.setAttribute("side", isRTL ? "left" : "right");
139
} else {
140
container.dir = "";
141
this.setAttribute("side", isRTL ? "right" : "left");
142
}
143
} else if (position.indexOf("before_") == 0 || position.indexOf("after_") == 0) {
144
container.orient = "";
145
arrowbox.orient = "";
146
if (position.indexOf("_end") > 0) {
147
arrowbox.pack = "end";
148
} else {
149
arrowbox.pack = "start";
150
}
151
arrowbox.style.transform = "translate(" + -offset + "px, 0)";
152
153
if (position.indexOf("before_") == 0) {
154
container.dir = "reverse";
155
this.setAttribute("side", "bottom");
156
} else {
157
container.dir = "";
158
this.setAttribute("side", "top");
159
}
160
}
161
]]>
162
</body>
163
</method>
164
</implementation>
165
<handlers>
166
<handler event="popupshowing" phase="target">
167
<![CDATA[
168
var arrow = document.getAnonymousElementByAttribute(this, "anonid", "arrow");
169
arrow.hidden = this.anchorNode == null;
170
document.getAnonymousElementByAttribute(this, "anonid", "arrowbox")
171
.style.removeProperty("transform");
172
173
if (this.getAttribute("animate") != "false") {
174
this.setAttribute("animate", "open");
175
// the animating attribute prevents user interaction during transition
176
// it is removed when popupshown fires
177
this.setAttribute("animating", "true");
178
}
179
180
// set fading
181
var fade = this.getAttribute("fade");
182
var fadeDelay = 0;
183
if (fade == "fast") {
184
fadeDelay = 1;
185
} else if (fade == "slow") {
186
fadeDelay = 4000;
187
} else {
188
return;
189
}
190
191
this._fadeTimer = setTimeout(() => this.hidePopup(true), fadeDelay, this);
192
]]>
193
</handler>
194
<handler event="popuphiding" phase="target">
195
let animate = (this.getAttribute("animate") != "false");
196
197
if (this._fadeTimer) {
198
clearTimeout(this._fadeTimer);
199
if (animate) {
200
this.setAttribute("animate", "fade");
201
}
202
} else if (animate) {
203
this.setAttribute("animate", "cancel");
204
}
205
</handler>
206
<handler event="popupshown" phase="target">
207
this.removeAttribute("animating");
208
this.setAttribute("panelopen", "true");
209
</handler>
210
<handler event="popuphidden" phase="target">
211
this.removeAttribute("panelopen");
212
if (this.getAttribute("animate") != "false") {
213
this.removeAttribute("animate");
214
}
215
</handler>
216
<handler event="popuppositioned" phase="target">
217
this.adjustArrowPosition();
218
</handler>
219
</handlers>
220
</binding>
221
</bindings>