/*--------------------------------------------------
BASE-1.0.1 contains CONFIG, UKISA, UTIL, UKISA.FLASH, UKISA.WIDGET.MULTIMAP, MODAL, FORM, BASE, POLYCELL.SHOPPINGLIST
Generated: 29/3/2011
--------------------------------------------------*/
/** 
 * @fileOverview Site configuration and localisation
 * @author Oliver Bishop / Tom McCourt
 * @version 0.0.1
 */

/* This sets the global namespaces */
var UKISA = {Config: {}, locale: {}, widget: {}, util: {}, site: {}};


// Shorthand the YUI Selector method - ala jQuery.
var $ = $ || YAHOO.util.Selector.query;

/* Main configuration values */
UKISA.Config = {
	REGION: "EUK",
	CODE: "POL",
	SITE: "Polycell",
	domLoad: function() {
		var shoppingList = new UKISA.Polycell.ShoppingList();
		UKISA.util.clearDefault("search");

		UKISA.Polycell.Page.highlight();

		if (document.body.id === "home-page") {
			UKISA.Polycell.Page.home();
			UKISA.Polycell.Page.tooltips();
		}		

		if (document.body.id === "product-page") {
			shoppingList.attach();
		}		
		
		if (document.body.id === "category-page") {
			UKISA.Polycell.CategoryAccordian.init();
		}

		if (document.body.id === "visual-guide-page") {
			UKISA.Polycell.CategoryAccordian.visual();
		}

		if (document.body.id === "guide-page") {
			UKISA.Polycell.Guide.init();
			shoppingList.multiAttach();
		}
		

		// Footer Fix
		(function() {
			var Dom, Event, documentHeight, viewportHeight, footerHeight, headerHeight, adjustment, minHeight, ie;
	
			Dom = YAHOO.util.Dom;
			Event = YAHOO.util.Event;
			
			ie = YAHOO.env.ua.ie;

			// Set header and footer height.
			minHeight = 0;
			headerHeight = 188;
			footerHeight = 120;
			adjustment = 12; // Some space somewhere I can't find.

			resize = function() {
				// Get the viewport height.
				documentHeight = Dom.getDocumentHeight();
				viewportHeight = YAHOO.util.Dom.getViewportHeight();

				minHeight = viewportHeight - headerHeight - footerHeight - adjustment;

				if (minHeight > 0) {
					Dom.setStyle("body", "min-height", minHeight + "px");
			
					// Dirty.
					if (ie >= 6 && ie < 7) {
						Dom.setStyle("body", "height", minHeight + "px");
					}
				}
			};

			Event.addListener(window, "resize", resize);

			resize();
		})();
		//END Footer Fix
	},
		
	contentLoad: function() {
		
		//this adds a modal
		el = $("a.modal", "content");
		i = el.length;
		for (; i--;) { el[i].onclick = function() { UKISA.Polycell.Navigation.terms(this); return false; }; }
	
	}
};

/**
 * Create the localisation namespace
 */
UKISA.locale[UKISA.Config.SITE] = {};
/** 
 * @fileOverview Site configuration and localisation
 * @author Oliver Bishop / Tom McCourt
 * @version 1.12.0
 * @changeLog Added a method to create namespaces.
 */

/* This sets the global namespaces */
//var UKISA = {locale: {}, widget: {}, util: {}, site: {}};


/**
 * Code required to work with the configuration file. Contains a getter method for l10n, site code initialisation.
 */
(function() {
	/**
	 * This retrieves the localised value as specified by the key.
	 *
	 * @name get
	 * @memberOf UKISA.locale
	 * @param {String} key The variable that holds the localised data.
	 * @returns {?} Returns whatever is held against the key e.g. function, string, integer
	 */
	UKISA.locale.get = function(key) {
		var i, value;

		key = key.split(".");
		value = UKISA.locale[UKISA.env.SITE][key[0]];

		if (value) {
			for (i = 1, ix = key.length; i < ix; i++) {
				value = value[key[i]];
			}
			
			if (typeof value[UKISA.env.REGION] !== "undefined") {
				value = value[UKISA.env.REGION];
			}	
		}	

		return (value !== "undefined") ? value : null;
	};

	/**
	 * Create a namespace for the UKISA library.
	 *
	 * @example UKISA.namespace("UKISA.widget");
	 * @example UKISA.namespace("widget");
	 * @example UKISA.namespace("UKISA.widget", "UKISA.site");
	 * @example UKISA.namespace("UKISA.widget.Rollover");
	 */
	UKISA.namespace = function() {
		var a, o, i, j, d;

		a = arguments; 
		o = null;

		for (i = 0, ix = a.length;  i < ix; i++) {
			d = ("" + a[i]).split(".");
			o = UKISA;

			for (j = (d[0] == "UKISA") ? 1 : 0, jx = d.length; j < jx; j++) {
				o[d[j]] = o[d[j]] || {};
				o = o[d[j]];
			}
		}

		return o;
	};
	
	/**
	 * Manage Sitestat statistics.
	 */
	UKISA.Sitestat = {
		/**
		 * Make a call to the Sitestat server to register a page view.
		 */
		hit: function(qs) {
			var url, ns_0, ns_pixelUrl;

			// This checks that the site is "live" as is must have the sitestat function.
			// This stops polluting the stats with UAT data.

			if (typeof sitestat === "function") {
				
				if (typeof UKISA.env.SITESTAT !== "undefined") {
					url = "http://int.sitestat.com/ici-paints/" + UKISA.env.SITESTAT + "/s?" + qs;

					url += "&amp;ns__t=" + (new Date()).getTime();
					ns_pixelUrl = url;
					ns_0 = document.referrer;
					ns_0 = (ns_0.lastIndexOf("/") == ns_0.length - 1) ? ns_0.substring(ns_0.lastIndexOf("/"), 0) : ns_0;

					if(ns_0.length > 0) {
						url += "&amp;ns_referrer=" + escape(ns_0);
					}
					if(document.images){
						ns_1 = new Image();
						ns_1.src = url;
					} else {
						document.write('<img src="' + url + '" width="1" height="1" alt="" class="tracking" />');
					}
				} else {
					alert("Sitestat version or site name not known.");
				}
			}
		}
	};

	/**
	 * This is a periodic timer to test for the loading of the config file. Once it has been loaded, the timer is cancelled.
	 * This keeps the config file clean and will only be needed for uat as on production all the script is minified as one.
	 */
	UKISA.bootstrap = function() {
		// Assign the global code init as set in the config to YUI
		YAHOO.util.Event.onDOMReady(UKISA.env.onDOMReady);

		// Assign the global code init as set in the config to YUI
		YAHOO.util.Event.addListener(window, "load", UKISA.env.onLoad);

		// Create the site namespace
		UKISA[UKISA.env.SITE] = {};

	};

	// Look for the UKISA.env object which will be in scripts/config.js so this test to see if the page is loaded for example on UAT.
	// If it is available immediately then this script will be on production and all concatenated into one file.
	if (typeof UKISA.env !== "undefined") {
		UKISA.bootstrap();
	} else {
		// If the env object is not found then create a poll method to test for it until it is loaded.
		UKISA.loader = YAHOO.lang.later(
			10, 
			this, 
			function() {
				if (typeof UKISA.env !== "undefined") {
					UKISA.bootstrap();
					UKISA.loader.cancel();
				}
			},
			null,
			true
		);
	}

	/**
	 * A global message display for errors to the user or to us.
	 */
	 UKISA.notify = function(t) {
		alert("Message:" + t);
	 };

	/**
	 * Apply a new window.console incase Firebug is not loaded or IE is being used.
	 */
	if (!window.console) {
		window.console = {
			log: function(t) {
				var stack, item;

				stack = document.getElementById("window-console");
				
				if (!stack) {
					stack = document.createElement("ul");
					stack.id = "window-console";
					stack.setAttribute("style", "clear: both; font-weight: bold; font-size: 11px; border: dashed 1px red; border-bottom: none; list-style: none; width: 50%;");
					document.body.appendChild(stack);
				}

				item = document.createElement("li");
				item.setAttribute("style", "border-bottom: 1px dashed red; padding: 2px 5px;");
				item.innerHTML = t;
				stack.appendChild(item);
			},
			info: function() {}
		};
	}

})();/** 
 * @fileOverview Helper methods to refactor code and make life easier.
 * @author Tom McCourt / Oliver Bishop
 * @version 1.0.0
 */

var UKISA = UKISA || {util: {}};
/**
 * @namespace Helper methods.
 * @memberOf UKISA.utils
 */
UKISA.util = {
	/**
	 * Proxy for a PNG fix script. In this case BelatedPNGFix is used.
	 * @param {String} t Comma seperated list of element IDs to use to apply the PNG fix to.
	 */
	pngFix: function(t) {
		if (typeof DD_belatedPNG !== "undefined") {
			DD_belatedPNG.fix(t);
		} else {
			alert("Missing PNG handler");
		}
	},
	/** 
	 * Opens a system print dialogue box.
	 *
	 * @param {Boolean} Returns false;
	 */
	print: function() {
		if (window.print) {
			window.print();
		}
		return false;
	},
	/**
	 * Apply a class of "nth-child" to a frequency of a collection of items.
	 *
	 * @memberOf UKISA.utils
	 * @param {Object} list Collection of enumerable objects.
	 * @param {Integer} freq The nth item in the list to apply the class to.
	 */
	nthChild: function(list, freq) {
		for (var i = 0, ix = list.length; i < ix; i++) {
			if ((i + 1) % freq == 0) {
				YAHOO.util.Dom.addClass(list[i], "nth-child"); 
			} else {
				YAHOO.util.Dom.removeClass(list[i], "nth-child"); 
			}
		}
	},
	/**
	 * Clear the default text on a textbox when focus is gained.
	 *
	 * @memberOf UKISA.utils
	 * @param {String} Unlimited list of arguments for inputs to apply this to
	 */
	clearDefault: function () {
		var action = function(el) {
			if (!el) { return; }

			var defaultValue = el.value;

			el.onfocus = function() {
				var old = defaultValue;
				if (this.value === defaultValue) {
					this.value = "";
				}
			};

			el.onblur = function() {
				var old = defaultValue;
				if (this.value === "" || this.value === defaultValue) {
					this.value = old;
				}
			};
		};

		for (var i = 0, ix = arguments.length; i < ix; i++) {
			action(document.getElementById(arguments[i]));
		}
	},
	/**
	 * Gets the real parent node of an element, skipping inapporpriate node types e.g. whitespace as used in IE.
	 *
	 * @memberOf UKISA.utils
	 * @param {String|HTMLObject} el Element to find the parent node of.
	 * @returns {HTMLObject} The real parent node of the element.
	 */
	parentNode: function(el) {
		var e = (typeof el == "string") ? document.getElementById(el) : el;
		var node = null;
		if (e && e.parentNode) {
			while (e.parentNode.nodeType != 1) {
				e = e.parentNode;
				node = e;
			}
			return (!node) ? e.parentNode : node;
		}
	},
	/**
	 * Remove white space before or after a string
	 *
	 * @memberOf UKISA.utils
	 * @param {String} s String to trim white space from
	 * @return {String}	 Returns a clean string with white space removed
	 */
	trim: function(s) {
		return s.replace(/^\s+|\s+$/g, "");
	},
	/**
	 * Get the scroll position of the document.
	 *
	 * @memberOf UKISA.utils
	 * @deprecated Use the YAHOO.util.Dom.getDocumentScrollLeft(), YAHOO.util.Dom.getDocumentScrollTop() instead.
	 * @return {Array}	 Array [0] is the left scroll in pixels, [1] is the top scroll in pixels.
	 */
	getScrollXY: function() { // Get scroll position of page
		var scrOfX = 0, scrOfY = 0;
		if(typeof(window.pageYOffset) === "number") {
			//Netscape compliant
			scrOfY = window.pageYOffset;
			scrOfX = window.pageXOffset;
		} else if(document.body && (document.body.scrollLeft || document.body.scrollTop)) {
			//DOM compliant
			scrOfY = document.body.scrollTop;
			scrOfX = document.body.scrollLeft;
		} else if(document.documentElement && (document.documentElement.scrollLeft || document.documentElement.scrollTop)) {
			//IE6 standards compliant mode
			scrOfY = document.documentElement.scrollTop;
			scrOfX = document.documentElement.scrollLeft;
		}
		return [scrOfX, scrOfY];
	}
};/**
 * @namespace The contains methods to control and write Flash objects.
 */

//var UKISA = UKISA || {Flash: {}};

UKISA.Flash = {
	_baseUrl: "/web/media/flash/",
	_supportedVersion: "8.0.0",
	_flashVersion: null,
	_defaultVars: {},
	_defaultParams: {
		"quality": "high",
		"pluginspage": "http://www.macromedia.com/go/getflashplayer",
		"wmode": "transparent"
	},
	/**
	 * This can be placed in the HEAD tag to be called to replace an HTML container without using the NOSCRIPT tag option and uses the SWFObject plugin.
	 *
	 * @requires SWFObject
	 * @param {String} el The container to replace.
	 */
	embed: function(movie, el, width, height, vars, params, version) {
		if (movie.toLowerCase().indexOf(".flv") !== -1) {
			return this.embedVideo(movie, el, width, height, vars, params, version);
		} else {
			return this.embedMovie(movie, el, width, height, vars, params, version);
		}
	},
	embedMovie: function(movie, el, width, height, vars, params, version) {
		var ver, vars, params;

		ver = version || this._supportedVersion;
		fVars = vars || this._defaultVars;
		fParams = params || this.defaultParams;

		if (typeof swfobject !== "undefined") {
			swfobject.embedSWF(this._baseUrl + movie, el, width, height, this._supportedVersion, null, fVars, fParams);
		} else {
			alert("Missing Flash handler script");
		}
	},
	embedVideo: function(movie, el, width, height, vars, params, version) {
		var ver, height, width, vars, params;

		ver = version || this._supportedVersion;
		height = height || 400;
		width = width || 400;

		fVars = vars || {
			"MM_ComponentVersion": "1",
			"skinName": "/web/media/flash/Halo_Skin_3",
			"streamName": "/web/media/movies/" + movie.substring(0, movie.indexOf(".")),
			"autoPlay": "true",
			"autoRewind": true
		};

		fParams = params || {
			"quality": "high",
			"scale": "noscale",
			"pluginspage": "http://www.macromedia.com/go/getflashplayer",
			"wmode": "transparent"
		};

		if (typeof swfobject !== "undefined") {
			swfobject.embedSWF("/web/media/flash/flv_player.swf", el, width, height, ver, null, fVars, fParams);
		} else {
			alert("Missing Flash handler script");
		}
	},
	/**
	 * Safely removes a Flash movie from the page.
	 * @param {String} el Flash placeholder.
	 */
	remove: function(el) {
		swfobject.removeSWF(el);
	}
};var UKISA = UKISA || {};
UKISA.widget = UKISA.widget || {};

/** 
 * Create and manage a MultiMap viewer
 */
UKISA.widget.MultiMap = {
	_viewer: null,
	_country: "GB",
	/**
	 * Recreates a MM viewer according to postcode and applies alt text.
	 * @param {String} canvas		The ID of the element to attach the MM viewer to.
	 * @param {String} postcode		The postcode to zero in to.
	 * @param {String} label		Alt text to apply to a location marker.
	 */
	reload: function(canvas, postcode, label) {
		var instance = this;

		var geocode = function(type, target, location, error_code) {
			var pan_zoom_widget, pos, icon;

			pos = instance._viewer.getCurrentPosition(); 
			icon = new MMIcon("/web/media/images/global/location.png");

			icon.iconSize = new MMDimensions( 32, 32 );
			icon.iconAnchor = new MMPoint( 16, 16 );
			instance._viewer.createMarker( pos, {'label': label, 'icon' : icon});

			pan_zoom_widget = new MMPanZoomWidget ();
			instance._viewer.addWidget ( pan_zoom_widget );
		};

		var canvas = document.getElementById(canvas);

		if (canvas) {
			this._viewer = new MultimapViewer(canvas);
			this._viewer.addEventHandler("endGeocode", geocode);
		}

		this._viewer.drawAndPositionMap(
			new MMLocation(
				new MMAddress(
					{
						postal_code: postcode, 
						country_code: this._country
					}
				) 
			) 
		);
	},
	/**
	 * Position a MM viewer according to postcode and apply alt text.
	 * @param {String} canvas		The ID of the element to attach the MM viewer to.
	 * @param {String} postcode		The postcode to zero in to.
	 * @param {String} label		Alt text to apply to a location marker.
	 */
	load: function(canvas, postcode, label) {
		var instance = this;

		var geocode = function(type, target, location, error_code) {
			var pan_zoom_widget, pos, icon;

			pos = instance._viewer.getCurrentPosition(); 
			icon = new MMIcon("/web/media/images/global/location.png");

			icon.iconSize = new MMDimensions( 32, 32 );
			icon.iconAnchor = new MMPoint( 16, 16 );
			instance._viewer.createMarker( pos, {'label': label, 'icon' : icon} );

			pan_zoom_widget = new MMPanZoomWidget ();
			instance._viewer.addWidget ( pan_zoom_widget );
		};

		var canvas = document.getElementById(canvas);

		if (!this._viewer || canvas) {
			this._viewer = new MultimapViewer(canvas);
			this._viewer.addEventHandler("endGeocode", geocode);
		}

		this._viewer.drawAndPositionMap(
			new MMLocation(
				new MMAddress(
					{
						postal_code: postcode, 
						country_code: this._country
					}
				) 
			) 
		);
	}
};/**
 * @namespace This contains generic methods to create a uniform style for modals.
 * @author Tom McCourt / Oliver Bishop
 * @version 0.0.2
 * @changeLog Add an ajax load page function.
 * @changeLog Added a check to make sure only same id containers are visible toggled. New id modals are created from scratch.
 * @changeLog Created.
 */

UKISA.namespace("UKISA.widget.Modal");

/**
 * Global dialog templates that use YUI Container widgets to allow a consistent look of the site.
 */
UKISA.widget.Container = null;

/**
 * Create a modal instance.
 *
 * @returns YAHOO.widget.Panel Returns a YAHOO.widget.Panel instance.
 * @example 
 * var modal = new UKISA.widget.Modal("my-id", "Some content");
 * modal.show();
 */
UKISA.widget.Modal = function(id, content, options) {
	var panel, hd, bd, ft, container, loader, body, ajax, container;

	panel = document.getElementById(id);

	container = UKISA.widget.Container;

	// This is a default content placeholder - simply has a "loading" message.
	loader = function() {
		var a = document.createElement("p");
		a.id = id + "-loading";
		a.className = "loading";
		a.innerHTML = "Please wait...";

		return a;
	};

	body = content || loader();

	if (panel && container && (id === container.id)) {
		container.setBody(body);

		return container;
	} else {
		// If the id's do not match then we may be dealing with a different style, so reset it.
		if (container && id !== container.id) {
			container.hide();
			container.destroy();
		}

		// This creates the custom shadow around the Panel box.
		panel = document.createElement("div");

		hd = panel.cloneNode(false);
		bd = panel.cloneNode(false);
		ft = panel.cloneNode(false);

		panel.id = id;
		panel.className = "yui-panel-container yui-dialog shadow";
		hd.className = "hd";
		bd.className = "bd";
		ft.className = "ft";

		panel.appendChild(hd);
		panel.appendChild(bd);
		panel.appendChild(ft);

		document.body.appendChild(panel);

		UKISA.widget.Container = new YAHOO.widget.Panel(id, { 
			fixedcenter: true,
			modal: true,
			visible : false,	
			close: true,
			underlay: "shadow",
			constraintoviewport: true,
			zIndex: 500,
			autofillheight: "body"
		});
		
		container = UKISA.widget.Container;
		
		container.changeBodyEvent.subscribe(function(e) {
			if (typeof UKISA.util.FR !== "undefined") {
				UKISA.util.FR();
			}

			var videoSrc = document.getElementById("video-src");

			if (videoSrc) {
				UKISA.Flash.embed(videoSrc.value, "video-player", 534, 339);
			}
                                   
		});

		container.hideEvent.subscribe(function(e) {
			//this.element.style.display = "none";
			swfobject.removeSWF("video-player");
		});

		container.showEvent.subscribe(function(e) {
			//this.element.style.display = "";

			
		});

		container.setBody(body);

		container.render(document.body);

		// Add some extra functionality.
		container.load = function(type, url, callback, qs) {
			callback = callback || {
				success: function(o) {
					container.setBody(o.responseText);
				}, 
				failure: function(o) {
					container.setBody([
						'<p class="error">',
							'Sorry, there was a problem when trying to fetch something. Please close this down and try again.',
						'</p>'
					].join(""));
				}, 
				timeout: 5000
			};

			this.ajax = YAHOO.util.Connect.asyncRequest(type, url, callback, qs);
		};

		return container;
	}
};/** 
 * @fileOverview Form management/validation
 * @author Oliver Bishop / Tom McCourt
 * @version 0.0.1
 */

/**
 * Puts the cursor focus on the field that did not pass validation.
 *
 * @param {HTMLObject} field The field that did not validate.
 */
function highlightField(field) {
	field.focus();
	if (field.select) {
		field.select();
	}
}

/**
 * Raised when a field input fails validation. This calls highlightField and raises an alert.
 *
 * @see highlightField
 * @param {HTMLObject} field	The field that did not validate.
 * @param {String} msg			Error message to display.
 * @returns {Boolean}			Return FALSE to prevent form submission.
 */
function fieldError(field, msg) {
	if (field) {
		highlightField(field);
	}
	alert(msg);
	return false;
}

/**
 * Validation that checks for numbers.
 *
 * @returns {Boolean} Validation result.
 */
function hasNumbers(str) {
	var exp = new RegExp("[0-9]");
	return exp.test(str);
}

/**
 * Validation that checks at least one radio button being checked.
 *
 * @returns {Boolean} Validation result.
 */
function isRadiogroupChecked(radioGroup) {
	for (var i=0;i<radioGroup.length;i++) {
		if (radioGroup[i].checked) {
			return true;
		}
	}
	return false;
}

/**
 * Validation that checks that the value is a number (float).
 *
 * @returns {Boolean} Validation result.
 */
function isNumeric(str) {
	var num=parseFloat(str);
	return (!isNaN(num)||str=="");
}

/**
 * Validation that checks that the value is an integer without a decimal point.
 *
 * @returns {Boolean} Validation result.
 */
function isInteger(str) {
	var num=parseInt(str);
	return (str.indexOf(".")<0 && (!isNaN(num)||str==""));
}

/**
 * Validation that checks that the value is a phone number.
 *
 * @returns {Boolean} Validation result.
 */
function isPhoneNumber(str) {
	var exp = new RegExp("^[0-9 ]*$");
	return exp.test(str);
}

/**
 * Validation that checks that a number is within a range or values.
 *
 * @returns {Boolean} Validation result.
 */
function inRange(num, lower, upper) {
	if (isNaN(num)) {
		num=0;
	}
	return (num>=lower&&num<=upper);
}

/**
 * Validation that checks that the value only contains alpha characters.
 *
 * @returns {Boolean} Validation result.
 */
function isAlpha(str) {
	var exp = new RegExp("[^A-Za-z]");
	return !exp.test(str);
}

/**
 * Validation that checks  that the value only contains alphanumeric characters.
 *
 * @returns {Boolean} Validation result.
 */
function isAlphaAndNumeric(str) {
	var exp = new RegExp("[^A-Za-z0-9]");
	return !exp.test(str);
}

/**
 * Trims all whitespace from user input.
 *
 * @returns {String} The trimmed value.
 */
function trimSpaces(str) {
	return str.replace(/\s+/g, "");
}

/**
 * Trims whitespace from the start and end of a value.
 *
 * @returns {String} The trimmed value.
 */
function trimOutsideSpaces(str) {
	return str.replace(/^\s+|\s+$/g, "");
}

/**
 * Validation that that a value is in the correct sequence.
 *
 * @returns {Boolean} Validation result.
 */
function isValidSequence(str, validSequence) {
	// is this correct - need to test
	var exp = new RegExp("[^" + validSequence + "]");
	return !exp.test(str);
}

/**
 * Validation that checks the the value is a valid email.
 *
 * @returns {Boolean} Validation result.
 */
function isEmail(str) {
	str = trimOutsideSpaces(str.toLowerCase());
	var exp = new RegExp(/^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[(2([0-4]\d|5[0-5])|1?\d{1,2})(\.(2([0-4]\d|5[0-5])|1?\d{1,2})){3} \])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/);
	return exp.test(str);
}

/**
 * Checks that a value has been selected from a drop down.
 *
 * @returns {Boolean} Validation result.
 */
function isValueSelected(field) {
	return (field.options[field.selectedIndex].value!="");
}

/**
 * Validates a postcode.
 *
 * @returns {Boolean} Validation result.
 */
function validatePostCode(field, combo, partial) {
	// drop out if not a UK postcode
	if(((combo) && combo.options[combo.options.selectedIndex].value!="United Kingdom")) {
		return true;
	}
	var str = trimSpaces(field.value.toUpperCase());
	
	// check if field filled
	if (str.length==0) {
		return fieldError(field, "Please enter a postcode.");
	}
	
	// check if its alphanumeric
	if (!isAlphaAndNumeric(str)) {
		return fieldError(field, "Please enter a valid UK postcode (containing both letters and numbers).");
	}
	
	// check postcode formatting
	var exp = (partial&&partial==true)?new RegExp("^[A-Z]{1,2}([0-9]{1,2}|[0-9][A-Z])($|[0-9][ABD-HJLNP-UW-Z]{2}$)"):new RegExp("^[A-Z]{1,2}([0-9]{1,2}|[0-9][A-Z])[0-9][ABD-HJLNP-UW-Z]{2}$");
	
	// need to disable this final validation because NS4 doesn't evalute regexp properly
	if (!exp.test(str)&&!document.layers) return fieldError(field, "Please enter a valid UK postcode.");
	else return true;
}

/**
 * Gets the number of days in a specified month.
 *
 * @returns {Integer} Number of dats in the year.
 */
function getDays(month, year) {
	var monthDays = new Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
	monthDays[1] = (year % 4 == 0 && year % 100 != 0 || year % 400 ==0)?monthDays[1]+1:monthDays[1];
	return monthDays[month-1];
}

/**
 * Validates a date of birth. 
 *
 * @returns {Boolean} Validation result.
 */
function validateDateOfBirth(day, month, year) {
	var dayStr = trimSpaces(day.value);
	var monthStr = trimSpaces(month.value);
	var yearStr = trimSpaces(year.value);
	var theDate = new Date();
	// check if fields filled
	if (dayStr.length==0||monthStr.length==0||yearStr.length==0) {
		return fieldError(day, "Please complete your full date of birth.");
	}
	// check if they are all individually valid
	if (!(isNumeric(yearStr)&&inRange(parseInt(yearStr), 1849, theDate.getFullYear()))) {
		return fieldError(year, "Please give a valid year.  It may not be before 1849 or after the present year.");
	}
	if (!(isNumeric(monthStr)&&inRange(parseInt(monthStr), 1, 12))) {
		return fieldError(month, "Please give a valid month (1 - 12).");
	}
	var daysInMonth = getDays(parseInt(monthStr), parseInt(yearStr));
	if (!(isNumeric(dayStr)&&inRange(parseInt(dayStr), 1, daysInMonth))) {
		return fieldError(day, "Please give a valid day.");
	}
	// check its not in the future
	var DOB = new Date(parseInt(yearStr), parseInt(monthStr) - 1, parseInt(dayStr));
	if (DOB>=theDate) {
		return fieldError(day, "Please give a date of birth that is not in the future.");
	}
	return true;
}
/** 
 * @fileOverview Standard site functionality
 * @author Oliver Bishop / Tom McCourt
 * @version 0.0.1
 */

/**
 * Code required to work with the configuration file. Contains a getter method for l10n, site code initialisation.
 *
 * @name PreInit
 */
(function() {
	/**
	 * This retrieves the localised value as specified by the key.
	 *
	 * @name get
	 * @memberOf UKISA.l10n
	 * @param {String} key The variable that holds the localised data.
	 * @returns {?} Returns whatever is held against the key e.g. function, string, integer
	 */
	UKISA.locale.get = function(key) {
		var value = UKISA.locale[UKISA.Config.SITE][key][UKISA.Config.REGION];
		return (value !== "undefined") ? value : null;
	};

	// Assign the global code init as set in the config to YUI
	YAHOO.util.Event.onDOMReady(UKISA.Config.domLoad);

	// Assign the global code init as set in the config to YUI
	YAHOO.util.Event.addListener(window, "load", UKISA.Config.contentLoad);

	// Create the site namespace
	UKISA[UKISA.Config.SITE] = {};
})();


UKISA.Polycell.Page = {
	/**
	 * @namespace Uses this breadcrumbs as a guide to highlight the corresponding navigation category tab.
	 *
	 * @function
	 */
	highlight: function() {
		// Use object detection for IE - to use instead of :hover for an LI element
		if (document.all && document.getElementById) {
			
			var nav = document.getElementById("nav");
			if (!nav) { return; }

			var list = nav.getElementsByTagName("ul");
			if (!list) { return; }

			for (var i = 0, ix = list[0].childNodes.length; i < ix; i++) {
				var node = list[0].childNodes[i];
				if (node.nodeName.toLowerCase() === "li") {
					node.onmouseover = function() {
						
						this.className += " hover";
					};
					node.onmouseout = function() {
						this.className = this.className.replace(" hover", "");
					};
				}
			}
		}
	},

	/**
	 * Create an IE6 hover state.
	 */
	home: function() {
		if (document.all && document.getElementById) {
		
			var nav = document.getElementById("product-selector");
			if (!nav) { return; }

			nav.onmouseover = function() {
				this.className = "hover";
			};
			nav.onmouseout = function() {
				this.className = "";
			};
		}
	},
	/**
	 * Embed flash movies on the home page featured item.
	 *
	 * @param {Boolean} FALSE
	 */
	player: function(movie, el, sizex, sizey, emptyContainer) {
		var vars, element;

		element = el || "featured-player-static";

		vars = {
			"MM_ComponentVersion": "1",
			"skinName": "/web/media/flash/Clear_Skin_1",
			"streamName": "/web/media/movies/" + movie.substring(0, movie.indexOf(".")),
			"autoPlay": "true",
			"autoRewind": true
		};

		if(sizex && sizey){
			UKISA.Flash.embed(movie, element, sizex, sizey, vars);
		}else{
			UKISA.Flash.embed(movie, element, 272, 153, vars);
		}

		return false;
	},
	/**
	 * Create the home page guide tooltips.
	 */
	tooltips: function() {
		var canvas, links, tooltip;

		canvas = document.getElementById("guide-finder");
		if (!canvas) { return; }

		canvas = canvas.getElementsByTagName("ul");
		if (!canvas) { return; }

		canvas = canvas[0];
		links = canvas.getElementsByTagName("a");

		tooltip = new YAHOO.widget.Tooltip("video-tooltip", { 
			context: links,
			effect: {
				effect: YAHOO.widget.ContainerEffect.FADE,duration:0.20
			},
			width: 218,
			zIndex: 150
		});
		tooltip.setHeader("");
		tooltip.setFooter("");
		tooltip.contextMouseOverEvent.subscribe( 
			function(type, args) {
				var context = args[0];
				if (context && context.id === "B3") {
					return false;
				} else {
					return true;
				}	
			}
		);

		// Set the text for the tooltip just before we display it.
		tooltip.contextTriggerEvent.subscribe(
			function(type, args) {
				var context = args[0];
				this.cfg.setProperty("text", context.title);
			}
		);

		// Overide the moveTo function to provide an offset for the speach bubble
		tooltip.moveTo = function(x, y) {
			this.cfg.setProperty("xy", [x - 43 ,y - this.element.offsetHeight]); 
		};
	}
};

UKISA.Polycell.Guide = {
	/**
	 * Initialise for all How to... pages.
	 */
	init: function() {
		var bookmarker = new YAHOO.dulux.co.uk.Widgets.Bookmarker();
		this.related();
		this.equalise();
	},
	/**
	 * Easily add a <span> to each link in the related links panel to add an arrow as per the design.
	 */
	related: function() {
		var canvas, link, i, ix, span;

		canvas = document.getElementById("related-articles");

		if (!canvas) { return; }

		link = canvas.getElementsByTagName("a");

		span = document.createElement("span");
		span.className = "direct";

		for (i = 0, ix = link.length; i < ix; i++) {
			link[i].appendChild(span.cloneNode(false));	
		}
	},
	/**
	 * Fix to force shopping lsit items to line up to have the correct height.
	 */
	equalise: function() {
		var canvas, items, columns, maxHeight, height, store, item;

		var canvas = document.getElementById("guide-shopping-list");
		if (!canvas) { return; }
		list = canvas.getElementsByTagName("ul");
		if (!canvas && !canvas.length) { return; }
		canvas = list[0];

		items = canvas.getElementsByTagName("li");
		columns = 4;
		maxHeight = 0;
		height = 0;
		store = [];

		for (var i = 0, ix = items.length; i < ix; i++) {
			item = items[i];
			store.push(item);
			height = item.offsetHeight;

			if (height > maxHeight) {
				maxHeight = height;
			}

			if (store.length === columns) {
				for (j = 0, jx = store.length; j < jx; j++) {
					store[j].style.height = maxHeight + "px";
				}
				store = [];
				maxHeight = 0;
			}
			
			if (i + 1 === items.length) {
				for (j = 0, jx = store.length; j < jx; j++) {
					store[j].style.height = maxHeight + "px";
				}
			}
		}
	}
};

UKISA.Polycell.CategoryAccordian = {
	/**
	 * Create an accordian display for the category page.
	 */
	init: function() {
		var category = document.getElementById("category-list");

		if (!category) { return; }

		// Hide all the content DIVs
		var content = category.getElementsByTagName("div");

		for (var i = 0, ix = content.length; i < ix; i++) {
			var contentClassName = content[i].className;

			if (contentClassName.indexOf("parent-category-content") !== -1 || contentClassName.indexOf("child-category-content") !== -1) {
				if (contentClassName.indexOf("active") === -1) {
					content[i].style.display = "none";	
				} else {
					container = YAHOO.util.Dom.getPreviousSibling(content[i]);
					container.className = "active";
				}
			}
		}

		var h2 = category.getElementsByTagName("h2");

		for (var i = 0, ix = h2.length; i < ix; i++) {

			h2[i].onclick = function() {

				var content = category.getElementsByTagName("div");

				var active = (this.nextSibling.nodeType !== 1) ? this.nextSibling.nextSibling : this.nextSibling;

				var state = active.style.display;

				for (var i = 0, ix = content.length; i < ix; i++) {
					if (content[i].className === "parent-category-content") {
						content[i].style.display = "none";
					}
				}
				
				for (var i = 0, ix = h2.length; i < ix; i++) {
					h2[i].className = "";
				}

				
				if (state === "block") {
					active.style.display = "none";		
					this.className = "";
				} else {
					active.style.display = "block";
					this.className = "active";
				}
				return false;
			};
		}

		var h3 = category.getElementsByTagName("h3");

		for (var i = 0, ix = h3.length; i < ix; i++) {

			h3[i].onclick = function() {	
				
				var content = category.getElementsByTagName("div");		
				
				var active = (this.nextSibling.nodeType !== 1) ? this.nextSibling.nextSibling : this.nextSibling;

				var state = active.style.display;

				for (var i = 0, ix = content.length; i < ix; i++) {
					if (content[i].className === "child-category-content") {
						content[i].style.display = "none";
					}
				}
				
				for (var i = 0, ix = h3.length; i < ix; i++) {
					h3[i].className = "";
				}

				if (state === "block") {
					active.style.display = "none";	
					this.className = "";	
				} else {
					active.style.display = "block";
					UKISA.Polycell.CategoryAccordian.equalise(active);
					this.className = "active";
				}
				return false;
			};
		}
	},
	/**
	 * Basic accordian script for the category page.
	 */
	visual: function() {
		var category = document.getElementById("visual-guide-list");

		if (!category) { return; }

		// Hide all the content DIVs
		var content = category.getElementsByTagName("div");

		for (var i = 0, ix = content.length; i < ix; i++) {
			var contentClassName, container;
			contentClassName = content[i].className;

			if (contentClassName.indexOf("parent-category-content") !== -1 || contentClassName.indexOf("child-category-content") !== -1) {
				if (contentClassName.indexOf("active") === -1) {
					content[i].style.display = "none";	
				} else {
					container = YAHOO.util.Dom.getPreviousSibling(content[i]);
					container.className = "active";
				}
			}
		}

		var h2 = category.getElementsByTagName("h2");

		for (var i = 0, ix = h2.length; i < ix; i++) {

			h2[i].onclick = function() {

				var content = category.getElementsByTagName("div");

				var active = (this.nextSibling.nodeType !== 1) ? this.nextSibling.nextSibling : this.nextSibling;

				var state = active.style.display;

				for (var i = 0, ix = content.length; i < ix; i++) {
					if (content[i].className == "parent-category-content") {
						content[i].style.display = "none";
					}
				}
				
				for (var i = 0, ix = h2.length; i < ix; i++) {
					h2[i].className = "";
				}

				if (state === "block") {
					active.style.display = "none";		
					this.className = "";
				} else {
					active.style.display = "block";
					this.className = "active";
				}
				return false;
			};
		}
	},
	/**
	 * Force the products in the category page to line up properly.
	 */
	equalise: function(target) {
		var canvas, items, columns, maxHeight, height, store;

		var canvas = target.getElementsByTagName("ul");

		if (!canvas && !canvas.length) { return; }

		canvas = canvas[0];
		items = canvas.getElementsByTagName("li");
		columns = 4;
		maxHeight = 0;
		height = 0;
		store = [];

		for (var i = 0, ix = items.length; i < ix; i++) {
			var item = items[i];

			if(item.className.indexOf("product") !== -1) {
				store.push(item);
				height = item.offsetHeight;
				if (height > maxHeight) {
					maxHeight = height;
				}
				if (store.length === columns) {

					for (j = 0, jx = store.length; j < jx; j++) {
						store[j].style.height = maxHeight + "px";
					}
					store = [];
					maxHeight = 0;
				}
			}

			if (i + 1 == items.length) {
				for (j = 0, jx = store.length; j < jx; j++) {
						store[j].style.height = maxHeight + "px";
				}
			}
		}
	}
};

UKISA.Polycell.Stockist = {
	canvas: null,
	/**
	 * Stockist search.
	 *
	 * @param {HTMLObject} e The form.
	 * @returns {Boolean} False.
	 */
	search: function(e) {
		var callback, transaction, canvas, field, error, validatePostCode;

		// First check that this is on the index page
		if (document.body.id !== "stockist-search-page") {
			return true;
		}

		validatePostCode = function (field) {

			var str = field.value.toUpperCase().replace(/ /g, "");

			var exp = new RegExp("[0-9]");

			if (exp.test(str)) {
				return true;
			}

			// check postcode formatting
			var exp = new RegExp("^[A-Z]{1,2}([0-9]{1,2}|[0-9][A-Z])[0-9][ABD-HJLNP-UW-Z]{2}$");

			// need to disable this final validation because NS4 doesn't evalute regexp properly
			if (!exp.test(str)) {
				return false;
			} else {
				return true;
			}
		}

		// Validation
		field = e["pc"];

		if (validatePostCode(field)) {
			return true;
		}

		error = document.getElementById("stockist-search-error"); 

		if (field && field.value.length === 0) {
			if (!error) {
				error = document.createElement("p");
				error.id = "stockist-search-error";
				error.className = "error";
				error.innerHTML = "Please enter a postcode or location";
				e.insertBefore(error, e.getElementsByTagName("fieldset")[0]);			
			} 
			return false;
		} else { 
			if (error) {
				e.removeChild(error);
			}
		}

		if (!this.canvas) {
			this.canvas = document.createElement("div");
			document.getElementById("content").appendChild(this.canvas);
		}

		this.canvas.innerHTML = "<p class=\"ajax-loader\">Please wait</p>";
		canvas = this.canvas;
		
		callback = {
			success: function(o) {
				canvas.innerHTML = o.responseText;
			},
			failure: function(o) {
				canvas.innerHTML = "<p class=\"error\">Sorry, there is a problem and we apologise for any inconvenience caused. Please try again.</p>";
			},
			timeout: 8000
		};	
		
		YAHOO.util.Connect.setForm(e);	
		transaction = YAHOO.util.Connect.asyncRequest("POST", e.getAttribute("action") + "?ajax=true", callback);

		YAHOO.util.Event.preventDefault(e); 

		return false;
	},
	/**
	 * Get the search results for the area or postcode.
	 */
	result: function() {
		var canvas, items, i;

		canvas = document.getElementById("stockist-results");

		if (!canvas) { return; }

		items = canvas.getElementsByTagName("li");

		for (i = 0, ix = items.length; i < ix; i++) {
			YAHOO.util.Event.addListener(items[i], "click", function(e) {
				var link = this.getElementsByTagName("a");

				YAHOO.util.Event.preventDefault(e); 
				if (link && link.length) {
					UKISA.Polycell.Stockist.map(link[0]);
				}
				return false;
			});
		}
	},
	/**
	 * Get the map and stockist address details.
     *
	 * @returns {Boolean} FALSE
	 */
	map: function(e) {
		var callback, transaction, canvas, aside;;

		if (!this.canvas) {
			this.canvas = document.getElementById("stockist-content");
			if (!this.canvas) {
				this.canvas = document.createElement("div");
				this.canvas.id = "stockist-content";

				aside = document.getElementById("content");
				aside.appendChild(this.canvas);
			}
		}
	
		this.canvas.innerHTML = "<p class=\"ajax-loader\">Please wait</p>";
		canvas = this.canvas;

		callback = {
			success: function(o) {
				var url, match, postcode, storeName, span, item, i;

				// Show the new map
				canvas.innerHTML = o.responseText;

				// Get the postcode
				url = decodeURI(e.getAttribute("href"));
				match = url.match(/pc=([a-zA-Z0-9 ]*)/);
				postcode =  RegExp.$1;

				// Get the store name
				span = e.getElementsByTagName("span");
				if (span && span.length) {
					storeName = span[0].innerHTML;
				} else {
					storeName = "Polycell stockist";
				}

				// Remove old active classes
				item = document.getElementById("stockist-results").getElementsByTagName("li");

				for (i = 0, ix = item.length; i < ix; i++) {
					YAHOO.util.Dom.removeClass(item[i], "active"); 
				}

				// Get the li to apply a selected class
				item = UKISA.util.parentNode(UKISA.util.parentNode(UKISA.util.parentNode(e)));

				YAHOO.util.Dom.addClass(item, "active"); 

				stockistMap = new UKISA.site.GMaps("stockist-map");
				stockistMap.clearMarkers();
				stockistMap.addMarker(postcode.replace(/ /g,  "")); 
				
			},
			failure: function(o) {
				canvas.innerHTML = "<p class=\"error\">Sorry, there is a problem and we apologise for any inconvenience caused. Please try again.</p>";
			},
			timeout: 8000
		};	

		// Replace store with accountRef to allow the script to behave as it usually does without looping through a whole set
		transaction = YAHOO.util.Connect.asyncRequest("GET", e.getAttribute("href").replace("store", "accountRef") + "&ajax=true", callback);

		return false;
	}
};


UKISA.Polycell.Navigation = {
	/**
	 * Use object detection for IE - to use instead of :hover for an LI element
	 */
	fixIE: function() {
		var items, i, ix, node;
		if (document.all && document.getElementById) {

			items = YAHOO.util.Selector.query("> ul > li", "nav");

			for (i = 0, ix = items.length; i < ix; i++) {
				node = items[i];
				node.onmouseover = function() {	
					this.className += " hover";
				};
				node.onmouseout = function() {
					this.className = this.className.replace(" hover", "");
				};
			}
		}
	},
	/**
	 * Create a modal box for the videos.
	 */
	terms: function(o) {
		var modal, load, success, failure, callback, link;

		// Used for closures;
		link = o;

		load = function() {
			var a = document.createElement("div");
			a.id = "terms-modal";
			a.className = "busy";

			var b = document.createElement("p");
			b.innerHTML = "Please wait&hellip;";

			a.appendChild(b);

			return a;
		};

		success = function(text) {
			var a = document.createElement("div");
			a.id = "terms-modal";
			a.innerHTML = text;
		
			return a;
		};

		var failure = function() {
			var a = document.createElement("div");
			a.id = "add-to-basket-modal";

			var b = document.createElement("p");
			b.className = "error";
			b.innerHTML = "Sorry, there was a problem and we could not fetch the page for you.";

			a.appendChild(b);

			return a;
		};
		
		modal = new UKISA.widget.Modal("video-modal", load());
		modal.show();
		
		callback = {
			success: function(o) {
				var q;

				var footer = [
					"<p class=\"print-modal\">",
						"<a class=\"print\" href=\"#\" onclick=\"return UKISA.util.print('printable');\">Print</a>",
					"</p>"
				];

				modal.setBody(success(o.responseText));
				modal.setFooter(footer.join(""));

				q = YAHOO.util.Selector.query("h1, h2, h3", "ukisa-modal");
				if (q && typeof Cufon !== "undefined") {
					Cufon.replace(q);
				}
			},
			failure: function(o) {
				modal.setBody(failure());
			}
		};	

		// Send the Ajax request.
		ajax = YAHOO.util.Connect.asyncRequest("GET", o.href, callback);

		return false;
	}
};/** 
 * @fileOverview Floating notebook
 * @author Tom McCourt / Oliver Bishop
 * @version 1.0.0
 */

/**
 * Shopping list funtionality - ajaxed add-to-list, floating list.
 */
UKISA.Polycell.ShoppingList = function() {	
	this.init();
};

UKISA.Polycell.ShoppingList.prototype = {
	init: function() {
		this.config = {
			offsetY: 12,
			startY: 114,
			minWidth: 700,
			duration: .5
		};

		this.note = {
			anim: null
		};

		this.tab = {
			anim: null,
			state: true
		};
		
		var tab = document.getElementById("notebook-tab");
		if (tab) {
			var instance = this;

			YAHOO.util.Event.addListener(tab, "click", this.toggle, null, this);  
			this.tab.anim = new YAHOO.util.Anim("notebook-body");
			this.tab.anim.duration = .3;
			this.tab.anim.method = YAHOO.util.Easing.  easeOut ;
			this.tab.anim.onComplete.subscribe(function() {
				instance.tab.state = !instance.tab.state;
			});
		}
	
		// Position it for the page load
		this.move();

		// Attach the event
		YAHOO.util.Event.addListener(window, "scroll", this.move, null, this);  
		YAHOO.util.Event.addListener(window, "resize", this.resize);  
	},
	toggle: function() {
		var start = (this.tab.state) ? 169 : 0;
		var finish = (this.tab.state) ? 0 : 169;

		this.tab.anim.attributes.width = { from: start, to: finish }; 
		this.tab.anim.animate();  
	},
	/**
	 * Animates the shopping list.
	 */
	move: function(e) {
		var offset, anim;

		if (UKISA.util.getScrollXY()[1] < 114) {
			anim = new YAHOO.util.Anim("notebook", {   
			top : { to: 100 }  
			}, 0.5, YAHOO.util.Easing.backOut).animate();   
		} else {
			anim = new YAHOO.util.Anim("notebook", {
			top : { to: UKISA.util.getScrollXY()[1] + 14 }
			}, 0.5, YAHOO.util.Easing.backOut).animate();   
		}
			
	},
	/**
	 * May fix position issues if the window is resized
	 */
	resize: function(e) {},
	/**
	 * Attach events to add an item to the shopping list in progressive enhancement style.
	 */
	attach: function() {
		var add = document.getElementById("add-shopping-list");

		if (add) {
			YAHOO.util.Event.addListener(add, "submit", this.add, null, this); 
		}
	},
	/**
	 * Enhances the add to shopping list function by Ajaxing it.
	 */
	add: function(e) {
		var callback, transaction, params, form, canvas, add;

		canvas = document.getElementById("notebook-content");
		if (!canvas) { return; }

		form = document.getElementById("add-shopping-list");

		add = document.getElementById("add-shopping-list-add");		
	
		add.src = add.src.replace("shopping_list_add.gif", "shopping_list_loading.gif");

		callback = {
			success: function(o) {
				var notice;

				notice = document.getElementById("add-shopping-list-error");			
				if (notice) {
					notice.parentNode.removeChild(notice);
				}

				canvas.innerHTML = o.responseText;
				add.src = add.src.replace("shopping_list_loading.gif", "shopping_list_success.gif");
				add.disabled = true;
			},
			failure: function(o) {
				var notice;

				notice = document.getElementById("add-shopping-list-error");			
				if (notice) {
					notice.parentNode.removeChild(notice);
				}

				notice = document.createElement("p");
				notice.id = "add-shopping-list-error";
				notice.className = "error";
				notice.innerHTML = "Sorry, this could not be added to your shopping list.";
				form.appendChild(notice);

				add.src = add.src.replace("shopping_list_loading.gif", "shopping_list_add.gif");
			},
			timeout: 8000
		};	
		
		params  = "colour=" + encodeURIComponent(form["colour"].value);
		params += "&listaction=" + encodeURIComponent(form["listaction"].value);
		params += "&product=" + encodeURIComponent(form["product"].value);
		params += "&successURL=" + encodeURIComponent("/includes/mini_shopping_list.jsp");	

		transaction = YAHOO.util.Connect.asyncRequest("POST", form.getAttribute("action") + "?ajax=true", callback, params);

		YAHOO.util.Event.preventDefault(e); 

		return false;
	},
	multiAttach: function() {
		var canvas, i;
		
		canvas = document.getElementById("guide-shopping-list");

		forms = canvas.getElementsByTagName("form");

		for (i = 0, ix = forms.length; i < ix; i++) {
			YAHOO.util.Event.addListener(forms[i], "submit", this.multiAdd, null, this); 
		}
	},
	multiAdd: function(e) {
		var tg, callback, transaction, params, form, canvas, add, i, inputs;

		canvas = document.getElementById("notebook-content");
		if (!canvas) { return; }

		form = (window.event) ? e.srcElement : e.target;

		inputs = form.getElementsByTagName("input");

		for (i = 0, ix = inputs.length; i < ix; i++) {
			if (inputs[i].getAttribute("type") === "image") {
				add = inputs[i];
				break;
			}
		}
	
		add.src = add.src.replace("shopping_list_add_multi.gif", "shopping_list_multi_loading.gif");
		add.src = add.src.replace("shopping_list_guide_add.gif", "shopping_list_guide_loading.gif");

		callback = {
			success: function(o) {
				var notice;

				notice = document.getElementById("add-shopping-list-error");			
				if (notice) {
					notice.parentNode.removeChild(notice);
				}

				canvas.innerHTML = o.responseText;
				add.src = add.src.replace("shopping_list_multi_loading.gif", "shopping_list_multi_success.gif");
				add.src = add.src.replace("shopping_list_guide_loading.gif", "shopping_list_guide_success.gif");
				add.disabled = true;
			},
			failure: function(o) {
				var notice, multiForm;

				notice = document.getElementById("add-shopping-list-error");			
				if (notice) {
					notice.parentNode.removeChild(notice);
				}
				notice = document.createElement("p");
				notice.id = "add-shopping-list-error";
				notice.className = "error";
				notice.innerHTML = "Sorry, this could not be added to your shopping list.";

				if (document.body.id === "guide-page") {
					multiForm = document.getElementById("add-shopping-list");
					multiForm.appendChild(notice);
				} else {
					form.appendChild(notice);
				}

				add.src = add.src.replace("shopping_list_multi_loading.gif", "shopping_list_add_multi.gif");
				add.src = add.src.replace("shopping_list_loading.gif", "shopping_list_add_multi.gif");
				add.src = add.src.replace("shopping_list_guide_loading.gif", "shopping_list_guide_add.gif");
			},
			timeout: 8000
		};	
		
		params  = "colour=" + encodeURIComponent(form["colour"].value);
		params += "&listaction=" + encodeURIComponent(form["listaction"].value);
		params += "&successURL=" + encodeURIComponent("/includes/mini_shopping_list.jsp");	
	
		if (form["product"]) {
			params += "&product=" + encodeURIComponent(form["product"].value);
		}
		if (form["products"]) {
			params += "&products=" + encodeURIComponent(form["products"].value);
		}

		transaction = YAHOO.util.Connect.asyncRequest("POST", form.getAttribute("action") + "?ajax=true", callback, params);

		YAHOO.util.Event.preventDefault(e); 

		return false;
	}
};
UKISA.Polycell.Sitestat = {
	/**
	 * Make a call to the Sitestat server to register a page view.
	 */
	hit: function(qs) {
		var url, ns_0, ns_pixelUrl;

		// This checks that the site is "live" as is must have the sitestat function.
		// This stops polluting the stats with UAT data.

		if (typeof sitestat === "function") {
			
			url = "http://int.sitestat.com/ici-paints/polycell-uk/s?" + qs;

			url += "&amp;ns__t=" + (new Date()).getTime();
			ns_pixelUrl = url;
			ns_0 = document.referrer;
			ns_0 = (ns_0.lastIndexOf("/") == ns_0.length - 1) ? ns_0.substring(ns_0.lastIndexOf("/"), 0) : ns_0;

			if(ns_0.length > 0) {
				url += "&amp;ns_referrer=" + escape(ns_0);
			}
			if(document.images){
				ns_1 = new Image();
				ns_1.src = url;
			} else {
				document.write('<img src="' + url + '" width="1" height="1" alt="" class="tracking" style=\"display: none;\" />');
			}
			
		}
	}
};
