////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//	DLib General JavaScript functions - copyright davidviner.com 2006-2011 (except where stated)
//
//	11.08.2011	5.10.3	DJV		Option title added in selectMove. Added border and shadow to the image tooltip popup.
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Some useful methods/functions.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// From http://www.delphifaq.com/faq/f1031.shtml

if (!String.prototype.trim)
{
	String.prototype.trim = function ()
	{
    	return this.replace (/^\s*/, "").replace (/\s*$/, "");
    }
}

function isArray (object)
{
	return object != null && typeof object == "object" && 'splice' in object && 'join' in object;
}

function undef (v, preSpace)
{
	preSpace = (undefined ? false : preSpace);
	return (v == undefined ? "" : (preSpace ? " " : "") + v);
}

function elm (id)
{
	return document.getElementById (id);
}

//C/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Utility functions.
// @DLibUtilities
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

DLibUtilities = function ()
{
	var	ta		= new Object,
		popImg	= null,
		ttTm	= null;

	var _private =
	{
		////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		// From http://www.softcomplex.com/docs/get_window_size_and_scrollbar_position.html
		////////////////////////////////////////////////////////////////////////////////////////////////////////////////

		filterResults : function (n_win, n_docel, n_body)
		{
			var n_result = n_win ? n_win : 0;

			if (n_docel && (!n_result || (n_result > n_docel))) n_result = n_docel;
			return (n_body && (!n_result || (n_result > n_body)) ? n_body : n_result);
		}
	}

	var _public =
	{
		//F/////////////////////////////////////////////////////////////////////////////////////////////////////////////
		// Find the x/Y position of an object (from: http://www.quirksmode.org/js/findpos.html).
		// @findPos		[int]	The x/y position.
		// @obj			Object	The object to check.
		// @doOffset	boolean	Factor in any scrolling.
		////////////////////////////////////////////////////////////////////////////////////////////////////////////////

		findPos : function (obj, doOffset)
		{
			if (doOffset == undefined) doOffset = false;

			var	left = 0;
			var top = 0;

			if (obj && obj.offsetParent)
			{
				left = obj.offsetLeft;
				top = obj.offsetTop;

				// WARNING: this loop will fail if it encounters a "position: relative" box

				while (obj = obj.offsetParent)
				{
					left += obj.offsetLeft;
					top += obj.offsetTop;
				}
			}

			if (doOffset)
			{
				var so = DLibUtilities.scrollOffset ();
				left -= so [0];
				top -= so [1];
			}

			return [parseInt (left), parseInt (top)];
		},

		//F/////////////////////////////////////////////////////////////////////////////////////////////////////////////
		// Find the X/Y scroll positions of the browser window. From
		// http://www.softcomplex.com/docs/get_window_size_and_scrollbar_position.html.
		// @scrollOffset	[int]	X/Y offset (if any).
		////////////////////////////////////////////////////////////////////////////////////////////////////////////////

		scrollOffset : function ()
		{
			scX = _private.filterResults (window.pageXOffset ? window.pageXOffset : 0,
				document.documentElement ? document.documentElement.scrollLeft : 0,
				document.body ? document.body.scrollLeft : 0);

			scY = _private.filterResults (window.pageYOffset ? window.pageYOffset : 0,
				document.documentElement ? document.documentElement.scrollTop : 0,
				document.body ? document.body.scrollTop : 0);

			return [scX, scY];
		},

		//F/////////////////////////////////////////////////////////////////////////////////////////////////////////////
		// Get the current browser window size. From www.howtocreate.co.uk/tutorials/javascript/browserwindow
		// @getWindowSize	[int]	Array of width/height.
		////////////////////////////////////////////////////////////////////////////////////////////////////////////////

		getWindowSize : function ()
		{
			var w = 0, h = 0;

			if (typeof (window.innerWidth) == 'number')
			{
				// Standard

				w = window.innerWidth;
				h = window.innerHeight;
			}
			else
			if (document.documentElement && (document.documentElement.clientWidth ||
				document.documentElement.clientHeight))
			{
				// IE 6+ in 'standards compliant mode'

				w = document.documentElement.clientWidth;
				h = document.documentElement.clientHeight;
			}
			else
			if (document.body && (document.body.clientWidth || document.body.clientHeight))
			{
				// IE 4 compatible

				w = document.body.clientWidth;
				h = document.body.clientHeight;
			}

			return [w, h];
		},

		////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		// Used by SEF_TABLE entry in dbscreens.php.
		////////////////////////////////////////////////////////////////////////////////////////////////////////////////

		selectMove : function (fn, md)
		{
			var selList = document.getElementById (fn + "_sel");
			var avList = document.getElementById (fn + "_av");
			var mainList = document.getElementById (fn);
			var from = avList;
			var to = selList;

			if (md == 1)
			{
				from = selList;
				to = avList;
			}

			if (from.length > 0)
			{
				var idx = from.selectedIndex;

				if (idx > -1)
				{
					var txt = from.options [idx].text;
					var val = from.options [idx].value;
					var newOpt = new Option (txt, val);
					newOpt.title = txt;
					var done = false;

					for (i = 0; i < to.length; i++)
						if (txt < to.options [i].text)
						{
							to.options.add (newOpt, i);
							done = true;
							break;
						}

					if (!done)
						to.options.add (newOpt, to.length);

					from.options [idx] = null;
				}

				var sList = "^";

				if (selList.length > 0)
				{
					for (i = 0; i < selList.length; i++)
					{
						sList += selList.options [i].value + "^";
					}
				}

				if (sList == "^") sList = "";

				mainList.value = sList;
			}
		},

		////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		// Fill the specified drop-down menu with the supplied array.
		////////////////////////////////////////////////////////////////////////////////////////////////////////////////

		fillMenu : function (fn, data)
		{
			var menu = document.getElementById (fn);

			// Remove any existing entries

			if (menu.length > 0)
			{
				for (i = menu.length - 1; i >= 0; i--)
				{
					menu.options [i] = null;
				}
			}

			// Add in the new options

			for (i = 0; i < data.length; i++)
			{
				var newOpt = (isArray (data [i]) ? new Option (data [i][1], data [i][0]) :
					new Option (data [i], data [i]));

				menu.options.add (newOpt, i);
			}
		},

		////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		// Initialise the taField values.
		////////////////////////////////////////////////////////////////////////////////////////////////////////////////

		initTA : function (taFlds, minRows, maxRows)
		{
			ta.flds = taFlds;
			ta.minRows = minRows;
			ta.maxRows = maxRows;
		},

		////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		// Handle a taField vertical size.
		////////////////////////////////////////////////////////////////////////////////////////////////////////////////

		expandTA : function (fld)
		{
			for (i = 0; i < ta.flds.length; i++)
			{
				document.getElementById (ta.flds [i]).rows = (fld == ta.flds [i] ? ta.maxRows : ta.minRows);
			}
		},

		////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		// Toggle the visibility of the image change fields (SEF_IMAGE).
		////////////////////////////////////////////////////////////////////////////////////////////////////////////////

		imgChgFlds : function (fld)
		{
			var f = document.getElementById ("ichg" + fld).style;
			f.display = (f.display == "none" ? "inline" : "none");
		},

		//F/////////////////////////////////////////////////////////////////////////////////////////////////////////////
		// Initialise an AJAX connection.
		// @initAjax	object	The ajax object.
		// @url			string	The URL of the ajax handler.
		// @resp		object	The function object	that will handle the ajax response (can be blank for no response).
		////////////////////////////////////////////////////////////////////////////////////////////////////////////////

		initAjax : function (url, resp)
		{
			resp = (resp == undefined ? "" : resp);
			var xmlHttp = (window.XMLHttpRequest ? new XMLHttpRequest () : new ActiveXObject ("MSXML2.XMLHTTP"));
			xmlHttp.open ("GET", url, true);

			if (resp != "") xmlHttp.onreadystatechange = resp;

			xmlHttp.send (null);
			return xmlHttp;
		},

		//F/////////////////////////////////////////////////////////////////////////////////////////////////////////////
		// Return true if there is a valid response from the specified AJAX connection.
		// @checkAjax	boolean	True if valid.
		// @ajax		object	The ajax object to be checked.
		////////////////////////////////////////////////////////////////////////////////////////////////////////////////

		checkAjax : function (ajax)
		{
			return (ajax != null && ajax.readyState == 4 && ajax.status == 200);
		},

		//F/////////////////////////////////////////////////////////////////////////////////////////////////////////////
		// Set the opacity level of the specified object.
		// @opacity
		// @o		object	The object to use.
		// @opac	int		The opacity level to use (0 to 100).
		////////////////////////////////////////////////////////////////////////////////////////////////////////////////

		opacity : function (o, opac)
		{
			o.style.opacity = (opac / 100);
			o.style.MozOpacity = (opac / 100);
			o.style.KhtmlOpacity = (opac / 100);
			o.style.filter = "alpha(opacity=" + opac + ")";
		},

		//F/////////////////////////////////////////////////////////////////////////////////////////////////////////////
		// Return the version number given a string and a starting position (version numbers are assumed to contain
		// only digits and dots).
		// @versionNumber	string	The version number.
		// @str				string	The string to use.
		// @pos				int		The starting position.
		////////////////////////////////////////////////////////////////////////////////////////////////////////////////

		versionNumber : function (str, pos, convUS)
		{
			convUS = (undefined ? false : convUS);

			if (convUS)
				str = str.replace (/_/g, ".");

			var version = "";

			while ((str.charAt (pos) >= '0' && str.charAt (pos) <= '9') || str.charAt (pos) == '.')
			{
				version += str.charAt (pos++);
			}

			return version;
		},

		//F/////////////////////////////////////////////////////////////////////////////////////////////////////////////
		// Return information about the platform, browser and browser version.
		// @systemCheck	array	[platform, browser, version].
		////////////////////////////////////////////////////////////////////////////////////////////////////////////////

		systemCheck : function ()
		{
			var	browser = '?';
			var	platform = '?';
			var ua = navigator.userAgent;

			var iPad = ua.indexOf ('iPad');
			var iPhone = ua.indexOf ('iPhone');
			var iWebTV = ua.indexOf ('WebTV');
			var iIE = ua.indexOf ('MSIE');
			var iOpera = ua.indexOf ('Opera');
			var iChrome = ua.indexOf ('Chrome');
			var iSafari = ua.indexOf ('Safari');
			var iMozilla = ua.indexOf ('Gecko');
			var iFirefox = ua.indexOf ('Firefox');
			var iKonqueror = ua.indexOf ('Konqueror');
			var iNetscape = ua.indexOf ('Mozilla');
			var iCamino = ua.indexOf ('Camino');

			var ver = -1;

			if (iWebTV >= 0)
			{
				browser = 'WebTV';
				ver = iWebTV + 6;
			}
			else
			if (iOpera >= 0)
			{
				browser = 'Opera';
				ver = iOpera + 6;
			}
			else
			if (iIE >= 0)
			{
				browser = 'Internet Explorer';
				ver = iIE + 5;
			}
			else
			if (iChrome >= 0)
			{
				browser = 'Chrome';
				ver = iChrome + 7;
			}
			else
			if (iCamino >= 0)
			{
				browser = 'Camino';
				ver = ua.indexOf('Camino/') + 7;
			}
			else
			if (iSafari >= 0)
			{
				browser = 'Safari';
				ver = iSafari + 7;
			}
			else
			if (iFirefox >= 0)
			{
				browser = 'Firefox';
				ver = ua.indexOf('Firefox/') + 8;
			}
			else
			if (iMozilla >= 0)
			{
				browser = 'Mozilla';
				ver = ua.indexOf('rv:') + 3;
			}
			else
			if (iKonqueror >= 0)
			{
				browser = 'Konqueror';
				ver = iKonqueror + 10;
			}
			else
			if (iNetscape >= 0)
			{
				browser = 'Netscape';
				ver = iNetscape + 8;
			}

			var version = DLibUtilities.versionNumber (ua, ver);

			if (ua.indexOf ('Win') >= 0)
			{
				platform = 'Windows';

				if (ua.indexOf ('95') >= 0) platform += " 95";
				else if (ua.indexOf ('98') >= 0) platform += " 98";
				else if (ua.indexOf ('2000') >= 0) platform += " 2000";
				else if (ua.indexOf ('NT 5.2') >= 0) platform += " XP/2003";
				else if (ua.indexOf ('NT 5.1') >= 0) platform += " XP";
				else if (ua.indexOf ('NT 5.0') >= 0) platform += " 2000";
				else if (ua.indexOf ('NT 6.0') >= 0) platform += " Vista";
				else if (ua.indexOf ('NT 6.1') >= 0) platform += " 7";
				else if (ua.indexOf ('NT') >= 0) platform += " NT";
			}

			if (iPad >= 0 || iPhone >= 0)
			{
				var v = DLibUtilities.versionNumber (ua, ua.indexOf('CPU OS') + 7, true);
				platform = (iPad >= 0 ? "iPad" : "iPhone") + " iOS " + v;
			}
			else
			{
				if (ua.indexOf ('Mac') >= 0)		platform = 'Macintosh';
				if (ua.indexOf ('Mac OS X') >= 0)	platform = 'Mac OS X';
				if (ua.indexOf ('OS/2') >= 0)		platform = 'OS/2';
				if (ua.indexOf ('X11') >= 0)		platform = 'UNIX';
				if (ua.indexOf ('Linux') >= 0)		platform = 'Linux';

				var ub = ua.indexOf ('Ubuntu/');
				if (ub >= 0) platform = 'Ubuntu Linux ' + DLibUtilities.versionNumber (ua, ub + 7);
			}

			if (browser == "Netscape" && version >= 5 && version < 7) version = 6;

			return [platform, browser, version];
		},

		//F/////////////////////////////////////////////////////////////////////////////////////////////////////////////
		// Return true if the specified value is found in the array to test. Based on the code at:
		// kevin.vanzonneveld.net/techblog/article/javascript_equivalent_for_phps_in_array
		// @in_array	boolean		True if found.
		// @needle		mixed		The item to search for.
		// @haystack	array		Array to be tested.
		////////////////////////////////////////////////////////////////////////////////////////////////////////////////

		in_array : function (needle, haystack)
		{
			var key = '';

			for (key in haystack)
			{
				if (haystack [key] === needle) return true;
			}

			return false;
		},

		//F/////////////////////////////////////////////////////////////////////////////////////////////////////////////
		// Return the specified number of non-blank spaces.
		// @spaces	string	The "nbsp" characters.
		// @qty		int		The number required.
		////////////////////////////////////////////////////////////////////////////////////////////////////////////////

		spaces : function (qty)
		{
			var txt = "";

			for (i = 0; i < qty; i++)
				txt += "&nbsp;";

			return txt;
		},

		//F/////////////////////////////////////////////////////////////////////////////////////////////////////////////
		// Return the specified CSS style of an object (based upon code from www.quirksmode.org/dom/getstyles.html).
		// @getStyle	string	The currently assigned style.
		// @id			string	The ID of the object to interrogate.
		// @prop		string	The property to return.
		////////////////////////////////////////////////////////////////////////////////////////////////////////////////

		getStyle : function (id, prop)
		{
			var obj = document.getElementById (id);

			if (obj.currentStyle) return obj.currentStyle [prop];
			return document.defaultView.getComputedStyle (obj, null).getPropertyValue (prop);
		},

		////////////////////////////////////////////////////////////////////////////////////////////////////////////////

		showTooltip : function (txt, id, ht, xOffset)
		{
			if (ht == undefined) ht = 0;
			if (xOffset == undefined) xOffset = 25;

			var tt = document.getElementById ("popuptooltip");

			if (tt)
			{
				if (ttTm != null)
					clearTimeout (ttTm);

				var ob = document.getElementById (id);
				var xy = DLibUtilities.findPos (ob);

				tt.style.position = "absolute";
				tt.style.display = "block";

				if (txt.substr (0, 4) == "IMG:")
				{
					tt.style.left = (xy [0] + xOffset) + "px";

					var top = (xy [1] - (ht / 2) + 15);
					var wh = DLibUtilities.getWindowSize ();
					var off = DLibUtilities.scrollOffset ();

					if (top + ht + 15 > wh [1] + off [1])	// Keep image onscreen
					{
						top = wh [1] - ht - 15 + off [1];
					}

					if (top - off [1] < 0)
					{
						top = off [1] + 5;
					}

					tt.style.top = parseInt (top) + "px";
					tt.style.maxWidth = "none";
					tt.innerHTML = '<img style="border: 1px solid black; box-shadow: 3px 3px 8px #555;" src="' +
						txt.substr (4) + '" border="0" alt=""' + (ht > 0 ? ' height="' + ht + '"' : '') + '/>';
				}
				else
				{
					tt.style.left = (xy [0] + xOffset) + "px";
					tt.style.top = (xy [1] + 20) + "px";
					tt.style.maxWidth = "250px";
					tt.innerHTML = txt;
				}
			}
		},

		////////////////////////////////////////////////////////////////////////////////////////////////////////////////

		clearTooltip : function ()
		{
			ttTm = setTimeout ("DLibUtilities.closeTooltip()", 500);
		},

		////////////////////////////////////////////////////////////////////////////////////////////////////////////////

		holdTooltip : function ()
		{
			clearTimeout (ttTm);
			ttTm = null;
		},

		////////////////////////////////////////////////////////////////////////////////////////////////////////////////

		closeTooltip : function ()
		{
			clearTimeout (ttTm);
			ttTm = null;
			var tt = document.getElementById ("popuptooltip");
			if (tt) tt.style.display = "none";
		},

		//F/////////////////////////////////////////////////////////////////////////////////////////////////////////////
		// Process special characters that cause problems in strings (javascript.about.com/library/bladdslash.htm).
		// @addSlashes	string	The processed string.
		// @s			string	The string to process.
		////////////////////////////////////////////////////////////////////////////////////////////////////////////////

		addSlashes : function (s)
		{
			s = s.replace(/\\/g,'\\\\');
			s = s.replace(/\'/g,'\\\'');
			s = s.replace(/\"/g,'\\"');
			return s.replace(/\0/g,'\\0');
		},

		//F/////////////////////////////////////////////////////////////////////////////////////////////////////////////
		// String the special processing performed by addSlashes (javascript.about.com/library/bladdslash.htm).
		// @stripSlashes	string	The processed string.
		// @s				string	The string to process.
		////////////////////////////////////////////////////////////////////////////////////////////////////////////////

		stripSlashes : function (s)
		{
			s = s.replace(/\\'/g,'\'');
			s = s.replace(/\\"/g,'"');
			s = s.replace(/\\0/g,'\0');
			return s.replace(/\\\\/g,'\\');
		}
	};

	return _public;
} ();

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


