/**
 * Create namespace
 */
if (!JS.Components) {
	JS.Components = {};
}

/**
 * Components:
 *		EmptyInput	- allows to have 'default value' for input if it's empty
 *		Overlay		- overlay, which is below modal box, but above content
 * 		Panel		- modal box
 * 		Slider		- component to slide in/slide out list of items in and out of the view
 * 		Accordion	- open and close items
 */


/**
 * Empty input behaviour. If inputs value is empty, then it's poopulated with default value on blur event.
 * If on focus event inputs value is default, then value is removed
 *  
 * @param {HTMLNode} element
 * @param {Object} config
 */
JS.Components.EmptyInput = function (input, config) {
	this.element = JS.Dom.get(input);
	if (!this.element) return; //exit if input doesn't exist
	
	//Set configuration
	this.config = {
		'default_value': this.element.value,	//Default value
		'class_name': 'empty',					//Class name which will be assigned to
												//the element when default value is set.
		'clear_on_submit': false				//Remove default form value if present on parent form submit event
	};
	
	if (config) {
		this.config = JS.extend(this.config, config);
	}
	
	//Assign event handlers
	var self = this;
	
	JS.Event.addListener(this.element, 'focus', function () {
		self.onFocusEvent();
	});
	JS.Event.addListener(this.element, 'blur', function () {
		self.onBlurEvent();
	});
	
	//Find form
	if (this.config.clear_on_submit) {
		var node_form = JS.Dom.getAncestorByTagName('form', this.element);
		
		if (node_form) {
			//Attach to submit event
			JS.Event.addListener(node_form, 'submit', function () {
				var v = self.element.value;
					v = v.replace(/^\s+|\s+$/g, '');
					
				if (v == self.config.default_value) {
					self.element.value = '';
				}
			});
		}
	}
	
	//Initial check
	this.onBlurEvent();
};

//Element
JS.Components.EmptyInput.prototype.element = null;

//Configuration
JS.Components.EmptyInput.prototype.config = {};

//Input lost focus, check if input is not empty or if it has default value
JS.Components.EmptyInput.prototype.onBlurEvent = function () {
	var v = this.element.value;
		v = v.replace(/^\s+|\s+$/g, '');
		
	if (v == this.config.default_value || v == '') {
		this.element.value = this.config.default_value;
		JS.Dom.addClassName(this.element, this.config.class_name);
	}
};

//Input was focused, replace default value with empty string if needed and
//remove class_name
JS.Components.EmptyInput.prototype.onFocusEvent = function () {
	var v = this.element.value;
		v = v.replace(/^\s+|\s+$/g, '');
		
	if (v == this.config.default_value) {
		this.element.value = '';
	}
	
	JS.Dom.removeClassName(this.element, this.config.class_name);
};




/**
 * Page overlay
 */
JS.Components.Overlay = function (config) {
	if (!config) config = {};
	
	this.element = document.createElement('DIV');
	document.body.insertBefore(this.element, document.body.firstChild);
	//document.body.appendChild(this.element);
		
	JS.Dom.addClassName(this.element, (config.className ? config.className : 'component-overlay'));
	
	if (!config.visible) this.hide();
};

//Overlay element
JS.Components.Overlay.prototype.element = null;

/**
 * Show overlay
 */
JS.Components.Overlay.prototype.show = function () {
	if (this.element) {
		this.element.style.display = 'block';
	}
};

/**
 * Hide overlay
 */
JS.Components.Overlay.prototype.hide = function () {
	if (this.element) {
		this.element.style.display = 'none';
	}
};


/**
 * Panel
 * 
 * Configuration properties
 * 		className		class name which will be attached to the panel
 * 		fixedCenter		Panel is fixed to the center
 */
JS.Components.Panel = function (element, config) {
	//Set config
	if (!JS.Dom.get(element)) return;
	if (!config) config = {};

	//Set configuration
	this.config = JS.extend({
			//Properties which can be overwriten
			className: 'component-panel',
			fixedCenter: false,
			
			left_offset: 0,
			top_offset: 0,
			
			cssZIndex: 10,
			
			overlay: true
		}, config, {
			//Properties which can't be overwriten
			visible: true	//value is true, because .hide() function otherwise will fail 
		});
		
	
	//Create html
	this._createHtml(JS.Dom.get(element));
	
	//Create overlay
	if (this.config.overlay) {
		this.overlay = new JS.Components.Overlay();
	}
	//this.element.parentNode.insertBefore(this.overlay.element, this.element);

	//Set style
	if (this.config.cssZIndex) {
		if (this.config.overlay) {
			this.overlay.element.style.zIndex = this.config.cssZIndex;
		}
		this.element.style.zIndex = this.config.cssZIndex+1;
	}
	
	//Hide
	this.hide();
	
	//Reset panel position
	this.resetPosition();
	
};

JS.Components.Panel.prototype._createHtml = function (inner) {
	inner.style.display = 'block';
	
	var pos = JS.Dom.getPosition(inner);
	
	var html = '<table><tr><td class="p-lt"><span><i></i></span></td><td class="p-t"></td><td class="p-rt"><span><i></i></span></td></tr>';
		html+= '<tr><td class="p-l"></td><td class="p-c"></td><td class="p-r"></td></tr>';
		html+= '<tr><td class="p-lb"><span><i></i></span></td><td class="p-b"></td><td class="p-rb"><span><i></i></span></td></tr></table>';
	
	//Create HTML and insert inner into the td.p-c
	var container = document.createElement('DIV');
	container.style.display = 'none';
	container.innerHTML = html;
	container.className = this.config.className;
	document.body.insertBefore(container, document.body.firstChild);
	
	container.getElementsByTagName('TD')[4].appendChild(inner);
	
	//Add listener to the close button
	var self = this;
	JS.Event.addListener(container.getElementsByTagName('I')[1], 'click', function () {
		self.hide();
	});
	
	JS.Event.addListener(window, 'resize', function () {
		self.resetPosition();
	});
	
	this.element = container;
	this.element.style.left = pos.left + this.config.left_offset + 'px';
	this.element.style.top = pos.top + this.config.top_offset + 'px';
};

//Element
JS.Components.Panel.prototype.element = null;

//Overlay
JS.Components.Panel.prototype.overlay = null;

//Configuration
JS.Components.Panel.prototype.config = null;

/**
 * Recalculate panel position
 */
JS.Components.Panel.prototype.resetPosition = function () {
	if (!this.config.fixedCenter) return false;
	
	var pos = JS.Dom.getViewportPosition();
	var w = parseInt(this.element.offsetWidth);
	var h = parseInt(this.element.offsetHeight);
	
	var p_x = Math.floor((pos.width - w) / 2 + pos.left);
	var p_y = Math.floor((pos.height - h) / 2 + pos.top);
	
	if (p_y < 0) p_y = 0;
	
	this.element.style.left = p_x + 'px';
	this.element.style.top = p_y + 'px';
};

/**
 * Show panel
 */
JS.Components.Panel.prototype.show = function () {
	if (this.config.visible) return;
	
	this.element.style.display = 'block';
	
	if (this.config.overlay) {
		this.overlay.show();
	}
	
	this.config.visible = true;
	
	this.resetPosition();
};

/**
 * Hide panel
 */
JS.Components.Panel.prototype.hide = function () {
	if (!this.config.visible) return;
	
	this.element.style.display = 'none';
	
	if (this.config.overlay) {
		this.overlay.hide();
	}
	
	this.config.visible = false;	
};




/**
 * Slider
 */
JS.Components.Slider = function (config) {
	/* Configuration */
		if (!config) return;
		
		this.config = JS.extend({
			movable: null,				//Movable element
			item_tagName: 'LI',			//Item tag name
			items_per_view: 3,			//Items fitting into the view
			
			sliderIndex: 0,			
			positions: [0],				//Position of the movable to make each item appear as first
			
			nav_next: null,				//Next navigation link
			nav_prev: null,				//Previous navigation link
			
			animation_speed: 400		//Animation speed
		}, config);
		
		this.config.movable = JS.Dom.get(this.config.movable);
		this.config.nav_next = JS.Dom.get(this.config.nav_next);
		this.config.nav_prev = JS.Dom.get(this.config.nav_prev);
		
		if (!this.config.movable) {
			return null;
		}
	
	/* Get widths */
		var items = this.config.movable.getElementsByTagName(this.config.item_tagName);
		var p = 0;
		this.items = items;
	
		for(var i=0,j=items.length; i<j; i++) {
			if (!this.config.positions[i]) {
				this.config.positions[i] = p;
			}
			
			p -= parseInt(items[i].offsetWidth);
		}
		
	/* Assign events */
		var self = this;
		
		if (this.config.nav_next) {
			JS.Event.addListener(this.config.nav_next, 'click', function (ev) {
				self.slideForward();
				JS.Event.stopEvent(ev);
			});
			JS.Event.addListener(this.config.nav_next, 'mousedown', JS.Event.stopEvent);
		}
		
		if (this.config.nav_prev) {
			JS.Event.addListener(this.config.nav_prev, 'click', function (ev) {
				self.slideBackward();
				JS.Event.stopEvent(ev);
			});
			JS.Event.addListener(this.config.nav_prev, 'mousedown', JS.Event.stopEvent);
		}
		
	/* Show/hide navigation links */
		this.resetNavigation();
};

//Configuration
JS.Components.Slider.prototype.config = null;

//Create transition between elements
JS.Components.Slider.prototype.slide = function (to) {
	if (to >= this.config.positions.length - this.config.items_per_view) to = this.config.positions.length - this.config.items_per_view;
	if (to < 0) to = 0;
	
	var from = parseInt(this.config.movable.style.marginLeft);
	if (!from) from = 0;
	
	var anim = new JS.Anim(this.config.movable, {
		from: {marginLeft: from + 'px'},
		to: {marginLeft: this.config.positions[to] + 'px'},
		transition: JS.AnimHelpers.Transitions.Sinoid,
		speed: this.config.animation_speed
	});
	
	this.config.sliderIndex = to;
	this.resetNavigation();
	anim.start();
};

//Create transition between elements
JS.Components.Slider.prototype.moveTo = function (to) {
	if (to >= this.config.positions.length - this.config.items_per_view) to = this.config.positions.length - this.config.items_per_view;
	if (to < 0) to = 0;
	
	this.config.movable.style.marginLeft = this.config.positions[to] + 'px';
	this.config.sliderIndex = to;
	this.resetNavigation();
};

JS.Components.Slider.prototype.resetNavigation = function () {
	var n = this.config.sliderIndex;
	
	if (n >= this.config.positions.length - this.config.items_per_view) {
		JS.Dom.addClassName(this.config.nav_next, 'disabled');
	} else {
		JS.Dom.removeClassName(this.config.nav_next, 'disabled');
	}
	
	if (n == 0) {
		JS.Dom.addClassName(this.config.nav_prev, 'disabled');
	} else {
		JS.Dom.removeClassName(this.config.nav_prev, 'disabled');
	}
};

//Slide to next
JS.Components.Slider.prototype.slideForward = function () {
	var n = this.config.sliderIndex + 1;
	if (n <= this.config.positions.length - this.config.items_per_view) {
		this.slide(n);
	}
};

//Slide to next
JS.Components.Slider.prototype.slideBackward = function () {
	var n = this.config.sliderIndex - 1;
	if (n >= 0) {
		this.slide(n);
	}
};


/**
 * Slider with timer
 */
JS.Components.SliderTimer = function (config) {
	if (!config) return
	JS.Components.Slider.apply(this, arguments);
	
	if (!this.config.timerInterval) {
		this.config.timerInterval = 4000;
	} else {
		this.config.timerInterval = parseInt(this.config.timerInterval);
		if (this.config.timerInterval <= 0) this.config.timerInterval = 4000;
	}
	
	if (!('repeat_from_first' in this.config)) {
		this.config.repeat_from_first = false;
	}
	
	if (this.config.repeat_from_first && this.items.length > 1) {
		var ind = this.items.length;
		this.items[ind] = this.items[0].cloneNode(true);
		this.items[0].parentNode.appendChild(this.items[ind]);
		
		this.config.positions[ind] = this.config.positions[ind-1] - this.items[ind-1].offsetWidth;
	}
	
	this.config.direction = 1;
	
	var self = this;
	this.config.timer = setInterval(function () { self.slideTimer(); }, this.config.timerInterval);
};

JS.extend(JS.Components.SliderTimer.prototype, JS.Components.Slider.prototype);

JS.Components.SliderTimer.prototype.slide = JS.Components.Slider.prototype.slide;
JS.Components.SliderTimer.prototype.slideBackward_ = JS.Components.Slider.prototype.slideBackward;
JS.Components.SliderTimer.prototype.slideForward_ = JS.Components.Slider.prototype.slideForward;

JS.Components.SliderTimer.prototype.slideBackward = function () {
	if (this.config.timer) clearInterval(this.config.timer);
	this.slideBackward_();
};

JS.Components.SliderTimer.prototype.slideForward = function () {
	if (this.config.timer) clearInterval(this.config.timer);
	this.slideForward_();
};

JS.Components.SliderTimer.prototype.slideTimer = function () {
	var n = this.config.sliderIndex;
	
	if (n >= this.config.positions.length - this.config.items_per_view) {
		if (this.config.repeat_from_first) {
			this.moveTo(0);
			this.config.sliderIndex = 0;
		} else {
			this.config.direction = -1;
		}
	} else if (n == 0) {
		this.config.direction = 1;
	}
	
	if (this.config.direction == 1) {
		this.slideForward_();
	} else {
		this.slideBackward_();
	}
};



/**
 * Accordion component (collapse/expand items on trigger click)
 * 
 * Items is an array of Object {trigger: HTMLNode, item: HTLMNode[, container: HTMLNode]}
 * Configuration options:
 * 		classNameOpen
 * 		classNameClosed
 * 		visibleOne
 * 		triggerEvent
 */
JS.Components.Accordion = function (items, config) {
	var self = this;
	
	//Set configuration
		this.config = JS.extend({
			classNameOpen: 'box',	//Adds classNameOpen class to the element when item is open
			classNameClosed: '',	//Adds classNameClosed class to the element when item is closed
			visibleOne: true,		//Only one item may be visible at a time
			triggerEvent: 'click',	//Event which will trigger collapse/expand
			preventDefault: true	//Prevent default behaviour when clicking on items
		}, config, {
			openedItemIndex: null	//Index of the item, which is open 
		});
	
	//Event handling functions, needed to maintain 'this' keyword reference
		this.functions = {
			toggleItem: function (ev) {
				self.toggleItem(this.accordion_index);
				
				if (self.config.preventDefault) {
					JS.Event.stopEvent(ev);
				}
			},
			changeClassNameToClosed: function (ev) {
				self.setClassName(ev.target.node.accordion_index, 0);
			},
			clearHeight: function (ev) {
				self.items[ev.target.node.accordion_index].item.style.height = 'auto';
			}
		};
	
	//Set items
		this.items = items;			//Items must be array of Object {trigger: ..., item: ...}
		
		//Go through items, add missing properties and get height of the items
		for(var i=0,j=this.items.length; i<j; i++) {
			this.items[i].state = 0;
			this.items[i].height = [0,0];
			this.items[i].anim = null;
			this.items[i].container = (this.items[i].container ? this.items[i].container : this.items[i].item);
			
			if ((this.config.classNameOpen && JS.Dom.hasClassName(this.items[i].container, this.config.classNameOpen)) ||
				(this.config.classNameClosed && !JS.Dom.hasClassName(this.items[i].container, this.config.classNameClosed)))
			{
				this.items[i].state = 1;
				this.items[i].height[1] = this.items[i].item.offsetHeight;	//Item is open, get open state height
			} else {
				this.items[i].height[0] = this.items[i].item.offsetHeight;	//Item is closed, get closed state height
			}
			
			var reverse_state = this.items[i].state ? 0 : 1;
			
			//Change state (if was open, then close and if closed, then open) and get height
			this.setClassName(i, reverse_state);	
			this.items[i].height[reverse_state] = this.items[i].item.offsetHeight;
			
			if (this.config.visibleOne) {
				if (this.config.openedItemIndex === null && this.items[i].state) {
					//Restore original state and set this item as opened
					this.setClassName(i, this.items[i].state);
					this.config.openedItemIndex = i;
				} else if (this.items[i].state) {
					//Change state to closed, since one item already open
					this.items[i].state = 0;
				} else {
					//Restore original state class names
					this.setClassName(i, this.items[i].state);
				}
			} else {
				//Restore original state
				this.setClassName(i, this.items[i].state);
			}
			
			//Bind event
			this.items[i].trigger.accordion_index = i;
			this.items[i].item.accordion_index = i;
			JS.Event.addListener(this.items[i].trigger, this.config.triggerEvent, this.functions.toggleItem);
		}
};

//Configuration
JS.Components.Accordion.prototype.config = {};

//Items
JS.Components.Accordion.prototype.items = {};

//Event handling functions
JS.Components.Accordion.prototype.functions = {};

/**
 * Slide up item (close)
 * 
 * @param {Object} item_index
 */
JS.Components.Accordion.prototype.slideUpItem = function (item_index) {
	//Don't need to do anything if item is already closed
	if (!this.items[item_index].state) return;
	
	//Stop current animation
	if (this.items[item_index].anim) this.items[item_index].anim.stop();
	
	//Animate
	this.items[item_index].anim = new JS.Anim(this.items[item_index].item, {
												from: {height: this.getItemHeight(item_index, 1) + 'px'},
												to: {height: this.getItemHeight(item_index, 0) + 'px'},
												transition: JS.AnimHelpers.Transitions.Sinoid,
												speed: 300
											});
	
	//Need to change classes after animation completes, this will look nicer
	this.items[item_index].anim.config.event.addListener('onComplete', this.functions.changeClassNameToClosed);
	this.items[item_index].anim.start();
	
	this.items[item_index].state = 0;
	
	//Clear opened item index if it's this item
	if (this.config.openedItemIndex == item_index) {
		this.config.openedItemIndex = null;
	}
};

/**
 * Slide down item (open)
 * 
 * @param {Object} item_index
 */
JS.Components.Accordion.prototype.slideDownItem = function (item_index) {
	//Don't need to do anything if item is already open
	if (this.items[item_index].state) return;
	
	//Close opened item if needed 
	if (this.config.visibleOne && this.config.openedItemIndex !== null) {
		this.slideUpItem(this.config.openedItemIndex);
	}
	
	//Stop current animation
	if (this.items[item_index].anim) this.items[item_index].anim.stop();
	
	//Animate
	this.items[item_index].anim = new JS.Anim(this.items[item_index].item, {
												from: {height: this.getItemHeight(item_index, 0) + 'px'},
												to: {height: this.getItemHeight(item_index, 1) + 'px'},
												transition: JS.AnimHelpers.Transitions.Sinoid,
												speed: 300
											});
	
	//Setting initial height will prevent content from beeing open for few milliseconds
	this.items[item_index].item.style.height = this.getItemHeight(item_index, 0) + 'px';
	
	this.items[item_index].anim.config.event.addListener('onComplete', this.functions.clearHeight);
	this.items[item_index].anim.start();
	
	this.setClassName(item_index, 1);
	this.items[item_index].state = 1;
	
	this.config.openedItemIndex = item_index;
};

/**
 * Toggle item state
 * 
 * @param {Object} item_index
 */
JS.Components.Accordion.prototype.toggleItem = function (item_index) {
	//Call slide function
	if (this.items[item_index].state) {
		this.slideUpItem(item_index);
	} else {
		this.slideDownItem(item_index);
	}
};

/**
 * Returns height of the item for given state
 * 
 * @param {Object} item_index
 * @param {Object} state		Optional argument, if not specified, then items current state will be used
 */
JS.Components.Accordion.prototype.getItemHeight = function (item_index, state) {
	if (state === undefined || state === null) state = this.items[item_index].state;
	return this.items[item_index].height[state];
};


//Set item height
JS.Components.Accordion.prototype.setItemHeight = function (item_index, state, height) {
	if (item_index >=0 && this.items.length > item_index) {
		this.items[item_index].height[state] = height;
	}
};

/**
 * Set appropriate classname to the item depending on state
 * 
 * @param {Numeric} item_index
 * @param {Object} state
 */
JS.Components.Accordion.prototype.setClassName = function (item_index, state) {
	if (state) {
		if (this.config.classNameOpen) JS.Dom.addClassName(this.items[item_index].container, this.config.classNameOpen);
		if (this.config.classNameClosed) JS.Dom.removeClassName(this.items[item_index].container, this.config.classNameClosed);
	} else {
		if (this.config.classNameOpen) JS.Dom.removeClassName(this.items[item_index].container, this.config.classNameOpen);
		if (this.config.classNameClosed) JS.Dom.addClassName(this.items[item_index].container, this.config.classNameClosed);
	}
};



/**
 * Tabs
 * 
 * Items is an array of Object {trigger: HTMLNode, item: HTLMNode}
 */
JS.Components.Tabs = function (items, config) {
	//Set configuration
		if (!JS.Object.isObject(config)) config = {};
		
		this.config = JS.extend({
			triggerClassActive: '',				//Class name for active tab trigger
			triggerClassInactive: '',			//Class name for inactive tab trigger
			itemClassActive: '',				//Class name for active tab item
			itemClassInactive: '',				//Class name for inactive tab item
			activeTabIndex: null,				//Active tab index
			triggerEvent: 'click'				//Trigger event
		}, config);
	
	//Functions
		var self = this;
		this.functions = {
			openTab: function (ev) { self.openTab(this.tabIndex); JS.Event.stopEvent(ev); }
		};
		
	//Set event
		this.event = new JS.Event.CustomEvent();
	
	//Set items
		var activeTabIndex = null;
		this.items = [];
		
		if (JS.Object.isArray(items)) {
			for(var i=0,j=items.length; i<j; i++) {
				var index = this.items.length;
				var item = JS.Dom.get(items[i].item);
				var trigger = JS.Dom.get(items[i].trigger);
				
				if (trigger && item) {
					//Add item to the list					
					trigger.tabIndex = index;
					this.items.push({
						item: item,
						trigger: trigger,
						status: false,
						index: index
					});
					
					if (i === this.config.activeTabIndex) {
						activeTabIndex = i;
					}
					
					//Bind event handlers
					JS.Event.addListener(trigger, this.config.triggerEvent, this.functions.openTab);
				}
			}
		}
		
		if (!activeTabIndex) activeTabIndex = 0;
		
		for(var i=0,j=this.items.length; i<j; i++) {
			if (activeTabIndex != i) {
				this.items[i].status = true;
				this.closeTab(i);
			} else {
				this.items[i].status = false;
				this.openTab(i);
			}
		}

		
};

//Configuration
JS.Components.Tabs.prototype.config = null;

//Event
JS.Components.Tabs.prototype.event = null;

//Item list
JS.Components.Tabs.prototype.items = null;

//Functions
JS.Components.Tabs.prototype.functions = null;

/**
 * Open tab
 * @param {Numeric} tab_index
 */
JS.Components.Tabs.prototype.openTab = function (tab_index) {
	if (tab_index === null || !this.items[tab_index] || this.items[tab_index].status) return;
	
	//Close opened tab
	if (this.config.activeTabIndex !== null) this.closeTab(this.config.activeTabIndex);
	
	//Remove class names which are for inactive tabs
	if (this.config.itemClassInactive) JS.Dom.removeClassName(this.items[tab_index].item, this.config.itemClassInactive);
	if (this.config.triggerClassInactive) JS.Dom.removeClassName(this.items[tab_index].trigger, this.config.triggerClassInactive);
	
	//Add class names which are for active tabs
	if (this.config.itemClassActive) JS.Dom.addClassName(this.items[tab_index].item, this.config.itemClassActive);
	if (this.config.triggerClassActive) JS.Dom.addClassName(this.items[tab_index].trigger, this.config.triggerClassActive);
	
	this.items[tab_index].status = true;
	this.config.activeTabIndex = tab_index;
	
	//Fire event
	this.event.fire('tabSelect', this.items[tab_index]);
};

/**
 * Close tab
 * @param {Numeric} tab_index
 */
JS.Components.Tabs.prototype.closeTab = function (tab_index) {
	if (tab_index === undefined || tab_index === null) tab_index = this.config.activeTabIndex;
	if (tab_index === null || !this.items[tab_index] || !this.items[tab_index].status) return;
	
	if (this.config.itemClassActive) JS.Dom.removeClassName(this.items[tab_index].item, this.config.itemClassActive);
	if (this.config.triggerClassActive) JS.Dom.removeClassName(this.items[tab_index].trigger, this.config.triggerClassActive);
	
	if (this.config.itemClassInactive) JS.Dom.addClassName(this.items[tab_index].item, this.config.itemClassInactive);
	if (this.config.triggerClassInactive) JS.Dom.addClassName(this.items[tab_index].trigger, this.config.triggerClassInactive);
	
	this.items[tab_index].status = false;
	
	if (tab_index === this.config.activeTabIndex) {
		this.config.activeTabIndex = null;
	}
	
	//Fire event
	this.event.fire('tabDeselect', this.items[tab_index]);
}


/**
 * Lightbox for html content
 */
JS.Components.LightboxHtml = function (config, links) {
	var self = this;
	
	if (!config) config = {};
	
	//Get links 
	if (!links) {
		var links = [];
		var a = document.getElementsByTagName('A');
		for(var i=0,j=a.length; i<j; i++) {
			if (a[i].rel && a[i].rel == 'lightbox[html]') {
				links.push(a[i]);
			}
		}
	}
	
	//Link click event
	var func_on_link_click = function (ev) {
		if (this.lightboxHtmlIndex === undefined || this.lightboxHtmlIndex === null) return;
		self.showHtmlContent(this.lightboxHtmlIndex);
		
		JS.Event.stopEvent(ev);
		return false;
	};
	
	//Set links
	this.links = [];
	for(var i=0,j=links.length; i<j; i++) {
		var link = JS.Dom.get(links[i]);
		if (link) {
			var link_index = this.links.length;
			
			//Remove rel
			link.rel = '';
			
			this.links.push(link);
			link.lightboxHtmlIndex = link_index;
				
			//Attach to link
			JS.Event.addListener(link, 'click', func_on_link_click);
		}
	}
	
	//Set config
	this.config = JS.extend({
		escape_html: false
	}, config);
	
	//Create htnk
	this.createHtml();
	this.panel = new JS.Components.Panel(this.config.container, {
		fixedCenter: true,
		cssZIndex: 40
	});
};

JS.Components.LightboxHtml.prototype.links = '';
JS.Components.LightboxHtml.prototype.config = {};
JS.Components.LightboxHtml.prototype.panel = null;
JS.Components.LightboxHtml.prototype.ajaxCache = {};

//Create html container nodes
JS.Components.LightboxHtml.prototype.createHtml = function () {
	var d = document.createElement('DIV');
		document.body.appendChild(d);
		JS.Dom.addClassName(d, 'text');
		JS.Dom.addClassName(d, 'lightbox-text');
		
	this.config.container = d;
};

//Show html content
JS.Components.LightboxHtml.prototype.showHtmlContent = function (linkIndex) {
	var link = this.links[linkIndex];
	if (link) {
		this.panel.show();
		this.populateContent('<div style="text-align: center; height: 400px;"><img src="/img/ajax-loader.gif" style="float: none; margin-top: 184px;" alt="" /></div>');
		this.loadContent(link.href);
	}
};

JS.Components.LightboxHtml.prototype.populateContent = function (html) {
	//Escape html
	if (this.config.escape_html) {
		html = html.replace(/\</g, '&lt;')
			   	   .replace(/\>/g, '&gt;')
			   	   .replace(/\"/g, '&quot;')
			   	   .replace(/\'/g, '&#039;')
			   	   .replace(/\'/g, '&#039;')
				   .replace(/\&/g, '&amp;');
	}
	
	this.config.container.innerHTML = html;
	this.panel.resetPosition();
};

JS.Components.LightboxHtml.prototype.loadContent = function (url) {
	var self = this;
	var url = url;
	
	if (this.ajaxCache[url])
	{
		this.populateContent(this.ajaxCache[url]);
	}
	else
	{
		JS.Ajax.get(url, {}, function (status, data) {
			if (status) {
				self.ajaxCache[url] = data;
				self.populateContent(data);
			} else {
				self.panel.hide();
			}
		}, {mode: 'html'});
	}
};