Added wrt files, prior to converting into Qt/C++.
[ptas] / wrt / zouba / WRTKit / UI / NotificationPopup.js
1 /*\r
2 � Copyright 2008 Nokia Corporation. All rights reserved.\r
3 \r
4 IMPORTANT:  The Nokia software ("WRTKit and Example Widget files") is supplied to you by Nokia\r
5 Corporation (�Nokia�) in consideration of your agreement to the following terms. Your use, installation\r
6 and/or redistribution of the WRTKit and Example Widget files constitutes acceptance of these terms. If\r
7 you do not agree with these terms, please do not use, install, or redistribute the WRTKit and Example\r
8 Widget files.\r
9 \r
10 In consideration of your agreement to abide by the following terms, and subject to these terms, Nokia\r
11 grants you a personal, non-exclusive license, under Nokia�s copyrights in the WRTKit and Example\r
12 Widget files, to use, reproduce, and redistribute the WRTKit and Example files, in text form (for HTML,\r
13 CSS, or JavaScript files) or binary form (for associated images), for the sole purpose of creating S60\r
14 Widgets.\r
15 \r
16 If you redistribute the WRTKit and Example files, you must retain this entire notice in all such\r
17 redistributions of the WRTKit and Example files.\r
18 \r
19 You may not use the name, trademarks, service marks or logos of Nokia to endorse or promote products\r
20 that include the WRTKit and Example files without the prior written explicit agreement with Nokia.\r
21 Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by\r
22 Nokia herein, including but not limited to any patent rights that may be infringed by your products that\r
23 incorporate the WRTKit and Example files or by other works in which the WRTKit and Example files\r
24 may be incorporated.\r
25 \r
26 The WRTKit and Example files are provided on an "AS IS" basis.  NOKIA MAKES NO\r
27 WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED\r
28 WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A\r
29 PARTICULAR PURPOSE, REGARDING THE EXAMPLES OR ITS USE AND OPERATION\r
30 ALONE OR IN COMBINATION WITH YOUR PRODUCTS.\r
31 \r
32 IN NO EVENT SHALL NOKIA BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR\r
33 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\r
34 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\r
35 INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, AND/OR\r
36 DISTRIBUTION OF THE EXAMPLES, HOWEVER CAUSED AND WHETHER UNDER THEORY\r
37 OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE,\r
38 EVEN IF NOKIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
39 \r
40 */\r
41 \r
42 ///////////////////////////////////////////////////////////////////////////////\r
43 // The NotificationPopup class handles the display of notifications such as\r
44 // warnings, information messages and progress indication.\r
45 \r
46 // Constructor.\r
47 function NotificationPopup() {\r
48     // create notification popup\r
49     this.containerElement = document.createElement("div");\r
50     this.containerElement.className = "NotificationPopupContainer";\r
51     this.popupElement = document.createElement("div");\r
52     this.popupElement.className = "NotificationPopup";\r
53     this.typeIndicatorElement = document.createElement("div");\r
54     this.typeIndicatorElement.className = "NotificationPopupTypeIndicator";\r
55     this.textElement = document.createElement("div");\r
56     this.textElement.className = "NotificationPopupText";\r
57     this.progressBarElement = document.createElement("div");\r
58     this.progressBarElement.className = "NotificationPopupProgressBar";\r
59     \r
60     // assemble popup\r
61     this.popupElement.appendChild(this.typeIndicatorElement);\r
62     this.popupElement.appendChild(this.textElement);\r
63     this.popupElement.appendChild(this.progressBarElement);\r
64     this.containerElement.appendChild(this.popupElement);\r
65     \r
66     // create progress bar image element and initialize it\r
67     this.progressBarImageElement = document.createElement("img");\r
68     var self = this;\r
69     this.progressBarImageElement.addEventListener("load", function() { self.progressBarImageLoadingCompleted(); }, false);\r
70     this.progressBarImageElement.setAttribute("alt", "");\r
71     this.progressBarImageURL = this.getProgressBarImage(0);\r
72     this.progressBarImageElement.src = this.progressBarImageURL;\r
73     this.progressBarElement.appendChild(this.progressBarImageElement);\r
74     \r
75     // init the popup to be fully down\r
76     this.popupElement.style.top = "100%";\r
77     \r
78     // set default popup contents\r
79     this.setPopupContents(null, null, null);\r
80 }\r
81 \r
82 // Notification container element.\r
83 NotificationPopup.prototype.containerElement = null;\r
84 \r
85 // Notification popup element.\r
86 NotificationPopup.prototype.popupElement = null;\r
87 \r
88 // Type indicator element.\r
89 NotificationPopup.prototype.typeIndicatorElement = null;\r
90 \r
91 // Notification text element.\r
92 NotificationPopup.prototype.textElement = null;\r
93 \r
94 // Progress bar element.\r
95 NotificationPopup.prototype.progressBarElement = null;\r
96 \r
97 // Progress bar image element.\r
98 NotificationPopup.prototype.progressBarImageElement = null;\r
99 \r
100 // Progress bar image URL.\r
101 NotificationPopup.prototype.progressBarImageURL = null;\r
102 \r
103 // Has the progress bar image been loaded?\r
104 NotificationPopup.prototype.progressBarImageLoaded = false;\r
105 \r
106 // Flag that tracks whether we're in the middle of starting to\r
107 // show a notification popup.\r
108 NotificationPopup.prototype.processingShowNotification = false;\r
109 \r
110 // Notification popup position (0 = hidden, 1 = showing).\r
111 NotificationPopup.prototype.popupPosition = 0;\r
112 \r
113 // Interval for timer ticks (in milliseconds)\r
114 NotificationPopup.prototype.ANIM_TIMER_INTERVAL = 25;\r
115 \r
116 // Animation timer identifier or null if no active timer.\r
117 NotificationPopup.prototype.animTimerId = null;\r
118 \r
119 // Time in milliseconds for the popup animation to complete\r
120 NotificationPopup.prototype.ANIM_TIME = 300;\r
121 \r
122 // Flag that determines the behavior of showNotification(). If set to true\r
123 // the popup will snap open when showNotification() is called instead of\r
124 // animation.\r
125 NotificationPopup.prototype.SHOW_SNAPS_OPEN = true;\r
126 \r
127 // Animation direction (0 = no movement, -1 hiding, +1 = showing).\r
128 NotificationPopup.prototype.animDir = 0;\r
129 \r
130 // Auto-hide timer identifier or null if no active timer.\r
131 NotificationPopup.prototype.autoHideTimerId = null;\r
132 \r
133 // The commanded display time.\r
134 NotificationPopup.prototype.displayTime = -1;\r
135 \r
136 // Displays a notification.\r
137 NotificationPopup.prototype.showNotification = function(displayTime, type, text, progress) {\r
138     uiLogger.debug("NotificationPopup.showNotification(" + displayTime + ", " + type + ", " + text + ", " + progress + ")");\r
139     \r
140     // mark that showNotification() has been called and that we are in\r
141     // the middle of starting to show the notification popup\r
142     this.processingShowNotification = true;\r
143     \r
144     // remember the display time\r
145     this.displayTime = displayTime;\r
146     \r
147     // attach the popup to the document if not attached\r
148     if (this.containerElement.parentNode == null) {\r
149         document.body.appendChild(this.containerElement);\r
150         uiLogger.debug("Notification popup attached to document");\r
151     }\r
152     \r
153     // set popup contents and update style\r
154     this.setPopupContents(type, text, progress);\r
155     \r
156     // if the progress image is loaded then we can complete the showing\r
157     // of the notification popup immediately - otherwise the image loaded\r
158     // allback will complete the process.\r
159     if (this.progressBarImageLoaded) {\r
160         this.completeShowNotification();\r
161     }\r
162 }\r
163 \r
164 // Completes displaying of a notification.\r
165 // Note: Used internally - don't call this directly.\r
166 NotificationPopup.prototype.completeShowNotification = function() {\r
167     uiLogger.debug("NotificationPopup.completeShowNotification()");\r
168     \r
169     // animation direction is +1 for showing the popup\r
170     if (this.popupPosition != 1) {\r
171         if (this.SHOW_SNAPS_OPEN) {\r
172             if (this.popupPosition == 0) {\r
173                 this.popupPosition = 1;\r
174             }\r
175         }\r
176         this.animatePopup(1);\r
177     }\r
178     \r
179     // setup auto hiding if a display time is specified\r
180     if (this.displayTime > 0) {\r
181         // stop any existing timer\r
182         if (this.autoHideTimerId != null) {\r
183             clearTimeout(this.autoHideTimerId);\r
184             uiLogger.debug("Auto hide timer stopped");\r
185         }\r
186         // set timer to hide notification\r
187         var self = this;\r
188         this.autoHideTimerId = setTimeout(function() {\r
189                                               if (self.displayTime > 0) {\r
190                                                   self.hideNotification();\r
191                                               }\r
192                                           }, this.ANIM_TIME + this.displayTime);\r
193         uiLogger.debug("Auto hide timer started");\r
194     }\r
195     \r
196     // mark us as no longer processing a show notification call\r
197     this.processingShowNotification = false;\r
198 }\r
199 \r
200 // Hides the currently displayed notification.\r
201 NotificationPopup.prototype.hideNotification = function() {\r
202     uiLogger.debug("NotificationPopup.hideNotification()");\r
203     // mark us as no longer processing a show notification call\r
204     this.processingShowNotification = false;\r
205     \r
206     // animation direction is -1 for hiding the popup\r
207     if (this.popupPosition != 0) {\r
208         this.animatePopup(-1);\r
209     }\r
210     \r
211     // stop auto hide timer if one is set\r
212     if (this.autoHideTimerId != null) {\r
213         clearTimeout(this.autoHideTimerId);\r
214         this.autoHideTimerId = null;\r
215         uiLogger.debug("Auto hide timer stopped");\r
216     }\r
217 }\r
218 \r
219 // Starts animation of the popup (1 to show, -1 to hide).\r
220 NotificationPopup.prototype.animatePopup = function(direction) {\r
221     uiLogger.debug("NotificationPopup.animatePopup(" + direction + ")");\r
222     // set the direction and star the animation timer\r
223     this.animDir = direction;\r
224     if (this.animTimerId == null) {\r
225         var self = this;\r
226         this.animTimerId = setInterval(function() { self.animate(); }, this.ANIM_TIMER_INTERVAL);\r
227         uiLogger.debug("Notification popup animation started");\r
228     }\r
229 }\r
230 \r
231 // Callback for animation timer.\r
232 NotificationPopup.prototype.animate = function() {\r
233     // calculate new popup position and clamp\r
234     var animStep = (this.ANIM_TIMER_INTERVAL / this.ANIM_TIME) * this.animDir;\r
235     var newPos = this.popupPosition + animStep;\r
236     if (newPos < 0) {\r
237         newPos = 0;\r
238     } else if (newPos > 1) {\r
239         newPos = 1;\r
240     }\r
241     \r
242     // set the new position to the popup element\r
243     this.popupPosition = newPos;\r
244     this.popupElement.style.top = (100 - Math.round(this.popupPosition * 100)) + "%";\r
245     \r
246     // have we reached the end of the animation?\r
247     if (newPos == 0 || newPos == 1) {\r
248         // reset animation direction\r
249         this.animDir = 0;\r
250         \r
251         // remove the popup from the body if its hidden\r
252         if (newPos == 0) {\r
253             document.body.removeChild(this.containerElement);\r
254             uiLogger.debug("Notification popup detached from document");\r
255         }\r
256         \r
257         // stop timer\r
258         clearTimeout(this.animTimerId);\r
259         this.animTimerId = null;\r
260         uiLogger.debug("Notification popup animation stopped");\r
261     }\r
262 }\r
263 \r
264 // Returns a URL for the progress bar image to use for the specified progress.\r
265 NotificationPopup.prototype.getProgressBarImage = function(progress) {\r
266     // path for progress bar images\r
267     var progressBarImagePath = "WRTKit/Resources/";\r
268     \r
269     if (progress < 0) {\r
270         // unknown progress\r
271         return progressBarImagePath + "ProgressBarUnknown.gif";\r
272     } else {\r
273         // known progress (should be between 0 and 1)\r
274         var progPct = Math.round(progress * 10) * 10;\r
275         if (progPct < 0) {\r
276             progPct = 0;\r
277         } else if (progPct > 100) {\r
278             progPct = 100;\r
279         }\r
280         return progressBarImagePath + "ProgressBar" + progPct + ".png";\r
281     }\r
282 }\r
283 \r
284 // Sets the contents of the popup.\r
285 NotificationPopup.prototype.setPopupContents = function(type, text, progress) {\r
286     uiLogger.debug("NotificationPopup.setPopupContents(" + type + ", " + text + ", " + progress + ")");\r
287     \r
288     // figure out notification type style name\r
289     var typeName = (type == null) ? "none" : type.toLowerCase();\r
290     typeName = typeName.charAt(0).toUpperCase() + typeName.substring(1);\r
291     \r
292     // set type element class names\r
293     this.typeIndicatorElement.className = "NotificationPopupTypeIndicator NotificationPopupTypeIndicator" + typeName;\r
294     \r
295     // set notification text\r
296     this.textElement.innerHTML = (text == null) ? "" : text;\r
297     \r
298     // set progress\r
299     this.progressBarElement.style.display = (progress == null) ? "none" : "block";\r
300     if (progress != null) {\r
301         var imgURL = this.getProgressBarImage(progress);\r
302         if (imgURL != this.progressBarImageURL) {\r
303             // load new image\r
304             this.progressBarImageLoaded = false;\r
305             this.progressBarImageURL = imgURL;\r
306             this.progressBarImageElement.src = imgURL;\r
307         } else {\r
308             // the correct image is already loaded\r
309             this.progressBarImageLoaded = true;\r
310         }\r
311     } else {\r
312         // there is no progress bar so there is no need\r
313         // to load any progress bar image\r
314         this.progressBarImageLoaded = true;\r
315     }\r
316 }\r
317 \r
318 // Callback for notifying the object that its progress bar image completed loading.\r
319 NotificationPopup.prototype.progressBarImageLoadingCompleted = function() {\r
320     uiLogger.debug("NotificationPopup.progressBarImageLoadingCompleted()");\r
321     \r
322     // mark the progress bar image as loaded\r
323     this.progressBarImageLoaded = true;\r
324     \r
325     // complete the process of displaying the notification popup\r
326     // if it has been commanded but not yet completed\r
327     if (this.processingShowNotification) {\r
328         this.completeShowNotification();\r
329     }\r
330 }\r