/**
 * LBI.common
 * @version 1.0
 * @author LBi - http://www.lbi.com/en
 * @requires jQuery Core 1.2.6 - http://www.jquery.com/
 * @requires jQuery UI 1.6rc2 - http://ui.jquery.com/
*/
/*jslint bitwise: true, eqeqeq: true, passfail: false, nomen: true, plusplus: false, undef: true, evil: true */
/*global window, document, navigator, $, jQuery, LBI, */

var LBI = window.LBI || {};

/**
 * @namespace Common re-used functionality.
 */
LBI.common = {	
	version					: 1.0,	
	
	identJSClass			: 'hasJS',
	dynamicInputSelector	: 'input.dyna-text',
	dynamicInputFocusClass	: 'focused',
	ajaxQueryParam			: 'rc=1',
	newWindowClass			: 'newwin',
	newWindowText			: 'This link will open a new window',
	//webSafeChar			: '&#8203;',
	webSafeChar				: '<span class="webSafeChar"> </span>',
	printLinkClass			: 'printwin',
	printLinkText			: 'This link will open the Print dialog',
	
	/**
	 * Add class to body to identify presence of JS.
	 * <p>
	 * Use hasJS.css instead to control load flicker etc.
	 */
	identJS: function() {
		$('body').addClass(LBI.common.identJSClass);
	},
	
	sortNumeric: function(b,a) {
		return a < b ? -1 : (a > b) ? 1 : 0;
	},
	isUnsignedInteger: function (s) {
		return (s.toString().search(/^[0-9]+$/) === 0);
	},
	/**	
	 * Returns object of all queries within a string.
	 * <p>
	 * Will return undefined for no query string.
	 * 
	 * @param {Object} 	theString
	 * @return {Object}	key:values of query string
	 */
	getStringQueries: function(theString) {
		// returns object of all queries within a string
		if (typeof theString !== 'string') {
			return;			
		}
		
		if (theString.indexOf('?') > -1) {
			// make sure you get query side of url
			theString = theString.split('?')[1];
		}
		
		var qs = theString, qsKey, qsValue, stringElements = {};
		// make an array of query string items
		qs = qs.split("&");
		// create object
		for (var i = qs.length - 1; i >= 0; i--) {
			qsKey = qs[i].split("=")[0];
			qsValue = qs[i].split("=")[1];
			stringElements[qsKey] = qsValue;
		}
		return stringElements;

	},
	/** 
	 * Splits a string that would not normally wrap (like and email address) with wrapping characters.
	 * <p>
	 * Since wrapping characters are not supported in IE6 without East Asian language support an empty 
	 * styled <span> is used instead. This leads to some accessibility issues.
	 * 
	 * @param (String) myString
	 * @return {String} 
	 */
	webSafeString: function (myString) {
		var stringAsArray = myString.split("");
		var stringLength = stringAsArray.length;
		var newArray = [];
		for (var i=0; i < stringLength; i++ ) {
			newArray.push(stringAsArray[i],LBI.common.webSafeChar);
		}
		var newString = newArray.join("");
		return newString;
	},
	/**
	 * Strip out and return local page anchor from URL.
	 * 
	 * @param 	{Object} anchor
	 * @return 	Return the anchor portion of the URL (or false if no anchor)
	 */
	urlGetAnchor: function(anchor) {
		if ( anchor.href.indexOf("#") >= 0 ) { //Check for anchorness
			anchor.destination = anchor.href.slice(anchor.href.indexOf("#")+1);
			return anchor.destination;
		} else {
			return false;
		}
	},
	
	/**
	 * New window/popup function.
	 * <p>
	 * Add the openInNewWindow function to the onclick event of links with a specified class name.
	 * 
	 * @return	{Boolean} Returns false if windown not open
	 */
	getNewWindowLinks: function() { 
		$('a').each(function (i) {
			if ($(this).hasClass(LBI.common.newWindowClass)) {
				$(this).title = $(this).title + " " + LBI.common.newWindowText;
				$(this).click(function () {
			    	var newWindow = window.open(this.getAttribute('href'), '_blank');
					if (newWindow) {
						if (newWindow.focus) {
							newWindow.focus();
						}
					}
					return false;
			    });
			}
		});
	},
	
	/**
	 * Print dialog function.
	 * <p>
	 * Add the window.print function to the onclick event of links with a specified class name.
	 */
	getPrintLinks: function() { 
		$('a').each(function (i) {
			if ($(this).hasClass(LBI.common.printLinkClass)) {
				$(this).title = $(this).title + " " + LBI.common.printLinkText;
				$(this).click(function () {
			    	var printWin = window.print();
					return false;
			    });
			}
		});
	},
	
	/**
	 * Input field text population.
	 * <p>
	 * Takes current value of form inputs and handles clearing and repopulating on focus.
	 */
	dynamicInputText: function() {
		$(LBI.common.dynamicInputSelector).each(function (i) {
			var target = this;
			target.savedText = target.value; // keep track of the original input value
			target.onfocus=function(){
				$(this)[0].value = jQuery.trim($(this)[0].value);
				if ($(this)[0].value === this.savedText) {
					$(this)[0].value = "";
				}
				$(this).addClass(LBI.common.dynamicInputFocusClass);
			};
			target.onblur=function(){
				$(this)[0].value = jQuery.trim($(this)[0].value);
				if ($(this)[0].value === "") {
					$(this)[0].value = this.savedText;
				}
				$(this).removeClass(LBI.common.dynamicInputFocusClass);
			};
		});
	},
	
	/**
	 * Equal height box columns.
	 * <p>
	 * Takes an array of elements and sets style to the maxiumum height.
	 * 
	 * @param (Array) boxes	 
	 */
	boxHeights: function(boxes) {
		var heights = [];
		for (var i=0;i<boxes.length;i++) {
			if (navigator.userAgent.toLowerCase().indexOf('opera') === -1) {
				heights.push(boxes[i].scrollHeight);
			} else {
				heights.push(boxes[i].offsetHeight);
			}
		}
		heights.sort(this.sortNumeric);
		var maxh = heights[0];
		for (var j=0;j<boxes.length;j++) {
			boxes[j].style.height = maxh+"px";
		}
	},
	
	/**
	 * @namespace Common AJAX functionality.
	 */
	ajax: {		
		bufferFieldID	: 'ajaxVirtualBufferUpdate',		
		/**
		 * Insert form field for buffer update
		 */
		prepareBuffer: function() {
			var objHidden = document.createElement('input');
			
			objHidden.setAttribute('type', 'hidden');
			objHidden.setAttribute('value', '1');
			objHidden.setAttribute('id', LBI.common.ajax.bufferFieldID);
			objHidden.setAttribute('name', LBI.common.ajax.bufferFieldID);

			document.body.appendChild(objHidden);
		},
		/**
		 * Updates value of hidden form field to nudge screen readers into recognising page state change.
		 * 
		 * @see LBI.common.ajax.prepareBuffer()
		 */
		updateBuffer: function() {
			var objHidden = document.getElementById(LBI.common.ajax.bufferFieldID);			
			if (objHidden) {
				if (objHidden.getAttribute('value') === '1') {
					objHidden.setAttribute('value', '0');
				} else {
					objHidden.setAttribute('value', '1');
				}
			} else {
				LBI.common.ajax.prepareBuffer();
				LBI.common.ajax.updateBuffer();
			}		
		},	
		/**
		 * Takes a string (URL expected) and appends parameter to identify as AJAX request for backend processing.
		 * 
		 * @param {String}	URL
		 * @return {String}	An AJAXed URL
		 */	
		tagUrl: function(url) {
			// 
			var prefix =(url.indexOf('?') < 0 ) ? "?" : "&" ;
			var ajaxURL = url + prefix + LBI.common.ajaxQueryParam;
			return ajaxURL;
		}
	},
	
	
	/**
	 * Parse version string.
	 * <p>
	 * Parse the version strings with a simple function and return them as objects with appropriate properties whose values are integers. 
	 * Once in this form, we can compare them with simple mathematics.
	 * 
	 * @param 	{String} str
	 * @return 	{Object} Return the major, minor and patch numbers
	 */
	parseVersionString: function(str) {
	    if (typeof(str) !== 'string') { return false; }
	    var x = str.split('.');
	    // parse from string or default to 0 if can't parse
	    var maj = parseInt(x[0], 10) || 0;
	    var min = parseInt(x[1], 10) || 0;
	    var pat = parseInt(x[2], 10) || 0;
	    return {
	        major: maj,
	        minor: min,
	        patch: pat
	    };
	},
	
	
	/**
	 * @namespace Effects.
	 * @requires jQuery UI effects plugin
	 */ 
	effects: {
		/**
		 * Highlight a DOM element.
		 * <p>
		 * Takes a DOM element and optionally a highlight colour. Sets the background colour of the DOM element to the highlight colour, then 
		 * fades to the previous background colour over the specified time interval.
		 * 
		 * @param {Object} element	The element to highlight
		 * @param {String} [color=#FFFFCC]	The colour to highlight the element with.
		 * @param {Integer} [speed=1000]	The time interval in which to perform the highlight, in milliseconds.
		 */
		highlightElement: function(element,color,speed) {
			color = (!color) ? "#FFFFCC" : color;
			speed = (!speed) ? 1000 : speed;
			$(element).effect('highlight', {color: color}, speed);
		}
	}
	
};/* /LBI.common */

