try { 
	var lastChar = __APPLICATION_PATH__.charAt( __APPLICATION_PATH__.length - 1 );
	if ( lastChar != "/" ) __APPLICATION_PATH__ += "/";
} catch( exception ) {
	var __APPLICATION_PATH__ = "./";
}

/**
 * @since 0.3.2
 */
navigator.isChrome 				= navigator.appVersion.indexOf( "Chrome" ) > -1;
/**
 * @since 0.3.2
 */
navigator.isFirefox 			= navigator.appName.indexOf( "Netscape" ) > -1 && navigator.appVersion.indexOf( "Chrome" ) == -1; 
/**
 * @since 0.3.2
 */
navigator.isInternetExplorer	= navigator.appVersion.indexOf( "MSIE" ) > -1;


Object.prototype.extendPrototype = function ( newMembers, replace ) {

	for( member in newMembers ) {
		if ( this.prototype.member && ! replace ) continue;
		this.prototype[ member ] = newMembers[ member ];
	}

};


Object.extendPrototype( {

	/**
	 * @since 0.2.14
	 * @author Dominique Liard
	 */
	// Usage : ParentType.extendClass( { ... } );
	extendClass : function ( childPrototype ) {
		var newType = function() {
			if ( this.initialize ) this.initialize.apply( this, arguments );
		};
	
		newType.prototype = new this();
		for( member in childPrototype ) newType.prototype[ member ] = childPrototype[ member ];	
		
		return newType;
	},

	/**
	 * @since 0.2.14
	 * @author Dominique Liard
	 */
	// usage: [{...}|object].extendObject({...});
	extendObject : function(childObject) {
		for(var member in this)
			childObject[member] = this[member];
		
		return childObject;
	},


	clone : function (){

	    if ( typeof(this) != 'object' ) return this;
		
	    var temporaryObject = new this.constructor();
	    for( var key in this ) temporaryObject[key] = (typeof(this[key]) == 'object' ? this[key].clone() : this[key]);

	    return temporaryObject;
	}
});

Array.extendPrototype( {
	
	contains : function( value ) {
	    for( var i=0; i<this.length; i++ ) {
	    	if ( value == this[i] ) return true;
	    }
	    return false;
	}
	
} );

/**
 * Create window.XMLHttpRequest on older IEs (5.5 and 6.0).
 * @since 0.4.0
 */		// Successfull Tested on IE 6.0
if ( ! window.XMLHttpRequest ) {
	window.XMLHttpRequest = function () {
		if ( window.ActiveXObject ) {
			try {
				return new ActiveXObject("Msxml2.XMLHTTP");								// Internet Explorer 6.0
			} catch (e) {
				return new ActiveXObject("Microsoft.XMLHTTP");							// older Internet Explorer
			}
		} else {
			throw new Error( "This web browser can't support Ajax components" );	// Unknown browser
		}
	};
}


/************************************************************************************
*** Permet de charger les fichiers de la librairie. Chacun des fichiers ne sera   ***
*** charger qu'une seule et unique fois.                                          ***
************************************************************************************/

var __importedPackages__ = new Array();
__importedPackages__.push( "corelib/services/web/javascript/Core.js" );

if ( typeof( importPackage ) == "undefined"  ) {				// Do not remove this test => is used by JavascriptMockedWebBrowser
	
	function importPackage( packagedTypeName ) {
	
	    if ( __importedPackages__.contains( packagedTypeName ) == false ) {
	        __importedPackages__.push( packagedTypeName );
	
	        try { 													// WEB Access

//	        	var newScriptNode = document.createElement( "script" );
//	        	newScriptNode.type = "text/javascript";
//	        	newScriptNode.src = __APPLICATION_PATH__ + packagedTypeName;
//	        	newScriptNode.innerHTML = " ";
//	        	document.body.insertBefore( document.body.firstChild, newScriptNode );
	        
				var xhrGet = new XMLHttpRequest();
				xhrGet.open( "GET", __APPLICATION_PATH__ + packagedTypeName, false );
				xhrGet.send( null );
				window.document.write( "<script type='text/javascript'><!--\n" + xhrGet.responseText + "\n//--></script>\n" );
				xhrGet.abort();
	        	
	        } catch( exception ) {									// Hard Drive Access
				window.document.write( "<script language='javascript' src='" + __APPLICATION_PATH__ + packagedTypeName + "'></script>\n" );
	        	//alert( exception );
	        }
	    }
	
	}
}

importPackage( "corelib/services/web/javascript/Exception.js" );
importPackage( "corelib/services/web/javascript/Form.js" );
importPackage( "corelib/services/web/javascript/Debug.js" );
importPackage( "corelib/services/web/javascript/L10N.js" );
importPackage( "corelib/services/web/javascript/jwt/JwtUtility.js" );			// TEMPORARY - Le temps de supprimer les anciens menus


/*************************************************************************************
*** Ajoute, sans supprimer les anciens, un gestionnaire d'événement à un tag HTML. ***
*************************************************************************************/

function addEventHandler( node, eventName, handler ) {

	if ( node == null ) throw new Exception( "addEventHandler: Bad node" );
	if ( typeof( eventName ) != "string" ) throw new Exception( "addEventHandler: Bad eventName" ); 
	if ( typeof( handler ) != "function" ) throw new Exception( "addEventHandler: Bad event handler" ); 

	var handlerArray = node[ eventName + "_handlers" ];
	if ( handlerArray == null ) {
		handlerArray = node[ eventName + "_handlers" ] = new Array(); 
		var __temp = null;
		eval( 
			"__temp = function( event ) {" +
			"    var result = true;" +
			"    var handlerArray = this['" + eventName + "_handlers'];" +
			"    event = ( event ? event : (window.event ? window.event : null ) );" +
			"    try { if ( event.target ) event.srcElement = event.target; } catch( exception ) {} " +		// DO NOT REMOVE TRY-CATCH for not native events
			"    for( var i=0; i<handlerArray.length; i++ ) {" +
			"        this.__temp__handler__ = handlerArray[i];" +   								// DO NOT REMOVE : CLOSURE MUST BE A METHOD !
			"        var returnCode = this.__temp__handler__( event );" +
			"        result = result && returnCode;" +												// For form validations 
			"    }" +
			"    return result;" +
			"}"
		);
		node[ eventName ] = __temp;																	// ATTENTION : ne pas changer (IE à besoin __temp = pour l'eval) 
	}
	
	handlerArray[ handlerArray.length ] = handler;
}


function removeEventHandler( node, eventName, handler ) {
	throw new Exception( "Not implemented" );
}

/**
 * Update CSS classes used for the body element, by adding a class dependant of the web browser used.
 * @since 0.3.6
 * @author Dominique Liard
 */
addEventHandler( window, "onload", function( event ) {
	if ( document.body.className != null && document.body.className != "" ) document.body.className += " "; 
	if ( navigator.isInternetExplorer ) document.body.className += "CSS_IE";
	else if ( navigator.isFirefox ) document.body.className += "CSS_FF";
	else if ( navigator.isChrome ) document.body.className += "CSS_CH";
});

/************************************************************************************
*** Permet de créer une méthode de simulation de click sur un tag, pour le        ***
*** navigateur firefox (compatibilité avec InternetExplorer)                      ***
************************************************************************************/

function attachClickMethod( node ) {
	if ( node.click ) return;
	node.click = function() {
		var clickEvent = document.createEvent( "MouseEvents" );
		clickEvent.initMouseEvent( 'click', true, true, document.defaultView, 1, 0, 0, 0, 0, false, false, false, false, 0, null );
		this.dispatchEvent( clickEvent );
	};
}

/************************************************************************************
*** Déclenche un event oncontextmenu sur Internet Explorer lors d'un click avec   ***
*** le bouton droit de la souris sur un quelconque tag <area ...>.                ***
************************************************************************************/

function updateAllAreasForOnContextMenuEvent() {
	if ( window.document.all ) {
		var areaNodes = window.document.getElementsByTagName( "area" );
		for( var i=0; i<areaNodes.length; i++ ) {
			areaNodes[i].onmousedown = function() {
				if ( window.event.button != 2 ) return;
				this.fireEvent( 'oncontextmenu' );
				window.event.cancelBubble = true;
			};

			areaNodes[i].imageNode = null;
			var mapName = "#" + areaNodes[i].parentNode.name;
			var imageNodes = document.getElementsByTagName( "img" );
			for (var imgIndex=0; imgIndex<imageNodes.length; imgIndex++ )
				if (imageNodes[imgIndex].usemap == mapName) areaNodes[i].imageNode = imageNodes[imgIndex];					
		}
	}
	return true;
}

addEventHandler( window, "onload", updateAllAreasForOnContextMenuEvent );

/************************************************************************************
*** Permet une gestion simplifiée des cookies.                                    ***
************************************************************************************/

function CookieManager() {
    this.cookies = new Array();

    var tempCookies = document.cookie.split(";");
	for(var i=0; i<tempCookies.length; i++) {
        var currentCookie = tempCookies[i].split("=");
        this.cookies[i] = currentCookie;
    }
    
    this.getValue = function CookiesManager_getValue(name) {
        for(var i=0;i<this.cookies.length; i++) {
            if (this.cookies[i][0].indexOf(name) > -1) {
				return this.cookies[i][1];
			}
        }
        return null; 
    };
    
    this.setValue = function CookieManager_setValue(key, value, expirationDate) {
        if (arguments.length != 3) {
        	expirationDate = new Date();
         	expirationDate.setTime( expirationDate.getTime()*1 + (365*24*60*60*1000) );
        }
	    document.cookie = key + "=" + value + ";expires=" + expirationDate.toGMTString();
    };
}


/************************************************************************************
*** Extension du type String                                                      ***
************************************************************************************/

String.extendPrototype( {

	endsWith : function( endString ) {
		if ( endString == null ) throw new NullPointerException();
		if ( typeof endString != "string" ) throw new BadTypeException( "parameter must be a string" );
		if ( endString.length > this.length ) throw new Exception( "parameter length is greater than this length" );
		return this.right( endString.length ) == endString;
	},
	
	
	left : function ( length ) {
		var strLength = this.length;
		if ( length > strLength ) throw new Exception( "Bad length for left function" );
		return this.substring( 0, length );    
	},

	
	right : function ( length ) {
		var strLength = this.length;
		if ( length > strLength ) throw new Exception( "Bad length for left function" );
		return this.substring( strLength - length );    
	},

	
	startsWith : function( startString ) {
		if ( startString == null ) throw new NullPointerException();
		if ( typeof startString != "string" ) throw new BadTypeException( "parameter must be a string" );
		if ( startString.length > this.length ) throw new Exception( "parameter length is greater than this length" );
		return this.substring( 0, startString.lenght ) == startString;
	},
	
	
	trim : function() {
		if ( this == "" ) return this;
		
		var begin = 0;
		var theChar = this.charAt( begin );
		while( theChar == ' ' || theChar == '\t' || theChar == '\r' || theChar == '\n' ) {
			begin ++;
			if ( begin == this.length ) return "";
			theChar = this.charAt( begin );
		}
		
		var end = this.length-1;
		theChar = this.charAt( end );
		while( theChar == ' ' || theChar == '\t' || theChar == '\r' || theChar == '\n' ) {
			end --;
			theChar = this.charAt( end );
		}
		
		return this.substring( begin, end+1 );
	},
	
	format: function() {
		var isprototype = (this == String.prototype);
		var index = (!isprototype ? 0 : 1);
		var value = (!isprototype ? this : arguments[0]);
		
		for(var i = index; i < arguments.length; i++)
			value = value.replace("\{" + (i - index) + "}", arguments[i].toString());
		
		return value;
	}
} );


/************************************************************************************
*** Extension du type Date                                                        ***
************************************************************************************/

Date.extendPrototype( {

	/**
	 * @since 0.2.15
	 * @author Sébastien Briquet
	 */
	addDays: function(/* int */ n)
	{
		this.setTime( this.getTime() + (n * 86400000));
		
		return this.getTime();
	},

	getWeek : function() {
		var firstDay = new Date( this.getFullYear(), 0, 1 );
		return Math.ceil( ( ( (this - firstDay ) / 86400000) + firstDay.getDay() ) / 7 );
	},
	
	/**
	 * Converts a date to a string using the specified formatting.
	 * Already native in Firefox but not in Internet Explorer browser
	 * @since 0.3.0
	 * @author Sébastien Briquet
	 */
	toLocaleFormat : function(format) {
		switch(format) {
			case "%a":
				return this.toString().left(3); // not the best way
			default:
				throw new Exception("the specified formatting is not currently supported");
		}
	},
	
	toURIString: function() {
		// ie: 19970714T170000Z
		var index = 0;

		if((new Date(1970, 12, 1)).getMonth() == 0) // dec.
			index++;

		return "" + this.getUTCFullYear() + (this.getUTCMonth() + index).toFixedString(2) + this.getUTCDate().toFixedString(2) + "T" + this.getUTCHours().toFixedString(2) + this.getUTCMinutes().toFixedString(2) + this.getUTCSeconds().toFixedString(2) + "Z";
	 }
} );

/************************************************************************************
*** Extension du type Number                                                      ***
************************************************************************************/

Number.extendPrototype( {
	toFixedString: function(digits)
	{
		var value = this.toString();
		
		if(!isNaN(digits) && digits > value.length)
			for(var i = value.length; i < digits; i++)
				value = "0" + value;

		return value;
		
	}
});


/************************************************************************************
*** Définition de la classe Locale                                                ***
************************************************************************************/

var Locale = Object.extendClass( {

	initialize : function( language, country ) {
		this._language = language;
		this._country = country;
	},
	
	getLanguage : function () { return this._language; },
	getCountry : function () { return this._country; }	
	
});


/**
 * Creates and appends a new element as the last child of this element.
 * 
 * @param elementName		The tag name of the new element to produce.
 * @param attributes		An associative array that defines all attributes to affect on the new element.
 * @param styleDefinitions	An associative array that defines all definitions to affect on the style object of the new element.
 *  
 * @since 0.4.0
 */
Element.prototype.createAndAppendChild = function( elementName, attributes, styleDefinitions ) {
	var newElement = document.createElement( elementName );
	if ( attributes ) {
		for( var key in attributes ) {
			 newElement[ key ] = attributes[ key ];
		}
	}
	if ( styleDefinitions ) {
		for( var key in styleDefinitions ) {
			 newElement.style[ key ] = styleDefinitions[ key ];
		}
	}
	this.appendChild( newElement );
	return newElement;
};


/**
 * @since 0.4.0
 */
Element.prototype.addCssClass = function( cssClassName ) {
	var classArray = this.className.split( " " );
	if ( classArray.contains( cssClassName ) == false ) {
		this.className += " " + cssClassName;
	}
};

/**
 * @since 0.4.0
 */
Element.prototype.removeCssClass = function( cssClassName ) {
	var rules = this.className.split(" ");
	var names = new Array();

	for( var i = 0; i < rules.length; i++ ) {
		if( rules[i] != cssClassName ) {
			names.push(rules[i]);
		}
	}

	this.className = names.join(" ");
};

