/*
ModalBox - The pop-up window thingie with AJAX, based on prototype and script.aculo.us.

Copyright Andrey Okonetchnikov (andrej.okonetschnikow@gmail.com), 2006-2007
All rights reserved.
 
VERSION 1.6.0
Last Modified: 12/13/2007
*/

if (!window.Modalbox)
	var Modalbox = new Object();

Modalbox.Methods = {
	overrideAlert: false, // Override standard browser alert message with ModalBox
	focusableElements: new Array,
	currFocused: 0,
	initialized: false,
	active: true,
	options: {
		title: "ModalBox Window", // Title of the ModalBox window
		overlayClose: true, // Close modal box by clicking on overlay
		width: 500, // Default width in px
		height: 90, // Default height in px
		overlayOpacity: .65, // Default overlay opacity
		overlayDuration: .25, // Default overlay fade in/out duration in seconds
		slideDownDuration: .5, // Default Modalbox appear slide down effect in seconds
		slideUpDuration: .5, // Default Modalbox hiding slide up effect in seconds
		resizeDuration: .25, // Default resize duration seconds
		inactiveFade: true, // Fades MB window on inactive state
		transitions: true, // Toggles transition effects. Transitions are enabled by default
		loadingString: "Please wait. Loading...", // Default loading string message
		closeString: "Close window", // Default title attribute for close window link
		closeValue: "&times;", // Default string for close link in the header
		params: {},
		method: 'get', // Default Ajax request method
		autoFocusing: true, // Toggles auto-focusing for form elements. Disable for long text pages.
		aspnet: false // Should be use then using with ASP.NET costrols. Then true Modalbox window will be injected into the first form element.
	},
	_options: new Object,
	
	setOptions: function(options) {
		Object.extend(this.options, options || {});
	},
	
	_init: function(options) {
		// Setting up original options with default options
		Object.extend(this._options, this.options);
		this.setOptions(options);
		
		//Create the overlay
		this.MBoverlay = new Element("div", { id: "MB_overlay", opacity: "0" });
		
		//Create DOm for the window
		this.MBwindow = new Element("div", {id: "MB_window", style: "display: none"}).update(
			this.MBframe = new Element("div", {id: "MB_frame"}).update(
				this.MBheader = new Element("div", {id: "MB_header"}).update(
					this.MBcaption = new Element("div", {id: "MB_caption"})
				)
			)
		);
		this.MBclose = new Element("a", {id: "MB_close", title: this.options.closeString, href: "#"}).update("<span>" + this.options.closeValue + "</span>");
		this.MBheader.insert({'bottom':this.MBclose});
		
		this.MBcontent = new Element("div", {id: "MB_content"}).update(
			this.MBloading = new Element("div", {id: "MB_loading"}).update(this.options.loadingString)
		);
		this.MBframe.insert({'bottom':this.MBcontent});
		
		// Inserting into DOM. If parameter set and form element have been found will inject into it. Otherwise will inject into body as topmost element.
		// Be sure to set padding and marging to null via CSS for both body and (in case of asp.net) form elements. 
		var injectToEl = this.options.aspnet ? $(document.body).down('form') : $(document.body);
		injectToEl.insert({'top':this.MBwindow});
		injectToEl.insert({'top':this.MBoverlay});
		
		// Initial scrolling position of the window. To be used for remove scrolling effect during ModalBox appearing
		this.initScrollX = window.pageXOffset || document.body.scrollLeft || document.documentElement.scrollLeft;
		this.initScrollY = window.pageYOffset || document.body.scrollTop || document.documentElement.scrollTop;
		
		//Adding event observers
		this.hideObserver = this._hide.bindAsEventListener(this);
		this.kbdObserver = this._kbdHandler.bindAsEventListener(this);
		this._initObservers();

		this.initialized = true; // Mark as initialized
	},
	
	show: function(content, options) {
		if(!this.initialized) this._init(options); // Check for is already initialized
		
		this.content = content;
		this.setOptions(options);
		
		if(this.options.title) // Updating title of the MB
			$(this.MBcaption).update(this.options.title);
		else { // If title isn't given, the header will not displayed
			$(this.MBheader).hide();
			$(this.MBcaption).hide();
		}
		
		if(this.MBwindow.style.display == "none") { // First modal box appearing
			this._appear();
			this.event("onShow"); // Passing onShow callback
		}
		else { // If MB already on the screen, update it
			this._update();
			this.event("onUpdate"); // Passing onUpdate callback
		} 
	},
	
	hide: function(options) { // External hide method to use from external HTML and JS
		if(this.initialized) {
			// Reading for options/callbacks except if event given as a pararmeter
			if(options && typeof options.element != 'function') Object.extend(this.options, options); 
			// Passing beforeHide callback
			this.event("beforeHide");
			if(this.options.transitions)
				Effect.SlideUp(this.MBwindow, { duration: this.options.slideUpDuration, transition: Effect.Transitions.sinoidal, afterFinish: this._deinit.bind(this) } );
			else {
				$(this.MBwindow).hide();
				this._deinit();
			}
		} else throw("Modalbox is not initialized.");
	},
	
	_hide: function(event) { // Internal hide method to use with overlay and close link
		event.stop(); // Stop event propaganation for link elements
		/* Then clicked on overlay we'll check the option and in case of overlayClose == false we'll break hiding execution [Fix for #139] */
		if(event.element().id == 'MB_overlay' && !this.options.overlayClose) return false;
		this.hide();
	},
	
	alert: function(message){
		var html = '<div class="MB_alert"><p>' + message + '</p><input type="button" onclick="Modalbox.hide()" value="OK" /></div>';
		Modalbox.show(html, {title: 'Alert: ' + document.title, width: 300});
	},
		
	_appear: function() { // First appearing of MB
		if(Prototype.Browser.IE && !navigator.appVersion.match(/\b7.0\b/)) { // Preparing IE 6 for showing modalbox
			window.scrollTo(0,0);
			this._prepareIE("100%", "hidden"); 
		}
		this._setWidth();
		this._setPosition();
		if(this.options.transitions) {
			$(this.MBoverlay).setStyle({opacity: 0});
			new Effect.Fade(this.MBoverlay, {
					from: 0, 
					to: this.options.overlayOpacity, 
					duration: this.options.overlayDuration, 
					afterFinish: function() {
						new Effect.SlideDown(this.MBwindow, {
							duration: this.options.slideDownDuration, 
							transition: Effect.Transitions.sinoidal, 
							afterFinish: function(){ 
								this._setPosition(); 
								this.loadContent();
							}.bind(this)
						});
					}.bind(this)
			});
		} else {
			$(this.MBoverlay).setStyle({opacity: this.options.overlayOpacity});
			$(this.MBwindow).show();
			this._setPosition(); 
			this.loadContent();
		}
		this._setWidthAndPosition = this._setWidthAndPosition.bindAsEventListener(this);
		Event.observe(window, "resize", this._setWidthAndPosition);
	},
	
	resize: function(byWidth, byHeight, options) { // Change size of MB without loading content
		var wHeight = $(this.MBwindow).getHeight();
		var wWidth = $(this.MBwindow).getWidth();
		var hHeight = $(this.MBheader).getHeight();
		var cHeight = $(this.MBcontent).getHeight();
		var newHeight = ((wHeight - hHeight + byHeight) < cHeight) ? (cHeight + hHeight - wHeight) : byHeight;
		if(options) this.setOptions(options); // Passing callbacks
		if(this.options.transitions) {
			new Effect.ScaleBy(this.MBwindow, byWidth, newHeight, {
					duration: this.options.resizeDuration, 
				  	afterFinish: function() { 
						this.event("_afterResize"); // Passing internal callback
						this.event("afterResize"); // Passing callback
					}.bind(this)
				});
		} else {
			this.MBwindow.setStyle({width: wWidth + byWidth + "px", height: wHeight + newHeight + "px"});
			setTimeout(function() {
				this.event("_afterResize"); // Passing internal callback
				this.event("afterResize"); // Passing callback
			}.bind(this), 1);
			
		}
		
	},
	
	resizeToContent: function(options){
		
		// Resizes the modalbox window to the actual content height.
		// This might be useful to resize modalbox after some content modifications which were changed ccontent height.
		
		var byHeight = this.options.height - this.MBwindow.offsetHeight;
		if(byHeight != 0) {
			if(options) this.setOptions(options); // Passing callbacks
			Modalbox.resize(0, byHeight);
		}
	},
	
	resizeToInclude: function(element, options){
		
		// Resizes the modalbox window to the camulative height of element. Calculations are using CSS properties for margins and border.
		// This method might be useful to resize modalbox before including or updating content.
		
		var el = $(element);
		var elHeight = el.getHeight() + parseInt(el.getStyle('margin-top')) + parseInt(el.getStyle('margin-bottom')) + parseInt(el.getStyle('border-top-width')) + parseInt(el.getStyle('border-bottom-width'));
		if(elHeight > 0) {
			if(options) this.setOptions(options); // Passing callbacks
			Modalbox.resize(0, elHeight);
		}
	},
	
	_update: function() { // Updating MB in case of wizards
		$(this.MBcontent).update("");
		this.MBcontent.appendChild(this.MBloading);
		$(this.MBloading).update(this.options.loadingString);
		this.currentDims = [this.MBwindow.offsetWidth, this.MBwindow.offsetHeight];
		Modalbox.resize((this.options.width - this.currentDims[0]), (this.options.height - this.currentDims[1]), {_afterResize: this._loadAfterResize.bind(this) });
	},
	
	loadContent: function () {
		if(this.event("beforeLoad") != false) { // If callback passed false, skip loading of the content
			if(typeof this.content == 'string') {
				var htmlRegExp = new RegExp(/<\/?[^>]+>/gi);
				if(htmlRegExp.test(this.content)) { // Plain HTML given as a parameter
					this._insertContent(this.content.stripScripts());
					this._putContent(function(){
						this.content.extractScripts().map(function(script) { 
							return eval(script.replace("<!--", "").replace("// -->", ""));
						}.bind(window));
					}.bind(this));
				} else // URL given as a parameter. We'll request it via Ajax
					new Ajax.Request( this.content, { method: this.options.method.toLowerCase(), parameters: this.options.params, 
						onSuccess: function(transport) {
							var response = new String(transport.responseText);
							this._insertContent(transport.responseText.stripScripts());
							this._putContent(function(){
								response.extractScripts().map(function(script) { 
									return eval(script.replace("<!--", "").replace("// -->", ""));
								}.bind(window));
							});
						}.bind(this),
						onException: function(instance, exception){
							Modalbox.hide();
							throw('Modalbox Loading Error: ' + exception);
						}
					});
					
			} else if (typeof this.content == 'object') {// HTML Object is given
				this._insertContent(this.content);
				this._putContent();
			} else {
				Modalbox.hide();
				throw('Modalbox Parameters Error: Please specify correct URL or HTML element (plain HTML or object)');
			}
		}
	},
	
	_insertContent: function(content){
		$(this.MBcontent).hide().update("");
		if(typeof content == 'string') {
			setTimeout(function() { // Hack to disable content flickering in Firefox
				this.MBcontent.update(content);
			}.bind(this), 1);
		} else if (typeof content == 'object') { // HTML Object is given
			var _htmlObj = content.cloneNode(true); // If node already a part of DOM we'll clone it
			// If clonable element has ID attribute defined, modifying it to prevent duplicates
			if(content.id) content.id = "MB_" + content.id;
			/* Add prefix for IDs on all elements inside the DOM node */
			$(content).select('*[id]').each(function(el){ el.id = "MB_" + el.id; });
			this.MBcontent.appendChild(_htmlObj);
			this.MBcontent.down().show(); // Toggle visibility for hidden nodes
			if(Prototype.Browser.IE) // Toggling back visibility for hidden selects in IE
				$$("#MB_content select").invoke('setStyle', {'visibility': ''});
		}
	},
	
	_putContent: function(callback){
		// Prepare and resize modal box for content
		if(this.options.height == this._options.height) {
			setTimeout(function() { // MSIE sometimes doesn't display content correctly
				Modalbox.resize(0, $(this.MBcontent).getHeight() - $(this.MBwindow).getHeight() + $(this.MBheader).getHeight(), {
					afterResize: function(){
						this.MBcontent.show().makePositioned();
						this.focusableElements = this._findFocusableElements();
						this._setFocus(); // Setting focus on first 'focusable' element in content (input, select, textarea, link or button)
						setTimeout(function(){ // MSIE fix
							if(callback != undefined)
								callback(); // Executing internal JS from loaded content
							this.event("afterLoad"); // Passing callback
						}.bind(this),1);
					}.bind(this)
				});
			}.bind(this), 1);
		} else { // Height is defined. Creating a scrollable window
			this._setWidth();
			this.MBcontent.setStyle({overflow: 'auto', height: $(this.MBwindow).getHeight() - $(this.MBheader).getHeight() - 13 + 'px'});
			this.MBcontent.show();
			this.focusableElements = this._findFocusableElements();
			this._setFocus(); // Setting focus on first 'focusable' element in content (input, select, textarea, link or button)
			setTimeout(function(){ // MSIE fix
				if(callback != undefined)
					callback(); // Executing internal JS from loaded content
				this.event("afterLoad"); // Passing callback
			}.bind(this),1);
		}
	},
	
	activate: function(options){
		this.setOptions(options);
		this.active = true;
		$(this.MBclose).observe("click", this.hideObserver);
		if(this.options.overlayClose)
			$(this.MBoverlay).observe("click", this.hideObserver);
		$(this.MBclose).show();
		if(this.options.transitions && this.options.inactiveFade)
			new Effect.Appear(this.MBwindow, {duration: this.options.slideUpDuration});
	},
	
	deactivate: function(options) {
		this.setOptions(options);
		this.active = false;
		$(this.MBclose).stopObserving("click", this.hideObserver);
		if(this.options.overlayClose)
			$(this.MBoverlay).stopObserving("click", this.hideObserver);
		$(this.MBclose).hide();
		if(this.options.transitions && this.options.inactiveFade)
			new Effect.Fade(this.MBwindow, {duration: this.options.slideUpDuration, to: .75});
	},
	
	_initObservers: function(){
		$(this.MBclose).observe("click", this.hideObserver);
		if(this.options.overlayClose)
			$(this.MBoverlay).observe("click", this.hideObserver);
		if(Prototype.Browser.IE)
			Event.observe(document, "keydown", this.kbdObserver);
		else
			Event.observe(document, "keypress", this.kbdObserver);
	},
	
	_removeObservers: function(){
		$(this.MBclose).stopObserving("click", this.hideObserver);
		if(this.options.overlayClose)
			$(this.MBoverlay).stopObserving("click", this.hideObserver);
		if(Prototype.Browser.IE)
			Event.stopObserving(document, "keydown", this.kbdObserver);
		else
			Event.stopObserving(document, "keypress", this.kbdObserver);
	},
	
	_loadAfterResize: function() {
		this._setWidth();
		this._setPosition();
		this.loadContent();
	},
	
	_setFocus: function() { 
		/* Setting focus to the first 'focusable' element which is one with tabindex = 1 or the first in the form loaded. */
		if(this.focusableElements.length > 0 && this.options.autoFocusing == true) {
			var firstEl = this.focusableElements.find(function (el){
				return el.tabIndex == 1;
			}) || this.focusableElements.first();
			this.currFocused = this.focusableElements.toArray().indexOf(firstEl);
			firstEl.focus(); // Focus on first focusable element except close button
		} else if($(this.MBclose).visible())
			$(this.MBclose).focus(); // If no focusable elements exist focus on close button
	},
	
	_findFocusableElements: function(){ // Collect form elements or links from MB content
		this.MBcontent.select('input:not([type~=hidden]), select, textarea, button, a[href]').invoke('addClassName', 'MB_focusable');
		return this.MBcontent.select('.MB_focusable');
	},
	
	_kbdHandler: function(event) {
		var node = event.element();
		switch(event.keyCode) {
			case Event.KEY_TAB:
				event.stop();
				
				/* Switching currFocused to the element which was focused by mouse instead of TAB-key. Fix for #134 */ 
				if(node != this.focusableElements[this.currFocused])
					this.currFocused = this.focusableElements.toArray().indexOf(node);
				
				if(!event.shiftKey) { //Focusing in direct order
					if(this.currFocused == this.focusableElements.length - 1) {
						this.focusableElements.first().focus();
						this.currFocused = 0;
					} else {
						this.currFocused++;
						this.focusableElements[this.currFocused].focus();
					}
				} else { // Shift key is pressed. Focusing in reverse order
					if(this.currFocused == 0) {
						this.focusableElements.last().focus();
						this.currFocused = this.focusableElements.length - 1;
					} else {
						this.currFocused--;
						this.focusableElements[this.currFocused].focus();
					}
				}
				break;			
			case Event.KEY_ESC:
				if(this.active) this._hide(event);
				break;
			case 32:
				this._preventScroll(event);
				break;
			case 0: // For Gecko browsers compatibility
				if(event.which == 32) this._preventScroll(event);
				break;
			case Event.KEY_UP:
			case Event.KEY_DOWN:
			case Event.KEY_PAGEDOWN:
			case Event.KEY_PAGEUP:
			case Event.KEY_HOME:
			case Event.KEY_END:
				// Safari operates in slightly different way. This realization is still buggy in Safari.
				if(Prototype.Browser.WebKit && !["textarea", "select"].include(node.tagName.toLowerCase()))
					event.stop();
				else if( (node.tagName.toLowerCase() == "input" && ["submit", "button"].include(node.type)) || (node.tagName.toLowerCase() == "a") )
					event.stop();
				break;
		}
	},
	
	_preventScroll: function(event) { // Disabling scrolling by "space" key
		if(!["input", "textarea", "select", "button"].include(event.element().tagName.toLowerCase())) 
			event.stop();
	},
	
	_deinit: function()
	{	
		this._removeObservers();
		Event.stopObserving(window, "resize", this._setWidthAndPosition );
		if(this.options.transitions) {
			Effect.toggle(this.MBoverlay, 'appear', {duration: this.options.overlayDuration, afterFinish: this._removeElements.bind(this) });
		} else {
			this.MBoverlay.hide();
			this._removeElements();
		}
		$(this.MBcontent).setStyle({overflow: '', height: ''});
	},
	
	_removeElements: function () {
		$(this.MBoverlay).remove();
		$(this.MBwindow).remove();
		if(Prototype.Browser.IE && !navigator.appVersion.match(/\b7.0\b/)) {
			this._prepareIE("", ""); // If set to auto MSIE will show horizontal scrolling
			window.scrollTo(this.initScrollX, this.initScrollY);
		}
		
		/* Replacing prefixes 'MB_' in IDs for the original content */
		if(typeof this.content == 'object') {
			if(this.content.id && this.content.id.match(/MB_/)) {
				this.content.id = this.content.id.replace(/MB_/, "");
			}
			this.content.select('*[id]').each(function(el){ el.id = el.id.replace(/MB_/, ""); });
		}
		/* Initialized will be set to false */
		this.initialized = false;
		this.event("afterHide"); // Passing afterHide callback
		this.setOptions(this._options); //Settings options object into intial state
	},
	
	_setWidth: function () { //Set size
		$(this.MBwindow).setStyle({width: this.options.width + "px", height: this.options.height + "px"});
	},
	
	_setPosition: function () {
		$(this.MBwindow).setStyle({left: Math.round((Element.getWidth(document.body) - Element.getWidth(this.MBwindow)) / 2 ) + "px"});
	},
	
	_setWidthAndPosition: function () {
		$(this.MBwindow).setStyle({width: this.options.width + "px"});
		this._setPosition();
	},
	
	_getScrollTop: function () { //From: http://www.quirksmode.org/js/doctypes.html
		var theTop;
		if (document.documentElement && document.documentElement.scrollTop)
			theTop = document.documentElement.scrollTop;
		else if (document.body)
			theTop = document.body.scrollTop;
		return theTop;
	},
	_prepareIE: function(height, overflow){
		$$('html, body').invoke('setStyle', {width: height, height: height, overflow: overflow}); // IE requires width and height set to 100% and overflow hidden
		$$("select").invoke('setStyle', {'visibility': overflow}); // Toggle visibility for all selects in the common document
	},
	event: function(eventName) {
		if(this.options[eventName]) {
			var returnValue = this.options[eventName](); // Executing callback
			this.options[eventName] = null; // Removing callback after execution
			if(returnValue != undefined) 
				return returnValue;
			else 
				return true;
		}
		return true;
	}
};

Object.extend(Modalbox, Modalbox.Methods);

if(Modalbox.overrideAlert) window.alert = Modalbox.alert;

Effect.ScaleBy = Class.create();
Object.extend(Object.extend(Effect.ScaleBy.prototype, Effect.Base.prototype), {
  initialize: function(element, byWidth, byHeight, options) {
    this.element = $(element)
    var options = Object.extend({
	  scaleFromTop: true,
      scaleMode: 'box',        // 'box' or 'contents' or {} with provided values
      scaleByWidth: byWidth,
	  scaleByHeight: byHeight
    }, arguments[3] || {});
    this.start(options);
  },
  setup: function() {
    this.elementPositioning = this.element.getStyle('position');
      
    this.originalTop  = this.element.offsetTop;
    this.originalLeft = this.element.offsetLeft;
	
    this.dims = null;
    if(this.options.scaleMode=='box')
      this.dims = [this.element.offsetHeight, this.element.offsetWidth];
	 if(/^content/.test(this.options.scaleMode))
      this.dims = [this.element.scrollHeight, this.element.scrollWidth];
    if(!this.dims)
      this.dims = [this.options.scaleMode.originalHeight,
                   this.options.scaleMode.originalWidth];
	  
	this.deltaY = this.options.scaleByHeight;
	this.deltaX = this.options.scaleByWidth;
  },
  update: function(position) {
    var currentHeight = this.dims[0] + (this.deltaY * position);
	var currentWidth = this.dims[1] + (this.deltaX * position);
	
	currentHeight = (currentHeight > 0) ? currentHeight : 0;
	currentWidth = (currentWidth > 0) ? currentWidth : 0;
	
    this.setDimensions(currentHeight, currentWidth);
  },

  setDimensions: function(height, width) {
    var d = {};
    d.width = width + 'px';
    d.height = height + 'px';
    
	var topd  = Math.round((height - this.dims[0])/2);
	var leftd = Math.round((width  - this.dims[1])/2);
	if(this.elementPositioning == 'absolute' || this.elementPositioning == 'fixed') {
		if(!this.options.scaleFromTop) d.top = this.originalTop-topd + 'px';
		d.left = this.originalLeft-leftd + 'px';
	} else {
		if(!this.options.scaleFromTop) d.top = -topd + 'px';
		d.left = -leftd + 'px';
	}
    this.element.setStyle(d);
  }
});

//autocomplete

var AutoComplete = Class.create({

	/**

	 * The select object

	 * @type {HTMLSelectElement}

	 */

	selector: null,

	/**

	 * The component that triggers the suggest

	 * @type {HTMLInputElement}

	 */

	input: null,

	/**

	 * The timeout between lookups

	 * @type {Number}

	 * @private

	 */

	_timeout: null,

	/**

	 * Visisbility status of the selector object

	 * @type {Boolean}

	 */

	visible: false,

	/**

	 * Flag indicating whether the components have been laid out

	 * @type {Boolean}

	 */

	drawn: false,



	/**

	 * Hide timeout

	 * @type {Number}

	 * @private

	 */

	_hideTimeout: null,



	/**

	 * The configuration options for the instance

	 * @type {AutoComplete.Options}

	 */

	options: null,



	/**

	 * @param {Object} input ID of form element, or dom element,  to _suggest on

	 * @param {String} URL of dictionary

	 * @param {Object} options

	 */

	initialize: function(input, action, options)

	{

		this.action = action;

		this.input = $(input);

		this.input.autocomplete = "off";

		this.options = new AutoComplete.Options(options || {});



		if(!this.input)

			alert('No input field/binding field given or found')



		if(!this.action)

			alert('No action url specified');



		this.selector = document.createElement('select');



		Event.observe(this.input, 'focus', this._onInputFocus.bindAsEventListener(this));

		//Event.observe(this.input, 'keyup', this._onInputKeyUp.bindAsEventListener(this));

		Event.observe(this.input, 'keydown', this._onInputKeyDown.bindAsEventListener(this));

		Event.observe(this.input, 'blur', this._onInputBlur.bindAsEventListener(this));

		Event.observe(this.selector, 'blur', this._onSelectorBlur.bindAsEventListener(this));

		Event.observe(this.selector, 'focus', this._onSelectorFocus.bindAsEventListener(this));

		Event.observe(this.selector, 'change', this._onSelectorChange.bindAsEventListener(this));



		Event.observe(window, 'resize', this._reposition.bind(this));

		Event.observe(window, 'scroll', this._reposition.bind(this));

	},



	/**

	 * The input fields focus event handler

	 */

	_onInputFocus: function(event)

	{

		this._onSelectorFocus(event);

	},



	/**

	 * The selector's blur event handler

	 * @param {Event} event

	 * @private

	 */

	_onSelectorBlur: function(event)

	{

		this._onInputBlur(event);

	},

	/**

	 * The input's blur event handler

	 * @param {Event} event

	 * @private

	 */

	_onInputBlur: function(event)

	{

		this._hideTimeout = setTimeout(this._checkOnBlur.bind(this), 100);

	},

	/**

	 * Complete's the blur event handlers. Used as a proxy to avoid event collisions when blurring from the input

	 * and focusing on the selector during a mouse navigation

	 * @private

	 */

	_checkOnBlur:function()

	{

		this._hideTimeout = null

		this.hide();

	},

	/**

	 * The input's key-up event handler

	 * @param {Event} event

	 * @private

	 */

	_onInputKeyUp: function(event)

	{

		this._suggest(event)

			&& Event.stop(event);

	},

	/**

	 * The input's key-down event handler

	 * @param {Event} event

	 * @private

	 */

	_onInputKeyDown: function(event)

	{

		this._suggest(event)

			&& Event.stop(event);

	},

	/**

	 * The selectors's focus event handler.

	 * @param {Event} event

	 * @private

	 */

	_onSelectorFocus: function(event)

	{

		if(this._hideTimeout)

		{

			clearTimeout(this._hideTimeout);

			this._hideTimeout = null;

		}

	},

	/**

	 * The selector's change event handler

	 * @param {Event} event

	 * @private

	 */

	_onSelectorChange: function(event)

	{

		this.select();

	},

	/**

	 * Lays the UI elements of the control out, sets interaction options

	 * @param {Object} event Event

	 */

	draw: function()

	{

		if(this.drawn) return;

		if(this.options.cssClass)

			this.selector.className = this.options.cssClass;

		Element.setStyle(this.selector, {

			display: 'none',

			position: 'absolute',

			width: this.input.offsetWidth + 'px'

		});

		this.selector.size = this.options.size;

		document.body.appendChild(this.selector);

		this.input.autocomplete = 'off';

		this.drawn = true;

	},



	/**

	 * Hides the option box

	 */

	hide: function()

	{

		if(!this.drawn || !this.visible) return;

		this.visible = false;

		if(window.Scriptaculous)

		{

			new Effect.BlindUp(this.selector, {

				duration: this.options.delay,

				queue: 'end',

				afterFinish: function(event){

					Element.setStyle(this.selector,{

						display: 'none'

					});

					this.selector.options.length = 0;

					setTimeout(this._restoreFocus.bind(this),50);

				}.bind(this)

			});

		}

		else

		{

			Element.setStyle(this.selector,{

				display: 'none'

			});

			this.selector.options.length = 0;

			// FF hack, wasn't selecting without this small delay for some reason

			setTimeout(this._restoreFocus.bind(this),50);

		}

	},

	/**

	 * Resores the focus to the input control to avoid the cursor getting lost somewhere.

	 * @private

	 */

	_restoreFocus: function() {

		this.input.focus();

	},

	/**

	 * Displays the select box

	 */

	show: function()

	{

		if(!this.drawn) this.draw();

		var trigger = null;

		if(this.selector.options.length)

		{

			if(window.Scriptaculous)

			{

				new Effect.BlindDown(this.selector,{

					duration: this.options.delay,

					queue: 'end'

				});

			}

			else

			{

				Element.setStyle(this.selector,{

					display: 'inline'

				});

			}

			this._reposition();

			this.visible = true;

		}

	},



	/**

	 * Removes the timeout function set by a suggest

	 * @private

	 */

	_cancelTimeout: function()

	{

		if(this._timeout)

		{

			clearTimeout(this._timeout);

			this._timeout = null;

		}

	},



	/**

	 * Triggers the suggest interaction

	 * @param {Object} event The interaction event (keyboard or mouse)

	 * @return {Boolean} Whether to stop the event

	 * @private

	 */

	_suggest: function(event)

	{

		this._cancelTimeout();

		var key = Event.keyPressed(event);

		var ignoreKeys = [

			20, // caps lock

			16, // shift

			17, // ctrl

			91, // Windows key

			121, // F1 - F12

			122,

			123,

			124,

			125,

			126,

			127,

			128,

			129,

			130,

			131,

			132,

			45, // Insert

			36, // Home

			35, // End

			33, // Page Up

			34, // Page Down

			144, // Num Lock

			145, // Scroll Lock

			44, // Print Screen

			19, // Pause

			93, // Mouse menu key

		];

		if(ignoreKeys.indexOf(key) > -1)

			return false;



		switch(key)

		{

			case Event.KEY_LEFT:

			case Event.KEY_RIGHT:

				return false;

				break;

			case Event.KEY_TAB:

			case Event.KEY_BACKSPACE:

			case 46: //Delete

				this.cancel();

				return false;

				break;

			case Event.KEY_RETURN:

				if(this.visible)

				{

					this.select();

					return true;

				}

				return false;

				break;

			case Event.KEY_ESC:

				this.cancel();

				return true;

				break;

			case Event.KEY_UP:

			case Event.KEY_DOWN:

				this._interact(event);

				return true;

				break;

			default:

				break;

		}



		if(this.input.value.length >= this.options.threshold - 1)

		{

			this._timeout = setTimeout(this._sendRequest.bind(this), 1000 * this.options.delay);

		}

		return false;

	},



	/**

	 * Sends the suggestion request

	 * @private

	 */

	_sendRequest: function()

	{

		this._request = new Ajax.Request(this.action + this.input.value, {

			onComplete: this._process.bind(this),

			method: this.options.requestMethod

		});

	},



	/**

	 * Repositions the selector (if visible) to match the new

	 * coords of the input.

	 * @private

	 */

	_reposition: function()

	{

		if(!this.drawn) return;

		var pos = Position.cumulativeOffset(this.input);

		pos.push(pos[0] + this.input.offsetWidth);

		pos.push(pos[1] + this.input.offsetHeight);

		Element.setStyle(this.selector,{

			left: pos[0] + 'px',

			top: pos[3] + 'px'

		});

	},



	/**

	 * Processes the resulting  from a suggestion request, adds options to the suggestion box.

	 * @param {XMLHTTPRequest} objXML The XMLHTTPRequest created by _sendRequest

	 * @param {String} jsonHeader the string of json commands to execute if the return type is json

	 * @private

	 */

	_process: function(objXML, jsonHeader)

	{

		this.selector.options.length = 0;

		switch(this.options.resultFormat)

		{

			case AutoComplete.Options.RESULT_FORMAT_XML:

				this._parseXML(objXML.responseXML);

				break;

			case AutoComplete.Options.RESULT_FORMAT_JSON:

				if(!jsonHeader)

				{

					jsonHeader = objXML.responseText && objXML.responseText.isJSON() ?

						objXML.responseText.evalJSON() : null;

				}

				this._parseJSON(jsonHeader);

				break;

			case AutoComplete.Options.RESULT_FORMAT_TEXT:

				this._parseText(objXML.responseText);

				break;

			default:

				alert("Unable to parse result type. Make sure you've set the resultFormat option correctly");

				break;

		}



		if(this.selector.options.length > (this.options.size))

			this.selector.size = this.options.size;

		else

			this.selector.size = this.selector.options.length > 1 ? this.selector.options.length : 2;



		if(this.selector.options.length)

		{

			//none selected by default

			this.selector.selectedIndex = -1;

			this.show();

		}

		else

			this.cancel();

	},



	/**

	 * Parses the XML result, adds options

	 * @param {XML} xml the XML of suggestions to parse

	 */

	_parseXML: function(xml)

	{

		var suggestions = null;

		for(var i = 0; i < xml.childNodes.length; i++)

		{

			if(xml.childNodes[i].tagName)

			{

				suggestions = xml.childNodes[i].childNodes;

			}

		}

		if(!suggestions)

		{

			alert("Could not parse response XML.");

			return;

		}

		for(i = 0; i < suggestions.length; i++)

		{

			suggestion = suggestions.item(i).firstChild.nodeValue;

			this._addOption(suggestion);

		}

	},

	/**

	 * Parses the JSON result, adds options

	 * @param {String} json The json response to parse

	 */

	_parseJSON: function(json)

	{

		if(!json) json = [];

		for(i = 0; i < json.length; i++)

			this._addOption(json[i]);

	},

	/**

	 * Parses the TEXT result, adds options

	 * @param {String} text The text response to parse

	 */

	_parseText: function(text)

	{

		var suggestions = (text||"").split(/\n/);

		for(i = 0; i < suggestions.length; i++)

			this._addOption(suggestions[i]);

	},

	/**

	 * Creates a suggestion option for the given suggestion,

	 * adds it to the selector object.

	 * @param {String} suggestion The suggestion

	 */

	_addOption: function(suggestion)

	{

		var opt = new Option(suggestion, suggestion);

		Prototype.Browser.IE ? this.selector.add(opt) : this.selector.add(opt, null);

	},



	/**

	 * Clears and hides the suggestion box.

	 */

	cancel: function()

	{

		this.hide();

	},



	/**

	 * Captures the currently selected suggestion option to the input field

	 */

	select: function()

	{

		if(this.selector.options.length)

			this.input.value = this.selector.options[this.selector.selectedIndex].value;

		this.cancel();

		if(typeof this.options.onSelect == 'function')

		{

			this.options['onSelect'](this.input);

		}

	},



	/**

	 * Processes key interactions with the input field, including navigating the selected option

	 * with the up/down arrows, esc cancelling and selecting the option.

	 * @param {Event} event The interaction event

	 * @private

	 */

	_interact: function(event)

	{

		if(!this.visible) return;



		var key = Event.keyPressed(event);

		if(key != Event.KEY_UP && key != Event.KEY_DOWN) return;

		var mx = this.selector.options.length;



		if(key == Event.KEY_UP)

		{

			if(this.selector.selectedIndex == 0)

				this.selector.selectedIndex = this.selector.options.length - 1;

			else

				this.selector.selectedIndex--;

		}

		else

		{

			if(this.selector.selectedIndex == this.selector.options.length - 1)

				this.selector.selectedIndex = 0;

			else

				this.selector.selectedIndex++;

		}

	}

});



/**

 * Helper class for defining options for the AutoComplete object

 * @version 1.2

 * @requires prototype.js <http://www.prototypejs.org/>

 * @author Beau D. Scott <beau_scott@hotmail.com>

 * 6/5/2008

 */

AutoComplete.Options = Class.create({

	/**

	 * Number of options to display before scrolling

	 * @type {Number}

	 */

	size: 10,

	/**

	 * CSS class name for autocomplete selector

	 * @type {String}

	 */

	cssClass: null,

	/**

	 * JavaScript callback function to execute upon selection

	 * @type {Function}

	 */

	onSelect: null,

	/**

	 * Minimum characters needed before an suggestion is executed

	 * @type {Number}

	 */

	threshold: 3,

	/**

	 * Time delay between key stroke and execution

	 * @type {Number}

	 */

	delay: .2,

	/**

	 * The request method to use when getting the suggestions

	 * @type {String}

	 */

	requestMethod: 'GET',

	/**

	 * The format of the results retrieved (xml, text or json)

	 * @type {String}

	 */

	resultFormat: 'xml',

	/**

	 * Constructor

	 * @type {Object} overrides Overriding properties

	 */

	initialize: function(overrides)

	{

		Object.extend(this, overrides || {});

	}

});

Object.extend(AutoComplete.Options, {

	/**

	 * Enumeration for XML result format

	 * Be sure your response type is application/xml or text/xml

	 * @static

	 */

	RESULT_FORMAT_XML: 'xml',

	/**

	 * Enumeration for JSon result format

	 * @static

	 */

	RESULT_FORMAT_JSON: 'json',

	/**

	 * Enumeration for text result format

	 * @static

	 */

	RESULT_FORMAT_TEXT: 'text'

});



//

// Various Prototype Event extensions

//

Object.extend(Event, {

	/**

	 * Enumeration for the backspace key code

	 * @type {Number}

	 * @static

	 */

	KEY_BACKSPACE: 8,

	/**

	 * Enumeration for the tab key code

	 * @static

	 */

	KEY_TAB:       9,

	/**

	 * Enumeration for the return/enter key code

	 * @static

	 */

	KEY_RETURN:   13,

	/**

	 * Enumeration for the escape key code

	 * @static

	 */

	KEY_ESC:      27,

	/**

	 * Enumeration for the left arrow key code

	 * @static

	 */

	KEY_LEFT:     37,

	/**

	 * Enumeration for the up arrow key code

	 * @static

	 */

	KEY_UP:       38,

	/**

	 * Enumeration for the right arrow key code

	 * @static

	 */

	KEY_RIGHT:    39,

	/**

	 * Enumeration for the down arrow key code

	 * @static

	 */

	KEY_DOWN:     40,

	/**

	 * Enumeration for the delete key code

	 * @static

	 */

	KEY_DELETE:   46,

	/**

	 * Enumeration for the shift key code

	 * @static

	 */

	KEY_SHIFT:    16,

	/**

	 * Enumeration for the cotnrol key code

	 * @static

	 */

	KEY_CONTROL:  17,

	/**

	 * Enumeration for the capslock key code

	 * @static

	 */

	KEY_CAPSLOCK: 20,

	/**

	 * Enumeration for the space key code

	 * @static

	 */

	KEY_SPACE:	  32,



	/**

	 * A simple interface to get the key code of the key pressed based, browser sensitive.

	 * @param {Event} event They keyboard event

	 * @return {Number} the key code of the key pressed

	 */

	keyPressed: function(event)

	{

		return Prototype.Browser.IE ? window.event.keyCode : event.which;

	}

});

//validation

var Validator = Class.create();



Validator.prototype = {

	initialize : function(className, error, test, options) {

		if(typeof test == 'function'){

			this.options = $H(options);

			this._test = test;

		} else {

			this.options = $H(test);

			this._test = function(){return true};

		}

		this.error = error || 'Validation failed.';

		this.className = className;

	},

	test : function(v, elm) {

		return (this._test(v,elm) && this.options.all(function(p){

			return Validator.methods[p.key] ? Validator.methods[p.key](v,elm,p.value) : true;

		}));

	}

}

Validator.methods = {

	pattern : function(v,elm,opt) {return Validation.get('IsEmpty').test(v) || opt.test(v)},

	minLength : function(v,elm,opt) {return v.length >= opt},

	maxLength : function(v,elm,opt) {return v.length <= opt},

	min : function(v,elm,opt) {return v >= parseFloat(opt)}, 

	max : function(v,elm,opt) {return v <= parseFloat(opt)},

	notOneOf : function(v,elm,opt) {return $A(opt).all(function(value) {

		return v != value;

	})},

	oneOf : function(v,elm,opt) {return $A(opt).any(function(value) {

		return v == value;

	})},

	is : function(v,elm,opt) {return v == opt},

	isNot : function(v,elm,opt) {return v != opt},

	equalToField : function(v,elm,opt) {return v == $F(opt)},

	notEqualToField : function(v,elm,opt) {return v != $F(opt)},

	include : function(v,elm,opt) {return $A(opt).all(function(value) {

		return Validation.get(value).test(v,elm);

	})}

}



var Validation = Class.create();



Validation.prototype = {

	initialize : function(form, options){

		this.options = Object.extend({

			onSubmit : true,

			stopOnFirst : false,

			immediate : false,

			focusOnError : true,

			useTitles : false,

			onFormValidate : function(result, form) {},

			onElementValidate : function(result, elm) {}

		}, options || {});

		this.form = $(form);

		if(this.options.onSubmit) Event.observe(this.form,'submit',this.onSubmit.bind(this),false);

		if(this.options.immediate) {

			var useTitles = this.options.useTitles;

			var callback = this.options.onElementValidate;

			Form.getElements(this.form).each(function(input) { // Thanks Mike!

				Event.observe(input, 'blur', function(ev) { Validation.validate(Event.element(ev),{useTitle : useTitles, onElementValidate : callback}); });

			});

		}

	},

	onSubmit :  function(ev){

		if(!this.validate()) Event.stop(ev);

	},

	validate : function() {

		var result = false;

		var useTitles = this.options.useTitles;

		var callback = this.options.onElementValidate;

		if(this.options.stopOnFirst) {

			result = Form.getElements(this.form).all(function(elm) { return Validation.validate(elm,{useTitle : useTitles, onElementValidate : callback}); });

		} else {

			result = Form.getElements(this.form).collect(function(elm) { return Validation.validate(elm,{useTitle : useTitles, onElementValidate : callback}); }).all();

		}

		if(!result && this.options.focusOnError) {

			Form.getElements(this.form).findAll(function(elm){return $(elm).hasClassName('validation-failed')}).first().focus()

		}

		this.options.onFormValidate(result, this.form);

		return result;

	},

	reset : function() {

		Form.getElements(this.form).each(Validation.reset);

	}

}



Object.extend(Validation, {

	validate : function(elm, options){

		options = Object.extend({

			useTitle : false,

			onElementValidate : function(result, elm) {}

		}, options || {});

		elm = $(elm);

		var cn = elm.classNames();

		return result = cn.all(function(value) {

			var test = Validation.test(value,elm,options.useTitle);

			options.onElementValidate(test, elm);

			return test;

		});

	},

	test : function(name, elm, useTitle) {

		var v = Validation.get(name);

		var prop = '__advice'+name.camelize();

		try {

		if(Validation.isVisible(elm) && !v.test($F(elm), elm)) {

			if(!elm[prop]) {

				var advice = Validation.getAdvice(name, elm);

				if(advice == null) {

					var errorMsg = useTitle ? ((elm && elm.title) ? elm.title : v.error) : v.error;

					advice = '<div class="validation-advice" id="advice-' + name + '-' + Validation.getElmID(elm) +'" style="display:none">' + errorMsg + '</div>'

					switch (elm.type.toLowerCase()) {

						case 'checkbox':

						case 'radio':

							var p = elm.parentNode;

							if(p) {

								new Insertion.Bottom(p, advice);

							} else {

								new Insertion.After(elm, advice);

							}

							break;

						default:

							new Insertion.After(elm, advice);

				    }

					advice = Validation.getAdvice(name, elm);

				}

				if(typeof Effect == 'undefined') {

					advice.style.display = 'block';

				} else {

					new Effect.Appear(advice, {duration : 1 });

				}

			}

			elm[prop] = true;

			elm.removeClassName('validation-passed');

			elm.addClassName('validation-failed');

			return false;

		} else {

			var advice = Validation.getAdvice(name, elm);

			if(advice != null) advice.hide();

			elm[prop] = '';

			elm.removeClassName('validation-failed');

			elm.addClassName('validation-passed');

			return true;

		}

		} catch(e) {

			throw(e)

		}

	},

	isVisible : function(elm) {

		while(elm.tagName != 'BODY') {

			if(!$(elm).visible()) return false;

			elm = elm.parentNode;

		}

		return true;

	},

	getAdvice : function(name, elm) {

		return $('advice-' + name + '-' + Validation.getElmID(elm)) || $('advice-' + Validation.getElmID(elm));

	},

	getElmID : function(elm) {

		return elm.id ? elm.id : elm.name;

	},

	reset : function(elm) {

		elm = $(elm);

		var cn = elm.classNames();

		cn.each(function(value) {

			var prop = '__advice'+value.camelize();

			if(elm[prop]) {

				var advice = Validation.getAdvice(value, elm);

				advice.hide();

				elm[prop] = '';

			}

			elm.removeClassName('validation-failed');

			elm.removeClassName('validation-passed');

		});

	},

	add : function(className, error, test, options) {

		var nv = {};

		nv[className] = new Validator(className, error, test, options);

		Object.extend(Validation.methods, nv);

	},

	addAllThese : function(validators) {

		var nv = {};

		$A(validators).each(function(value) {

				nv[value[0]] = new Validator(value[0], value[1], value[2], (value.length > 3 ? value[3] : {}));

			});

		Object.extend(Validation.methods, nv);

	},

	get : function(name) {

		return  Validation.methods[name] ? Validation.methods[name] : Validation.methods['_LikeNoIDIEverSaw_'];

	},

	methods : {

		'_LikeNoIDIEverSaw_' : new Validator('_LikeNoIDIEverSaw_','',{})

	}

});



Validation.add('IsEmpty', '', function(v) {

				return  ((v == null) || (v.length == 0)); // || /^\s+$/.test(v));

			});



Validation.addAllThese([

	['required', 'This is a required field.', function(v) {

				return !Validation.get('IsEmpty').test(v);

			}],

	['validate-number', 'Please enter a valid number in this field.', function(v) {

				return Validation.get('IsEmpty').test(v) || (!isNaN(v) && !/^\s+$/.test(v));

			}],

	['validate-digits', 'Please use numbers only in this field. please avoid spaces or other characters such as dots or commas.', function(v) {

				return Validation.get('IsEmpty').test(v) ||  !/[^\d]/.test(v);

			}],

	['validate-alpha', 'Please use letters only (a-z) in this field.', function (v) {

				return Validation.get('IsEmpty').test(v) ||  /^[a-zA-Z]+$/.test(v)

			}],

	['validate-alphanum', 'Please use only letters (a-z) or numbers (0-9) only in this field. No spaces or other characters are allowed.', function(v) {

				return Validation.get('IsEmpty').test(v) ||  !/\W/.test(v)

			}],

	['validate-date', 'Please enter a valid date.', function(v) {

				var test = new Date(v);

				return Validation.get('IsEmpty').test(v) || !isNaN(test);

			}],

	['validate-email', 'Please enter a valid email address. For example fred@domain.com .', function (v) {

				return Validation.get('IsEmpty').test(v) || /\w{1,}[@][\w\-]{1,}([.]([\w\-]{1,})){1,3}$/.test(v)

			}],

	['validate-url', 'Please enter a valid URL.', function (v) {

				return Validation.get('IsEmpty').test(v) || /^(http|https|ftp):\/\/(([A-Z0-9][A-Z0-9_-]*)(\.[A-Z0-9][A-Z0-9_-]*)+)(:(\d+))?\/?/i.test(v)

			}],

	['validate-date-au', 'Please use this date format: dd/mm/yyyy. For example 17/03/2006 for the 17th of March, 2006.', function(v) {

				if(Validation.get('IsEmpty').test(v)) return true;

				var regex = /^(\d{2})\/(\d{2})\/(\d{4})$/;

				if(!regex.test(v)) return false;

				var d = new Date(v.replace(regex, '$2/$1/$3'));

				return ( parseInt(RegExp.$2, 10) == (1+d.getMonth()) ) && 

							(parseInt(RegExp.$1, 10) == d.getDate()) && 

							(parseInt(RegExp.$3, 10) == d.getFullYear() );

			}],

	['validate-currency-dollar', 'Please enter a valid $ amount. For example $100.00 .', function(v) {

				// [$]1[##][,###]+[.##]

				// [$]1###+[.##]

				// [$]0.##

				// [$].##

				return Validation.get('IsEmpty').test(v) ||  /^\$?\-?([1-9]{1}[0-9]{0,2}(\,[0-9]{3})*(\.[0-9]{0,2})?|[1-9]{1}\d*(\.[0-9]{0,2})?|0(\.[0-9]{0,2})?|(\.[0-9]{1,2})?)$/.test(v)

			}],

	['validate-selection', 'Please make a selection', function(v,elm){

				return elm.options ? elm.selectedIndex > 0 : !Validation.get('IsEmpty').test(v);

			}],

	['validate-one-required', 'Please select one of the above options.', function (v,elm) {

				var p = elm.parentNode;

				var options = p.getElementsByTagName('INPUT');

				return $A(options).any(function(elm) {

					return $F(elm);

				});

			}]

]);

//accordion

eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('g r=J.K();r.L={M:c(d,t,u){5.d=d;5.v=t.N();5.w=u;5.x=(y[3]||"O");5.m=(y[4]||"P");5.7=h Q();g 6=$(d).z(\'*\');n(g i=0;i<6.9;i++){R(6.8(i).S){T 5.v:6.8(i).o.U="V";6.8(i).W=5.A(5.w);B;X:a(6.8(i).p==5.x){6[i].C=5.D(5.7.9);5.7[5.7.9]=6.8(i);a(5.7.9==1){6.8(i).d="k"}}a(6.8(i).p==5.m){6.8(i).o.E="F"}B}}5.9=5.7.9;5.q(0,Y)},q:c(f,G){a((f>=5.9)||(f<0)){b}a($(\'k\')==5.7[f]){a(G){n(g i=0;i<5.9;i++){a(5.j(5.7[i]).o.E!="F"){h l.H(5.j(5.7[i]))}}h l.I(5.j(5.7[f]));b}b}h l.Z([h l.H(5.j($(\'k\'))),h l.I(5.j(5.7[f]))],{10:0.2});$(\'k\').d="";5.7[f].d="k";b},j:c(e){g 6=e.z(\'*\');n(g i=0;i<6.9;i++){a(6.8(i).p==5.m){b 6.8(i)}}},D:c(i){b c(){b i}},A:c(s){b c(){11(s+".q("+5.12.C()+");")}}};',62,65,'|||||this|tags|panels|item|length|if|return|function|id||index|var|new||_body|visible|Effect|contentClassName|for|style|className|show|Accordion||tag|name|headerTag|instance|headingClassName|arguments|getElementsByTagName|_returnEvalCode|break|_index|_returnIndex|display|none|force|SlideUp|SlideDown|Class|create|prototype|initialize|toUpperCase|panel|panelBody|Array|switch|tagName|case|cursor|pointer|onclick|default|true|Parallel|duration|eval|parentNode'.split('|'),0,{}))

//

function stopRKey(evt) {
  var evt = (evt) ? evt : ((event) ? event : null);
  var node = (evt.target) ? evt.target : ((evt.srcElement) ? evt.srcElement : null);
  if ((evt.keyCode == 13) && (node.type=="text"))  {return false;}
}

document.onkeypress = stopRKey;

function handleEnter (field, event) {
		var keyCode = event.keyCode ? event.keyCode : event.which ? event.which : event.charCode;
		if (keyCode == 13) {
			var i;
			for (i = 0; i < field.form.elements.length; i++)
				if (field == field.form.elements[i])
					break;
			i = (i + 1) % field.form.elements.length;
			field.form.elements[i].focus();
			return false;
		} 
		else
		return true;
	}      



	var arrayOfRolloverClasses = new Array();
	var arrayOfClickClasses = new Array();
	var activeRow = false;
	var activeRowClickArray = new Array();
	
	function highlightTableRow()
	{
		var tableObj = this.parentNode;
		if(tableObj.tagName!='TABLE')tableObj = tableObj.parentNode;

		if(this!=activeRow){
			this.setAttribute('origCl',this.className);
			this.origCl = this.className;
		}
		this.className = arrayOfRolloverClasses[tableObj.id];
		
		activeRow = this;
		
	}
	
	function clickOnTableRow()
	{
		var tableObj = this.parentNode;
		if(tableObj.tagName!='TABLE')tableObj = tableObj.parentNode;		
		
		if(activeRowClickArray[tableObj.id] && this!=activeRowClickArray[tableObj.id]){
			activeRowClickArray[tableObj.id].className='';
		}
		this.className = arrayOfClickClasses[tableObj.id];
		
		activeRowClickArray[tableObj.id] = this;
				
	}
	
	function resetRowStyle()
	{
		var tableObj = this.parentNode;
		if(tableObj.tagName!='TABLE')tableObj = tableObj.parentNode;

		if(activeRowClickArray[tableObj.id] && this==activeRowClickArray[tableObj.id]){
			this.className = arrayOfClickClasses[tableObj.id];
			return;	
		}
		
		var origCl = this.getAttribute('origCl');
		if(!origCl)origCl = this.origCl;
		this.className=origCl;
		
	}
		
	function addTableRolloverEffect(tableId,whichClass,whichClassOnClick)
	{
		arrayOfRolloverClasses[tableId] = whichClass;
		arrayOfClickClasses[tableId] = whichClassOnClick;
		
		var tableObj = document.getElementById(tableId);
		var tBody = tableObj.getElementsByTagName('TBODY');
		if(tBody){
			var rows = tBody[0].getElementsByTagName('TR');
		}else{
			var rows = tableObj.getElementsByTagName('TR');
		}
		for(var no=0;no<rows.length;no++){
			rows[no].onmouseover = highlightTableRow;
			rows[no].onmouseout = resetRowStyle;
			
			if(whichClassOnClick){
				rows[no].onclick = clickOnTableRow;	
			}
		}
		
	}


function ajaxupdate(myid,url){
$(myid).innerHTML = '<br clear=all><center><img align="center" src="../js/Loading.gif" /></center>';
new Ajax.Updater(myid, url, {
asynchronous:true, 
evalScripts:true});
}

function over(element){
       new Effect.Morph(element, 
       {style:'background-color:#FFFFD5; border:1px solid #E9E9E9; color: #C00;',
         duration:0.2});
       /*style:'	font-family: Arial, Helvetica, sans-serif;font-size: 11px;font-style: normal;font-weight: bold;font-variant: normal;background-color:#FFFFD5;border-style:solid;border-color:#E9E9E9;color: #C00;border-width:1px;padding-top: 1px; padding-bottom: 1px;text-align: center;'*/
}

function out(element){
       new Effect.Morph(element, 
       {style:'background-color:#FBFBFB; border:1px solid #D0D0D0; color:#AA2808;',
         duration:0.2});
      /*style:'	font-family: Arial, Helvetica, sans-serif;font-size: 11px;font-style: normal;font-weight: bold;font-variant: normal;background-color:#FFF;border-style:solid;border-color:#E9E9E9;color: #C00;border-width:1px;padding-top: 1px;padding-bottom: 1px;text-align: center;'*/
}

function ajaxform(form,url,refreshid,refreshurl){
formObj = $(form);
postParameters = Form.serialize(formObj);
new Ajax.Request(url, {
  method: 'post',
  parameters: postParameters,
  onSuccess: function(postreq) {
   ajaxupdate(refreshid,refreshurl);
  }
});
}

function ajaxformupdate(form,url,myid){
if($(myid)) $(myid).innerHTML = '<br clear=all><center><img align="center" src="../js/Loading.gif" /></center>';
formObj = $(form);
postParameters = Form.serialize(formObj);
new Ajax.Request(url, {
  method: 'post',
  parameters: postParameters,
  onSuccess: function(postreq) {
  	if($(myid)) $(myid).innerHTML = postreq.responseText;
  	setTimeout(function() {postreq.responseText.evalScripts()}, 10);
  }
});
}


function hide_field(field) {
	document.getElementById(field).style.display='none';
}
function unhide_field(field) {
	document.getElementById(field).style.display='';
}

function toggle_field(field) {
	var el = document.getElementById(field);
	if ( el.style.display != 'none' ) {
		el.style.display = 'none';
	}
	else {
		el.style.display = '';
	}
}


//date picker

var DatePickerUtils = {
  oneDayInMs		: 24 * 3600 * 1000,
  _daysInMonth	: [31,28,31,30,31,30,31,31,30,31,30,31],
  /**
   * getMonthDays : given the year and month find the number of days.
   */
  getMonthDays	: function ( year, month ) {
    if (((0 == (year%4)) && 
	 ( (0 != (year%100)) || (0 == (year%400)))) && (month == 1))
      return 29;
    return this._daysInMonth[month];
  },
  /**
   * convertDate : turn an ANSI date or (real) number of days relative to now
   * and returns a Date object.
   */
  parseDate : function(dateString) {
    var dateObj = DatePickerUtils.ansiDateToObject(dateString);
    if (!dateObj) {
      var relDate = parseFloat(dateString);
      dateObj = new Date();
      dateObj.setTime(dateObj.getTime() + dateString * this.oneDayInMs);
    }
    return dateObj;
  },
  /**
   * dateObjectToAnsi - note: year is padded to 4 digits, just in case
   */
  dateObjectToAnsi: function(dateObj) {
    if (!dateObj) return null;
    return dateObj.getFullYear().toPaddedString(4) + '-' +
        (dateObj.getMonth() + 1).toPaddedString(2) + '-' +
        dateObj.getDate().toPaddedString(2);
  },
  /**
   * ansiDateToObject - returns null of it fails to parse
   */
  ansiDateToObject: function(ansiDate) {
    var dateObj = null;
    var parsedDate = String(ansiDate).match(/^(\d+)-0*(\d+)-0*(\d+)$/);
    if (parsedDate)
      dateObj = new Date(parsedDate[1],parsedDate[2] - 1,parsedDate[3]);
    return dateObj;
  },
  /**
   * yearMonthToAnsiStub takes year and (0-based) month and returns the
   * ANSI date minus the two digit date-of-month, e.g. "2009-03-"
   */
  yearMonthToAnsiStub: function(year, month) {
    return year.toPaddedString(4)+'-'+(month+1).toPaddedString(2)+'-';
  },
  /**
   * Standard default filter generators which return DatePickerFilter objects
   */
  /**
   * noDatesBefore takes an ISO date string or a real number indicating how
   * many days relative to the current time to set the cutoff of valid dates.
   * If any time during a given date is valid, the date is allowed.
   */
  noDatesBefore: function (firstDate) {
    return new DatePickerFilter(
      function(year, month) {
	/* Perform our date comparisons with ANSI/ISO date strings */
        var testDate = DatePickerUtils.dateObjectToAnsi(
			     DatePickerUtils.parseDate(firstDate));
	var dateFilter = new Array();
	var monthDays = DatePickerUtils.getMonthDays(year, month);
	var calDate = DatePickerUtils.yearMonthToAnsiStub(year,month);
	for (var i = 1; i <= monthDays; i++)
	  dateFilter[i] = (testDate > (calDate+i.toPaddedString(2)) );

	return dateFilter;
      },
      function(year, month) {
	/* Perform our date comparisons with ANSI/ISO date strings */
        var testDate = 
	  DatePickerUtils.dateObjectToAnsi(DatePickerUtils.parseDate(firstDate));
	var calDate = DatePickerUtils.yearMonthToAnsiStub(year,month) +
	  DatePickerUtils.getMonthDays(year,month);
	return (testDate <= calDate);
      }
      );  
  },
  /**
   * noDatesAfter takes an ISO date string or a real number indicating how
   * many days relative to the current time to set the cutoff of valid dates.
   * If any time during a given date is valid, the date is allowed.
   */
  noDatesAfter: function (firstDate) {
    return new DatePickerFilter(
      function(year, month) {
	/* Perform our date comparisons with ANSI/ISO date strings */
        var testDate = DatePickerUtils.dateObjectToAnsi(
			     DatePickerUtils.parseDate(firstDate));
	var dateFilter = new Array();
	var monthDays = DatePickerUtils.getMonthDays(year, month);
	var calDate = DatePickerUtils.yearMonthToAnsiStub(year,month);
	for (var i = 1; i <= monthDays; i++)
	  dateFilter[i] = (testDate < (calDate+i.toPaddedString(2)) );

	return dateFilter;
      },
      function(year, month) {
	/* Perform our date comparisons with ANSI/ISO date strings */
        var testDate = 
	  DatePickerUtils.dateObjectToAnsi(DatePickerUtils.parseDate(firstDate));
	var calDate = DatePickerUtils.yearMonthToAnsiStub(year,month) + '01';
	return (testDate >= calDate);
      }
      );  
  },
  /**
   * noWeekends returns a filter that excludes Saturdays and Sundays.  No
   * time or demand at the moment for something that deals with locale-specific
   * weekend configurations (e.g. Fri, Sat in the Middle East).
   */
  noWeekends: function () {
    return new DatePickerFilter(
      function(year, month) {
	var dateFilter = new Array();
	var monthDays = DatePickerUtils.getMonthDays(year, month);
	var calDate = new Date(year,month,1);
	for (var i = 1; i <= monthDays; calDate.setFullYear(year,month,++i))
	  dateFilter[i] = ((calDate.getDay() % 6) == 0); // 0 = Sun, 6 = Sat
	return dateFilter;
      },
      null
      );  
  }
}

/**
 * DatePickerFormatter class for matching and stringifying dates.
 *
 * By Arturas Slajus <x11@arturaz.net>.
 */
var DatePickerFormatter = Class.create();
DatePickerFormatter.prototype = {
  /**
   * Create a DatePickerFormatter.
   *
   * format: specify a format by passing 3 value array consisting of
   *   "yyyy", "mm", "dd". Default: ["yyyy", "mm", "dd"].
   *
   * separator: string for splitting the values. Default: "-".
   *
   * Use it like this:
   *   var df = new DatePickerFormatter(["dd", "mm", "yyyy"], "/");
   *   df.current_date();
   *   df.match("7/7/2007");
   */
  initialize: function(format, separator) {
    if (Object.isUndefined(format))
      format = ["yyyy", "mm", "dd"];
    if (Object.isUndefined(separator))
      separator = "-";

    this._format 	= format;
    this.separator	= separator;
                
    this._formatYearIndex	= format.indexOf("yyyy");
    this._formatMonthIndex= format.indexOf("mm");
    this._formatDayIndex	= format.indexOf("dd");
                
    this._yearRegexp	= /^\d{4}$/;
    this._monthRegexp 	= /^0\d|1[012]|\d$/;
    this._dayRegexp 	= /^0\d|[12]\d|3[01]|\d$/;
  },
    
  /**
   * Match a string against date format.
   * Returns: [year, month, day]
   */
  match: function(str) {
    var d = str.split(this.separator);
        
    if (d.length < 3)
      return false;
        
    var year = d[this._formatYearIndex].match(this._yearRegexp);
    if (year) { year = year[0] } else { return false }
    var month = d[this._formatMonthIndex].match(this._monthRegexp);
    if (month) { month = month[0] } else { return false }
    var day = d[this._formatDayIndex].match(this._dayRegexp);
    if (day) { day = day[0] } else { return false }
        
    return [year, month, day];
  },
    
  /**
   * Return current date according to format.
   */
  currentDate: function() {
    var d = new Date;
    return this.dateToString(
			     d.getFullYear(),
			     d.getMonth() + 1,
			     d.getDate()
			     );
  },
    
  /**
   * Return a stringified date according to format.  Note, month is from
   * 1 to 12 here.
   */
  dateToString: function(year, month, day, separator) {
    if (Object.isUndefined(separator))
      separator = this.separator;

    var a = [0, 0, 0];
    a[this._formatYearIndex]	= year;
    a[this._formatMonthIndex] 	= month.toPaddedString(2);
    a[this._formatDayIndex] 	= day.toPaddedString(2);
        
    return a.join(separator);
  }
}; 

/**
 * DatePickerFilter
 * Titi Ala'ilima <tigre@pobox.com>
 */

var DatePickerFilter = Class.create();

DatePickerFilter.prototype = {
  /* A flexible way of blocking dates off from being selected.  Should
     be able to go so far as to hook it into an AJAX-based holiday filter,
     should anyone be kind enough to build one.  Note that validDates and
     validMonthP take 0-based months.
  */
  initialize : function (dateFilterFunction, monthFilterFunction) {
    if (dateFilterFunction) this.badDates = dateFilterFunction;
    if (monthFilterFunction) this.validMonthP = monthFilterFunction;
  },
  /**
   * badDates is a method which takes a fear and (0-based) month and
   * returns an array indexed by the (1-based) date, with value true if
   * the filter says this date is not allowed.  (This way,
   * an empty array equates to an unfiltered month.)
   */
  badDates : null,
  /**
   * validMonthP is a method which takes a fear and (0-based) month and
   * returns a Boolean saying whether or not the month is allowed by this
   * filter
   */
  validMonthP : null,
  /* Using "append" we can string filters together, such as "before date a",
     "after date b", and "not on weekends".  Note: this changes the current
     DatePickerFilter rather than returning a new one.
     Caveat Integrator: This uses closures. These can cause memory leaks (in
     IE) so be careful!
  */
  append : function (nextFilter) {
    if (!this.badDates)
      this.badDates = nextFilter.badDates;
    else if (nextFilter.badDates) {
      var firstBadDates = this.badDates;
      this.badDates = function (year, month) {
	  var results1 = firstBadDates(year,month);
	  var results2 = nextFilter.badDates(year,month);
	  /* An element-wise "or", since if it's bad in one filter, it's
	     bad for the aggregate. */
	  for (var i = 0; i < results1.length; i++)
	    results1[i] = results1[i] || results2[i];
	  return results1;
	};
    }
    if (!this.validMonthP)
      this.validMonthP = nextFilter.validMonthP;
    else if (nextFilter.validMonthP) {
      var firstValidMonthP = this.validMonthP;
      this.validMonthP = function (year, month) {
	  return firstValidMonthP(year,month) && nextFilter.validMonthP(year,month);
      };
    }
    return this; // Just so we can chain filters inline
  }
};


/**
 * DatePicker
 */

var DatePicker	= Class.create();

DatePicker.prototype	= {
  Version	: '1.0.0',
  _relative	: null,
  _div		: null,
  _zindex	: 1,
  _keepFieldEmpty: false,
  _dateFormat	: null,
  /* language */
  _language	: 'en',
  _language_month	: $H({
      'fr' : [ 'Janvier', 'F&#233;vrier', 'Mars', 'Avril', 'Mai', 'Juin', 
	       'Juillet', 'Aout', 'Septembre', 'Octobre', 'Novembre',
	       'D&#233;cembre' ],
      'en' : [ 'January', 'February', 'March', 'April', 'May', 'June', 'July',
	       'August', 'September', 'October', 'November', 'December' ],
      'sp' : [ 'Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio',
	       'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre' ],
      'it' : [ 'Gennaio', 'Febbraio', 'Marzo', 'Aprile', 'Maggio', 'Giugno',
	       'Luglio', 'Agosto', 'Settembre', 'Ottobre', 'Novembre',
	       'Dicembre' ],
      'de' : [ 'Januar', 'Februar', 'M&#228;rz', 'April', 'Mai', 'Juni', 'Juli',
	       'August', 'September', 'Oktober', 'November', 'Dezember' ],
      'pt' : [ 'Janeiro', 'Fevereiro', 'Mar&#231;o', 'Abril', 'Maio', 'Junho',
	       'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro' ],
      'hu' : [ 'Janu&#225;r', 'Febru&#225;r', 'M&#225;rcius', '&#193;prilis', 
	       'M&#225;jus', 'J&#250;nius', 'J&#250;lius', 'Augusztus',
	       'Szeptember', 'Okt&#243;ber', 'November', 'December' ],
      'lt' : [ 'Sausis', 'Vasaris', 'Kovas', 'Balandis', 'Gegu&#382;&#279;',
	       'Bir&#382;elis', 'Liepa', 'Rugj&#363;tis', 'Rus&#279;jis',
	       'Spalis', 'Lapkritis', 'Gruodis' ],
      'nl' : [ 'januari', 'februari', 'maart', 'april', 'mei', 'juni', 'juli',
	       'augustus', 'september', 'oktober', 'november', 'december' ],
      'dk' : [ 'Januar', 'Februar', 'Marts', 'April', 'Maj', 'Juni', 'Juli',
	       'August', 'September', 'Oktober', 'November', 'December' ],
      'no' : [ 'Januar', 'Februar', 'Mars', 'April', 'Mai', 'Juni', 'Juli',
	       'August', 'September', 'Oktober', 'November', 'Desember' ],
      'lv' : [ 'Janv&#257;ris', 'Febru&#257;ris', 'Marts', 'Apr&#299;lis',
	       'Maijs', 'J&#363;nijs', 'J&#363;lijs', 'Augusts', 'Septembris',
	       'Oktobris', 'Novembris', 'Decemberis' ],
      'ja' : [ '1&#26376;', '2&#26376;', '3&#26376;', '4&#26376;', '5&#26376;',
	       '6&#26376;', '7&#26376;', '8&#26376;', '9&#26376;',
	       '10&#26376;', '11&#26376;', '12&#26376;' ],
      'fi' : [ 'Tammikuu', 'Helmikuu', 'Maaliskuu', 'Huhtikuu', 'Toukokuu',
	       'Kes&#228;kuu', 'Hein&#228;kuu', 'Elokuu', 'Syyskuu', 'Lokakuu',
	       'Marraskuu', 'Joulukuu' ],
      'ro' : [ 'Ianuarie', 'Februarie', 'Martie', 'Aprilie', 'Mai', 'Junie',
	       'Julie', 'August', 'Septembrie', 'Octombrie', 'Noiembrie',
	       'Decembrie' ],
      'zh' : [ '1&#32;&#26376;', '2&#32;&#26376;', '3&#32;&#26376;', 
	       '4&#32;&#26376;', '5&#32;&#26376;', '6&#32;&#26376;',
	       '7&#32;&#26376;', '8&#32;&#26376;', '9&#32;&#26376;',
	       '10&#26376;', '11&#26376;', '12&#26376;'],
      'sv' : [ 'Januari', 'Februari', 'Mars', 'April', 'Maj', 'Juni', 'Juli',
	       'Augusti', 'September', 'Oktober', 'November', 'December' ]
	}),
  _language_day	: $H({
      'fr'	: [ 'Lun', 'Mar', 'Mer', 'Jeu', 'Ven', 'Sam', 'Dim' ],
	'en'	: [ 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun' ],
	'sp'	: [ 'Lun', 'Mar', 'Mie', 'Jue', 'Vie', 'S&#224;b', 'Dom' ],
	'it'	: [ 'Lun', 'Mar', 'Mer', 'Gio', 'Ven', 'Sab', 'Dom' ],
	'de'	: [ 'Mon', 'Die', 'Mit', 'Don', 'Fre', 'Sam', 'Son' ],
	'pt'	: [ 'Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'S&#225;', 'Dom' ],
	'hu'	: [ 'H&#233;', 'Ke', 'Sze', 'Cs&#252;', 'P&#233;', 'Szo', 'Vas' ],
	'lt'  : [ 'Pir', 'Ant', 'Tre', 'Ket', 'Pen', '&Scaron;e&scaron;', 'Sek' ],
	'nl'	: [ 'ma', 'di', 'wo', 'do', 'vr', 'za', 'zo' ],
	'dk'	: [ 'Man', 'Tir', 'Ons', 'Tor', 'Fre', 'L&#248;r', 'S&#248;n' ],
	'no'	: [ 'Man', 'Tir', 'Ons', 'Tor', 'Fre', 'L&#248;r', 'Sun' ],
	'lv'	: [ 'P', 'O', 'T', 'C', 'Pk', 'S', 'Sv' ],
	'ja'	: [ '&#26376;', '&#28779;', '&#27700;', '&#26408;', '&#37329;', 
		    '&#22303;', '&#26085;' ],
	'fi'	: [ 'Ma', 'Ti', 'Ke', 'To', 'Pe', 'La', 'Su' ],
	'ro'	: [ 'Lun', 'Mar', 'Mie', 'Joi', 'Vin', 'Sam', 'Dum' ],
	'zh'	: [ '&#21608;&#19968;', '&#21608;&#20108;', '&#21608;&#19977;', 
		    '&#21608;&#22235;', '&#21608;&#20116;', '&#21608;&#20845;', 
		    '&#21608;&#26085;' ],
	'sv'	: [ 'M&#229;n', 'Tis', 'Ons', 'Tor', 'Fre', 'L&#246;r', 
		    'S&#246;n' ]
	}),
  _language_close	: $H({
      'fr'	: 'fermer',
	'en'	: 'close',
	'sp'	: 'cierre',
	'it'	: 'fine',
	'de'	: 'schliessen',
	'pt'	: 'fim',
	'hu'	: 'bez&#225;r',
	'lt'  : 'udaryti',
	'nl'	: 'sluiten',
	'dk'	: 'luk',
	'no'	: 'lukk',
	'lv'	: 'aizv&#275;rt',
	'ja'	: '&#38281;&#12376;&#12427;',
	'fi'	: 'sulje',
	'ro'	: 'inchide',
	'zh'	: '&#20851;&#32;&#38381',
	'sv'	: 'st&#228;ng'
	}),
  _language_date_format : $H({
      'en': [ ["mm", "dd", "yyyy"], "/" ],
	'lt': [ ["yyyy", "mm", "dd"], "-" ],
	'fr': [ ["dd", "mm", "yyyy"], "/" ],
	'sp': [ ["dd", "mm", "yyyy"], "/" ],
	'it': [ ["dd", "mm", "yyyy"], "/" ],
	'de': [ ["dd", "mm", "yyyy"], "/" ],
	'pt': [ ["dd", "mm", "yyyy"], "/" ],
	'hu': [ ["dd", "mm", "yyyy"], "/" ],
	'nl': [ ["dd", "mm", "yyyy"], "/" ],
	'dk': [ ["dd", "mm", "yyyy"], "/" ],
	'no': [ ["dd", "mm", "yyyy"], "/" ],
	'lv': [ ["dd", "mm", "yyyy"], "/" ],
	'ja': [ ["yyyy", "mm", "dd"], "-" ],
	'fi': [ ["dd", "mm", "yyyy"], "/" ],
	'ro': [ ["dd", "mm", "yyyy"], "/" ],
	'zh': [ ["yyyy", "mm", "dd"], "-" ],
	'sv': [ ["dd", "mm", "yyyy"], "/" ]
	}),
  /* date manipulation */
  _todayDate		: new Date(),
  _currentDate		: null,
  _clickCallback		: Prototype.emptyFunction,
  _cellCallback		: Prototype.emptyFunction,
  _dateFilter : new DatePickerFilter(),
  _id_datepicker		: null,
  /* positionning */
  _topOffset		: 30,
  _leftOffset		: 0,
  _isPositionned		: false,
  _relativePosition 	: true,
  _setPositionTop 	: 0,
  _setPositionLeft	: 0,
  _bodyAppend		: false,
  /* Effects Adjustment */
  _showEffect		: "appear", 
  _showDuration		: 0.2,
  _enableShowEffect 	: true,
  _closeEffect		: "fade", 
  _closeEffectDuration	: 0.2,
  _enableCloseEffect 	: true,
  _closeTimer		: null,
  _enableCloseOnBlur	: false,
  /* afterClose : called when the close function is executed */
  _afterClose	: Prototype.emptyFunction,
  /* return the name of current month in appropriate language */
  getMonthLocale	: function ( month ) {
    return	this._language_month.get(this._language)[month];
  },
  getLocaleClose	: function () {
    return	this._language_close.get(this._language);
  },
  _initCurrentDate : function () {
    /* Create the DateFormatter */
    if (!this._dateFormat)
      this._dateFormat = this._language_date_format.get(this._language);
    this._df = new DatePickerFormatter(this._dateFormat[0], this._dateFormat[1]);
    /* check if value in field is proper, if not set to today */
    this._currentDate = $F(this._relative);
    if (! this._df.match(this._currentDate)) {
      this._currentDate = this._df.currentDate();
      /* set the field value ? */
      if (!this._keepFieldEmpty)
	$(this._relative).value = this._currentDate;
    }
    var a_date = this._df.match(this._currentDate);
    this._currentYear 	= Number(a_date[0]);
    this._currentMonth	= Number(a_date[1]) - 1;
    this._currentDay	= Number(a_date[2]);
  },
  /* init */
  initialize	: function ( h_p ) {
    /* arguments */
    this._relative= h_p["relative"];
    if (h_p["language"])
      this._language = h_p["language"];
    this._zindex	= ( h_p["zindex"] ) ? parseInt(Number(h_p["zindex"])) : 1;
    if (!Object.isUndefined(h_p["keepFieldEmpty"]))
      this._keepFieldEmpty	= h_p["keepFieldEmpty"];
    if (Object.isFunction(h_p["clickCallback"])) 
      this._clickCallback	= h_p["clickCallback"];
    if (!Object.isUndefined(h_p["leftOffset"]))
      this._leftOffset	= parseInt(h_p["leftOffset"]);
    if (!Object.isUndefined(h_p["topOffset"]))
      this._topOffset	= parseInt(h_p["topOffset"]);
    if (!Object.isUndefined(h_p["relativePosition"]))
      this._relativePosition = h_p["relativePosition"];
    if (!Object.isUndefined(h_p["showEffect"]))
      this._showEffect 	= h_p["showEffect"];
    if (!Object.isUndefined(h_p["enableShowEffect"]))
      this._enableShowEffect	= h_p["enableShowEffect"];
    if (!Object.isUndefined(h_p["showDuration"]))
      this._showDuration 	= h_p["showDuration"];
    if (!Object.isUndefined(h_p["closeEffect"]))
      this._closeEffect 	= h_p["closeEffect"];
    if (!Object.isUndefined(h_p["enableCloseEffect"]))
      this._enableCloseEffect	= h_p["enableCloseEffect"];
    if (!Object.isUndefined(h_p["closeEffectDuration"]))
      this._closeEffectDuration = h_p["closeEffectDuration"];
    if (Object.isFunction(h_p["afterClose"]))
      this._afterClose	= h_p["afterClose"];
    if (!Object.isUndefined(h_p["externalControl"]))
      this._externalControl= h_p["externalControl"];
    if (!Object.isUndefined(h_p["dateFormat"])) 
      this._dateFormat	= h_p["dateFormat"];
    if (Object.isFunction(h_p["cellCallback"]))
      this._cellCallback	= h_p["cellCallback"];
    this._setPositionTop	= ( h_p["setPositionTop"] ) ? 
    parseInt(Number(h_p["setPositionTop"])) : 0;
    this._setPositionLeft	= ( h_p["setPositionLeft"] ) ? 
    parseInt(Number(h_p["setPositionLeft"])) : 0;
    if (!Object.isUndefined(h_p["enableCloseOnBlur"]) && h_p["enableCloseOnBlur"])
      this._enableCloseOnBlur	= true;
    if (!Object.isUndefined(h_p["dateFilter"]) && h_p["dateFilter"])
      this._dateFilter = h_p["dateFilter"];
    // Backwards compatibility
    if (!Object.isUndefined(h_p["disablePastDate"]) && h_p["disablePastDate"])
      this._dateFilter.append(DatePickerFilter.noDatesBefore(0));
    else if (!Object.isUndefined(h_p["disableFutureDate"]) && 
	!h_p["disableFutureDate"])
      this._dateFilter.append(DatePickerFilter.noDatesAfter(0));
    this._id_datepicker		= 'datepicker-'+this._relative;
    this._id_datepicker_prev	= this._id_datepicker+'-prev';
    this._id_datepicker_next	= this._id_datepicker+'-next';
    this._id_datepicker_hdr	= this._id_datepicker+'-header';
    this._id_datepicker_ftr	= this._id_datepicker+'-footer';
    
    /* build up calendar skel */
    this._div = new Element('div', { 
      id : this._id_datepicker,
      className : 'datepicker',
      style : 'display: none; z-index:'+this._zindex });
    this._div.innerHTML = '<table><thead><tr><th width="10px" id="'+this._id_datepicker_prev+'" style="cursor: pointer;">&nbsp;&lt;&lt;&nbsp;</th><th id="'+this._id_datepicker_hdr+'" colspan="5"></th><th width="10px" id="'+this._id_datepicker_next+'" style="cursor: pointer;">&nbsp;&gt;&gt;&nbsp;</th></tr></thead><tbody id="'+this._id_datepicker+'-tbody"></tbody><tfoot><td colspan="7" id="'+this._id_datepicker_ftr+'"></td></tfoot></table>';
    /* finally declare the event listener on input field */
    Event.observe(this._relative, 
		  'click', this.click.bindAsEventListener(this), false);
    /* need to append on body when doc is loaded for IE */
    document.observe('dom:loaded', this.load.bindAsEventListener(this), false);
    /* automatically close when blur event is triggered */
    if ( this._enableCloseOnBlur ) {
      Event.observe(this._relative, 'blur', function (e) { 
		      this._closeTimer = this.close.bind(this).delay(1); 
		    }.bindAsEventListener(this));
      Event.observe(this._div, 'click', function (e) { 
		      if (this._closeTimer) { 
			window.clearTimeout(this._closeTimer); 
			this._closeTimer = null; 
		      } 
		    });
    }
  },
  /**
   * load	: called when document is fully-loaded to append datepicker
   *		  to main object.
   */
  load		: function () {
    /* if externalControl defined set the observer on it */
    if (this._externalControl) 
      Event.observe(this._externalControl, 'click',
		    this.click.bindAsEventListener(this), false);
    /* append to page */
    if (this._relativeAppend) {
   /* append to parent node */
      if ($(this._relative).parentNode) {
	this._div.innerHTML = this._wrap_in_iframe(this._div.innerHTML);
	$(this._relative).parentNode.appendChild( this._div );
      }
    } else {
      /* append to body */
      var body	= document.getElementsByTagName("body").item(0);
      if (body) {
	this._div.innerHTML = this._wrap_in_iframe(this._div.innerHTML);
	body.appendChild(this._div);
   }
      if ( this._relativePosition ) {
	var a_pos = Element.cumulativeOffset($(this._relative));
	this.setPosition(a_pos[1], a_pos[0]);
      } else {
	if (this._setPositionTop || this._setPositionLeft)
	  this.setPosition(this._setPositionTop, this._setPositionLeft);
      }
    }
    /* init the date in field if needed */
    this._initCurrentDate();
    /* set the close locale content */
    $(this._id_datepicker_ftr).innerHTML = this.getLocaleClose();
    /* declare the observers for UI control */
    Event.observe($(this._id_datepicker_prev), 
		  'click', this.prevMonth.bindAsEventListener(this), false);
    Event.observe($(this._id_datepicker_next), 
		  'click', this.nextMonth.bindAsEventListener(this), false);
    Event.observe($(this._id_datepicker_ftr), 
    'click', this.close.bindAsEventListener(this), false);
  },
  /* hack for buggy form elements layering in IE */
  _wrap_in_iframe	: function ( content ) {
    return	( Prototype.Browser.IE ) ?
    "<div style='height:167px;width:185px;background-color:white;align:left'><iframe width='100%' height='100%' marginwidth='0' marginheight='0' frameborder='0' src='about:blank' style='filter:alpha(Opacity=50);'></iframe><div style='position:absolute;background-color:white;top:2px;left:2px;width:180px'>" + content + "</div></div>" : content;
  },
  /**
   * visible	: return the visibility status of the datepicker.
   */
  visible	: function () {
    return	$(this._id_datepicker).visible();
  },
  /**
   * click	: called when input element is clicked
   */
  click		: function () {
    /* init the datepicker if it doesn't exists */
    if ( $(this._id_datepicker) == null ) this.load();
    if (!this._isPositionned && this._relativePosition) {
      /* position the datepicker relatively to element */
      var a_lt = Element.positionedOffset($(this._relative));
      $(this._id_datepicker).setStyle({
	  'left'	: Number(a_lt[0]+this._leftOffset)+'px',
	    'top'	: Number(a_lt[1]+this._topOffset)+'px'
	    });
      this._isPositionned	= true;
    }
    if (!this.visible()) {
      this._initCurrentDate();
      this._redrawCalendar();
    }
    /* eval the clickCallback function */
    eval(this._clickCallback());
    /* Effect toggle to fade-in / fade-out the datepicker */
    if ( this._enableShowEffect ) {
      new Effect.toggle(this._id_datepicker, 
			this._showEffect, { duration: this._showDuration });
    } else {
      $(this._id_datepicker).show();
    }
  },
  /**
   * close	: called when the datepicker is closed
   */
  close		: function () {
    if ( this._enableCloseEffect ) {
      switch(this._closeEffect) {
	case 'puff': 
	new Effect.Puff(this._id_datepicker, { 
	  duration : this._closeEffectDuration });
	break;
	case 'blindUp': 
	new Effect.BlindUp(this._id_datepicker, { 
	  duration : this._closeEffectDuration });
	break;
	case 'dropOut': 
	new Effect.DropOut(this._id_datepicker, { 
	  duration : this._closeEffectDuration }); 
	break;
	case 'switchOff': 
	new Effect.SwitchOff(this._id_datepicker, { 
	  duration : this._closeEffectDuration }); 
	break;
	case 'squish': 
	new Effect.Squish(this._id_datepicker, { 
	  duration : this._closeEffectDuration });
	break;
	case 'fold': 
	new Effect.Fold(this._id_datepicker, { 
	  duration : this._closeEffectDuration });
	break;
	case 'shrink': 
	new Effect.Shrink(this._id_datepicker, { 
	  duration : this._closeEffectDuration });
	break;
	default: 
	new Effect.Fade(this._id_datepicker, { 
	  duration : this._closeEffectDuration });
	break;
      };
    } else {
      $(this._id_datepicker).hide();
    }
    eval(this._afterClose());
  },
  /**
   * setDateFormat
   */
  setDateFormat	: function ( format, separator ) {
    if (Object.isUndefined(format))
      format	= this._dateFormat[0];
    if (Object.isUndefined(separator))
      separator	= this._dateFormat[1];
    this._dateFormat	= [ format, separator ];
  },
  /**
   * setPosition	: set the position of the datepicker.
   *  param : t=top | l=left
   */
  setPosition	: function ( t, l ) {
    var h_pos	= { 'top' : '0px', 'left' : '0px' };
    if (!Object.isUndefined(t))
      h_pos['top']	= Number(t)+this._topOffset+'px';
    if (!Object.isUndefined(l))
      h_pos['left']= Number(l)+this._leftOffset+'px';
    $(this._id_datepicker).setStyle(h_pos);
    this._isPositionned	= true;
  },
  /**
   * _buildCalendar	: draw the days array for current date
   */
  _buildCalendar		: function () {
    var _self	= this;
    var tbody	= $(this._id_datepicker+'-tbody');
    try {
      while ( tbody.hasChildNodes() )
	tbody.removeChild(tbody.childNodes[0]);
    } catch ( e ) {};
    /* generate day headers */
    var trDay	= new Element('tr');
    this._language_day.get(this._language).each( function ( item ) {
						   var td	= new Element('td');
						   td.innerHTML	= item;
						   td.className	= 'wday';
						   trDay.appendChild( td );
						 });
    tbody.appendChild( trDay );
    /* generate the content of days */
    
    /* build-up days matrix */
    var a_d	= [ [ 0, 0, 0, 0, 0, 0, 0 ] ,[ 0, 0, 0, 0, 0, 0, 0 ]
		    ,[ 0, 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0, 0 ]
		    ,[ 0, 0, 0, 0, 0, 0, 0 ]
		    ];
    var currentMonth	= this._currentMonth;
    var currentYear	= this._currentYear;
    /* set date at beginning of month to display */
    var d		= new Date(currentYear, currentMonth, 1, 12);
    /* start the day list on monday */
    var startIndex	= (d.getDay() + 6) % 7;
    var nbDaysInMonth	= DatePickerUtils.getMonthDays(currentYear, currentMonth);
    var daysIndex		= 1;
    var badDates = (this._dateFilter.badDates) ? this._dateFilter.badDates(currentYear, currentMonth) : [];

    /* The first week */
    for ( var j = startIndex; j < 7; j++ ) {
      a_d[0][j]	= { 
	d : daysIndex
	,m : currentMonth
	,y : currentYear 
	,b : badDates[daysIndex]
      };
      daysIndex++;
    }
    /* Fill in days before the current month starts */
    var a_prevMY	= this._prevMonthYear();
    var nbDaysInMonthPrev	= DatePickerUtils.getMonthDays(a_prevMY[1], a_prevMY[0]);
    for ( var j = 0; j < startIndex; j++ ) {
      a_d[0][j]	= { 
	d : Number(nbDaysInMonthPrev - startIndex + j + 1) 
	,m : Number(a_prevMY[0])
	,y : a_prevMY[1]
	,c : 'outbound'
	,b : true
      };
    }
    /* Now the remaining weeks */
    var switchNextMonth	= false;
    for ( var i = 1; i < 6; i++ ) {
      for ( var j = 0; j < 7; j++ ) {
	a_d[i][j]	= { 
	  d : daysIndex
	  ,m : currentMonth
	  ,y : currentYear
	  ,c : ( switchNextMonth )
	       ? 'outbound' :
	       ( 
		((daysIndex == this._todayDate.getDate()) &&
		 (currentMonth  == this._todayDate.getMonth()) &&
		 (currentYear == this._todayDate.getFullYear())) ? 'today' : null)
	  ,b : switchNextMonth || badDates[daysIndex]
	};
	daysIndex++;
	/* if at the end of the month : reset counter */
	if (daysIndex > nbDaysInMonth ) {
	  daysIndex	= 1;
	  switchNextMonth = true;
	  if (this._currentMonth + 1 > 11 ) {
	    currentMonth = 0;
	    currentYear += 1;
	  } else {
	    currentMonth += 1;
	  }
	}
      }
    }
    /* now generate the table cells for the dates */
    for ( var i = 0; i < 6; i++ ) {
      var tr	= new Element('tr');
      for ( var j = 0; j < 7; j++ ) {
	var h_ij = a_d[i][j];
	var td	= new Element('td');
	/* id is : datepicker-day-mon-year or depending on language other way */
	/* don't forget to add 1 on month for proper formmatting */
	var id	= $A([
		      this._relative,
		      this._df.dateToString(h_ij["y"], h_ij["m"]+1, h_ij["d"], '-')
		      ]).join('-');
	/* set id and classname for cell if exists */
	td.setAttribute('id', id);
	if (h_ij["c"])
	  td.className	= h_ij["c"];
	this._bindCellOnClick( td, h_ij["b"], h_ij["c"] );
	td.innerHTML= h_ij["d"];
	tr.appendChild( td );
      }
      tbody.appendChild( tr );
    }
    return	tbody;
  },
  /**
   * _bindCellOnClick	: bind the cell onclick depending on status.
   */
  _bindCellOnClick	: function ( td, badDateP, cellClass ) {
    if ( badDateP ) {
      td.className= ( cellClass ) ? 'nclick_' + cellClass : 'nclick';
    } else {
      /* Create a closure so we have access to the DatePicker object */
      var _self	= this;
      td.onclick	= function () { 
	$(_self._relative).value = String($(this).readAttribute('id')
					  ).replace(_self._relative+'-','').replace(/-/g, _self._df.separator);
	/* if we have a cellCallback defined call it and pass it the cell */
	if (_self._cellCallback)
	  _self._cellCallback(this);
	_self.close(); 
      };
    }
  },
  /**
   * nextMonth	: redraw the calendar content for next month.
   */
  _nextMonthYear	: function () {
    var c_mon	= this._currentMonth;
    var c_year	= this._currentYear;
    if (c_mon + 1 > 11) {
      c_mon	= 0;
      c_year	+= 1;
    } else {
      c_mon	+= 1;
    }
    return	[ c_mon, c_year ];
  },
  nextMonth	: function () {
    this._maybeRedrawMonth(this._nextMonthYear());
  },
  /**
   * prevMonth	: redraw the calendar content for previous month.
   */
  _prevMonthYear	: function () {
    var c_mon	= this._currentMonth;
    var c_year	= this._currentYear;
    if (c_mon - 1 < 0) {
      c_mon	= 11;
      c_year	-= 1;
    } else {
      c_mon	-= 1;
    }
    return	[ c_mon, c_year ];
  },
  prevMonth	: function () {
    this._maybeRedrawMonth(this._prevMonthYear());
  },
  _maybeRedrawMonth : function(a_new) {
    var _newMon = a_new[0];
    var _newYear = a_new[1];
    if (!this._dateFilter.validMonthP ||
	this._dateFilter.validMonthP(_newYear, _newMon)) {
      this._currentMonth	= _newMon;
      this._currentYear 	= _newYear;
      this._redrawCalendar();
    }
  },
  _redrawCalendar	: function () {
    this._setLocaleHdr(); this._buildCalendar();
  },
  _setLocaleHdr	: function () {
    /* next link */
    var a_next	= this._nextMonthYear();
    $(this._id_datepicker_next).setAttribute('title',
					     this.getMonthLocale(a_next[0])+' '+a_next[1]);
    /* prev link */
    var a_prev	= this._prevMonthYear();
    $(this._id_datepicker_prev).setAttribute('title',
					     this.getMonthLocale(a_prev[0])+' '+a_prev[1]);
    /* header */
    $(this._id_datepicker_hdr).update('&nbsp;&nbsp;&nbsp;'+this.getMonthLocale(this._currentMonth)+'&nbsp;'+this._currentYear+'&nbsp;&nbsp;&nbsp;');
  }
};

//nou pt update

function options_ajax_updater(id_element,url,_where){
		$(id_element+'_spinner').style.display="inline";
	new Ajax.Updater(id_element+"_div",url, 
		{
			method: "get",
			onSuccess: function(transport){
				$(id_element+'_spinner').style.display="none";
			}
		});	
}
//lasa doar numere
function checkNumericInput(evt){
	var charCode = (evt.which) ? evt.which : event.keyCode
	if((charCode == 16) || (charCode == 35) || (charCode == 36) || (charCode == 37) || (charCode == 39) || (charCode==46))
		return true;
	if(charCode >= 96 && charCode <= 105) return true;
	if (charCode > 31 && (charCode < 48 || charCode > 57))
		return false;

	return true;
}
//lasa doar litere
function checkAlphaNumericInput(evt){
	var charCode = (evt.which) ? evt.which : event.keyCode
	if((charCode == 8) || (charCode == 16) || (charCode == 35) || (charCode == 36) || (charCode == 37) || (charCode == 39) || (charCode==46))
		return true;
	if((charCode >= 65 && charCode <= 90)) return true;
	else return false;
}


