/*****************************************************************
 *
 * jsProgressBarHandler 0.3.3 - by Bramus! - http://www.bram.us/
 *
 * v 0.3.3 - 2008.11.10 - UPD: fixed IE compatibility issue (thanks Kevin - Sep 19 2008 / 6pm)
 *                      - UPD: setPercentage now parses the targetPercentage to an Integer to avoid infinite loop (thanks Jack - Sep 07 2008 / 9pm)
 *                      - 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.
 *                      - UPD: setPercentage now takes an overrideQueue param. If set the current queue is cleared.
 *                      - ADD: Added onTick callback event which gets called when the percentage is updated.
 *                      - ADD: Added stable (as in "non-crashing") versions of the additions which first surfaced in the (unreleased) 0.3.2 release
 *                             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)
 * v 0.3.2 - 2008.04.09 (*UNRELEASED*)
 *                      - ADD: implemented preloading of images to avoid slight flicker when switching images (BUGGY!)
 *                      - ADD: percentage image now has class percentImage and percentage Text now has class percentText; This allows you to style the output easily.
 * v 0.3.1 - 2008.02.20 - UPD: fixed queue bug when animate was set to false (thanks Jamie Chong)
 *                      - UPD: update Prototype to version 1.6.0.2
 * v 0.3.0 - 2008.02.01 - ADD: animation queue, prevents from the progressbar getting stuck when multiple calls are made during an animation
 *                      - UPD: multiple barImages now work properly in Safari
 * v 0.2.1 - 2007.12.20 - ADD: option : set boxImage
 *                        ADD: option : set barImage (one or more)
 *                        ADD: option : showText
 * v 0.2   - 2007.12.13 - SYS: rewrite in 2 classs including optimisations
 *                        ADD: Config options
 * v 0.1   - 2007.08.02 - initial release
 *
 * @see http://www.barenakedapp.com/the-design/displaying-percentages on how to create a progressBar Background Image!
 *
 * Licensed under the Creative Commons Attribution 2.5 License - http://creativecommons.org/licenses/by/2.5/
 *
 *****************************************************************/


 /**
  * CONFIG
  * -------------------------------------------------------------
  */

 	// Should jsProgressBarHandler hook itself to all span.progressBar elements? - default : true
		var autoHook	= true;	
 
 	// Default Options
		var defaultOptions = {
			animate		: true,										// Animate the progress? - default: true
			showText	: true,										// show text with percentage in next to the progressbar? - default : true
			width		: 120,										// Width of the progressbar - don't forget to adjust your image too!!!
			boxImage	: 'images/bramus/percentImage.png',			// boxImage : image around the progress bar
			barImage	: 'images/bramus/percentImage_back.png',	// Image to use in the progressbar. Can be an array of images too.
			height		: 12,										// Height of the progressbar - don't forget to adjust your image too!!!
			onTick		: function(pbObj) { return true }
		}

 /**
  * NO NEED TO CHANGE ANYTHING BENEATH THIS LINE
  * -------------------------------------------------------------
  */

	/**
	 * JS_BRAMUS Object
	 * -------------------------------------------------------------
	 */

		if (!JS_BRAMUS) { var JS_BRAMUS = new Object(); }


	/**
	 * ProgressBar Class
	 * -------------------------------------------------------------
	 */

		JS_BRAMUS.jsProgressBar = Class.create();

		JS_BRAMUS.jsProgressBar.prototype = {


		 /**
		 * Datamembers
		 * -------------------------------------------------------------
		 */

		 el: null, 							// Element where to render the progressBar in
		 id: null, 							// Unique ID of the progressbar
		 percentage: null, 							// Percentage of the progressbar

		 options: null, 							// The options

		 initialPos: null, 							// Initial postion of the background in the progressbar
		 initialPerc: null, 							// Initial percentage the progressbar should hold
		 pxPerPercent: null, 							// Number of pixels per 1 percent

		 backIndex: null, 							// index in the array of background images currently used
		 numPreloaded: null, 							// number of images preloaded

		 running: null, 							// is this one running (being animated) or not?

		 queue: false, 						// queue of percentages to set to


		 /**
		 * Constructor
		 *
		 * @param HTMLElement el
		 * @param string id
		 * @param int percentage
		 * @return void
		 * -------------------------------------------------------------
		 */

		 initialize: function(el, percentage, options) {

		  // get the options
		  this.options = Object.clone(defaultOptions);
		  Object.extend(this.options, options || {});

		  // datamembers from arguments
		  this.el = $(el);
		  this.id = $(el).id;
		  this.percentage = 0; 						// Set to 0 intially, we'll change this later.
		  this.backIndex = 0; 						// Set to 0 initially
		  this.numPreloaded = 0; 						// Set to 0 initially
		  this.running = false; 					// Set to false initially
		  this.queue = Array(); 					// Set to empty Array initially

		  // datamembers which are calculatef
		  this.imgWidth = this.options.width * 2; 	// define the width of the image (twice the width of the progressbar)
		  this.initialPos = this.options.width * (-1); // Initial postion of the background in the progressbar (0% is the middle of our image!)
		  this.pxPerPercent = this.options.width / 100; 	// Define how much pixels go into 1%
		  this.initialPerc = percentage; 				// Store this, we'll need it later.

		  // enfore backimage array
		  if (this.options.barImage.constructor != Array) { 	// used to be (but doesn't work in Safari): if (this.options.barImage.constructor.toString().indexOf("Array") == -1) {
		   this.options.barImage = Array(this.options.barImage);
		  }

		  // preload Images
		  this.preloadImages();

		 },


		 /**
		 * Preloads the images needed for the progressbar
		 *
		 * @return void
		 * -------------------------------------------------------------
		 */

		 preloadImages: function() {

		  // loop all barimages
		  for (i = 0; i < this.options.barImage.length; i++) {

		   // create new image ref
		   var newImage = null;
		   newImage = new Image();

		   // set onload, onerror and onabort functions
		   newImage.onload = function() { this.numPreloaded++; } .bind(this);
		   newImage.onerror = function() { this.numPreloaded++; } .bind(this);
		   newImage.onabort = function() { this.numPreloaded++; } .bind(this);

		   // set image source (preload it!)
		   newImage.src = this.options.barImage[i];

		   // image is in cache
		   if (newImage.complete) {
		    this.numPreloaded++;
		   }

		  }

		  // if not IE, check if they're loaded
		  if (!Prototype.Browser.IE) {
		   this.checkPreloadedImages();

		   // if IE, just init the visuals as it's quite hard to tame all IE's
		  } else {
		   this.initVisuals();
		  }

		 },


		 /**
		 * Check whether all images are preloaded and loads the percentage if so
		 *
		 * @return void
		 * -------------------------------------------------------------
		 */

		 checkPreloadedImages: function() {

		  // all images are loaded, go init the visuals
		  if (parseInt(this.numPreloaded, 10) >= parseInt(this.options.barImage.length, 10)) {

		   // initVisuals
		   this.initVisuals();

		   // not all images are loaded ... wait a little and then retry
		  } else {

		   if (parseInt(this.numPreloaded, 10) <= parseInt(this.options.barImage.length, 10)) {
		    // $(this.el).update(this.id + ' : ' + this.numPreloaded + '/' + this.options.barImage.length);
		    setTimeout(function() { this.checkPreloadedImages(); } .bind(this), 100);
		   }

		  }

		 },


		 /**
		 * Intializes the visual output and sets the percentage
		 *
		 * @return void
		 * -------------------------------------------------------------
		 */

		 initVisuals: function() {

		  // create the visual aspect of the progressBar
		  $(this.el).update(
						'<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" />' +
						((this.options.showText == true) ? '<span id="' + this.id + '_percentText" class="percentText">0%</span>' : ''));

		  // set the percentage
		  this.setPercentage(this.initialPerc);
		 },


		 /**
		 * Sets the percentage of the progressbar
		 *
		 * @param string targetPercentage
		 * @param boolen clearQueue
		 * @return void
		 * -------------------------------------------------------------
		 */
		 setPercentage: function(targetPercentage, clearQueue) {

		  // if clearQueue is set, empty the queue and then set the percentage
		  if (clearQueue) {

		   this.percentage = (this.queue.length != 0) ? this.queue[0] : targetPercentage;
		   this.timer = null;
		   this.queue = [];

		   setTimeout(function() { this.setPercentage(targetPercentage); } .bind(this), 10);

		   // no clearQueue defined, set the percentage
		  } else {

		   // add the percentage on the queue
		   this.queue.push(targetPercentage);

		   // process the queue (if not running already)
		   if (this.running == false) {
		    this.processQueue();
		   }
		  }

		 },


		 /**
		 * Processes the queue
		 *
		 * @return void
		 * -------------------------------------------------------------
		 */

		 processQueue: function() {

		  // stuff on queue?
		  if (this.queue.length > 0) {

		   // tell the world that we're busy
		   this.running = true;

		   // process the entry
		   this.processQueueEntry(this.queue[0]);

		   // no stuff on queue
		  } else {

		   // return;
		   return;

		  }

		 },


		 /**
		 * Processes an entry from the queue (viz. animates it)
		 *
		 * @param string targetPercentage
		 * @return void
		 * -------------------------------------------------------------
		 */

		 processQueueEntry: function(targetPercentage) {

		  // get the current percentage
		  var curPercentage = parseInt(this.percentage, 10);

		  // define the new percentage
		  if ((targetPercentage.toString().substring(0, 1) == "+") || (targetPercentage.toString().substring(0, 1) == "-")) {
		   targetPercentage = curPercentage + parseInt(targetPercentage);
		  }

		  // min and max percentages
		  if (targetPercentage < 0) targetPercentage = 0;
		  if (targetPercentage > 100) targetPercentage = 100;

		  // if we don't need to animate, just change the background position right now and return
		  if (this.options.animate == false) {

		   // remove the entry from the queue 
		   this.queue.splice(0, 1); // @see: http://www.bram.us/projects/js_bramus/jsprogressbarhandler/#comment-174878

		   // Change the background position (and update this.percentage)
		   this._setBgPosition(targetPercentage);

		   // call onTick
		   if (!this.options.onTick(this)) {
		    return;
		   }

		   // we're not running anymore
		   this.running = false;

		   // continue processing the queue
		   this.processQueue();

		   // we're done!
		   return;
		  }

		  // define if we need to add/subtract something to the current percentage in order to reach the target percentage
		  if (targetPercentage != curPercentage) {
		   if (curPercentage < targetPercentage) {
		    newPercentage = curPercentage + 1;
		   } else {
		    newPercentage = curPercentage - 1;
		   }
		   callTick = true;
		  } else {
		   newPercentage = curPercentage;
		   callTick = false;
		  }

		  // Change the background position (and update this.percentage)
		  this._setBgPosition(newPercentage);

		  // call onTick
		  if (callTick && !this.options.onTick(this)) {
		   return;
		  }

		  // Percentage not reached yet : continue processing entry
		  if (curPercentage != newPercentage) {

		   this.timer = setTimeout(function() { this.processQueueEntry(targetPercentage); } .bind(this), 10);

		   // Percentage reached!
		  } else {

		   // remove the entry from the queue
		   this.queue.splice(0, 1);

		   // we're not running anymore
		   this.running = false;

		   // unset timer
		   this.timer = null;

		   // process the rest of the queue
		   this.processQueue();

		   // we're done!
		   return;
		  }

		 },


		 /**
		 * Gets the percentage of the progressbar
		 *
		 * @return int
		 */
		 getPercentage: function(id) {
		  return this.percentage;
		 },


		 /**
		 * Set the background position
		 *
		 * @param int percentage
		 */
		 _setBgPosition: function(percentage) {
		 try{
		  // adjust the background position
		  $(this.id + "_percentImage").style.backgroundPosition = (this.initialPos + (percentage * this.pxPerPercent)) + "px 50%";

		  // adjust the background image and backIndex
		  var newBackIndex = Math.floor((percentage - 1) / (100 / this.options.barImage.length));

		  if ((newBackIndex != this.backIndex) && (this.options.barImage[newBackIndex] != undefined)) {
		   $(this.id + "_percentImage").style.backgroundImage = "url(" + this.options.barImage[newBackIndex] + ")";
		  }

		  this.backIndex = newBackIndex;

		  // Adjust the alt & title of the image
		  $(this.id + "_percentImage").alt = "";
		  $(this.id + "_percentImage").title = "";

		  // Update the text
		  if (this.options.showText == true) {
		   $(this.id + "_percentText").update("");
		  }

		  // adjust datamember to stock the percentage
		  this.percentage = percentage;
		 } catch (e)
		 { }
		}
		}


	/**
	 * ProgressHandlerBar Class - automatically create ProgressBar instances
	 * -------------------------------------------------------------
	 */
	 
		JS_BRAMUS.jsProgressBarHandler = Class.create();

	
		JS_BRAMUS.jsProgressBarHandler.prototype = {
			
			
			/**
			 * Datamembers
			 * -------------------------------------------------------------
			 */
			 
				pbArray				: new Array(),		// Array of progressBars
		
		
			/**
			 * Constructor
			 *
			 * @return void
			 * -------------------------------------------------------------
			 */
			 
				initialize			: function() {		
				
					// get all span.progressBar elements
					$$('span.progressBar').each(function(el) {
														 
						// create a progressBar for each element
						this.pbArray[el.id]	= new JS_BRAMUS.jsProgressBar(el, parseInt(el.innerHTML.replace("%",""))); 
					
					}.bind(this));
				},
		
		
			/**
			 * Set the percentage of a progressbar
			 *
			 * @param string el
			 * @param string percentage
			 * @return void
			 * -------------------------------------------------------------
			 */
				setPercentage		: function(el, percentage, clearQueue) {
					this.pbArray[el].setPercentage(percentage, clearQueue);
				},
		
		
			/**
			 * Get the percentage of a progressbar
			 *
			 * @param string el
			 * @return int percentage
			 * -------------------------------------------------------------
			 */
				getPercentage		: function(el) {
					return this.pbArray[el].getPercentage();
				}
			
		}


	/**
	 * ProgressHandlerBar Class - hook me or not?
	 * -------------------------------------------------------------
	 */
	
		if (autoHook == true) {
			function initProgressBarHandler() { myJsProgressBarHandler = new JS_BRAMUS.jsProgressBarHandler(); }
			document.observe('dom:loaded', initProgressBarHandler, false);
		}
