var scroller = new Fx.Scroll(window);

var Site = {
	
	start: function(){

		new SmoothScroll({links: '.scroollers'});

		if($('submenu') && $('innerwrapper'))  slidingtabs = new SlidingTabs('submenu','innerwrapper');
		if($('submenu') && $('innerwrappertwo')) Site.ActivateSubmenu();
		if($('submitter')) {
			$('submitter').addEvent('click',function(evt) {
				new Event(evt).stop();
				CheckFeedback.CheckValue();
			});
		}

		$$('a.remooz').each(function(element) {
			new ReMooz(element, {
				origin: element.getElement('img'),
				resizeOptions: {
					transition: Fx.Transitions.Back.easeOut,
					resizeLimit: {x: 600, y: 480},
					resizeOpacity: 0.4,
					hideSource: true
				}
			});
		});

		if($$('h3.atStart').length>0) {
			Site.AccordOne();
		}
		if($$('h3.atStarttwo').length>0) {
			Site.AccordTwo();
		}

		//let's do fancy stuff for the demo download
		if($('system')) {
			var sys=$('system');
			// let's init 
			sys.selectedIndex=0;
			sys.addEvent('change', function() { 
				toppos=(sys.selectedIndex>0) ? sys.selectedIndex.toInt()*40 +'px' : 0+ 'px';
				$('arti-sys').setStyle('background-position', 'center -'+toppos+ '');
				console.log(toppos);
			});
		}
		if($('version')) {
			var ver=$('version');
			// let's init 
			ver.selectedIndex=0;
			ver.addEvent('change', function() { 
				toppos=(ver.selectedIndex>0) ? ver.selectedIndex.toInt()*50 +'px' : 0+ 'px';
				$('arti-mod').setStyle('background-position', 'center -'+toppos+ '');
				
			});
		}
		if($('rdvdate')) {
			$('assist').setStyle('display','none');
			$('pel').addEvent('click', function(e) {
				var toggler=$('pel').checked;
				if(toggler) {
					$('assist').setStyle('display','block');
					$('call').setStyle('display','none');

				}
				else {
					$('assist').setStyle('display','none');
					$('call').setStyle('display','block');
				}
			
			});
			
			MooTools.lang.set('fr-Fr', 'Date', {
				months:    ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Aout', 'Septembre', 'Octobre', 'Novembre', 'Decembre'],
				days:      ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi', 'Samedi'],
				dateOrder: ['date', 'month', 'year', '/']
			});
			MooTools.lang.setLanguage('fr-Fr');
			var maxdate= new Date().increment('month', 3);
			new CalendarEightysix('rdvdate', { 'excludedWeekdays': [0, 6], 'defaultDate': 'today', 'minDate': 'today', 'maxDate': maxdate, 'format':'%A %D %B', 'toggler': 'rdvdate-picker', 'offsetY': -4 });
		}
	},
	
	AccordOne : function () {
		var accordion = new Accordion('h3.atStart', 'div.atStart', {
			opacity: false,
			onActive: function(toggler, element){
				$$('h3.atStart').addEvent('click', function() { 
					Site.scrollTo('contentinner');
				});
				toggler.setStyle('color', '#E16E21');
				toggler.setStyle('cursor', 'default');
				toggler.setStyle('background-position', '0 0');
			},
			onBackground: function(toggler, element){
				toggler.setStyle('background-position', '0 -30px');
				toggler.setStyle('color', '#939393');
				toggler.setStyle('cursor', 's-resize');
			}
		}, $('accordion'));
	},
	
	AccordTwo : function () {
		var accordiontwo = new Accordion('h3.atStarttwo', 'div.atStarttwo', {
			opacity: false,
			onActive: function(toggler, element){
				$$('h3.atStarttwo').addEvent('click', function() { 
					Site.scrollTo('contentinner');
				});
				toggler.setStyle('color', '#E16E21');
				toggler.setStyle('cursor', 'default');
				toggler.setStyle('background-position', '0 0');
			},
			onBackground: function(toggler, element){
				toggler.setStyle('background-position', '0 -30px');
				toggler.setStyle('color', '#939393');
				toggler.setStyle('cursor', 's-resize');
			}
		}, $('accordiontwo'));
	
	},
	ActivateSubmenu: function() {
		$$('#submenu li').each(function(lnk) {
			if(!lnk.hasClass("demo")) {
				lnk.addEvent('click', function(){
					location.href='/logiciels/artifact/';
				});
			}
		});
	},
	scrollTo: function(element){
		if(this.scrollingTo != element) {
			this.scrollTries = 0;
			this.scrollingTo = element;
		} else this.scrollTries++;
		$clear(this.scrollTimer);
		if($(element)) scroller.toElement($(element));
		else
			if(this.scrollTries < 15) this.scrollTimer = this.scrollTo.pass(element, this).delay(100);
	}
}

window.addEvent('domready', function() {
	Site.start();
});

var CheckFeedback = {

	CheckValue : function() {

		var messenger = $('messenger').action;
		var contact = $('contact').value;
		var email = $('email').value;
		//var emailmatch = $('emailmatch').value;
		var phone = $('phone').value;
		var lblcontact = $('lblcontact');
		var lblemail = $('lblemail');
		var lblemailmatch = $('lblemailmatch');
		var lblphone = $('lblphone');
		if($('message')) {
			var message = $('message').value;
			var lblmessage = $('lblmessage');
			var messagee=true;
		}
		else {
			var messagee=true;
		}
		var contacte=true;
		var emaile=true;
		var emailmatche=true;
		
		if(!contact) {
			contacte=false;
			lblcontact.addClass('warn');
			lblcontact.innerHTML = 'Veuillez indiquer votre nom';
		}
		else {
			contacte=true;
			lblcontact.removeClass('warn');
			lblcontact.innerHTML = 'Votre nom';
		}
		if(!email) {
			emaile=false;
			lblemail.addClass('warn');
			lblemail.innerHTML = 'Veuillez indiquer votre e-mail';
		}
		else {
			if (!(/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(email))) {
				emaile=false;
				lblemail.addClass('warn');
				lblemail.innerHTML = 'Votre e-mail n\'est pas valide';
			}
			else {
				emaile=true;
				lblemail.removeClass('warn');
				lblemail.innerHTML = 'Votre e-mail';
			}
		}
		/*
		if(!emailmatch) {
			emaile=false;
			lblemailmatch.addClass('warn');
			lblemailmatch.innerHTML = 'Veuillez confirmer votre e-mail';
		}
		else {
			if (emailmatch!=email) {
				emailmatche=false;
				lblemailmatch.addClass('warn');
				lblemailmatch.innerHTML = 'Vos e-mails ne correspondent pas';
			}
			else {
				emailmatche=true;
				lblemailmatch.removeClass('warn');
				lblemailmatch.innerHTML = 'Veuillez confirmer votre e-mail';
			}
		}
		*/

		if($('title') && $('message')) {
			messagee=true;
		}
		/*
		else if($('message')) {
			if(!message) {
				messagee=false;
				lblmessage.addClass('warn');
				lblmessage.innerHTML = 'Veuillez indiquer un message';
			}
			else {
				messagee=true;
				lblmessage.removeClass('warn');
				lblmessage.innerHTML = 'Votre Message';
			}
		}
		*/
		if(!phone) {
			phonee=false;
			lblphone.addClass('warn');
			lblphone.innerHTML = 'Veuillez indiquer votre numero de telephone';
		}
		else {
			phonee=true;
			lblphone.removeClass('warn');
			lblphone.innerHTML = 'votre numero de telephone';
		}


		/*
		if(messagee==false || !emaile || !emailmatche || !contacte || !phonee) {
			return false;
		}
		*/
		if(messagee==false || !emaile || !contacte || !phonee) {
			return false;
		}
		else {
			if (messenger.search('='))
				var messengeruri=messenger+'&ajax=true';
			else 
				var messengeruri=messenger+'?ajax=true';

			//CheckFeedback.loadUrl(messengeruri);
			$('messenger').submit();
		}
	
	},

	loadUrl : function(theUri) {
		var Uri=theUri;
		// let's first fade content //
		var myPost=$('messenger').toQueryString();
		var FadeContentfx = new Fx.Style($('loader'), 'opacity', {
			wait: true,
			duration: 1000,
			onComplete: function() {
				new Ajax(Uri, {
					method: 'post',
					data: myPost,
					update: 'loader',
					evalScripts: true,
					onComplete: function() {
						var LiveContentFx = new Fx.Style($('loader'), 'opacity', {
									wait: true,
									duration: 1000
								}).start(0,1);
						}
				}).request();
			}
		}).start(1,0);
	}
}
var SlidingTabs = new Class({
  options: {
    startingSlide: 0, // sets the slide to start on, either an element or an id 
    activeButtonClass: 'clicked', // class to add to selected button
    activationEvent: 'click', // you can set this to mouseover or whatever you like
    wrap: true, // calls to previous() and next() should wrap around?
    slideEffect: { // options for effect used to animate the sliding, see Fx.Base in mootools docs
      duration: 800,
    },
    animateHeight: true, // animate height of container
    rightOversized: 0 // how much of the next pane to show to the right of the current pane
  },
  current: null, // zero based current pane number, read only
  buttons: false,
  outerSlidesBox: null,
  innerSlidesBox: null,
  panes: null,
  fx: null, // this one animates the scrolling inside
  heightFx: null, // this one animates the height
  resizeMarker:false,
  
  initialize: function(buttonContainer, slideContainer, options) {
    if (buttonContainer) { this.buttons = $(buttonContainer).getChildren(); }
	
    this.outerSlidesBox = $(slideContainer);
    this.innerSlidesBox = this.outerSlidesBox.getFirst();
    this.panes = this.innerSlidesBox.getChildren();
    
    this.setOptions(options);
    
    //this.fx = new Fx.Scroll(this.outerSlidesBox, this.options.slideEffect);
    this.fx = new Fx.Scroll(this.outerSlidesBox, {
      duration: 800, // 0.4 of a second
      onComplete:function() {
      	this.Externalfunc(this);
      }.bind(this)
    });
    /*
	*/
    this.heightFx = this.outerSlidesBox.set('height', this.options.slideEffect);
    
    // set up button highlight
    this.current = this.options.startingSlide ? this.panes.indexOf($(this.options.startingSlide)) : 0;
    if (this.buttons) { this.buttons[this.current].addClass(this.options.activeButtonClass); }
    
    // add needed stylings
    this.outerSlidesBox.setStyle('overflow', 'hidden');
    this.panes.each(function(pane, index) {
      pane.setStyles({
       'float': 'left',
       'overflow': 'hidden'
      });
    }.bind(this));
    
    // stupidness to make IE work - it boggles the mind why this has any effect
    // maybe it's something to do with giving it layout?
    this.innerSlidesBox.setStyle('float', 'left');
    
    if (this.options.startingSlide) this.fx.toElement(this.options.startingSlide);

    // add events to the buttons
	/*
	if (this.buttons) this.buttons.each( function(button) {
      button.addEvent(this.options.activationEvent, this.buttonEventHandler.bindWithEvent(this, button));
    }.bind(this));
	*/
	
	if (this.buttons) this.buttons.each( function(button) {
	  if(button.hasClass('demo') && $('mono')) {
		button.addEvent(this.options.activationEvent, function(){
			location.href='/logiciels/artifact/telechargement-demos/';
		});
	  }
	  else {
		button.addEvent(this.options.activationEvent, this.buttonEventHandler.bindWithEvent(this, button));
	  }
	}.bind(this));

    if (this.options.animateHeight)
      this.heightFx.set(this.panes[this.current].offsetHeight);
    
    
    // set up all the right widths inside the panes
    this.recalcWidths();
  },
  
  // to change to a specific tab, call this, argument is the pane element you want to switch to.
 Externalfunc:function(element) {

 },
 
changeTo: function(element, animate) {
	//console.log(element);

    if ($type(element) == 'number') element = this.panes[element - 1];
    if (!$defined(animate)) animate = true;
    var event = { cancel: false, target: $(element), animateChange: animate };
    //this.fireEvent('change', event);
    if (event.cancel == true) { return; };
 
    if (this.buttons) { this.buttons[this.current].removeClass(this.options.activeButtonClass); };
 
    this.current = this.panes.indexOf($(event.target));

    var oldHeight = this.outerSlidesBox.getStyle('height');
    this.panes[this.current].setStyle('display','block');
    var oldHeight = this.outerSlidesBox.setStyle('height', oldHeight);
    
    if (this.buttons) { this.buttons[this.current].addClass(this.options.activeButtonClass); };
 
    this.fx.cancel();
    if (event.animateChange) {
      this.fx.toElement(event.target);
    } else {
      this.outerSlidesBox.scrollTo(this.current * this.outerSlidesBox.offsetWidth.toInt(), 0);
    }

    if (this.options.animateHeight) {
       // this.heightFx.tween('height',this.panes[this.current].offsetHeight);
        this.heightFx.tween('height',this.panes[this.current].offsetHeight); 
    }
 
  },
  
  // Handles a click
  buttonEventHandler: function(event, button) {
    if (event.target == this.buttons[this.current]) return;
	event.stop();
    this.changeTo(this.panes[this.buttons.indexOf($(button))]);
  },
  
  // call this to go to the next tab
  next: function() {
    var next = this.current + 1;
    if (next == this.panes.length) {
      if (this.options.wrap == true) { next = 0 } else { return }
    }
    
    this.changeTo(this.panes[next]);
  },
  
  // to go to the previous tab
  previous: function() {
    var prev = this.current - 1
    if (prev < 0) {
      if (this.options.wrap == true) { prev = this.panes.length - 1 } else { return }
    }
    
    this.changeTo(this.panes[prev]);
  },

  jumpto : function(num) {
    this.changeTo(this.panes[num]);
  },
  
  // call this if the width of the sliding tabs container changes to get everything in line again
  recalcWidths: function() {
    this.panes.each(function(pane, index) {
      pane.setStyle('width', this.outerSlidesBox.offsetWidth.toInt() - this.options.rightOversized + 'px');
      //pane.setStyles({'width': '905px', 'overflow': 'auto'});
    }.bind(this));
    
    this.innerSlidesBox.setStyle(
      //'width', (this.outerSlidesBox.offsetWidth.toInt() * this.panes.length) + 'px'
      'width', (640 * this.panes.length) + 'px'
    );

    // fix positioning
    if (this.current > 0) {
      this.fx.cancel();
      this.outerSlidesBox.scrollTo(this.current * this.outerSlidesBox.offsetWidth.toInt(), 0);
    }
  }
});
SlidingTabs.implement(new Options, new Events);

/**
 * ReMooz - Zoomer
 *
 * Inspired by so many boxes and zooms
 *
 * @version		1.0
 *
 * @license		MIT-style license
 * @author		Harald Kirschner <mail [at] digitarald.de>
 * @copyright	Author
 */

var ReMooz = new Class({

	Implements: [Events, Options, Chain],

	options: {
		link: null,
		type: 'image',
		container: null,
		className: null,
		centered: false,
		dragging: true,
		closeOnClick: true,
		shadow: (Browser.Engine.trident) ? 'onOpenEnd' : 'onOpen', // performance
		resize: true,
		margin: 20,
		resizeFactor: 0.95,
		resizeLimit: false, // {x: 640, y: 640}
		fixedSize: false,
		cutOut: true,
		addClick: true,
		opacityLoad: 0.6,
		opacityResize: 1,
		opacityTitle: 0.9,
		resizeOptions: {},
		fxOptions: {},
		closer: true,
		parse: false, // 'rel'
		parseSecure: false,
		temporary: false,
		onBuild: $empty,
		onLoad: $empty,
		onOpen: $empty,
		onOpenEnd: $empty,
		onClose: $empty,
		onCloseEnd: $empty,
		generateTitle: function(el) {
			var text = el.get('title');
			if (!text) return false;
			var title = text.split(' :: ');
			var head = new Element('h6', {'html': title[0]});
			return (title[1]) ? [head, new Element('p', {'html': title[1]})] : head;
		}
	},

	initialize: function(element, options) {
		this.element = $(element);
		this.setOptions(options);
		if (this.options.parse) {
			var obj = this.element.getProperty(this.options.parse);
			if (obj && (obj = JSON.decode(obj, this.options.parseSecure))) this.setOptions(obj);
		}
		var origin = this.options.origin;
		this.origin = ((origin) ? $(origin) || this.element.getElement(origin) : null) || this.element;
		this.link = this.options.link || this.element.get('href') || this.element.get('src');
		this.container = $(this.options.container) || this.element.getDocument();
		this.bound = {
			'click': function(e) {
				this.open.delay(1, this);
				return false;
			}.bind(this),
			'close': this.close.bind(this),
			'dragClose': function(e) {
				if (e.rightClick) return;
				this.close();
			}.bind(this)
		};
		if (this.options.addClick) this.bindToElement();
	},

	destroy: function() {
		if (this.box) this.box.destroy();
		this.box = this.tweens = this.body = this.content = null;
	},

	bindToElement: function(element) {
		($(element) || this.element).addClass('remooz-element').addEvent('click', this.bound.click);
		return this;
	},

	getOriginCoordinates: function() {
		var coords = this.origin.getCoordinates();
		delete coords.right;
		delete coords.bottom;
		return coords;
	},

	open: function(e) {
		if (this.opened) return (e) ? this.close() : this;
		this.opened = this.loading = true;
		if (!this.box) this.build();
		this.coords = this.getOriginCoordinates();
		this.coords.opacity = this.options.opacityLoad;
		this.coords.display = '';
		this.tweens.box.set(this.coords);
		this.box.addClass('remooz-loading');
		ReMooz.open(this.fireEvent('onLoad'));
		this['open' + this.options.type.capitalize()]();
		return this;
	},

	finishOpen: function() {
		this.tweens.fade.start(0, 1);
		this.drag.attach();
		this.fireEvent('onOpenEnd').callChain();
	},

	close: function() {
		if (!this.opened) return this;
		this.opened = false;
		ReMooz.close(this.fireEvent('onClose'));
		if (this.loading) {
			this.box.setStyle('display', 'none');
			return this;
		}
		this.drag.detach();
		this.tweens.fade.cancel().set(0).fireEvent('onComplete');
		if (this.tweens.box.timer) this.tweens.box.clearChain();
		var vars = this.getOriginCoordinates();
		if (this.options.opacityResize != 1) vars.opacity = this.options.opacityResize;
		this.tweens.box.start(vars).chain(this.closeEnd.bind(this));
		return this;
	},

	closeEnd: function() {
		if (this.options.cutOut) this.element.setStyle('visibility', 'visible');
		this.box.setStyle('display', 'none');
		this.fireEvent('onCloseEnd').callChain();
		if (this.options.temporary) this.destroy();
	},

	openImage: function() {
		var tmp = new Image();
		tmp.onload = tmp.onabort = tmp.onerror = function(fast) {
			this.loading = tmp.onload = tmp.onabort = tmp.onerror = null;
			if (!tmp.width || !this.opened) {
				this.fireEvent('onError').close();
				return;
			}
			var to = {x: tmp.width, y: tmp.height};
			if (!this.content) this.content = $(tmp).inject(this.body);
			else tmp = null;
			this[(this.options.resize) ? 'zoomRelativeTo' : 'zoomTo'].create({
				'delay': (tmp && fast !== true) ? 1 : null,
				'arguments': [to],
				'bind': this
			})();
		}.bind(this);
		tmp.src = this.link;
		if (tmp && tmp.complete && tmp.onload) tmp.onload(true);
	},

	/**
	 * @todo Test implementation
	 */
	openElement: function() {
		this.content = this.content || $(this.link) || $E(this.link);
		if (!this.content) {
			this.fireEvent('onError').close();
			return;
		}
		this.content.inject(this.body);
		this.zoomTo({x: this.content.scrollWidth, y: this.content.scrollHeight});
	},

	zoomRelativeTo: function(to) {
		var scale = this.options.resizeLimit;
		if (!scale) {
			scale = this.container.getSize();
			scale.x *= this.options.resizeFactor;
			scale.y *= this.options.resizeFactor;
		}
		for (var i = 2; i--;) {
			if (to.x > scale.x) {
				to.y *= scale.x / to.x;
				to.x = scale.x;
			} else if (to.y > scale.y) {
				to.x *= scale.y / to.y;
				to.y = scale.y;
			}
		}
		return this.zoomTo({x: to.x.toInt(), y: to.y.toInt()});
	},

	zoomTo: function(to) {
		to = this.options.fixedSize || to;
		var box = this.container.getSize(), scroll = this.container.getScroll();
		var pos = (!this.options.centered) ? {
			x: (this.coords.left + (this.coords.width / 2) - to.x / 2).toInt()
				.limit(scroll.x + this.options.margin, scroll.x + box.x - this.options.margin - to.x),
			y: (this.coords.top + (this.coords.height / 2) - to.y / 2).toInt()
				.limit(scroll.y + this.options.margin, scroll.y + box.y - this.options.margin - to.y)
		} :  {
			x: scroll.x + ((box.x - to.x) / 2).toInt(),
			y: scroll.y + ((box.y - to.y) / 2).toInt()
		};
		if (this.options.cutOut) this.element.setStyle('visibility', 'hidden');
		this.box.removeClass('remooz-loading');
		var vars = {left: pos.x, top: pos.y, width: to.x, height: to.y};
		if (this.options.opacityResize != 1) vars.opacity = [this.options.opacityResize, 1];
		else this.box.set('opacity', 1);
		this.tweens.box.start(vars).chain(this.finishOpen.bind(this));
		this.fireEvent('onOpen');
	},

	build: function() {
		this.addEvent('onBlur', function() {
			this.focused = false;
			this.box.removeClass('remooz-box-focus').setStyle('z-index', ReMooz.options.zIndex);
		}, true);
		this.addEvent('onFocus', function() {
			this.focused = true;
			this.box.addClass('remooz-box-focus').setStyle('z-index', ReMooz.options.zIndexFocus);
		}, true);

		var classes = ['remooz-box', 'remooz-type-' + this.options.type, 'remooz-engine-' + Browser.Engine.name + Browser.Engine.version];
		if (this.options.className) classes.push(this.options.className);
		this.box = new Element('div', {
			'class': classes.join(' '),
			'styles': {
				'display': 'none',
				'top': 0,
				'left': 0,
				'zIndex': ReMooz.options.zIndex
			}
		});

		this.tweens = {
			'box': new Fx.Morph(this.box, $merge({
					'duration': 400,
					'unit': 'px',
					'transition': Fx.Transitions.Quart.easeOut,
					'chain': 'cancel'
				}, this.options.resizeOptions)
			),
			'fade': new Fx.Tween(null, $merge({
					'property': 'opacity',
					'duration': (Browser.Engine.trident) ? 0 : 300,
					'chain': 'cancel'
				}, this.options.fxOptions)).addEvents({
					'onComplete': function() {
						if (!this.element.get('opacity')) this.element.setStyle('display', 'none');
					},
					'onStart': function() {
						if (!this.element.get('opacity')) this.element.setStyle('display', '');
					}
				}
			)
		};
		this.tweens.fade.element = $$();

		if (this.options.shadow) {
			if (Browser.Engine.webkit420) {
				this.box.setStyle('-webkit-box-shadow', '0 0 10px rgba(0, 0, 0, 0.7)');
			} else if (!Browser.Engine.trident4) {
				var shadow = new Element('div', {'class': 'remooz-bg-wrap'}).inject(this.box);
				['n', 'ne', 'e', 'se', 's', 'sw', 'w', 'nw'].each(function(dir) {
					new Element('div', {'class': 'remooz-bg remooz-bg-' + dir}).inject(shadow);
				});
				this.tweens.bg = new Fx.Tween(shadow, {
					'property': 'opacity',
					'chain': 'cancel'
				}).set(0);
				this.addEvent(this.options.shadow, this.tweens.bg.set.bind(this.tweens.bg, 1), true);
				this.addEvent('onClose', this.tweens.bg.set.bind(this.tweens.bg, 0), true);
			}
		}

		if (this.options.closer) {
			var closer = new Element('a', {
				'class': 'remooz-btn-close',
				'events': {'click': this.bound.close}
			}).inject(this.box);
			this.tweens.fade.element.push(closer);
		}
		this.body = new Element('div', {'class': 'remooz-body'}).inject(this.box);

		var title = this.options.title || this.options.generateTitle.call(this, this.element);
		if (title) { // thx ie6
			var title = new Element('div', {'class': 'remooz-title'}).adopt(
				new Element('div', {'class': 'remooz-title-bg', 'opacity': this.options.opacityTitle}),
				new Element('div', {'class': 'remooz-title-content'}).adopt(title)
			).inject(this.box);
			this.tweens.fade.element.push(title);
		}
		this.tweens.fade.set(0).fireEvent('onComplete');

		this.drag = new Drag.Move(this.box, {
			'snap': 15,
			'preventDefault': true,
			'onBeforeStart': function() {
				if (!this.focused && !this.loading) ReMooz.focus(this);
				else if (this.loading || this.options.closeOnClick) this.box.addEvent('mouseup', this.bound.dragClose);
			}.bind(this),
			'onSnap': function() {
				this.box.removeEvent('mouseup', this.bound.dragClose);
				if (!this.options.dragging) this.drag.stop();
				else this.box.addClass('remooz-box-dragging');
			}.bind(this),
			'onComplete': function() {
				this.box.removeClass('remooz-box-dragging');
			}.bind(this)
		});
		this.drag.detach();

		this.fireEvent('onBuild', this.box, this.element);
		this.box.inject(this.element.getDocument().body);
	}

});

ReMooz.factory = function(extended) {
	return $extend(this, extended);
};

ReMooz.factory(new Options).factory({

	options: {
		zIndex: 41,
		zIndexFocus: 42,
		query: 'a.remooz',
		modal: false
	},

	assign: function(elements, options) {
		return $$(elements).map(function(element) {
			return new ReMooz(element, options);
		}, this);
	},

	stack: [],

	open: function(obj) {
		var last = this.stack.getLast();
		this.focus(obj);
		if (last && this.options.modal) last.close();
	},

	close: function(obj) {
		var length = this.stack.length - 1;
		if (length > 1 && this.stack[length] == obj) this.focus(this.stack[length - 1]);
		this.stack.erase(obj);
	},

	focus: function(obj) {
		var last = this.stack.getLast();
		obj.fireEvent('onFocus', [obj]);
		if (last == obj) return;
		if (last) last.fireEvent('onBlur', [last]);
		this.stack.erase(obj).push(obj);
	}

});

var CalendarEightysix = new Class({
	Implements: [Events, Options],
	
	options: {
		'slideDuration': 500,
		'fadeDuration': 200,
		'toggleDuration': 200,
		'fadeTransition': Fx.Transitions.linear,
		'slideTransition': Fx.Transitions.Quart.easeOut,
		
		'prefill': true,
		'defaultDate': null,
		'linkWithInput': true,
		'keyNavigation': false,
		
		'theme': 'default',
		'defaultView': 'month',
		'startMonday': false,
		'alwaysShow': false,
		'injectInsideTarget': false,
		'format': '%m/%d/%Y',
		'alignX': 'right',
		'alignY': 'ceiling',
		'offsetX': 0,
		'offsetY': 0,
		
		'draggable': false,
		'pickable': true,
		'toggler': null,
		'disallowUserInput': false,
		
		'minDate': null,
		'maxDate': null,
		'excludedWeekdays': null,
		'excludedDates': null,
		
		'createHiddenInput': false,
		'hiddenInputName': 'date',
		'hiddenInputFormat': '%t'
	},
	
	initialize: function(target, options) {
		this.setOptions(options);
		
		this.target = $(target);
		this.transitioning = false;
		this.today = new Date().clearTime();
		
		//Extend Date with unix timestamp parser
		Date.defineParser({
		    re: /^[0-9]{10}$/,
		    handler: function(bits) { return new Date.parse('Jan 01 1970').set('seconds', bits[0]); }
		});
		//Extend Date with a workaround for the '-' delimiter parse bug
		Date.defineParser({
		    re: /\-/,
		    handler: function(bits) { return new Date.parse(bits.input.replace(/\-/, '.')); }
		});
		
		//Create the currect selected date
		if($defined(this.options.defaultDate)) 
			this.selectedDate = new Date().parse(this.options.defaultDate).clearTime();
		else if(this.options.linkWithInput && $chk(this.target.get('value'))) 
			this.selectedDate = new Date().parse(this.target.get('value')).clearTime();
		if(!$defined(this.selectedDate) || !this.selectedDate.isValid()) 
			this.selectedDate = this.today.clone();
		
		//Create the HTML base of the calender
		var innerHtml = '<div class="c86-wrapper"><div class="c86-header"><div class="c86-arrow-left"></div><div class="c86-arrow-right"></div><div class="c86-label c86-clickable"></div></div>'+
							'<div class="c86-body"><div class="c86-inner"><div class="c86-container a"></div><div class="c86-container b"></div></div></div><div class="c86-footer"></div></div>';
		this.element = new Element('div', { 'class': 'calendar-eightysix', 'html': innerHtml, 'style': 'display: '+ (this.options.alwaysShow ? 'block' : 'none') }).addClass(this.options.theme);
		
		//Add the calender to the document and position it
		if(this.options.injectInsideTarget) this.element.injectBottom(this.target);
		else {
			this.element.injectBottom($(document.body));
			this.position();
			window.addEvent('resize', this.position.bind(this));
		}
		
		//Assign the containers
		this.currentContainer = this.element.getElement('.c86-container.a').setStyle('z-index', 999);
		this.tempContainer = this.element.getElement('.c86-container.b').setStyle('z-index', 998);
		
		//Assign the interface elements and events
		this.header = this.element.getElement('.c86-header');
		this.label = this.header.getElement('.c86-label');
		this.arrowLeft = this.header.getElement('.c86-arrow-left');
		this.arrowRight = this.header.getElement('.c86-arrow-right');
		
		this.label.addEvent('click', this.levelUp.bind(this));
		this.arrowLeft.addEvent('click', this.slideLeft.bind(this));
		this.arrowRight.addEvent('click', this.slideRight.bind(this));
		
		//Create dates ranges
		if($defined(this.options.minDate)) {
			this.options.minDate = Date.parse(this.options.minDate).clearTime();
			if(!this.options.minDate.isValid()) this.options.minDate = null;
		}
		if($defined(this.options.maxDate)) {
			this.options.maxDate = Date.parse(this.options.maxDate).clearTime();
			if(!this.options.maxDate.isValid()) this.options.maxDate = null;
		}
		
		//Parse excluded dates
		if($defined(this.options.excludedDates)) {
			var excludedDates = [];
			this.options.excludedDates.each(function(date) {
				excludedDates.include(this.format(new Date().parse(date).clearTime(), '%t'));
			}.bind(this));
			this.options.excludedDates = excludedDates;
		}
		
		//Make the calendar draggable?
		if(this.options.draggable && !this.options.injectInsideTarget) {
			this.header.addClass('c86-dragger');
			this.label.setStyle('width', 'auto');
			new Drag(this.element, { 'handle': this.header });
		}
		
		//Create hidden input
		if(this.options.createHiddenInput) {
			this.hiddenInput = new Element('input', { 'type': 'hidden', 'name': this.options.hiddenInputName }).injectAfter(this.target);
		}
		
		//Link with the input element
		if(!this.options.disallowUserInput && this.options.linkWithInput && this.target.get('tag') == 'input') {
			this.target.addEvent('keyup', function() {
				this.setDate(this.target.get('value'), false);
			}.bind(this));
		}
		//Or toggler...
		if($defined(this.options.toggler)) this.options.toggler = $(this.options.toggler);
		
		//Add show and hide events
		($defined(this.options.toggler) ? this.options.toggler : this.target).addEvents({
			'focus': this.show.bind(this), 'click': this.show.bind(this)
		});
		
		if(!this.options.alwaysShow) document.addEvent('mousedown', this.outsideClick.bind(this));
		MooTools.lang.addEvent('langChange', function() { this.render(); this.pick(); }.bind(this));
		
		//Other events
		if(this.target.get('tag') == 'input') {
			this.target.addEvent('keydown', this.onKeyDown.bind(this));
			if(this.options.disallowUserInput) this.target.addEvent('contextmenu', ($lambda(false)));
		}
		
		//See if the date is correct
		this.selectedDate = this.correctDate(this.selectedDate);
		
		//Prefill the current date
		if(this.options.prefill) this.pick();
		
		//Render the default view
		this.viewDate = this.selectedDate.clone().set('date', 1).clearTime();
		this.view = this.options.defaultView;
		this.render();
	},
	
	render: function() {
		this.currentContainer.empty();
		
		switch(this.view) {
			case 'decade': this.renderDecade(); break;
			case 'year': this.renderYear(); break;
			default: this.renderMonth();
		}
		
		return this;
	},
	
	/* Rendering */
	
	renderMonth: function() {
		this.view = 'month';
		this.currentContainer.empty().addClass('c86-month');
		if(this.options.pickable) this.currentContainer.addClass('c86-pickable');
		
		var lang = MooTools.lang.get('Date'), weekdaysCount = this.viewDate.format('%w') - (this.options.startMonday ? 1 : 0);
		if(weekdaysCount == -1) weekdaysCount = 6;
		
		//Label
		this.label.set('html', lang.months[this.viewDate.get('month')] +' '+ this.viewDate.format('%Y'));
		
		//Day label row
		var row = new Element('div', { 'class': 'c86-row' }).injectBottom(this.currentContainer);
		for(var i = (this.options.startMonday ? 1 : 0); i < (this.options.startMonday ? 8 : 7); i++) {
			var day = new Element('div', { 'html': lang.days[this.options.startMonday && i == 7 ? 0 : i] }).injectBottom(row);
			day.set('html', day.get('html').substr(0, 2));
		}
		
		//Add days for the beginning non-month days
		row = new Element('div', { 'class': 'c86-row' }).injectBottom(this.currentContainer);
		y = this.viewDate.clone().decrement('month').getLastDayOfMonth();
		for(var i = 0; i < weekdaysCount; i++) {
			this.injectDay(row, this.viewDate.clone().decrement('month').set('date', y - (weekdaysCount - i) + 1), true);
		}
		
		//Add month days
		for(var i = 1; i <= this.viewDate.getLastDayOfMonth(); i++) {
			this.injectDay(row, this.viewDate.clone().set('date', i));
			if(row.getChildren().length == 7) {
				row = new Element('div', { 'class': 'c86-row' }).injectBottom(this.currentContainer);
			}
		}
		
		//Add outside days
		var y = 8 - row.getChildren().length, startDate = this.viewDate.clone().increment('month').set('date', 1);
		for(var i = 1; i < y; i++) {
			this.injectDay(row, startDate.clone().set('date', i), true);
		}
		
		//Always have six rows
		for(var y = this.currentContainer.getElements('.c86-row').length; y < 7; y++) {
			row = new Element('div', { 'class': 'c86-row' }).injectBottom(this.currentContainer);
			for(var z = 0; z < 7; z++) {
				this.injectDay(row, startDate.clone().set('date', i), true);
				i++;
			}
		}
		
		this.renderAfter();
	},
	
	//Used by renderMonth
	injectDay: function(row, date, outside) {
		var day = new Element('div', { 'html': date.get('date') }).injectBottom(row);
		day.store('date', date);
		if(outside) day.addClass('c86-outside');
		
		if(($defined(this.options.minDate) && this.format(this.options.minDate, '%t') > this.format(date, '%t')) || 
		   ($defined(this.options.maxDate) && this.format(this.options.maxDate, '%t') < this.format(date, '%t')) ||
		   ($defined(this.options.excludedWeekdays) && this.options.excludedWeekdays.contains(date.format('%w').toInt())) ||
		   ($defined(this.options.excludedDates) && this.options.excludedDates.contains(this.format(date, '%t'))))
			day.addClass('c86-non-selectable');
		else if(this.options.pickable) day.addEvent('click', this.pick.bind(this));
		
		if(date.format('%x') == this.today.format('%x')) day.addClass('c86-today');
		if(date.format('%x') == this.selectedDate.format('%x')) day.addClass('c86-selected');
	},
	
	renderYear: function() {
		this.view = 'year';
		this.currentContainer.addClass('c86-year-decade');
		var lang = MooTools.lang.get('Date').months;
		
		//Label
		this.label.set('html', this.viewDate.format('%Y'));
		
		var row = new Element('div', { 'class': 'c86-row' }).injectBottom(this.currentContainer);
		for(var i = 1; i < 13; i++) {
			var month = new Element('div', { 'html': lang[i - 1] }).injectBottom(row);
			month.set('html', month.get('html').substr(0, 3)); //Setting and getting the innerHTML takes care of html entity problems (e.g. [M&a]uml;r => [Mär]z)
			var iMonth = this.viewDate.clone().set('month', i - 1);
			month.store('date', iMonth);
			
			if(($defined(this.options.minDate) && this.format(this.options.minDate.clone().set('date', 1), '%t') > this.format(iMonth, '%t')) ||
			   ($defined(this.options.maxDate) && this.format(this.options.maxDate.clone().set('date', 1), '%t') < this.format(iMonth, '%t')))
				month.addClass('c86-non-selectable');
			else month.addEvent('click', this.levelDown.bind(this));
			
			if(i - 1 == this.today.get('month') && this.viewDate.get('year') == this.today.get('year')) month.addClass('c86-today');
			if(i - 1 == this.selectedDate.get('month') && this.viewDate.get('year') == this.selectedDate.get('year')) month.addClass('c86-selected');
			if(!(i % 4) && i != 12) row = new Element('div', { 'class': 'c86-row' }).injectBottom(this.currentContainer);
		}
		
		this.renderAfter();
	},
	
	renderDecade: function() {
		this.label.removeClass('c86-clickable');
		this.view = 'decade';
		this.currentContainer.addClass('c86-year-decade');
		
		var viewYear, startYear;
		viewYear = startYear = this.viewDate.format('%Y').toInt();
		while(startYear % 12) startYear--;
		
		//Label
		this.label.set('html', startYear +' &#150; '+ (startYear + 11));
		
		var row = new Element('div', { 'class': 'c86-row' }).injectBottom(this.currentContainer);
		for(var i = startYear; i < startYear + 12; i++) {
			var year = new Element('div', { 'html': i }).injectBottom(row);
			var iYear = this.viewDate.clone().set('year', i);
			year.store('date', iYear);
			
			if(($defined(this.options.minDate) && this.options.minDate.get('year') > i) ||
			   ($defined(this.options.maxDate) && this.options.maxDate.get('year') < i)) year.addClass('c86-non-selectable');
			else year.addEvent('click', this.levelDown.bind(this));
			
			if(i == this.today.get('year')) year.addClass('c86-today');
			if(i == this.selectedDate.get('year')) year.addClass('c86-selected');
			if(!((i + 1) % 4) && i != startYear + 11) row = new Element('div', { 'class': 'c86-row' }).injectBottom(this.currentContainer);
		}
		
		this.renderAfter();
	},
	
	renderAfter: function() {
		//Iterate rows and add classes and remove navigation if nessesary
		var rows = this.currentContainer.getElements('.c86-row');
		
		for(var i = 0; i < rows.length; i++) {
			rows[i].set('class', 'c86-row '+ ['a', 'b', 'c', 'd', 'e', 'f', 'g'][i] +' '+ (i % 2 ? 'c86-even' : 'c86-odd')).getFirst().addClass('c86-first');
			rows[i].getLast().addClass('c86-last');
			
			if( (this.view == 'month' && i == 1 && $defined(this.options.minDate) && this.options.minDate.diff(this.viewDate) <= 0) ||
				(this.view != 'month' && i == 0 && $defined(this.options.minDate) && this.format(this.options.minDate, '%t') >= this.format(rows[i].getFirst().retrieve('date'), '%t')) )
				this.arrowLeft.setStyle('visibility', 'hidden');
			
			if(i == rows.length - 1 && $defined(this.options.maxDate)) {
				if((this.view == 'month' && this.options.maxDate.diff(this.viewDate.clone().increment('month').decrement()) >= 0) ||
				   (this.view == 'year' &&  this.format(this.options.maxDate, '%t') <= this.format(rows[i].getLast().retrieve('date').clone().increment('month'), '%t')) ||
				   (this.view == 'decade' && this.format(this.options.maxDate, '%t') <= this.format(rows[i].getLast().retrieve('date').clone().increment('year'), '%t')))
					this.arrowRight.setStyle('visibility', 'hidden');
			}
		};
		
		if($defined(this.$events['render'+ this.view])) {
			var elements = this.currentContainer.getElements('div[class~=c86-row] > div');
			if(this.view == 'month') {
				for(var i = 0; i < 7; i++) elements[i] = null;
				elements = elements.clean();
			}
			this.fireEvent('render'+ this.view, { 'view': this.view, 'elements': elements });
		}
	},
	
	/* Animations */
	
	slideLeft: function() {
		this.switchContainers();
		
		//Render new view
		switch(this.view) {
			case 'month':  this.viewDate.decrement('month'); break;
			case 'year':   this.viewDate.decrement('year'); break;
			case 'decade': this.viewDate.set('year', this.viewDate.get('year') - 12); break;
		}
		this.render();
		
		//Tween the new view in and old view out
		this.currentContainer.set('tween', { 'duration': this.options.slideDuration, 'transition': this.options.slideTransition }).tween('left', [-this.currentContainer.getWidth(), 0]);
		this.tempContainer.set('tween', { 'duration': this.options.slideDuration, 'transition': this.options.slideTransition }).tween('left', [0, this.tempContainer.getWidth()]);
	},
	
	slideRight: function() {
		this.switchContainers();
		
		//Render new view
		switch(this.view) {
			case 'month': this.viewDate.increment('month'); break;
			case 'year': this.viewDate.increment('year'); break;
			case 'decade': this.viewDate.set('year', this.viewDate.get('year') + 12); break;
		}
		this.render();
		
		//Tween the new view in and old view out
		this.currentContainer.set('tween', { 'duration': this.options.slideDuration, 'transition': this.options.slideTransition }).tween('left', [this.currentContainer.getWidth(), 0]);
		this.tempContainer.set('tween', { 'duration': this.options.slideDuration, 'transition': this.options.slideTransition }).tween('left', [0, -this.currentContainer.getWidth()]);
	},
	
	levelDown: function(e) {
		if(this.transitioning) return;
		this.switchContainers();
		this.viewDate = $(e.target).retrieve('date');
		
		//Render new view
		switch(this.view) {
			case 'year': this.renderMonth(); break;
			case 'decade': this.renderYear(); break;
		}
		
		//Tween the new view in and old view out
		this.transitioning = true;
		this.currentContainer.set('tween', { 'duration': this.options.fadeDuration, 'transition': this.options.fadeTransition, 
											 'onComplete': function() { this.transitioning = false }.bind(this) }).setStyles({'opacity': 0, 'left': 0}).fade('in');
		this.tempContainer.set('tween', { 'duration': this.options.fadeDuration, 'transition': this.options.fadeTransition }).fade('out');
	},
	
	levelUp: function() {
		if(this.view == 'decade' || this.transitioning) return;
		this.switchContainers();
		
		//Set viewdates and render
		switch(this.view) {
			case 'month': this.renderYear(); break;
			case 'year':  this.renderDecade(); break;
		}
		
		//Tween the new view in and old view out
		this.transitioning = true;
		this.currentContainer.set('tween', { 'duration': this.options.fadeDuration, 'transition': this.options.fadeTransition, 
											 'onComplete': function() { this.transitioning = false }.bind(this) }).setStyles({'opacity': 0, 'left': 0}).fade('in');
		this.tempContainer.set('tween', { 'duration': this.options.fadeDuration, 'transition': this.options.fadeTransition }).fade('out');
	},
	
	switchContainers: function() {
		this.currentContainer = this.currentContainer.hasClass('a') ? this.element.getElement('.c86-container.b') : this.element.getElement('.c86-container.a');
		this.tempContainer = this.tempContainer.hasClass('a') ? this.element.getElement('.c86-container.b') : this.element.getElement('.c86-container.a');
		this.currentContainer.empty().removeClass('c86-month').removeClass('c86-year-decade').setStyles({ 'opacity': 1, 'display': 'block', 'z-index': 999 });
		this.tempContainer.setStyle('z-index', 998);
		
		this.label.addClass('c86-clickable');
		this.arrowLeft.setStyle('visibility', 'visible');
		this.arrowRight.setStyle('visibility', 'visible');
	},
	
	/* Positioning and visibility */
	
	position: function() {
		var top, left;
		var coordinates = this.target.getCoordinates();
		
		switch(this.options.alignX) {
			case 'left':
				left = coordinates.left;
				break;
			case 'middle':
				left = coordinates.left + (coordinates.width / 2) - (this.element.getWidth() / 2);
				break;
			case 'right': default:
				left = coordinates.left + coordinates.width;
		}
		
		switch(this.options.alignY) {
			case 'bottom':
				top = coordinates.top + coordinates.height;
				break;
			case 'top':
				top = coordinates.top - this.element.getHeight();
				break;
			case 'ceiling': default:
				top = coordinates.top;
		}
		
		left += this.options.offsetX.toInt();
		top += this.options.offsetY.toInt();
		
		this.element.setStyles({ 'top': top, 'left': left });
	},
	
	show: function() {
		if(!this.visible & !this.options.alwaysShow) {
			this.visible = true;
			if(!Browser.Engine.trident) {
				this.element.setStyles({ 'opacity': 0, 'display': 'block' });
				if(!this.options.injectInsideTarget) this.position();
				this.element.set('tween', { 'duration': this.options.toggleDuration, 'transition': this.options.fadeTransition }).fade('in');
			}  else {
				this.element.setStyles({ 'opacity': 1, 'display': 'block' });
				if(!this.options.injectInsideTarget) this.position();
			}
		}
	},
	
	hide: function() {
		if(this.visible & !this.options.alwaysShow) {
			this.visible = false;
			if(!Browser.Engine.trident) {
				this.element.set('tween', { 'duration': this.options.toggleDuration, 'transition': this.options.fadeTransition,
											'onComplete': function() { this.element.setStyle('display', 'none') }.bind(this) }).fade('out');
			} else this.element.setStyle('display', 'none');
		}
	},
	
	toggle: function() {
		if(this.visible) this.hide();
		else this.show();
	},
	
	outsideClick: function(e) {
		if(this.visible) {
			var elementCoords = this.element.getCoordinates();
			var targetCoords  = this.target.getCoordinates();
			if(((e.page.x < elementCoords.left || e.page.x > (elementCoords.left + elementCoords.width)) ||
			    (e.page.y < elementCoords.top || e.page.y > (elementCoords.top + elementCoords.height))) &&
			   ((e.page.x < targetCoords.left || e.page.x > (targetCoords.left + targetCoords.width)) ||
			    (e.page.y < targetCoords.top || e.page.y > (targetCoords.top + targetCoords.height))) ) this.hide();
		}
	},
	
	/* Formating and picking */
	
	pick: function(e) {
		if($defined(e)) {
			this.selectedDate = $(e.target).retrieve('date');
			this.element.getElements('.c86-selected').removeClass('c86-selected');
			$(e.target).addClass('c86-selected');
			
			(this.hide.bind(this)).delay(150);
			
			//If outside day, set viewdate and render
			if($(e.target).hasClass('c86-outside')) {
				if(this.options.alwaysShow) {
					if(this.selectedDate.diff(this.viewDate) > 0) this.slideLeft();
					else this.slideRight();
				} else {
					this.viewDate = this.selectedDate.clone().set('date', 1);
					(this.render.bind(this)).delay(300);
				}
			}
		}
		
		var value = this.format(this.selectedDate);
		
		if(!this.options.injectInsideTarget) {
			switch(this.target.get('tag')) {
				case 'input': this.target.set('value', value); break;
				default: this.target.set('html', value);
			}
		}
		
		if($defined(this.hiddenInput)) this.hiddenInput.set('value', this.format(this.selectedDate, this.options.hiddenInputFormat));
		this.fireEvent('change', this.selectedDate);
		
		return this;
	},
	
	//Extended format parser
	format: function(date, format) {
		if(!$defined(format)) format = this.options.format;
		if(!$defined(date)) return;
		format = format.replace(/%([a-z%])/gi,
			function($1, $2) {
				switch($2) {
					case 'D': return date.get('date');
					case 'n': return date.get('mo') + 1;
					case 't': return (date.getTime() / 1000).toInt();
				}
				return '%'+ $2;
			}
		);
		return date.format(format);
	},
	
	onKeyDown: function(e) {
		if(this.options.keyNavigation) {
			var newDate = this.selectedDate.clone();
			var right = true;
			var pressed = false;
			
			switch(e.code) {
				//Left
				case 37: newDate.decrement(); pressed = true; right = false; break;
				//Right
				case 39: newDate.increment(); pressed = true; break;
				//Up
				case 38: newDate.decrement('month'); pressed = true; right = false; break;
				//Down
				case 40: newDate.increment('month'); pressed = true; break;
			}
			
			if(pressed) {
				//Correct it
				newDate = this.correctDate(newDate, right);
				
				//If different, set it
				if(this.selectedDate.diff(newDate) != 0) this.setDate(newDate);
			}
		}
		if(this.options.disallowUserInput) return false;
	},
	
	//Checks if the date is an excluded date, excluded weekday or isn't within the range
	//If so it returns a correct pickable date
	correctDate: function(date, right) {
		if(!$defined(right)) right = true;
		
		//Check if the date is lower than the minimal date
		if($defined(this.options.minDate) && date.diff(this.options.minDate) > 0) date = this.options.minDate.clone();
		//Check if the date is higher than the maximum date
		else if($defined(this.options.maxDate) && date.diff(this.options.maxDate) < 0) date = this.options.maxDate.clone();
		
		//Check if the currect picked weekday is allowed
		var i = 0;
		while( ($defined(this.options.excludedWeekdays) && this.options.excludedWeekdays.contains(date.format('%w').toInt())) ||
			   ( ($defined(this.options.minDate) && date.diff(this.options.minDate) > 0) ||
				 ($defined(this.options.maxDate) && date.diff(this.options.maxDate) < 0) ) ||
			   ($defined(this.options.excludedDates) && this.options.excludedDates.contains(this.format(date, '%t'))) ) {
			if(i == 31) right = !right; //Reverse
			else if(i == 62) {
				date = this.options.minDate.clone();
				break; //Stop a possible infinitive loop
			}
			
			if(right) date.increment();
			else date.decrement();
			i++;
		}
		
		return date;
	},
	
	setDate: function(value, pick) {
		if(!$defined(pick)) pick = true;
		
		if($type(value) == 'date') {
			var date = value.clearTime();
		} else {
			var date = $chk(value) ? new Date().parse(this.target.get('value')).clearTime() : new Date().clearTime();
		}
		
		if(date.isValid()) {
			this.selectedDate = this.correctDate(date);
			this.viewDate = this.selectedDate.clone().set('date', 1);
			this.render();
			if(pick) this.pick();
		}
		
		return this;
	},
	
	getDate: function() {
		return this.selectedDate;
	}
});
