/*
 * $Id: LEA_Framework.js $
 *
 * Copyright (c) 2009 DéGRIGO. All Rights Reserved.
 *
 * This software is the confidential and proprietary information of DéGRIGO
 * ("Confidential Information"). You shall not disclose such Confidential
 * Information and shall use it only in accordance with the terms of the license
 * agreement you entered into with DéGRIGO.
 *
 * DéGRIGO MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
 * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-
 * INFRINGEMENT. DéGRIGO SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY
 * LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
 * DERIVATIVES.
 */

/**
 * This object can be used to execute an action and to call the sended methods to be executed.
 */
function AjaxObject() {
    
    var ready = true;
    
    var request = null;
    var xmlProcessMethod = null;
    var textProcessMethod = null;
    
    this.executeAction = function(url, textMethod, xmlMethod) {

        ready = false;

        textProcessMethod = textMethod;
        xmlProcessMethod = xmlMethod;
        
        if (window.XMLHttpRequest) { // Non-IE browsers

            request = new XMLHttpRequest();
            request.onreadystatechange = processStateChange;
            
            try {
                request.open("GET", url, true);
                request.setRequestHeader("Content-Type", "text/plain;charset=ISO-8859-1");
            } catch (e) {
                alert(e);
            }

            request.send(null);
        } else if (window.ActiveXObject) { // IE

            request = new ActiveXObject("Microsoft.XMLHTTP");
        
            if (request) {
                request.onreadystatechange = processStateChange;
                request.open("GET", url, true);
                request.setRequestHeader("Content-Type", "text/plain;charset=ISO-8859-1");
                request.send();
            }
        }
    };

     var processStateChange = function() {

        if (request.readyState == 4) { // Complete

            if (request.status == 200) { // OK response
                
                if(textProcessMethod != null) {
                    textProcessMethod(request.responseText);
                }
                
                if(xmlProcessMethod != null) {
                    xmlProcessMethod(request.responseXML);
                }
                
                ready = true;
                
            } else {
                
                alert("The action could not be executed. \nStatus code : " + request.statusText);
            }
        }
    };
}
var ajaxObj = new AjaxObject();

/*
 * Constants.
 */
function _Constants() {
    // -- general --
    this.BACK = "back";
    this.BLOCK = "block";
    this.BUTTON = "button";
    this.DISABLED = "disabled";
    this.DIV = "div";
    this.FALSE = "false";
    this.FILE = "file";
    this.HIDDEN = "hidden";
    this.HREF = "href";
    this.INLINE = "inline";
    this.INPUT = "input";
    this.NONE = "none";
    this.ONCLICK = "onclick";
    this.SELECT = "select";
    this.SPAN = "span";
    this.SRC = "src";
    this.TEXT = "text";
    this.TRUE = "true";
    this.VISIBLE = "visible";

    // -- characters --
    this.AMPERSAND  ="&";
    this.EQUAL = "=";
    this.QUESTION_MARK = "?";
}
var jsConst = new _Constants();

/**
 * Utility methods.
 */
function _Util() {
	var REJECTED_BROWSER_PATTERN = "MSIE (?:8.0|7.0|6.0|5.5|5.0)";
    var SUPPORTED_BROWSERS = "Mozilla Firefox, Safari";
	
    this.checkBrowserSupport = function() {

        var brwPattern = new RegExp(REJECTED_BROWSER_PATTERN);
        var rejectedBrowser = brwPattern.exec( navigator.userAgent );
        
        if( rejectedBrowser != null) {
//            alert("This browser: " + rejectedBrowser + " is not supported for this function.\n" +
//                  "Supported browsers are: " + SUPPORTED_BROWSERS);
                  
            return false;
        }

        return true;
    };

	/**
	 * Creates a new HTML element 
	 */
    this.createHTMLElement = function(tagName, type, name, id, value, size, className) {
    	if (tagName == null || tagName == "") {
    		return null;
        }
 
        var newElement = document.createElement(tagName);

    	if (type != null && type != "") {
    	  	newElement.type = type;
        }

        if (name != null && name != "") {
    	  	newElement.name = name;
        }

        if (id != null && id != "") {
    	  	newElement.id = id;
        }

        if (value != null && value != "") {
    	  	newElement.value = value;
        }

        if (size != null && size != "") {
    	  	newElement.size = size;
        }

        if (className != null && className != "") {
    		newElement.className = className;
        }

        return newElement;
    };
	
    /** Get the left position of the element.
     *
     * @param element   the element to get the left position
     *
     * @return          the left position as Integer
     */    
    this.getElementLeft = function(element) {

        var tmp = element.offsetLeft;
        element = element.offsetParent;
        while(element) {
            tmp += element.offsetLeft;
            element = element.offsetParent;
        }
        return tmp;
    };
    
    /** Get the top position of the element.
     *
     * @param element   the element to get the top position
     *
     * @return          the top position as Integer
     */    
    this.getElementTop = function(element) {
    
        var tmp = element.offsetTop + element.offsetHeight;
        element = element.offsetParent;
        while(element) {
            tmp += element.offsetTop;
            element = element.offsetParent;
        }
        return tmp;
    };
    
    /**
     * Inserts a new row at the end of the table if the index is not specified
     * 
     * @param table		the table object into where the row will be inserted 
     * @param index		the index for the insert. If null the row is inserted at the end.
     * 
     * @return		the inserted row object
     */
    this.insertRowToTable = function(table, index) {
    	var insertIndex = -1;

    	if(index != null) {
    		insertIndex = index;
        }

        return table.insertRow(insertIndex);
    };
    
    /**
     * Inserts a new cell at the end of the row if the index is not specified
     * 
     * @param row		the row object into where the cell will be inserted 
     * @param index		the index for the insert. If null the cell is inserted at the end.
     * 
     * @return		the inserted cell object
     */
    this.insertCellToRow = function(row, index) {
    	var insertIndex = -1;

    	if(index != null) {
    		insertIndex = index;
        }

        return row.insertCell(insertIndex);
    };

    /**
     * Sets an HTML element's focus.
     * 
     * @param id	the id of the HTML elemnt to set focus
     */
    this.setFocus = function(id) {
        document.getElementById(id).focus();
    };
    
    /**
     * Sets the value of the html element with the sent id to value of the checkbox (checked=1 or not=0)
     * 
	 * @param oChkBox	the checkbox element
	 * @param id		the id of the HTMLElement
	 */
	this.setChecked = function(oChkBox, id) {
		document.getElementById(id).value = (oChkBox.checked ? 1 : 0);
	};

    /** Add an event to the eventParent, testing if to use either W3C's addEventListener or Microsoft's model.
    *
    * @param eventParent   the element to add the event to
    * @param event         the event to attach
    * @param               the event listener method
    * @param               true to use the capturing, false to use the bubbling <br />
    *                       - Capturing; parent element executes the event first,<br />
    *                       - Bubbling;  the inner element executes the event first. 
    */ 
   this._addEventListener = function(eventParent, event, eventListener, capturing) {
   
       if ( eventParent.addEventListener ) { // W3C

           eventParent.addEventListener(event, eventListener, capturing);
       } else if (eventParent.attachEvent) { // MS
       
           eventParent.attachEvent('on'+event, eventListener);
       } else { // Other
           
           eval("eventParent.on" +event + "=" +eventListener + ";");
       }
   };
   
   /** Remove an event from the eventParent, testing if to use either W3C's removeEventListener or Microsoft's model.
    *
    * @param eventParent   the element to add the event to
    * @param event         the event to attach
    * @param               the event listener method
    * @param               true to use the capturing, false to use the bubbling <br />
    *                       - Capturing; parent element executes the event first,<br />
    *                       - Bubbling;  the inner element executes the event first. 
    */ 
   this._removeEventListener = function(eventParent, event, eventListener, capturing) {
   
       if ( eventParent.addEventListener ) {
           
           eventParent.removeEventListener(event, eventListener, capturing);
       } else if (eventParent.attachEvent) {
       
           eventParent.detachEvent('on'+event, eventListener);
       } else { // Other
           
           eval("eventParent.on" +event + "= '';");
       }
   };

	 /* function getScrollXY() {
		  var scrOfX = 0, scrOfY = 0;
		  if( typeof( window.pageYOffset ) == 'number' ) {
		    //Netscape compliant
		    scrOfY = window.pageYOffset;
		    scrOfX = window.pageXOffset;
		  } else if( document.body && ( document.body.scrollLeft || document.body.scrollTop ) ) {
		    //DOM compliant
		    scrOfY = document.body.scrollTop;
		    scrOfX = document.body.scrollLeft;
		  } else if( document.documentElement && ( document.documentElement.scrollLeft || document.documentElement.scrollTop ) ) {
		    //IE6 standards compliant mode
		    scrOfY = document.documentElement.scrollTop;
		    scrOfX = document.documentElement.scrollLeft;
		  }
		  return [ scrOfX, scrOfY ];
		}*/
//	  var myWidth = 0, myHeight = 0;
//	  if( typeof( window.innerWidth ) == 'number' ) {
//	    //Non-IE
//	    myWidth = window.innerWidth;
//	    myHeight = window.innerHeight;
//	  } else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
//	    // IE 6+ in 'standards compliant mode'
//	    myWidth = document.documentElement.clientWidth;
//	    myHeight = document.documentElement.clientHeight;
//	  } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
//	    //IE 4 compatible
//	    myWidth = document.body.clientWidth;
//	    myHeight = document.body.clientHeight;
//	  }
//	  if(myHeight < 817){
//		  myHeight = 817 + 90;
//	  }
//	  // We have a body padding-bottom for 90 px
//	  document.body.style.height = (myHeight - 90) + "px";

}
var util = new _Util();

/**
 * Securer_class that does securing tasks
 */
function Screr() {
    var oForm = null;
	
	this.submitForm = function(id) {
		oForm = document.getElementById(id);
		oForm.appendChild(util.createHTMLElement(jsConst.INPUT, jsConst.HIDDEN, "_effect", "_effect", "1we32RTH54Bde", null, "text"));

		ajaxObj.executeAction('/ajaxController.php?do=matrix&_cause='+document.getElementById('_cause').value, setID);
	};
	
    var setID = function(no) {

    	document.getElementById('_effect').value = no;
    	oForm.submit();
    };
}
var scrObj = new Screr();

/**
 * Offers methods to slide and fade elements. 
 * Calculates increasing and then decreasing numbers to slide smoother  
 *
 * <ul>
 * 	<li>Sliding vertical by changing top</li>
 *  <li>Sliding horizontal by changing left</li>
 *  <li>Changing height and width</li>
 *  <li>Fading opacity</li>
 * </ul>
 */
function Animator() {
    
	var oElement = null;
    var methodAfterFadeIn = null;
    var methodAfterFadeOut = null;
    var methodAfterTopMvt = null;
    var methodAfterLeftMvt = null;
    var methodAfterHeightMvt = null;
    var methodAfterWidthMvt = null;
	
    var FADING_INTERVAL    = 30;
    var OPACITY_INTERVAL   = 5;
    var OPACITY_TO   	   = 0;
    var ELEMENT_DISPLAY    = jsConst.BLOCK;
	var ELEMENT_VISIBILITY = jsConst.VISIBLE;
    var elementOpacity = 100;

    var SLIDING_INTERVAL  = 15;

    // Top position
    var elementTop = 0;
	var etMvtValues = new Array();
	var	etIndex = 0;
	var etTurn = 0;
	var etRepetitios = 4;

	// Left Position
	var elementLeft = 0;
	var elMvtValues = new Array();
	var	elIndex = 0;
	var elTurn = 0;
	var elRepetitios = 4;
	
	// Height
	var elementHeight = 0;
	var ehMvtValues = new Array();
	var	ehIndex = 0;
	var ehTurn = 0;
	var ehRepetitios = 4;
	
	// Width
	var elementWidth = 0;
	var ewMvtValues = new Array();
	var	ewIndex = 0;
	var ewTurn = 0;
	var ewRepetitios = 4;
	
	var topMvtTimeoutId = null;
	var leftMvtTimeoutId = null;
	var heightMvtTimeoutId = null;
	var widthMvtTimeoutId = null;
	var fadeTimeoutId = null;
	
	this.initialize = function (elem, eTop, eHeight, eLeft, eWidth, eOpacity) {
		elementTop = eTop;
		elementHeight = eHeight;
		elementLeft = eLeft;
		elementWidth = eWidth;
		elementOpacity = eOpacity;
		
		oElement = elem;
		
		if(eTop != null)
			oElement.style.top= elementTop + "px";
		if(eHeight != null)
			oElement.style.height= elementHeight + "px";		
		if(eLeft != null)
			oElement.style.left= elementLeft + "px";
		if(eWidth != null)
			oElement.style.width= elementWidth + "px";
		if(eOpacity != null)
			setElementOpacity(oElement, elementOpacity);
	};
	
	this.animateTop = function(topTo, rep, method){

		if(rep != null)
			etRepetitios = rep;
		if(topMvtTimeoutId != null)
			clearTimeout(topMvtTimeoutId);
		methodAfterTopMvt = method;
		
		etMvtValues = calculateAnimation(topTo - elementTop, etRepetitios);
		etIndex = 0;
		etTurn = 0;
		if(etMvtValues != null)
			moveTop();
	};
	var moveTop = function () {
		if(etTurn++ >= etMvtValues[etIndex][1]) {
			etIndex++;
			// Hear sets turn to 1 not 0, because first time it has to be 0 to get all movement of first cycle
			etTurn = 1;
		}
		if(etIndex < etMvtValues.length) {
			elementTop += etMvtValues[etIndex][0];
			oElement.style.top=(elementTop) + "px";
			topMvtTimeoutId = self.setTimeout(moveTop, SLIDING_INTERVAL);
		} else if(methodAfterTopMvt != null) {
			methodAfterTopMvt();
		}
	};
	this.animateLeft = function(leftTo, rep, method){

		if(rep != null)
			elRepetitios = rep;
		if(leftMvtTimeoutId != null)
			clearTimeout(leftMvtTimeoutId);
		methodAfterLeftMvt = method;
		
		elMvtValues = calculateAnimation(leftTo - elementLeft, elRepetitios);
		elIndex = 0;
		elTurn = 0;
		if(elMvtValues != null)
			moveLeft();
	};
	var moveLeft = function () {
		if(elTurn++ >= elMvtValues[elIndex][1]) {
			elIndex++;
			// Hear sets turn to 1 not 0, because first time it has to be 0 to get all mouvement of first cycle
			elTurn = 1;
		}
		if(elIndex < elMvtValues.length) {
			elementLeft += elMvtValues[elIndex][0];
			oElement.style.left=(elementLeft) + "px";
			leftMvtTimeoutId = self.setTimeout(moveLeft, SLIDING_INTERVAL);
		} else if(methodAfterLeftMvt != null) {
			methodAfterLeftMvt();
		}
	};

	this.animateHeight = function(heightTo, rep, method){

		if(rep != null)
			ehRepetitios = rep;
		if(heightMvtTimeoutId != null)
			clearTimeout(heightMvtTimeoutId);
		methodAfterHeightMvt = method;
		
		ehMvtValues = calculateAnimation(heightTo - elementHeight, ehRepetitios);
		ehIndex = 0;
		ehTurn = 0;
		if(ehMvtValues != null)
			moveHeight();
	};
	var moveHeight = function () {
		if(ehTurn++ >= ehMvtValues[ehIndex][1]) {
			ehIndex++;
			// Hear sets turn to 1 not 0, because first time it has to be 0 to get all mouvement of first cycle
			ehTurn = 1;
		}
		if(ehIndex < ehMvtValues.length) {
			elementHeight += ehMvtValues[ehIndex][0];
			oElement.style.height=(elementHeight) + "px";
			heightMvtTimeoutId = self.setTimeout(moveHeight, SLIDING_INTERVAL);
		} else if(methodAfterHeightMvt != null) {
			methodAfterHeightMvt();
		}
	};
	this.animateWidth = function(widthTo, rep, method){

		if(rep != null)
			ewRepetitios = rep;
		if(widthMvtTimeoutId != null)
			clearTimeout(widthMvtTimeoutId);
		methodAfterWidthMvt = method;
		
		ewMvtValues = calculateAnimation(widthTo - elementWidth, ewRepetitios);
		ewIndex = 0;
		ewTurn = 0;
		if(ewMvtValues != null)
			moveWidth();
	};
	var moveWidth = function () {
		if(ewTurn++ >= ewMvtValues[ewIndex][1]) {
			ewIndex++;
			// Hear sets turn to 1 not 0, because first time it has to be 0 to get all mouvement of first cycle
			ewTurn = 1;
		}
		if(ewIndex < ewMvtValues.length) {
			elementWidth += ewMvtValues[ewIndex][0];
			oElement.style.width=(elementWidth) + "px";
			widthMvtTimeoutId = self.setTimeout(moveWidth, SLIDING_INTERVAL);
		} else if(methodAfterWidthMvt != null) {
			methodAfterWidthMvt();
		}
	};
	
	/**
	 * This method caluculates an increasing and then decreasing number serie,
	 * that will give a smoother sliding for an element. 
	 * calculateAnimation will look if the size is negative or positive and set the incBy minus or plus
	 * so that one same method can move up or down a div. No need then to tka absolute value.
	 * And the "to" value must be first, meaning headerTo - header will give the change value plus 
	 * the signe(the direction for the mouvement).
	 * 
	 * @param size			the size for mouvement
	 * @param repetitions	the number of repetitions of an increase number
	 * 
	 * @return  null if no mouvement (size is 0),
	 * 			else an array of associated increasing number and number of times it sould be applied
	 */
	var calculateAnimation = function(size, repetitions) {

		if(size != 0) {
			var signe = (size > 0 ? +1 : -1);
			size = Math.abs(size);
			
			var incBy = 1;
			var temp = 0, temp2 = 0;
			// Find the last possible increasing number 
			for(; ; incBy++){
				temp += incBy * repetitions; 
				if(temp >= size / 2) {
					break;
				}
				temp2 += incBy * repetitions;
			}
	
			var lastInc = Math.floor( (size - temp2 * 2) / incBy) - 1;
			var firstInc = ((size - temp2 * 2 ) % incBy ) + incBy;

			var incs = new Array();
			var index = 1;
			for( ; index < incBy; index++) {
				incs[index - 1] = new Array(signe * index, repetitions);
			}
			if(lastInc != 0) {
				incs[index - 1] = new Array(signe * index, lastInc);
				index = incBy + 1;
			}
			for( var y = incBy - 1; y > 1; y--, index++) {
				incs[index - 1] = new Array(signe * y, repetitions);
			}
			incs[index - 1] = new Array(signe * 1, repetitions + firstInc);
			
			/*var t = 0;
			for (var ind = 0; ind < incs.length; ind++) {
				t += incs[ind][0] * incs[ind][1];
				alert(incs[ind][0] + " - " + incs[ind][1] + " - " + t);
			}*/
			return incs;
		}
		return null;
	};
	
	this.fadeIn = function(opacTo, method) {

    	if(fadeTimeoutId != null)
			clearTimeout(fadeTimeoutId);
    	
    	oElement.style.display = jsConst.BLOCK;
    	oElement.style.visibility = jsConst.VISIBLE;
    	
    	OPACITY_TO = 100;
    	if (opacTo != null) {
    		OPACITY_TO = opacTo;
    	}
    	
    	methodAfterFadeIn = method;
    	
    	fadeInElement();
	};
	
	this.fadeOut = function(opacTo, hide, method) {

    	if(fadeTimeoutId != null)
			clearTimeout(fadeTimeoutId);
    	
		methodAfterFadeOut = method;

    	OPACITY_TO = 0;
    	if (opacTo != null) {
    		OPACITY_TO = opacTo;
    	}

    	if (hide != null && hide == true) {
	        ELEMENT_DISPLAY    = jsConst.NONE;
	    	ELEMENT_VISIBILITY = jsConst.HIDDEN;
    	}
    	
		fadeOutElement();
	};
	
	var fadeInElement = function() {

        if(elementOpacity < OPACITY_TO) {
        	elementOpacity = elementOpacity + OPACITY_INTERVAL;

        	setElementOpacity(oElement, elementOpacity);

        	fadeTimeoutId = self.setTimeout(fadeInElement, FADING_INTERVAL);
            
            return true;
        } else if(methodAfterFadeIn != null){
        	methodAfterFadeIn();
        }
        return false;
	};
    var fadeOutElement = function() {

        if(elementOpacity > OPACITY_TO) {
        	elementOpacity = elementOpacity - OPACITY_INTERVAL;

        	setElementOpacity(oElement, elementOpacity);

        	fadeTimeoutId = self.setTimeout(fadeOutElement, FADING_INTERVAL);
            
            return true;
        }  else {
        	 if(methodAfterFadeOut != null){
        		 methodAfterFadeOut();
             }
        	oElement.style.display = ELEMENT_DISPLAY;
        	oElement.style.visibility = ELEMENT_VISIBILITY;
        }
        return false;
    };
    
	var setElementOpacity = function(divToFade, elOpacity) {

        if (navigator.appName.indexOf("Microsoft")!= -1 &&parseInt(navigator.appVersion)>=4) {

        	divToFade.style.filter = 'alpha(opacity=' + elOpacity + ')';
        } else {//navigator.appName.indexOf("Netscape")!=-1 &&parseInt(navigator.appVersion)>=5)

            divToFade.style.opacity = elOpacity / 100;
        }

        return true;
	};
}
