// StyledForm Classes
var StyledForm = {};
(function() {
	var $empty = function() {};
	// Form Elements
	StyledForm.Dropdown = new Class(function() {
		var SelectOption = function(display,value,selected,displayElement,optionElement) {
			this.display = display;
			this.value = value;
			this.selected = selected;
			this.displayElement = displayElement;
			this.optionElement = optionElement;
			this.disable = function() {
				this.displayElement.addClass('disabled');
			};
			this.enable = function() {
				this.displayElement.removeClass('disabled');
			};
			this.destroy = function() {
				this.displayElement = null;
				this.optionElement = null;
			};
		};
		function stopEvent(e) { var evt = new Event(e).stop(); }
		
		return {
			options: {
				activeClass: 'active',
				defaultValue: null,
				dropdownClass: 'dropdown',
				dropdownBackgroundClass: 'dropdownBg',
				selectionClass: 'selection',
				selectionDivClass: 'dropdownSelection',
				defaultSelectionClass: 'defaultSelection',
				menuClass: 'menu',
				listClass: 'list',
				optionsClass: 'options',
				optionTag: 'p',
				optionClass: 'option',
				transition: Fx.Transitions.Sine.easeOut,
				duration: 250,
				typeDelay: 500,
				mouseLeaveDelay: 500,
				initialValue: null,
				excludedValues: []
			},
			clearTimer: null,
			collapseInterval: null,
			dropdown: null,
			events: { options: {} },
			highlighted: null,
			input: null,
			list: null,
			listOptions: [],
			open: false,
			selection: null,
			selectedOption: null,
			typed: {lastKey: null, value: null, timer: null, pressed: null, shortlist: [], startkey: null},
			initialize: function(el, options) {
				this.setOptions(options);
				this.defaultValue = this.options.defaultValue;
				var i;
				var select = $(el);
				function mouseenterDropdown() {
					$clear(this.collapseInterval);
				}
				function mouseleaveDropdown() {
					this.collapseInterval = this.collapse.delay(this.options.mouseLeaveDelay, this);
				}
				this.events.mouseenter = mouseenterDropdown.bind(this);
				this.events.mouseleave = this.options.mouseLeaveDelay ? mouseleaveDropdown.bind(this) : $empty;
				this.events.keydown = this.keydown.bind(this);
				this.events.keypress = this.keypress.bind(this);
				this.events.options = {
					mousemove: this.addMouseHighlight.bind(this),
					mouseenter: this.mouseenter.bind(this),
					mouseleave: this.mouseleave.bind(this)
				};
				var selectOptions = select.getElements('option');
				this.dropdown = new Element('div',{
					'class':this.options.dropdownClass
				});
				select.getProperty('class').split(' ').each(function(clazz) {
					this.dropdown.addClass(clazz);
				},this);
				var id = select.getProperty('id');
				if (id && id.trim() !== '') {
					select.setProperty('id','');
					this.dropdown.setProperty('id',id + 'Dropdown');
				}
				// create options list
				var menu = new Element('div',{'class':this.options.menuClass});
				this.list = new Element('div',{'class':this.options.listClass});
				var optionsDiv = new Element('div',{'class':this.options.optionsClass});
				var listOptions = this.listOptions;
				var option, display, value, selected, selectedOption, optionElement, selectOption, optionClass, defaultOption, initialOption;
				for (i = 0; i < selectOptions.length; i = i + 1) {
					option = selectOptions[i];
					optionClass = option.getProperty('class') + ' ' + this.options.optionClass;
					optionClass = optionClass.trim();
					display = option.innerHTML;
					value = option.getProperty('value');
					optionElement = new Element(this.options.optionTag,{
						'class':optionClass,
						'events': {
							'mouseup': stopEvent,
							'click': this.listOptionClicked.bind(this),
							'mousedown': stopEvent,
							'mouseenter': this.events.options.mouseenter
						}
					});
					optionElement.setHTML(display);
					selectOption = new SelectOption(display,value,selected,optionElement,option);
					optionElement.store('optionData',selectOption);
					selected = option.getProperty('selected');
					if (selected || this.options.initialValue === selectOption.value) {
						this.selectedOption = selectOption;
					}
					listOptions.push(selectOption);
					if (i === 0 || value === this.options.defaultValue) { defaultOption = selectOption; }
					if (value === this.options.initialValue) { initialOption = selectOption; }
					optionElement.inject(optionsDiv);
				}
				if (initialOption) { this.selectedOption = initialOption; }
				if (!this.selectedOption) { this.selectedOption = defaultOption; }
				if (!this.defaultValue) { this.defaultValue = selectOptions[0].getProperty('value'); }
				this.fireEvent('onSelect',this.selectedOption);
				optionsDiv.inject(this.list);
				this.list.inject(menu);
				// create dropdown selection div and children
				var dropdownSelection = new Element('div',{'class':this.options.selectionDivClass});
				var dropdownBackground = new Element('div',{'class':this.options.dropdownBackgroundClass});
				var selectedText = selectedOption ? selectedOption.value : selectOptions[0].value;
				this.selection = new Element('span',{
					'class':this.options.selectionClass,
					'events': {
						'mousedown': this.selectionClicked.bind(this)
					}
				});
				this.selection.setHTML(selectedText);
				this.input = new Element('input',{
					'type':'text',
					'value':this.selectedOption.optionElement.value,
					'id': id,
					'name':select.getProperty('name'),
					'events': {
						'focus': this.focus.bind(this),
						'blur': this.blur.bind(this)
					}
				});
				var evt = window.ie || window.webkit ? 'keydown' : 'keypress';
				var target = window.ie ? $(document.body) : window;
				target.addEvent('keydown',this.events.keydown).addEvent(evt,this.events.keypress);
				dropdownBackground.inject(dropdownSelection);
				this.selectListOption(this.selectedOption.displayElement);
				this.selection.inject(dropdownSelection);
				this.input.inject(dropdownSelection);
				// clone the original select
				var selectClone = select.clone();
				// inject everything
				dropdownSelection.inject(this.dropdown);
				menu.inject(this.dropdown);
				select.replaceWith(this.dropdown);
				if (this.defaultValue !== this.selectedOption.value) { this.fireEvent('onChange',this); }
				document.addEvent('mousedown', this.clickOutside.bind(this));
			},
			addMouseHighlight: function(e) {
				var current = this.highlighted.displayElement;
				var options = current.getParent().getElements('.' + this.options.optionClass);
				options.addEvent('mouseenter',this.events.options.mouseenter);
				document.removeEvent('mousemove',this.events.options.mousemove);
			},
			blur: function(e) {
				if (this.open) { this.input.focus(); } // necessary because of the order in which IE executes events
				this.input.store('hasFocus',false);
			},
			clickOutside: function(e) {
				this.collapse();
			},
			collapse: function() {
				if (this.open) {
					this.toggle();
				}
				this.fireEvent('onCollapse');
			},
			destroy: function() {
				var listOptions = this.listOptions;
				var i = listOptions.length;
				if (i) {
					do {
						i = i - 1;
						listOptions[i].destroy();
					} while (i);
				}
				this.dropdown = null;
				this.input = null;
				this.list = null;
				this.selectedOption = null;
				this.selection = null;
			},
			expand: function() {
				if (!this.open) {
					this.toggle();
					this.input.focus();
				}
				this.fireEvent('onExpand');
			},
			foundMatch: function() {
				var typed = this.typed;
				var shortlist = typed.shortlist;
				var value = typed.value;
				var i = 0;
				var optionsLength = shortlist.length;
				var excludedValues = this.options.excludedValues;
				var found = false;
				var option;
				do {
					option = shortlist[i];
					if (option.display.toLowerCase().indexOf(value) === 0 && !excludedValues.contains(option.value)) {
						found = true;
						this.keyboardHighlightOption(option);
						typed.pressed = i + 1;
						i = optionsLength;
					}
					i = i + 1;
				} while(i < optionsLength);
				return found;
			},
			focus: function(e) {
				this.input.store('hasFocus',true);
				this.expand();
			},
			highlightOption: function(option) {
				if (this.highlighted) {
					this.removeHighlightOption(this.highlighted.displayElement);
				}
				this.highlighted = option.retrieve('optionData');
				this.fireEvent('onHighlight',option);
			},
			keyboardHighlightOption: function(option) {
				this.removeHighlightOption(this.highlighted.displayElement);
				this.highlightOption(option.displayElement);
				this.fireEvent('onKeyboardHighlight',option);
			},
			keydown: function(e) {
				if (!this.open) { return; }
				var current = this.highlighted.displayElement;
				var options = current.getParent().getElements('.' + this.options.optionClass);
				options.removeEvent('mouseenter',this.events.options.mouseenter);
				document.addEvent('mousemove',this.events.options.mousemove);
			},
			keypress: function(e) {
				if (!this.open) { return; }
				var evt = new Event(e);
				$clear(this.clearTimer); // clear the typing timer
				var current = this.highlighted.displayElement;
				var previous, next;
				var code = evt.code;
				var key = evt.key;
				var typed = this.typed;
				var i, options, option, optionsLength, found, first, excludedValues, shortlist;
				switch(code) {
					case 38: // up
					case 37: // left
						evt.stop();
						previous = current.getPrevious();
						if (!previous) {
							previous = current.getParent().getLast();
						}
						if (typed.pressed > 0) { typed.pressed = typed.pressed - 1; }
						this.keyboardHighlightOption(previous.retrieve('optionData'));
						break;
					case 40: // down
					case 39: // right
						evt.stop();
						next = current.getNext();
						if (!next) {
							next = current.getParent().getFirst();
						}
						if (typed.shortlist.length > 0) { typed.pressed = typed.pressed + 1; }
						this.keyboardHighlightOption(next.retrieve('optionData'));
						break;
					case 13: // enter
						evt.stop();
					case 9: // tab - skips the stop event but clicks the item
						evt.target = current;
						this.listOptionClicked(evt);
						break;
					case 27: // esc
						evt.stop();
						this.toggle();
						break;
					case 32: // space
					default: // anything else
						if (!(code >= 48 && code <= 122 && (code <= 57 || (code >= 65 && code <= 90) || code >=97) || code === 32)) { break; }
						if (evt.control || evt.alt || evt.meta) { return; }
						// alphanumeric or space
						key = code === 32 ? ' ' : key;
						$clear(typed.timer);
						options = this.listOptions;
						optionsLength = options.length;
						excludedValues = this.options.excludedValues;
						if (typed.timer === null) { // timer is expired
							typed.shortlist = [];
							if (key === typed.lastKey || key === typed.startkey) { // get next
								typed.pressed = typed.pressed + 1;
								typed.value = key;
							} else { // get first
								typed = this.resetTyped();
								typed.value = key;
								typed.startkey = key;
								typed.pressed = 1;
							}
							typed.timer = this.resetTyped.delay(500,this);
						} else {
							if (key === typed.lastKey) { // check for match, if no match get next
								typed.value = typed.value + key;
								if (this.foundMatch()) { // got a match so break
									typed.timer = this.resetTyped.delay(500,this);
									break;
								} else { // no match fall through
									typed.shortlist = [];
									typed.value = key;
									typed.pressed = typed.pressed + 1;
									typed.timer = null;
								}
							} else { // reset timer, get first match, set pressed to found position
								typed.timer = this.resetTyped.delay(500,this);
								typed.value = typed.value + key;
								typed.startkey = typed.value.substring(0,1);
								typed.lastKey = key;
								this.foundMatch();
								break;
							}
						}
						typed.lastKey = key;
						shortlist = typed.shortlist;
						i = 0;
						found = 0;
						do {
							option = options[i];
							if (option.display.toLowerCase().indexOf(key) === 0 && !excludedValues.contains(option.value)) {
								if (found === 0) { first = option; }
								found = found + 1;
								if (found === typed.pressed) { this.keyboardHighlightOption(option); }
								shortlist.push(option);
							}
							i = i + 1;
						} while(i < optionsLength);
						if (typed.pressed > found) {
							this.keyboardHighlightOption(first);
							typed.pressed = 1;
						}
						break;
				}
			},
			listOptionClicked: function(e) {
				var evt = new Event(e);
				if (!evt.type.match(/^key/)) { evt.stop(); }
				var option = evt.target;
				this.selectListOption(option,evt);
				this.collapse();
				if (this.options.hasLinks) {
					location.href = option.getProperty('href');
				}
			},
			mouseenter: function(e) {
				var evt = new Event(e);
				var option = evt.target;
				this.highlightOption(option);
			},
			mouseleave: function(e) {
				var evt = new Event(e);
				var option = evt.target;
				this.removeHighlightOption(option);
			},
			removeHighlightOption: function(option) {
				this.fireEvent('onRemoveHighlight',option);
			},
			resetTyped: function() {
				var typed = this.typed;
				typed.value = null;
				typed.timer = null;
				return this.typed;
			},
			selectionClicked: function(e) {
				stopEvent(e);
				this.expand();
			},
			selectListOption: function(option,evt) {
				option = $(option);
				var selectOption = option.retrieve('optionData');
				this.selection.empty();
				var firstChild = selectOption.displayElement.getFirst();
				if (firstChild) {
					this.selection.adopt(selectOption.displayElement.clone());
				} else {
					this.selection.setHTML(selectOption.displayElement.innerHTML);
				}
				this.selection.setStyle('display', 'block');
				var oldValue = this.value;
				this.value = selectOption.value;
				this.input.setProperty('value',this.value);
				this.selectedOption = selectOption;
				this.fireEvent('onSelect',[selectOption,evt]);
				if ($defined(oldValue) && oldValue !== this.value) {
					this.fireEvent('onChange',[this,evt]);
				}
			},
			toggle: function() {
				$clear(this.collapseInterval);
				this.fireEvent(this.open ? 'onClose' : 'onOpen',this);
				this.open = !this.open;
				if (this.open) {
					this.dropdown.addClass(this.options.activeClass).addClass(this.options.dropdownClass + '-' + this.options.activeClass);
					this.highlightOption(this.selectedOption.displayElement);
					this.dropdown.addEvent('mouseenter',this.events.mouseenter);
					this.dropdown.addEvent('mouseleave',this.events.mouseleave);
				} else {
					this.dropdown.removeClass(this.options.activeClass).removeClass(this.options.dropdownClass + '-' + this.options.activeClass);
					this.dropdown.removeEvent('mouseenter',this.events.mouseenter);
					this.dropdown.removeEvent('mouseleave',this.events.mouseleave);
					this.removeHighlightOption(this.highlighted.displayElement);
				}
			}
		};
	}());
	StyledForm.Dropdown.implement(new Events,new Options);
	StyledForm.SimpleCheckbox = new Class({
		options: {
			checkClass: 'check',
			checkedClass: 'checked',
			disabledClass: 'disabled',
			checked: false
		},
		check: null, // <Element> a clone of the input wrapped by this class
		checked: false, // <Boolean> whether or not the checkbox is ticked
		events: {}, // <Object> hash of bound functions for events
		id: null, // <String> id of the checkbox/wrapper
		name: null, // <String> form name of the checkbox
		value: null, // <String> value of the checkbox
		wrapper: null, // <Element> the div wrapping the supposedly hidden checkbox
		initialize: function(check,options) {
			this.setOptions(options);
			this.events = {
				blur: this.blur.bind(this),
				click: this.click.bind(this),
				focus: this.focus.bind(this)
			};
			check = $(check);
			var props = check.getProperties('value','name','id');
			this.value = props.value;
			this.name = props.name;
			this.id = props.id;
			this.check = check.clone().setProperty('id',this.id);
			this.wrapper = new Element('div',{
				'class': this.options.checkClass,
				'id': this.id + 'SimpleCheckbox'
			});
			this.wrapper.adopt(this.check);
			check.replaceWith(this.wrapper);
			this.wrapper.store('StyledForm.SimpleCheckbox',this);
			this.wrapper.addEvents(this.events);
			var label = document.getElement('label[for=' + props.id + ']');
			if (window.ie && label) { label.addEvent('click',this.events.click); }
			if (this.options.checked || check.checked) {
				this.events.click();
			}
		},
		toggle: function() {
			if (this.wrapper.hasClass(this.options.checkedClass)) {
				this.wrapper.removeClass(this.options.checkedClass);
				this.check.removeProperty('checked');
				this.checked = false;
				this.fireEvent('onUncheck',this);
			} else {
				this.wrapper.addClass(this.options.checkedClass);
				this.check.setProperty('checked','checked');
				this.checked = true;
				this.fireEvent('onCheck',this);
			}
			this.fireEvent('onChange',this);
		},
		blur: function(e) { },
		click: function(e) {
			var evt = function() { this.stop = function() {} };
			if (e) { evt = new Event(e); evt.stop(); }
			this.toggle();
		},
		focus: function(e) { }
	});
	StyledForm.SimpleCheckbox.implement(new Events,new Options);
	StyledForm.Slider = new Class(function() {
		function stopEvent(e) {
			var evt;
			if (e) {
				evt = new Event(e);
				evt.stop();
			}
		}
		return {
			options: {
				animate: true,
				duration: 250,
				transition: 'circ:out',
				itemSize: 120,
				horizontal: true,
				forwardButtonClass: 'forward',
				backButtonClass: 'back',
				scrubberClass: 'scrubber',
				snapTo: true,
				trackClass: 'track',
				buttonHoldDelay: 150,
				scrollSpeed: 0.5
			},
			el: null,
			track: null,
			trackSize: null,
			scrubber: null,
			scrubberSize: null,
			scrubberPosition: null,
			itemTrackSize: null,
			forwardButton: null,
			backButton: null,
			drag: false,
			dragOffset: null,
			buttonHoldInterval: null,
			events: {},
			scrubberLimits: { 'top': null, 'bottom': null, 'left': null, 'right': null },
			initialize: function(el, scrubberRatio, options) {
				this.setOptions(options);
				this.el = $(el);
				options = this.options;
				this.track = el.getElement('.' + this.options.trackClass);
				var sliderSize;
				if (options.horizontal) {
					sliderSize = el.getSize().size.x;
					this.trackSize = this.track.getSize().size.x;
					this.scrubberTween = 'left';
				} else {
					sliderSize = el.getSize().size.y;
					this.trackSize = this.track.getSize().size.y;
					this.scrubberTween = 'marginTop';
				}

				this.events = {
					'mousedown': this.mouseDown.bind(this),
					'mousemove': this.mouseMove.bind(this),
					'mouseup': this.mouseUp.bind(this)
				};
				this.track.addEvent('mousedown', this.events.mousedown);
				document.addEvent('mousemove', this.events.mousemove);
				document.addEvent('mouseup', this.events.mouseup);

				this.scrubber = el.getElement('.' + this.options.scrubberClass);
				this.scrubberSize = Math.floor(scrubberRatio * sliderSize);

				var sides = this.options.horizontal ? ['Left','Right'] : ['Top','Bottom'];
				var scrubberSize = this.scrubberSize;
				var scrubber = this.scrubber;
				sides.each(function(side) {
					scrubberSize = scrubberSize - scrubber.getStyle('margin' + side).toInt();
					scrubberSize = scrubberSize - scrubber.getStyle('border' + side + 'Width').toInt();
					scrubberSize = scrubberSize - scrubber.getStyle('padding' + side).toInt();
				});
				
				this.scrubberPosition = 0;
				this.scrubberTween = this.scrubber.effect(this.scrubberTween,{
					duration: this.options.duration,
					transition: this.options.transition
				});
				this.scrubber.setStyle(this.options.horizontal ? 'width' : 'height', scrubberSize);

				this.itemTrackSize = this.options.itemSize * scrubberRatio;

				this.forwardButton = el.getElement('.' + this.options.forwardButtonClass);
				var forwardButton = this.forwardButton;
				forwardButton.addEvent('mousedown', this.forwardButtonClick.bind(this));
				forwardButton.addEvent('click', stopEvent);

				this.backButton = el.getElement('.' + this.options.backButtonClass);
				var backButton = this.backButton;
				backButton.addEvent('mousedown', this.backButtonClick.bind(this));
				backButton.addEvent('click', stopEvent);

				if (this.options.horizontal) {
					this.scrubberLimits.left = 0;
					this.scrubberLimits.right = this.trackSize - this.scrubberSize;
				} else {
					this.scrubberLimits.top = 0;
					this.scrubberLimits.bottom = this.trackSize - this.scrubberSize;
				}
			},
			load: function() {
				this.el.fade('in');
			},
			mouseDown: function(e) {
				var evt = new Event(e);
				this.drag = true;
				this.isMouseDown = true;
				stopEvent(e);
				var mousePosition = this.options.horizontal ? evt.page.x : evt.page.y;
				if (this.isPositionAboveScrubber(mousePosition)) {
					this.setScrubberOffset(mousePosition);
				} else {
					this.centerScrubberToPosition(mousePosition);
				}
			},
			mouseMove: function(e) {
				var evt = new Event(e);
				var mousePosition;
				if (this.drag) {
					mousePosition = this.options.horizontal ? evt.page.x : evt.page.y;
					this.dragScrubberTo(mousePosition);
				}
			},
			mouseUp: function() {
				$clear(this.buttonHoldInterval);
				if (!this.isMouseDown) { return; } 
				this.isMouseDown = false;
				if (this.drag) {
					this.drag = false;
				}
				this.setScrubberPosition(this.scrubberPosition);
				if (this.scrubberPosition === (this.trackSize - this.scrubberSize)) {
					this.fireEvent('onReachedEnd',this);
				}
			},
			mouseWheel: function(e) {
				var evt = new Event(e);
				if (evt.wheel > 0 && this.scrubberPosition != this.scrubberLimits[this.options.horizontal ? 'left' : 'top']) {
					// wheel up
					this.backButtonClick(e);
				} else if (evt.wheel < 0 && this.scrubberPosition != this.scrubberLimits[this.options.horizontal ? 'right' : 'bottom']) {
					// wheel down
					this.forwardButtonClick(e);
				}
				this.isMouseDown = true;
				this.mouseUp();
			},
			forwardButtonClick: function(e) {
				stopEvent(e);
				this.isMouseDown = true;
				this.slideScrubberTo(this.scrubberPosition + (this.scrubberSize * this.options.scrollSpeed));
				this.buttonHoldInterval = this.forwardButtonClick.delay(this.options.buttonHoldDelay,this);
			},
			backButtonClick: function(e) {
				stopEvent(e);
				this.isMouseDown = true;
				this.slideScrubberTo(this.scrubberPosition - (this.scrubberSize * this.options.scrollSpeed));
				this.buttonHoldInterval = this.backButtonClick.delay(this.options.buttonHoldDelay,this);
			},
			slideScrubberTo: function(trackPosition) {
				this.setScrubberPosition(trackPosition);
			},
			setScrubberOffset: function(position) {
				var trackPosition = this.getTrackPosition(position);
				this.dragOffset = trackPosition - this.scrubberPosition;
			},
			dragScrubberTo: function(position) {
				var trackPosition = this.getTrackPosition(position);
				this.setScrubberPosition(trackPosition - this.dragOffset, false);
			},
			isPositionAboveScrubber: function(position) {
				var trackPosition = this.getTrackPosition(position);
				return (trackPosition > this.scrubberPosition && trackPosition < (this.scrubberPosition + this.scrubberSize)) ? true : false;
			},
			getTrackPosition: function(position) {
				var trackPos = this.options.horizontal ? this.track.getPosition().x : this.track.getPosition().y;
				return position - trackPos;
			},
			centerScrubberToPosition: function(position) {
				var trackPosition = this.getTrackPosition(position);
				var halfScrubberSize = this.scrubberSize / 2;
				this.setScrubberPosition(trackPosition - halfScrubberSize);
				this.dragOffset = halfScrubberSize;
			},
			setScrubberPosition: function(position, animate) {
				animate = $defined(animate) ? animate : this.options.animate;
				this.scrubberPosition = position;
				if (this.scrubberPosition < 0) {
					this.scrubberPosition = 0;
				} else if ((this.scrubberPosition + this.scrubberSize) > this.trackSize) {
					this.scrubberPosition = this.trackSize - this.scrubberSize;
				}

				var modGrid = this.scrubberPosition % this.itemTrackSize;
				if (this.options.snapTo) {
					if (modGrid > 0 && this.scrubberPosition !== (this.trackSize - this.scrubberSize)) {
						this.scrubberPosition = this.scrubberPosition - modGrid;
					}
				}

				var positionRatio = this.scrubberPosition / this.trackSize;
				if (animate) {
					this.scrubberTween.start(this.scrubberPosition);
					this.fireEvent('onSlideTo', positionRatio);
				} else {
					this.scrubberTween.set(this.scrubberPosition);
					this.fireEvent('onMoveTo', positionRatio);
				}
			},
			destroy: function() {
				document.removeEvent('mousemove', this.events.mousemove);
				document.removeEvent('mouseup', this.events.mouseup);
				this.el = null;
				this.track = null;
				this.scrubber = null;
				this.forwardButton = null;
				this.backButton = null;
			}
		};
	}());
	StyledForm.Slider.implement(new Events,new Options);
	StyledForm.Field = new Class({
		submittable: $empty, // <Function> returns boolean
		input: null,
		initialize: function(input,submitTest) {
			this.input = input;
			this.submittable = submitTest.pass([input]);
		}
	});
	StyledForm.FieldSet = new Class({
		fields: [],
		initialize: function(fields,options) {
			this.setOptions(options);
			this.fields = fields || [];
		},
		addField: function(field) {
			this.fields.push(field);
		},
		submittable: function() {
			var submittable = true;
			var fields = this.fields;
			var i = fields.length;
			if (!i) { return submittable; }
			var field;
			do {
				i = i - 1;
				submittable = submittable && fields[i].submittable();
			} while (i);
			var evt = submittable ? 'onSubmittable' : 'onUnsubmittable';
			this.fireEvent(evt);
			return submittable;
		}
	});
	StyledForm.FieldSet.implement(new Events,new Options);
})();
// Gateway Class
(function() {
	var $empty = function() {};
	// Utility functions
	function stopEvent(e) {
		var evt = new Event(e);
		evt.stop();
	};
	function createScrollBar(scrollBarHeight,options) {
		// Create scroll bar
		var scrollBar = new Element('div',{
			'class': options.scrollBarClass,
			'styles': {
				'height': scrollBarHeight
			}
		});

		// Setup back button
		var backButton = new Element('p',{
			'class': options.backButtonClass
		});
		backButton.addEvents({
			'mouseenter': backButton.addClass.pass([options.backButtonClass + 'Over'],backButton),
			'mouseleave': backButton.removeClass.pass([options.backButtonClass + 'Over'],backButton),
			'mousedown': backButton.addClass.pass([options.backButtonClass + 'Down'],backButton),
			'mouseup': backButton.removeClass.pass([options.backButtonClass + 'Down'],backButton)
		});
		scrollBar.adopt(backButton);

		// Setup track
		var track = new Element('div', {
			'class': options.trackBarClass
		});

		// Setup scrubber
		var scrubber = new Element('div',{
			'class': options.scrubberClass
		});
		scrubber.addEvents({
			'mousedown': scrubber.addClass.pass([options.scrubberClass + 'Down'],scrubber),
			'mouseup': scrubber.removeClass.pass([options.scrubberClass + 'Down'],scrubber)
		});
		track.adopt(scrubber);
		scrollBar.adopt(track);

		// Setup forward button
		var forwardButton = new Element('p',{
			'class': options.forwardButtonClass
		});
		forwardButton.addEvents({
			'mouseenter': forwardButton.addClass.pass([options.forwardButtonClass + 'Over'],forwardButton),
			'mouseleave': forwardButton.removeClass.pass([options.forwardButtonClass + 'Over'],forwardButton),
			'mousedown': forwardButton.addClass.pass([options.forwardButtonClass + 'Down'],forwardButton),
			'mouseup': forwardButton.removeClass.pass([options.forwardButtonClass + 'Down'],forwardButton)
		});
		scrollBar.adopt(forwardButton);

		return scrollBar;
	};
	function createSlider(scrollBar, el, sliderOptions, options) {
		var scrollBarHeight = scrollBar.getStyle('height').toInt();
		var backButtonHeight = scrollBar.getElement('.' + options.backButtonClass).getSize().size.y;
		var forwardButtonHeight = scrollBar.getElement('.' + options.forwardButtonClass).getSize().size.y;
		var trackHeight = scrollBarHeight - backButtonHeight - forwardButtonHeight;
		scrollBar.getElement('.' + options.trackBarClass).setStyles({
			'height': trackHeight,
			'top': backButtonHeight
		});

		// Create slider
		var scrubberRatio = trackHeight / el.getSize().scrollSize.y;
		var slider = new StyledForm.Slider(scrollBar,scrubberRatio,sliderOptions);

		// Setup mousewheel events
		slider.boundMousewheel = slider.mouseWheel.bindWithEvent(slider);

		return slider;
	};
	function getNodeId(node) {
		var attributes = node.attributes;
		var i = 0;
		var length = attributes.length;
		for (i = 0; i < length; i = i + 1) {
			if (attributes[i].nodeName === 'id') {
				return attributes[i].nodeValue;
			}
		}
		return null;
	};
	function getNodeValue(node) {
		return node.firstChild ? node.firstChild.nodeValue : '';
	};
	function updateImage(el,properties) {
		var height = el.getSize().size.y;
		var newHeight = properties.height.toInt();
		var marginTop = el.getStyle('marginTop').replace('px','').toInt() + height - newHeight;
		el.setStyle('marginTop',marginTop);
		el.setProperties(properties);
		el.store('pngFixed',false).fixPng();
	};
	var Gateway = new Class({
		/* Config */
		basePath: '/Resources/Smirnoff3/global/html/languages/',
		defaultDateOrder: 'd:m:y',
		defaultLocale: 'en_ROW',
		enterDefault: '/Resources/Smirnoff3/global/html/images/default/button_enter.png',
		enterOver: '/Resources/Smirnoff3/global/html/images/default/button_enter_over.png',
		enterDown: '/Resources/Smirnoff3/global/html/images/default/button_enter_down.png',
		failureDelay: 1000,
		failureForward: 'http://www.centurycouncil.org/',
		redirects: {
			'es':  'http://www.themissingbottles.com/'
		},
		swfLocation: '/Resources/Smirnoff3/global/html/setLocale',
		/* End Config */
		age: null,
		cache: {},
		checkbox: null,
		cookies: {},
		defaultSelectionSize: 16,
		delay: null,
		dropdown: null,
		events: {},
		fields: null,
		fieldSet: null,
		listTween: null,
		locale: null,
		oldPosition: {},
		optionValues: {},
		request: null,
		slider: null,
		initialize: function() {
			this.request = new Ajax(this.basePath,{
				'method': 'get',
				'onSuccess': this.requestSuccess.bind(this),
				'onFailure': this.requestFailure.bind(this)
			});
			this.fieldSet = new StyledForm.FieldSet([],{
				'onSubmittable': this.enterEventsAdd.bind(this),
				'onUnsubmittable': this.enterEventsRemove.bind(this)
			});
			addEvent('domready',this.domready.bind(this));
			addEvent('load',this.load.bind(this));
			addEvent('resize',this.fixPosition.bind(this));
			addEvent('beforeunload',this.beforeunload.bind(this));
		},
		domready: function() {
			this.fixPosition();
			this.fields = $('fields');
			var cookies = this.cookies;
			$$('input[type=text], select').each(function(input) {
				var key = 'gw_' + input.getProperty('name');
				var value = Cookie.get(key);
				cookies[key] = value;
			});
			var selectedValue = this.domreadyProcessOptions();
			this.domreadySetupFormElements(cookies,selectedValue);
			this.domreadySetupEvents();
			// setup focus/blur events for text inputs
			this.fields.getElements('input').each(function(input) {
				var props = input.getProperties('title','name');
				var defaultValue = props.title;
				input.store('defaultValue',defaultValue);
				input.addEvents({
					focus: this.dateInputFocus.pass([input],this),
					blur: this.dateInputBlur.pass([input],this),
					change: this.dateInputChange.pass([input],this),
					keyup: this.dateInputKeyupDelay.bindAsEventListener(this,[input]) // had to use keyup because character needs to be present
				});
				var key = 'gw_' + props.name;
				input.value = cookies[key] ? cookies[key] : defaultValue;
				var field = new StyledForm.Field(input,this.submitTest);
				this.fieldSet.addField(field);
			},this);
			if (window.gecko) { $$('input[type=text]').setProperty('autocomplete','off'); }
			this.domreadySetupSlider.delay(1,this); // if this is not delayed the slider doesn't load correctly on a FF3 refresh
			if (selectedValue.length < 5) { this.setupPage(); }
			this.fieldSet.submittable();
		},
		domreadyProcessOptions: function() {
			var options = $$('select.formField option');
			var i = options.length;
			if (!i) { return; }
			var optionValues = this.optionValues;
			var option, origValue, pieces, parsed, value, selectedValue;
			var selected = null;
			var hiddenCountryValue = $('hdnCountryValue') ? $('hdnCountryValue').value.toLowerCase() : null;
			if (hiddenCountryValue && this.redirects[hiddenCountryValue]) { window.location = this.redirects[hiddenCountryValue]; return; }
			do {
				i = i - 1;
				option = options[i];
				origValue = option.getProperty('value');
				// (one or two digits) : (five or six alphanumeric or underscore characters) [ ; (m:d:y) ] [ | (anything) ]
				pieces = origValue.match(/(\d{1,2}):(\w{2})_(\w{2,3});?(\w:\w:\w)?\|?(.*)?/); // whole match is index 0
				parsed = pieces ? { age: pieces[1], lang: pieces[2], country: pieces[3], dateOrder: pieces[4], target: pieces[5] } : { country: origValue };
				switch (parsed.country) {
					case 'no': // should be the only value the regex doesn't match
						value = parsed.country; break;
					case 'CA':
					case 'CH':
						value = parsed.age + ':' + parsed.lang.toUpperCase() + parsed.country + (parsed.target ? '|' + parsed.target : ''); break;
					default:
						value = parsed.age + ':' + parsed.country + (parsed.target ? '|' + parsed.target : ''); break;
				}
				optionValues[value] = parsed;
				option.setProperty('value',value);
				selected = hiddenCountryValue && !selected && parsed.country.toLowerCase() == hiddenCountryValue ? option : selected;
			} while(i);
			return selected ? selected.getProperty('value') : null;
		},
		domreadySetupEvents: function() {
			// click events
			var why = $('why');
			$('why_ask').addEvent('click',why.addClass.pass(['open'],why)).addEvent('click',stopEvent)
					.addEvent('click',this.trackWhyAsk);
			why.getElement('.closeButton').addEvent('click',why.removeClass.pass(['open'],why)).addEvent('click',stopEvent);
			$('nav_accessibility').addEvent('click',smirnoffPopup.pass(['accessibility_statement']));
			$('nav_privacy').addEvent('click',smirnoffPopup.pass(['privacy_statement']));
			$('nav_terms').addEvent('click',smirnoffPopup.pass(['terms_of_use']));
			var popupBlocked = $('popupBlocked');
			popupBlocked.addEvent('click',popupBlocked.setStyle.pass(['display','none'],popupBlocked)).addEvent('click',stopEvent);
			// setup enter events
			var enter = $('enter');
			this.events.enter = {
				mousedown: this.enterMousedown.pass([enter],this),
				mouseout: this.enterMouseout.pass([enter],this),
				mouseover: this.enterMouseover.pass([enter],this),
				focus: this.enterMouseover.pass([enter],this),
				blur: this.enterMouseout.pass([enter],this)
			};
			// submit events
			var form = $('validateLDAForm');
			var onsubmit = form.getProperty('onsubmit');
			form.removeProperty('onsubmit').addEvent('submit',stopEvent);
			this.events.submittable = this.submittable.bind(this);
		},
		domreadySetupFormElements: function(cookies,selectedValue) {
			// setup styled checkbox
			this.checkbox = new StyledForm.SimpleCheckbox('chkRemember',{checked: Cookie.get('gw_chkRemember')});
			// dropdown
			var country = $('country') || $('Country');
			var countryName = country.getProperty('name');
			this.dropdown = new StyledForm.Dropdown(country,{
				'defaultValue': 'no',
				'initialValue': cookies[countryName] ? cookies[countryName] : selectedValue,
				'excludedValues': ['no'],
				'mouseLeaveDelay': null,
				'onChange': this.dropdownChange.bind(this),
				'onClose': this.dropdownClose.bind(this),
				'onHighlight': this.optionHighlight,
				'onKeyboardHighlight': this.resetScrubberPosition.bind(this),
				'onOpen': this.dropdownOpen.bind(this),
				'onRemoveHighlight': this.optionRemoveHighlight,
				'onSelect': this.dropdownSelect.bind(this)
			});
			this.defaultSelectionSize = this.dropdown.selection.getStyle('fontSize').toInt();
			this.dropdown.addEvent('onSelect',this.checkSelectionSize.pass([this.dropdown],this));
			if (window.ie6) { // add hover events for ie6
				this.dropdown.dropdown.getElement('.dropdownSelection').addEvents({
					'mouseenter': function() { this.toggleClass('hover'); },
					'mouseleave': function() { this.toggleClass('hover'); }
				});
			}
			$$('.country .option').getLast().addClass('last-option');
		},
		domreadySetupSlider: function() {
			// setup for slider
			var menu = document.getElement('div.dropdown .menu');
			var options = {
				scrollBarClass: 'scroller',
				backButtonClass: 'back',
				forwardButtonClass: 'forward',
				trackBarClass: 'track',
				scrubberClass: 'scrubber'
			};
			var scrollBar = createScrollBar(360, options);
			menu.adopt(scrollBar);
			// create effect for options
			var optionsEl = menu.getElement('.options');
			this.listTween = optionsEl.effect('marginTop',{ transition: Fx.Transitions.linear, wait:false });
			// create slider
			this.slider = createSlider(scrollBar, optionsEl, {
				'backButtonClass': options.backButtonClass,
				'forwardButtonClass': options.forwardButtonClass,
				'horizontal': false,
				'itemSize': 30,
				'scrubberClass': options.scrubberClass,
				'trackClass': options.trackBarClass,
				'transition': Fx.Transitions.linear,
				'scrollSpeed': 0.33,
				'onSlideTo': this.moveContent.bindAsEventListener(this,['slide']),
				'onMoveTo': this.moveContent.bindAsEventListener(this,['move'])
			}, options);
			// setup mousewheel events
			menu.addEvents({
				'mouseenter': document.addEvent.pass(['mousewheel',this.slider.mouseWheel.bind(this.slider)],document),
				'mouseleave': document.removeEvents.pass(['mousewheel'],document)
			});
			this.resetScrubberPosition(this.dropdown.selectedOption);
			// fix menu background for ie6
			var menuInner;
			if (window.ie6) {
				menuInner = new Element('div',{'class':'menuInner'});
				menuInner.adopt(menu.getChildren());
				menu.adopt(menuInner);
			}
		},
		load: function() {
			this.fixPosition();
			// png fix
			$$('.png').each(function(el) { el.fixPng(); });
			$$('input').removeProperty('disabled');
			this.loadSetupTracking();
			this.trackPageLoaded();
		},
		loadSetupTracking: function() {
			if (typeof cmCreatePageviewTag === 'undefined') { return; }
			this.trackDateInputBlur = function(input) {
				var id = input.getProperty('id');
				var param;
				switch (id.toLowerCase()) {
					case 'month':
						param = 'Month of Birth'; break;
					case 'day':
						param = 'Day of Birth'; break;
					case 'year':
						param = 'Year of Birth'; break;
				}
				cmCreatePageElementTag(param,'Age','Gateway: HTML Gateway / Age','Gateway');
			};
			this.trackDropdownChange = function(value) {
				value = value.replace(/,/g,'');
				cmCreatePageElementTag('Country Selection :: ' + value,'Country','Gateway: HTML Gateway / Age','Gateway');
			};
			this.trackPageLoaded = function() {
				cmCreatePageviewTag('Gateway: HTML Gateway / Age','Gateway');
				cmCreateConversionEventTag('Gateway: HTML Gateway Conversion',1,'Gateway');
			};
			this.trackValidateAge = cmCreateConversionEventTag.pass(['Gateway: HTML Gateway Conversion',2,'Gateway']);
			this.trackValidateAgeDry = cmCreatePageviewTag.pass(['Gateway: Dry Country','Gateway']);
			this.trackValidateAgeFailure = cmCreatePageviewTag.pass(['Gateway: Non LPA / Age','Gateway']);
			this.trackWhyAsk = cmCreatePageviewTag.pass(['Gateway: Why Ask / Age','Gateway']);
		},
		beforeunload: function() {
			if (this.dropdown) { this.dropdown.destroy(); }
			if (this.slider) { this.slider.destroy(); }
			$clear(this.delay);
		},
		checkSelectionSize: function(dropdown) {
			var selectionSize = dropdown.selection.getSize().size.y;
			if (selectionSize <= 55) { return; }
			var fontSize = dropdown.selection.getStyle('fontSize').toInt();
			dropdown.selection.setStyle('fontSize',(fontSize - 1));
			this.checkSelectionSize(dropdown);
		},
		dateInputBlur: function(input) {
			this.trackDateInputBlur(input);
			input.removeClass('focus');
			var defaultValue = input.retrieve('defaultValue');
			var value = input.value;
			if (!value || value === '') { input.value = defaultValue; }
			this.fieldSet.submittable();
		},
		dateInputChange: function(input) {
			input.removeClass('error');
		},
		dateInputFocus: function(input) {
			this.trackDateInputFocus(input);
			input.addClass('focus');
			var defaultValue = input.retrieve('defaultValue');
			var value = input.value;
			if (value === defaultValue) { input.setProperty('value',''); }
		},
		dateInputKeyup: function(evt,input) {
			var defaultValueLength = input.retrieve('defaultValue').length;
			var value = input.value;
			var regex = new RegExp('\\b\\d{' + defaultValueLength + '}\\b');
			if (!value.match(regex) || input !== evt.target) { return; }
			this.fieldSet.submittable();
			var next = input.getNext();
			// ignore anything that isn't a single character when determining whether or not to move focus
			if (evt.key.match(/^(\w|`)$/)) { next ? next.giveFocus().select() : $('enter').focus(); }
		},
		dateInputKeyupDelay: function(e,input) {
			var evt = new Event(e);
			this.dateInputKeyup.delay(100,this,[evt,input]);
		},
		dropdownChange: function(dropdown,evt) {
			dropdown.dropdown.removeClass('error');
			var value = dropdown.selectedOption.value;
			this.trackDropdownChange(dropdown.selectedOption.display);
			if (value === 'no') {
				this.age = null;
				return this.sendRequest(this.defaultLocale);
			}
			var parsed = this.optionValues[value];
			var dateOrder = parsed.dateOrder || this.defaultDateOrder;
			var fields = this.fields;
			if (dateOrder.indexOf('y') === 0) { fields.addClass('flipped'); }
			else { fields.removeClass('flipped'); }
			fields.getElements('input').removeClass('first').removeClass('second').removeClass('third');
			var fieldsP = fields.getElement('fieldset');
			dateOrder = dateOrder.split(':');
			dateOrder.each(function(key,i) {
				var clazz = i === 0 ? 'first' : (i === 1 ? 'second' : 'third');
				var field;
				switch (key) {
					case 'm': field = $('Month'); break;
					case 'd': field = $('Day'); break;
					case 'y': field = $('Year'); break;
				}
				fieldsP.adopt(field.addClass(clazz));
			});
			var lang = parsed.lang;
			var country = parsed.country;
			var locale = lang + '_' + country;
			this.age = parsed.age;
			this.locale = locale;
			this.setDocumentCookie(lang,country);
			this.setFlashCookie(lang,country);
			this.sendRequest(locale);
		},
		dropdownClose: function() {
			this.fields.removeClass('hide');
		},
		dropdownOpen: function() {
			this.fields.addClass('hide');
		},
		dropdownSelect: function(selectedOption,evt) {
			this.trackDropdownSelect();
			if (evt && evt.type.match(/^key/) && evt.code === 9 && (window.ie || window.webkit)) { setTimeout(this.focusFirst,15); }
			$$('div.dropdown .option').removeClass('selected');
			selectedOption.displayElement.addClass('selected');
			if (this.dropdown) { this.dropdown.selection.setStyle('fontSize',this.defaultSelectionSize); }
		},
		enterEventsAdd: function() {
			// enter events
			var enter = $('enter');
			if (!enter.retrieve('hasEvents')) { enter.addEvents(this.events.enter); }
			enter.store('hasEvents',true);
			// submit events
			$('validateLDAForm').removeEvent('submit',stopEvent).addEvent('submit',this.events.submittable);
		},
		enterMousedown: function(enter) { enter.setProperty('src',this.enterDown); },
		enterMouseout: function(enter) { enter.setProperty('src',this.enterDefault); },
		enterMouseover: function(enter) { enter.setProperty('src',this.enterOver); },
		enterEventsRemove: function() {
			var enter = $('enter');
			['mousedown','mouseout','mouseover','focus','blur'].each(function(type) {
				enter.removeEvent(type,this.events.enter[type]);
			},this);
			enter.store('hasEvents',false);
			$('validateLDAForm').removeEvent('submit',this.events.submittable).addEvent('submit',stopEvent);
		},
		fixPosition: function() {
			var wrapper = document.getElement('div.wrapper');
			var wrapperSize = wrapper.getSize().size;
			var winSize = getSize().size;
			if (winSize.y < 660) { wrapper.setStyles({'top':'0px','marginTop':'0px'}); }
			else { wrapper.setStyles({'top':'50%','marginTop':-(wrapperSize.y / 2) + 'px'}); }
		},
		focusFirst: function() { $('fields').getElement('input').focus(); },
		isDateNotWellFormed: function(day,month,year) {
			// month is zero based due to Date object handling (i.e. January === 0)
			var notWellFormed = '';
			var daysInFebruary = (year % 4 === 0 && (!(year % 100 === 0) || year % 400 === 0)) ? 29 : 28;
			var daysInMonth = (month === 3 || month === 5 || month === 8 || month === 10) ? 30 : (month === 1 ? daysInFebruary : 31);
			notWellFormed = month >= 0 && month <= 11 ? notWellFormed : notWellFormed + 'm';
			notWellFormed = day <= daysInMonth ? notWellFormed : notWellFormed + 'd';
			notWellFormed = year >= 1890 ? notWellFormed : notWellFormed + 'y';
			return notWellFormed;
		},
		moveContent: function(positionRatio,mode) {
			// fireEvent in Slider.js appears to not pass args which evaluate to false
			if (typeof positionRatio !== 'number' || !positionRatio) { positionRatio = 0; }
			var list = document.getElement('div.dropdown .menu .options');
			var position = -positionRatio * list.getSize().scrollSize.y;
			mode === 'slide' ? this.listTween.start(position) : this.listTween.set(position);
		},
		optionHighlight: function(option) { option.addClass('highlight'); },
		optionRemoveHighlight: function(option) { option.removeClass('highlight'); },
		rememberMeHandler: function() {
			var cookieOptions = {/*'domain':'*.smirnoff.com',*/'path':'/','duration':'30'};
			if (this.checkbox.checked) {
				Cookie.set('gw_chkRemember',true,cookieOptions);
				$$('input[type=text]').each(function(input) {
					Cookie.set('gw_' + input.getProperty('name'),input.value,cookieOptions);
				});
			} else {
				Cookie.set('gw_chkRemember',false,{'domain':'*.smirnoff.com'});
			}
		},
		requestFailure: function(xhr) {
			this.cache[this.locale] = this.defaultLocale;
			this.locale = this.defaultLocale;
			// without delay onSuccess of request for default locale doesn't fire if it is not cached
			this.sendRequest.delay(15,this,[this.defaultLocale]);
		},
		requestSuccess: function(text,doc) {
			var xmlDom;
			if (!doc.hasChildNodes()) { // if XMLHttpRequest doesn't correctly parse the document try and parse it here
				xmlDom = (document.all) ? new ActiveXObject("Microsoft.XMLDOM") : new DOMParser();
				xmlDom.async = false;
				doc = (document.all) ? ((xmlDom.loadXML(text)) ? xmlDom : false) : xmlDom.parseFromString(text, "text/xml");
			}
			this.cache[this.locale] = doc;
			var nodes = doc.getElementsByTagName('text');
			var i = nodes.length;
			var id, value, node, el, properties;
			do {
				i = i - 1;
				node = nodes[i];
				id = getNodeId(node);
				value = getNodeValue(node);
				el = $(id);
				if (el) { $(id).setHTML(value); }
			} while (i);
			nodes = doc.getElementsByTagName('image');
			i = nodes.length;
			do {
				i = i - 1;
				node = nodes[i];
				id = getNodeId(node);
				el = $(id);
				if (!el) { continue; }
				properties = {
					'src': getNodeValue(node.getElementsByTagName('src')[0]),
					'alt': getNodeValue(node.getElementsByTagName('alt')[0]),
					'width': getNodeValue(node.getElementsByTagName('width')[0]),
					'height': getNodeValue(node.getElementsByTagName('height')[0])
				};
				updateImage(el,properties);
			} while (i);
			node = doc.getElementsByTagName('button')[0];
			$('enter').setProperties({
				'width': getNodeValue(node.getElementsByTagName('width')[0]),
				'height': getNodeValue(node.getElementsByTagName('height')[0])
			});
			this.enterDefault = getNodeValue(node.getElementsByTagName('src')[0]);
			this.enterOver = getNodeValue(node.getElementsByTagName('over')[0]);
			this.enterDown = getNodeValue(node.getElementsByTagName('down')[0]);
			this.setupPage();
		},
		resetScrubberPosition: function(option) {
			var list = option.displayElement.getParent();
			var display = option.displayElement;
			var position, height, ratio, scrubberPosition;
			if (list.getParent()) {
				position = display.getTop() - (list.getStyle('marginTop').toInt() || 0) - list.getParent().getTop() - (list.getParent().getSize().size.y / 2);
				height = list.getSize().size.y;
				ratio = position / height;
				if (this.slider) {
					scrubberPosition = this.slider.trackSize * ratio;
					this.slider.setScrubberPosition(scrubberPosition);
				}
			}
		},
		sendRequest: function(locale) {
			this.request.cancel();
			this.request.url = this.basePath + locale + '.xml';
			var cached = this.cache[locale];
			if (cached && typeof cached === 'string') { this.requestSuccess('',this.cache[cached]); } // if cached but no data for locale
			else if (cached) { this.requestSuccess('',cached); } // if cached but data for locale
			else { this.request.request(); } // if not cached
		},
		setDocumentCookie: function(lang,country) {
			localize.setLanguage(lang);
			localize.setCountry(country);
		},
		setFlashCookie: function(lang,country) {
			var flashcookie = $('flashcookieWrapper');
			if (!flashcookie) {
				flashcookie = new Element('div',{'id':'flashcookieWrapper','styles':{'position':'absolute'}});
				$('frame').adopt(flashcookie);
			}
			var now = new Date().getTime();
			var swf = new SWFObject(this.swfLocation + '.swf?nocache=' + now, 'flashcookie', '1', '1', '8', '#FFFFFF');
			swf.addVariable('languageID',lang);
			swf.addVariable('countryID',country);
			swf.write('flashcookieWrapper');
		},
		setupPage: function() {
			document.getElement('.remembermeWrapper')
					.setStyle('width',this.checkbox.wrapper.getSize().size.x + document.getElement('.remembermeLabel').getSize().size.x);
			$('by_entering').getElement('.terms').addEvent('click',smirnoffPopup.pass(['terms_of_use'])).addEvent('click',stopEvent);
			$('by_entering').getElement('.privacy').addEvent('click',smirnoffPopup.pass(['privacy_statement'])).addEvent('click',stopEvent);
			$('enter').setProperty('src',this.enterDefault);
		},
		submittable: function(e) {
			var evt = new Event(e);
			var submittable = this.fieldSet.submittable();
			if (!submittable) { evt.stop(); evt.stopPropagation(); }
			else { this.validateAge(e); }
			return submittable;
		},
		submitTest: function(input) {
			var defaultValue = input.retrieve('defaultValue');
			var defaultValueLength = defaultValue.length === 2 ? '1,2' : defaultValue.length;
			var value = input.value;
			var regex = new RegExp('\\b\\d{' + defaultValueLength + '}\\b');
			return value !== defaultValue && value.match(regex);
		},
		trackDateInputBlur: $empty, // an input field loses focus
		trackDateInputFocus: $empty, // an input field gets focus
		trackDropdownChange: $empty, // the dropdown value changes
		trackDropdownSelect: $empty, // a dropdown value is selected
		trackPageLoaded: $empty, // page has loaded
		trackValidateAge: $empty, // form is submitted
		trackValidateAgeDry: $empty, // country is dry (this.age === 0)
		trackValidateAgeSuccess: $empty, // user passes age validation
		trackValidateAgeFailure: $empty, // user fails age validation (this.age > 0)
		trackWhyAsk: $empty, // why ask questions opened
		validateAge: function(e) {
			this.trackValidateAge();
			var evt = new Event(e);
			evt.stop();
			var now = new Date();
			var month = $('Month').value.toInt() - 1; // have to subtract one because of the way the Date object handles month
			var day = $('Day').value.toInt();
			var year = $('Year').value.toInt();
			var yearsDiff = now.getFullYear() - year;
			var isNotWellFormed = this.isDateNotWellFormed(day,month,year);
			$('validateLDAForm').removeEvent('submit',stopEvent);
			if (!this.age) { // select your country was selected
				return this.dropdown.dropdown.addClass('error');
			} else if (isNotWellFormed) { // if date not well formed don't try and validate
				return this.validateAgeError(isNotWellFormed);
			} else if (this.age === '0') { // dry country
				this.validateAgeFailure();
			} else if (yearsDiff > this.age || (yearsDiff == this.age && month < now.getMonth())
								|| (yearsDiff == this.age && month == now.getMonth() && day <= now.getDate())) { // of age
				this.rememberMeHandler();
				this.validateAgeSuccess();
				this.validateAgePostBack();
			} else { // underage
				this.validateAgeFailure();
			}
		},
		validateAgeError: function(isNotWellFormed) {
			var bits = isNotWellFormed.match(/(^m)?(d)?(y$)?/);
			if (bits[1]) { $('Month').addClass('error'); }
			if (bits[2]) { $('Day').addClass('error'); }
			if (bits[3]) { $('Year').addClass('error'); }
		},
		validateAgeFailure: function() {
			this.age === '0' ? this.trackValidateAgeDry() : this.trackValidateAgeFailure();
			this.dropdown.input.removeEvents().setProperty('disabled','disabled'); // disable dropdown
			this.fields.getElements('input').removeEvents().setProperty('disabled','disabled');
			$('enter').removeEvents().setProperty('disabled','disabled'); // disable enter events
			$('noEntry').removeClass('hidden');
			var forward = function() { window.location = this.failureForward; };
			this.delay = forward.delay(this.failureDelay,this);
		},
		validateAgePostBack: function() {
			if (typeof PostBack === 'undefined') { return; } // CMS function not defined, should mean a testing environment
			$('validateLDAForm').removeEvents('submit');
			PostBack('btnSubmit','');
		},
		validateAgeSuccess: function() {
			this.trackValidateAgeSuccess();
		}
	});
	var gateway = new Gateway();

})();
// Element extensions
(function() {
	var BLANK_GIF_PATH = '/Resources/Smirnoff3/global/html/images/blank.gif';
	function fixBg(el) {
		var elSrc = el.getStyle('backgroundImage');
		var bgSrc, alphaFilter, method;
		if (elSrc.match(/url\('?"?(.*\.png)"?'?\)$/) && !el.retrieve('pngFixed')) {
			bgSrc = elSrc.match(/url\('?"?(.*\.png)"?'?\)$/)[1];
			el.setStyle('backgroundImage', "url(" + BLANK_GIF_PATH + ")");
			method = el.getStyle('background-repeat') == 'no-repeat' ? 'crop' : 'scale';
			el.style.filter = 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src="' + bgSrc + '", sizingMethod="' + method + '")';
			el.store('pngFixed',true);
		}
	}
	function fixSrc(el,setDimensions) {
		var imgSrc = el.getProperty('src');
		if (imgSrc.match(/\.png$/) && !el.retrieve('pngFixed')) {
			el.setProperty('src',BLANK_GIF_PATH);
			el.setStyles({
				backgroundImage: 'none',
				filter: 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src="' + imgSrc + '", sizingMethod="scale")'
			});
			el.store('pngFixed',true);
		}
	}
	var uid = 0;
	var storage = {};
	Element.extend({
		store: function(key,value) {
			if (!this.uid) {
				uid = uid + 1;
				this.uid = uid;
				storage[this.uid] = {};
			}
			storage[this.uid][key] = value;
			return this;
		},
		retrieve: function(key) {
			return this.uid ? storage[this.uid][key] : null;
		},
		fixPng: function() {
			if (!window.ie6) { return this; }
			var tag = this.getTag();
			if (tag === 'img' || (tag === 'input' && this.getProperty('type') === 'image')) { fixSrc(this); }
			else { fixBg(this); }
			return this;
		},
		giveFocus: function() {
			this.focus();
			return this;
		}
	});
	addEvent('beforeunload',function() {
		var id;
		for (id in storage) {
			storage[id] = null;
		}
	});
})();
