toolkit/content/widgets/dialog.xml

branch
TOR_BUG_3246
changeset 7
129ffea94266
equal deleted inserted replaced
-1:000000000000 0:a3415e8a296f
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
7 <bindings id="dialogBindings"
8 xmlns="http://www.mozilla.org/xbl"
9 xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
10 xmlns:xbl="http://www.mozilla.org/xbl">
11
12 <binding id="dialog" extends="chrome://global/content/bindings/general.xml#root-element">
13 <resources>
14 <stylesheet src="chrome://global/skin/dialog.css"/>
15 </resources>
16 <content>
17 <xul:vbox class="box-inherit dialog-content-box" flex="1">
18 <children/>
19 </xul:vbox>
20
21 <xul:hbox class="dialog-button-box" anonid="buttons"
22 xbl:inherits="pack=buttonpack,align=buttonalign,dir=buttondir,orient=buttonorient"
23 #ifdef XP_UNIX
24 >
25 <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/>
26 <xul:button dlgtype="help" class="dialog-button" hidden="true"/>
27 <xul:button dlgtype="extra2" class="dialog-button" hidden="true"/>
28 <xul:button dlgtype="extra1" class="dialog-button" hidden="true"/>
29 <xul:spacer anonid="spacer" flex="1"/>
30 <xul:button dlgtype="cancel" class="dialog-button"/>
31 <xul:button dlgtype="accept" class="dialog-button" xbl:inherits="disabled=buttondisabledaccept"/>
32 #else
33 pack="end">
34 <xul:button dlgtype="extra2" class="dialog-button" hidden="true"/>
35 <xul:spacer anonid="spacer" flex="1" hidden="true"/>
36 <xul:button dlgtype="accept" class="dialog-button" xbl:inherits="disabled=buttondisabledaccept"/>
37 <xul:button dlgtype="extra1" class="dialog-button" hidden="true"/>
38 <xul:button dlgtype="cancel" class="dialog-button"/>
39 <xul:button dlgtype="help" class="dialog-button" hidden="true"/>
40 <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/>
41 #endif
42 </xul:hbox>
43 </content>
44
45 <implementation>
46 <field name="_mStrBundle">null</field>
47 <field name="_closeHandler">(function(event) {
48 if (!document.documentElement.cancelDialog())
49 event.preventDefault();
50 })</field>
51
52 <property name="buttons"
53 onget="return this.getAttribute('buttons');"
54 onset="this._configureButtons(val); return val;"/>
55
56 <property name="defaultButton">
57 <getter>
58 <![CDATA[
59 if (this.hasAttribute("defaultButton"))
60 return this.getAttribute("defaultButton");
61 else // default to the accept button
62 return "accept";
63 ]]>
64 </getter>
65 <setter>
66 <![CDATA[
67 this._setDefaultButton(val);
68 return val;
69 ]]>
70 </setter>
71 </property>
72
73 <method name="acceptDialog">
74 <body>
75 <![CDATA[
76 return this._doButtonCommand("accept");
77 ]]>
78 </body>
79 </method>
80
81 <method name="cancelDialog">
82 <body>
83 <![CDATA[
84 return this._doButtonCommand("cancel");
85 ]]>
86 </body>
87 </method>
88
89 <method name="getButton">
90 <parameter name="aDlgType"/>
91 <body>
92 <![CDATA[
93 return this._buttons[aDlgType];
94 ]]>
95 </body>
96 </method>
97
98 <method name="moveToAlertPosition">
99 <body>
100 <![CDATA[
101 // hack. we need this so the window has something like its final size
102 if (window.outerWidth == 1) {
103 dump("Trying to position a sizeless window; caller should have called sizeToContent() or sizeTo(). See bug 75649.\n");
104 sizeToContent();
105 }
106
107 var xOffset = (opener.outerWidth - window.outerWidth) / 2;
108 var yOffset = opener.outerHeight / 5;
109
110 var newX = opener.screenX + xOffset;
111 var newY = opener.screenY + yOffset;
112
113 // ensure the window is fully onscreen (if smaller than the screen)
114 if (newX < screen.availLeft)
115 newX = screen.availLeft + 20;
116 if ((newX + window.outerWidth) > (screen.availLeft + screen.availWidth))
117 newX = (screen.availLeft + screen.availWidth) - window.outerWidth - 20;
118
119 if (newY < screen.availTop)
120 newY = screen.availTop + 20;
121 if ((newY + window.outerHeight) > (screen.availTop + screen.availHeight))
122 newY = (screen.availTop + screen.availHeight) - window.outerHeight - 60;
123
124 window.moveTo( newX, newY );
125 ]]>
126 </body>
127 </method>
128
129 <method name="centerWindowOnScreen">
130 <body>
131 <![CDATA[
132 var xOffset = screen.availWidth/2 - window.outerWidth/2;
133 var yOffset = screen.availHeight/2 - window.outerHeight/2; //(opener.outerHeight *2)/10;
134
135 xOffset = xOffset > 0 ? xOffset : 0;
136 yOffset = yOffset > 0 ? yOffset : 0;
137 window.moveTo(xOffset, yOffset);
138 ]]>
139 </body>
140 </method>
141
142 <constructor>
143 <![CDATA[
144 this._configureButtons(this.buttons);
145
146 // listen for when window is closed via native close buttons
147 window.addEventListener("close", this._closeHandler, false);
148
149 // for things that we need to initialize after onload fires
150 window.addEventListener("load", this.postLoadInit, false);
151
152 window.moveToAlertPosition = this.moveToAlertPosition;
153 window.centerWindowOnScreen = this.centerWindowOnScreen;
154 ]]>
155 </constructor>
156
157 <method name="postLoadInit">
158 <parameter name="aEvent"/>
159 <body>
160 <![CDATA[
161 function focusInit() {
162 const dialog = document.documentElement;
163 const defaultButton = dialog.getButton(dialog.defaultButton);
164 // give focus to the first focusable element in the dialog
165 if (!document.commandDispatcher.focusedElement) {
166 document.commandDispatcher.advanceFocusIntoSubtree(dialog);
167
168 var focusedElt = document.commandDispatcher.focusedElement;
169 if (focusedElt) {
170 var initialFocusedElt = focusedElt;
171 while (focusedElt.localName == "tab" ||
172 focusedElt.getAttribute("noinitialfocus") == "true") {
173 document.commandDispatcher.advanceFocusIntoSubtree(focusedElt);
174 focusedElt = document.commandDispatcher.focusedElement;
175 if (focusedElt == initialFocusedElt)
176 break;
177 }
178
179 if (initialFocusedElt.localName == "tab") {
180 if (focusedElt.hasAttribute("dlgtype")) {
181 // We don't want to focus on anonymous OK, Cancel, etc. buttons,
182 // so return focus to the tab itself
183 initialFocusedElt.focus();
184 }
185 }
186 #ifndef XP_MACOSX
187 else if (focusedElt.hasAttribute("dlgtype") && focusedElt != defaultButton) {
188 defaultButton.focus();
189 }
190 #endif
191 }
192 }
193
194 try {
195 if (defaultButton)
196 window.notifyDefaultButtonLoaded(defaultButton);
197 } catch (e) { }
198 }
199
200 // Give focus after onload completes, see bug 103197.
201 setTimeout(focusInit, 0);
202 ]]>
203 </body>
204 </method>
205
206 <property name="mStrBundle">
207 <getter>
208 <![CDATA[
209 if (!this._mStrBundle) {
210 // need to create string bundle manually instead of using <xul:stringbundle/>
211 // see bug 63370 for details
212 this._mStrBundle = Components.classes["@mozilla.org/intl/stringbundle;1"]
213 .getService(Components.interfaces.nsIStringBundleService)
214 .createBundle("chrome://global/locale/dialog.properties");
215 }
216 return this._mStrBundle;
217 ]]></getter>
218 </property>
219
220 <method name="_configureButtons">
221 <parameter name="aButtons"/>
222 <body>
223 <![CDATA[
224 // by default, get all the anonymous button elements
225 var buttons = {};
226 this._buttons = buttons;
227 buttons.accept = document.getAnonymousElementByAttribute(this, "dlgtype", "accept");
228 buttons.cancel = document.getAnonymousElementByAttribute(this, "dlgtype", "cancel");
229 buttons.extra1 = document.getAnonymousElementByAttribute(this, "dlgtype", "extra1");
230 buttons.extra2 = document.getAnonymousElementByAttribute(this, "dlgtype", "extra2");
231 buttons.help = document.getAnonymousElementByAttribute(this, "dlgtype", "help");
232 buttons.disclosure = document.getAnonymousElementByAttribute(this, "dlgtype", "disclosure");
233
234 // look for any overriding explicit button elements
235 var exBtns = this.getElementsByAttribute("dlgtype", "*");
236 var dlgtype;
237 var i;
238 for (i = 0; i < exBtns.length; ++i) {
239 dlgtype = exBtns[i].getAttribute("dlgtype");
240 buttons[dlgtype].hidden = true; // hide the anonymous button
241 buttons[dlgtype] = exBtns[i];
242 }
243
244 // add the label and oncommand handler to each button
245 for (dlgtype in buttons) {
246 var button = buttons[dlgtype];
247 button.addEventListener("command", this._handleButtonCommand, true);
248
249 // don't override custom labels with pre-defined labels on explicit buttons
250 if (!button.hasAttribute("label")) {
251 // dialog attributes override the default labels in dialog.properties
252 if (this.hasAttribute("buttonlabel"+dlgtype)) {
253 button.setAttribute("label", this.getAttribute("buttonlabel"+dlgtype));
254 if (this.hasAttribute("buttonaccesskey"+dlgtype))
255 button.setAttribute("accesskey", this.getAttribute("buttonaccesskey"+dlgtype));
256 } else if (dlgtype != "extra1" && dlgtype != "extra2") {
257 button.setAttribute("label", this.mStrBundle.GetStringFromName("button-"+dlgtype));
258 var accessKey = this.mStrBundle.GetStringFromName("accesskey-"+dlgtype);
259 if (accessKey)
260 button.setAttribute("accesskey", accessKey);
261 }
262 }
263 // allow specifying alternate icons in the dialog header
264 if (!button.hasAttribute("icon")) {
265 // if there's an icon specified, use that
266 if (this.hasAttribute("buttonicon"+dlgtype))
267 button.setAttribute("icon", this.getAttribute("buttonicon"+dlgtype));
268 // otherwise set defaults
269 else
270 switch (dlgtype) {
271 case "accept":
272 button.setAttribute("icon","accept");
273 break;
274 case "cancel":
275 button.setAttribute("icon","cancel");
276 break;
277 case "disclosure":
278 button.setAttribute("icon","properties");
279 break;
280 case "help":
281 button.setAttribute("icon","help");
282 break;
283 default:
284 break;
285 }
286 }
287 }
288
289 // ensure that hitting enter triggers the default button command
290 this.defaultButton = this.defaultButton;
291
292 // if there is a special button configuration, use it
293 if (aButtons) {
294 // expect a comma delimited list of dlgtype values
295 var list = aButtons.split(",");
296
297 // mark shown dlgtypes as true
298 var shown = { accept: false, cancel: false, help: false,
299 disclosure: false, extra1: false, extra2: false };
300 for (i = 0; i < list.length; ++i)
301 shown[list[i].replace(/ /g, "")] = true;
302
303 // hide/show the buttons we want
304 for (dlgtype in buttons)
305 buttons[dlgtype].hidden = !shown[dlgtype];
306
307 #ifdef XP_WIN
308 # show the spacer on Windows only when the extra2 button is present
309 var spacer = document.getAnonymousElementByAttribute(this, "anonid", "spacer");
310 spacer.removeAttribute("hidden");
311 spacer.setAttribute("flex", shown["extra2"]?"1":"0");
312 #endif
313
314 }
315 ]]>
316 </body>
317 </method>
318
319 <method name="_setDefaultButton">
320 <parameter name="aNewDefault"/>
321 <body>
322 <![CDATA[
323 // remove the default attribute from the previous default button, if any
324 var oldDefaultButton = this.getButton(this.defaultButton);
325 if (oldDefaultButton)
326 oldDefaultButton.removeAttribute("default");
327
328 var newDefaultButton = this.getButton(aNewDefault);
329 if (newDefaultButton) {
330 this.setAttribute("defaultButton", aNewDefault);
331 newDefaultButton.setAttribute("default", "true");
332 }
333 else {
334 this.setAttribute("defaultButton", "none");
335 if (aNewDefault != "none")
336 dump("invalid new default button: " + aNewDefault + ", assuming: none\n");
337 }
338 ]]>
339 </body>
340 </method>
341
342 <method name="_handleButtonCommand">
343 <parameter name="aEvent"/>
344 <body>
345 <![CDATA[
346 return document.documentElement._doButtonCommand(
347 aEvent.target.getAttribute("dlgtype"));
348 ]]>
349 </body>
350 </method>
351
352 <method name="_doButtonCommand">
353 <parameter name="aDlgType"/>
354 <body>
355 <![CDATA[
356 var button = this.getButton(aDlgType);
357 if (!button.disabled) {
358 var noCancel = this._fireButtonEvent(aDlgType);
359 if (noCancel) {
360 if (aDlgType == "accept" || aDlgType == "cancel")
361 window.close();
362 }
363 return noCancel;
364 }
365 return true;
366 ]]>
367 </body>
368 </method>
369
370 <method name="_fireButtonEvent">
371 <parameter name="aDlgType"/>
372 <body>
373 <![CDATA[
374 var event = document.createEvent("Events");
375 event.initEvent("dialog"+aDlgType, true, true);
376
377 // handle dom event handlers
378 var noCancel = this.dispatchEvent(event);
379
380 // handle any xml attribute event handlers
381 var handler = this.getAttribute("ondialog"+aDlgType);
382 if (handler != "") {
383 var fn = new Function("event", handler);
384 var returned = fn(event);
385 if (returned == false)
386 noCancel = false;
387 }
388
389 return noCancel;
390 ]]>
391 </body>
392 </method>
393
394 <method name="_hitEnter">
395 <parameter name="evt"/>
396 <body>
397 <![CDATA[
398 if (evt.defaultPrevented)
399 return;
400
401 var btn = this.getButton(this.defaultButton);
402 if (btn)
403 this._doButtonCommand(this.defaultButton);
404 ]]>
405 </body>
406 </method>
407
408 </implementation>
409
410 <handlers>
411 <handler event="keypress" keycode="VK_RETURN"
412 group="system" action="this._hitEnter(event);"/>
413 <handler event="keypress" keycode="VK_ESCAPE" group="system">
414 if (!event.defaultPrevented)
415 this.cancelDialog();
416 </handler>
417 #ifdef XP_MACOSX
418 <handler event="keypress" key="." modifiers="meta" phase="capturing" action="this.cancelDialog();"/>
419 #else
420 <handler event="focus" phase="capturing">
421 var btn = this.getButton(this.defaultButton);
422 if (btn)
423 btn.setAttribute("default", event.originalTarget == btn || !(event.originalTarget instanceof Components.interfaces.nsIDOMXULButtonElement));
424 </handler>
425 #endif
426 </handlers>
427
428 </binding>
429
430 <binding id="dialogheader">
431 <resources>
432 <stylesheet src="chrome://global/skin/dialog.css"/>
433 </resources>
434 <content>
435 <xul:label class="dialogheader-title" xbl:inherits="value=title,crop" crop="right" flex="1"/>
436 <xul:label class="dialogheader-description" xbl:inherits="value=description"/>
437 </content>
438 </binding>
439
440 </bindings>

mercurial