toolkit/content/widgets/notification.xml

branch
TOR_BUG_9701
changeset 15
b8a032363ba2
equal deleted inserted replaced
-1:000000000000 0:812b187c9f42
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 <!DOCTYPE bindings [
8 <!ENTITY % notificationDTD SYSTEM "chrome://global/locale/notification.dtd">
9 %notificationDTD;
10 ]>
11
12 <bindings id="notificationBindings"
13 xmlns="http://www.mozilla.org/xbl"
14 xmlns:xbl="http://www.mozilla.org/xbl"
15 xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
16
17 <binding id="notificationbox">
18 <content>
19 <xul:stack xbl:inherits="hidden=notificationshidden"
20 class="notificationbox-stack">
21 <xul:spacer/>
22 <children includes="notification"/>
23 </xul:stack>
24 <children/>
25 </content>
26
27 <implementation>
28 <field name="PRIORITY_INFO_LOW" readonly="true">1</field>
29 <field name="PRIORITY_INFO_MEDIUM" readonly="true">2</field>
30 <field name="PRIORITY_INFO_HIGH" readonly="true">3</field>
31 <field name="PRIORITY_WARNING_LOW" readonly="true">4</field>
32 <field name="PRIORITY_WARNING_MEDIUM" readonly="true">5</field>
33 <field name="PRIORITY_WARNING_HIGH" readonly="true">6</field>
34 <field name="PRIORITY_CRITICAL_LOW" readonly="true">7</field>
35 <field name="PRIORITY_CRITICAL_MEDIUM" readonly="true">8</field>
36 <field name="PRIORITY_CRITICAL_HIGH" readonly="true">9</field>
37 <field name="PRIORITY_CRITICAL_BLOCK" readonly="true">10</field>
38
39 <field name="currentNotification">null</field>
40
41 <field name="_closedNotification">null</field>
42 <field name="_blockingCanvas">null</field>
43 <field name="_animating">false</field>
44
45 <property name="notificationsHidden"
46 onget="return this.getAttribute('notificationshidden') == 'true';">
47 <setter>
48 if (val)
49 this.setAttribute('notificationshidden', true);
50 else this.removeAttribute('notificationshidden');
51 return val;
52 </setter>
53 </property>
54
55 <property name="allNotifications" readonly="true">
56 <getter>
57 <![CDATA[
58 var closedNotification = this._closedNotification;
59 var notifications = this.getElementsByTagName('notification');
60 return Array.filter(notifications, function(n) n != closedNotification);
61 ]]>
62 </getter>
63 </property>
64
65 <method name="getNotificationWithValue">
66 <parameter name="aValue"/>
67 <body>
68 <![CDATA[
69 var notifications = this.allNotifications;
70 for (var n = notifications.length - 1; n >= 0; n--) {
71 if (aValue == notifications[n].getAttribute("value"))
72 return notifications[n];
73 }
74 return null;
75 ]]>
76 </body>
77 </method>
78
79 <method name="appendNotification">
80 <parameter name="aLabel"/>
81 <parameter name="aValue"/>
82 <parameter name="aImage"/>
83 <parameter name="aPriority"/>
84 <parameter name="aButtons"/>
85 <parameter name="aEventCallback"/>
86 <body>
87 <![CDATA[
88 if (aPriority < this.PRIORITY_INFO_LOW ||
89 aPriority > this.PRIORITY_CRITICAL_BLOCK)
90 throw "Invalid notification priority " + aPriority;
91
92 // check for where the notification should be inserted according to
93 // priority. If two are equal, the existing one appears on top.
94 var notifications = this.allNotifications;
95 var insertPos = null;
96 for (var n = notifications.length - 1; n >= 0; n--) {
97 if (notifications[n].priority < aPriority)
98 break;
99 insertPos = notifications[n];
100 }
101
102 const XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
103 var newitem = document.createElementNS(XULNS, "notification");
104 newitem.setAttribute("label", aLabel);
105 newitem.setAttribute("value", aValue);
106 if (aImage)
107 newitem.setAttribute("image", aImage);
108 newitem.eventCallback = aEventCallback;
109
110 if (aButtons) {
111 // The notification-button-default class is added to the button
112 // with isDefault set to true. If there is no such button, it is
113 // added to the first button (unless that button has isDefault
114 // set to false). There cannot be multiple default buttons.
115 var defaultElem;
116
117 for (var b = 0; b < aButtons.length; b++) {
118 var button = aButtons[b];
119 var buttonElem = document.createElementNS(XULNS, "button");
120 buttonElem.setAttribute("label", button.label);
121 buttonElem.setAttribute("accesskey", button.accessKey);
122 buttonElem.classList.add("notification-button");
123
124 if (button.isDefault ||
125 b == 0 && !("isDefault" in button))
126 defaultElem = buttonElem;
127
128 newitem.appendChild(buttonElem);
129 buttonElem.buttonInfo = button;
130 }
131
132 if (defaultElem)
133 defaultElem.classList.add("notification-button-default");
134 }
135
136 newitem.setAttribute("priority", aPriority);
137 if (aPriority >= this.PRIORITY_CRITICAL_LOW)
138 newitem.setAttribute("type", "critical");
139 else if (aPriority <= this.PRIORITY_INFO_HIGH)
140 newitem.setAttribute("type", "info");
141 else
142 newitem.setAttribute("type", "warning");
143
144 if (!insertPos) {
145 newitem.style.position = "fixed";
146 newitem.style.top = "100%";
147 newitem.style.marginTop = "-15px";
148 newitem.style.opacity = "0";
149 }
150 this.insertBefore(newitem, insertPos);
151 if (!insertPos)
152 this._showNotification(newitem, true);
153
154 // Fire event for accessibility APIs
155 var event = document.createEvent("Events");
156 event.initEvent("AlertActive", true, true);
157 newitem.dispatchEvent(event);
158
159 return newitem;
160 ]]>
161 </body>
162 </method>
163
164 <method name="removeNotification">
165 <parameter name="aItem"/>
166 <parameter name="aSkipAnimation"/>
167 <body>
168 <![CDATA[
169 if (aItem == this.currentNotification)
170 this.removeCurrentNotification(aSkipAnimation);
171 else if (aItem != this._closedNotification)
172 this._removeNotificationElement(aItem);
173 return aItem;
174 ]]>
175 </body>
176 </method>
177
178 <method name="_removeNotificationElement">
179 <parameter name="aChild"/>
180 <body>
181 <![CDATA[
182 if (aChild.eventCallback)
183 aChild.eventCallback("removed");
184 this.removeChild(aChild);
185
186 // make sure focus doesn't get lost (workaround for bug 570835)
187 let fm = Components.classes["@mozilla.org/focus-manager;1"]
188 .getService(Components.interfaces.nsIFocusManager);
189 if (!fm.getFocusedElementForWindow(window, false, {}))
190 fm.moveFocus(window, this, fm.MOVEFOCUS_FORWARD, 0);
191 ]]>
192 </body>
193 </method>
194
195 <method name="removeCurrentNotification">
196 <parameter name="aSkipAnimation"/>
197 <body>
198 <![CDATA[
199 this._showNotification(this.currentNotification, false, aSkipAnimation);
200 ]]>
201 </body>
202 </method>
203
204 <method name="removeAllNotifications">
205 <parameter name="aImmediate"/>
206 <body>
207 <![CDATA[
208 var notifications = this.allNotifications;
209 for (var n = notifications.length - 1; n >= 0; n--) {
210 if (aImmediate)
211 this._removeNotificationElement(notifications[n]);
212 else
213 this.removeNotification(notifications[n]);
214 }
215 this.currentNotification = null;
216
217 // Must clear up any currently animating notification
218 if (aImmediate)
219 this._finishAnimation();
220 ]]>
221 </body>
222 </method>
223
224 <method name="removeTransientNotifications">
225 <body>
226 <![CDATA[
227 var notifications = this.allNotifications;
228 for (var n = notifications.length - 1; n >= 0; n--) {
229 var notification = notifications[n];
230 if (notification.persistence)
231 notification.persistence--;
232 else if (Date.now() > notification.timeout)
233 this.removeNotification(notification);
234 }
235 ]]>
236 </body>
237 </method>
238
239 <method name="_showNotification">
240 <parameter name="aNotification"/>
241 <parameter name="aSlideIn"/>
242 <parameter name="aSkipAnimation"/>
243 <body>
244 <![CDATA[
245 this._finishAnimation();
246
247 var height = aNotification.boxObject.height;
248 var skipAnimation = aSkipAnimation || (height == 0);
249
250 if (aSlideIn) {
251 this.currentNotification = aNotification;
252 aNotification.style.removeProperty("position");
253 aNotification.style.removeProperty("top");
254 aNotification.style.removeProperty("margin-top");
255 aNotification.style.removeProperty("opacity");
256
257 if (skipAnimation) {
258 this._setBlockingState(this.currentNotification);
259 return;
260 }
261 }
262 else {
263 this._closedNotification = aNotification;
264 var notifications = this.allNotifications;
265 var idx = notifications.length - 1;
266 this.currentNotification = (idx >= 0) ? notifications[idx] : null;
267
268 if (skipAnimation) {
269 this._removeNotificationElement(this._closedNotification);
270 this._closedNotification = null;
271 this._setBlockingState(this.currentNotification);
272 return;
273 }
274
275 aNotification.style.marginTop = -height + "px";
276 aNotification.style.opacity = 0;
277 }
278
279 this._animating = true;
280 ]]>
281 </body>
282 </method>
283
284 <method name="_finishAnimation">
285 <body><![CDATA[
286 if (this._animating) {
287 this._animating = false;
288 if (this._closedNotification) {
289 this._removeNotificationElement(this._closedNotification);
290 this._closedNotification = null;
291 }
292 this._setBlockingState(this.currentNotification);
293 }
294 ]]></body>
295 </method>
296
297 <method name="_setBlockingState">
298 <parameter name="aNotification"/>
299 <body>
300 <![CDATA[
301 var isblock = aNotification &&
302 aNotification.priority == this.PRIORITY_CRITICAL_BLOCK;
303 var canvas = this._blockingCanvas;
304 if (isblock) {
305 if (!canvas)
306 canvas = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
307 const XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
308 var content = this.firstChild;
309 if (!content ||
310 content.namespaceURI != XULNS ||
311 content.localName != "browser")
312 return;
313
314 var width = content.boxObject.width;
315 var height = content.boxObject.height;
316 content.collapsed = true;
317
318 canvas.setAttribute("width", width);
319 canvas.setAttribute("height", height);
320 canvas.setAttribute("flex", "1");
321
322 this.appendChild(canvas);
323 this._blockingCanvas = canvas;
324
325 var bgcolor = "white";
326 try {
327 var prefService = Components.classes["@mozilla.org/preferences-service;1"].
328 getService(Components.interfaces.nsIPrefBranch);
329 bgcolor = prefService.getCharPref("browser.display.background_color");
330
331 var win = content.contentWindow;
332 var context = canvas.getContext("2d");
333 context.globalAlpha = 0.5;
334 context.drawWindow(win, win.scrollX, win.scrollY,
335 width, height, bgcolor);
336 }
337 catch(ex) { };
338 }
339 else if (canvas) {
340 canvas.parentNode.removeChild(canvas);
341 this._blockingCanvas = null;
342 var content = this.firstChild;
343 if (content)
344 content.collapsed = false;
345 }
346 ]]>
347 </body>
348 </method>
349
350 </implementation>
351
352 <handlers>
353 <handler event="transitionend"><![CDATA[
354 if (event.target.localName == "notification" &&
355 event.propertyName == "margin-top")
356 this._finishAnimation();
357 ]]></handler>
358 </handlers>
359
360 </binding>
361
362 <binding id="notification" role="xul:alert">
363 <content>
364 <xul:hbox class="notification-inner outset" flex="1" xbl:inherits="type">
365 <xul:hbox anonid="details" align="center" flex="1"
366 oncommand="this.parentNode.parentNode._doButtonCommand(event);">
367 <xul:image anonid="messageImage" class="messageImage" xbl:inherits="src=image,type,value"/>
368 <xul:description anonid="messageText" class="messageText" flex="1" xbl:inherits="xbl:text=label"/>
369 <xul:spacer flex="1"/>
370 <children/>
371 </xul:hbox>
372 <xul:toolbarbutton ondblclick="event.stopPropagation();"
373 class="messageCloseButton close-icon tabbable"
374 xbl:inherits="hidden=hideclose"
375 tooltiptext="&closeNotification.tooltip;"
376 oncommand="document.getBindingParent(this).close();"/>
377 </xul:hbox>
378 </content>
379 <resources>
380 <stylesheet src="chrome://global/skin/notification.css"/>
381 </resources>
382 <implementation>
383 <property name="label" onset="this.setAttribute('label', val); return val;"
384 onget="return this.getAttribute('label');"/>
385 <property name="value" onset="this.setAttribute('value', val); return val;"
386 onget="return this.getAttribute('value');"/>
387 <property name="image" onset="this.setAttribute('image', val); return val;"
388 onget="return this.getAttribute('image');"/>
389 <property name="type" onset="this.setAttribute('type', val); return val;"
390 onget="return this.getAttribute('type');"/>
391 <property name="priority" onget="return parseInt(this.getAttribute('priority')) || 0;"
392 onset="this.setAttribute('priority', val); return val;"/>
393 <property name="persistence" onget="return parseInt(this.getAttribute('persistence')) || 0;"
394 onset="this.setAttribute('persistence', val); return val;"/>
395 <field name="timeout">0</field>
396
397 <property name="control" readonly="true">
398 <getter>
399 <![CDATA[
400 var parent = this.parentNode;
401 while (parent) {
402 if (parent.localName == "notificationbox")
403 return parent;
404 parent = parent.parentNode;
405 }
406 return null;
407 ]]>
408 </getter>
409 </property>
410
411 <method name="close">
412 <body>
413 <![CDATA[
414 var control = this.control;
415 if (control)
416 control.removeNotification(this);
417 else
418 this.hidden = true;
419 ]]>
420 </body>
421 </method>
422
423 <method name="_doButtonCommand">
424 <parameter name="aEvent"/>
425 <body>
426 <![CDATA[
427 if (!("buttonInfo" in aEvent.target))
428 return;
429
430 var button = aEvent.target.buttonInfo;
431 if (button.popup) {
432 document.getElementById(button.popup).
433 openPopup(aEvent.originalTarget, "after_start", 0, 0, false, false, aEvent);
434 aEvent.stopPropagation();
435 }
436 else {
437 var callback = button.callback;
438 if (callback) {
439 var result = callback(this, button);
440 if (!result)
441 this.close();
442 aEvent.stopPropagation();
443 }
444 }
445 ]]>
446 </body>
447 </method>
448 </implementation>
449 </binding>
450
451 <binding id="popup-notification">
452 <content align="start">
453 <xul:image class="popup-notification-icon"
454 xbl:inherits="popupid,src=icon"/>
455 <xul:vbox flex="1">
456 <xul:description class="popup-notification-description"
457 xbl:inherits="xbl:text=label"/>
458 <children includes="popupnotificationcontent"/>
459 <xul:label class="text-link popup-notification-learnmore-link"
460 xbl:inherits="href=learnmoreurl">&learnMore;</xul:label>
461 <xul:spacer flex="1"/>
462 <xul:hbox class="popup-notification-button-container"
463 pack="end" align="center">
464 <xul:button anonid="button"
465 class="popup-notification-menubutton"
466 type="menu-button"
467 xbl:inherits="oncommand=buttoncommand,label=buttonlabel,accesskey=buttonaccesskey">
468 <xul:menupopup anonid="menupopup"
469 xbl:inherits="oncommand=menucommand">
470 <children/>
471 <xul:menuitem class="menuitem-iconic popup-notification-closeitem"
472 label="&closeNotificationItem.label;"
473 xbl:inherits="oncommand=closeitemcommand,hidden=hidenotnow"/>
474 </xul:menupopup>
475 </xul:button>
476 </xul:hbox>
477 </xul:vbox>
478 <xul:vbox pack="start">
479 <xul:toolbarbutton anonid="closebutton"
480 class="messageCloseButton close-icon popup-notification-closebutton tabbable"
481 xbl:inherits="oncommand=closebuttoncommand"
482 tooltiptext="&closeNotification.tooltip;"/>
483 </xul:vbox>
484 </content>
485 <resources>
486 <stylesheet src="chrome://global/skin/notification.css"/>
487 </resources>
488 <implementation>
489 <field name="closebutton" readonly="true">
490 document.getAnonymousElementByAttribute(this, "anonid", "closebutton");
491 </field>
492 <field name="button" readonly="true">
493 document.getAnonymousElementByAttribute(this, "anonid", "button");
494 </field>
495 <field name="menupopup" readonly="true">
496 document.getAnonymousElementByAttribute(this, "anonid", "menupopup");
497 </field>
498 </implementation>
499 </binding>
500 </bindings>

mercurial