function currentYear(){
   var date = new Date();
   var yy = date.getYear();
   return (yy < 1000) ? yy + 1900 : yy;
}


/**
 * SimpleTabs - Unobtrusive Tabs with Ajax
 *
 * @example
 *
 *	var tabs = new SimpleTabs($('tab-element'), {
 * 		selector: 'h2.tab-tab'
 *	});
 *
 * @version		1.0
 *
 * @license		MIT License
 * @author		Harald Kirschner <mail [at] digitarald.de>
 * @copyright	2007 Author
 */
var SimpleTabs = new Class({

	Implements: [Events, Options],

	/**
	 * Options
	 */
	options: {
		show: 0,
		selector: '.tab-tab',
		classWrapper: 'tab-wrapper',
		classMenu: 'tab-menu',
		classContainer: 'tab-container',
		onSelect: function(toggle, container, index) {
			toggle.addClass('tab-selected');
			container.fade('show').setStyle("display","block");
		},
		onDeselect: function(toggle, container, index) {
			toggle.removeClass('tab-selected');
			container.fade('hide').setStyle("display","none");
		},
		onRequest: function(toggle, container, index) {
			container.addClass('tab-ajax-loading');
		},
		onComplete: function(toggle, container, index) {
			container.removeClass('tab-ajax-loading');
		},
		onFailure: function(toggle, container, index) {
			container.removeClass('tab-ajax-loading');
		},
		onAdded: Class.empty,
		getContent: null,
		ajaxOptions: {},
		cache: true,
        skipLoadingFirst: false,
        firstContainerElement: false,
        firstContainerContent: null
	},

	/**
	 * Constructor
	 *
	 * @param {Element} The parent Element that holds the tab elements
	 * @param {Object} Options
	 */
	initialize: function(element, options) {
		this.element = $(element);
		this.setOptions(options);
		this.selected = null;
		this.build();
	},

	build: function() {
		this.tabs = [];
		this.menu = new Element('ul', {'class': this.options.classMenu});
		this.wrapper = new Element('div', {'class': this.options.classWrapper});
        var pos = 0;
		this.element.getElements(this.options.selector).each(function(el) {
           if(this.options.skipLoadingFirst && this.options.firstContainerElement && pos == 0){
              this.options.firstContainerContent = this.options.firstContainerElement.innerHTML;
              pos++;
           }
            var content = el.get('href') || (this.options.getContent ? this.options.getContent.call(this, el) : el.getNext());
			this.addTab(el.get('html'), el.title || el.get('text'), content, el.get('class') || 'normal');
		}, this);
		this.element.empty().adopt(this.menu, this.wrapper);

		if (this.tabs.length) this.select(this.options.show);
	},

	/**
	 * Add a new tab at the end of the tab menu
	 *
	 * @param {String} inner Text
	 * @param {String} Title
	 * @param {Element|String} Content Element or URL for Ajax
	 */
	addTab: function(text, title, content, classa) {
		var grab = $(content);
        var pos = this.tabs.length;
		var container = (grab || new Element('div'))
			.fade('hide')
			.addClass(this.options.classContainer)
			.inject(this.wrapper);
            
		var evt = (this.options.hover) ? 'mouseenter' : 'click';
		var a = new Element('a', {
				href: '#',
				title: title
			});
		if(container.getElements('a.link').length) {
			a.set('href', container.getElements('a.link').get('href').toString());
		}

		var tab = {
			container: container,
			toggle: new Element('li').grab(a.grab(
				new Element('span', {html: text}).addClass(classa)
			)).addEvent(evt, this.onClick.bindWithEvent(this, [pos])).inject(this.menu)
		};
		if (!grab && $type(content) == 'string') tab.url = content;
		this.tabs.push(tab);
		return this.fireEvent('onAdded', [tab.toggle, tab.container, pos]);
	},

	onClick: function(evt, index) {
		var h=evt.target.parentNode.href;
		if(!h || !h.length || h.indexOf('#')>-1) {
			this.select(index);
		} else {
			window.location = h;
		}
		return false;
	},

	/**
	 * Select the tab via tab-index
	 *
	 * @param {Number} Tab-index
	 */
	select: function(index) {
		if (this.selected === index || !this.tabs[index]) return this;
		if (this.ajax) this.ajax.cancel().removeEvents();
        var tab = this.tabs[index];

        if(this.options.skipLoadingFirst && this.options.firstContainerContent && index == 0){
            tab.loaded = true;
            tab.container.innerHTML = this.options.firstContainerContent;
        }

		var params = [tab.toggle, tab.container, index];
		if (this.selected !== null) {
			var current = this.tabs[this.selected];
			if (this.ajax && this.ajax.running) this.ajax.cancel();
			params.extend([current.toggle, current.container, this.selected]);
			this.fireEvent('onDeselect', [current.toggle, current.container, this.selected]);
		}
        
		this.fireEvent('onSelect', params);

		if (tab.url && (!tab.loaded || !this.options.cache)) {
			this.ajax = this.ajax || new Request.HTML();
			this.ajax.setOptions({
				url: tab.url,
				method: 'get',
				update: tab.container,
				onFailure: this.fireEvent.pass(['onFailure', params], this),
				onComplete: function(resp) {
					tab.loaded = true;
					this.fireEvent('onComplete', params);
				}.bind(this)
			}).setOptions(this.options.ajaxOptions);
			this.ajax.send();
			this.fireEvent('onRequest', params);
		}
		this.selected = index;
		return this;
	}

});

/**
 * Observer - Observe formelements for changes
 *
 * @version		1.0rc3
 *
 * @license		MIT-style license
 * @author		Harald Kirschner <mail [at] digitarald.de>
 * @copyright	Author
 */
var Observer = new Class({

	Implements: [Options, Events],

	options: {
		periodical: false,
		delay: 1000
	},

	initialize: function(el, onFired, options){
		this.setOptions(options);
		this.addEvent('onFired', onFired);
		this.element = $(el) || $$(el);
		this.value = this.element.get('value');
		if (this.options.periodical) this.timer = this.changed.periodical(this.options.periodical, this);
		else this.element.addEvent('keyup', this.changed.bind(this));
	},

	changed: function() {
		var value = this.element.get('value');
		if ($equals(this.value, value)) return;
		this.clear();
		this.value = value;
		this.timeout = this.onFired.delay(this.options.delay, this);
	},

	setValue: function(value) {
		this.value = value;
		this.element.set('value', value);
		return this.clear();
	},

	onFired: function() {
		this.fireEvent('onFired', [this.value, this.element]);
	},

	clear: function() {
		$clear(this.timeout || null);
		return this;
	}

});

var $equals = function(obj1, obj2) {
	return (obj1 == obj2 || JSON.encode(obj1) == JSON.encode(obj2));
};

/**
 * Autocompleter
 *
 * @version		1.1.1
 *
 * @todo: Caching, no-result handling!
 *
 *
 * @license		MIT-style license
 * @author		Harald Kirschner <mail [at] digitarald.de>
 * @copyright	Author
 */
var Autocompleter = {};

Autocompleter.Base = new Class({

	options: {
		minLength: 1,
		markQuery: true,
		width: 'inherit',
		maxChoices: 10,
		injectChoice: null,
		customChoices: null,
		className: 'autocompleter-choices',
		zIndex: 42,
		delay: 400,
		observerOptions: {},
		fxOptions: {},
		onOver: $empty,
		onSelect: $empty,
		onSelection: $empty,
		onShow: $empty,
		onHide: $empty,
		onBlur: $empty,
		onFocus: $empty,

		autoSubmit: false,
		overflow: false,
		overflowMargin: 25,
		selectFirst: false,
		filter: null,
		filterCase: false,
		filterSubset: false,
		forceSelect: false,
		selectMode: true,
		choicesMatch: null,

		multiple: false,
		separator: ', ',
		separatorSplit: /\s*[,;]\s*/,
		autoTrim: true,
		allowDupes: false,

		cache: true,
		relative: false
	},

	initialize: function(element, options) {
		this.element = $(element);
		this.setOptions(options);
		this.build();
		this.observer = new Observer(this.element, this.prefetch.bind(this), $merge({
			'delay': this.options.delay
		}, this.options.observerOptions));
		this.queryValue = null;
		if (this.options.filter) this.filter = this.options.filter.bind(this);
		var mode = this.options.selectMode;
		this.typeAhead = (mode == 'type-ahead');
		this.selectMode = (mode === true) ? 'selection' : mode;
		this.cached = [];
	},

	/**
	 * build - Initialize DOM
	 *
	 * Builds the html structure for choices and appends the events to the element.
	 * Override this function to modify the html generation.
	 */
	build: function() {
		if ($(this.options.customChoices)) {
			this.choices = this.options.customChoices;
		} else {
			this.choices = new Element('ul', {
				'class': this.options.className,
				'styles': {
					'zIndex': this.options.zIndex
				}
			}).inject(document.body);
			this.relative = false;
			if (this.options.relative) {
				this.choices.inject(this.element, 'after');
				this.relative = this.element.getOffsetParent();
			}
			this.fix = new OverlayFix(this.choices,0);
		}
		if (!this.options.separator.test(this.options.separatorSplit)) {
			this.options.separatorSplit = this.options.separator;
		}
		this.fx = (!this.options.fxOptions) ? null : new Fx.Tween(this.choices, $merge({
			'property': 'opacity',
			'link': 'cancel',
			'duration': 200
		}, this.options.fxOptions)).addEvent('onStart', Chain.prototype.clearChain).set(0);
		this.element.setProperty('autocomplete', 'off')
			.addEvent((Browser.Engine.trident || Browser.Engine.webkit) ? 'keydown' : 'keypress', this.onCommand.bind(this))
			.addEvent('click', this.onCommand.bind(this, [false]))
			.addEvent('focus', this.toggleFocus.create({bind: this, arguments: true, delay: 100}))
			.addEvent('blur', this.toggleFocus.create({bind: this, arguments: false, delay: 100}));
		this.choices.setStyle('display','none');
	},

	destroy: function() {
		if (this.fix) this.fix.destroy();
		this.choices = this.selected = this.choices.destroy();
	},

	toggleFocus: function(state) {
		this.focussed = state;
		if (!state) this.hideChoices(true);
		this.fireEvent((state) ? 'onFocus' : 'onBlur', [this.element]);
	},

	onCommand: function(e) {
		if (!e && this.focussed) return this.prefetch();
		if (e && e.key && !e.shift) {
			switch (e.key) {
				case 'enter':
					if (this.element.value != this.opted) return true;
					if (this.selected && this.visible) {
						this.choiceSelect(this.selected);
						return !!(this.options.autoSubmit);
					}
					break;
				case 'up': case 'down':
					if (!this.prefetch() && this.queryValue !== null) {
						var up = (e.key == 'up');
						this.choiceOver((this.selected || this.choices)[
							(this.selected) ? ((up) ? 'getPrevious' : 'getNext') : ((up) ? 'getLast' : 'getFirst')
						](this.options.choicesMatch), true);
					}
					return false;
				case 'esc': case 'tab':
					this.hideChoices(true);
					break;
			}
		}
		return true;
	},

	setSelection: function(finish) {
		var input = this.selected.inputValue, value = input;
		var start = this.queryValue.length, end = input.length;
		if (input.substr(0, start).toLowerCase() != this.queryValue.toLowerCase()) start = 0;
		if (this.options.multiple) {
			var split = this.options.separatorSplit;
			value = this.element.value;
			start += this.queryIndex;
			end += this.queryIndex;
			var old = value.substr(this.queryIndex).split(split, 1)[0];
			value = value.substr(0, this.queryIndex) + input + value.substr(this.queryIndex + old.length);
			if (finish) {
				var space = /[^\s,]+/;
				var tokens = value.split(this.options.separatorSplit).filter(space.test, space);
				if (!this.options.allowDupes) tokens = [].combine(tokens);
				var sep = this.options.separator;
				value = tokens.join(sep) + sep;
				end = value.length;
			}
		}
		this.observer.setValue(value);
		this.opted = value;
		if (finish || this.selectMode == 'pick') start = end;
		this.element.selectRange(start, end);
		this.fireEvent('onSelection', [this.element, this.selected, value, input]);
	},

	showChoices: function() {
		var match = this.options.choicesMatch, first = this.choices.getFirst(match);
		this.selected = this.selectedValue = null;
		if (this.fix) {
			var pos = this.element.getCoordinates(this.relative), width = this.options.width || 'auto';
			this.choices.setStyles({
				'left': pos.left,
				'top': pos.bottom,
				'width': (width === true || width == 'inherit') ? pos.width : width
			});
		}
		if (!first) return;
		if (!this.visible) {
			this.visible = true;
			this.choices.setStyle('display', '');
			if (this.fx) this.fx.start(1);
			this.fireEvent('onShow', [this.element, this.choices]);
		}
		if (this.options.selectFirst || this.typeAhead || first.inputValue == this.queryValue) this.choiceOver(first, this.typeAhead);
		var items = this.choices.getChildren(match), max = this.options.maxChoices;
		var styles = {'overflowY': 'hidden', 'height': ''};
		this.overflown = false;
		if (items.length > max) {
			var item = items[max - 1];
			styles.overflowY = 'scroll';
			styles.height = item.getCoordinates(this.choices).bottom;
			this.overflown = true;
		};
		this.choices.setStyles(styles);
		this.fix.show();
	},

	hideChoices: function(clear) {
		if (clear) {
			var value = this.element.value;
			if (this.options.forceSelect) value = this.opted;
			if (this.options.autoTrim) {
				value = value.split(this.options.separatorSplit).filter($arguments(0)).join(this.options.separator);
			}
			this.observer.setValue(value);
		}
		if (!this.visible) return;
		this.visible = false;
		this.observer.clear();
		var hide = function(){
			this.choices.setStyle('display', 'none');
			this.fix.hide();
		}.bind(this);
		if (this.fx) this.fx.start(0).chain(hide);
		else hide();
		this.fireEvent('onHide', [this.element, this.choices]);
	},

	prefetch: function() {
		var value = this.element.value, query = value;
		if (this.options.multiple) {
			var split = this.options.separatorSplit;
			var values = value.split(split);
			var index = this.element.getCaretPosition();
			var toIndex = value.substr(0, index).split(split);
			var last = toIndex.length - 1;
			index -= toIndex[last].length;
			query = values[last];
		}
		if (query.length < this.options.minLength) {
			this.hideChoices();
		} else {
			if (query === this.queryValue || (this.visible && query == this.selectedValue)) {
				if (this.visible) return false;
				this.showChoices();
			} else {
				this.queryValue = query;
				this.queryIndex = index;
				if (!this.fetchCached()) this.query();
			}
		}
		return true;
	},

	fetchCached: function() {
		return false;
		if (!this.options.cache
			|| !this.cached
			|| !this.cached.length
			|| this.cached.length >= this.options.maxChoices
			|| this.queryValue) return false;
		this.update(this.filter(this.cached));
		return true;
	},

	update: function(tokens) {
		this.choices.empty();
		this.cached = tokens;
		if (!tokens || !tokens.length) {
			this.hideChoices();
		} else {
			if (this.options.maxChoices < tokens.length && !this.options.overflow) tokens.length = this.options.maxChoices;
			tokens.each(this.options.injectChoice || function(token){
				var choice = new Element('li', {'html': this.markQueryValue(token)});
				choice.inputValue = token;
				this.addChoiceEvents(choice).inject(this.choices);
			}, this);
			this.showChoices();
		}
	},

	choiceOver: function(choice, selection) {
		if (!choice || choice == this.selected) return;
		if (this.selected) this.selected.removeClass('autocompleter-selected');
		this.selected = choice.addClass('autocompleter-selected');
		this.fireEvent('onSelect', [this.element, this.selected, selection]);
		if (!selection) return;
		this.selectedValue = this.selected.inputValue;
		if (this.overflown) {
			var coords = this.selected.getCoordinates(this.choices), margin = this.options.overflowMargin,
				top = this.choices.scrollTop, height = this.choices.offsetHeight, bottom = top + height;
			if (coords.top - margin < top && top) this.choices.scrollTop = Math.max(coords.top - margin, 0);
			else if (coords.bottom + margin > bottom) this.choices.scrollTop = Math.min(coords.bottom - height + margin, bottom);
		}
		if (this.selectMode) this.setSelection();
	},

	choiceSelect: function(choice) {
		if (choice) this.choiceOver(choice);
		this.setSelection(true);
		this.queryValue = false;
		this.hideChoices();
	},

	filter: function(tokens) {
		var regex = new RegExp(((this.options.filterSubset) ? '' : '^') + this.queryValue.escapeRegExp(), (this.options.filterCase) ? '' : 'i');
		return (tokens || this.tokens).filter(regex.test, regex);
	},

	/**
	 * markQueryValue
	 *
	 * Marks the queried word in the given string with <span class="autocompleter-queried">*</span>
	 * Call this i.e. from your custom parseChoices, same for addChoiceEvents
	 *
	 * @param		{String} Text
	 * @return		{String} Text
	 */
	markQueryValue: function(str) {
		return (!this.options.markQuery || !this.queryValue) ? str : str.replace(new RegExp('(' + this.queryValue.escapeRegExp() + ')', 'i'), '<em class="autocompleter-queried">$1</em>');
	},

	/**
	 * addChoiceEvents
	 *
	 * Appends the needed event handlers for a choice-entry to the given element.
	 *
	 * @param		{Element} Choice entry
	 * @return		{Element} Choice entry
	 */
	addChoiceEvents: function(el) {
		return el.addEvents({
			'mouseover': this.choiceOver.bind(this, [el]),
			'click': this.choiceSelect.bind(this, [el])
		});
	}
});

Autocompleter.Base.implement(new Events);
Autocompleter.Base.implement(new Options);

Autocompleter.Local = new Class({

	Extends: Autocompleter.Base,

	options: {
		minLength: 0,
		delay: 200
	},

	initialize: function(element, tokens, options) {
		this.parent(element, options);
		this.tokens = tokens;
	},

	query: function() {
		this.update(this.filter());
	}

});

Autocompleter.Ajax = {};

Autocompleter.Ajax.Base = new Class({

	Extends: Autocompleter.Base,

	options: {
		postVar: 'value',
		postData: {},
		ajaxOptions: {},
		onRequest: $empty,
		onComplete: $empty
	},

	initialize: function(element, options) {
		this.parent(element, options);
		var indicator = $(this.options.indicator);
		if (indicator) {
			this.addEvents({
				'onRequest': indicator.show.bind(indicator),
				'onComplete': indicator.hide.bind(indicator)
			}, true);
		}
	},

	query: function(){
		var data = $unlink(this.options.postData);
		data[this.options.postVar] = this.queryValue;
		this.fireEvent('onRequest', [this.element, this.request, data, this.queryValue]);
		this.request.send({'data': data});
	},

	/**
	 * queryResponse - abstract
	 *
	 * Inherated classes have to extend this function and use this.parent(resp)
	 *
	 * @param		{String} Response
	 */
	queryResponse: function() {
		this.fireEvent('onComplete', [this.element, this.request, this.response]);
	}

});

Autocompleter.Ajax.Json = new Class({

	Extends: Autocompleter.Ajax.Base,

	initialize: function(el, url, options) {
		this.parent(el, options);
		this.request = new Request.JSON($merge({
			'url': url,
			'link': 'cancel'
		}, this.options.ajaxOptions)).addEvent('onComplete', this.queryResponse.bind(this));
	},

	queryResponse: function(response) {
		this.parent();
		this.update(response);
	}

});

Autocompleter.Ajax.Xhtml = new Class({

	Extends: Autocompleter.Ajax.Base,

	initialize: function(el, url, options) {
		this.parent(el, options);
		this.request = new Request.HTML($merge({
			'url': url,
			'link': 'cancel',
			'update': this.choices
		}, this.options.ajaxOptions)).addEvent('onComplete', this.queryResponse.bind(this));
	},

	queryResponse: function(tree, elements) {
		this.parent();
		if (!elements || !elements.length) {
			this.hideChoices();
		} else {
			this.choices.getChildren(this.options.choicesMatch).each(this.options.injectChoice || function(choice) {
				elX = choice.getElement('.t');
				if(elX)
				{
					elX.set('html',this.markQueryValue(elX.get('text')));
					choice.inputValue = elX.get('text');
					this.addChoiceEvents(choice);
				}
			}, this);
			this.showChoices();
		}

	}

});


var OverlayFix = new Class({

	initialize: function(el,offset) {
		this.element = $(el);
		this.shown = false;
		this.offset = offset ? offset : 0;
		this.relative = this.element.getOffsetParent();
		if (Browser.Engine.trident) {
			this.fix = new Element('div', {
				'class':'overlayFix',
				'styles': {
					'position': 'absolute',
					'display': 'none',
					'background-color': '#000'
				},
				'opacity':0.25
			}).set('html','<iframe style="display:block;position:absolute;left:0;top:0;border:none;" width="100%" height="100%" frameborder="0" scrolling="no" src=""></iframe>').getFirst().set('opacity',0.01).getParent().inject(this.element, 'after');
		}
		else {
			this.fix = new Element('div', {
				'class':'overlayFix',
				'styles': {
					'position': 'absolute',
					'border': 'none',
					'display': 'none',
					'background-color' : '#000000'
				},
				'opacity':0.25
			}).inject(this.element, 'after');
		}
	},

	show: function() {
		if (this.fix && !this.shown) {
			this.shown = true;
			var coords = this.element.getCoordinates(this.relative);
			delete coords.right;
			delete coords.bottom;
			coords.top += this.offset;
			coords.left += this.offset;
			this.fix.setStyles($extend(coords, {
				'display': '',
				'zIndex': (this.element.getStyle('zIndex') || 1) - 1
			}));
		}
		return this;
	},

	hide: function() {
		if (this.fix && this.shown) {
			this.fix.setStyle('display', 'none');
			this.shown = false;
		}
		return this;
	},

	destroy: function() {
		this.fix = this.fix.destroy();
	}

});

/**
 * @todo Clean that up or check if they exist already
 */
Element.implement({

	getOffsetParent: function() {
		var body = this.getDocument().body;
		if (this == body) return null;
		if (!Browser.Engine.trident) return $(this.offsetParent);
		var el = this;
		while ((el = el.parentNode)){
			if (el == body || Element.getComputedStyle(el, 'position') != 'static') return $(el);
		}
		return null;
	},

	getCaretPosition: function() {
		if (!Browser.Engine.trident) return this.selectionStart;
		this.focus();
		var work = document.selection.createRange();
		var all = this.createTextRange();
		work.setEndPoint('StartToStart', all);
		return work.text.length;
	},

	selectRange: function(start, end) {
		if (Browser.Engine.trident) {
			var range = this.createTextRange();
			range.collapse(true);
			range.moveEnd('character', end);
			range.moveStart('character', start);
			range.select();
		} else {
			this.focus();
			this.setSelectionRange(start, end);
		}
		return this;
	}

});

/*

--------------------------------------
    Slider for 1.2 MooTools double
--------------------------------------

*/

var SliderX = new Class({

	Implements: [Events, Options],

	options: {/*
		onChange: $empty,
		onComplete: $empty,*/
		onTick: function(position){
			this.moveKnob.setStyle(this.property, position);
		},
		snap: false,
		offset: 0,
		range: false,
		wheel: false,
		steps: 100,
		mode: 'horizontal'
	},

	initialize: function(upper, element, options){
		this.upper = $(upper);
		this.element = $(element);
		this.elementBg = this.upper.getElement('div.knobBg');
		this.elementInputOne = this.upper.getElement('input.one');
		this.elementInputTwo = this.upper.getElement('input.two');
		this.knob = this.upper.getElement('div.knob.first');
		this.maxknob = this.upper.getElement('div.knob.second');

		this.setOptions(options);
		this.previousChange = this.previousEnd = this.step = -1;

		var offset, limit = {}, modifiers = {'x': false, 'y': false};
		switch (this.options.mode){
			case 'vertical':
				this.axis = 'y';
				this.property = 'top';
				offset = 'offsetHeight';
				break;
			case 'horizontal':
				this.axis = 'x';
				this.property = 'left';
				offset = 'offsetWidth';
		}
		this.half = this.knob[offset] / 2;

		this.getPos = this.element['get' + this.property.capitalize()].bind(this.element);

		this.full = 304 - this.knob.getSize().x + (this.options.offset * 2);
		this.min = $chk(this.options.range[0]) ? this.options.range[0] : 0;
		this.max = $chk(this.options.range[1]) ? this.options.range[1] : this.options.steps;
		this.range = this.max - this.min;
		this.steps = this.options.steps || this.full;
		this.stepSize = Math.abs(this.range) / this.steps;
		this.stepWidth = this.stepSize * this.full / Math.abs(this.range) ;
		
		this.knob.setStyle(this.property, - this.options.offset);

		this.maxPreviousChange = -1;
		this.maxPreviousEnd = -1;
		this.maxstep = this.options.full;
		this.maxknob.setStyle(this.property, this.full - this.options.offset);

		modifiers[this.axis] = this.property;
		limit[this.axis] = [- this.options.offset, this.full - this.options.offset];
		this.drag = new Drag(this.knob, {
			snap: 0,
			limit: limit,
			modifiers: modifiers,
			onStart: function(){
					this.draggedKnob();
			}.bind(this),
			onDrag: function(){
					this.draggedKnob();
			}.bind(this),
			onComplete: function(){
					this.draggedKnob();
					this.end();
			}.bind(this)
		});
		this.maxdrag = new Drag(this.maxknob, {
			limit: limit,
			modifiers: modifiers,
			snap: 0, 
			onStart: function(){
				this.draggedKnob(1);
			}.bind(this),
			onDrag: function(){
				this.draggedKnob(1);
			}.bind(this),
			onComplete: function(){
				this.draggedKnob(1);
				this.end();
			}.bind(this)
		});
		if (this.options.snap) {
			this.drag.options.grid = Math.ceil(this.stepWidth);
			this.drag.options.limit[this.axis][1] = this.full;
			this.maxdrag.options.grid = Math.ceil(this.stepWidth);
			this.maxdrag.options.limit[this.axis][1] = this.full;
		}
	},

	toStep: function(position){
		var step = (position + this.options.offset) * this.stepSize / this.full * this.steps;
		return this.options.steps ? Math.round(step -= step % this.stepSize) : step;
	},

	toPosition: function(step){
		return (this.full * Math.abs(this.min - step)) / (this.steps * this.stepSize) - this.options.offset;
	},

	setMin: function(stepMin){
		if (!((this.range > 0) ^ (stepMin < this.min))) stepMin = this.min;
		if (!((this.range > 0) ^ (stepMin > this.max))) stepMin = this.max;
		this.step = Math.round(stepMin);
		this.moveKnob = this.knob;
		this.fireEvent('tick', this.toPosition(this.step));
		this.checkStep();
		this.end();
		return this;
	},

	setMax: function(stepMax){
		if (!((this.range > 0) ^ (stepMax < this.min))) stepMax = this.min;
		if (!((this.range > 0) ^ (stepMax > this.max))) stepMax = this.max;
		this.maxstep = Math.round(stepMax);
		this.moveKnob = this.maxknob;
		this.fireEvent('tick', this.toPosition(this.maxstep));
		this.checkStep(1);
		this.end();
		return this;
	},

	draggedKnob: function(mx){
		var dir = this.range < 0 ? -1 : 1;
		if(mx==null) {
			var position = this.drag.value.now[this.axis];
			position = position.limit(-this.options.offset, this.full -this.options.offset);
			this.step = Math.round(this.min + dir * this.toStep(position));
			this.checkStep();
		}
		else {  
			var position = this.maxdrag.value.now[this.axis];
			position = position.limit(-this.options.offset, this.full -this.options.offset);
			this.maxstep = Math.round(this.min + dir * this.toStep(position));
			this.checkStep(1);
		}
	},

	checkStep: function(mx){
		var hasChanged = false;
		if(mx==null) {
			if (this.previousChange != this.step){
				this.previousChange = this.step;
				hasChanged = true;
			}
		}
		else {  
			if (this.maxPreviousChange != this.maxstep){
				this.maxPreviousChange = this.maxstep;
				hasChanged = true;
			}
		}
		if (!hasChanged) return;
		if(this.maxknob!=null) {
			if(this.step < this.maxstep)
				this.fireEvent('change', {
					minpos: this.step, maxpos: this.maxstep,
					step: this.step, maxstep: this.maxstep,
					leftEdge: this.knob.getStyle('left'), rightEdge:this.maxknob.getStyle('left'),
					bg: this.elementBg, inputOne: this.elementInputOne, inputTwo: this.elementInputTwo 
				});
			else
				this.fireEvent('change', {
					minpos: this.maxstep, maxpos: this.step,
					step: this.step, maxstep: this.maxstep, 
					leftEdge: this.maxknob.getStyle('left'), rightEdge:this.knob.getStyle('left'),
					bg: this.elementBg, inputOne: this.elementInputOne, inputTwo: this.elementInputTwo 
				});
		}
		else {
			this.fireEvent('change', this.step);
		}
	},

	end: function(){
		if (this.previousEnd !== this.step || (this.maxknob != null && this.maxPreviousEnd != this.maxstep)) {

			this.previousEnd = this.step;

			if(this.maxknob != null) {
				this.maxPreviousEnd = this.maxstep;

				if(this.step < this.maxstep)
					this.fireEvent('complete', {
						minpos: this.step, maxpos: this.maxstep,
						step: this.step, maxstep: this.maxstep,
						leftEdge: this.knob.getStyle('left'), rightEdge:this.maxknob.getStyle('left'),
						bg: this.elementBg, inputOne: this.elementInputOne, inputTwo: this.elementInputTwo 
					});
				else
					this.fireEvent('complete', {
						minpos: this.maxstep, maxpos: this.step,
						step: this.step, maxstep: this.maxstep, 
						leftEdge: this.maxknob.getStyle('left'), rightEdge:this.knob.getStyle('left'),
						bg: this.elementBg, inputOne: this.elementInputOne, inputTwo: this.elementInputTwo 
					});
			}
			else {  
				this.fireEvent('complete', this.step + '');
			}
		}
	}

});

/*
--------------------------------------
    CustomSelect for 1.2 MooTools
--------------------------------------
*/
var CustomSelect = new Class({

	Implements: Events,

	initialize: function(selectArea,optionContainerClass,afterElement,fixOffset,doOverlay){
		if(!selectArea) { return (false); }
		this.selectArea = selectArea;
		this.id = selectArea.get('id');
		this.selectList = false;
		this.selected = false;
		this.afterElement = afterElement ? afterElement : false;
		this.selectOpen = false;
		this.fixOffset = fixOffset ? fixOffset : 0;
		this.doOverlay = doOverlay;
		this.buildContents();
		if (optionContainerClass) this.optionContainer.addClass(optionContainerClass);
		this.selectElement = $(selectArea).getElement('select');
		this.selectElement.setStyle('display', 'none');
		this.elements = this.selectElement.getChildren().each(function(child) {
			if(child.get('tag') == 'optgroup') {
				this.addOptionGroup(child);
			} else {
				this.addOption(child);
			}
		}.bind(this));
		this.bindEvents();

		if (this.doOverlay) this.fix = new OverlayFix(this.selectArea,this.fixOffset);
    },
	buildContents: function() {
		this.selectField = new Element('div', {
			'class': 'selectField'
		});
		this.dropArea = new Element('div', {
			'class': 'status'
		});
		this.selectedOption = new Element('div', {
			'class': 'selected'
		});
		this.optionContainer = new Element('div', {
			'class': 'optContainer',
			'html': ''
		});
		this.selectedOption.inject(this.dropArea);
		this.dropArea.inject(this.selectField);
		if (this.afterElement)
			this.optionContainer.inject(this.selectArea);
		else
			this.optionContainer.inject(document.body);
		this.selectField.inject(this.selectArea, 'top');
	},
	bindEvents: function() {
		this.dropArea.addEvents({
			'click': function(e){
				if(this.selectOpen == true) {
					this.hideList();
				} else {
					new Event(e).stop();
					this.showList();
				}
			}.bind(this),
			'mouseover': function(e) {
				if(this.selectOpen == false) {
					this.hideList();
				}
			}.bind(this)
		});
		$(document.body).addEvent('click', function() {
			this.hideList();
		}.bind(this));
	},
	
	addOptionGroup: function(optionGroup) {
		var group = new Element('div').addClass('optGroup');
		var label = new Element('div').addClass('optLabel'); 
		var optList  = new Element('div').addClass('optList');
		optList.inject(group);
		label.setText(optionGroup.getProperty('label'));
		label.inject(group, 'top');
		optionGroup.getElements('option').each(function(option) {
			newOption = this.returnOption(option);
			newOption.inject(optList);
		}.bind(this));
		group.inject(this.optionContainer);

	},
	addOption: function(option) {
		newOption = this.returnOption(option);
		newOption.inject(this.optionContainer);
	},
	/* 
	   Znovu nacte Select. Vyuziti pro vazane comboboxy
	*/
	reload: function()
	{
		this.optionContainer.empty();		
		this.elements = this.selectElement.getChildren().each(function(child) {
			if(child.get('tag') == 'optgroup') {
				this.addOptionGroup(child);
			} else {
				this.addOption(child);
			}
		}.bind(this));		
		if (this.doOverlay) this.fix = new OverlayFix(this.selectArea,this.fixOffset);
	},
	
	/* 
	   Vymaze hodnoty selectu.
	*/
	reset: function()
	{
		this.selectElement.empty()
	},
	
	/* 
	   Naplni hodnoty selectu.
	*/
	populate: function(options)
	{
			this.reset();
			if(options != null)
			{
				options.each(function(option){
					o = new Element('option', {
						'value': option.id,
						'text': option.title
					});
					o.inject(this.selectElement);
				}, this);
			}
			this.reload();
	},
	
	/* 
	   Zobrazi loader
	*/
	loader: function()
	{
		this.reset();	
		this.selectedOption.set('html', '<img src="http://www.aaaauto.cz/images/ajax-loader.gif" align="absmiddle"/> Wait please ...');
	},

	returnOption: function(option) {
		var newOption = new Element('div', {
			'class': 'opt',
			'html': option.text
		});
		if($defined(option.getProperty('class')) && $chk(option.getProperty('class'))) {
			newOption.addClass(option.getProperty('class'));
		}
		if(option.disabled) {
			newOption.addClass('disabled') 
		} else {
			newOption.addEvents({
				'click': this.onOptionClick.bindWithEvent(this),
				'mouseout': this.onOptionMouseout.bindWithEvent(this),
				'mouseover': this.onOptionMouseover.bindWithEvent(this)
			})
		}
		if(option.selected) {
			if(this.selected) { this.selected.removeClass('selected'); }
			this.selected = newOption;
			newOption.addClass('selected');
			this.selectedOption.set('text',option.text);
		}
		newOption.value = option.value;
		return newOption;
	},
	onOptionClick: function(e) {
		var event = new Event(e);
		if(this.selected != event.target) {
			this.selected.removeClass('selected');
			event.target.addClass('selected');
			var oldClass = this.selected.get('class').replace(/(opt|over|selected)/g,'').clean();
			var newClass = event.target.get('class').replace(/(opt|over|selected)/g,'').clean();
			this.selected = event.target;
			if (newClass.length>0) this.selectedOption.addClass(newClass);
			if (oldClass.length>0) this.selectedOption.removeClass(oldClass);
			this.selectedOption.set('text',this.selected.get('text'));
			this.selectElement.value = event.target.value;
		 	this.fireEvent('change', event.target.value);
		}
		this.hideList();
	},
	onOptionMouseover: function(e) {
		var event = new Event(e);
		event.target.addClass('over');
	},
	onOptionMouseout: function(e) {
		var event = new Event(e);
		event.target.removeClass('over');
	},
	showList: function() {
		if(this.selectOpen == false) {
			customSelects.each(function(c){c.hideList()});
			this.selectOpen = true;
			pos = this.selectField.getCoordinates();
			if (this.afterElement) {
				this.optionContainer.setStyles({'display':'block',left:0,top:pos.height,'z-index':100});
			}
			else {
				this.optionContainer.setStyles({'display':'block',left:pos.left,top:(pos.top+pos.height),'z-index':800});
			}
			if (this.doOverlay) this.fix.show();
			if (this.optionContainer.getSize().y > 400) this.optionContainer.setStyles({'height':400,'overflow-y':'auto'});
		}
        if(this.optionContainer.hasClass("branch"))
        $$('body.branch div.video-container').setStyles({'display':'none'});
	},
	hideList: function() {
		if(this.selectOpen == true) {
			this.selectOpen = false;
			this.optionContainer.setStyles({'display':'none','z-index':1});
			if (this.doOverlay) this.fix.hide();
		}
        if(this.optionContainer.hasClass("branch"))
        $$('body.branch div.video-container').setStyles({'display':'block'});
	}
});

