	
	Application.util = {
		
		init: function()
		{
			// Browser information
			this.browserInformation.init();
			
			// XML serialization
			this.serialize.init();
			
			// CSS manipulation
			this.style.init();
			
			// Text selection
			this.selectText.init();
			
			// XSLT
			this.xslt.init();
			
			// URL information
			this.urlInformation.init();
			
			// Default Objects Enhancements
			this.objectsEnhancements.init();
		},
		
		/*
			-----------
			XML to Text
			-----------
		*/
		
		serialize:
		{
			string: null,
			
			init: function()
			{
				if(Application.util.browserInformation.browser == "Explorer")
				{
					Application.util.serialize.string = Application.util.serialize.IE.string;
				}
				else
				{
					Application.util.serialize.string = Application.util.serialize.FF.string;
				}
			},
			
			IE:
			{
				string: function(xmlNode)
				{
					return xmlNode.xml;
				}
			},
			
			FF:
			{
				string: function(xmlNode)
				{
					return ( new XMLSerializer() ).serializeToString(xmlNode);
				}
			}
		},
		
		/*
			-----------
			Select Text
			-----------
		*/
		
		selectText:
		{
			range: null,
			
			init: function()
			{
				if(Application.util.browserInformation.browser == "Explorer")
				{
					Application.util.selectText.range = Application.util.selectText.IE.range;
				}
				else
				{
					Application.util.selectText.range = Application.util.selectText.FF.range;
				}
			},
			
			IE:
			{
				range: function(element, start, end)
				{
					var sel = element.createTextRange();
					sel.collapse(true);
					sel.moveStart("character", start);
					sel.moveEnd("character", end);
					sel.select();
				}
			},
			
			FF:
			{
				range: function(element, start, end)
				{
					element.selectionStart = start;
					element.selectionEnd = end;
				}
			}
		},
		
		/*
			---------
			Style Lib
			---------
		*/
		
		style:
		{
			getCurrent: null,
			getPos: null,
			getRule: null,
			getMatchingRules: null,
			
			init: function()
			{
				if(Application.util.browserInformation.browser == "Explorer")
				{
					Application.util.style.getCurrent = Application.util.style.IE.getCurrent;
					Application.util.style.getPos = Application.util.style.IE.getPos;
					Application.util.style.getRule = Application.util.style.IE.getRule;
					Application.util.style.getMatchingRules = Application.util.style.IE.getMatchingRules;
				}
				else
				{
					Application.util.style.getCurrent = Application.util.style.FF.getCurrent;
					Application.util.style.getPos = Application.util.style.FF.getPos;
					Application.util.style.getRule = Application.util.style.FF.getRule;
					Application.util.style.getMatchingRules = Application.util.style.FF.getMatchingRules;
				}
			},
			
			IE:
			{
				getCurrent: function(block, property)
				{
					return block.currentStyle[property];
				},
				
				getPos: function( obj )
				{
					var curleft = curtop = 0;
					
					if (!obj.offsetParent)
					{
						return false;
					}
					
					do
					{
						curleft += obj.offsetLeft;
						curtop += obj.offsetTop;
					} while (obj = obj.offsetParent);
					
					return { left: curleft, top: curtop };
				},
				
				getMatchingRules: function( ruleName )
				{
					var rules = document.styleSheets[0].rules;
					var matchingRules = [];
					
					ruleName = ruleName.toLowerCase();
					
					for (i=rules.length-1;i>=0;i--)
					{
						if(rules.item(i).selectorText.toLowerCase().indexOf( ruleName ) == -1)
						{
							continue;
						}
						
						matchingRules[ matchingRules.length ] = rules[i];
					}
					
					return matchingRules;
				},
				
				getRule: function( ruleName )
				{
					var rules = document.styleSheets[0].rules;
					ruleName = ruleName.toLowerCase();
					
					for (i=rules.length-1;i>=0;i--)
					{
						if(rules[i].selectorText.toLowerCase() == ruleName)
						{
							continue;
						}
						
						return rules[i];
					}
					
					return false;
				}
			},
			
			FF:
			{
				getCurrent: function(block, property)
				{
					return document.defaultView.getComputedStyle(block, null).getPropertyValue(property);
				},
				
				getPos: function( obj )
				{
					var curleft = curtop = 0;
					
					if (!obj.offsetParent)
					{
						return false;
					}
					
					do
					{
						curleft += obj.offsetLeft;
						curtop += obj.offsetTop;
					} while (obj = obj.offsetParent);
					
					return { left: curleft, top: curtop };
				},
				
				getMatchingRules: function( ruleName )
				{
					var rules = document.styleSheets[0].cssRules;
					var matchingRules = [];
					
					for (i=rules.length-1;i>=0;i--)
					{
						if(rules.item(i).selectorText.indexOf( ruleName ) == -1)
						{
							continue;
						}
						
						matchingRules[ matchingRules.length ] = rules[i];
					}
					
					return matchingRules;
				},
				
				getRule: function( ruleName )
				{
					var rules = document.styleSheets[0].cssRules;
					
					for (i=rules.length-1;i>=0;i--)
					{
						if(rules[i].selectorText == ruleName)
						{
							continue;
						}
						
						return rules[i];
					}
					
					return false;
				}
			}
		},
		
		/*
			------------------
			BrowserInformation
			------------------
		*/
		
		browserInformation:
		{
			init: function ()
			{
				this.browser = this.searchString(this.dataBrowser) || "An unknown browser";
				this.version = this.searchVersion(navigator.userAgent)
					|| this.searchVersion(navigator.appVersion)
					|| "an unknown version";
				this.OS = this.searchString(this.dataOS) || "an unknown OS";
			},
			
			searchString: function (data)
			{
				for (var i=0;i<data.length;i++)	{
					var dataString = data[i].string;
					var dataProp = data[i].prop;
					this.versionSearchString = data[i].versionSearch || data[i].identity;
					if (dataString) {
						if (dataString.indexOf(data[i].subString) != -1)
							return data[i].identity;
					}
					else if (dataProp)
						return data[i].identity;
				}
			},
			
			searchVersion: function (dataString)
			{
				var index = dataString.indexOf(this.versionSearchString);
				if (index == -1) return;
				return parseFloat(dataString.substring(index+this.versionSearchString.length+1));
			},
			
			dataBrowser:
			[
				{
					string: navigator.vendor,
					subString: "Apple",
					identity: "Safari"
				},
				{
					prop: window.opera,
					identity: "Opera"
				},
				{
					string: navigator.vendor,
					subString: "iCab",
					identity: "iCab"
				},
				{
					string: navigator.vendor,
					subString: "KDE",
					identity: "Konqueror"
				},
				{
					string: navigator.userAgent,
					subString: "Firefox",
					identity: "Firefox"
				},
				{	// for newer Netscapes (6+)
					string: navigator.userAgent,
					subString: "Netscape",
					identity: "Netscape"
				},
				{
					string: navigator.userAgent,
					subString: "MSIE",
					identity: "Explorer",
					versionSearch: "MSIE"
				},
				{
					string: navigator.userAgent,
					subString: "Gecko",
					identity: "Mozilla",
					versionSearch: "rv"
				},
				{ 	// for older Netscapes (4-)
					string: navigator.userAgent,
					subString: "Mozilla",
					identity: "Netscape",
					versionSearch: "Mozilla"
				}
			],
			
			dataOS : 
			[
				{
					string: navigator.platform,
					subString: "Win",
					identity: "Windows"
				},
				{
					string: navigator.platform,
					subString: "Mac",
					identity: "Mac"
				},
				{
					string: navigator.platform,
					subString: "Linux",
					identity: "Linux"
				}
			]
		},
		
		xslt:
		{
			init: function()
			{
				this.disableOutputEscaping.init();
			},
			
			disableOutputEscaping:
			{
				correct: null,
				
				init: function()
				{
					if(Application.util.browserInformation.browser == "Firefox")
					{
						Application.util.xslt.disableOutputEscaping.correct = Application.util.xslt.disableOutputEscaping.correctFF;
					}
					else
					{
						Application.util.xslt.disableOutputEscaping.correct = Application.util.xslt.disableOutputEscaping.correctIE;
					}
				},
				
				correctIE: function()
				{
					return true;
				},
				
				correctFF: function( args )
				{
					var area = document.getElementById( args.id );
					
					area.innerHTML = area.textContent;
					
					return true;
				}
			}
		},
		
		urlInformation:
		{
			siteName: null,
			protocol: null,
			params: null,
			
			init: function()
			{
				var url = document.location.href.toString();
				var internalArray = url.split("://");
				
				this.protocol = internalArray[0];
				
				// Replace multiple consecutive slashes
				var tokens = internalArray[1].replace(/\/\/+/, '/').split("/");
				
				this.siteName = tokens[0];
				
				// Create parameters
				this.params = new Array();
				
				for( var i = 1; i < tokens.length ; i++ )
				{
					var currentParam = tokens[i].split("_");
					
					this.params[ currentParam[0] ] = currentParam[1];
				}
				
				/*
				var parameters = internalArray[1][1].split("?")[1];
				
				if(!parameters)
				{
					return true;
				}
				
				if(parameters.indexOf("#") > -1)
				{
					parameters = parameters.substr(0, parameters.indexOf("#")).split("&")
				}
				else
				{
					parameters = parameters.split("&");	
				}
				
				for(var i=0;i<parameters.length;i++)
				{
					var temp = parameters[i].split("=");
					
					this.params[ temp[0] ] = temp[1];
				}
				*/
				
				return true;
			}
		},
		
		objectsEnhancements:
		{
			init: function()
			{
				this.array();
			},
			
			array: function()
			{
				Array.prototype.inArray = 	function (value)
											{
												for (var i=(this.length-1); i>=0; i--)
												{
													if (this[i] === value)
													{
														return true;
													}
												}
												
												return false;
											};
			}
		}
		
	}
	