Add better text explaining what a membership means
[fripost-web.git] / site / js / bramus / jsProgressBarHandler.js
blob0051235c5c4cee66b598b220e6460998ba60c1af
1 /*****************************************************************\r
2  *\r
3  * jsProgressBarHandler 0.3.3 - by Bramus! - http://www.bram.us/\r
4  *\r
5  * v 0.3.3 - 2008.11.10 - UPD: fixed IE compatibility issue (thanks Kevin - Sep 19 2008 / 6pm)\r
6  *                      - UPD: setPercentage now parses the targetPercentage to an Integer to avoid infinite loop (thanks Jack - Sep 07 2008 / 9pm)\r
7  *                      - UPD: Moved from Event.Observe(window, 'load', fn) to document.observe('dom:loaded', fn) in order to force people to use an up to date Prototype release.\r
8  *                      - UPD: setPercentage now takes an overrideQueue param. If set the current queue is cleared.\r
9  *                      - ADD: Added onTick callback event which gets called when the percentage is updated.\r
10  *                      - ADD: Added stable (as in "non-crashing") versions of the additions which first surfaced in the (unreleased) 0.3.2 release\r
11  *                             Preloading support partially implemented in IE as all versions (IE6,7&8) are quite hard to tame (one time they work, the next reload they don't anymore)\r
12  * v 0.3.2 - 2008.04.09 (*UNRELEASED*)\r
13  *                      - ADD: implemented preloading of images to avoid slight flicker when switching images (BUGGY!)\r
14  *                      - ADD: percentage image now has class percentImage and percentage Text now has class percentText; This allows you to style the output easily.\r
15  * v 0.3.1 - 2008.02.20 - UPD: fixed queue bug when animate was set to false (thanks Jamie Chong)\r
16  *                      - UPD: update Prototype to version 1.6.0.2\r
17  * v 0.3.0 - 2008.02.01 - ADD: animation queue, prevents from the progressbar getting stuck when multiple calls are made during an animation\r
18  *                      - UPD: multiple barImages now work properly in Safari\r
19  * v 0.2.1 - 2007.12.20 - ADD: option : set boxImage\r
20  *                        ADD: option : set barImage (one or more)\r
21  *                        ADD: option : showText\r
22  * v 0.2   - 2007.12.13 - SYS: rewrite in 2 classs including optimisations\r
23  *                        ADD: Config options\r
24  * v 0.1   - 2007.08.02 - initial release\r
25  *\r
26  * @see http://www.barenakedapp.com/the-design/displaying-percentages on how to create a progressBar Background Image!\r
27  *\r
28  * Licensed under the Creative Commons Attribution 2.5 License - http://creativecommons.org/licenses/by/2.5/\r
29  *\r
30  *****************************************************************/\r
33  /**\r
34   * CONFIG\r
35   * -------------------------------------------------------------\r
36   */\r
38         // Should jsProgressBarHandler hook itself to all span.progressBar elements? - default : true\r
39                 var autoHook    = true; \r
40  \r
41         // Default Options\r
42                 var defaultOptions = {\r
43                         animate         : true,                                                                         // Animate the progress? - default: true\r
44                         showText        : true,                                                                         // show text with percentage in next to the progressbar? - default : true\r
45                         width           : 120,                                                                          // Width of the progressbar - don't forget to adjust your image too!!!\r
46                         boxImage        : 'images/bramus/percentImage.png',                     // boxImage : image around the progress bar\r
47                         barImage        : 'images/bramus/percentImage_back1.png',       // Image to use in the progressbar. Can be an array of images too.\r
48                         height          : 12,                                                                           // Height of the progressbar - don't forget to adjust your image too!!!\r
49                         onTick          : function(pbObj) { return true }\r
50                 }\r
52  /**\r
53   * NO NEED TO CHANGE ANYTHING BENEATH THIS LINE\r
54   * -------------------------------------------------------------\r
55   */\r
57         /**\r
58          * JS_BRAMUS Object\r
59          * -------------------------------------------------------------\r
60          */\r
62                 if (!JS_BRAMUS) { var JS_BRAMUS = new Object(); }\r
65         /**\r
66          * ProgressBar Class\r
67          * -------------------------------------------------------------\r
68          */\r
70                 JS_BRAMUS.jsProgressBar = Class.create();\r
72                 JS_BRAMUS.jsProgressBar.prototype = {\r
75                         /**\r
76                          * Datamembers\r
77                          * -------------------------------------------------------------\r
78                          */\r
79                          \r
80                                 el                              : null,                                                         // Element where to render the progressBar in\r
81                                 id                              : null,                                                         // Unique ID of the progressbar\r
82                                 percentage              : null,                                                         // Percentage of the progressbar\r
84                                 options                 : null,                                                         // The options\r
86                                 initialPos              : null,                                                         // Initial postion of the background in the progressbar\r
87                                 initialPerc             : null,                                                         // Initial percentage the progressbar should hold\r
88                                 pxPerPercent    : null,                                                         // Number of pixels per 1 percent\r
90                                 backIndex               : null,                                                         // index in the array of background images currently used\r
91                                 numPreloaded    : null,                                                         // number of images preloaded\r
93                                 running                 : null,                                                         // is this one running (being animated) or not?\r
95                                 queue                   : false,                                                        // queue of percentages to set to\r
98                         /**\r
99                          * Constructor\r
100                          *\r
101                          * @param HTMLElement el\r
102                          * @param string id\r
103                          * @param int percentage\r
104                          * @return void\r
105                          * -------------------------------------------------------------\r
106                          */\r
107                          \r
108                                 initialize              : function(el, percentage, options) {\r
110                                         // get the options\r
111                                         this.options                    = Object.clone(defaultOptions);\r
112                                         Object.extend(this.options, options || {});\r
114                                         // datamembers from arguments\r
115                                         this.el                         = $(el);\r
116                                         this.id                         = $(el).id;\r
117                                         this.percentage         = 0;                                                    // Set to 0 intially, we'll change this later.\r
118                                         this.backIndex          = 0;                                                    // Set to 0 initially\r
119                                         this.numPreloaded       = 0;                                                    // Set to 0 initially\r
120                                         this.running            = false;                                                // Set to false initially\r
121                                         this.queue                      = Array();                                              // Set to empty Array initially\r
123                                         // datamembers which are calculatef\r
124                                         this.imgWidth           = this.options.width * 2;               // define the width of the image (twice the width of the progressbar)\r
125                                         this.initialPos         = this.options.width * (-1);    // Initial postion of the background in the progressbar (0% is the middle of our image!)\r
126                                         this.pxPerPercent       = this.options.width / 100;             // Define how much pixels go into 1%\r
127                                         this.initialPerc        = percentage;                                   // Store this, we'll need it later.\r
129                                         // enfore backimage array\r
130                                         if (this.options.barImage.constructor != Array) {       // used to be (but doesn't work in Safari): if (this.options.barImage.constructor.toString().indexOf("Array") == -1) {\r
131                                                 this.options.barImage = Array(this.options.barImage);\r
132                                         }\r
134                                         // preload Images\r
135                                         this.preloadImages();\r
137                                 },\r
140                         /**\r
141                          * Preloads the images needed for the progressbar\r
142                          *\r
143                          * @return void\r
144                          * -------------------------------------------------------------\r
145                          */\r
147                                 preloadImages   : function() {\r
149                                         // loop all barimages\r
150                                         for (i = 0; i < this.options.barImage.length; i++) {\r
152                                                 // create new image ref\r
153                                                 var newImage = null;\r
154                                                 newImage = new Image();\r
156                                                 // set onload, onerror and onabort functions\r
157                                                 newImage.onload         = function() { this.numPreloaded++; }.bind(this);\r
158                                                 newImage.onerror        = function() { this.numPreloaded++; }.bind(this);\r
159                                                 newImage.onabort        = function() { this.numPreloaded++; }.bind(this);\r
161                                                 // set image source (preload it!)\r
162                                                 newImage.src = this.options.barImage[i];\r
164                                                 // image is in cache\r
165                                                 if (newImage.complete) {\r
166                                                         this.numPreloaded++;\r
167                                                 }\r
168                                                 \r
169                                         }\r
171                                         // if not IE, check if they're loaded\r
172                                         if (!Prototype.Browser.IE) {\r
173                                                 this.checkPreloadedImages();\r
175                                         // if IE, just init the visuals as it's quite hard to tame all IE's\r
176                                         } else {\r
177                                                 this.initVisuals();\r
178                                         }\r
180                                 },\r
183                         /**\r
184                          * Check whether all images are preloaded and loads the percentage if so\r
185                          *\r
186                          * @return void\r
187                          * -------------------------------------------------------------\r
188                          */\r
190                                 checkPreloadedImages    : function() {\r
192                                         // all images are loaded, go init the visuals\r
193                                         if (parseInt(this.numPreloaded,10) >= parseInt(this.options.barImage.length,10) ) {\r
195                                                 // initVisuals\r
196                                                 this.initVisuals();\r
198                                         // not all images are loaded ... wait a little and then retry\r
199                                         } else {\r
201                                                 if ( parseInt(this.numPreloaded,10) <= parseInt(this.options.barImage.length,10) ) {\r
202                                                         // $(this.el).update(this.id + ' : ' + this.numPreloaded + '/' + this.options.barImage.length);\r
203                                                         setTimeout(function() { this.checkPreloadedImages(); }.bind(this), 100);\r
204                                                 }\r
206                                         }\r
208                                 },\r
211                         /**\r
212                          * Intializes the visual output and sets the percentage\r
213                          *\r
214                          * @return void\r
215                          * -------------------------------------------------------------\r
216                          */                             \r
217                                 \r
218                                 initVisuals             : function () {\r
220                                         // create the visual aspect of the progressBar\r
221                                         $(this.el).update(\r
222                                                 '<img id="' + this.id + '_percentImage" src="' + this.options.boxImage + '" alt="0%" style="width: ' + this.options.width + 'px; height: ' + this.options.height + 'px; background-position: ' + this.initialPos + 'px 50%; background-image: url(' + this.options.barImage[this.backIndex] + '); padding: 0; margin: 0;" class="percentImage" />' + \r
223                                                 ((this.options.showText == true)?'<span id="' + this.id + '_percentText" class="percentText">0%</span>':''));\r
224                                 \r
225                                         // set the percentage\r
226                                         this.setPercentage(this.initialPerc);\r
227                                 },\r
228                         \r
229                         \r
230                         /**\r
231                          * Sets the percentage of the progressbar\r
232                          *\r
233                          * @param string targetPercentage\r
234                          * @param boolen clearQueue\r
235                          * @return void\r
236                          * -------------------------------------------------------------\r
237                          */\r
238                                 setPercentage   : function(targetPercentage, clearQueue) {\r
239                                         \r
240                                         // if clearQueue is set, empty the queue and then set the percentage\r
241                                         if (clearQueue) {\r
242                                                 \r
243                                                 this.percentage = (this.queue.length != 0) ? this.queue[0] : targetPercentage;\r
244                                                 this.timer              = null;\r
245                                                 this.queue              = [];\r
246                                                 \r
247                                                 setTimeout(function() { this.setPercentage(targetPercentage); }.bind(this), 10);\r
248                                                 \r
249                                         // no clearQueue defined, set the percentage\r
250                                         } else {\r
251                                         \r
252                                                 // add the percentage on the queue\r
253                                                 this.queue.push(targetPercentage);\r
254                                                 \r
255                                                 // process the queue (if not running already)\r
256                                                 if (this.running == false) {\r
257                                                         this.processQueue();\r
258                                                 }\r
259                                         }\r
260                                         \r
261                                 },\r
262                         \r
263                         \r
264                         /**\r
265                          * Processes the queue\r
266                          *\r
267                          * @return void\r
268                          * -------------------------------------------------------------\r
269                          */\r
270                                 \r
271                                 processQueue    : function() {\r
272                                         \r
273                                         // stuff on queue?\r
274                                         if (this.queue.length > 0) {\r
275                                                 \r
276                                                 // tell the world that we're busy\r
277                                                 this.running = true;\r
278                                                 \r
279                                                 // process the entry\r
280                                                 this.processQueueEntry(this.queue[0]);\r
281                                                 \r
282                                         // no stuff on queue\r
283                                         } else {\r
284                                                         \r
285                                                 // return;\r
286                                                 return;\r
287                                                         \r
288                                         }\r
289                                         \r
290                                 },\r
291                         \r
292                         \r
293                         /**\r
294                          * Processes an entry from the queue (viz. animates it)\r
295                          *\r
296                          * @param string targetPercentage\r
297                          * @return void\r
298                          * -------------------------------------------------------------\r
299                          */\r
300                                 \r
301                                 processQueueEntry       : function(targetPercentage) {\r
302                                                                                 \r
303                                         // get the current percentage\r
304                                         var curPercentage       = parseInt(this.percentage,10);\r
305                                         \r
306                                         // define the new percentage\r
307                                         if ((targetPercentage.toString().substring(0,1) == "+") || (targetPercentage.toString().substring(0,1) == "-")) {\r
308                                                 targetPercentage        = curPercentage + parseInt(targetPercentage);\r
309                                         }\r
310                                 \r
311                                         // min and max percentages\r
312                                         if (targetPercentage < 0)               targetPercentage = 0;\r
313                                         if (targetPercentage > 100)             targetPercentage = 100;\r
314                                         \r
315                                         // if we don't need to animate, just change the background position right now and return\r
316                                         if (this.options.animate == false) {\r
317                                                 \r
318                                                 // remove the entry from the queue \r
319                                                 this.queue.splice(0,1); // @see: http://www.bram.us/projects/js_bramus/jsprogressbarhandler/#comment-174878\r
320                                                 \r
321                                                 // Change the background position (and update this.percentage)\r
322                                                 this._setBgPosition(targetPercentage);\r
323                                         \r
324                                                 // call onTick\r
325                                                 if (!this.options.onTick(this)) {\r
326                                                         return; \r
327                                                 }\r
328                                                 \r
329                                                 // we're not running anymore\r
330                                                 this.running = false;\r
331                                                 \r
332                                                 // continue processing the queue\r
333                                                 this.processQueue();\r
334                                                 \r
335                                                 // we're done!\r
336                                                 return;\r
337                                         }\r
338                                         \r
339                                         // define if we need to add/subtract something to the current percentage in order to reach the target percentage\r
340                                         if (targetPercentage != curPercentage) {                                        \r
341                                                 if (curPercentage < targetPercentage) {\r
342                                                         newPercentage = curPercentage + 1;\r
343                                                 } else {\r
344                                                         newPercentage = curPercentage - 1;      \r
345                                                 }                                               \r
346                                                 callTick = true;                                                \r
347                                         } else {\r
348                                                 newPercentage = curPercentage;\r
349                                                 callTick = false;\r
350                                         }                                                                                       \r
351                                                                                         \r
352                                         // Change the background position (and update this.percentage)\r
353                                         this._setBgPosition(newPercentage);\r
354                                         \r
355                                         // call onTick\r
356                                         if (callTick && !this.options.onTick(this)) {\r
357                                                 return; \r
358                                         }\r
359                                         \r
360                                         // Percentage not reached yet : continue processing entry\r
361                                         if (curPercentage != newPercentage) {\r
362                                                 \r
363                                                 this.timer = setTimeout(function() { this.processQueueEntry(targetPercentage); }.bind(this), 10);\r
364                                                 \r
365                                         // Percentage reached!\r
366                                         } else {\r
367                                                                                                                   \r
368                                                 // remove the entry from the queue\r
369                                                 this.queue.splice(0,1);\r
370                                                 \r
371                                                 // we're not running anymore\r
372                                                 this.running = false;   \r
373                                                 \r
374                                                 // unset timer\r
375                                                 this.timer = null;\r
376                                                 \r
377                                                 // process the rest of the queue\r
378                                                 this.processQueue();\r
379                                                 \r
380                                                 // we're done!\r
381                                                 return;\r
382                                         }\r
383                                         \r
384                                 },\r
385                         \r
386                         \r
387                         /**\r
388                          * Gets the percentage of the progressbar\r
389                          *\r
390                          * @return int\r
391                          */\r
392                                 getPercentage           : function(id) {\r
393                                         return this.percentage;\r
394                                 },\r
395                         \r
396                         \r
397                         /**\r
398                          * Set the background position\r
399                          *\r
400                          * @param int percentage\r
401                          */\r
402                                 _setBgPosition          : function(percentage) {\r
403                                         // adjust the background position\r
404                                                 $(this.id + "_percentImage").style.backgroundPosition   = (this.initialPos + (percentage * this.pxPerPercent)) + "px 50%";\r
405                                                                                                 \r
406                                         // adjust the background image and backIndex\r
407                                                 var newBackIndex                                                                                = Math.floor((percentage-1) / (100/this.options.barImage.length));\r
408                                                 \r
409                                                 if ((newBackIndex != this.backIndex) && (this.options.barImage[newBackIndex] != undefined)) {\r
410                                                         $(this.id + "_percentImage").style.backgroundImage      = "url(" + this.options.barImage[newBackIndex] + ")";\r
411                                                 }\r
412                                                 \r
413                                                 this.backIndex                                                                                  = newBackIndex;\r
414                                         \r
415                                         // Adjust the alt & title of the image\r
416                                                 $(this.id + "_percentImage").alt                                                = percentage + "%";\r
417                                                 $(this.id + "_percentImage").title                                              = percentage + "%";\r
418                                                 \r
419                                         // Update the text\r
420                                                 if (this.options.showText == true) {\r
421                                                         $(this.id + "_percentText").update("" + percentage + "%");\r
422                                                 }\r
423                                                 \r
424                                         // adjust datamember to stock the percentage\r
425                                                 this.percentage = percentage;\r
426                                 }\r
427                 }\r
430         /**\r
431          * ProgressHandlerBar Class - automatically create ProgressBar instances\r
432          * -------------------------------------------------------------\r
433          */\r
434          \r
435                 JS_BRAMUS.jsProgressBarHandler = Class.create();\r
437         \r
438                 JS_BRAMUS.jsProgressBarHandler.prototype = {\r
439                         \r
440                         \r
441                         /**\r
442                          * Datamembers\r
443                          * -------------------------------------------------------------\r
444                          */\r
445                          \r
446                                 pbArray                         : new Array(),          // Array of progressBars\r
447                 \r
448                 \r
449                         /**\r
450                          * Constructor\r
451                          *\r
452                          * @return void\r
453                          * -------------------------------------------------------------\r
454                          */\r
455                          \r
456                                 initialize                      : function() {          \r
457                                 \r
458                                         // get all span.progressBar elements\r
459                                         $$('span.progressBar').each(function(el) {\r
460                                                                                                                  \r
461                                                 // create a progressBar for each element\r
462                                                 this.pbArray[el.id]     = new JS_BRAMUS.jsProgressBar(el, parseInt(el.innerHTML.replace("%",""))); \r
463                                         \r
464                                         }.bind(this));\r
465                                 },\r
466                 \r
467                 \r
468                         /**\r
469                          * Set the percentage of a progressbar\r
470                          *\r
471                          * @param string el\r
472                          * @param string percentage\r
473                          * @return void\r
474                          * -------------------------------------------------------------\r
475                          */\r
476                                 setPercentage           : function(el, percentage, clearQueue) {\r
477                                         this.pbArray[el].setPercentage(percentage, clearQueue);\r
478                                 },\r
479                 \r
480                 \r
481                         /**\r
482                          * Get the percentage of a progressbar\r
483                          *\r
484                          * @param string el\r
485                          * @return int percentage\r
486                          * -------------------------------------------------------------\r
487                          */\r
488                                 getPercentage           : function(el) {\r
489                                         return this.pbArray[el].getPercentage();\r
490                                 }\r
491                         \r
492                 }\r
495         /**\r
496          * ProgressHandlerBar Class - hook me or not?\r
497          * -------------------------------------------------------------\r
498          */\r
499         \r
500                 if (autoHook == true) {\r
501                         function initProgressBarHandler() { myJsProgressBarHandler = new JS_BRAMUS.jsProgressBarHandler(); }\r
502                         document.observe('dom:loaded', initProgressBarHandler, false);\r
503                 }\r