/* <![CDATA[ */
	
	// Functions:						Util(), Behaviour()
	// Date: 								8 May 2007
	// Author:							Russ Back
	// This version:				EXTRACTED FROM CORE extensions.js IN USE FOR EACH COMMERCE STORE
	// Production version:	svn/JavaScript/Deployment/Arcadia Corporate/extensions.js
	// Documentation:				svn/Documentation/Util User Guides/extensions.js.doc
	// Notes:								EXTRACTED FROM CORE extensions.js IN USE FOR EACH COMMERCE STORE
	
	// brand configuration
	var Brand = {

		// popup windows
		newWindowClass : "new_window",	// class to check for when adding popup windows
		newWindowTitle : " (this link will open in a new browser window)",	// title to append to popup window links
		popupWindowName : "Arcadia_popup",	// name of popup window
		
		// toggle
		toggleClass : "toggle",	// class to check when adding toggle feature
		toggleContentClass : "toggle_content",	// class to check for when toggling children elements of Arcadia.toggleClass
		toggleForceClass : "forcelink",	// class to cancel link and open/close toggle content
		
		// form validation
		formValidationClass : "validate", // classname of form to validate
		formValidationRequiredFieldClass : "required",	// class name of fields that require a value
		formValidationNumericFieldClass : "numeric", // class name of fields that require a numeric value
		formValidationDateFieldClass : "date", // class name of fields that require a DD/MM/YY value
		formValidationEmailFieldClass : "email", // class name of fields that require a valid email address
		formValidationMessage : "Please complete the following:" // message of alert box
		
		}

	// utility functions
	var Util = {
		
		// add event listener taken from http://ejohn.org/projects/flexible-javascript-events/
		addEvent : function(obj, type, fn) {
			if ( obj.attachEvent ) {
				obj['e'+type+fn] = fn;
				obj[type+fn] = function(){obj['e'+type+fn]( window.event );}
				obj.attachEvent( 'on'+type, obj[type+fn] );
				} 
			else {
				obj.addEventListener( type, fn, false );
				}
			},
		
		// document.getElement(s)ById shortcut utility, taken from prototype.js
		$ : function() {
		  var els = new Array();
			for (var i = 0; i < arguments.length; i++) {
		  	var el = arguments[i];
		    if (typeof el == "string") el = document.getElementById(el);
			  if (arguments.length == 1) return el;
		    els.push(el);
			  }
			return els;
			},
		
		// array creation utility, taken from prototype.js
		$A : function(els) {
		  if (! els) return [];
			var results = [];
		  for (var i = 0; i < els.length; i++) results.push(els[i]);
			if (results.length == 0) results[0] = els;
		  return results;
		  },
		
		// return an array of elements containing the given classname. Can be narrowed down by providing 
		// element types to search for and the parent node to search from
		getElementsByClassName : function(className, tag, parent) {
			var els = (Util.$(parent) || document.body).getElementsByTagName((tag || "*")), matches = new Array();
			for (var i = 0; i < els.length; i++) { if (Util.hasClassName(els[i], className)) matches.push(els[i]); }
			return matches;
			},
			
		// check if an element has a given classname
		hasClassName : function(el, className) {
			var re = new RegExp("(^|\\s)" + className + "(\\s|$)");
			return Util.$(el).className.match(re);
			},
			
		// create new dom element and apply properties as required
		createNode : function(el, args, text) {
			// create new element
			var el = document.createElement(el);
			// loop through each property/value pair specified in args and apply to this node
			if (args) {
				for (var i = 0; i < args.length; i++) el.setAttribute(args[i][0], args[i][1]);
				}
			// create text node and append to element if required
			if (text) el.appendChild(document.createTextNode(text));
			// and return the element, ready to be attached to the dom
			return el;
			},
			
		// cancel a user's click
		cancelClick : function(e) {
			// if it's IE, cancel event bubbling and return false

			if (window.event) {
				window.event.cancelBubble = true;
				window.event.returnValue = false;
				}
			// or use Mozilla's alternative methods
			if (e && e.stopPropagation && e.preventDefault) {
				e.stopPropagation();
				e.preventDefault();
				}
			},
			
		// debug console - expects pairs of values (ie element, value : [[element, element.innerHTML], [element, element.id]])
		debug : function(args) {
			// get the console and create an empty para variable 
			var console = Util.$("extensions_debug_console"), para;	
			// create console if not available
			if (console == null) {
				// create console div
				var console = Util.createNode("div", [["id", "extensions_debug_console"]]);
				// insert into beginning of body
				document.body.insertBefore(console, document.body.firstChild);
				// create heading and intro for clarity and append to console
				var heading = Util.createNode("h1", [], "Extensions JavaScript debug console");
				para = Util.createNode("p", [["id", "console_intro"]], "All debug pairs are split. ie. val1 | val2 | val3");
				console.appendChild(heading);
				console.appendChild(para);
				}		
			// loop through each argument
			for (var i = 0; i < args.length; i++) {
				// create a new paragraph element
				para = Util.createNode("p", []);
				// split the values of each argument
				for (var j = 0; j < args[i].length; j++) {
					// and output each set of values as a single debug line, adding a divider for clarity
					if (j != 0) para.innerHTML += " | ";
					para.innerHTML += args[i][j];
					}
				// append debug content to console
				console.appendChild(para);
				}
			}

		};	
	
	// behaviour layer	
	var Behaviour = {
		// initiate behaviour functions
		init : function() {
			Behaviour.addToggles();
			Behaviour.addTargets();
			Behaviour.addFormValidation();
			},
	
		// attach popup() function to a elements	
		addTargets : function() {
			// get all elements with class="new_window" (*** do NOT specify <a> only as <area> can also be used ***)
			var links = Util.getElementsByClassName(Brand.newWindowClass), title;
			// loop through each element
			for (var i = 0; i < links.length; i++) {
				// create anonymous function and bind to the onclick event for this element
				var func = function() { Behaviour.popup(this.href); };
				Util.addEvent(links[i], "click", func);
				// cancel the user's click
				Util.addEvent(links[i], "click", Util.cancelClick);
				// update the title string
				var title = links[i].title || "";
				links[i].title = title + Brand.newWindowTitle;
				}
			},
		
		// spawn a new browser window
		popup : function(url) {
			// declare width and height variables
			var w, h; 
			// account card
			if (url.toLowerCase().match("https://www.gecapitalbank.co.uk/outfit/splash.htm")) w = 740, h = 570;
			// multimap
			else if (url.toLowerCase().match("multimap.com")) w = 800, h = 430;
			// voucher express
			else if (url.toLowerCase().match("voucherexpress.co.uk/VERSE/arcadia")) w = 790, h = 455;

			
			var attr = w ? "width=" + w + ",height=" + h + ",screenX=100,screenY=100,scrollbars=yes" : "toolbar=yes,location=yes,status=yes,menubar=yes,scrollbars=yes,resizable=yes";
			// open url in new window, focus and return false to cancel underlying link element action
			var win = window.open(url, Brand.popupWindowName, attr);
			// focus on the window in case it's already open
			win.focus();
			},
			
		// add validation function to forms
		addFormValidation : function() {
			var forms = Util.getElementsByClassName(Brand.formValidationClass);
			for (var i = 0; i < forms.length; i++) {
				forms[i].onsubmit = function() { return Behaviour.validateForm(this); }
				}
			},
			
		// attach toggle() function to a elements
		addToggles : function() {
			// get each a element that needs to toggle
			var links = Util.getElementsByClassName(Brand.toggleClass, "a"), force;
			// loop through each element...
			for (var i = 0; i < links.length; i++) { 
				// check if this link's toggle content contains an active static link
				// (use innerHTML in this case as a hidden link may be active)
	//			force = Util.hasClassName(links[i].parentNode, Brand.navActiveStaticClass) || links[i].parentNode.innerHTML.match(Brand.navActiveStaticClass);
				// toggle and cancel the user's click if this is a toggle link that should open instead of going to a page
	//			if (! Util.hasClassName(links[i], Brand.toggleForceClass)) {	
					// create anonymous function and bind to the onclick event for this element
					var func = function() { Behaviour.toggle(this); };
					Util.addEvent(links[i], "click", func);
					// cancel the user's click
					Util.addEvent(links[i], "click", Util.cancelClick);
	//				}
				// force open toggle if necessary (no need to add onload as addToggles is called onload)
	//			if (force) Behaviour.toggle(links[i], true);
				}
			},
			
		// add "show and hide" functionality to an element's content
		toggle : function(el, force) {
			// get this a element's parent element, plus the child elements that need to be toggled
			var parent = Util.$(el).parentNode, els = Util.getElementsByClassName(Brand.toggleContentClass, "", parent);
			// loop through each of the child elements...
			for (var i = 0; i < els.length; i++) {
				// if the child elements are hidden (or we need to force the elements to display at all times), set the visibility to "block"
				if (force || els[i].style.display != "block") els[i].style.display = "block";
				// otherwise we can hide each child element
				else els[i].style.display = "none";
				}
			},
		
		// validate form content
		validateForm : function(form) {
			// default values and reg expressions for validation
			var fieldValid = true, formValid = true, error = "", name = "", numeric = /^[0-9]*$/, date = /^\d{1,2}\/\d{1,2}\/\d{1,2}$/, 
				email = /^[0-9a-z]([-_.]?[0-9a-z])*@[0-9a-z]([-.]?[0-9a-z])*\.(([a-z][a-z])|org|mil|com|net|org|int|gov|biz|info|coop|museum|name|pro|aero)$/i;
			// get labels to use for alert box and all fields that are required
			var labels = form.getElementsByTagName("label"), fields = Util.getElementsByClassName(Brand.formValidationRequiredFieldClass, "", form);
			// loop through each of the fields...
			for (var i = 0; i < fields.length; i++) {
				// fail if no value provided or value has not been changed
				if (fields[i].value == "" || fields[i].value == fields[i].defaultValue) fieldValid = false;
				// we have a value to check so check it's numeric if required
				else if (Util.hasClassName(fields[i], Brand.formValidationNumericFieldClass) && numeric.test(fields[i].value) == false) fieldValid = false;
				// or check it's a valid email address
				else if (Util.hasClassName(fields[i], Brand.formValidationEmailFieldClass) && email.test(fields[i].value) == false) fieldValid = false;
				// or check it's a valid DD/MM/YY string
				else if (Util.hasClassName(fields[i], Brand.formValidationDateFieldClass) && date.test(fields[i].value) == false) fieldValid = false;
				// if the field is not valid...
				if (! fieldValid) {
					// loop through the labels and get the label text to add to the error message
					for (var j = 0; j < labels.length; j++) {	
						// consider use of childNode instead of innerHTML?
						if (labels[j].htmlFor == fields[i].id) { name = labels[j].innerHTML; break;	}
						}
					// compile the error message for the user
					error += "- " + name + "\n";
					// and flag the form as invalid
					formValid = false;
					}
				// reset the fieldValid value
				fieldValid = true;
				}
			// alert the user if the form is invalid and prevent form processing by returning false
			if (! formValid) {
				alert (Brand.formValidationMessage + "\n------------------------------------------------------------\n" + error);
				return false;
				}
			return true;
			}
	
		}

	// initiate extensions
	Util.addEvent(window, "load", Behaviour.init);
		
/* ]]> */