﻿/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * File:		SMDragDrop.js
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 *
 * Purpose:	javascript AJAX progress bar
 *			
 * Copyright:	Synaptic Mash 2008 All Rights Reserved
 *
 * Classes:
 *		none
 *		
 * Requirements:
 *		basicajax.js
 *
 * Developer contact:	Jason Hillier <jason.hillier@synapticmash.com>
 * 
 * Notes:
 * ------
 * javascript AJAX progress bar function. automatically calls back to server
 * to get elapsed progress. when 100% is reached, it executes specified
 * action.
 * NOTE: on the form, you need two divs for this: i.e.:
 * <div class="progressBar_border" style="width:100px;"><div id='divProgress' class="progressBar_contents" ></div></div>
 * OR:
 * the function library can handle drawing the progress bar for you e.g.:
 * startProgressDraw(_progURL, _divProgressID, _scriptWhenDone, progStyle);
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
 //constants
 var UPDATE_SPEED=1000;
 
 //globals
 var divProgressID;
 var scriptWhenDone;
 var progURL;
 
 //<summary>
 //EntryPoint: just call this function to start a progress bar
 //</summary>
 //<parameters>
 //progURL=URL to get an integer from 0 to 100 which indicates progress
 //divID=id of div tag to update
 //scriptWhenDone=javascript to run when progress reached 100%
 //</parameters>
 function startProgress(_progURL, _divProgressID, _scriptWhenDone)
 {
	divProgressID=_divProgressID;
	scriptWhenDone=_scriptWhenDone;
	progURL=_progURL;
	
	//firefox bug fix - requires iframe ajax to be called from setTimeout
	setTimeout("new Ajax.Request('" + progURL + "',{ method: 'get', onSuccess: onProgressUpdate });", 1000);
 }
 
  //<summary>
 //EntryPoint: just call this function to start a progress bar
 //</summary>
 //<parameters>
 //progURL=URL to get an integer from 0 to 100 which indicates progress
 //divID=id of div tag to update
 //scriptWhenDone=javascript to run when progress reached 100%
 //progStyle=style of outside box. (eg you can have it draw to absolute, such as: "display:absolute;width:100px;top:200px;left:200px;"
 //</parameters>
 function startProgressDraw(_progURL, _divProgressID, _scriptWhenDone, progStyle)
 {
	//TODO: this is not yet implemented
 }
 
 function onProgressUpdate(transport)
{
	var divProgress=document.getElementById(divProgressID);
	var progValue=transport.responseText;
	
	if ((progValue*1)=="NaN")
	{
		//TODO: better handling for when something goes wrong
		alert("ERROR checking file progress.");
		return;
	}
	
	//repeat until we hit 100%
	if (progValue<100)
	{
		//
		
		//firefox bug fix - requires iframe ajax to be called from setTimeout
		setTimeout("new Ajax.Request('" + progURL + "',{ method: 'get', onSuccess: onProgressUpdate });", UPDATE_SPEED);
	}
	else
	{
		progValue=100; //update progress bar to exactly 100%
		if (scriptWhenDone!=null && scriptWhenDone!='') setTimeout(scriptWhenDone, 10);
	}
	
	//UPDATE PROGRESS BAR --->
	
	//figure out what 100% is in pixels
	var totalWidth=divProgress.parentNode.style.width.replace("px", "");
	var multipleFactor=totalWidth/100;
	var divNewWidth=progValue*multipleFactor;
	
	//display update to progress bar
	divProgress.style.width=divNewWidth + "px";
}

function resetProgress()
{
	var divProgress=document.getElementById(divProgressID);
	divProgress.style.width="0px";
}

//ABOVE FUNCTIONS ARE BEING DEPRECATED AND PUT INTO THIS CLASS
//TODO: make this class cleanup after itself
var SMProgress_currentInstance=null;

 //<summary>
 //Create an instance of a progress bar object.
 //</summary>
 //<parameters>
 //aboveElement: (required) - the HTML DOM element to center the progress bar over
 //</parameters>
var SMProgress=Class.create({
	_options: [],
	_element: null,
	_avgIntervals: 0,
	_progress: 0,
	_intervalObj: null,
	_state: 'off',
	
	initialize: function()
	{
		this._options=Object.extend({
			style: 'auto',
			aboveElement: null,
			cssProgress_outside: null,
			cssProgress_inside: null,
			AsyncURL:null,
			AsyncComplete:null,
			AsyncID:null
			}, arguments[0] || { });
		
		if (this._options.aboveElement)
		{
			this._options.aboveElement=$(this._options.aboveElement);
		}
		else
		{
			this._options.aboveElement=document.viewport;
		}
	},
	
	show: function(aboveElement)
	{
		if (this._state=='on') return;
		
		if (aboveElement!=null) this._options.aboveElement=$(aboveElement);
		
		SMProgress_currentInstance=this;
		
		this._state='on';
		
		switch (this._options.style)
		{
			case "auto":
				if (this._avgIntervals==0)
				{
					this._showBusy();
				}
				else
				{
					this._progress=0;
					this._element=null;
					this._showProgress();
				}
				
				this._intervalObj=setInterval("SMProgress_currentInstance._showProgress()", 500);
				break;
			case "overlay":
				if (this._options.AsyncURL)
				{
					this._progress=0;
					this._element=null;
					SMProgress_Static.ProgressBars.push(this);
					this._showProgress();
				}
				break;
		}
	},
	
	_showBusy: function()
	{
		if (this._element==null)
		{
			this._element=document.createElement('div');
			this._element.appendChild(document.createElement('img'));
			Element.Methods.setStyle(this._element, "display:none;position:absolute;");
			document.body.appendChild(this._element);
		}
		
		var offsetTop=this._options.aboveElement.offsetTop;
		if (!offsetTop) offsetTop=0;
		var offsetLeft=this._options.aboveElement.offsetLeft;
		if (!offsetLeft) offsetLeft=0;
		
		var y=this._options.aboveElement.getDimensions().height/2+offsetTop;
		var x=this._options.aboveElement.getDimensions().width/2+offsetLeft;
		
		this._element.childNodes[0].src="/media/js/images/ajax-loader7.gif";
		Element.Methods.setStyle(this._element, "display:block;top:" + y + "px;left:" + x + "px;");
	},
	
	_showProgress: function()
	{
		if (!this._options.AsyncURL)
		{
			this._progress++;
			if (this._avgIntervals==0) return;
		}
		
		if (this._element==null)
		{
			this._element=document.createElement('div');
			this._element.appendChild(document.createElement('div'));
			this._element.childNodes[0].innerHTML="&nbsp;";
			
			document.body.appendChild(this._element);
			
			if (this._options.style=="overlay")
			{
				$(this._element).setStyle("display:block;position:absolute;background-color:#FFFFFF;");
				$(this._element).clonePosition(this._options.aboveElement);
				$(this._element).setStyle({opacity:.2});
				
				Element.Methods.setStyle(this._element.childNodes[0], "display:block;background-color:#A1C364;width:" + this._progress + "px;height:" + $(this._element).getDimensions().height + "px;");
			}
			else
			{
				//ProgressBar OUTSIDE style
				if (this._options.cssProgress_outside!=null)
				{
					Elements.Methods.addClassName(this._element, cssProgress_outside);
					Element.Methods.setStyle(this._element, "display:none;");
				}
				else
				{
					Element.Methods.setStyle(this._element, "display:none;position:absolute;border: solid 1px #000000;width:100px;height:16px;background-color:#FFFFFF;");
				}
				//ProgressBar INSIDE style
				if (this._options.cssProgress_inside!=null)
				{
					Elements.Methods.addClassName(this._element.childNodes[0], cssProgress_inside);
				}
				else
				{
					Element.Methods.setStyle(this._element.childNodes[0], "display:block;background-color:#A1C364;width:" + tmpProgress + "px;height:16px;");
				}
			}
		}
		
		if (this._options.AsyncURL)
		{
			//firefox bug fix - requires iframe ajax to be called from setTimeout
			setTimeout("new Ajax.Request('" + this._options.AsyncURL + "',{ method: 'get', onSuccess: SMProgress_Static.AsyncUpdate });", UPDATE_SPEED);
			
			return;
		}
		
		var offsetTop=this._options.aboveElement.offsetTop;
		if (!offsetTop) offsetTop=0;
		var offsetLeft=this._options.aboveElement.offsetLeft;
		if (!offsetLeft) offsetLeft=0;
		
		var y=this._options.aboveElement.getDimensions().height/2+offsetTop;
		var x=this._options.aboveElement.getDimensions().width/2+offsetLeft;
		var totalWidth=this._element.style.width.replace("px", "");
		
		var tmpProgress=this._progress/this._avgIntervals;
		if (tmpProgress>1) tmpProgress=.9; //if it went over it is taking longer than expected, show user we arent quite done yet
		
		tmpProgress=tmpProgress*totalWidth;
		
		Element.Methods.setStyle(this._element.childNodes[0], "width:" + tmpProgress + "px;");
		Element.Methods.setStyle(this._element, "display:block;");
		Element.Methods.setStyle(this._element, "top:" + y + "px;left:" + x + "px;");
	},
	
	hide: function()
	{
		this._state='off';
		
		Element.Methods.setStyle(this._element, "display:none;position:absolute;");
		
		var element = $(this._element);
		if(element&&element.up()){
			$(this._element).remove();
		}
		if (this._progress<=0) this._progress=1;
		if (this._avgIntervals<=0) this._avgIntervals=1;
		
		this._avgIntervals=(this._avgIntervals+this._progress)/2;
		
		clearInterval(this._intervalObj);
	}
});

var SMProgress_Static={
	ProgressBars: [],
	AsyncUpdate: function(transport)
	{
		//var current=SMProgress_currentInstance;
		
		var AsyncID=transport.responseText.split(":")[0];
		var progValue=transport.responseText.split(":")[1];
		
		var current=SMProgress_Static.GetHandleByID(AsyncID);
		
		if (!current)
		{
			//TODO: better handling for when something goes wrong
			alert("ERROR checking file progress. handle:" + AsyncID + " not found");
			return;
		}
		
		//repeat until we hit 100%
		if (progValue<100)
		{
			current._showProgress();
		}
		else
		{
			progValue=100; //update progress bar to exactly 100%
			if (current._options.AsyncComplete!=null) current._options.AsyncComplete(current._options.AsyncID);
		}
		
		//UPDATE PROGRESS BAR --->
		//figure out what 100% is in pixels
		var totalWidth=$(current._element).getDimensions().width;
		var multipleFactor=totalWidth/100;
		var divNewWidth=progValue*multipleFactor;
		//display update to progress bar
		Element.Methods.setStyle(current._element.childNodes[0],"width: " + divNewWidth + "px");
		
		if (progValue==100)
		{
			$(current._element).remove();
		}
	},
	
	GetHandleByID: function(AsyncID)
	{
		for (var i=0;i<SMProgress_Static.ProgressBars.length;i++)
		{
			if (SMProgress_Static.ProgressBars[i]._options.AsyncID==AsyncID)
			{
				return SMProgress_Static.ProgressBars[i];
			}
		}
		
		return null;
	}
}
