/* ------------------------------------------------------------------------------------ *
| GLOBALS Javascript FILE :: For Independent Pictures MEMBERZONE GLOBAL FUNCTIONS		|
| js/globals.js																			|
| 																						|
| DEPENDENCIES :: MooTools 1.2.1														|
| 																						|
| PROJECT :: www.independent-pictures.ch v1.0											|
| Copyright (C) 2009, QUERIDODESIGN, Switzerland										|
| 																						|
+ ------------------------------------------------------------------------------------- +
| Authors :: Rajeev J. Sebastian, Nathan Querido, Jan Kassens, Christoph Pojer			|
* ------------------------------------------------------------------------------------- */

// OBSERVER CLASS :: JanK
var Observer = new Class({

	Implements: [Options, Events],

	options: {
		interval: 100,
		duration: 0
	},

	initialize: function(element, property, options){
		this.setOptions(options);
		this.element = $(element);
		this.property = property;
		this.value = this.element.get(property);
		this.start();
	},

	fire: function() {
		var value = this.element.get(this.property);
		this.fireEvent('onChange', [value]);
	},
	check: function() {
		var value = this.element.get(this.property);
		if (value == this.value || value == 'search') return;
		this.value = value;
		this.fireEvent('onChange', [value]);
	},

	set: function(value) {
		this.stop();
		var v =  this.element.set(this.property, value);
		this.value = value;
		this.start();
		return v;
	},

	get: function() {
		return this.element.get(this.property);
	},

	start: function() {
		this.stop();
		this.interval = this.check.periodical(this.options.interval, this);
	},

	stop: function() {
		$clear(this.interval);
	}

});

Element.Events.observedChange = {

	onAdd: function(fn){
		new Observer(this, 'value', {onChange: fn});
	}

};

// DEFAULT FORM ELEMENT VALUE CLASS :: JanK
var InputText = new Class({

	initialize: function(element){
		this.element = element = $(element);
		this.text = element.value;
		element.addEvents({
			focus: (function(){
				if (element.value == this.text){
					element.value = '';
					element.removeClass('default_text');
				}
			}).bind(this),
			blur: (function(){
				if (element.value == ''){
					element.value = this.text;
					element.addClass('default_text');
				}
			}).bind(this)
		});
	}
});

// DETAIL TIPS :: insanekane
// styled in www/css/memberzone/content.css:TableView Detail Tip
// ui in agavi/app/modules/Member/templates/TableViewSuccess.php:The Tip Container
var DetailTips = new Class({
	Implements: [Events, Options],

	options: {
		tipDataSelector: '.data_wrapper',
		tippedSelector: 'a.tableview_detail_tipped',
		topGap: 15, //these are the default gaps
		bottomGap: -10,
		gaps: {
			'h5': [10, -5], //format is <selector> : [<topgap>, <bottomgap>],
			'td': [16, -10]
		},
		topOffset: 50, //offset for the window scroller
		tipWidth: 300,
		tipShowDelay: 500,
		fadeOptions: {
			duration: 100
		},
		alignOnParent: 'td, th',
		allowTipClicks: false, //allow clicks on the tip container (used when tip has a form)
		hideOnMouseLeave: true, //hide the tip when mouse leaves the tipped element
		hideOnMouseLeaveTip: true //hide the tip when mouse leaves the tip
	},

	//tipContainer: the container of the tip UI
	//tipped: the elements which have tips associated with them
	initialize: function(tipContainer, options) {
		this.setOptions(options);
		this.tipContainer = $(tipContainer);
		this.tipped = $$(this.options.tippedSelector);

		this.initTipped();
		this.initRequest();
	},

	initTipped: function() {
		var self = this;
		this.tipContainer.setStyle('display', 'block');
		this.tipContainer.set('tween', this.options.fadeOptions).fade('hide');
		this.tipContainer.addEvent('mouseenter', self.tipContainerMouseOver.bindWithEvent(self));
		if(this.options.hideOnMouseLeaveTip) this.tipContainer.addEvent('mouseleave', self.tipContainerMouseOut.bindWithEvent(self));
		this.tipped.each(function(el){
// 			el.addEvent('mouseover', self.tipShowMouseOver.bindWithEvent(self, el));
			if(self.options.hideOnMouseLeave) el.addEvent('mouseleave', self.tipShowMouseOut.bindWithEvent(self, el));
			el.addEvent('click', self.tipShowClick.bindWithEvent(self, el));
		});
		document.addEvent('click', function(event) {
			var target = $(event.target);
			if($chk(target.getParent(self.options.tippedSelector)) || target.match(self.options.tippedSelector)) return false;
			else if(self.options.allowTipClicks && self.tipContainer.hasChild(target)) return true;
			else {
				self.tipContainer.fade('hide');
				self.tipContainer.removeClass('data_display');
				self.tipContainer.removeClass('arrow_top');
				self.tipContainer.removeClass('arrow_bottom');
				if(self.__currentEl) self.__currentEl.getParent().removeClass('cell_active');
				self.hidden = true;
				self.req.cancel();
				self.__currentEl = null;
			}
		});
	},

	initRequest: function() {
		var self = this;
		this.req = new Request.HTML({
			update: this.tipContainer.getElement(this.options.tipDataSelector),
			onSuccess: function() {
				self.tipContainer.addClass('data_display');
				self.move(self.__currentEl);
				self.fireEvent('showing', self);
			}
		});
	},

	tipContainerMouseOver: function(event) {
		this.__mouseTimer = $clear(this.__mouseTimer);
	},
	tipContainerMouseOut: function(event) {
		var el = this.__currentEl;
// 		this.__mouseTimer = this.tippedLeave.delay(1000, this, [null, el.getParent()]);
		this.tippedLeave(null, el.getParent());
	},

	tipShowMouseOver: function(event, el) {
// 		if((this.__currentEl == el && !this.__mouseTimer)
// 			|| this.scrolling
// 			|| !this.__currentEl && this.__mouseEl == el) return;
// 		if(this.__currentEl) {
// 			//should not happen other than through scrl
// 		}
// 		if(this.__mouseTimer) this.__mouseTimer = $clear(this.__mouseTimer);
// 		this.__mouseEl = el;
// 		this.__mouseTimer = this.tipShow.delay(this.options.tipShowDelay, this, [null, el]);

	},

	tipShowMouseOut: function(event, el) {
		if(this.scrolling) return;
		this.__mouseTimer = $clear(this.__mouseTimer);
		if(this.__currentEl == el) {
			this.__mouseTimer = this.tippedLeave.delay(500, this, [null, el.getParent()]);
		}
	},

	tipShowClick: function(event, el) {
		this.__mouseTimer = $clear(this.__mouseTimer);
		this.tipShow(event, el);
	},

	tipShow: function(event, el) {
		if(event) event.preventDefault();
		if(this.__currentEl == el) return;
		this.hideTip();
		this.req.get(el.href);

		if($chk(this.__currentEl)) this.__currentEl.getParent().removeClass('cell_active');

		//store the current element; so we can reposition the tip when we get data
		this.__currentEl = $(el);
		this.tipContainer.fade('hide');

		el.getParent().addClass('cell_active');
	},

	hideTip: function() {
		this.tipContainer.fade('hide');
		this.tipContainer.removeClass('data_display');
		this.tipContainer.removeClass('arrow_top');
		this.tipContainer.removeClass('arrow_bottom');
	},

	tippedLeave: function(event, el) {
		this.__mouseTimer = $clear(this.__mouseTimer);
		var self = this;
		el.removeClass('cell_active');
		self.hideTip();
		this.req.cancel();
		this.__currentEl = null;
	},

	getGaps: function(parent) {
		var ret = false;
		$H(this.options.gaps).each(function(value, key) {
			if(parent.match(key)) {
				ret = value;
			}
		});
		if(ret) return ret;
		return [this.options.topGap, this.options.bottomGap];
	},

	move: function(el) {
		var tipC = this.tipContainer;
		var pos = el.retrieve('__detail_tip_pos');
		if(!$chk(pos)) {
			pos = el.getParent().getCoordinates();
			el.store('__detail_tip_pos', pos);
		}
		// console.log(document.getScrollSize(), pos.top + this.options.topGap);
		var ds = window.getScroll();
		var dv = window.getSize(); //viewpoirt size
		var dz = window.getScrollSize();
		var ptip = tipC.getSize();
		var gaps = this.getGaps(el.getParent());
		var topGap = gaps[0];
		var bottomGap = gaps[1];
		if(ds.y + dv.y < pos.top + ptip.y + topGap ) {
			var klass = "arrow_bottom";
			var top = pos.top - bottomGap - ptip.y;
		} else {
			var klass = "arrow_top";
			var top = pos.top + topGap;
		}
		
		if(pos.left == 0) {
			var left = pos.left;
			var els = el.getCoordinates();
			var arrowPos = els.left + els.width/2; //assumes tipC.left is < els.left
		} else if(dv.x < pos.left + ptip.x) {
			var left = pos.left + (pos.width - ptip.x);
			var arrowPos = (ptip.x - pos.width) + pos.width/2;
		} else {
			var arrowPos = ptip.x/2;
			var left = pos.left - (ptip.x - pos.width)/2;
		}
		tipC.setStyles({
			left: left, top: top
		});

		tipC.addClass(klass);
		tipC.getElements('.arrow_wrapper').setStyle('left', arrowPos);

		// first check if the box is already within the current viewport

		if( ds.y < top && (top + ptip.y + this.options.topOffset) < (ds.y + dv.y)) {
			tipC.fadeIn();
		} else {
			var y = top + ptip.y + this.options.topOffset - dv.y;
			var self = this;
			function f() {
// 				self.scrolling = false;
				self.tipContainer.fadeIn();
				windowScroller.removeEvent('complete', f);
			}
// 			this.scrolling = true;
			windowScroller.addEvent('complete', f);
			windowScroller.start(0, y);
		}

	}
});

var DialogTips = new Class({
	Implements: [Events, Options],

	options: {
		tipDataSelector: '.data_wrapper',
		tippedSelector: 'a.tableview_detail_tipped',
		topGap: 15, //these are the default gaps
		bottomGap: -10,
		gaps: {
			'h5': [15, -5], //format is <selector> : [<topgap>, <bottomgap>],
			'td': [15, -10]
		},
		topOffset: 50, //offset for the window scroller
		tipWidth: 300,
		tipShowDelay: 500,
		fadeOptions: {
			duration: 100
		},
		alignOnParent: 'td, th'
	},

	//tipContainer: the container of the tip UI
	//tipped: the elements which have tips associated with them
	initialize: function(tipContainer, options) {
		this.setOptions(options);
		this.tipContainer = $(tipContainer);
		this.tipped = $$(this.options.tippedSelector);

		this.initTipped();
	},

	initTipped: function() {
		var self = this;
		this.tipContainer.setStyle('display', 'block');
		this.tipContainer.set('tween', this.options.fadeOptions).fade('hide');
		this.tipContainer.addEvents({
			'mouseenter': self.tipContainerMouseOver.bindWithEvent(self),
			'mouseleave' : self.tipContainerMouseOut.bindWithEvent(self)
		});
		this.tipped.each(function(el){
// 			el.addEvent('mouseover', self.tipShowMouseOver.bindWithEvent(self, el));
// 			el.addEvent('mouseleave', self.tipShowMouseOut.bindWithEvent(self, el));
			el.addEvent('click', self.tipShowClick.bindWithEvent(self, el));
		});
		document.addEvent('click', function(event) {
			var target = $(event.target);
			if($chk(target.getParent(self.options.tippedSelector)) || target.match(self.options.tippedSelector)) return false;
			else {
				self.hideTip();
// 				if(self.__currentEl) self.__currentEl.getParent().removeClass('cell_active');
				self.hidden = true;
			}
		});
	},

	tipContainerMouseOver: function(event) {
		this.__mouseTimer = $clear(this.__mouseTimer);
	},
	tipContainerMouseOut: function(event) {
		var el = this.__currentEl;
// 		this.__mouseTimer = this.tippedLeave.delay(1000, this, [null, el.getParent()]);
		this.tippedLeave(null, el.getParent());
	},

	tipShowMouseOver: function(event, el) {

	},

	tipShowMouseOut: function(event, el) {
		if(this.scrolling) return;
		this.__mouseTimer = $clear(this.__mouseTimer);
		if(this.__currentEl == el) {
			this.__mouseTimer = this.tippedLeave.delay(500, this, [null, el.getParent()]);
		}
	},

	tipShowClick: function(event, el) {
		this.__mouseTimer = $clear(this.__mouseTimer);
		this.tipShow(event, el);
	},

	tipShow: function(event, el) {
		if(event) event.preventDefault();
		this.hideTip();
		this.fireEvent('showing', [el, this.tipContainer]);

		if($chk(this.__currentEl)) this.__currentEl.getParent().removeClass('cell_active');

		//store the current element; so we can reposition the tip when we get data
		this.__currentEl = $(el);
		this.tipContainer.fade('hide');

		el.getParent().addClass('cell_active');

		this.tipContainer.addClass('data_display');
		this.move(this.__currentEl);
	},

	hideTip: function() {
		this.tipContainer.fade('hide');
		this.tipContainer.removeClass('data_display');
		this.tipContainer.removeClass('arrow_top');
		this.tipContainer.removeClass('arrow_bottom');
	},

	tippedLeave: function(event, el) {
		this.__mouseTimer = $clear(this.__mouseTimer);
		var self = this;
// 		el.removeClass('cell_active');
		self.hideTip();
		this.__currentEl = null;
	},

	getGaps: function(parent) {
		var ret = false;
		$H(this.options.gaps).each(function(value, key) {
			if(parent.match(key)) {
				ret = value;
			}
		});
		if(ret) return ret;
		return [this.options.topGap, this.options.bottomGap];
	},

	move: function(el) {
		var tipC = this.tipContainer;
		var pos = el.retrieve('__detail_tip_pos');
		if(!$chk(pos)) {
			pos = el.getCoordinates();
			el.store('__detail_tip_pos', pos);
		}
		// console.log(document.getScrollSize(), pos.top + this.options.topGap);
		var ds = window.getScroll();
		var dv = window.getSize(); //viewpoirt size
		var dz = window.getScrollSize();
		var ptip = tipC.getSize();
		var gaps = this.getGaps(el);
		var topGap = gaps[0];
		var bottomGap = gaps[1];
		if(ds.y + dv.y < pos.top + ptip.y + topGap ) {
			var klass = "arrow_bottom";
			var top = pos.top - bottomGap - ptip.y;
		} else {
			var klass = "arrow_top";
			var top = pos.top + topGap;
		}
		
		if(pos.left == 0) {
			var left = pos.left;
			var els = el.getCoordinates();
			var arrowPos = els.left + els.width/2; //assumes tipC.left is < els.left
		} else if(dv.x < pos.left + ptip.x) {
			var left = pos.left + (pos.width - ptip.x);
			var arrowPos = (ptip.x - pos.width) + pos.width/2;
		} else {
			var arrowPos = ptip.x/2;
			var left = pos.left - (ptip.x - pos.width)/2;
		}
		tipC.setStyles({
			left: left, top: top
		});

		tipC.addClass(klass);
		tipC.getElements('.arrow_wrapper').setStyle('left', arrowPos);

		// first check if the box is already within the current viewport

		if( ds.y < top && (top + ptip.y + this.options.topOffset) < (ds.y + dv.y)) {
			tipC.fadeIn();
		} else {
			var y = top + ptip.y + this.options.topOffset - dv.y;
			var self = this;
			function f() {
// 				self.scrolling = false;
				self.tipContainer.fadeIn();
				windowScroller.removeEvent('complete', f);
			}
// 			this.scrolling = true;
			windowScroller.addEvent('complete', f);
			windowScroller.start(0, y);
		}

	}

});

Date.$culture = "GBdot";//setup the culture to a sane value

var DateRangePicker = new Class({
	Implements: Options,

	options: {
		classNormal: 'input.normal',
		classFocus: 'input.focus',
		classError: 'input.error',
		prevButton: '.date_arrow_left',
		nextButton: '.date_arrow_right',
		startProxy: '#start_date_proxy',
		endProxy: '#end_date_proxy',
		submitButton: 'button',
		startReal: '#start_date',
		endReal: '#end_date',
		inputFormat: /(\d{1,2})\/(\d{1,2})\/(\d{2,4})/,
		minDate: Date.parse('1/1/2009')
	},

	initialize: function(rangeContainer, formContainer, options) {

		this.rangeContainer = $(rangeContainer);
		this.formContainer = $(formContainer);
		this.dateUrl = this.formContainer.get('action');
		this.setOptions(options);
		//setup today and the thursday of the week
		this.today = Date.parse(todaysDate);
		var day = this.today.get('Day');
		if(day != 4)
			this.thursday =  this.today.clone().decrement('day', day > 4 ? day-4 : day - 4 + 7);
		else
			this.thursday = this.today;

		var f = this.rangeContainer.getElement.bind(this.rangeContainer);

		this.prevButton = f(this.options.prevButton);
		this.prevButton.addEvent('click', this.prev.bind(this));

		this.nextButton = f(this.options.nextButton);
		this.nextButton.addEvent('click', this.next.bind(this));

		//setup observers
		this.startObserver = new Observer(f(this.options.startProxy), 'value', {
			onChange: this.startChanged.bind(this)
		});
		this.endObserver = new Observer(f(this.options.endProxy), 'value', {
			onChange: this.endChanged.bind(this)
		});

		var self = this;

		$$(f(this.options.endProxy), f(this.options.startProxy)).addEvents({
			'focus': function(ev) {
				this.morph(self.options.classFocus);
			},
			'blur': function(ev) {
				this.morph(self.options.classNormal);
			},
			keypress:function(ev) {
				if(ev.code == Event.Keys.enter) { ev.stop(); self.submitClicked(); }
			}
		});
		this.startObserver.fire();
		this.endObserver.fire();
		this.diff();
		f(this.options.submitButton).addEvent('click', this.submitClicked.bind(this));
		
	},

	diff: function() {
		var s = Date.parse(this.startObserver.get());
		var e = Date.parse(this.endObserver.get());
		return s.diff(e);
	},
	prev: function(event) {
		event.stop();
		if( this.prevButton.hasClass('end') ) return;
		var diff = this.diff();
		if(diff) {
			var d = Date.parse(this.startObserver.get());
			if(d.clone().decrement('day', diff+1) >= this.options.minDate) {
				d.decrement();
				this.endObserver.set(d.format('%x'));
				d.decrement('day', diff);
				this.startObserver.set(d.format('%x'));
			} else {
				var d = this.options.minDate.clone();
				this.startObserver.set(d.format('%x'));
				d.increment('day', diff);
				this.endObserver.set(d.format('%x'));
			}
			this.resetButtons();
		}

	},
	next: function(event) {
		event.stop();
		if(this.nextButton.hasClass('end')) return;
		var diff = this.diff();
		if(diff) {
			//when the user presses next, there are two cases:
			// the new range will go past this week; in this case, the start date must be set to this thursday
			// otherwise, do as normal
			var s = Date.parse(this.startObserver.get());
			var d = Date.parse(this.endObserver.get());
			if( d.clone().increment() < this.thursday ) {
				d.increment();
				this.startObserver.set(d.format('%x'));
				d.increment('day', diff);
				this.endObserver.set(d.format('%x'));
			} else {
				var d = this.thursday.clone();
				this.startObserver.set(d.format('%x'));
				this.endObserver.set(this.thursday.clone().increment('day', diff).format('%x'));
			}
			this.resetButtons();
		}
	},
	startChanged: function(value) {
		this.resetButtons();
	},
	endChanged: function(value) {
		this.resetButtons();
	},
	resetButtons: function() {
		var s = Date.parse(this.startObserver.get());
		var d = Date.parse(this.endObserver.get());
		if(	s.invalid() || s < this.options.minDate
			|| d.invalid() || d < this.options.minDate
			|| s >= d) {
			
			if(s.invalid() || s < this.options.minDate || s >= d ) {
				this.startObserver.element.addClass('error').morph(this.options.classError);
				this.startError = true;
			}
			if( d.invalid() || d < this.options.minDate || s >= d ) {
				this.endObserver.element.addClass('error').morph(this.options.classError);
				this.endError = true;
			}
		} else {
			this.startObserver.element.removeClass('error').morph(this.options.classNormal);
			this.startError = false;
			this.endObserver.element.removeClass('error').morph(this.options.classNormal);
			this.endError = false;
		}
		if(this.startError || this.endError) {
			this.prevButton.addClass('end');
			this.nextButton.addClass('end');
		} else {
			this.prevButton.removeClass('end');
			if( s < this.thursday ) {
				this.nextButton.removeClass('end');
			} else {
				this.nextButton.addClass('end');
			}
		}
	},
	dateToQueryString: function(date) {
		return ''+date.getFullYear()+'-'+(date.getMonth()+1)+'-'+date.getDate();
	},
	submitClicked: function(event) {
		if(event) event.stop();
		var startReal = this.formContainer.getElement(this.options.startReal);
		var endReal = this.formContainer.getElement(this.options.endReal);

		var sd = Date.parse(this.startObserver.get());
		var ed = Date.parse(this.endObserver.get());
		if(sd && ed && sd < ed && !this.startError && !this.endError) {
			var action = this.dateUrl + '/' + this.dateToQueryString(sd) + '/' + this.dateToQueryString(ed);
			this.formContainer.action = action;
			this.formContainer.submit();
		}
	}
});

// FORM VALIDATIN CLASS :: zilenCe, insanekane
var FormValidator = new Class({

	Implements: [Options, Events],

	options: {
		classNormal: 'normal',
		classFocus: 'focus',
		classError: 'error'
	},

	elements: {},
	voptions: {},
 	grouped: {},

	Regex: {
		email: /^[a-z0-9._%-]+@[a-z0-9.-]+\.[a-z]{2,4}$/i,
		phone: /^[0-9\s-\(\)\+]+$/i,
		postcode: /^[0-9]+$/i
	},

	initialize: function(el, options){
		this.setOptions(options);

		this.el = $(el).addEvent('submit', this.submit.bindWithEvent(this));

		this.els = this.el.getElements('input[type!=submit][type!=reset][type!=checkbox], textarea').filter(function(el){
			var title = el.get('title');

			el.addEvents({
				focus: this.focus.bind(this, el),
				blur: this.blur.bind(this, el),
				keypress: this.swallowEnter.bindWithEvent(this, el)
			});

			el.morph(el.get('tag')+'.'+this.options.classNormal);
			if(!title) return false;

			this.elements[el.id] = el;
			this.voptions[el.id] = title.split(',').map(String.trim).map(String.toLowerCase);

			el.erase('title');

			return true;
		}, this);

		this.el.getElements('input[type=checkbox]').each(function(el){
			var group = el.get('grouped-for');
			if(!group) return;

			this.grouped[group] = el.id;
			el.addEvent('click', this.groupChange.bindWithEvent(this, group));
		}, this);
// 		this.checkAll();
		this.els.each(function(el){
			el.morph(el.get('tag')+'.'+this.options.classNormal);
		}, this);
	},

 	groupChange: function(event, group) {
		this.fireEvent('groupChanged', group);
	},

	submit: function(e){
		this.error = false;
		this.els.each(function(el){
			this.check(el);
		}, this);
		if(this.error){
			e.stop();
			return false;
		}
		return true;

	},

	swallowEnter: function(ev, el) {
		if(ev.code == Event.Keys.enter) { ev.stop(); }
	},

	focus: function(el){
		el.morph(el.get('tag')+'.'+this.options.classFocus);
	},

	blur: function(el){
		this.error = false;
		if(this.els.contains(el)) {
			this.check(el);
			if(!this.error) {
				el.morph(el.get('tag')+'.'+this.options.classNormal);
			}
		} else {
			el.morph(el.get('tag')+'.'+this.options.classNormal);
		}
	},

	check: function(el){
		var error = false,
			value = el.get('value');
		var check = false;
		var matchGroup = $H(this.grouped).filter(function(checkbox, group) {
			if( el.getParent(group) ) {
				if ($(checkbox).checked) check = true;
				return true;
			}
			return false;
		});

		if(matchGroup.getLength() > 0 && !check) return;
		
		if(this.voptions[el.id].contains('required') && (!value || value.test(/^\s+$/))){
			error = true;
		}

		this.voptions[el.id].each(function(option) {
			if(option.test(/^copy\((.+)\)/)) {
				var otherSel = option.match(/^copy\((.+)\)/)[1];
				var otherEl = $$(otherSel)[0];
				if(otherEl.value != value) error = true;
			}
		});

		Hash.each(this.Regex, function(v, i){
			if(!this.voptions[el.id].contains(i)) return;

			if(!value.test(v)) error = true;
		}, this);

		el.set('value', value.trim());

		if(error){
			this.error = error;
			el.morph(el.get('tag')+'.'+this.options.classError);
			el.addClass('input_error');
			this.fireEvent('errorFound', [el]);
		} else {
			el.removeClass('input_error');
			this.fireEvent('errorClear', [el]);
		}
	},

 	checkAll: function() {
		this.els.each(function(el){
			this.check(el);
		}, this);
	},

	reset: function(){
		this.els.fireEvent('keydown');
		this.error = false;
		this.el.getElements('input[type!=submit][type!=reset][type!=checkbox], textarea').set('value', '');
	}
});

// PROFILE SETTINGS :: insanekane

Function.implement({
	delayed: function(delay) {
		var f = this;
		return function() {
			f.delay(delay);
		};
	}
});

function detailsFormLoaded() {
	var sbInstance = this;
	var disableTabs = false;
	var validator = new FormValidator('details_form');
	$$('.spinner_overlay').setStyle('display', 'none');
	function resetTabs() {
		var tab = $$('.overlay_header li.active');
		if(tab.length) tab = tab[0];
		var id = tab.getElement('a').id;

		var tabs = $$('.settings_content div.form_tab');
		tabs.each(function(el) {
			if(id != 'tab_' + el.id) el.setStyle('display', 'none');
			else el.setStyle('display', 'block');
		});
	}

	function checkError(el) {
		var tab = $(el).getParent('.form_tab');
		if(tab.getElements('.input_error').length) {
			$('tab_' + tab.id).addClass('error');
		} else {
			$('tab_' + tab.id).removeClass('error');
		}
	}
	
	validator.addEvent('errorFound', checkError);
	validator.addEvent('errorClear', checkError);
	
	resetTabs();
	$$('.overlay_header li a').addEvent('click', function(ev) {
		ev.stop();
		if(!disableTabs) {
			$$('.overlay_header li.active').removeClass('active');
			this.getParent('li').addClass('active');
			resetTabs();
		}
	});
	$('details_form').set('send', {
		onRequest: function() {
			$$('.settings_content input').each(function(el){
				el.disabled = true;
			});
			$$('.overlay_header').addClass('disabled');
			$$('.settings_content').addClass('disabled');
			$('submit_details').addClass('disabled');
			disableTabs = true;
			$$('.spinner_overlay').setStyle('display', 'block');
		},
		onComplete: function() {
			sbInstance.close();
		}
	});
	$('details_form').addEvent('submit', function(ev) {
		ev.stop();
	});
	$('submit_details').addEvent('click', function(ev) {
		ev.stop();
		if(disableTabs) return;
		validator.checkAll();
		var errorTabs = $$('.overlay_header li a.error');
		if(errorTabs.length) {
			//if there are tabs with errors within them, we change to the first tab, and then scroll to the first error
			var tab = errorTabs[0].getParent();
			$$('.overlay_header li.active')[0].removeClass('active');
			tab.addClass('active');
			resetTabs();
			var tabs = $$('.settings_content div.form_tab');
			tabs.each(function(el) {
				if(errorTabs[0].id == 'tab_' + el.id) {
					new Fx.Scroll($$('.settings_content')[0], {
						offset: {
							'x': 0,
							'y': -20
						},
						wheelStops: false
					}).toElement(el.getElement('.input_error'));
				}
			});
		}
		if(!validator.error){
			$('details_form').send();
		}
	});
}

var StyledCheckbox = new Class({
	Implements: [Events, Options],
	options: {
		animate: false, // Whether the widget should be animated :: insanekane
		animationOptions: {duration:300, link: 'chain'}, // "link: chain" is important for the animation :: insanekane
		animationStateNormal: {'background-color': '#FFF'},
		animationStatePressed: { 'background-color': '#FFF' },
		group: null, //$$('elements'), // Group of elements to process; used with radio-button groups :: insanekane
		onAction: $empty, // Event fired when this value changes :: insanekane
		saveUnchecked: false //Whether to save the unchecked state when POSTing the form.
	},

	initialize: function(element, options) {
		this.setOptions(options);
		this.element = element;
		this.build();
		if(this.options.animate) this.buildAnimation();
	},

	// FADE EFFECT, LABELS :: nfq
	buildAnimation: function() {
		var anim = new Fx.Morph(this.element, this.options.animationOptions );
		anim.set(this.options.animationStateNormal);
		this.element.store('EF.widget.animation', anim);
	},

	startAnimation: function() {
		var anim = this.element.retrieve('EF.widget.animation');
		anim.start(this.options.animationStatePressed);
		anim.start(this.options.animationStateNormal);
	},

	// CUSTOM CHECKS + RADIOS :: nfq, JanK
	build: function() {
		var e = this.element;
		var ec = e.getElement('input');

		this.check(e);
		ec.style.display = 'none';
		var isCheckbox = ec.get('type') == 'checkbox';
		var isFileCheck = e.hasClass('');
		if (this.options.saveUnchecked && isCheckbox && !isFileCheck) {
			// This hidden input is absolutely necessary for Ether.Flex to work
			// Apparently, EF requires a value "0" when the checkbox is unchecked, which by default will not be sent
			// by the browser. So, we have this here hack, which mirrors the checked status of checkbox, *and* sends "0"
			// when the checkbox is unchecked :: insanekane
			// NOTE: For Independent city chooser, we DO NOT send the value if its unchecked; so we manipulate the checkbox directly.
			var hidden = new Element('input', {
					type: 'hidden',
					value: ec.get('checked')?1:0,
					name: ec.get('name')
				}).inject(ec, 'after');
				ec.set('name', '');
		}
		this.value = isCheckbox ? ec.get('checked') : ec.get('value');
		this.checked = ec.get('checked');
		e.addEvent('click',function(event){
			if(this.options.animate && event.target == ec) this.startAnimation();
			if(event.target == ec ) {
				if (isCheckbox) {
					this.check(e);
					if (this.options.saveUnchecked && !isFileCheck) { hidden.set('value', ec.get('checked')?1:0); }
				} else {
					$$(this.options.group).each(function(j){
						if(j.getElement('input').type == 'radio') this.check(j);
					}.bind(this));
				}
				if(!isFileCheck && event.target == ec) {
					// Two events are generated, apparently one by the label (e) and one by the checkbox (ec)
					// this causes issues with the tags widget's send method being called twice, the first with wrong data
					// so, we have an extra guard on the target :: insanekane
					this.value = isCheckbox ? ec.get('checked') : ec.get('value');
					this.checked = ec.get('checked');
					this.fireEvent('action', ec.get('value'));
				}
			}
		}.bind(this));
	},

	check: function(el){
		el = $(el) || $(this.element);
		var input = el.getElement('input');
		var type = input.get('type');
		if (input.checked) {
			el.addClass(type + '_on');
			el.removeClass(type + '_off');
		} else {
			el.addClass(type + '_off');
			el.removeClass(type + '_on');
		}
	},

	setChecked: function(val) {
		var el = $(el) || $(this.element);
		var input = el.getElement('input');
		input.checked = val;
		this.check();
	},

	isChecked: function() {
		var el = $(el) || $(this.element);
		var input = el.getElement('input');
		return input.checked;
	}

});

StyledCheckbox.extend({
	assign: function(selector, options) {
		return $$(selector).map(function(el) {
			return new StyledCheckbox(el, options);
		});
	}
});



// FALLBACK FOR IE :: JanK
Element.implement({

	fadeOut: function(){
		this.fade(Browser.Engine.trident ? 'hide' : 'out');
	},

 fadeIn: function(){
	 this.fade(Browser.Engine.trident ? 'show' : 'in');
 }

});




window.addEvent('domready', function(){

	// IE 6 + 7, Opera AND Firefox 2 DETECTION NOTICE :: nfq
	if(Browser.Engine.trident4) $$('.login_footer button').setStyle('display', 'none'), $$('.third_row').set('html', "<p>Ihr Browser (<strong>Internet Explorer 6</strong>) unterstützt leider nicht die notwendigen Funktionen für diesen Bereich der Website. Wir empfehlen Ihnen <a href=http://www.mozilla-europe.org/de/firefox/>Firefox 3</a>, <a href=http://www.google.com/chrome/>Google Chrome</a> oder <a href=http://www.apple.com/safari/download/>Safari 3</a> zu installieren, was Sie mit wenigen Mausklicks selber machen können.<br /><br />Unfortunately, the browser you are using (<strong>Internet Explorer 6</strong>) doesn't support the necessary functions for this Area of the website.<br /> We suggest <a href=http://www.mozilla.com/>Firefox 3</a>, <a href=http://www.google.com/chrome/>Google Chrome</a> or <a href=http://www.apple.com/safari/download/>Safari 3</a>, which can be installed in just a few Mouse Clicks.</p>");
	else if(Browser.Engine.trident5) $$('.message').set('html', "<p><em>ACHTUNG</em>: Sie benutzen <strong>Internet Explorer 7</strong>. Dieses Programm verlangsamt das Boxoffice um 80%. Wir empfehlen Ihnen daher unbedingt <a href=http://www.mozilla-europe.org/de/firefox/>Firefox 3</a>, <a href=http://www.google.com/chrome/>Google Chrome</a> oder <a href=http://www.apple.com/safari/download/>Safari 3</a> zu installieren.<br /><br /><em>WARNING</em>: You are using <strong>Internet Explorer 7</strong>. This Browser slows<br /> the Boxoffice application to around 80%. We strongly recommend <br /> installing <a href=http://www.mozilla-europe.org/de/firefox/>Firefox 3</a>, <a href=http://www.google.com/chrome/>Google Chrome</a> or <a href=http://www.apple.com/safari/download/>Safari 3</a>.</p>");
	else if(document.querySelectorAll && Browser.Engine.trident) $$('.message').set('html', "<p><em>ACHTUNG</em>: Sie benutzen <strong>Internet Explorer 8</strong>. Dieses Programm verlangsamt das Boxoffice um 80%. Wir empfehlen Ihnen daher unbedingt <a href=http://www.mozilla-europe.org/de/firefox/>Firefox 3</a>, <a href=http://www.google.com/chrome/>Google Chrome</a> oder <a href=http://www.apple.com/safari/download/>Safari 3</a> zu installieren.<br /><br /><em>WARNING</em>: You are using <strong>Internet Explorer 8</strong>. This Browser slows<br /> the Boxoffice application to around 80%. We strongly recommend <br /> installing <a href=http://www.mozilla-europe.org/de/firefox/>Firefox 3</a>, <a href=http://www.google.com/chrome/>Google Chrome</a> or <a href=http://www.apple.com/safari/download/>Safari 3</a>.</p>");
	else if(Browser.Engine.presto) $$('.login_footer button').setStyle('display', 'none'), $$('.third_row').set('html', "<p>Ihr Browser (<strong>Opera</strong>) unterstützt leider nicht die notwendigen Funktionen für diesen Bereich der Website. Wir empfehlen Ihnen <a href=http://www.mozilla-europe.org/de/firefox/>Firefox 3</a>, <a href=http://www.google.com/chrome/>Google Chrome</a> oder <a href=http://www.apple.com/safari/download/>Safari 3</a> zu installieren, was Sie mit wenigen Mausklicks selber machen können.<br /><br />Unfortunately, the browser you are using (<strong>Opera</strong>) doesn't support the necessary functions for this Area of the website.<br /> We suggest <a href=http://www.mozilla.com/>Firefox 3</a>, <a href=http://www.google.com/chrome/>Google Chrome</a> or <a href=http://www.apple.com/safari/download/>Safari 3</a> which can be installed in a few Mouse Clicks.</p>");
	else if(Browser.Engine.gecko && Browser.Engine.version < 19) $$('.login_footer button, .second_row').setStyle('display', 'none'), $$('.third_row').set('html', "<p>Ihr Browser (<strong>Firefox 2</strong>) unterstützt leider nicht die notwendigen Funktionen für diesen Bereich der Website. Wir empfehlen Ihnen <a href=http://www.mozilla-europe.org/de/firefox/>Firefox 3</a>, <a href=http://www.google.com/chrome/>Google Chrome</a> oder <a href=http://www.apple.com/safari/download/>Safari 3</a> zu installieren, was Sie mit wenigen Mausklicks selber machen können.<br /><br />Unfortunately, the browser you are using (<strong>Firefox 2</strong>) doesn't support the necessary functions for this Area of the website.<br /> We suggest <a href=http://www.mozilla.com/>Firefox 3</a>, <a href=http://www.google.com/chrome/>Google Chrome</a> or <a href=http://www.apple.com/safari/download/>Safari 3</a> which can be installed in just a few Mouse Clicks.</p>");

	// GRAB ALL INPUTS AND USE DEFAULT TEXT WITH CSS CLASS '.default_text' :: JanK
	$$('input.search_input').each(function(input){
	    new InputText(input);
	});
	
	var settings = $$('a.settings');
	if(settings.length)
		SqueezeBox.assign(settings, {
			size: {x: 800, y: 530},
			sizeLoading: {x: 800, y: 260},
			marginInner: {x: 0, y: 0},
			overlayOpacity: 0.2,
			closeBtn: true,
			closable: false,
			parse: 'rel',
			ajaxOptions: {
				method: 'get'
			},
			onUpdateComplete: detailsFormLoaded
	});

	if($chk($('tableview_detail_tip_container')))
		var detailTips = new DetailTips($('tableview_detail_tip_container'), {
			tippedSelector: '.tableview_detail_tipped'
	   });

	if($chk($('city_chooser_tip_container'))) {
		var detailTips = new DetailTips($('city_chooser_tip_container'), {
			tippedSelector: '.city_chooser a',
			allowTipClicks: true,
			tipWidth: 200,
			hideOnMouseLeave: false,
			hideOnMouseLeaveTip: false
		});
		detailTips.addEvent('showing', function() {
			var cbs = StyledCheckbox.assign(detailTips.tipContainer.getElements('.city_styled_checkbox'));
			var selectAll = detailTips.tipContainer.getElement('.select_all');
			var unselectAll = detailTips.tipContainer.getElement('.unselect_all');
			var submitB = detailTips.tipContainer.getElement('button');
			function resetSelectAll() {
				var checkedCBs = cbs.filter(function(el){ return el.isChecked(); })
				if(checkedCBs.length == cbs.length) {
					unselectAll.removeClass('hidden');
					selectAll.addClass('hidden');
				} else {
					selectAll.removeClass('hidden');
					unselectAll.addClass('hidden');
				}

				if(checkedCBs.length == 0) {
					submitB.addClass('disabled');
					submitB.disabled = true;
				} else {
					submitB.removeClass('disabled');
					submitB.disabled = false;
				}
			}
			resetSelectAll();
			cbs.each(function(el){
				el.addEvent('action', resetSelectAll);
			});
			selectAll.addEvent('click', function(ev) {
				ev.stop();
				cbs.each(function(el) {
					el.setChecked(true);
				});
				resetSelectAll();
			});
			unselectAll.addEvent('click', function(ev) {
				ev.stop();
				cbs.each(function(el) {
					el.setChecked(false);
				});
				resetSelectAll();
			});
			
		});
	}

	windowScroller = new Fx.Scroll(window, {link: 'chain'});
	if($('date_range_form'))
	var dateRangePicker = new DateRangePicker($$('.date_range')[0], $('date_range_form'));
		
	if($$('.login_form, .bb_form').length) {
		$$('input').each(function(el){
			el.addEvents({
				focus: function(ev) {
					this.morph('input.focus');
				},
				blur: function(ev) {
					$(this).morph('input.normal');
				}
			});
			if(!el.hasClass('error')) el.morph('input.normal');
		});

		$$('textarea').each(function(el){
			el.addEvents({
				focus: function(ev) {
					this.morph('textarea.focus');
				},
				blur: function(ev) {
					$(this).morph('textarea.normal');
				}
			})
			if(!el.hasClass('error')) el.morph('textarea.normal');
		});
	}

	var highlights = {};
	var setHighlight = function(element, type){
		removeHighlight(type);
		highlights[type] = element.addClass(type + '-highlight');
	};
	var removeHighlight = function(type){
		if (highlights[type]) highlights[type].removeClass(type + '-highlight');
	};
	$(document).addEvent('click', function(){
		removeHighlight('click');
	});
	$$('tr.highlightable').addEvents({
		click: function(e){
			e.stopPropagation();
			setHighlight(this, 'click');
		},
		mouseover: function(){
			setHighlight(this, 'hover');
		},
		mouseout: function(){
			removeHighlight('hover');
		}
	});

	if($('confirm_container')) {

		$$('.button.delete').addEvent('click', function(ev) {
			ev.stop();
			var el = this;
			var sb = SqueezeBox.fromElement(this, {
				size: {x: 500, y: 250},
				sizeLoading: {x: 500, y: 125},
				marginInner: {x: 0, y: 0},
				overlayOpacity: 0.2,
				closeBtn: true,
				closable: false,
				parse: 'rel',
				ajaxOptions: {
					method: 'get'
				},
				'target': $('confirm_container').clone().setStyle('display', 'block'),
				'handler': 'clone',
				'onUpdate': function() {
					sb.content.getElement('a.no').addEvent('click', function(event){
						event.stop();
						sb.close();
					});
					sb.content.getElement('a.button.yes').setAttribute('href', el.getAttribute('href'));
					sb.content.getElement('a.button.yes').addEvent('click', function() {
						sb.content.getElement('.spinner_overlay').fade('in');
						sb.content.getElements('a.button').addClass('disabled');
					});
					sb.content.getElement('.spinner_overlay').fade('hide');
				}
			});
		});
	}

	if($('help_container')) {

		$$('a.button.help').addEvent('click', function(ev) {
			ev.stop();
			var el = this;
			var sb = SqueezeBox.fromElement(this, {
				size: {x: 700, y: 500},
				sizeLoading: {x: 700, y: 250},
				marginInner: {x: 0, y: 0},
				overlayOpacity: 0.2,
				closeBtn: true,
				closable: false,
				parse: 'rel',
				ajaxOptions: {
					method: 'get'
				},
				'target': $('help_container').clone().setStyle('display', 'block'),
				'handler': 'clone',
				'onUpdate': function() {
					sb.content.getElement('a.close').addEvent('click', function(event){
						event.stop();
						sb.close();
					});
				}
			});
		});
	}

});
