﻿//function used to create all of the sliders
function RenderSliders() {
	$("div.slider, div.dualslider").each(function()
		{
			//Get our slider container vars.
			var sliderContainer = $(this);
			var uiSliderContainer = sliderContainer.children("div.ui-slider-container");	//the main slider container
			var sliderTrack = uiSliderContainer.children("div.ui-slider-track");			//the actual area the handles move along
			var sliderHandles = sliderTrack.children("div.ui-slider-handle");				//handle(s) used to alter the selected values on the slider
			var sliderRange = sliderTrack.children("div.ui-slider-range");					//range is the highlighted area showing the area covered by the slider				
			var sliderSummary = uiSliderContainer.children('label.ui-slider-summary');		//label showing the value currently selected by the slider
			var sliderLowerLabel = uiSliderContainer.children('label.limit-low');			//label showing the lower bound of the slider
			var sliderUpperLabel = uiSliderContainer.children('label.limit-high');			//label showing the upper bound of the slider
			var handleCount = sliderHandles.length;											//indicates whether this is a single or dual slider
			var dataContainer = sliderContainer.children("select");							//select list(s) used to create this slider
			var upperRangeLimit = sliderContainer.find('input#UPPER_RANGE_LIMIT').val();		//the left param of the slider, used by the summary control to see if the upper handle has been moved or not
			var summaryDefaultText = sliderContainer.find('input#DUAL_SLIDER_SUMMARY_DEFAULT_TEXT').val();	//the text used by a dual slider's summary if neither handle has been moved
			var summaryPrefix = sliderContainer.find('input#DUAL_SLIDER_SUMMARY_PREFIX').val();			//the text used by a dual slider's summary if only the upper handle has been moved e.g. 'Up to £10,000'
			var summarySuffix = sliderContainer.find('input#DUAL_SLIDER_SUMMARY_SUFFIX').val();			//the text used by a dual slider's summary if only the lower handle has been moved e.g. '£10,000 and above'
			var summarySeparator = sliderContainer.find('input#DUAL_SLIDER_SUMMARY_SEPARATOR').val();		//the text used by a dual slider's summary if both handles have been moved e.g. '£10,000 to £20,000'
			var useRange = (sliderContainer.find('input#USE_RANGE').val() == 'false') ? false : true ;		//value used to signify if the dual slider should use the range param
			var dataItems = new Array();  													//values as an array of jquery objects.

			//Loop though each of our available data items in our data container.
			$(dataContainer[0]).children().each(function(iDataItem)
			{	
				//Create a string key of this option.
				var dataItemKey = this.value + ":" + this.text;
				
				//we dont want a 0 value as this is covered by the 'any' option
				if(this.value != '0') {					
					dataItems.push({key: dataItemKey, item: this, ordinal: [iDataItem,null]});	
				}
			});
			
			//if this is a single slider we need to operate this as a FIFO queue and not a LIFO stack.
			//we need to shift out element 0 and re-add it to the end of the queue, this should force the 
			//inital state of the handle to begin at the right hand side
			//If this is a dual slider we need to duplicate the 'any' option into the end of the array so we
			//have two otherwise it will be impossible to deselect the lower handle
			if(handleCount == 1) {
				var val = dataItems.shift();	//shift the first item out of the array (the 'any' option)
				dataItems.push(val);			//push it into the end
				
				//configure the upper and lower labels, this is a single slider so only 1 datacontainer
				//to worry about, so we can just take the upper and lower values
				sliderUpperLabel.html(dataContainer.find('option:first').text());
				sliderLowerLabel.html(dataContainer.find('option:first').next('option').text());
			}
			else {
				var val = dataItems[0];			//copy first item out of the array (the 'any' option)
				dataItems.push(val);			//push it into the end
				sliderUpperLabel.html($(dataContainer[1]).find('option:first').text());
				sliderLowerLabel.html($(dataContainer[0]).find('option:first').next('option').text());
			}
						
			//The number of steps is equal to the data length - 1.
			var dataLength = (dataItems.length - 1);
			//Hide our select element.
			dataContainer.hide();
			//Enable and show our slider bar.
			sliderTrack.slider(
			{
				//Set the number of steps to equal the options in the select element.
				steps: dataLength,
				min: 0,
				max: dataLength,
				range: useRange,
				//Feedback to the user the output value of the slider.
				slide: function(e,ui)
				{	
					ui.handle.children("div.value").text(dataItems[ui.value].item.text);
					if((handleCount == 1))
					{
						sliderRange.width(ui.handle.position().left + (ui.handle.width() / 2));
						sliderSummary.text(dataItems[ui.value].item.text);
					}
					else //Handle the range for multiple values.
					{
						var handleIndex = (ui.handle.hasClass('high')) ? 1 : 0;
						var lowerHandle = sliderHandles.eq(0);
						var upperHandle = sliderHandles.eq(1);	
						
						//ok we need to do some extra processing here to stop non-range based sliders from breaking
						//it should be possible for non range based sliders to select the same value, however they
						//shouldn't both be able to select the upper or lower limits and they also shouldn't be able
						//to cross over each other or everything will go west!
						if(!useRange) {
							if(handleIndex == 1) {		//upper handle slide
								if(ui.value == 0) {		//if upper handle has been set to 0, reset it to 1
									sliderTrack.slider("moveTo",1, 1);
								}
								else {
									var lowerHandlePosition = $(this).slider('value',0)
									if(ui.value < lowerHandlePosition) {	//if upper handle is below lower handle reset to same value
										sliderTrack.slider("moveTo",lowerHandlePosition, 1);
									}
								}								
							}
							else {				//lower handle slide
								if(ui.value == dataLength) {	//if lower handle is at the upper limit move it back one
									sliderTrack.slider("moveTo",dataLength-1, 0);
								}	
								else {
									var upperHandlePosition = $(this).slider('value',1)
									if(ui.value > upperHandlePosition) {		//if the lower handle is above the upper one reset to same value
										sliderTrack.slider("moveTo",upperHandlePosition, 0);
									}
								}						
							}	
						}				

						if(lowerHandle.position()) {
							// ok we need to detect if the lower slider is still at any and is so change to text to read 'Up To {0}'
							if(upperHandle.position().left == upperRangeLimit && lowerHandle.position().left == 0) {
								sliderSummary.text(summaryDefaultText);
							}
							else if(lowerHandle.position().left == 0) {
								var text = summaryPrefix + upperHandle.text();
								sliderSummary.text(text);
							}
							else if(upperHandle.position().left == upperRangeLimit) {
								var text = lowerHandle.text() + summarySuffix;
								sliderSummary.text(text);
							}
							else if(upperHandle.position().left == lowerHandle.position().left) {
								var text = lowerHandle.text();
								sliderSummary.text(text);
							}
							else {
								var text = lowerHandle.text() + summarySeparator + upperHandle.text();
								sliderSummary.text(text);
							}
						}	
						
						//Set our range width to display our active area.
						try {
						sliderRange.width(	(upperHandle.position().left + (ui.handle.width() / 2)) -
											(lowerHandle.position().left + (ui.handle.width() / 2))).css("left", lowerHandle.position().left + (ui.handle.width() / 2));
						}
						catch(ex) { }
					}
				},
				//When the slider has changed update our select element to match this value.
				change: function(e,ui)
				{		
					var handleIndex = (ui.handle.hasClass('low')) ? 0 : 1;
					
					//we need to handle the single and dual sliders separatly due to the combined dataitems array
					if(handleCount == 1) {
						dataContainer.eq(handleIndex)[0].selectedIndex = dataItems[ui.value].ordinal[handleIndex];
						dataContainer.eq(0).trigger("change");
					}
					else {
						if(handleIndex == 0) {
							dataContainer.eq(0)[0].selectedIndex = dataItems[ui.value].ordinal[0];
							dataContainer.eq(0).trigger("change");
						}
						else {
							//if this is a dual slider with the range param set we need to knock the selected
							//index back by one to account for the staggered select values
							if(useRange)
								dataContainer.eq(1)[0].selectedIndex = dataItems[ui.value].ordinal[0]-1;
							else
								dataContainer.eq(1)[0].selectedIndex = dataItems[ui.value].ordinal[0];

							dataContainer.eq(1).trigger("change");
						}					
					}					
				}
			}).show();

			//Initialise our slider handles to our selected dataItem values.
			//but make sure to do the upper handle first if it exists as otherwise it'll screw up
			//the lower handle cos of the range issue!
			if(dataContainer[1]) {
				var dc = dataContainer[1];
				try
				{
					//move the upper handle to its position, if its position is 0 then it is unselected
					//and must be moved to the upper range limit
					var dataItemKey = dc.options[dc.selectedIndex].value + ":" + dc.options[dc.selectedIndex].text;
					var index = containsKey(dataItemKey, dataItems);
					if(index == 0) index = dataItems.length;
					sliderTrack.slider("moveTo",index, 1);
				}
				catch(ex) { }				
			}
			if(dataContainer[0]) {
				var dc = dataContainer[0];
				try
				{
					var dataItemKey = dc.options[dc.selectedIndex].value + ":" + dc.options[dc.selectedIndex].text;				
					sliderTrack.slider("moveTo", containsKey(dataItemKey, dataItems), 0);
				}
				catch(ex) {}				
			}
		});
			
		//function used to return the index of a value within the array passed in
		function containsKey(key, array)
		{
			for(var i = 0 ; i < array.length ; i++)
			{
				if(array[i].key == key) return i;
			}
			return -1;
		}
}

//function used to destroy all sliders!
function DestroySliders() {
	$("div.slider, div.dualslider").each(
		function() {
			var sliderContainer = $(this);
			var uiSliderContainer = sliderContainer.children("div.ui-slider-container");
			var sliderTrack = uiSliderContainer.children("div.ui-slider-track");
			sliderTrack.slider('destroy');
		}
	);
}

//fucntion used to reset all sliders
function ResetSliders() {
	$("div.slider, div.dualslider").each(
		function() {
			ResetSlider($(this));	
		}
	);
}

//function used to reset a slider
function ResetSlider(container) {
	var sliderTrack = container.find("div.ui-slider-track");
	var steps = container.find('option').length;
	
	//we need to handle dual and single sliders differently
	var handleCount = sliderTrack.find("div.ui-slider-handle").length;
	if(handleCount == 1) {
		sliderTrack.slider('moveTo',steps,0);
	}
	else {
		sliderTrack.slider('moveTo',steps-1,1);
		sliderTrack.slider('moveTo',0,0);
	}
}