/**
 * rSelect
 *
 * @version 1.6
 * @author Ryan Brill
 *
 * @requires prototype.js
 * @requires prototype_ss.js
 * @requires DOM.js
 * @requires EventSelectors.js
 **/

var rSelectClass = Class.create();
rSelectClass.prototype = {

	//Constructor
	initialize: function(el, s) {
		this.items = [];									// array of list items
		this.el = el;										// <select class="rSelect">
		this.label = document.createElement('div');			// the label of our dropdown
		this.labelText = document.createElement('span');	// the text node inside our label
		this.container = document.createElement('div');		// the container element
		this.ulcontainer = document.createElement('div');	// Generated UL mirroring the <select> box
		this.imask = document.createElement('iframe');		// iframe fix for IE
		this.actualCols = 0;								// Actual number of columns that get created
		this.ulInit = false;								// Keeps track of if ul is initialized
		this.s = {
			fixedWidth: true,					// set the width to the size of the original <select> box
			className: 'rSelectBox',			// Class name to apply to the <div> tag
			selectedClass: 'selected',			// Class name for the seleted item in the select box
			hoverClass: 'hover',				// Class name for the hover of the items in the list
			toggleClass: 'toggle',				// Class name for the toggle all items in the list
			isMultiSelect: false,				// whether or not this is a multiple select box. It will look for the attribute multiple="multiple" on the select box
			defaultLabel: 'No Values Selected',	// Default value for when no options are selected in a multi-select box
			pxPerChar: 8,						// Number of pixels to allow for each character in the label
			maxHeight: 300,						// Maximum height of the dropdown for multi selects
			maxCols: 1,							// Maximum number of columns - will be fewer colums if fewer fit in maxHeight
			pxPerRow: 22,						// Number of pixels to allow for each row
			processed: 'rSelectReplaced',        // Flag to tell whether a select has been processed yet
			width: Element.getDimensions(this.el).width
			
		};
		for (var key in s) {
			this.s[key] = s[key];
		}
		
		if(this.el.hasClassName(this.s.processed)) {
			return 0;
		}
		Element.addClassName(this.el, this.s.processed);
		
		var multi = (this.el.attributes['multiple']) ? this.el.attributes['multiple'].value : this.el.getAttribute('multiple');
		if (multi && (multi.toLowerCase() == "multiple" || multi.toLowerCase() == "true")){
			this.s.isMultiSelect = true;
		}
		
		Element.addClassName(this.container, this.s.className);
		if(this.el.className != ''){
			Element.addClassName(this.container, this.el.className);
		}
		
		/* Event observers */
		Event.observe(this.label, 'click', this.clickLabel.bind(this));
		
		this.createContainer();
		Element.hide(this.el);
	},
	
	
	//Methods
	findElements: function() {
		var alleles = this.el.childNodes;
		var eles = new Array();
		var totalEles = 0;
		var makeSelected = false;
		var currentRow = 0;
		var ul = document.createElement('ul');
		
		// add top level <option> and <optgroups> to eles, and count all rows (totalEles) that will get outputted
		for (var i=0; i<alleles.length; i++) {
			switch (String(alleles[i].tagName).toLowerCase()) {
				case 'optgroup':
					eles.push(alleles[i]);
					var opts = alleles[i].getElementsByTagName('option');
					if (alleles[i].label) {
						totalEles++;
					}
					totalEles = totalEles + opts.length;
				case 'option':
					if (alleles[i].childNodes.length == 1) {
						eles.push(alleles[i]);
						totalEles++;
					}
			}
		}
		
		// Check how many rows we are expecting
		var expectedCols = (Math.ceil(totalEles * this.s.pxPerRow / this.s.maxHeight) > this.s.maxCols ? this.s.maxCols : Math.ceil(totalEles * this.s.pxPerRow / this.s.maxHeight));
		
		for (var i=0; i<eles.length; i++) {
			
			// Close our current UL and start a new one
			if (currentRow > Math.ceil(totalEles / expectedCols) - 1) {
				Element.addClassName(ul, 'col');
				this.ulcontainer.appendChild(ul);
				ul = document.createElement('ul');
				currentRow = 0;
				this.actualCols++;
			}	
				
			// Fix disabled options in IE
			if(eles[i].selected && eles[i].disabled){
				makeSelected = true;
			}
			if(makeSelected && !eles[i].disabled && String(eles[i].tagName).toLowerCase() == "option"){
				makeSelected = false;
				eles[i].selected = true;
			}
			
			switch (String(eles[i].tagName).toLowerCase()) {
				case 'optgroup':
					var li = document.createElement('li');
					var optgroupUl = document.createElement('ul');
					
					if (eles[i].label) {
						Element.addClassName(li, 'optlabel');
						if (eles[i].disabled) {
							Element.addClassName(li, 'disabled');
							Element.addClassName(optgroupUl, 'disabled');
						}
						li.innerHTML = eles[i].label;
						ul.appendChild(li);
						currentRow++;
					}
					
					var opts = eles[i].getElementsByTagName('option');
					currentRow = currentRow + opts.length;

					for (var j=0; j<opts.length; j++) {
						// Fix disabled options in IE
						if(opts[j].selected && (eles[i].disabled || opts[j].disabled)){
							makeSelected = true;
						}
						if(makeSelected && !eles[i].disabled && !opts[j].disabled){
							makeSelected = false;
							opts[j].selected = true;
						}
						
						this.createElement(opts[j], eles[i].disabled, optgroupUl);
					}
					ul.appendChild(optgroupUl);
					break;
				case 'option':
					if (eles[i].childNodes.length == 1) {
						this.createElement(eles[i], eles[i].disabled, ul);
						currentRow++;
					}
					break;
			}
		}
		this.actualCols++;
		if (this.actualCols > 1) {
			Element.addClassName(ul, 'col');
		}
		this.ulcontainer.appendChild(ul);
		
	},
	createElement: function(el, state, parent) {
		// Fix disabled options in IE
		var elSelected = (el.selected && (!el.disabled && (!el.parentNode || !el.parentNode.disabled))) ? true : false;
		
		var itemvar = {};
		itemvar.value = el.value;
		itemvar.el = el;
		itemvar.selected = elSelected;
		
		itemvar.disabled = (el.disabled || el.parentNode.disabled) ? true : false;
		itemvar.text = el.text;
		itemvar.li = document.createElement('li');
		if(itemvar.el.className != ''){
			Element.addClassName(itemvar.li, itemvar.el.className);
		}
		if (state == true) {
			itemvar.li.innerHTML = el.text;
			Element.addClassName(itemvar.li, 'disabled');
		}
		else {
			itemvar.a = document.createElement('a');
			itemvar.a.href = 'javascript:void(0);';
			itemvar.text = el.text;
			if(this.s.isMultiSelect){
				itemvar.a.innerHTML = '<input type="checkbox" ' + ((itemvar.selected)? ' checked="checked"' : '' ) + '> ' + el.text;
			}else{
				itemvar.a.innerHTML = el.text;
			}
			itemvar.li.appendChild(itemvar.a);
		}
		parent.appendChild(itemvar.li);
		this.items.push(itemvar);
		if (elSelected) { // create our label element
			//this.setLabel(el.text);
		}

	},
	
	createContainer: function(){
		Element.addClassName(this.label, 'label');
		
		var icon = document.createElement('div');
		Element.addClassName(icon, 'icon');
		icon.appendChild(this.labelText);
		this.label.appendChild(icon);
		this.container.appendChild(this.label);
		
		// container width
		if (this.s.fixedWidth == true && this.s.width) {
			this.container.style.width = this.s.width + 'px'; // set the width of the original <select>
		}
		
		Element.insert(this.el, {after: this.container});
		
		var text = [];
		var opts = this.el.getElementsByTagName('option');
		if(opts[0].selected)
		{
			text =opts[0].text;
		}
		else
		{
			for(var i=0, final=opts.length; i<final; i++)
			{
				if(opts[i].selected)
				{
					text.push(opts[i].text);
				}
			}
			text = text.join(', ');
		}
		if(text == '')
		{
			text = this.s.defaultLabel;
		}
		this.setLabel(text);
	},
	
	createUL: function() {
		
		Element.addClassName(this.ulcontainer, 'ulcontainer');
		this.container.appendChild(this.ulcontainer);
		this.ulcontainer.show();
		
		var width = this.container.offsetWidth;
		var uldims = Element.getDimensions(this.ulcontainer);
		
		var uls = this.ulcontainer.childNodes;
		var ulswidth = 0;
		for (i=0; i<uls.length; i++) {
			if (uls[i].tagName.toLowerCase() == 'ul') {
				ulswidth += uls[i].offsetWidth;
			}
		}
		
		// dropdown width
		if (ulswidth > width) {
			// options longer than select
			this.ulcontainer.style.width = ulswidth + ((!isNaN(this.s.maxHeight) && uldims.height > this.s.maxHeight) ? 17 : 0) + 'px';
			//alert ('2');
		}
		else if (this.s.fixedWidth == true) {
			// set the width of the original <select>
			this.ulcontainer.style.width = width + 'px';
			this.ulcontainer.style.width = width + (width - this.ulcontainer.offsetWidth) + 'px';
			//alert ('3');
		}
		
		if (!isNaN(this.s.maxHeight) && uldims.height > this.s.maxHeight) {
			this.ulcontainer.style.height = this.s.maxHeight + 'px';
			this.ulcontainer.style.overflow = 'auto';
		}
		
		var left = String(Position.cumulativeOffset(this.ulcontainer));
		left = Number(left.substring(0, left.indexOf(',')));
		left += Element.getDimensions(this.ulcontainer).width;
		if(Element.getDimensions(document.getElementsByTagName('body')[0]).width < left){
			this.ulcontainer.style.right = "0px";
		}
		
		var uldims = Element.getDimensions(this.ulcontainer);
		
		if (document.all) { 
			/* create an iFrame to fix IE bug */
			this.imask.scrolling = 'no';
			this.imask.frameborder = '0';
			this.imask.style.display = 'none';
			this.imask.style.position = 'absolute';
			this.imask.style.marginTop = '-1';
			this.imask.style.zIndex = 10;
			this.ulcontainer.style.zIndex = 11;
			this.imask.style.width = uldims.width + 'px';
			this.imask.style.height = uldims.height + 'px';
			this.container.appendChild(this.imask);
			this.imask.style.top = this.ulcontainer.style.top;
			if(Element.getDimensions(document.getElementsByTagName('body')[0]).width < left){
				this.imask.style.right = "0px";
			}
		}
		
		this.ulInit = true;
	},	
	

	clickLabel: function(e) {
		if(!this.ulInit){	//ul not initialized?
			this.findElements();
			this.createUL();
			this.initializeULEvents();
			this.show();
		}
		else
			this.toggle();
		for (var i=0; i<this.items.length; i++) {
			Element.removeClassName(this.items[i].li, this.s.hoverClass);
			Element.removeClassName(this.items[i].li, this.s.selectedClass);
			if (this.items[i].selected == true) {
				Element.addClassName(this.items[i].li, this.s.hoverClass);
				Element.addClassName(this.items[i].li, this.s.selectedClass);
			}
		}
		if (typeof(this.el.onclick) == 'function') {
			this.el.onclick();
		}
		if(!Element.visible(this.ulcontainer)){
			this.hide();
			if (typeof(this.el.onclose) == 'function') {
				this.el.onclose();
			}
			if (typeof(Event.fire) == 'function') {
				Event.fire(this.el, "close");
			}
		}
	},
	toggle: function() {
		if(Element.visible(this.ulcontainer)){
			this.hide();
		}else{
			this.show();
		}
	},
	hide: function() {
		Element.hide(this.ulcontainer);
		if (document.all) { 
			Element.hide(this.imask);
		}
	},
	show: function() {
		Element.show(this.ulcontainer);
		if (document.all) { 
			Element.show(this.imask);
		}
		var left = String(Position.cumulativeOffset(this.ulcontainer));
		left = Number(left.substring(0, left.indexOf(',')));
		left += Element.getDimensions(this.ulcontainer).width;
		if(Element.getDimensions(document.getElementsByTagName('body')[0]).width < left){
			this.ulcontainer.style.right = "0px";
		}
	},
	checkItem: function(itemvar, index){
		itemvar.selected = true;
		itemvar.el.selected = true;
		if(itemvar.li.getElementsByTagName('input')[0]){
			itemvar.li.getElementsByTagName('input')[0].checked = true;
		}
		Element.addClassName(itemvar.li, this.s.selectedClass);
		if(index){
			this.el.selectedIndex = index;
		}
	},
	uncheckItem: function(itemvar){
		itemvar.selected = false;
		itemvar.el.selected = false;
		if(itemvar.li.getElementsByTagName('input')[0]){
			itemvar.li.getElementsByTagName('input')[0].checked = false;
		}
		Element.removeClassName(itemvar.li, this.s.selectedClass);
	},
	onClick: function(e) {
		var ele = Event.element(e);
		while(ele && ele != this.container){
			if(ele.tagName.toLowerCase() == 'a'){
				break;
			}
			ele = ele.parentNode;
		}
		if(ele.tagName.toLowerCase() != 'a'){
			return;
		}
		//alert(ele.tagName);
		if(this.s.isMultiSelect){
			for (var i=0; i<this.items.length; i++) {
				if (this.items[i].a == ele) {
					if(this.items[i].selected == true){
						this.uncheckItem(this.items[i]);
					}else{
						this.checkItem(this.items[i]);
					}
					break;
				}
			}
			
		}else{
			for (var i=0; i<this.items.length; i++) {
				if (this.items[i].a == ele) {
					this.checkItem(this.items[i], i);
				} else {
					this.uncheckItem(this.items[i]);
				}
			}
			this.hide();
		}
		var allchecked = true;
		for(var x=0; x<this.items.length; x++){
			if(this.items[x].a == ele){
				var itemvar = this.items[x];
			}
			if(this.items[x].selected == false && !Element.hasClassName(this.items[x].li, this.s.toggleClass) && !this.items[x].disabled){
				allchecked = false;
			}
		}
		if(Element.hasClassName(itemvar.li, this.s.toggleClass)){
			for(var x=0; x<this.items.length; x++){
				if(allchecked){
					//uncheck all
					this.uncheckItem(this.items[x]);
				}else{
					//check all					
					if (!this.items[x].disabled) {
						//this.checkItem(this.items[x]);
						this.uncheckItem(this.items[x]);
					}
					this.checkItem(this.items[0]);					
				}
			}
		}else if(allchecked){
			for(var x=0; x<this.items.length; x++){
				if(Element.hasClassName(this.items[x].li, this.s.toggleClass)){
					//alert ('ran');
					this.checkItem(this.items[x]);
				}
			}
		}else{
			for(var x=0; x<this.items.length; x++){
				if(Element.hasClassName(this.items[x].li, this.s.toggleClass)){
					this.uncheckItem(this.items[x]);
				}
			}
		}
		this.updateLabel();
		if (typeof(this.el.onclick) == 'function') {
			this.el.onclick();
		
		}
		if (typeof(this.el.onchange) == 'function') {
			this.el.onchange();
			
		}
		if (typeof(Event.fire) == 'function') {
			Event.fire(this.el, "change");
		}

	},
	onMouseOver: function (e) {
		var ele = Event.element(e);
		if(ele.tagName.toLowerCase() != 'a' && ele.tagName.toLowerCase() != 'li'){
			return;
		}
		for (var i=0; i<this.items.length; i++) {
			Element.removeClassName(this.items[i].li, this.s.hoverClass);
			if (this.items[i].a == ele) {
				Element.addClassName(this.items[i].li, this.s.hoverClass);
			}
		}
	},
	initializeULEvents: function() {
		Event.observe(this.ulcontainer, 'click', this.onClick.bind(this));
		Event.observe(this.ulcontainer, 'mouseover', this.onMouseOver.bind(this));
		Event.observe(document, 'click', this.onBlur.bind(this), false);
		Event.observe(window, 'blur', this.onBlur.bind(this), false);
	},
	onBlur: function (e) {
		var el = Event.element(e);
		var found = false;
		do {
			if (el == null || el == window || el == document.body) break;
			if(el == this.container){
				found = true;
				break;
			}
		} while(el = el.parentNode);
		if(!found && Element.visible(this.ulcontainer)){
			this.hide();
			if (typeof(this.el.onclose) == 'function') {
				this.el.onclose();
			}
			if (typeof(Event.fire) == 'function') {
				Event.fire(this.el, "close");
			}
		}

	},
	updateLabel: function() {
		//alert(this.s.tagName);
	
		if(Element.hasClassName(this.items[0].li, this.s.toggleClass) && this.items[0].selected)
		{
			text = this.items[0].text;
		}
		else
		{
			var selectedItems = [];
			for(var x=0; x<this.items.length; x++){
				if(this.items[x].selected && !Element.hasClassName(this.items[x].li, this.s.toggleClass)){
					var textToPush;
					textToPush=replaceSubstring(this.items[x].text,"<img src='http://www.exotiqvillaholidays.com/images/asterik-ico.png' style='display:inline;padding-bottom:3px;'>",""); 
					//alert(textToPush);
					//selectedItems.push(this.items[x].text);
					selectedItems.push(textToPush);
				}
			}
			text = selectedItems.join(', ');

		}
		if(text == ''){
			text = this.s.defaultLabel;
		}
			
		this.setLabel(text);
		
	},
	setLabel: function(text) {
		//shorten text if necessary
		var shorttext = text.substring(0, Math.round(this.s.width/this.s.pxPerChar));
		if(shorttext != text)
			text = shorttext.substring(0, shorttext.length-2) + '\u2026'; // truncate text and replace last character with ellipsis
			
		//this.labelText.innerHTML = text; // This brakes in IE
		var text = document.createTextNode(text);
		this.labelText.innerHTML = '';
		this.labelText.insertBefore(text, this.labelText.firstChild);
	}
}

function match_select(changer, changing, label)
{
	var changerValue = document.getElementById(changer).value;
	var optionEls = document.getElementById(changer).childNodes;
	for(var i = 0; i < optionEls.length; i++)
	{
		if(optionEls[i].value == changerValue)
		{
			var changerLabel = optionEls[i].innerHTML;
		}
	}
	document.getElementById(changing).value = changerValue;
	document.getElementById(changing).nextSibling.childNodes[0].childNodes[0].childNodes[0].innerHTML = changerLabel;
}
function replaceSubstring(inputString, fromString, toString) {
	// Goes through the inputString and replaces every occurrence of fromString with toString
	var temp = inputString;
	if (fromString == "") {
		return inputString;
	}
	if (toString.indexOf(fromString) == -1) { // If the string being replaced is not a part of the replacement string (normal situation)
		while (temp.indexOf(fromString) != -1) {
			var toTheLeft = temp.substring(0, temp.indexOf(fromString));
			var toTheRight = temp.substring(temp.indexOf(fromString)+fromString.length, temp.length);
			temp = toTheLeft + toString + toTheRight;
		}
	} else { // String being replaced is part of replacement string (like "+" being replaced with "++") - prevent an infinite loop
		var midStrings = new Array("~", "`", "_", "^", "#");
		var midStringLen = 1;
		var midString = "";
		// Find a string that doesn't exist in the inputString to be used
		// as an "inbetween" string
		while (midString == "") {
			for (var i=0; i < midStrings.length; i++) {
				var tempMidString = "";
				for (var j=0; j < midStringLen; j++) { tempMidString += midStrings[i]; }
				if (fromString.indexOf(tempMidString) == -1) {
				midString = tempMidString;
				i = midStrings.length + 1;
				}
			}
		} // Keep on going until we build an "inbetween" string that doesn't exist
		// Now go through and do two replaces - first, replace the "fromString" with the "inbetween" string
		while (temp.indexOf(fromString) != -1) {
			var toTheLeft = temp.substring(0, temp.indexOf(fromString));
			var toTheRight = temp.substring(temp.indexOf(fromString)+fromString.length, temp.length);
			temp = toTheLeft + midString + toTheRight;
		}
		// Next, replace the "inbetween" string with the "toString"
		while (temp.indexOf(midString) != -1) {
			var toTheLeft = temp.substring(0, temp.indexOf(midString));
			var toTheRight = temp.substring(temp.indexOf(midString)+midString.length, temp.length);
			temp = toTheLeft + toString + toTheRight;
		}
	} // Ends the check to see if the string being replaced is part of the replacement string or not
	return temp; // Send the updated string back to the user
} // Ends the "replaceSubstring" function