﻿



/// <reference path="../jQuery/1.3.2/jquery-1.3.2-vsdoc.js" />


/**
 * MANHEIM PORTFOLIO GLOBAL UTILITIES CLASS
 *
 * Self initialising UTILITY CLASS instance - as such no instance instantiation required
 * 
 * 1. Configures any core class prototype extensions
 * 2. Provides generic utility methods
 * 
 * USAGE:
 *		INITIATED		: Prior to jQuery document load therefore ready for all classes to use
 * 		METHOD ACCESS	: Methods accessed via global object : 'mrm.global' : e.g.'mrm.global.exampleMethod()'
 *
 *
 * - Sets up the following prototype methods:
 *
 *		- String
 *		  - String.prototype.startsWith()
 *		  - String.prototype.endsWith()
 *
 *
 * - Provides following global methods:
 *		
 *		- GENERAL
 *		  - getQueryStringParameter()
 *		  - unencodeAjaxResponse()
 *		
 *		- COMMON DISPLAY CONTROL
 *		  - switchElementClass()
 *		  - toggleElementClass()
 *		
 *		- DATA MANIPULATION 
 *		  - mergeDataListsIntoUniqueList
 *		  - removeValuesFromDataList()
 */
	 
	
	(function (){
		
		
		var Utilities = Object.subClass(
			{
				/*
				 =============================
				 CONSTANTS
				 =============================
				 */
					EVENT_PROPERTY_TYPE		: "type",
					EVENT_PROPERTY_TARGET	: "target",
					EVENT_PROPERTY_DATA		: "data",
					CONST_POSTCODE_REGEX    :  /^([Gg][Ii][Rr] 0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([A-Za-z][0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9]?[A-Za-z])))) [0-9][A-Za-z]{2})$/g,				
				
				/*
				 =============================
				 CONFIGURATION PROPERTIES (instance configuration)
				 =============================
				 */
				
				
				
				/*
				 =============================
				 CONSTRUCTOR
				 =============================
				 */
					init : function ()
					{
						this._configureStringPrototypeMethods();
					},
				
				
				
				/*
				 =============================
				 INTERNAL RUN-TIME PROPERTIES
				 =============================
				 */
					_configureStringPrototypeMethods : function ()
					{
						/**
						 * String.prototype.startsWith()
						 *
						 * @runtimeScope = string object
						 *
						 * @param	string [String]				test string
						 * @param	caseSensitive [Boolean]		
						 * @return	[boolean]		
						 */
						String.prototype.startsWith = function(string, caseSensitive)
						{
							if (caseSensitive) return (string == this.substring(0, string.length));
							else return (string.toLowerCase() == this.substring(0, string.length).toLowerCase());
						}

						/**
						 * String.prototype.endsWith()
						 *
						 * @runtimeScope = string object
						 *
						 * @param	string [String]				test string
						 * @param	caseSensitive [Boolean]		
						 * @return	[boolean]	
						 */
						String.prototype.endsWith = function(string, caseSensitive)
						{
							if (caseSensitive) return (string == this.substring(this.length - string.length));
							else return (string.toLowerCase() == this.substring(this.length - string.length).toLowerCase());
						}
						
					},
				
				
				
				/*
				 =============================
				 PUBLIC METHODS
				 =============================
				 */
					/*
					 =============================
					 GENERAL
					 =============================
					*/
						/**
						 * Access to querystring parameters
						 *
						 * @param	name [String]	name of required query string parameter
						 * @return	[String]		queryString param defined by 'name'
						 */
							getQueryStringParameter : function (name)
							{ 
								name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]"); 
								var regexS = "[\\?&]" + name + "=([^&#]*)"; 
								var regex = new RegExp(regexS);
								var results = regex.exec(window.location.href);
								if (results == null)  return ""; 
								else return results[1]; 
							},



						/**
						 * Unescape the .NET encoding for an Ajax callback
						 *
						 * @param	response [?String]	Escaped Ajax callback response string
						 * @return	[?String]			Unescaped string
						 */
							unencodeAjaxResponse : function (response)
							{
								response = unescape(response);
								response = response.replace(/Â/g, '');
								response = response.replace(/\+/g, ' ');
								return response;
							},
					
					
					
					/*
					 =============================
					 EVENT GENERATION
					 =============================
					*/
						/**
						 * Generate event object with standardised format
						 *
						 * @param	name [String]		Event name
						 * @param	data [Object]		Event data object
						 * @param	target [Object]		Class instance object : this is a reference to the object reference to the class instance 
						 * @return	[Object]			event object
						 */
							generateEventObject : function (type, data, target)
							{
								var e = {};
								e[this.EVENT_PROPERTY_TYPE] = type;
								e[this.EVENT_PROPERTY_DATA] = data;
								e[this.EVENT_PROPERTY_TARGET] = target;
								
								return e;
							},
						
					
					
					/*
					 =============================
					 COMMON DISPLAY CONTROL
					 =============================
					*/
						/*
						 * Switch supplied classes on a given element 
						 * 
						 * - Toggle a single class on a given element an element
						 * - If element has 'class1' it is replaced with 'class2' else vice-versa
						 *
						 * @param	element [resolved jQueryObject]	target jQuery element
						 * @param	class1	[String]
						 * @param	class2	[String]
						 */
							switchElementClass : function (element, class1, class2) 
							{
								if (element.hasClass(class1)) element.removeClass(class1).addClass(class2); 
								else element.removeClass(class2).addClass(class1);
							},



						/*
						 * Toggle element class 
						 * 
						 * - Toggle a single class on a given element an element
						 */
							toggleElementClass : function (element, className) 
							{
								if (element.hasClass(className)) element.removeClass(className);
								else element.addClass(className);
							},


					/*
					=============================
					Validation Methods
					=============================
					*/
					
						validatePostcode : function(postcode)
						{				
							//the postcode needs a space
							if (postcode.indexOf(' ') == -1 && postcode != '') {
								postcode = postcode.substr(0, postcode.length - 3) + ' ' + postcode.substr(postcode.length - 3, 3);
							}
					        
							var re = new RegExp(this.CONST_POSTCODE_REGEX);
							return postcode.match(re);					
						},
					
					
					/*
					 =============================
					 DATA MANIPULATION
					 =============================
					*/
						/*
						 * mergeDataIntoUniqueList ..... [previously know as 'GetUniqueLists']
						 *
						 * Merge 2 delimited (common delimiter) data lists into one, removing data duplications
						 * 
						 * @param	dataListA	[String]	String of delimited data values
						 * @param	dataListB	[String]	String of delimited data values
						 * @param	delimiter	[String]	String representing data separater used in listA and listB
						 */
							mergeDataListsIntoUniqueList : function (dataListA, dataListB, delimiter) 
							{
								//split the two lists into arrays
								var a = dataListA.split(delimiter);
								var b = dataListB.split(delimiter);
								
								// Add initial delimiter for existance checking (cleaned and removed at end);
								var returnString = delimiter;

								//cycle the first list and add the values to the return string if they aren't already present
								for (var i = 0; i < a.length; i++) {
									if (returnString.indexOf(delimiter + a[i] + delimiter) == -1 && a[i] != '') {
										returnString += a[i] + delimiter;
									}
								}

								//now cycle the second list and if any values aren't present then add them to the return list
								for (var j = 0; j < b.length; j++) {
									if (returnString.indexOf(delimiter + b[j] + delimiter) == -1 && b[j] != '') {
										returnString += b[j] + delimiter;
									}
								}

								//trim any leading and trailing separators
								if (returnString.startsWith(delimiter, true)) returnString = returnString.substring(1);
								if (returnString.endsWith(delimiter, true)) returnString = returnString.substring(0, returnString.length-1);
								
								//return the finished value list
								return returnString;
							},


						/*
						 * removeValuesFromDataList ..... [previously know as 'removeValuesFromList']
						 *
						 * Remove a series of data values from a defined list of delimited data
						 * 
						 * @param	dataList	[String]	String of delimited data values from which to remove 'valuesList' data
						 * @param	valuesList	[String]	String of delimited data values to remove from 'dataList'
						 * @param	delimiter	[String]	String representing data separater used in listA and listB
						 */
							removeValuesFromDataList : function (dataList, valuesList, delimiter) 
							{
								//split both lists into arrays
								var data	= dataList.split(delimiter);
								var values	= valuesList.split(delimiter);

								//the string of values to be returned   
								var returnString = '';

								//cycle the main list of values
								for (var i = 0; i < data.length; i++) 
								{
									var item = data[i];
									//check we have a valid listItem to be processed
									if (item != '') 
									{
										var add = true;
										//cycle the values array to see if this item should be added
										for (var j = 0; j < values.length; j++) 
										{
											if (item == values[j]) add = false;
										}

										//if add is still set to true then we can add it
										if (add) returnString += item + delimiter;
									}
								}

								//trim any leading and trailing separators
								if (returnString.endsWith(delimiter, true)) returnString = returnString.substring(0, returnString.length-1);

								//return the finished value list
								return returnString;
							},
				
				/*
				=============================
				UVL Module Methods
				=============================
				*/
					DEBUG					: false,
					ARGUMENT_WORKFLOW		: "wflw",
					
					getScopedWorkflowKey: function(element, workflowAction)
					{
						// form.action e.g. /results.aspx?wflw=se_de_se
						
						// get url
						var submitUrl = ($(element).attr("action"))? $(element).attr("action") : $(element).attr("href");
						
						return this.getScopedWorkflowKeyFromUrl(submitUrl,workflowAction);
					},
					
					
					getScopedWorkflowKeyFromUrl: function(url,workflowAction)
					{
						var submitUrl = url;
						
						// get indexes
						var startIndex = submitUrl.indexOf(this.ARGUMENT_WORKFLOW) + this.ARGUMENT_WORKFLOW.length + 1; // start after wflw=
						var endIndex = submitUrl.indexOf("&",startIndex);
						
						// get full workflow
						var wflw
						if (endIndex != -1)
						{
							wflw = submitUrl.substring(startIndex,endIndex);
						}
						else
						{
							wflw = submitUrl.substring(startIndex);
						}
						
						if (workflowAction != null)
						{
							// now we have the scoped workflow trim off the action + "_" and add the relavant search action
							wflw = wflw.substring(0, wflw.length -3) + workflowAction;
						}
						
						this._debugtrace("Resolved workflow of " + wflw + "to fire.");
						
						return wflw;
					},
				
				
				
				/*
				 =============================
				 INTERNAL METHODS
				 =============================
				 */
					/*
					 =============================
					 UTILITIES
					 =============================
					 */
					 
					_debugtrace: function(message)
					{
						if (this.DEBUG)
						{
							alert(message);
						}
					}
					 
					/*
					 =============================
					 SETUP
					 =============================
					 */
					/*
					 =============================
					 DISPLAY CREATION
					 =============================
					 */
					/*
					 =============================
					 DISPLAY CONTROL
					 =============================
					 */
					/*
					 =============================
					 INTERNAL EVENT HANDLERS
					 =============================
					 */
			}	
		);
		
		
		
		try {
			// Check that namespace into which the Class definition will be creates has been defined & if not then create
			if (!mrm.global.isNamespaceDefined("mrm.global")) mrm.global.createNamespace("mrm.global", "1.0");
			
			// Create instance
			mrm.global.utilities = new Utilities();
		}
		catch (e)
		{
			alert("!! WARNING !! \n" + e.message);
		}
		
		
		
		
	})();
	
	
	// Method testing:
	// alert("mrm.global.utilities >> mergeDataListsIntoUniqueList = " + mrm.global.utilities.mergeDataListsIntoUniqueList("a,b,c,d,e,f,g,h,i,j", "a,c,e,f,j,k,l,m,n,o,p,q,r", ","));
	// alert("mrm.global.utilities >> removeValuesFromDataList = " + mrm.global.utilities.removeValuesFromDataList("a,b,c,d,e,f,g,h,i,j", "a,f,k,l", ","));
	
	
	//alert("mrm.global.utilities ::  Class definition successful");
