

/***/
var SelectboxBase = Class.create({
	initialize: function(e, subcss)
	{
		this.model = $(e);
		if (!this.model) return;
		this.subcss = subcss;
		this.initview(this.getSelected());
    },

    getSelected: function()
    {},
	
	getListItems: function(c)
	{
		var itemTemp = new Template('<div class="item" value="#{value}" style="display:#{display}">#{text}</div>')
		var listItem = Array()
		var items = this.model.getElementsBySelector(this.litem)
		c.count = items.size()
		items.each(function(e){
			var v = e.getAttribute('v') ? e.getAttribute('v'):e.value
			var dis = e.getAttribute('display')
			var values = {value: v, text: e.innerHTML, display:dis}
			listItem.push(itemTemp.evaluate(values))
		})
		return listItem		
	},

	initview:function(selected)
	{
        this.model.control = this;
		this.id = this.model.id+'_dd'
		var css = 'selectbox'
		var c = {count:0};
		var listItem = this.getListItems(c)
		var listcss = null
		if (c.count>15) listcss = ' scroller'
		var temp = '<div id="#{id}" class="#{css} #{subcss}"><div class="item selected">#{selected}</div><div class="list#{listcss}" style="display:none">#{list}</div></div><div id="#{overlayid}" class="dd_overlay" style="display:none"/>'
		var ddTemp = new Template(temp)
		var overlayid = 'overlay_'+this.id
		var data = {id: this.id,css:css, subcss:this.subcss, listcss:listcss, selected:selected.innerHTML, list:listItem.join(''), overlayid:overlayid}
		this.model.insert({after:ddTemp.evaluate(data)}).hide()
		this.overlay = $(overlayid)
		this.value = this.model.value
		this.view = this.model.next('.'+css)
		this.drop = false
		this.observeEvent()
	},
	
	observeEvent: function()
	{
		var t = this
		t.overlay.observe('click', function(){
			t.slideup()
		})
			
		this.view.down('.selected').observe('click', function(){
			if (t.disable) return
			
			if (t.drop)	t.slideup()
			else t.slidedown()
		})
		
		this.view.getElementsBySelector('.list .item').each(function(e){
			e.observe('click', function(){
				t.itemclick(this)
			})
		})
	},
	
	itemclick: function(e)
	{
		this.slideup()
		this.updatevalue(e.getAttribute('value'), e.innerHTML)
	},
	
	updatevalue:function(newvalue, newlabel)
	{
		if (this.model.value != newvalue)
		{
			this.view.down('.selected').update(newlabel)
			this.value = this.model.value = this.view.value = newvalue
            this.model.fireEvt('change');
		}
	},
	
	slideup:function()
	{
		this.drop = false
		this.view.down('.list').hide()
		this.view.setStyle({zIndex:'',position:''})
		this.overlay.hide()
	},
	
	slidedown:function()
	{
		this.drop = true
		this.view.setStyle({zIndex:98,position:'relative'})
		this.view.down('.list').show()
		this.overlay.show()
	},
	
	select: function(value)
	{
		if (value == this.value) return

		var selected = $(this.id).down(' .list .item[value="'+value+'"]')
		if (selected) this.updatevalue(value, selected.innerHTML)
	}
})

var Selectbox = Class.create(SelectboxBase, {
	initialize: function($super, e, subcss)
	{
		this.litem = 'option';
        $super(e, subcss);
	},

    getSelected: function()
    {
		return this.model.down(this.litem+':[value="'+this.model.value+'"]');
    }
})

var SelectboxLi = Class.create(SelectboxBase, {
	initialize: function($super, e, subcss)
	{
		this.litem = 'li';
        $super(e, subcss);
	},

    getSelected: function()
    {
		var selected = this.model.down(this.litem+':[selected="selected"]') || this.model.down(this.litem);
		this.model.value = selected.getAttribute('v');
        return selected;
    }
})



/***/
/*
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:
				if(Event.element(event) == this.focusableElements.last()) {
					Event.stop(event);
					this._moveFocus();  // Find last element in MB to handle event on it. If no elements found, uses close ModalBox button
				}
				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);
  }
});

/***/
var Validator = Class.create({
	initialize:function()
	{
	},
	
	validateNotEmpty:function(e)
	{
		e = $(e);
		if (e.value.length < 1) 
		{ 
			alert('Value is empty');
			return false; 
		}
		return true;
	},
	
	validateIsNumber:function(e)
	{
		e = $(e);
		if(e.value.length < 1 || isNaN(e.value)) 
		{ 
			alert("Value is not number");
			return false; 
		}
		return true;
	},
	
	validateEmail:function(e)
	{
		e = $(e);
		var emailRegExp = /^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.([a-z]){2,4})$/;
		var val = emailRegExp.test(e.value);
		if( e.value.length < 1 || val == false) 
		{ 
			alert("Email is incorrect");
			return false; 
		}
		return true;
	},
	
	validateNumberInteger:function(e)
	{
		e = $(e);
		var i, s = e.value;
		for (i = 0; i < s.length; i++)
		{   
			var c = s.charAt(i);
			if (((c < "0") || (c > "9"))) 
			{
				alert("Value is not Integer");
				return false;
			}
		}
		return true;
	},
	
	validateStringCharacter:function(e)
	{
		e = $(e);
		var i, s = e.value;
		for( i = 0; i < s.length; i++ )
		{
			var c = s.charAt(i);
			if(c < "a" || c > "z")
			{
				alert("String not chacracter");
				return false;
			}			
		}
		return true;
	}, 
	
	validateLengthInput:function(e, length)
	{
		e = $(e);
		var lengthinput = e.value.length;
		if(e.value.length < length)
		{
			alert("Input contain a minimum of "+length+" characters.")
			return false;
		}
		return true;
	}	
	
});

/***/
Element.addMethods({
    'find': function(element, selector){
        return element.getElementsBySelector(selector);
    },

    'fireEvt': function(element, event){
        var evt;
        if(document.createEvent)
        {
            // dispatch for firefox + others
            evt = document.createEvent('HTMLEvents');
            evt.initEvent(event, true, true ); // event type,bubbling,cancelable
            return !element.dispatchEvent(evt);
        }
        else
        {
            // dispatch for IE
            evt = document.createEventObject();
            return element.fireEvent('on'+event , evt)
        }
    }
})

String.prototype.hash = function(separator){
    var out = new Hash();
    var array = this.split(separator);
    array.each(function(item){
        if (item) out.set(item, item);
    })
    return out;
};

var Client = Class.create({});
Object.extend(Client, {
    messagebox: null,
	get: function(path)
	{
		document.location = Client.getUrl(path);
	},

    open: function(path, windowName)
    {
        var url = Client.getUrl(path);
        window.open(url, windowName);
    },

    openFront: function(path, windowName)
    {
        var url = url_front + '/' + path;
        window.open(url, windowName);
    },

    ajax: function(url, options)
    {
        $$('.'+options.messagebox).invoke('update', '<div class="ajax_loader"></div>');
        var callback = options.onComplete;
        options.onComplete = function(transport){
            callback(Client.log(transport, options));
        }
        new Ajax.Request(url, options);
    },

    getUrl: function(path)
    {
        return url_subapp + '/' + path;
    },

    log: function(transport, options)
    {
        var response = transport.responseText.split('<!-- debug-info -->');

        if (response.length>1 && $$('.log').length>0)
            $$('.log').first().insert({before:response[1]});

        $$('.'+options.messagebox).invoke('update', response[0]);
        return response[0];
    }
})


/***/
var History = {
    __altered: false,
    __currentHash: null,
    __previousHash: null,
    __iframe: false,
    __title: false,
    
    init: function() {
        var hash  = location.hash.substring(1);
        this.hash = $H(hash.toQueryParams());
        this.__currentHash  = hash;
        this.__previousHash = hash;

        this.__title = document.title;
    },
    
    set: function($name, $value) {
        this.__previousHash = this.hash.toQueryString();
        this.hash.set($name, $value);
        this.apply();
    },
    
    get: function($name) {
        return this.hash.get($name);
    },
    
    unset: function($name) {
        this.hash.unset($name);
        this.apply();
    },
    
    update: function() {
        this.__previousHash = this.hash.toQueryString();
        var hash = window.location.hash.substring(1);
        this.hash = $H(hash.toQueryParams());
        this.__currentHash = hash;
    },
    
    apply: function() {
        var newHash = this.hash.toQueryString();

        var path = window.location.href.replace(/#.*/g, '');
        window.location.replace(path +'#'+ newHash);
    },

    /**
     * @desc Return true if current hash is different of previous hash.
     * this.__altered allows to force the dispatch.
     */
    isAltered: function() {
        if(this.__altered == true) {
            return true;
        }
        this.__altered = false;

        return (History.__currentHash != History.__previousHash);
    },
    
    /**
     * @use  For IE compatibility
     * @desc Set hash value on iframe
     */
    setHashOnIframe: function(hash) {
        try {
            var doc = History.__iframe.contentWindow.document;
            doc.open();
            doc.write('<html><body id="history">' + hash + '</body></html>');
            doc.close();
        } catch(e) {}
    },
    
    /**
     * @use  For IE compatibility
     * @desc Get hash value on iframe
     */
    getHashOnIframe: function() {
        var doc = this.__iframe.contentWindow.document;
        if (doc && doc.body.id == 'history') {
            return doc.body.innerText;
        } else {
            return this.hash.toQueryString();
        }
    },
    
    setTitle: function(title) {
        if(document.title) {
            document.title = title;
        }
    },
    
    getTitle: function() {
        return this.__title;
    }
};

History.init();


/***/
var XControl = Class.create({
    name:null,
    view:null,
    selector:null,
    events: null,

    initialize: function(element)
    {
        this.loadview(element);
        this.events = new Array();
    },

    loadview: function(element)
    {
        this.view = $(element);
        this.name = this.view.id;
        this.view.control = this;
    },

    observe: function(eventName, callback)
    {
        if (!this.events[eventName])
            this.events[eventName] = new Array();
        this.events[eventName].push(callback);
    },

    resetObserve: function()
    {
        this.events = new Array();
    },

    fire: function(eventName, memo)
    {
        if (this.events[eventName])
            this.events[eventName].each(function(callback){
                callback(memo);
            });
    }
})

var FormControlSelector = '.formcontrol';
var FormControl = Class.create(XControl, {
    selector:FormControlSelector,
    form: null,
    noreload:null,
    url:null,
    container:null,

    initialize: function($super, element)
    {
        $super(element);
        this.noreload = this.view.hasClassName('noreload');
        if (this.view.hasClassName('stub'))
            this.render();
        else
            this.observeEvent();
    },

    observeEvent: function()
    {
        var control = this;
        this.view.observe('keypress', function(event){
            if (event.keyCode == 13 && (event.target.tagName=='INPUT'))
                control.submitSaveForm();
        });
        this.find('.submit').invoke('observe', 'click', function(){control.submitSaveForm()});
    },

    find: function()
    {
        var control = this;
        var args = $A(arguments);
        args.each(function(a, index){
            if (a[0]=='.') args[index] = control.container + a;
            else args[index] += control.container;
        })
        return Selector.findChildElements(this.view, args);
    },

    findOne: function(selector)
    {
        return this.find(selector).first();
    },

    checkForChanges: function(){},

    checkForFilterChanges: function(){},

    formBeforeSubmit: function(){},

    discardAllChanges: function(){},

    loadview: function($super, element)
    {
        $super(element);
        this.form = this.view.up('form');
        this.url = this.view.getAttribute('url');
        this.container = this.view.hasClassName('xcontainer') ? '.' + this.view.id : '';
    },

    render: function()
    {
        var params = this.getLocationHash();
        this.find('input').each(function(e){
            params[e.name] = e.value;
        })
        this.requestAjax(params);
    },

    refresh: function()
    {
        if (this.checkForChanges())
        {
            if (!confirm('Do you want to discard all changes?')) return;
            else this.discardAllChanges();
        }
        this.checkForFilterChanges();
        this.submitForm();
    },

    submitSaveForm: function()
    {
        if (this.checkForChanges())
        {
            this.setFormAction('save');
            this.checkForFilterChanges();
            this.submitForm();
        }
        else if (this.checkForFilterChanges())
        {
            this.submitForm();
        }
    },

    submitForm: function()
    {
        this.formBeforeSubmit();
        if (this.view.hasClassName('noajax'))
            this.submitFormNormal();
        else
            this.submitFormAjax();
    },

    submitFormAjax: function()
    {
        var action = this.getFormAction();
        if (!action){
            var hashable = this.getHashable();
            this.setLocationHash(hashable);
        }
        var params = this.serialize();
        this.showAjaxloader();
        this.requestAjax(params);
    },

    getHashable: function()
    {
        var elements = this.find('input:not(.nohash)', 'select:not(.nohash)', 'textarea:not(.nohash)');
        return Form.serializeElements(elements);
    },

    serialize: function(options)
    {
        var elements = this.find('input', 'select', 'textarea');
        return Form.serializeElements(elements, options);
    },

    setValue: function(e, value)
    {
        if (Object.isUndefined(e.originValue)) e.originValue = e.value;
        if (value != e.originValue){
            e.addClassName('changed');
            e.value = value;
        }
    },

    requestAjax: function(params)
    {
        var control = this;
        var wrapper = this.view.up();
        var action = this.getFormAction();
        Client.ajax(this.url, {
            parameters: params,
            onComplete: function(response){
                if(control.noreload)
                {
                    control.hideAjaxloader();
                    $$('.msgflash').invoke('update', response);
                }
                else
                {
                    wrapper.update(response);
                    control.loadview(wrapper.down(control.selector));
                    control.ajaxComplete();
                    control.observeEvent();
                }
                control.fire('ajaxcomplete', {action: action});
            }
        });
    },


    ajaxComplete: function()
    {
    },

    hideAjaxloader: function()
    {
        this.find('.loading_bar_holder').each(function(e){
            e.update('');
        });
        this.find('.loading_circle_holder').each(function(e){
            e.update('');
        });
    },

    showAjaxloader: function()
    {
        this.find('.loading_bar_holder').each(function(e){
            e.update('<input type="button" class="loading_bar"></input>');
        });
        this.find('.loading_circle_holder').each(function(e){
            e.update('<div class="loading_circle"></div>');
        });
        this.find('.loading_longbar_holder').each(function(e){
            e.update('<div class="ajaxloading"></div>');
        });
    },

    submitFormNoajax: function()
    {
        this.form.action = this.url;
        this.submitFormNormal();
    },

    submitFormNormal: function()
    {
        var action = this.getFormAction();
        if (action) this.form.method = 'post';
        this.form.submit();
    },

    setFormAction: function(action)
    {
        this.findOne('.action').value = action;
        return this;
    },

    getFormAction: function()
    {
        var e = this.findOne('.action');
        return e ? e.value : null;
    },

    setLocationHash: function(params)
    {
        this.setHash(this.name, params);
    },

    getLocationHash: function()
    {
        var hash = this.getHash(this.name);
        if (!hash) hash = '';
        return hash.toQueryParams();
    },

    setHash: function(key, value)
    {
        var value = value.replace(/&/g, ';').replace(/=/g, ':');
        History.set(key, value);
    },

    getHash: function(key)
    {
        var value = History.get(key);
        return value ? value.replace(/;/g, '&').replace(/:/g, '=') : null;
    }
})

/***/
var allresizers = new Array();
function updateAllResizers()
{
	allresizers.each(function(r){r.updateOffset()});
}

var ResizerW = Class.create({
	element:null,
	width:null, 
	height:null,
	thick:6,
	offset:{x:null, y:null},
	padding:null,

	initialize: function(e)
	{
		allresizers.push(this);
		this.element = e = $(e);
		this.padding = parseInt(e.getStyle('padding-left')) + parseInt(e.getStyle('padding-right'));
		this.updateOffset();
		new Draggable(this.div, {
			constraint:"horizontal", 
			starteffect:null, 
			endeffect:null,
			onDrag:this.resize,
			onEnd:this.endResize
		});
	},
	
	updateOffset:function()
	{
		var dim = this.element.getDimensions();
		var offset = this.element.cumulativeOffset();
		this.height = dim.height;
		this.offset.x = offset[0]+dim.width - this.thick/2;
		this.offset.y = offset[1];
		this.updateDiv();
	},
	
	resize:function(div, event)
	{
		try
		{
			var t = div.element.model;
			var e = t.element;
			var eoffset = e.cumulativeOffset();
			var doffset = div.element.cumulativeOffset();
			var width = doffset[0] - eoffset[0] + t.thick/2 - t.padding;
			t.offset.x = doffset[0];
			e.setStyle({width:width+'px'});
			updateAllResizers();
		} 
		catch(ex){}
	},
	
	endResize:function(div, event)
	{
		var t = div.element.model;
		t.resize(div, event);
		if (typeof(t.afterResize)=='function')
			t.afterResize();
	},
	
	updateDiv: function()
	{
		if (!this.div)
		{
			this.div = new Element('div');
			this.div.addClassName('handler resize_w');
			this.div.model = this;
			$(document.body).insert(this.div);
		}
		return this.div.setStyle({
			width:this.thick+'px', 
			height:this.height+'px', 
			left:this.offset.x+'px',
			top:this.offset.y+'px'
		});
	}
});

/***/
var GridSelectSelector = '.gridselect';
var GridselectControl = Class.create(XControl, {
    drop:null,
    model:null,
    view:null,

    loadview: function(element)
    {
        this.model = $(element);
        var control = this.model.control = this;
        this.view = Builder.node('div', {className:'dropdown'},
            Builder.node('div', {className:'valuebox'})
        );
        this.model.value = this.model.getAttribute('value');
        var display = this.model.getAttribute('display');
        if (!display) display = this.model.value;
        this.setDisplayValue(display);

        if (this.model.hasClassName('filtered')) this.view.addClassName('filtered');

        this.model.insert({after:this.view}).hide();

        this.drop = new DropdownControl(this.view, this.model.getAttribute('drop'));

        this.drop.observe('show', function(){
            var grid = control.getGrid();
            grid.resetObserve();
            grid.observe('rowselect', function(memo){
                control.setValue(memo.id);
                control.setDisplayValue(memo.display);
                control.drop.hide();
                control.fire('rowselect', memo);
            });
            grid.find('.clear_selection').invoke('observe', 'click', function(){
                control.setValue('');
                control.setDisplayValue('');
                control.drop.hide();
                control.fire('rowselect', {id:'', display:''});
            });
        })
    },

    setValue: function(value)
    {
        if (Object.isUndefined(this.model.originValue)) this.model.originValue = this.model.value;

        this.model.value = value;
        if (value != this.model.originValue)
            this.view.addClassName('changed');
        else
            this.view.removeClassName('changed');
    },

    setDisplayValue: function(value)
    {
        this.view.down('.valuebox').update(value);
    },

    getGrid: function()
    {
        return this.drop.content.control;
    }
})

/***/
document.observe('dom:loaded', function(){
    $$(GridSelector).each(function(e){
        if (Object.isUndefined(e.control)) new GridControl(e)
    });
});

var GridSelector = '.gridsolo';
var GridControl = Class.create(FormControl, {
    selector:GridSelector,
    newIndex:null,
    rowSelector:null,
    cellSelector:null,
    filterSelector:null,
    actionSelector:null,
    actionRowSelector: null,
    editboxSelector:null,
    fieldSelect:null,

    initialize: function($super, element)
    {
        this.newIndex = 0;
        this.rowSelector = '.row';
        this.cellSelector = '.cell';
        this.filterSelector = '.filter';
        this.actionSelector = '.action_item';
        this.actionRowSelector = this.rowSelector +' '+ this.actionSelector;
        this.editboxSelector = '.editbox';
        $super(element);
        this.fieldSelect = this.view.getAttribute('fieldselect');
    },

    ajaxComplete: function()
    {
        this.view.find(GridSelector).each(function(e){new GridControl(e)});

        //init gridlist
        if (this.view.next())
            this.view.next().find(GridSelector).each(function(e){new GridControl(e)});
    },

    setFilter: function(key, value)
    {
        this.setValue(this.findOne(this.filterSelector+'.field-'+key+' .box'), value);
    },

    observeEvent: function($super)
    {
        $super();
        this.observeRows();
        this.observeBasicActions();
        this.observeFilter();
        this.observeSelectActions();
        this.observeMassActions();
        this.observeColumnResize();
    },

    getSelectedRowIds: function()
    {
        var control = this;
        var ids = new Array();
        this.findRow('.selected').each(function(e){
            ids.push(control.getRecordId(e));
        });
        return ids;
    },

    getSelectedRows: function()
    {
        return this.findRow('.selected');
    },

    getRecordId: function(row)
    {
        return row.getAttribute('key');
    },

    findRow: function(selector)
    {
        selector = Object.isUndefined(selector) ? '' : selector;
        return this.find(this.rowSelector + selector);
    },

    findCell: function(selector)
    {
        selector = Object.isUndefined(selector) ? '' : selector;
        return this.find(this.cellSelector + selector);
    },

    findFilter: function(selector)
    {
        selector = Object.isUndefined(selector) ? '' : selector;
        return this.find(this.filterSelector + selector);
    },

    observeRows: function()
    {
        var control = this;
        this.findRow(':nth-child(2n)').invoke('addClassName', 'alternate');
        this.findRow().invoke('observe', 'click', function(event){control.toggleRowSelect(this, event)});
        this.findRow(' input.check[type="checkbox"]').invoke('observe', 'click', function(event){control.checkboxClick(this, event)});
        this.findRow(' .thumbimg').each(function(e){
            var cell = e.up(control.cellSelector);
            var src = cell.getAttribute('value');
            new Tooltip(cell, '<img class="tooltip_img" src="'+src+'" />')
        });

        this.find(this.actionRowSelector+'.delete').invoke('observe', 'click', function(event){control.deleteItem(this, event)});
        this.find(this.actionRowSelector+'.inline_edit').each(function(e){
            e.toggleRowEdit = control.toggleRowEdit;
            e.observe('click', control.toggleRowEdit);
        });

        this.findCell().each(function(e){
            var i = e.down('.box');
            if (i) i.observe('change', control.inputChanged);

            e.observe('click', function(event){
                if (event.altKey){
                    this.toggleClassName('selected');
                    event.stopPropagation();
                }
            })
            e.observe('dblclick', function(event){
                control.toggleCellEdit(this);
                event.stopPropagation();
            })
            if (e.hasClassName('oneclickedit'))
                e.observe('click', function(event){
                    if (!this.hasClassName('editing')) control.enableCellEdit(e);
                    event.stopPropagation();
                })
        });

        this.observeActionBox();
    },

    observeBasicActions: function()
    {
        var control = this;
        this.view.control = this;
        this.find('input.check_all').invoke('observe', 'click', function(){control.setAllCheckbox(this.checked)});
        this.find('.pager select').invoke('observe', 'change', function(){control.refresh()});
        this.find('.pager .page').invoke('observe', 'click', function(){
            var page = this.value;
            control.find('.pager_input').each(function(e){
                e.value = page;
            });
            control.refresh()
        });
        this.find('.sortable').invoke('observe', 'click', function(){control.sortColumn(this)});
    },

    observeFilter: function()
    {
        var control = this;
        this.findFilter(' .box').each(function(e){
            e.originValue = e.value;
            e.observe('change', control.inputChanged);
            if (e.value) e.addClassName('filtered');
        })

        this.findFilter(' select').invoke('observe', 'change', function(){
            control.refresh()
        });

        this.find('.clear_filter').invoke('observe', 'click', function(){control.clearFilter()});
        this.findFilter(' input.daterange_picker').each(function(e){
            var dr = new DaterangeControl(e);
            dr.applyCallback = function(){
                control.refresh();
            }
        });

        this.findFilter(' '+GridSelectSelector).each(function(e){
            if (Object.isUndefined(e.control))
            {
                new GridselectControl(e);
                e.control.observe('rowselect', function(){control.refresh()});
            }
        });
    },

    observeActionBox: function()
    {
        this.findRow(' .actionbox').each(function(e){
            if (e.down('.action_wrapper')){
                e.observe('mouseover', function(){
                    this.down('div.action_wrapper').show();
                });
                e.observe('mouseout', function(){
                    this.down('div.action_wrapper').hide();
                });
            }
        });
    },

    observeColumnResize: function()
    {
        this.find('thead .caption th').each(function(e){
			new ResizerW(e);
            e.setStyle({width:e.getStyle('width')});
        });
        updateAllResizers();
    },

    observeSelectActions: function()
    {
        var control = this;
        this.find('.select_all').invoke('observe', 'click', function(){
            control.selectAll();
        });

        this.find('.select_none').invoke('observe', 'click', function(){
            control.selectNone();
        });

        this.find('.select_editing').invoke('observe', 'click', function(){
            control.selectEditing();
        });

        this.find('.select_inverse').invoke('observe', 'click', function(){
            control.selectInverse();
        });
    },

    observeMassActions: function()
    {
        var control = this;
        this.find('.add_new').invoke('observe', 'click', function(){
            control.addNew();
        });

        this.find('.toogle_edit').invoke('observe', 'click', function(){
            control.editSelected();
        });

        this.find('.mass_action').invoke('observe', 'click', function(){
            var action = this.getAttribute('action');
            var confirm = !this.hasClassName('noconfirm');
            var selected_check = !this.hasClassName('noselected');
            var file_export = this.hasClassName('file_export');
            control.actOnSelecteds(action, confirm, selected_check, file_export, this.innerHTML);
        });
    },

    formBeforeSubmit: function()
    {
        this.removeUnchangedFilter();
        this.find(this.editboxSelector).invoke('remove');
    },

    removeUnchangedInputs: function()
    {
        var control = this;
        this.findRow('.editing .inline_edit').each(function(e){
            if (!e.up(control.rowSelector).down('.changed') && e.toggleRowEdit)
                e.toggleRowEdit();
        });
        this.findCell('.editing input:not(.changed)').each(function(e){control.undoEdit(e)});
        this.findCell('.editing select:not(.changed)').each(function(e){control.undoEdit(e)});
        this.findCell('.editing input[type=checkbox].changed').each(function(e){control.undoCheckboxEdit(e)});
    },

    removeUnchangedFilter: function()
    {
        this.findFilter(' .box').each(function(e){ if(e.value=='') e.disable()});
    },

    undoCheckboxEdit: function(checkbox)
    {
        var cell = checkbox.up(this.cellSelector);
        if (cell.hasClassName('keepedit')) return;

        checkbox.hide().checked = true;
        cell.insert(checkbox.value);
    },

    undoEdit: function(input)
    {
        this.cancelCellEdit(input.up(this.cellSelector));
    },

    checkForChanges: function()
    {
        var control = this;
        this.findCell('.editing input:not(.changed)').each(function(e){
            if (e.value != e.up(control.cellSelector).getAttribute('value')){
                e.addClassName('changed');
            }
        });
        this.removeUnchangedInputs();
        var changes = this.findCell('.editing .box.changed').length;
        return changes>0;
    },

    checkForFilterChanges: function()
    {
        this.findFilter('.editing .box').each(function(e){
            if (e.value != e.originValue) e.addClassName('changed');
            else e.removeClassName('changed');
        });
        var changes = this.findFilter('.editing input.changed').length;

        return changes>0;
    },

    editSelected: function()
    {
        this.findRow('.selected .inline_edit').invoke('toggleRowEdit');
        //this.findCell('.selected.editable').each(this.toggleCellEdit);
    },

    toggleCellEdit: function(e)
    {
        if (!e.hasClassName('editable')) return;
        var editing = e.hasClassName('editing');
        if (!editing) this.enableCellEdit(e);
        else this.cancelCellEdit(e);
        updateAllResizers();
    },

    toggleRowEdit: function(event)
    {
        var control = this.up('.grid').control;
        var row = this.up(control.rowSelector);
        var cells = row.find(control.container + control.cellSelector+'.editable');
        var editing = row.hasClassName('editing');
        if (!editing)
        {
            cells.each(function(e){control.enableCellEdit(e)});
            row.addClassName('editing');
            this.update('Cancel');
        }
        else
        {
            cells.each(control.cancelCellEdit);
            row.removeClassName('editing');
            this.update('Edit');
        }
        if (event) event.stopPropagation();
        updateAllResizers();
    },

    enableCellEdit: function(cell)
    {
        this.saveCellFormatedValue(cell);
        var cell_value = cell.getAttribute('value');
        var editbox = this.getEditbox(cell, cell_value);

        var i = cell.addClassName('editing').update(editbox).down('.box').observe('change', this.inputChanged);

        if (i.type!='checkbox')
        {
            i.value = i.originValue = cell_value;
            if (i.getAttribute('type')=='datetime')
            {
                this.initDatepicker(i);
            }
            else if (i.hasClassName('gridselect_ready'))
            {
                i.addClassName('gridselect');
                new GridselectControl(i);
            }
        }
        this.fire('celledit', {cell: cell});
    },

    getEditbox: function(cell, cell_value)
    {
        var editbox_template = this.findOne(this.editboxSelector+' .edit-'+cell.getAttribute('field'));
        var id = this.getRecordId(cell.up(this.rowSelector));

        var editbox = editbox_template.innerHTML.gsub(/#id/, id).gsub(/#v/, cell_value);
        var display = cell.down('.displayvalue');
        display = display ? display.innerHTML : '';
        editbox = editbox.gsub(/#f/, display);

        var checked = cell_value>0 ? 'checked="checked"' : '';
        return editbox.gsub(/#checked/, checked);
    },

    saveCellFormatedValue: function(e)
    {
        if (!e.formated){
            var value = e.down();
            e.formated = value ? value : e.innerHTML;
        }
    },

    initDatepicker: function(e)
    {
        e.observe('click', function(){
            new CalendarDateSelect(this);
        }).observe('blur', this.inputChanged)
    },

    cancelCellEdit: function(cell)
    {
        if (cell.hasClassName('keepedit')) return;
        cell.removeClassName('editing').update(cell.formated);
    },

    inputChanged: function()
    {
        if (this.type=='checkbox') this.value = this.checked ? 1:0;

        if (this.value != this.originValue)
            this.addClassName('changed');
        else
            this.removeClassName('changed');
    },

    clearFilter: function()
    {
        var control = this;
        this.find('.filter input', '.filter select').each(function(e){
            control.setValue(e, '')
        });
        this.refresh();
    },

    sortColumn: function(e)
    {
        var sort_order = this.findOne('.sort_order');
        var sort_field = this.findOne('.sort_field');

        if (e.hasClassName('asc')) this.setValue(sort_order, 'desc');
        else if(e.hasClassName('desc')) this.setValue(sort_order, '');
        else this.setValue(sort_order, 'asc');
        this.setValue(sort_field, sort_order.value? e.title:null);
        this.refresh();
    },

    discardAllChanges: function()
    {
        var control = this;
        this.findRow('.editing .inline_edit').each(function(e){
            if (e.toggleRowEdit) e.toggleRowEdit();
        })
        this.findCell('.editing').each(function(e){
            control.cancelCellEdit(e);
        })
    },

    actOnSelecteds: function(action, confirmRequired, selected_check, file_export, label)
    {
        if (!label) label = action;
        if (selected_check && this.getSelectedRows().length < 1) {alert('No item selected!');return;}
        if (confirmRequired && !confirm('Do you want to `'+label+'` selected items?')) return;
        this.setFormAction(action);

        if (file_export) {
            this.submitFormNoajax();
            this.setFormAction('');
        }
        else
            this.refresh();
    },

    processAction: function(action)
    {
        this.setFormAction(action).refresh();
    },

    deleteItem: function(e, event)
    {
        this.selectNone();
        var row = e.up(this.rowSelector);
        row.addClassName('editing');
        this.selectRow(row, true);
        if (confirm('Do you want to delete this item?'))
        {
            this.setFormAction('delete');
            this.refresh();
        }
        else
            row.removeClassName('editing');
        event.stopPropagation();
    },

    checkboxClick: function(e, event)
    {
        var row = e.up(this.rowSelector);
        if(e.checked)
            row.addClassName('selected')
        else
            row.removeClassName('selected')
        event.stopPropagation();
    },

    toggleRowSelect: function(e, event)
    {
        var element = event.element();
        if (element.tagName != 'INPUT'
            && element.tagName != 'SELECT'
            && !element.hasClassName('node_icon')
            && !element.hasClassName('action_item'))
        {
            var c = e.down('input'+this.container+'.check[type="checkbox"]');
            if (c) this.selectRow(e, !c.checked, c);
        }

        var id = this.getRecordId(e);
        var display = this.fieldSelect ? this.getFieldValue(e, this.fieldSelect) : id;
        this.fire('rowselect', {id:id, display:display});
    },

    getFieldValue: function(row, fieldname)
    {
        return row.down('.cell[field='+fieldname+']').getAttribute('value');
    },

    setAllCheckbox: function(checked)
    {
        var control = this;
        this.findRow().each(function(row){
            control.selectRow(row, checked)
        });
    },

    selectRow: function(row, checked, e)
    {
        if (!e) e = row.down('input[type="checkbox"]');
        e.checked = checked;
        if(e.checked)
            row.addClassName('selected')
        else
            row.removeClassName('selected')
    },

    selectAll: function()
    {
        this.findOne('input.check_all').checked = true;
        this.setAllCheckbox(true);
    },

    selectNone: function()
    {
        this.find('input.check_all[type="checkbox"]').first().checked = false;
        this.setAllCheckbox(false);
        this.findCell('.selected').each(function(e){e.removeClassName('selected')});
    },

    selectEditing: function()
    {
        var control = this;
        this.findRow().each(function(row){control.selectRow(row, false)});
        this.findRow('.editing').each(function(row){control.selectRow(row, true)});
        this.findRow(':not(.selected) '+this.cellSelector+'.editing').each(function(e){e.toggleClassName('selected')});
    },

    selectInverse: function()
    {
        var control = this;
        var selected = this.getSelectedRows();
        this.findRow(':not(.selected)').each(function(row){control.selectRow(row, true)});
        selected.each(function(row){control.selectRow(row, false)});
    },

    addNew: function()
    {
        var control = this;
        var new_id = "new_" + this.newIndex++;
        this.findOne('tbody').insert('<tr class="row addnew editing '+new_id+'" key="'+new_id+'"></tr>')
        var editbox = this.findOne(this.editboxSelector);

        var row = this.findOne('.'+new_id);
        row.update(editbox.innerHTML);

        row.find(this.container+this.cellSelector+'.editable').each(function(e)
        {
            e.update('');
            control.enableCellEdit(e);
            var box = e.down('.box');
            var filter = control.findOne(control.filterSelector+'.field-'+e.getAttribute('field')+' select');
            if (filter && filter.value) box.value = filter.value;

            if (box.value && box.value != '#NULL') box.addClassName('changed');

            filter = control.findOne(control.filterSelector+'.field-'+e.getAttribute('field')+' '+GridSelectSelector);
            if (filter)
            {
                box = e.down(GridSelectSelector);
                if (box && (filter.value != ''))
                {
                    box.control.setValue(filter.value);
                    box.control.setDisplayValue(filter.getAttribute('display'));
                }
            }
        });

        var cancel = row.down('.inline_edit');
        cancel.toggleRowEdit = function(){this.up(control.rowSelector+'.editing').remove()};
        cancel.observe('click', function(){this.toggleRowEdit()});
    }
});


/***/
document.observe('dom:loaded', function(){
    $('country_select').observe('change', function(){
        Client.get('country/'+this.value);
    })
});
document.observe('dom:loaded', function(){
    $('category_id').observe('change', function(){
        if($('keyword').value != "Search..." && $('keyword').value.length >= 2)
        {
            Client.get('product/search?keyword='+ $('keyword').value + '&category_id=' + $('category_id').value);
        }
    })
});

var error_not_number = "Please enter a number";
var error_not_empty = "Please enter your ";
var activeEle = null;
if (validator == false || validator == undefined)
{
    try{
        var validator = new Validator();
    }
    catch (e)
    {
        validator = null;
    }
}

function GetObjectMessage()
{
    var objmessage = null;
    if (activeEle != null)
    {
        objmessage = $(activeEle).down('.messagebox');
    }
    else
    {
        objmessage = $$('.messagebox').first();
    }
    return objmessage;
}

function ShowMessage(text)
{
    HideErrorMessage();
    var objmessage = GetObjectMessage();
    $(objmessage).show();
    $(objmessage).update(text);
}

function ShowErrorMessage(text)
{
    var objmessage = GetObjectMessage();
    objmessage.removeClassName('confirm');
    objmessage.addClassName('warning');
    ShowMessage(text);
}

function ShowNoticeMessage(text)
{
    var objmessage = GetObjectMessage();
    if(objmessage.hasClassName('error')){
        objmessage.removeClassName('error');
    }
    if(objmessage.hasClassName('confirm')){
        objmessage.removeClassName('confirm');
    }
    objmessage.addClassName('notice');
    ShowMessage(text);
}

function ShowConfirmMessage(text)
{
    var objmessage = GetObjectMessage();
    if(objmessage.hasClassName('error')){
        objmessage.removeClassName('error');
    }
    if(objmessage.hasClassName('notice')){
        objmessage.removeClassName('notice');
    }
    objmessage.addClassName('confirm');
    ShowMessage(text);
}

function HideErrorMessage()
{
    var objmessage = $$('.messagebox');
    if(objmessage.length > 0)
    {
        for (var i = 0; i< objmessage.length; i++)
        {
            $(objmessage[i]).update('');
            $(objmessage[i]).hide();
        }
    }
}

function RemoveHighlight()
{
    var objmessage = $$('.error');
    if(objmessage.length > 0)
    {
        for (var i = 0; i< objmessage.length; i++)
        {
            RemoveHighlightError($(objmessage[i]));
        }
    }
}

function isEmpty (obj, error)
{
    if (obj.alt != '')
        error  = error + obj.alt;
    else
        error  = "Field not empty " + obj.name.replace(/[\W]/g, '_').replace(/__/g, '_').replace(/_$/g, '').replace(/_/g, '-');
    if (obj.value =='')
    {
        obj.addClassName('error');
        ShowNoticeMessage(error);
        obj.focus();
        return false;
    } else if(obj.hasClassName('error')){
        obj.removeClassName('error');
    }
    return true;
}

function HighlightError(obj, error)
{
    RemoveHighlight();
    obj.addClassName('error');
    ShowErrorMessage(error);
    obj.focus();
}

function RemoveHighlightError(obj)
{
    if(obj.hasClassName('error')){
        obj.removeClassName('error');
    }
}

function checkNumber(obj, error)
{
    if (obj.alt != '')
        error  = "The value of field " + obj.alt + " must be a numeric!";
    else
        error  = "The value of field " + obj.name.replace(/[\W]/g, '_').replace(/__/g, '_').replace(/_$/g, '').replace(/_/g, '-') + " must be a numeric!";
   if (obj.value != '' && isNaN(obj.value))
    {
        obj.addClassName('error');
        ShowNoticeMessage(error);
        obj.focus();
        return false;
    } else if(obj.hasClassName('error')){
        obj.removeClassName('error');
    }
    return true;
}

function validateRequired (id)
{
    id = '#' + id + ' input.required';
    var arr_required = $$(id);
    for(var i = 0; i< arr_required.length; i++)
    {
        if (!isEmpty($(arr_required[i]), error_not_empty)){
            return false;
        }
        if($(arr_required[i]).hasClassName('validateIllegalChars') && !validateIllegalCharByElement($(arr_required[i]))){
            return false;
        }
        if($(arr_required[i]).hasClassName('validateEmail') && !validateEmailByElement($(arr_required[i]))){
            return false;
        }
        if($(arr_required[i]).hasClassName('validateNumber') && !checkNumber($(arr_required[i]), error_not_number)){
            return false;
        }
    }
    return true;
}

function validateEmailByElement(elem)
{
    var regular = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
    if (elem.value != '' && !regular.test(elem.value)) {
        var error = "Invalid email address, please try again.";
        elem.addClassName('error');
        ShowNoticeMessage(error);
        elem.focus();
        return false;
    } else if(elem.hasClassName('error')){
        elem.removeClassName('error');
    }
    return true;
}

function validateNumber (id)
{
    id = '#' + id + ' input.validateNumber';
    var arr_required_number = $$(id);
    for(var i = 0; i< arr_required_number.length; i++)
    {
        if (!checkNumber($(arr_required_number[i]), error_not_number)){
            return false;
        }
        if($(arr_required_number[i]).hasClassName('validateIllegalChars') && !validateIllegalCharByElement($(arr_required_number[i]))){
            return false;
        }
    }
    return true;
}

function validateEmail (id)
{
    id = '#' + id + ' input.validateEmail';
    var arr_required_email = $$(id);
    for(var i = 0; i< arr_required_email.length; i++)
    {
        if(!validateEmailByElement($(arr_required_email[i])))
            return false;
    }
    return true;
}

function validateIllegalChars(id)
{
    id = '#' + id + ' input.validateIllegalChars';
    var arr_required_illegal = $$(id);
    for(var i = 0; i< arr_required_illegal.length; i++)
    {
        if (!validateIllegalCharByElement($(arr_required_illegal[i]))) {
          return false;
        }
    }
    return true;
}

function validateIllegalCharByElement(elem)
{
    var illegalChars = /^([A-Za-z0-9_ ])*$/;
    //var illegalChars = /^([\w-\s\.]+)*$/;
    var reg = new RegExp(illegalChars);
    if (elem.value != '' && !elem.value.match(illegalChars)) {
        var error = "The value of field " + elem.alt + " can not include special characters";
        elem.addClassName('error');
        ShowNoticeMessage(error);
        elem.focus();
        return false;
    } else if(elem.hasClassName('error')){
        elem.removeClassName('error');
    }
    return true;
}

function validatePhone(id)
{
    id = '#' + id + ' input.validatePhone';
    var arr_required_tel = $$(id);
    for(var i = 0; i< arr_required_tel.length; i++)
    {
        if (!validatePhoneByElement($(arr_required_tel[i]))) {
          return false;
        }
    }
    return true;
}

function validatePhoneByElement(elem)
{
    var regChars = /[\(\)\.\-\ ]/g;
    var reg = new RegExp(regChars);
    if (elem.value != '' && isNaN(elem.value.replace(regChars, ''))) {
        var error = "Invalid phone number, please try again.";
        elem.addClassName('error');
        ShowNoticeMessage(error);
        elem.focus();
        return false;
    } else if(elem.hasClassName('error')){
        elem.removeClassName('error');
    }
    return true;
}

function ValidateForm(id)
{
    RemoveHighlight();
    HideErrorMessage();
    if (!validateRequired(id) || !validateNumber (id) || !validateEmail(id) || !validateIllegalChars(id) || !validatePhone(id))
    {
        return false;
    }
    return true;
}

function submitenter(myfield,e)
{
	var keycode;
	if (window.event) keycode = window.event.keyCode;
	else if (e) keycode = e.which;
	else return true;

	if (keycode == 13)
	{
		myfield.form.submit();
		return false;
	}
	else return true;
}

function addtocart()
{
	HideErrorMessage();
    var id = $('proid_select').value;
	var qty = $('product[qty]').value;
    if(!checkNumber($('product[qty]'), 'Please enter a numeric!')) return false;
	var url = url_subapp+'/cart/add/'+id+'/'+qty;
	Client.ajax(url, {
		messagebox: 'ajax_message',
        method: 'post',
        parameters: {'category_id': $F('productdetail_category_id')},
		onComplete: function(response){
			//$('Minicart').control.refresh();
            GetMinicart();
		}
	});
}

function GetMinicart()
{
    Client.ajax(url_subapp + '/ajax/GetMinicart', {
        onComplete: function(response){
            $('mini_cart').update(response);
        }
    });
}

function CheckFormSendtofriend()
{
	if(!ValidateForm('frmSendToFriends'))
	{
		return false;
	}
	return true;
}

function CheckRegisterCustomer(id)
{
    HideErrorMessage();
    RemoveHighlight();
    activeEle = 'frm_register_customer';
    if (!ValidateForm('frm_register_customer'))
	{
		return false;
	}
	if (!ValidateCustomerPassword()) return false;
    if(!CheckCustomerEmail(id, $F('register[customer][email]')))
        return false;
	$(id).submit();
}


function ValidateFormChangePassword(id)
{
    activeEle = 'frm_changepass_customer';
    if ($F('curent_password').length < 6)
    {
        HighlightError($('curent_password'), 'Your current password should contain more than 6 characters');
        return false;
    }

    if ($F('password').length < 6)
    {
        HighlightError($('password'), 'Your new password should contain more than 6 characters');
        return false;
    }
    if ($F('repassword').length < 6)
    {
        HighlightError($('repassword'), 'Your new password confirmation should contain more than 6 characters');
        return false;
    }
    if ($F('password') != $F('repassword'))
    {
        HighlightError($('password'), 'The new password confirmation must match your new password!');
        return false;
    }
//    Client.ajax(url_subapp + '/ajax/CheckCustomerPasswd', {
//          method: 'post',
//          messagebox:'ajax_customer_change_pass',
//          parameters: {'customer_id': $F('customer_id'),'password' : $F('curent_password')},
//          onSuccess: function(transport) {
//             var data = transport.responseText;
//             if(data.length == '')
//             {
//                 $('frm_changepass_customer').submit();
//             }
//          }
//    });
    return true;
}

function ValidateCustomerPassword()
{
    if ($F('password').length < 6)
    {
        HighlightError($('password'), 'Your password should contain at least 6 characters');
        return false;
    }
    if ($F('repassword').length < 6)
    {
        HighlightError($('repassword'), 'Your password confirmation should contain more than 6 characters');
        return false;
    }
    if ($F('password') != $F('repassword'))
    {
        HighlightError($('password'), 'The password confirmation must match your password');
        return false;
    }

    return true;
}

function changeShippingBlock(country_id, state_id, postcode_id)
{
    if(country_id =='checkout_address_billing_country_id' && $('same_address2').checked ) return false;
    FadeOut();
    new Ajax.Request(url_subapp + '/ajax/GetShippingBlock', {
          method: 'post',
          parameters: {'country_id': $F(country_id),'state' : $F(state_id),'postalcode' : $F(postcode_id)},
          onSuccess: function(transport) {
             var state = transport.responseText;
             $('shipping_rate_block').update(state);
             setTimeout('FadeIn()', 500);
          }
    });
}

function change_country_shipping(country_id, name, div_state_id, state_id ,postcode_id)
{
    if (country_id != '')
    {
        new Ajax.Request(url_subapp + '/country/LoadState', {
          method: 'post',
          parameters: {'country_id': $F(country_id), 'name':name},
          onSuccess: function(transport) {
              var text = transport.responseText;
              $(div_state_id).update(text);
              $(state_id).observe('change', function(){
                   changeShippingBlock(country_id, state_id, postcode_id);
              });
              changeShippingBlock(country_id, state_id, postcode_id);
          }
        });
    }
}

// FIXME: Violate namming convention
function change_country(country_id, name, div_state_id)
{
    if (country_id != '')
    {
        new Ajax.Request(url_subapp + '/country/LoadState', {
          method: 'post',
          parameters: {'country_id': $F(country_id), 'name':name},
          onSuccess: function(transport) {
              var text = transport.responseText;
              $(div_state_id).update(text);
          }
        });
    }
}

function checkCustomer (cus_email)
{
	new Ajax.Request(url_subapp + '/customer/AjaxCheckCustomer', {
	  method: 'post',
      messagebox:'ajax_login_checkout_error',
	  parameters: {'email': cus_email, 'password': $F('LoginPassword')},
	  onComplete: function(transport) {
	  	var text = transport.responseText;
	  	if (text == '0')
	  	{
            HighlightError($("LoginEmail"), 'Invalid email or password');
			$("LoginEmail").setStyle({color:"#000000", border:'1px solid red'});
			$("LoginEmail").value = cus_email;
            $("LoginEmail").focus();
			$("LoginPassword").value ='';
			$("LoginEmail").enable();
			$("LoginPassword").enable();
	  	}
	  	else
	  	{
            window.location = url_https+'/checkout/';
	  	}
	  }
	});
}
function LoginCheck(id)
{
	activeEle = 'frm_login_checkout';
    var cus_email = $F("LoginEmail");
	if (!ValidateForm(id))
	{
		return false;
	}
	$("LoginEmail").disable();
	$("LoginPassword").disable();
	$("LoginEmail").setStyle("color", "#ff0000");
	$("LoginEmail").value = "Loading ... ";
	if (!checkCustomer(cus_email))
	{
		return false;
	}
	return false;
}

function CustomerLoginByPress(myfield,e)
{
    HideErrorMessage();
    var keycode;
    if (window.event) keycode = window.event.keyCode;
    else if (e) keycode = e.which;

    if (keycode == 13)
    {
        LoginCheck('frm_login_checkout');
        return false;
    }
}
var is_loaded_address = false;
function load_address(id, type)
{
    is_loaded_address = false;
    var aid = '';
    if(id != '')
    {
        aid = $F(id);
        if ($F(id) == '') return false;
    }
	new Ajax.Request(url_subapp + '/ajax/GetAddress', {
	  method: 'post',
	  parameters: {'address_id': aid, 'address_type': type},
	  onSuccess: function(transport) {
	  	var text = transport.responseText;
	  	if (type == 2)
	  	{
	  		$('checkout_billing_address').update(text);
	  	}
	  	else
	  	{
	  		$('checkout_shipping_address').update(text);
	  	}
	  }
	});
	is_loaded_address = true;
	return false;
}

function checkCheckoutForm()
{
    $('btnproceed').disable().setStyle({backgroundColor: '#999', cursor:'default'}).value = "Processing...";
    activeEle = 'checkout_billing_address';
    if (!ValidateForm('checkout_billing_address'))
    {
        enableButton('btnproceed', 'Proceed');
        return false;
    }
    activeEle = 'checkout_shipping_address';
    if ($('same_address2').checked && !ValidateForm('checkout_shipping_address'))
	{
		enableButton('btnproceed', 'Proceed');
        return false;
	}
	if (!CheckCreditCard())
	{
		enableButton('btnproceed', 'Proceed');
        return false;
	}
    $('checkout_orders_comment').value = $('checkout_orders_comment_tmp').value.escapeHTML();
    if (!$F('is_loggedin'))
    {
        activeEle = 'checkout_register';
        if (!ValidateCustomerPassword())
        {
            enableButton('btnproceed', 'Proceed');
            return false;
        }
        Client.ajax(url_subapp + '/ajax/CheckCustomer', {
            method: 'post',
            messagebox: 'ajax_checkout_register',
            parameters: {'email': $F('checkout[email]')},
            onSuccess: function(response) {
                if (response.responseText.length == '')
                {
                    $('checkout_customer_password_temp').value = $('password').value;
                    $('frm_checkout_card').submit();
                }
            }
        });
        enableButton('btnproceed', 'Proceed');
        return false;
    }
    $('frm_checkout_card').submit();
}

function enableButton(id, val)
{
    $(id).enable();
    $('btnproceed').setStyle({backgroundColor: '#000'});
    if(val != '')
        $(id).value = val;
}

function submitCheckoutForm()
{
	$('frm_checkout_card').submit();
}

function changeShipping()
{
    activeEle = 'shipping_rate_block';
    new Ajax.Request(url_subapp + '/cart/SetShippingMehod', {
        method: 'post',
        parameters: {'shipping_method_id': $F('shipping_id')},
        onSuccess: function(transport) {
            var cart_total = transport.responseText.evalJSON();
            if (cart_total.error)
                ShowNoticeMessage(cart_total.message);
            else
            {
                if($('discount') && cart_total.total_discount)
                    $('shiping_discount').update(cart_total.total_discount);
                if($('tax') && cart_total.tax)
                    $('tax').update(cart_total.tax);
                if($('gift') && cart_total.gift)
                    $('gift').update(cart_total.gift);
                $('shiping_cost').update(cart_total.shipping);
                $('grand_total').update(cart_total.grand_total);
            }
        }
    });
}

function change_address()
{
    if( $('shipping_id') ) {
        FadeOut();
        new Ajax.Request(url_subapp + '/ajax/GetBlockAddress', {
            method: 'post',
            parameters: {'shipping_method_id': $F('shipping_id')},
            onSuccess: function(transport) {
                text = transport.responseText;
                $('shipping_rate_block').update(transport.responseText);
                setTimeout('FadeIn()', 500);
            }
        });
    } else if( $('shipping_country')) {
        FadeOut();
        new Ajax.Request(url_subapp + '/ajax/GetShippingBlock', {
            method: 'post',
            parameters: {'country_id': $F('shipping_country'),'state' : $F('shipping_state'),'postalcode' : $F('delivery_postalcode')},
            onSuccess: function(transport) {
                var state = transport.responseText;
                $('shipping_rate_block').update(state);
                setTimeout('FadeIn()', 500);
            }
        });
    }
}

function GetBlockAddress() {

    new Ajax.Request(url_subapp + '/ajax/GetBlockAddress', {
        method: 'post',
        parameters: {'country_id': $F('shipping_country'), 'state' : $F('shipping_state'), 'postalcode' : $F('delivery_postalcode')},
        onSuccess: function(transport) {
            var state = transport.responseText;
            $('ablock_state').update(state);
        }
    });
}

//check credit card
function CheckCreditCard() {
	activeEle = 'checkout_payment_block';
    var gate = $F('checkout[payment_method]');
	if (gate == "2") {
		var regx = /^([a-zA-Z 0-9_.-])+$/;
		var creditOwner = $F('checkout_cc_owner');
		var creditNumber = $F('checkout_cc_number');
		var ownerStatus = regx.test(creditOwner);
		var numberStatus = regx.test(creditNumber);
		if (ownerStatus == false) {
            HighlightError($("checkout_cc_owner"), 'Please enter a valid credit card owner');
			return false;
		} else if (numberStatus == false) {
            HighlightError($("checkout_cc_number"), 'Please enter a valid credit card number!');
			return false;
		}
	}
	if (ValidCreditCard() == false) {
        //HighlightError($("checkout_cc_number"), 'Invalid credit card, please try again!');
		return false;
	}
	return true;
}

function ValidCreditCard() {
	var gate = $F('checkout[payment_method]');
	if (gate == "2") {
		var type = $F("checkout_cc_type");
		type = type.toLowerCase().strip();
		var number = $F("checkout_cc_number");
		number = number.toLowerCase().strip();

		var validCreditCard = CheckCreditCardnumber(number, type);
        if (!validCreditCard)
        {
            HighlightError($("checkout_cc_number"), 'Invalid credit card, please try again!');
            return false;
        }
        if (!CheckExpireDateCard())
        {
            ShowNoticeMessage('Invalid expiration date!');
            return false;
        }
		var cvv = $F("checkout_cc_cvv");
		if (cvv.length == 0) {
            HighlightError($("checkout_cc_cvv"), 'Please fill in cvv!');
			return false;
		} else if (isNaN(cvv) || cvv.length > 5) {
            HighlightError($("checkout_cc_cvv"), 'Cvv number not correct, please try again!');
			return false;
		}
	}
	return true;
}
function CheckCreditCardnumber(cardNumber, cardType) {
  	var isValid = false;
  	var ccCheckRegExp = /[^\d ]/;
  	isValid = !ccCheckRegExp.test(cardNumber);
  	if (isValid) {
   		var cardNumbersOnly = cardNumber.replace(/ /g,"");
    	var cardNumberLength = cardNumbersOnly.length;
    	var lengthIsValid = false;
    	var prefixIsValid = false;
    	var prefixRegExp;

    	switch(cardType) {
      		case "6": //mastercard
        		lengthIsValid = (cardNumberLength == 16);
        		prefixRegExp = /^5[1-5]/;
        		break;
        	case "8": //Discover
        		lengthIsValid = (cardNumberLength == 16);
        		prefixRegExp = /^6[0-5]/;
        		break;
      		case "5": //visa
        		lengthIsValid = (cardNumberLength == 16 || cardNumberLength == 13);
        		prefixRegExp = /^4/;
        		break;
      		case "7": //American Express
        		lengthIsValid = (cardNumberLength == 15);
        		prefixRegExp = /^3(4|7)/;
        		break;
      		default:
        		prefixRegExp = /^$/;
                ShowNoticeMessage('Card type not found');
    	}
    	prefixIsValid = prefixRegExp.test(cardNumbersOnly);
    	isValid = prefixIsValid && lengthIsValid;
  	}

  	if (isValid) {
    	var numberProduct;
    	var numberProductDigitIndex;
    	var checkSumTotal = 0;

    	for (digitCounter = cardNumberLength - 1;
			digitCounter >= 0;
			digitCounter --) {
      		checkSumTotal += parseInt (cardNumbersOnly.charAt(digitCounter));
      		digitCounter --;
      		numberProduct = String((cardNumbersOnly.charAt(digitCounter) * 2));
      		for (var productDigitCounter = 0;
				 productDigitCounter < numberProduct.length;
        		productDigitCounter ++) {
        		checkSumTotal += parseInt(numberProduct.charAt(productDigitCounter));
      		}
    	}
    	isValid = (checkSumTotal % 10 == 0);
  	}

  	return isValid;
}

function CheckExpireDateCard()
{
    var date_card_year = parseInt($F('checkout_creditcard_expdate_year'), 10);
    var date_card_month = parseInt($F('checkout_creditcard_expdate_month'), 10);
    var current_date = new Date();
    var current_year = current_date.getFullYear();
    var current_month = current_date.getMonth() + 1;
    if (date_card_year > current_year)
        return true;
    else if (date_card_year == current_year)
    {
        if(date_card_month >= current_month)
            return true;
    }
    return false;
}

var is_shipping_checked = true;
function ChangeShippingAddress()
{
    if ($('same_address1').checked && is_shipping_checked == true)
    {
        is_shipping_checked = false;
        $('checkout_shipping_address').hide();
        changeShippingBlock('checkout_address_billing_country_id', 'checkout_address_billing_state' ,'BillingPostcode');
    }
    if ($('same_address2').checked &&is_shipping_checked == false)
    {
        is_shipping_checked = true;
        $('checkout_shipping_address').show();
        changeShippingBlock('checkout_address_shipping_country_id', 'checkout_address_shipping_state' ,'ShippingPostcode');
    }
}

function ChangeDefaultAddress(obj)
{
	$('selected_address_id').value= obj.value;
}

function SetDefaultAddress()
{
	HideErrorMessage();
    if ($F('selected_address_id') == '')
	{
        ShowNoticeMessage('Please select an address');
		return false;
	}
	Client.ajax(url_subapp + '/ajax/SetDefaultAddress', {
	  method: 'post',
      messagebox: 'ajax_message',
	  parameters: {'address_id': $F('selected_address_id'), 'address_type': $F('address_type')},
	  onComplete: function(transport) {
	  	var text = transport.responseText;
	  }
	});
}

function DeleteAddress()
{
	HideErrorMessage();
    if ($F('selected_address_id') == '')
	{
        ShowNoticeMessage('Please select an address');
		return false;
	}
	if (confirm('Are you sure?'))
	{
		Client.ajax(url_subapp + '/ajax/DeleteAddressbook', {
		  method: 'post',
		  parameters: {'address_id': $F('selected_address_id'), 'address_type': $F('address_type')},
		  onComplete: function(transport) {
		  	if (transport == '1')
		  	{
				$('address-'+ $F('selected_address_id')).remove();
				$('selected_address_id').value= '';
                ShowNoticeMessage('item(s) have been deleted');
		  	}
            else
                ShowNoticeMessage(transport);
		  }
		});
	}
}

function CheckRegisterCheckout()
{
    if (!ValidateCustomerPassword()) return false;
    $('checkout_password').value= $F('password');
    checkCheckoutForm();
}

function InsertEmail(obj)
{
    $('login_mail_address').update(obj.value);
}

function echeck(str) {

        var at="@"
        var dot="."
        var lat=str.indexOf(at)
        var lstr=str.length
        var ldot=str.indexOf(dot)
        if (str.indexOf(at)==-1){
           alert("Invalid E-mail ID")
           return false
        }

        if (str.indexOf(at)==-1 || str.indexOf(at)==0 || str.indexOf(at)==lstr){
            alert("Invalid e-mail address, please try again")
           return false
        }

        if (str.indexOf(dot)==-1 || str.indexOf(dot)==0 || str.indexOf(dot)==lstr){
            alert("Invalid e-mail address, please try again")
            return false
        }

         if (str.indexOf(at,(lat+1))!=-1){
            alert("Invalid e-mail address, please try again")
            return false
         }

         if (str.substring(lat-1,lat)==dot || str.substring(lat+1,lat+2)==dot){
            alert("Invalid e-mail address, please try again")
            return false
         }

         if (str.indexOf(dot,(lat+2))==-1){
            alert("Invalid e-mail address, please try again")
            return false
         }

         if (str.indexOf(" ")!=-1){
            alert("Invalid e-mail address, please try again")
            return false
         }

          return true
    }


function CheckCustomerEmail(id, email)
{
    Client.ajax(url_subapp + '/ajax/CheckCustomer', {
        method: 'post',
        messagebox: 'ajax_message',
        parameters: {'email': email},
        onComplete: function(response) {
            if (response.length == '')
            {
                $(id).submit();
            }
        }
    });
    return false;
}
function removeAddress(id, type)
{
    var address_selected = $F(id)
    if(address_selected != '' && confirm('Are you sure?'))
    {
        Client.ajax(url_subapp + '/ajax/DeleteAddressbook', {
          method: 'post',
          parameters: {'address_id': address_selected},
          onComplete: function(transport) {
              if (transport == '1')
                {
                    ShowConfirmMessage('item(s) have been deleted');
                    load_address('', type);
                }
                else
                {
                    ShowNoticeMessage(transport);
                }
          }
        });
    }
}

function RefreshShippingRate()
{
    var url = url_subapp + '/cart/RefreshShippingRate';
    Client.ajax(url, {
        onComplete: function(response){
            $('shipping_rate_block').update(response);
        }
    });
}

function ApplyDiscount()
{
    Client.ajax(url_subapp + '/cart/applydiscount', {
      method: 'post',
      messagebox:'ajax_message',
      parameters: {'couponcode': $F('couponcode')},
      onComplete: function(transport) {
        var text = transport.responseText;
        //window.location = window.location.href;RefreshShippingRate
            var url = url_subapp + '/cart/RefreshShippingRate';
            Client.ajax(url, {
                onComplete: function(response){
                    $('shipping_rate_block').update(response);
                }
            });
      }
    });
}

function GetElementPosition(elemID){
    var offsetTrail = document.getElementById(elemID);
    var offsetLeft = 0;
    var offsetTop = 0;
    var offsetHeight = $(elemID).getHeight();
    var offsetWidth = $(elemID).getWidth();
    while (offsetTrail){
    offsetLeft += offsetTrail.offsetLeft;
    offsetTop += offsetTrail.offsetTop;
    offsetTrail = offsetTrail.offsetParent;
    }
    if (navigator.userAgent.indexOf('Mac') != -1 && typeof document.body.leftMargin != 'undefined'){
    offsetLeft += document.body.leftMargin;
    offsetTop += document.body.topMargin;
    offsetHeight += document.body.clientHeight;
    offsetWidth += document.body.clientWidth;
    }
    return {left:offsetLeft,top:offsetTop,height:offsetHeight,width:offsetWidth};
}

/*
function GetAjaxRequest(url, method, params, message)
{
    this.url = url;
    this.method = method;
    this.params = params;
    if(this.url.length > 0) {
        new Ajax.Request(this.url, {
           method: this.method,
           messagebox: message,
           parameters: this.params
           onSuccess: function(response) {
               return response;
           }
        });
    }
    return '';
}
*/

function submitCheckoutOrder(){

  $('frm_checkout_order').submit();
}

function changePayment(obj){
    if(obj.value == 2)
        $('payment_creditcard').show();
    else $('payment_creditcard').hide();
}


function UseGift()
{
    var usegift = $('usegift').value;
    new Ajax.Request(url_subapp + '/checkout/usegift/' + usegift, {
      method: 'get',
      onSuccess: function(transport) {
           var url_shipping = url_subapp + '/cart/RefreshShippingRate';
           var url_discount = url_subapp + '/cart/RefreshDiscountCoupon';
           var url_paymentmethod = url_subapp + '/checkout/RefreshPaymentmethod';
           Client.ajax(url_shipping, {onComplete: function(response){$('shipping_rate_block').update(response);}});
           Client.ajax(url_discount, {onComplete: function(response){$('apply_discount_block').update(response);}});
           if($('checkout_payment_block'))
                Client.ajax(url_paymentmethod, {onComplete: function(response){$('checkout_payment_block').update(response);}});
      }
    });
}
