/**
 * datepicker.js - MooTools Datepicker class
 * @version 1.15
 * 
 * by MonkeyPhysics.com
 *
 * Source/Documentation available at:
 * http://www.monkeyphysics.com/mootools/script/2/datepicker
 * 
 * --
 * 
 * Smoothly animating, very configurable and easy to install.
 * No Ajax, pure Javascript. 4 skins available out of the box.
 * 
 * --
 *
 * Some Rights Reserved
 * http://creativecommons.org/licenses/by-sa/3.0/
 * 
 */

var DatePicker = new Class({

	Implements: Options,

	// working date, which we will keep modifying to render the calendars
	d: '',

	// just so that we need not request it over and over
	today: '',

	// current user-choice in date object format
	choice: {}, 

	// size of body, used to animate the sliding
	bodysize: {}, 

	// to check availability of next/previous buttons
	limit: {}, 

	// element references:
	attachTo: null,    // selector for target inputs
	picker: null,      // main datepicker container
	slider: null,      // slider that contains both oldContents and newContents, used to animate between 2 different views
	oldContents: null, // used in animating from-view to new-view
	newContents: null, // used in animating from-view to new-view
	input: null,       // original input element (used for input/output)
	visual: null,      // visible input (used for rendering)

	options: { 
		pickerClass: 'datepicker',
		days: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
		months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
		dayShort: 2,
		monthShort: 3,
		startDay: 0, // Sunday (0) through Saturday (6) - be aware that this may affect your layout, since the days on the right might have a different margin
		timePicker: false,
		yearPicker: true,
		yearsPerPage: 20,
		format: 'd-m-Y',
		allowEmpty: false,
		inputOutputFormat: 'U', // default to unix timestamp
		animationDuration: 400,
		useFadeInOut: !Browser.Engine.trident, // dont animate fade-in/fade-out for IE
		startView: 'month', // allowed values: {time, month, year, decades}
		positionOffset: { x: 0, y: 0 },
		minDate: null, // { date: '[date-string]', format: '[date-string-interpretation-format]' }
		maxDate: null, // same as minDate
		debug: false,
		toggleElements: null,

		// and some event hooks:
		onShow: $empty,   // triggered when the datepicker pops up
		onClose: $empty,  // triggered after the datepicker is closed (destroyed)
		onSelect: $empty  // triggered when a date is selected
	},

	initialize: function(attachTo, options) {
		this.attachTo = attachTo;
		this.setOptions(options).attach();
		if ($chk(this.options.minDate)) this.options.minDate = this.unformat(this.options.minDate.date, this.options.minDate.format);
		if ($chk(this.options.maxDate)) {
			this.options.maxDate = this.unformat(this.options.maxDate.date, this.options.maxDate.format);
			this.options.maxDate.setHours(23);
			this.options.maxDate.setMinutes(59);
			this.options.maxDate.setSeconds(59);
		}
		document.addEvent('mousedown', this.close.bind(this));
	},

	attach: function() {
		// toggle the datepicker through a separate element?
		if ($chk(this.options.toggleElements)) {
			var togglers = $$(this.options.toggleElements);
			document.addEvents({
				'keydown': function(e) {
					if (e.key == "tab") {
						this.close(null, true);
					}
				}.bind(this)
			});
		};

		// attach functionality to the inputs
		$$(this.attachTo).each(function(item, index) {

			// never double attach
			if (item.retrieve('datepicker')) return;

			// determine starting value(s)
			if ($chk(item.get('value'))) {
				var init_clone_val = this.format(new Date(this.unformat(item.get('value'), this.options.inputOutputFormat)), this.options.format);
			} else if (!this.options.allowEmpty) {
				var init_clone_val = this.format(new Date(), this.options.format);
			} else {
				var init_clone_val = '';
			}

			// create clone
			var display = item.getStyle('display');
			var clone = item
			.setStyle('display', this.options.debug ? display : 'none')
			.store('datepicker', true) // to prevent double attachment...
			.clone()
			.store('datepicker', true) // ...even for the clone (!)
			.removeProperty('name')    // secure clean (form)submission
			.setStyle('display', display)
			.set('value', init_clone_val)
			.inject(item, 'after');

			// events
			if ($chk(this.options.toggleElements)) {
				togglers[index]
					.setStyle('cursor', 'pointer')
					.addEvents({
						'click': function(e) {
							this.onFocus(item, clone);
						}.bind(this)
					});
				clone.addEvents({
					'blur': function() {
						item.set('value', clone.get('value'));
					}
				});
			} else {
				clone.addEvents({
					'keydown': function(e) {
						if (this.options.allowEmpty && (e.key == "delete" || e.key == "backspace")) {
							item.set('value', '');
							e.target.set('value', '');
							this.close(null, true);
						} else if (e.key == "tab") {
							this.close(null, true);
						} else {
							e.stop();
						}
					}.bind(this),
					'focus': function(e) {
						this.onFocus(item, clone);
					}.bind(this)
				});
			}
		}.bind(this));
	},

	onFocus: function(original_input, visual_input) {
		var init_visual_date, d = visual_input.getCoordinates();

		if ($chk(original_input.get('value'))) {
			init_visual_date = this.unformat(original_input.get('value'), this.options.inputOutputFormat).valueOf();
		} else {
			init_visual_date = new Date();
			if ($chk(this.options.maxDate) && init_visual_date.valueOf() > this.options.maxDate.valueOf()) {
				init_visual_date = new Date(this.options.maxDate.valueOf());
			}
			if ($chk(this.options.minDate) && init_visual_date.valueOf() < this.options.minDate.valueOf()) {
				init_visual_date = new Date(this.options.minDate.valueOf());
			}
		}

		this.show({ left: d.left + this.options.positionOffset.x, top: d.top + d.height + this.options.positionOffset.y }, init_visual_date);
		this.input = original_input;
		this.visual = visual_input;
		this.options.onShow();
	},

	dateToObject: function(d) {
		return {
			year: d.getFullYear(),
			month: d.getMonth(),
			day: d.getDate(),
			hours: d.getHours(),
			minutes: d.getMinutes(),
			seconds: d.getSeconds()
		};
	},

	dateFromObject: function(values) {
		var d = new Date();
		d.setDate(1);
		['year', 'month', 'day', 'hours', 'minutes', 'seconds'].each(function(type) {
			var v = values[type];
			if (!$chk(v)) return;
			switch (type) {
				case 'day': d.setDate(v); break;
				case 'month': d.setMonth(v); break;
				case 'year': d.setFullYear(v); break;
				case 'hours': d.setHours(v); break;
				case 'minutes': d.setMinutes(v); break;
				case 'seconds': d.setSeconds(v); break;
			}
		});
		return d;
	},

	show: function(position, timestamp) {
		if ($chk(timestamp)) {
			this.d = new Date(timestamp);
		} else {
			this.d = new Date();
		}
		this.today = new Date();
		this.choice = this.dateToObject(this.d);
		this.mode = (this.options.startView == 'time' && !this.options.timePicker) ? 'month' : this.options.startView;
		this.render();
		this.picker.setStyles(position);
	},

	render: function(fx) {
		if (!$chk(this.picker)) {
			this.constructPicker();
		} else {
			// swap contents so we can fill the newContents again and animate
			var o = this.oldContents;
			this.oldContents = this.newContents;
			this.newContents = o;
			this.newContents.empty();
		}

		// remember current working date
		var startDate = new Date(this.d.getTime());

		// intially assume both left and right are allowed
		this.limit = { right: false, left: false };

		// render! booty!
		if (this.mode == 'decades') {
			this.renderDecades();
		} else if (this.mode == 'year') {
			this.renderYear();
		} else if (this.mode == 'time') {
			this.renderTime();
			this.limit = { right: true, left: true }; // no left/right in timeview
		} else {
			this.renderMonth();
		}

		this.picker.getElement('.previous').setStyle('visibility', this.limit.left ? 'hidden' : 'visible');
		this.picker.getElement('.next').setStyle('visibility', this.limit.right ? 'hidden' : 'visible');
		this.picker.getElement('.titleText').setStyle('cursor', this.allowZoomOut() ? 'pointer' : 'default');

		// restore working date
		this.d = startDate;

		// if ever the opacity is set to '0' it was only to have us fade it in here
		// refer to the constructPicker() function, which instantiates the picker at opacity 0 when fading is desired
		if (this.picker.getStyle('opacity') == 0) {
			this.picker.tween('opacity', 0, 1);
		}

		// animate
		if ($chk(fx)) this.fx(fx);
	},

	fx: function(fx) {
		if (fx == 'right') {
			this.oldContents.setStyles({ left: 0, opacity: 1 });
			this.newContents.setStyles({ left: this.bodysize.x, opacity: 1 });
			this.slider.setStyle('left', 0).tween('left', 0, -this.bodysize.x);
		} else if (fx == 'left') {
			this.oldContents.setStyles({ left: this.bodysize.x, opacity: 1 });
			this.newContents.setStyles({ left: 0, opacity: 1 });
			this.slider.setStyle('left', -this.bodysize.x).tween('left', -this.bodysize.x, 0);
		} else if (fx == 'fade') {
			this.slider.setStyle('left', 0);
			this.oldContents.setStyle('left', 0).set('tween', { duration: this.options.animationDuration / 2 }).tween('opacity', 1, 0);
			this.newContents.setStyles({ opacity: 0, left: 0}).set('tween', { duration: this.options.animationDuration }).tween('opacity', 0, 1);
		}
	},

	constructPicker: function() {
		this.picker = new Element('div', { 'class': this.options.pickerClass }).inject(document.body);
		if (this.options.useFadeInOut) {
			this.picker.setStyle('opacity', 0).set('tween', { duration: this.options.animationDuration });
		}

		var h = new Element('div', { 'class': 'header' }).inject(this.picker);
		var titlecontainer = new Element('div', { 'class': 'title' }).inject(h);
		new Element('div', { 'class': 'previous' }).addEvent('click', this.previous.bind(this)).set('text', '«').inject(h);
		new Element('div', { 'class': 'next' }).addEvent('click', this.next.bind(this)).set('text', '»').inject(h);
		new Element('div', { 'class': 'closeButton' }).addEvent('click', this.close.bindWithEvent(this, true)).set('text', 'x').inject(h);
		new Element('span', { 'class': 'titleText' }).addEvent('click', this.zoomOut.bind(this)).inject(titlecontainer);

		var b = new Element('div', { 'class': 'body' }).inject(this.picker);
		this.bodysize = b.getSize();
		this.slider = new Element('div', { styles: { position: 'absolute', top: 0, left: 0, width: 2 * this.bodysize.x, height: this.bodysize.y }})
					.set('tween', { duration: this.options.animationDuration, transition: Fx.Transitions.Quad.easeInOut }).inject(b);
		this.oldContents = new Element('div', { styles: { position: 'absolute', top: 0, left: this.bodysize.x, width: this.bodysize.x, height: this.bodysize.y }}).inject(this.slider);
		this.newContents = new Element('div', { styles: { position: 'absolute', top: 0, left: 0, width: this.bodysize.x, height: this.bodysize.y }}).inject(this.slider);
	},

	renderTime: function() {
		var container = new Element('div', { 'class': 'time' }).inject(this.newContents);

		this.picker.getElement('.titleText').set('text', this.format(this.d, 'j M, Y'));

		new Element('input', { type: 'text', 'class': 'hour' })
			.set('value', this.leadZero(this.d.getHours()))
			.addEvents({
				mousewheel: function(e) {
					var i = e.target, v = i.get('value').toInt();
					i.focus();
					if (e.wheel > 0) {
						v = (v < 23) ? v + 1 : 0;
					} else {
						v = (v > 0) ? v - 1 : 23;
					}
					i.set('value', this.leadZero(v));
					e.stop();
				}.bind(this)
			})
			.set('maxlength', 2)
			.inject(container);

		new Element('input', { type: 'text', 'class': 'minutes' })
			.set('value', this.leadZero(this.d.getMinutes()))
			.addEvents({
				mousewheel: function(e) {
					var i = e.target, v = i.get('value').toInt();
					i.focus();
					if (e.wheel > 0) {
						v = (v < 59) ? v + 1 : 0;
					} else {
						v = (v > 0) ? v - 1 : 59;
					}
					i.set('value', this.leadZero(v));
					e.stop();
				}.bind(this)
			})
			.set('maxlength', 2)
			.inject(container);

		new Element('div', { 'class': 'separator' }).set('text', ':').inject(container);

		new Element('input', { type: 'submit', value: 'OK', 'class': 'ok' })
			.addEvents({
				click: function(e) {
					e.stop();
					this.select($merge(this.dateToObject(this.d), { hours: this.picker.getElement('.hour').get('value').toInt(), minutes: this.picker.getElement('.minutes').get('value').toInt() }));
				}.bind(this)
			})
			.set('maxlength', 2)
			.inject(container);
	},

	renderMonth: function() {
		var month = this.d.getMonth();

		this.picker.getElement('.titleText').set('text', this.options.months[month] + ' ' + this.d.getFullYear());

		this.d.setDate(1);
		while (this.d.getDay() != this.options.startDay) {
			this.d.setDate(this.d.getDate() - 1);
		}

		var container = new Element('div', { 'class': 'days' }).inject(this.newContents);
		var titles = new Element('div', { 'class': 'titles' }).inject(container);
		var d, i, classes, e, weekcontainer;

		for (d = this.options.startDay; d < (this.options.startDay + 7); d++) {
			new Element('div', { 'class': 'title day day' + (d % 7) }).set('text', this.options.days[(d % 7)].substring(0,this.options.dayShort)).inject(titles);
		}

		var available = false;
		var t = this.today.toDateString();
		var currentChoice = this.dateFromObject(this.choice).toDateString();

		for (i = 0; i < 42; i++) {
			classes = [];
			classes.push('day');
			classes.push('day'+this.d.getDay());
			if (this.d.toDateString() == t) classes.push('today');
			if (this.d.toDateString() == currentChoice) classes.push('selected');
			if (this.d.getMonth() != month) classes.push('otherMonth');

			if (i % 7 == 0) {
				weekcontainer = new Element('div', { 'class': 'week week'+(Math.floor(i/7)) }).inject(container);
			}

			e = new Element('div', { 'class': classes.join(' ') }).set('text', this.d.getDate()).inject(weekcontainer);
			if (this.limited('date')) {
				e.addClass('unavailable');
				if (available) {
					this.limit.right = true;
				} else if (this.d.getMonth() == month) {
					this.limit.left = true;
				}
			} else {
				available = true;
				e.addEvent('click', function(e, d) {
					if (this.options.timePicker) {
						this.d.setDate(d.day);
						this.d.setMonth(d.month);
						this.mode = 'time';
						this.render('fade');
					} else {
						this.select(d);
					}
				}.bindWithEvent(this, { day: this.d.getDate(), month: this.d.getMonth(), year: this.d.getFullYear() }));
			}
			this.d.setDate(this.d.getDate() + 1);
		}
		if (!available) this.limit.right = true;
	},

	renderYear: function() {
		var month = this.today.getMonth();
		var thisyear = this.d.getFullYear() == this.today.getFullYear();
		var selectedyear = this.d.getFullYear() == this.choice.year;

		this.picker.getElement('.titleText').set('text', this.d.getFullYear());
		this.d.setMonth(0);

		var i, e;
		var available = false;
		var container = new Element('div', { 'class': 'months' }).inject(this.newContents);

		for (i = 0; i <= 11; i++) {
			e = new Element('div', { 'class': 'month month'+(i+1)+(i == month && thisyear ? ' today' : '')+(i == this.choice.month && selectedyear ? ' selected' : '') })
			.set('text', this.options.monthShort ? this.options.months[i].substring(0, this.options.monthShort) : this.options.months[i]).inject(container);

			if (this.limited('month')) {
				e.addClass('unavailable');
				if (available) {
					this.limit.right = true;
				} else {
					this.limit.left = true;
				}
			} else {
				available = true;
				e.addEvent('click', function(e, d) {
					this.d.setDate(1);
					this.d.setMonth(d);
					this.mode = 'month';
					this.render('fade');
				}.bindWithEvent(this, i));
			}
			this.d.setMonth(i);
		}
		if (!available) this.limit.right = true;
	},

	renderDecades: function() {
		// start neatly at interval (eg. 1980 instead of 1987)
		while (this.d.getFullYear() % this.options.yearsPerPage > 0) {
			this.d.setFullYear(this.d.getFullYear() - 1);
		}

		this.picker.getElement('.titleText').set('text', this.d.getFullYear() + '-' + (this.d.getFullYear() + this.options.yearsPerPage - 1));

		var i, y, e;
		var available = false;
		var container = new Element('div', { 'class': 'years' }).inject(this.newContents);

		if ($chk(this.options.minDate) && this.d.getFullYear() <= this.options.minDate.getFullYear()) {
			this.limit.left = true;
		}

		for (i = 0; i < this.options.yearsPerPage; i++) {
			y = this.d.getFullYear();
			e = new Element('div', { 'class': 'year year' + i + (y == this.today.getFullYear() ? ' today' : '') + (y == this.choice.year ? ' selected' : '') }).set('text', y).inject(container);

			if (this.limited('year')) {
				e.addClass('unavailable');
				if (available) {
					this.limit.right = true;
				} else {
					this.limit.left = true;
				}
			} else {
				available = true;
				e.addEvent('click', function(e, d) {
					this.d.setFullYear(d);
					this.mode = 'year';
					this.render('fade');
				}.bindWithEvent(this, y));
			}
			this.d.setFullYear(this.d.getFullYear() + 1);
		}
		if (!available) {
			this.limit.right = true;
		}
		if ($chk(this.options.maxDate) && this.d.getFullYear() >= this.options.maxDate.getFullYear()) {
			this.limit.right = true;
		}
	},

	limited: function(type) {
		var cs = $chk(this.options.minDate);
		var ce = $chk(this.options.maxDate);
		if (!cs && !ce) return false;

		switch (type) {
			case 'year':
				return (cs && this.d.getFullYear() < this.options.minDate.getFullYear()) || (ce && this.d.getFullYear() > this.options.maxDate.getFullYear());

			case 'month':
				// todo: there has got to be an easier way...?
				var ms = ('' + this.d.getFullYear() + this.leadZero(this.d.getMonth())).toInt();
				return cs && ms < ('' + this.options.minDate.getFullYear() + this.leadZero(this.options.minDate.getMonth())).toInt()
					|| ce && ms > ('' + this.options.maxDate.getFullYear() + this.leadZero(this.options.maxDate.getMonth())).toInt()

			case 'date':
				return (cs && this.d < this.options.minDate) || (ce && this.d > this.options.maxDate);
		}
	},

	allowZoomOut: function() {
		if (this.mode == 'decades') return false;
		if (this.mode == 'year' && !this.options.yearPicker) return false;
		return true;
	},

	zoomOut: function() {
		if (!this.allowZoomOut()) return;
		if (this.mode == 'year') {
			this.mode = 'decades';
		} else if (this.mode == 'time') {
			this.mode = 'month';
		} else {
			this.mode = 'year';
		}
		this.render('fade');
	},

	previous: function() {
		if (this.mode == 'decades') {
			this.d.setFullYear(this.d.getFullYear() - this.options.yearsPerPage);
		} else if (this.mode == 'year') {
			this.d.setFullYear(this.d.getFullYear() - 1);
		} else if (this.mode == 'month') {
			this.d.setMonth(this.d.getMonth() - 1);
		}
		this.render('left');
	},

	next: function() {
		if (this.mode == 'decades') {
			this.d.setFullYear(this.d.getFullYear() + this.options.yearsPerPage);
		} else if (this.mode == 'year') {
			this.d.setFullYear(this.d.getFullYear() + 1);
		} else if (this.mode == 'month') {
			this.d.setMonth(this.d.getMonth() + 1);
		}
		this.render('right');
	},

	close: function(e, force) {
		if (!$(this.picker)) return;
		var clickOutside = ($chk(e) && e.target != this.picker && !this.picker.hasChild(e.target) && e.target != this.visual);
		if (force || clickOutside) {
			if (this.options.useFadeInOut) {
				this.picker.set('tween', { duration: this.options.animationDuration / 2, onComplete: this.destroy.bind(this) }).tween('opacity', 1, 0);
			} else {
				this.destroy();
			}
		}
	},

	destroy: function() {
		this.picker.destroy();
		this.picker = null;
		this.options.onClose();
	},

	select: function(values) {
		this.choice = $merge(this.choice, values);
		var d = this.dateFromObject(this.choice);
		this.input.set('value', this.format(d, this.options.inputOutputFormat));
		this.visual.set('value', this.format(d, this.options.format));
		this.options.onSelect();
		this.close(null, true);
	},

	leadZero: function(v) {
		return v < 10 ? '0'+v : v;
	},

	format: function(t, format) {
		var f = '';
		var h = t.getHours();
		var m = t.getMonth();

		for (var i = 0; i < format.length; i++) {
			switch(format.charAt(i)) {
				case '\\': i++; f+= format.charAt(i); break;
				case 'y': f += (100 + t.getYear() + '').substring(1); break
				case 'Y': f += t.getFullYear(); break;
				case 'm': f += this.leadZero(m + 1); break;
				case 'n': f += (m + 1); break;
				case 'M': f += this.options.months[m].substring(0,this.options.monthShort); break;
				case 'F': f += this.options.months[m]; break;
				case 'd': f += this.leadZero(t.getDate()); break;
				case 'j': f += t.getDate(); break;
				case 'D': f += this.options.days[t.getDay()].substring(0,this.options.dayShort); break;
				case 'l': f += this.options.days[t.getDay()]; break;
				case 'G': f += h; break;
				case 'H': f += this.leadZero(h); break;
				case 'g': f += (h % 12 ? h % 12 : 12); break;
				case 'h': f += this.leadZero(h % 12 ? h % 12 : 12); break;
				case 'a': f += (h > 11 ? 'pm' : 'am'); break;
				case 'A': f += (h > 11 ? 'PM' : 'AM'); break;
				case 'i': f += this.leadZero(t.getMinutes()); break;
				case 's': f += this.leadZero(t.getSeconds()); break;
				case 'U': f += Math.floor(t.valueOf() / 1000); break;
				default:  f += format.charAt(i);
			}
		}
		return f;
	},

	unformat: function(t, format) {
		var d = new Date();
		var a = {};
		var c, m;

		for (var i = 0; i < format.length; i++) {
			c = format.charAt(i);
			switch(c) {
				case '\\': r = null; i++; break;
				case 'y': r = '[0-9]{2}'; break;
				case 'Y': r = '[0-9]{4}'; break;
				case 'm': r = '0[1-9]|1[012]'; break;
				case 'n': r = '[1-9]|1[012]'; break;
				case 'M': r = '[A-Za-z]{'+this.options.monthShort+'}'; break;
				case 'F': r = '[A-Za-z]+'; break;
				case 'd': r = '0[1-9]|[12][0-9]|3[01]'; break;
				case 'j': r = '[1-9]|[12][0-9]|3[01]'; break;
				case 'D': r = '[A-Za-z]{'+this.options.dayShort+'}'; break;
				case 'l': r = '[A-Za-z]+'; break;
				case 'G': 
				case 'H': 
				case 'g': 
				case 'h': r = '[0-9]{1,2}'; break;
				case 'a': r = '(am|pm)'; break;
				case 'A': r = '(AM|PM)'; break;
				case 'i': 
				case 's': r = '[012345][0-9]'; break;
				case 'U': r = '-?[0-9]+$'; break;
				default:  r = null;
			}

			if ($chk(r)) {
				m = t.match('^'+r);
				if ($chk(m)) {
					a[c] = m[0];
					t = t.substring(a[c].length);
				} else {
					if (this.options.debug) alert("Fatal Error in DatePicker\n\nUnexpected format at: '"+t+"' expected format character '"+c+"' (pattern '"+r+"')");
					return d;
				}
			} else {
				t = t.substring(1);
			}
		}

		for (c in a) {
			var v = a[c];
			switch(c) {
				case 'y': d.setFullYear(v < 30 ? 2000 + v.toInt() : 1900 + v.toInt()); break; // assume between 1930 - 2029
				case 'Y': d.setFullYear(v); break;
				case 'm':
				case 'n': d.setMonth(v - 1); break;
				// FALL THROUGH NOTICE! "M" has no break, because "v" now is the full month (eg. 'February'), which will work with the next format "F":
				case 'M': v = this.options.months.filter(function(item, index) { return item.substring(0,this.options.monthShort) == v }.bind(this))[0];
				case 'F': d.setMonth(this.options.months.indexOf(v)); break;
				case 'd':
				case 'j': d.setDate(v); break;
				case 'G': 
				case 'H': d.setHours(v); break;
				case 'g': 
				case 'h': if (a['a'] == 'pm' || a['A'] == 'PM') { d.setHours(v == 12 ? 0 : v.toInt() + 12); } else { d.setHours(v); } break;
				case 'i': d.setMinutes(v); break;
				case 's': d.setSeconds(v); break;
				case 'U': d = new Date(v.toInt() * 1000);
			}
		};

		return d;
	}
});

window.addEvent('domready', function() {
	/**
	 * Initial variable declarations
	 */
	var message_count = 0;
	var timer;
	var saved;

	/**
	 * Position container for system messages
	 */

	if ($('fra_msg_container')) {
		$('fra_msg_container').setStyle('position', 'absolute');
	}
	/**
	 *	Create embossed text
	 */
	$each($$('.header_text'), function(el) {
		el.adopt(
			new Element(
				'h2',
				{
					'class': 'shade',
					'text': el.getElement('h2').get('text')
				}
			)
		)
	});
	/**
	 * Create drop-shadow for base_table headers
	 *              /
	$each($$('.base_table th'), function(el) {
		el.adopt(
			new Element(
				'div',
				{
					'class': 'shade',
					'text': el.get('text')
				}
			)
		)
	});
	/**/
	/**
	 * Close parent frame
	 */
	$each($$('.hide_parent_frame'), function(el) {
		el.addEvent('click', function(e) {
			e.stop();
			
			target_frame = this.get('rel');
			$(target_frame).addClass('hidden');
		});
	});
	function close_all_messages() {
		$('fra_close_all_messages').removeClass('hidden');
		$('fra_close_all_messages').addEvent('click', function() {
			$('fra_msg_container').empty();
			message_count = 0;
		});
	}

	if ($('fra_close_all_messages')) {
		close_all_messages();
/*		$('fra_close_all_messages').removeClass('hidden');
		$('fra_close_all_messages').addEvent('click', function() {
			$('fra_msg_container').empty();
			messages_count = 0;
		});
*/
	}
	/**
	 * Hide specified form
	 */
	$each($$('.form_cancel'), function(el) {
		el.addEvent('click', function(e) {
			e.stop();
			$(el.rel).addClass('hidden');
		});
	});

	/**
	 * Build error/notice messages
	 * primarily for JSON-returned messages
	 */
	function generate_message(message_type, message_text) {
		$('fra_msg_container').adopt(
			new Element('div',
				{
					'class': 'msg ' + message_type
				}
			).adopt(
				new Element('img',
					{
						'src': DIR_MAIN + DIR_IMAGES + '/layout/btn_msg_close.gif',
						'class': 'msg_close',
						'alt': 'Close this message',
						'align': 'top',
						'events': {
							'click': function(el) {
								this.getParent().destroy();
								--message_count;
							}
						}
					}
				),
				new Element('div',
					{
						'class': 'msg_text',
						'html': ((message_type == 'error') ? '<b>ERROR:</b> ' : '') + message_text
					}
				),
				new Element('div',
					{
						'class': 'clear'
					}
				)
			)
		);
		++message_count;
		if (message_count >= 2) {
			if (!$('fra_close_all_messages')) {
				var fra_close_all = new Element('div',
					{
						'class': 'msg hidden',
						'id': 'fra_close_all_messages',
						'html': '<div class="msg_text">Click Here to Hide All Messages</div><div class="clear"></div>'
					}
				).inject($('fra_msg_container'), 'top');

				close_all_messages();
			}
		}
	}

	if ($('tbl_grouped')) {
		$('lnk_chrono').removeClass('hidden');

		$('lnk_chrono').addEvent('click', function(el) {
			$('lnk_grouped').removeClass('hidden');
			$('lnk_chrono').addClass('hidden');
			$('tbl_grouped').addClass('hidden');
			$('tbl_chrono').removeClass('hidden');
		});
		$('lnk_grouped').addEvent('click', function(el) {
			$('lnk_chrono').removeClass('hidden');
			$('lnk_grouped').addClass('hidden');
			$('tbl_chrono').addClass('hidden');
			$('tbl_grouped').removeClass('hidden');
		});
	}
	$each($$('.autocomplete'), function(el) {
		switch (el.name) {
			default:
			case 'athlete_name':
			case 'student_name':
				use_tokens = tokens_students;
			break;
		}
		/*
		new Autocompleter.Local(el, use_tokens, {
			'minLength': 1, // We need at least 1 character
			'selectMode': 'true', // Instant completion
			'relative': 'true',
			'filterSubset': 'true',
			'multiple': false // Tag support, by default comma separated
		});
		new Meio.Autocomplete(el, use_tokens, {
			minChars: 1,
			filter: {
				type: 'contains',
				path: 'name'
			}
			
		});
		*/
		var target_hidden = el.get('ref');

		new Meio.Autocomplete.Select(el, use_tokens, {
			minChars: 1,
			selectOnTab: true,
			valueField: $(target_hidden),
			valueFilter: function(data) {
				return data.id;
			},
			filter: {
				type: 'contains',
				path: 'name'
			},
			listOptions: {
				classes: {
					container: 'autocompleter-choices'
				}
			},
			onNoItemToList: function(elements) {
				// On donation form -- old system || new system
				if (page_id == 'df1' || page_id == 'df0') {
					$('student_no_choice').removeClass('hidden');
				}
				// Old system in use
				if (page_id == 'df1') {
					$('txt_student_id').value = '-99';
				}
			},
			onSelect: function() {
				if (page_id == 'df1' || page_id == 'df0') {
					$('student_no_choice').addClass('hidden');
				}
			}
		});
	});

	// Initialize date selectors
	$$('input.date').each( function(el){
		new DatePicker(el, {
			inputOutputFormat: 'Y-m-d',
			format: 'm/d/Y',
			positionOffset: {x: 0, y: -268},
			allowEmpty: true
		});
	});

	// Add close function to any close buttons on messages
	$each($$('.msg_close'), function(el) {
		// el.removeEvent('click', function() {});
		el.addEvent('click', function() {
			el.getParent().destroy();
		});
	});

	// Handle form-cancel button
	var add_form_cancel = function(button_id, form_el) {
		button_id.addEvent('click', function(e) {
			var e = new Event(e).stop();
			form_el.addClass('hidden');
		});
	}

	// Handle form-accept button
	var add_form_accept = function(button_id, form_el, select_list, sel_el, sel_hi) {
		button_id.addEvent('click', function(e) {
			var e = new Event(e).stop();
			if (select_list.options.selectedIndex < 0) { return false; }
			if (select_list.options[select_list.options.selectedIndex].value == 0) { return false; }
			sel_el.set('value', select_list.options[select_list.options.selectedIndex].innerHTML);
			sel_hi.set('value', select_list.options[select_list.options.selectedIndex].value);
			form_el.addClass('hidden');
		});
	}
	// Button to add new team
	if ($('btn_new_team')) {
		$('btn_new_team').addEvent('click', function() {
			$('fra_new_team').removeClass('hidden');
		});
		$('sel_new_team_coach').addEvent('change', function() {
			if (this.options[this.options.selectedIndex].value == '-8') {
				$('fra_coach_form').removeClass('hidden');
			} else {
				$('fra_coach_form').addClass('hidden');
			}
		});
	}

	if ($('btn_new_school')) {
		$('btn_new_school').addEvent('click', function() {
			$('fra_new_school').removeClass('hidden');
		});
	}

	// Add hover state to buttons with class "button"
	$each($$('.button'), function(el) {
		if (el.src) {
			el.addEvent('mouseover', function(e) {
				el.set('src', this.src.replace('0.png', '1.png'));
			});
			el.addEvent('mouseout', function(e) {
				el.set('src', this.src.replace('1.png', '0.png'));
			});
		}
	});

	if ($('discount_frame')) {
		$each($$('.discount_box'), function(el) {
			el.addEvent('mouseover', function(e) {
				el.setStyle('background-position', '0 -160px');
			});
			el.addEvent('mouseout', function(e) {
				el.setStyle('background-position', '0 0');
			});
		});
	}
	if ($('cbox_show_letter')) {
		$('cbox_show_letter').addEvent('click', function(el) {
			if (this.checked) {
				$('row_l1').removeClass('hidden');
				//$('row_l2').removeClass('hidden');
			} else {
				$('row_l1').addClass('hidden');
				//$('row_l2').addClass('hidden');
			}

		});
	}

	// Modal operation
	if ($('fb-modal')) {
		// hide using opacity on page load
		$('fb-modal').setStyles({
			opacity:0,
			display:'block'
		});
		// hiders
		$('fb-close').addEvent('click',function(e) { $('fb-modal').fade('out'); });
		window.addEvent('keypress',function(e) { if(e.key == 'esc') { $('fb-modal').fade('out'); } });
		$(document.body).addEvent('click',function(e) { 
			if($('fb-modal').get('opacity') == 1 && !e.target.getParent('.generic_dialog')) { 
				$('fb-modal').fade('out'); 
			} 
		});
		// click to show
		$('discount_bar').addEvent('click',function() {
			$('fb-modal').fade('in');
			$('fb-modal').removeClass('hidden');
		});
	}

	// If true, user is on donation page
	if ($('frm_donate')) {
		$('lnk_cvv_help').addEvents({
			'mouseover': function() {
				$('fra_cvv_info').removeClass('hidden');
			},
			'mouseout': function() {
				$('fra_cvv_info').addClass('hidden');
			}
		});
		$each($$('.discount_box a'), function(el) {
			el.addEvent('click', function(e) {
				// var e = new Event(e).stop();

			});
		});

		$$('#block_amount input').setStyle('display', 'none');

		// Generate link-style submit button
		// <noscript> will put generic button otherwise
		// $('fra_lnk_submit').addClass('info_block');
		var donation_form_submitted = false;
		$('fra_submit').addClass('hidden');
		$('fra_lnk_submit').adopt(
			new Element('div', {'class': 'center'}).adopt(
				new Element('a', {
					'class': 'submit_link',
					'text': 'Make Donation',
					'events': {
						'click': function() {
							init_events('clear_default');
							this.set('text', 'Sending...');
							if (donation_form_submitted === false) {
								$('frm_donate').submit();
							}
							donation_form_submitted = true;
						}
					}
				})
			)
		);

		init_events = function(run_command) {
			$each($$('.text'), function(field_el) {
				field_id = field_el.id;

				if (!$(field_id).get('rel')) return false;

				if (run_command == 'clear_default') {
					if ($(field_id).value == $(field_id).get('rel')) {
						$(field_id).value = '';
					}
					return false;
				}

				if ($(field_id).value == '' || $(field_id).value == $(field_id).get('rel')) {
					$(field_id).value = $(field_id).get('rel');
					$(field_id).addClass('blank_field');
				}

				$(field_id).addEvents({
					'focus': function() {
						if (this.value == this.get('rel')) {
							this.value = '';
							this.removeClass('blank_field');
						} else {
							this.removeClass('blank_field');
						}
					},
					'blur': function() {
						if (this.value == '') {
							this.value = this.get('rel');
							this.addClass('blank_field');
						}
					}
				});
			});
		}
		// Turn preset messages into clickable inputs
		$each($$('#block_message label'), function(el) {
			var rid = el.get('for');
			$(rid).addEvent('click', function() {
				$('txt_message').set('value', el.get('text')).focus();
			});
		});
		$each($$('.discount_box'), function(el) {
			el.addEvent('mouseover', function(element) {
				this.addClass('highlight');
			});
			el.addEvent('mouseout', function(element) {
				el.removeClass('highlight');
			});
		});

		$('summary_student').addEvent('click', function() {
			$('txt_student').focus();
		});

		var donate_amount_previous = 50;
		$each($$('.amount_box label a'), function(el) {
			if (el.hasClass('nojsselected')) {
				el.addClass('selected');
			}
			if (el.hasClass('selected')) {
				$('summary_amount').set('text', '$' + el.get('rel'));
			}
			el.addEvent('click', function(e) {
				var e = new Event(e).stop();
				var amount = el.get('rel');
				$('rad_amount_' + amount).set('checked', true);
				if (donate_amount_previous > 0) {
					$('lbl_' + donate_amount_previous).removeClass('selected');
				}
				donate_amount_previous = amount;
				el.addClass('selected');
				if ($('txt_student').value !== '' && $('txt_student').value !== '(student\'s name)') {
					var student_name = $('txt_student').value;
				} else {
					var student_name = 'the student of your choice';
				}
				$('summary_amount').set('text', '$' + amount);
			});
		});
		if ($('txt_student')) {
			$('txt_student').addEvent('blur', function() {
				$('summary_student').set('text', this.value);
			});
		}

		init_events('default');

		$('frm_donate').addEvent('submit', function(e) {
			init_events('clear_default');
		});
	}

	$each($$('.sel_relation_list'), function(select_list) {
		var sel_name = select_list.get('name');
		var sel_el = $('txt_' + sel_name);
		var sel_hi = $('txt_' + sel_name + '_id');
		var sel_fr = $('fra_' + sel_name);
		var btn_ca = $('btn_cancel_' + sel_name);
		var btn_ac = $('btn_accept_' + sel_name);

		sel_el.addEvent('focus', function() {
			sel_fr.removeClass('hidden');
		});
		add_form_accept(btn_ac, sel_fr, select_list, sel_el, sel_hi);
		add_form_cancel(btn_ca, sel_fr);
	});

	var add_button_events = function(btn_id, fra_to_toggle) {
		$(btn_id).addEvents({
			'mouseover': function() {
				this.setStyle('background-position', '0px -51px');
			},
			'mouseout': function() {
				this.setStyle('background-position', '0px 0px');
			},
			'click': function() {
				fra_to_toggle.removeClass('hidden');
			}
		});
	}
	if ($('btn_add_coach')) {
		add_button_events('btn_add_coach', $('side_form'));
		add_form_cancel($('btn_cancel'), $('side_form'));
	}
	if ($('btn_add_team')) {
		add_button_events('btn_add_team', $('side_form'));
		add_form_cancel($('btn_cancel'), $('side_form'));
	}
	if ($('btn_add_rep')) {
		add_button_events('btn_add_rep', $('side_form'));
		add_form_cancel($('btn_cancel'), $('side_form'));
	}
	if ($('btn_add_school')) {
		add_button_events('btn_add_school', $('side_form'));
		add_form_cancel($('btn_cancel'), $('side_form'));
	}
	if ($('btn_new_campaign')) {
		add_button_events('btn_new_campaign', $('side_form'));
		add_form_cancel($('btn_cancel'), $('side_form'));
	}
	// Run calculation on campaign page
	if ($('txt_kids_in_program')) {
		var calculation_box = new Element('div', {id: 'fra_calculation'}).adopt(
			new Element('span')
		);
	}
	if ($('lnk_rep_add_school')) {
		$('lnk_rep_add_school').addEvent('click', function(e) {
			var e = new Event(e).stop();
			$('fra_select_school').removeClass('hidden');
		});
		$('lnk_new_school').addEvent('click', function(e) {
			var e = new Event(e).stop();

		});
	}
	// Give corners to panels
	$each($$('.panel_container'), function(el) {
		var ctl = new Element('div', {'class': 'panel_corner top_left'}).inject(el);
		var ctr = new Element('div', {'class': 'panel_corner top_right'}).inject(el);
		var cbl = new Element('div', {'class': 'panel_corner bottom_left'}).inject(el);
		var cbr = new Element('div', {'class': 'panel_corner bottom_right'}).inject(el);
	});
	/**
	 * Check-entry autocompletion
	 */
	/*
	new Meio.Autocomplete.Select('txt_athlete', tokens_students, {
		minChars: 0,
		selectOnTab: true,
		filter: {
			type: 'contains',
			path: 'name'
		},
		listOptions: {
			classes: {
				container: 'autocompleter-choices'
			}
		}
	});
	*/
	/**
	 * Controller for toggling student containers
	 */
	$each($$('.expand_student'), function(el) {
		var id = el.get('rel');
		var data_holder = $('student-' + id);
		var img_handle = $('expand-' + id);
		var row_student = $('row-' + id);

		el.addEvent('click', function(e) {
			var e = new Event(e).stop();
			if (data_holder.hasClass('hidden')) {
				data_holder.removeClass('hidden');
				img_handle.set('src', DIR_MAIN + '/images/layout/img_data_close.png');
				row_student.addClass('student_highlight');
			} else {
				data_holder.addClass('hidden');
				img_handle.set('src', DIR_MAIN + '/images/layout/img_data_expand.png');
				row_student.removeClass('student_highlight');
			}
		});
	});
	/**
	 * Controller for toggling team groups
	 */
	$each($$('.expand_group'), function(el) {
		var id = el.get('rel');
		var data_holder = $('group_members_' + id);
		var img_handle = $('expand_group_' + id);
		var row_student = $('group_row_' + id);

		if (row_student) {
			el.addEvent('click', function(e) {
				var e = new Event(e).stop();
				if (data_holder.hasClass('hidden')) {
					data_holder.removeClass('hidden');
					img_handle.set('src', DIR_MAIN + '/images/layout/img_data_close.png');
				} else {
					data_holder.addClass('hidden');
					img_handle.set('src', DIR_MAIN + '/images/layout/img_data_expand.png');
				}
			});
		}
	});
	// To expand student donation information
	$each($$('.expand_donations'), function(el) {
		var id = el.get('rel');
		var data_holder = $('student_donations_' + id);
		var img_handle = $('expand_student_' + id);
		var row_student = $('student_row_' + id);

		el.addEvent('click', function(e) {
			var e = new Event(e).stop();
			if (data_holder.hasClass('hidden')) {
				data_holder.removeClass('hidden');
				img_handle.set('src', DIR_MAIN + '/images/layout/img_data_close.png');
				row_student.addClass('highlight');
			} else {
				data_holder.addClass('hidden');
				img_handle.set('src', DIR_MAIN + '/images/layout/img_data_expand.png');
				row_student.removeClass('highlight');
			}
		});
	});

	if ($('expand_all')) {
		$('expand_all').addEvent('click', function(e) {
			var e = new Event(e).stop();
			$$('.expander').removeClass('hidden');
			$$('.highlighter').addClass('highlight');
			$$('.handle').set('src', DIR_MAIN + '/images/layout/img_data_close.png');
		});
		$('collapse_all').addEvent('click', function(e) {
			var e = new Event(e).stop();
			$$('.expander').addClass('hidden');
			$$('.highlighter').removeClass('highlight');
			$$('.handle').set('src', DIR_MAIN + '/images/layout/img_data_expand.png');
		});
	}

	if ($('example_code')) {
		var example_rendered = false;
		var example_displayed = false;

		$('example_code').addEvent('click', function(e) {
			var e = new Event(e).stop();
			if (example_displayed === false) {
				if (example_rendered === false) {
					var example = new Element('div', {
						'class': 'example_image', 'id': 'example_container', 'events': {
							'click': function() {
								$('example_container').hide();
								$('txt_campaign_code').focus();
								example_displayed = false;
							}
						}
					}).adopt(
						new Element('img', {'src': DIR_MAIN + '/images/layout/img_example_letter_campaign_code.png', 'class': 'block'})
					).inject($('frm_team_info'));

					example_rendered = true;
				}
				$('txt_campaign_code').focus();
				$('example_container').show();
				example_displayed = true;
			} else {
				$('txt_campaign_code').focus();
				$('example_container').hide();
				example_displayed = false;
			}

		});
	}

	// "Kids In Program" field -- should only be on setup page
	if ($('txt_campaign_size')) {
		$('txt_campaign_size').addEvent('change', function() {
			var fee = fees[this.options[this.options.selectedIndex].value];
			$('txt_letter_fee').value = '$' + fee;
		});
	}

	// Team Info Form
	if ($('frm_team_info')) {
		var card_flipped = false;
		$('discount_bar').addEvent('click', function(e) {
			if (card_flipped === false) {
				this.addClass('back');
				card_flipped = true;
			} else {
				this.removeClass('back');
				card_flipped = false;
			}
		});
	}
	if ($('discount_bar')) {
		$('discount_bar').addEvents({
			'mouseover': function() {
				$('free_gift_notice').removeClass('hidden');
			},
			'mouseout': function() {
				$('free_gift_notice').addClass('hidden');
			}
		});
	}

	if ($('check_entry')) {
		$('sel_amount').addEvent('change', function() {
			var option = this.options[this.options.selectedIndex].value;
			if (option === 'other') {
				$('txt_amount').value = '$';
				$('txt_amount').focus();
			} else {
				$('txt_amount').value = '$' + this.options[this.options.selectedIndex].value;
			}
		});
	}
	/**
	 * Panel Campaign Viewer
	 */
	if (page_id == 'panel_campaign_viewer') {
		$each($$('.select_amount'), function(el) {
			el.addEvent('change', function() {
				target_id = this.id.substring(11);
				var option = this.options[this.options.selectedIndex].value;
				if (option === 'other') {
					$('txt_m_amo_' + target_id).value = '$';
					$('txt_m_amo_' + target_id).focus();
				} else {
					$('txt_m_amo_' + target_id).value = '$' + this.options[this.options.selectedIndex].value;
				}
			});
		});
		/**
		 * Load form for adding multiple checks
		 */
		$('multiple_check_entry').setStyles({
			position: 'absolute',
			left: '100px',
			top: '120px'
		});
		$('lnk_add_multiple_checks').addEvent('click', function(e) {
			e.stop();
			
			$('multiple_check_entry').removeClass('hidden');
		});
		/**
		 * Allow use of up & down keys to navigate between cells
		 */
		$each($$('.cell_nav'), function(el) {
			el.addEvent('keydown', function(e) {
				target_cell = this.id.substring(0, 10);
				current_id = parseInt(this.id.substring(10));
				if (e.key == 'down' && (current_id + 1) < check_fields) {
					$(target_cell + (++current_id)).focus();
				} else if (e.key == 'up' && current_id > 0) {
					$(target_cell + (--current_id)).focus();
				}
			});
		});
	}
	/**
	 * Team manager
	 */
	if (page_id == 'panel_campaign_teams') {
		var selected_student_id = 0;
		/**
		 *	Show create-a-team form
		 */
		$('btn_create_team').addEvent('click', function(e) {
			new Event(e).stop();

			if ($('frm_add_team').hasClass('hidden')) {
				$('frm_add_team').removeClass('hidden');
			} else {
				$('frm_add_team').addClass('hidden');
			}
		});

		$('form_create_team').addEvent('submit', function(e) {
			e.stop();

			this.set('send',
			{
				onRequest: function() {
					// Stuff to do when request sent
				},
				onComplete: function(response) {
					// Stuff to do with response
					var data = JSON.decode(response);
					if (data.show_message === true) {
						generate_message(data.type, data.text);
					}

					if (data.extra != '') {
						$('list_teams').adopt(
							new Element('li',
								{
									'html': '<a href="#" id="group_' + data.extra.team_id + '">' + data.extra.team_name + '</a><div id="group_delete_' + data.extra.team_id + '" class="hidden group_delete"><img src="' + DIR_MAIN + '/images/layout/btn_delete.png" /></div>'
								}
							)
						);
					}

					if (data.type != 'error') {
						selectable_teams();
						$('frm_add_team').addClass('hidden');
						$('txt_team_name').value = '';
						if ($('lbl_no_teams')) {
							$('lbl_no_teams').addClass('hidden');
						}
					}
				}
			}).send();
		});
		/**
		 * File upload usability enhancement
		 */
		var max_file_length = 13;
		$('file_excel_students').addEvent('change', function(e) {
			file_name = this.value;
			file_name_length = this.value.length;
			file_ext = file_name.substr(file_name_length-3, 3);
			
			$('lbl_file_name').set('title', 'Selected file: ' + file_name);
			if (file_name_length > max_file_length) {
				file_name = this.value.substring(0, max_file_length) + '...' + file_ext;
			}
			$('lbl_file_name').set('html', '<b>File:</b> ' + file_name);

			/**
			 * Warn if file type not correct
			 */
			if (file_ext != 'xls') {
				$('lbl_file_name').set('html', '<b>File may be incorrect format</b>\r\n' + $('lbl_file_name').get('html'));
				$('lbl_file_name').addClass('msg error');
			} else {
				$('lbl_file_name').removeClass('msg error');
			}
		});
		/**
		 * Edit currently selected student
		 */
		function edit_student() {
			if (selected_student_id <= 0) {
				$('fra_edit_student').addClass('hidden');
				return;
			}
			$('fra_edit_student').removeClass('hidden');
			$('dat_si').value = selected_student_id;
			$('txt_edit_student_name').value = student_list[selected_student_id].name;
			$('txt_edit_student_email').value = student_list[selected_student_id].email;
			
			
		}
		/**
		 * Detect which student is selected on the un-teamed side
		 */
		$('cbo_students_no_team').addEvents({
			'change': function(el) {
				selected_student_id = this.options[this.selectedIndex].value;
				edit_student();
			},
			'click': function(el) {
				$clear(timer);
				timer = (function() {
					selected_student_id = this.options[this.selectedIndex].value;
				}).delay(200, this);
			},
			'dblclick': function(el) {
				$clear(timer);
				selected_student_id = this.options[this.selectedIndex].value;
				add_student_to_list(selected_team);
			},
			'keydown': function(e) {
				if (e.key == 'enter') {
					add_student_to_list(selected_team);
				}
			}
		});
		/**
		 * Handle list of students on team
		 */
		$('cbo_students_team').addEvents({
			'change': function(el) {
				selected_student_id = this.options[this.selectedIndex].value;
				edit_student();
			},
			'click': function(el) {
				$clear(timer);
				timer = (function() {
					selected_student_id = this.options[this.selectedIndex].value;
				}).delay(200, this);
			},
			'dblclick': function(el) {
				$clear(timer);
				selected_student_id = this.options[this.selectedIndex].value;
				add_student_to_list(0);
			},
			'keydown': function(e) {
				if (e.key == 'enter') {
					add_sttudent_to_list(0);
				}
			}
		});
		/**
		 * Make teams selectable
		 */
		var selected_team = 0;

		function selectable_teams() {
			$each($$('#list_teams a'), function(el) {
				el.addEvent('click', function(e) {
					e.stop();
					selected_student_id = 0;
					edit_student();
					if (selected_team > 0) {
						$('group_delete_' + selected_team).addClass('hidden');
					}
					$('group_' + selected_team).removeClass('selected');
					selected_team = el.get('id').substr(6);
					if (selected_team > 0) {
						$('group_delete_' + selected_team).removeClass('hidden');
					}
					$('group_' + selected_team).addClass('selected');
					populate_lists();
				});
			});
			
			$each($$('.group_delete'), function(el) {
				el.addEvent('click', function(e) {
					e.stop();
					
					group_id = el.get('id').substr(13);
					if (group_id > 0) {
						var confirm_delete = confirm('Are you sure you want to remove this team?\r\n\r\nAny students on this team will be returned to the default group.');
						if (confirm_delete == true) {
							var delete_request = new Request.JSON({
								url: DIR_MAIN + '/actions/panel_delete_team.php',
								onComplete: function(data) {

									if (data.show_message === true) {
										generate_message(data.type, data.text);
									}
									if (data.type != 'error') {
										$('group_' + group_id).getParent().destroy();
										selected_team = 0;
										$each(student_list, function(student, index) {
											if (student.group_id == group_id) {
												student_list[index].group_id = 0;
											}
										});
										populate_lists();
									}
								}
							}).post({ 'gid': group_id, 'h': $('fh').value, 'c': $('ci').value });
						}
					}
				});
			});
		}
		selectable_teams();
		/**
		 * Add student to list
		 */
		var add_student_to_list = function(team_id) {
			if (selected_student_id > 0) {
				student_list[selected_student_id].group_id = team_id;
				populate_lists();
				saved = false;
			}
			selected_student_id = 0;
			edit_student();
		}
		$('btn_add_to_list').addEvent('click', function(e) {
			e.stop();
			add_student_to_list(selected_team);
		});
		$('btn_remove_from_list').addEvent('click', function(e) {
			e.stop();
			add_student_to_list(0);
		});

		/**
		 *	Populate select boxes with students
		 */
		function populate_lists() {
			$('cbo_students_team').empty();
			$('cbo_students_no_team').empty();

			$each(student_list, function(student, index) {
				if (student.group_id == selected_team) {
					$('cbo_students_team').appendChild( new Element('option', {'value': index}).appendText(student.name) );
				} else if (student.group_id == 0) {
					$('cbo_students_no_team').appendChild( new Element('option', {'value': index}).appendText(student.name) );
				}
			});
		}
		populate_lists();
		/**
		 *	Handle team save form
		 */
		$('form_save_teams').set('send', {
			onRequest: function() {
				// Stuff to do when saving teams
			},
			onComplete: function(response) {
				var data = JSON.decode(response);
				if (data.show_message === true) {
					generate_message(data.type, data.text);
				}
				if (data.type != 'error') {
					saved = true;
				}
			}
		});

		/**
		 * Save team information
		 */
		var save_teams = function() {
			// console.log(JSON.encode(student_list));
			$('dat_td').set('value', JSON.encode(student_list));
			
			$('form_save_teams').send();
		}
		
		$('btn_save_teams').addEvent('click', function(e) {
			e.stop();
			
			save_teams();
		});
		/**
		 * Handle student excel uploads
		 */

		var complete_upload = function(success) {
			var data = JSON.decode(response);
			if (data.show_message === true) {
				generate_message(data.type, data.text);
			}
			if (data.extra != '') {
				// display_new_students(data.
				console.log(data.extra);
			}
		}
		$('form_add_students_excel').addEvent('submit', function(e) {
			// Stuff while sending
		});

		/**
		 *	Warn if there are unsaved changes
		 */
		window.onbeforeunload = function() {
			if (saved === false) {
				return "You have unsaved changes.";
			}
		}
	}
	/**
	 * End team manager section
	 */
});
