/**
 * 3D Rotate Tool JavaScript version
 * http://www.yofla.com/flash/3d-rotate/ 
 * 
 * License: All rights reserved for the function RotateToolManager
 *  Other classes in this file respect the copyright of their authors.
 *   
 * @author  Matus Laco matus@yofla.com
 * @since   06/2010
 * @updated 08/2010 
 * @version 0.0.2 
 * 
 * 
 * version 0.0.2
 * - added support for touch events
 * 
 */


function RotateToolManager(){var instances=new Array();var isAuthorized;var isSwfobject=(typeof(swfobject)=="undefined")?false:true;var isDomReady=false;var queue=new Array();var loadedCount=0;this.add=function(params){if(!params.target){alert("Target not defined!");return}var target=params.target;if(instances[target]){alert("Rotate Tool with target: "+target+" was already initialized!")}else{if(isSwfobject){if(swfobject.hasFlashPlayerVersion("9.0.0")){return}if(isDomReady){instances[target]=new RotateTool(params)}else{queue[target]=params}}else{var b=new RotateTool(params);instances[target]=b}}};this.checkXMLLoad=function(target){if(instances[target]&&instances[target].isXMLLoaded==false){alert("Failed loading xml: "+instances[target].getPathToConfig())}};this.rotate=function(target){instances[target].showNextImage()};this.domReady=function(){isDomReady=true;for(var i in queue){var params=queue[i];window.RotateTool.add(params)}};if(isSwfobject){swfobject.addDomLoadEvent(this.domReady)}this.authorize=function(){var authImgLoaded=function(){if(this.width==1){setAuthorized(true)}else{setAuthorized(false)}};var authImgError=function(){setAuthorized(true)};var domain=document.location.href;var parentDomain=top.location.href;var parentFrames=parent.frames.length;if(parentDomain&&domain&&parentDomain==domain){parentFrames=0}if(parentFrames>0){setAuthorized(false)}var authImg=document.createElement("img");authImg.onload=authImgLoaded;authImg.onerror=authImgError;authImg.src="https://authorize.yoflaserver.com/js/authimg.php?d="+domain+"&s=YOFLA&p=3DRTJS&v=0.0.2"};this.imagesLoaded=function(){var instancesCount=0;for(var i in instances){instancesCount++}loadedCount++;if(loadedCount==instancesCount){this.authorize()}};var setAuthorized=function(status){isAuthorized=status;for(var i in instances){instances[i].setAuthorized(status)}};var RotateTool=function(params){if(!params.path){params.path=""}if(!params.target){return false}if(!params.configFile){params.configFile="config.xml"}if(!document.getElementById(params.target)){alert('Could not find element with id: "'+params.target+'"!');return false}var target=params.target;var targetDiv=document.getElementById(params.target);var path=params.path;var configFile=params.configFile;var xmlLoader=new XMLLoader();var pathToConfig;var xmlTimeout;var logger=new YLogger();var log=function(msg){logger.logPrefix(msg,path+"@"+target)};var images=new Array();var imagesToLoad=0;var loadedImagesCount=0;var clickpane;var isAuthorized;var settings;var dx=1;var isRotating=false;var firstImageId=0;var rotateImage;var lastImgH;var newImgH;var hSteps;var previousImage=false;var rotateInterval;var rotateIntervalDuration=50;var lastPointerX=0;var startPointerX=0;var wasRotating=true;var isMouseDown=false;var targetWidth;var targetHeight;this.isXMLLoaded=false;this.getPathToConfig=function(){return pathToConfig};if(path.length>0){var pathLastChar=path.substr(path.length-1);if(pathLastChar=="/"||pathLastChar=="\\"){}else{path=path+"/"}}else{path=""}pathToConfig=path+configFile;if(params.targetWidth>0&&params.targetHeight>0){targetWidth=params.targetWidth-2;targetHeight=params.targetHeight-2;targetDiv.style.width=params.targetWidth+"px";targetDiv.style.height=params.targetHeight+"px"}else{if(targetDiv.offsetWidth==0||targetDiv.offsetHeight==0){alert("RotateTool: Target size not defined!")}else{targetWidth=targetDiv.offsetWidth;targetHeight=targetDiv.offsetHeight}}this.setAuthorized=function(status){isAuthorized=status;if(!isAuthorized){addCopyright()}};this.onXMLLoaded=function(xmldoc){this.isXMLLoaded="true";clearTimeout(xmlTimeout);var settingsNode=xmldoc.getElementsByTagName("settings")[0];settings=new Settings(settingsNode);var imagesNode=xmldoc.getElementsByTagName("images")[0];var imageNodes=imagesNode.getElementsByTagName("image");imagesToLoad=imageNodes.length;hSteps=imagesToLoad;if(imagesToLoad==0){var imageNodes=imagesNode.getElementsByTagName("img");imagesToLoad=imageNodes.length;hSteps=imagesToLoad}if(imagesToLoad==0){log("No Images loaded!")}preloader=new Preloader(targetDiv);for(var i=0;i<imagesToLoad;i++){var imagePath=path+imageNodes[i].getAttribute("src");var image=document.createElement("img");images.push(image);image.onload=imageLoaded;image.onerror=imageError;image.src=imagePath;image.style.display="none"}};this.showNextImage=function(){newImgH=lastImgH+dx;if(newImgH>=hSteps){newImgH=0}if(newImgH<0){newImgH=hSteps-1}try{rotateImage.src=images[newImgH].src}catch(err){}lastImgH=newImgH};var imagesLoaded=function(){for(var i in images){}targetDiv.appendChild(rotateImage);rotateImage.style.display="block";rotateIntervalDuration=(settings.rotation.rotatePeriod*1000)/hSteps;lastImgH=imagesToLoad-1;newImgH=0;window.RotateTool.rotate(target);clickpane=document.createElement("div");clickpane.style.width=targetWidth+"px";clickpane.style.height=targetHeight+"px";clickpane.style.display="block";clickpane.style.position="absolute";clickpane.style.left="0px";clickpane.style.top="0px";clickpane.style.cursor="pointer";clickpane.style.zIndex=90;targetDiv.appendChild(clickpane);if(DeviceDetector.isTouchDevice){clickpane.addEventListener("touchstart",touchStart,false);clickpane.addEventListener("touchmove",touchMove,false);clickpane.addEventListener("touchend",touchEnd,false);clickpane.addEventListener("touchcancel",touchCancel,false)}else{addEvent(clickpane,"mousedown",onMouseDown);addEvent(clickpane,"mouseup",onMouseUp)}window.RotateTool.imagesLoaded();startRotation()};var imageLoaded=function(){loadedImagesCount++;var percent=Math.round((loadedImagesCount/imagesToLoad)*100);preloader.update(percent);if(!rotateImage){rotateImage=this;var scaleRatio=1;var imageWidth=this.width;var imageHeight=this.height;var targetRatio=targetWidth/targetHeight;var imageRatio=imageWidth/imageHeight;if(targetRatio<imageRatio){scaleRatio=targetWidth/imageWidth}else{scaleRatio=targetHeight/imageHeight}var newHeight;var newWidth;newHeight=Math.floor(this.height*scaleRatio);newWidth=Math.floor(this.width*scaleRatio);this.height=newHeight;this.width=newWidth;this.style.position="absolute";var diff;if(targetHeight>newHeight){diff=(targetHeight-newHeight)/2;this.style.top=diff+"px"}else{diff=(targetWidth-newWidth)/2;this.style.left=diff+"px"}this.style.cursor="pointer";this.style.zIndex=10;if(window.attachEvent){addEvent(this,"mousedown",onMouseDown);addEvent(this,"mouseup",onMouseUp)}}if(imagesToLoad==loadedImagesCount){imagesLoaded();preloader.destroy()}};var onMouseDown=function(e){};var onMouseUp=function(e){if(isRotating){stopRotation()}else{startRotation()}};var onMouseMove=function(e){};var touchStart=function(event){wasRotating=isRotating;stopRotation();startPointerX=event.targetTouches[0].screenX};var touchEnd=function(event){var currentX=event.changedTouches[0].screenX;var dif=startPointerX-currentX;if(dif==0){if(wasRotating){stopRotation()}else{startRotation()}}else{startRotation()}};var touchMove=function(event){event.preventDefault();var currentPointerX=event.targetTouches[0].screenX;if(currentPointerX>lastPointerX){dx=-1;eval('window.RotateTool.rotate("'+target+'")')}else{if(currentPointerX<lastPointerX){dx=1;eval('window.RotateTool.rotate("'+target+'")')}else{dx=0}}lastPointerX=currentPointerX};var touchCancel=function(){stopRotation()};var imageError=function(){log("Error loading image: "+this.src)};var startRotation=function(){rotateInterval=setInterval('RotateTool.rotate("'+target+'")',rotateIntervalDuration);isRotating=true};var stopRotation=function(){clearInterval(rotateInterval);isRotating=false};var addCopyright=function(){var logo=document.createElement("div");logo.innerHTML='<a id="yoflalink" title="3D Rotate Tool by YoFLA.com" target="_blank" style="display: block; width: 25px; background-color: red; -moz-border-radius: 10px; -webkit-border-radius: 10px; color: white; text-decoration: none;" href="http://www.yofla.com/flash/3d-rotate/">Y</a>';logo.style.position="absolute";logo.style.fontSize="20px";logo.style.fontWeight="bolder";logo.style.fontFamily="verdana, arial, sans-serif";logo.style.marginTop="3px";logo.style.marginLeft="3px";logo.style.top=0;logo.style.left=0;logo.style.zIndex=80;logo.style.textAlign="center";logo.onmouseover=function(){var d=document.getElementById("yoflalink");d.style.color="yellow"};logo.onmouseout=function(){var d=document.getElementById("yoflalink");d.style.color="white"};targetDiv.appendChild(logo)};var paneClick=function(){if(isRotating){stopRotation()}else{startRotation()}};var paneMouseDown=function(){};var paneMouseUp=function(){};var Settings=function(settingsXML){var rotatation={rotatePeriod:settingsXML.getElementsByTagName("rotation")[0].getAttribute("rotatePeriod")};return{rotation:rotatation}};xmlLoader.loadXML(pathToConfig,{obj:this,fnc:this.onXMLLoaded},true);xmlTimeout=setTimeout('RotateTool.checkXMLLoad("'+target+'")',5000);targetDiv.style.position="relative"}};

var RotateTool = new RotateToolManager();


//--------------------------------------------------------------------------
// ROTATE TOOL RELATED "CLASSES" 
//--------------------------------------------------------------------------

/**
 *  Creates a prelaoder in the target div
 *
 */
var Preloader = function( targetDiv ){
	// create percentage
	var percentDiv = document.createElement('div');
	percentDiv.style.fontSize    = '32px';
	percentDiv.style.fontFamily  = 'verdana, arial, sans-serif';
	percentDiv.style.lineHeight  = targetDiv.offsetHeight - 30 + 'px';
	percentDiv.style.textAlign   = 'center';
	percentDiv.style.top    = '0px';
	percentDiv.style.left   = '0px';
	percentDiv.innerHTML = '&nbsp; 0%';
	
	targetDiv.appendChild(percentDiv);
	
	
	this.update = function(percent)	{
		var prefix = '';
		if(percent < 10) prefix = '&nbsp; ';
		percentDiv.innerHTML = prefix + percent + '%';
	}
	
	this.destroy = function(){
		targetDiv.removeChild(percentDiv);		
	}
}// end Preloader



//------------------------------------------------------------------------------
// OTHER LIBRARIES
//------------------------------------------------------------------------------

// addEvent, removeEvent function by John Resig:
// http://ejohn.org/projects/flexible-javascript-events/
function addEvent( obj, type, fn ) {

  if ( obj.attachEvent ) {
    obj['e'+type+fn] = fn;
    obj[type+fn] = function(){obj['e'+type+fn]( window.event );}
    obj.attachEvent( 'on'+type, obj[type+fn] );
  } else
    obj.addEventListener( type, fn, false );
}

function removeEvent( obj, type, fn ) {
  if ( obj.detachEvent ) {
    obj.detachEvent( 'on'+type, obj[type+fn] );
    obj[type+fn] = null;
  } else
    obj.removeEventListener( type, fn, false );
}


/**
 * Very simple and basic Device detecting 
 * 
 */
var DeviceDetector = function(){

	var Device = {};
	Device.UA = navigator.userAgent;
	Device.Type = false;
	Device.Types = ["iPhone", "iPod", "iPad", "android"];

	for (var d = 0; d < Device.Types.length; d++) {
		var t = Device.Types[d];
		Device[t] = !!Device.UA.match(new RegExp(t, "i"));
		Device.Type = Device.Type || Device[t];
	}
	
	return { isTouchDevice : Device.Type ? true : false};
	
}();




/**
 * Class for displaying log messages.
 *
 * @author Matus Laco, matus@yofla.com
 * @version 0.0.1 Early Beta
 * @since  10/July/2010
 */
function YLogger ()
{
	var logdiv;   // reference to log div
	
	/**
	 * Creates the div for displaying log messages
	 */
	var createlogdiv = function()
	{
		// create logger div if it does not exists
		if(!document.getElementById('yoflalogdiv'))
		{
			logdiv = document.createElement('div');     
			logdiv.setAttribute('id','yoflalogdiv');
			logdiv.style.fontFamily = "sans-serif, verdana, arial";
			logdiv.style.fontSize = "10px";
			logdiv.style.width = "300px"; 
			logdiv.style.height = "300px"; 
			logdiv.style.left = "300px"; 
			logdiv.style.top = "300px";
			logdiv.style.overflow = "auto";
			logdiv.style.position = "absolute"; 
			logdiv.style.background = "#FFFF00"; 
			logdiv.style.border = "1px solid #FF0000"; 
			logdiv.style.zIndex = 1000; 
			logdiv.innerHTML = 'Test Div';
			//logdiv.style.display = 'none'; 
			document.body.appendChild(logdiv);
		};
	}
	
	
	/**
	 * Function to display a message in the log window.
	 *
	 * @acces public
	 * @param msg {String} The message to by displayed
	 * @param prefix {String} The prefis which is prepended before 
	 */
	this.log = function( msg )
	{
		createlogdiv();
		var prevtxt = logdiv.innerHTML.substr(0,900);
		logdiv.innerHTML = msg + '<br>' + prevtxt
		
	};
	
	
	/**
	 * Function to display a message in the log window with prefix
	 *
	 * @acces public
	 * @param msg {String} The message to by displayed
	 * @param prefix {String} The prefis which is prepended before 
	 */
	this.logPrefix = function(msg, prefix)
	{
		var tolog = prefix + ': ' + msg;
		this.log( tolog );
	}
	
}// enc class YLogger


// AJAXLib v. 1.0
// author: Jacek Karaszewski, http://www.karaszewski.com/tools/ajaxlib/
// licenced under Creative Commons Attribution 2.5 License
// ---
// wrapped into a namespace, added params for functionToCall
// by Matus Laco, www.yofla.com


/**
 * Class for loading .xml and parsing it to DOM. Start point is the
 * loadXML function. The parsed XML DOM object is passed as a parameter
 * to the functionToCall function
 *
 */
 
function XMLLoader(){
	
	
	// private vars
	var functionToCall;
	var stripWS;
	var nodesToDelete;
	var resultXML;
	var xmlRequestObj;
	
	// PUBLIC FUNCTIONS
	this.loadXML = function(url, callFunc, ignoreWhite)
	{
		
		functionToCall = callFunc;
		stripWS = ignoreWhite;
		xmlRequestObj = window.XMLHttpRequest?new XMLHttpRequest():new ActiveXObject("Microsoft.XMLHTTP")
		xmlRequestObj.onreadystatechange = proccessXML;
		xmlRequestObj.open("GET", url, true);
		xmlRequestObj.send("");		
	};
	
	// PRIVATE FUNCTIONS
	
	/**
	 *
	 */
	var proccessXML = function ()
	{
		if (xmlRequestObj.readyState == 4 && (xmlRequestObj.status == 200 || xmlRequestObj.status == 304)) {
			if(stripWS) {
				stripWhiteSpace(xmlRequestObj.responseXML);
			}
			resultXML = xmlRequestObj.responseXML;
			
			
			if ( typeof(functionToCall) == 'object' )
			{
				functionToCall.fnc.call(functionToCall.obj, resultXML);
			}	
			else if ( typeof(functionToCall) == 'function')
			{
				functionToCall( resultXML );
			}		
			else if ( typeof (functionToCall) == 'string')
			{
				eval(functionToCall);
			}
			else
			{
				alert('undefined type of functionToCall');
			}
		}
		else
		{
		}		
	};

	
	/**
	 *
	 */
	var stripWhiteSpace = function ( node )
	{
		nodesToDelete = Array();
		findWhiteSpace(node, 0);
		for(i=nodesToDelete.length-1;i>=0;i--) {
			nodeRef = nodesToDelete[i];
			nodeRef.parentNode.removeChild(nodeRef)
		}		
	};// end function stripWhiteSpace()
	
	
	/**
	 *
	 */
	var findWhiteSpace = function (node, nodeNo)
	{
		for (i=0; i<node.childNodes.length; i++) {
			if (node.childNodes[i].nodeType == 3 && is_ws(node.childNodes[i])) {
				nodesToDelete[nodesToDelete.length] = node.childNodes[i]
			}
			if (node.childNodes[i].hasChildNodes()) {
				findWhiteSpace(node.childNodes[i], i);
			}
		}
		node = node.parentNode;
		i = nodeNo;		
	};// end function findWhiteSpace
	
	
	/**
	 *
	 */
	var is_ws = function ( nod )
	{
		return !(/[^\t\n\r ]/.test(nod.data));
	};
}



// end of file rotatetool.js
