/*
 * --------------------------------------------------------------------
 * jQuery-Plugin - accessibleUISlider - creates a UI slider component from a select element(s)
 * by Scott Jehl, scott@filamentgroup.com
 * http://www.filamentgroup.com
 * reference article: http://www.filamentgroup.com/lab/update_jquery_ui_16_slider_from_a_select_element/
 * demo page: http://www.filamentgroup.com/examples/slider_v2/index.html
 * 
 * Copyright (c) 2008 Filament Group, Inc
 * Dual licensed under the MIT (filamentgroup.com/examples/mit-license.txt) and GPL (filamentgroup.com/examples/gpl-license.txt) licenses.
 *
 * Usage Notes: please refer to our article above for documentation
 *  
 * Changelog: 
 *  08.12.08: Initial write
 *  01.05.08: updated to jQuery UI 1.6 api and CSS framework
 * 		 02.16.09: added slider param for orientation to force horizontal
 * --------------------------------------------------------------------
 */



jQuery.fn.selectToUISlider = function(settings){
		 var selects = jQuery(this);
		 
		 //accessible slider options
		 var options = jQuery.extend({
		 		 labels: 3, //number of visible labels
		 		 tooltip: true, //show tooltips, boolean
		 		 tooltipSrc: 'text',//accepts 'value' as well
		 		 labelSrc: 'value',//accepts 'value' as well		 
		 		 sliderOptions: null
		 }, settings);

		 //handle ID attrs - selects each need IDs for handles to find them
		 var handleIds = (function(){
		 		 var tempArr = [];
		 		 selects.each(function(){
		 		 		 tempArr.push('handle_'+jQuery(this).attr('id'));
		 		 });
		 		 return tempArr;
		 })();
		 
		 //array of all option elements in select element (ignores optgroups)
		 var selectOptions = (function(){
		 		 var opts = [];
		 		 selects.eq(0).find('option').each(function(){
		 		 		 opts.push({
		 		 		 		 value: jQuery(this).attr('value'),
		 		 		 		 text: jQuery(this).text()
		 		 		 });
		 		 });
		 		 return opts;
		 })();
		 
		 //array of opt groups if present
		 var groups = (function(){
		 		 if(selects.eq(0).find('optgroup').size()>0){
		 		 		 var groupedData = [];
		 		 		 selects.eq(0).find('optgroup').each(function(i){
		 		 		 		 groupedData[i] = {};
		 		 		 		 groupedData[i].label = jQuery(this).attr('label');
		 		 		 		 groupedData[i].options = [];
		 		 		 		 jQuery(this).find('option').each(function(){
		 		 		 		 		 groupedData[i].options.push({text: jQuery(this).text(), value: jQuery(this).attr('value')});
		 		 		 		 });
		 		 		 });
		 		 		 return groupedData;
		 		 }
		 		 else return null;
		 })();		 
		 
		 //check if obj is array
		 function isArray(obj) {
		 		 return obj.constructor == Array;
		 }
		 //return tooltip text from option index
		 function ttText(optIndex){
		 		 return (options.tooltipSrc == 'text') ? selectOptions[optIndex].text : selectOptions[optIndex].value;
		 }
		 
		 //plugin-generated slider options (can be overridden)
		 var sliderOptions = {
		 		 step: 1,
		 		 min: 0,
		 		 orientation: 'horizontal',
		 		 max: selectOptions.length-1,
		 		 range: selects.length > 1,//multiple select elements = true
		 		 slide: function(e, ui) {//slide function
		 		 		 		 var thisHandle = jQuery(this).find('.ui-slider-handle.ui-state-active'); //bug - ui.handle regression
		 		 		 		 //handle feedback 
		 		 		 		 thisHandle.find('.ui-slider-tooltip').text( ttText(ui.value) );
		 		 		 		 //control original select menu
		 		 		 		 var currSelect = jQuery('#' + thisHandle.attr('id').split('handle_')[1]);
		 		 		 		 currSelect.find('option').eq(ui.value).attr('selected', 'selected');
		 		 },
		 		 values: (function(){
		 		 		 var values = [];
		 		 		 selects.each(function(){
		 		 		 		 values.push( jQuery(this).get(0).selectedIndex );
		 		 		 });
		 		 		 return values;
		 		 })()
		 };
		 
		 //slider options from settings
		 options.sliderOptions = (settings) ? jQuery.extend(sliderOptions, settings.sliderOptions) : sliderOptions;
		 		 
		 //select element change event		 
		 selects.bind('change keyup click', function(){
		 		 var thisIndex = jQuery(this).get(0).selectedIndex;
		 		 var thisHandle = jQuery('#handle_'+ jQuery(this).attr('id'));
		 		 var handleIndex = thisHandle.data('handleNum');
		 		 thisHandle.parents('.ui-slider:eq(0)').slider("values", handleIndex, thisIndex);
		 });
		 
		 

		 //create slider component div
		 var sliderComponent = jQuery('<div></div>');
		 
		 //CREATE HANDLES
		 selects.each(function(i){
		 		 var hidett = '';
		 		 if( options.tooltip == false ){hidett = ' style="display: none;"';}
		 		 jQuery('<a href="#" id="'+handleIds[i]+'" class="ui-slider-handle"><span class="ui-slider-tooltip ui-widget-content ui-corner-all"'+ hidett +'></span></a>').data('handleNum',i).appendTo(sliderComponent);
		 });
		 
		 //CREATE SCALE AND TICS
		 
		 //write dl if there are optgroups
		 if(groups) {
		 		 var inc = 0;
		 		 var scale = sliderComponent.append('<dl class="ui-slider-scale ui-helper-reset"></dl>').find('.ui-slider-scale:eq(0)');
		 		 jQuery(groups).each(function(h){
		 		 		 scale.append('<dt style="width: '+ (100/groups.length).toFixed(2) +'%' +'; left:'+ (h/(groups.length-1) * 100).toFixed(2)  +'%' +'"><span>'+this.label+'</span></dt>');//class name becomes camelCased label
		 		 		 var groupOpts = this.options;
		 		 		 jQuery(this.options).each(function(i){
		 		 		 		 var style = (inc == selectOptions.length-1 || inc == 0) ? 'style="display: none;"' : '' ;
		 		 		 		 var labelText = (options.labelSrc == 'text') ? groupOpts[i].text : groupOpts[i].value;
		 		 		 		 scale.append('<dd style="left:'+ leftVal(inc) +'"><span class="ui-slider-label">'+ labelText +'</span><span class="ui-slider-tic ui-widget-content"'+ style +'></span></dd>');
		 		 		 		 inc++;
		 		 		 });
		 		 });
		 }
		 //write ol
		 else {
		 		 var scale = sliderComponent.append('<ol class="ui-slider-scale ui-helper-reset"></ol>').find('.ui-slider-scale:eq(0)');
		 		 jQuery(selectOptions).each(function(i){
		 		 		 var style = (i == selectOptions.length-1 || i == 0) ? 'style="display: none;"' : '' ;
		 		 		 var labelText = (options.labelSrc == 'text') ? this.text : this.value;
		 		 		 scale.append('<li style="left:'+ leftVal(i) +'"><span class="ui-slider-label">'+ labelText +'</span><span class="ui-slider-tic ui-widget-content"'+ style +'></span></li>');
		 		 });
		 }
		 
		 function leftVal(i){
		 		 return (i/(selectOptions.length-1) * 100).toFixed(2)  +'%';
		 		 
		 }
		 

		 
		 
		 //show and hide labels depending on labels pref
		 //show the last one if there are more than 1 specified
		 if(options.labels > 1) sliderComponent.find('.ui-slider-scale li:last span.ui-slider-label, .ui-slider-scale dd:last span.ui-slider-label').addClass('ui-slider-label-show');
		 //set increment
		 var increm = Math.round(selectOptions.length / options.labels);
		 //show em based on inc
		 for(var j=0; j<selectOptions.length; j+=increm){
		 		 if((selectOptions.length - j) > increm){//don't show if it's too close to the end label
		 		 		 sliderComponent.find('.ui-slider-scale li:eq('+ j +') span.ui-slider-label, .ui-slider-scale dd:eq('+ j +') span.ui-slider-label').addClass('ui-slider-label-show');
		 		 }
		 }

		 //style the dt's
		 sliderComponent.find('.ui-slider-scale dt').each(function(i){
		 		 jQuery(this).css({
		 		 		 'left': ((100 /( groups.length))*i).toFixed(2) + '%'
		 		 });
		 });
		 




		 //inject and return 
		 sliderComponent
		 .insertAfter(jQuery(this).eq(this.length-1))
		 .slider(options.sliderOptions)
		 .find('.ui-slider-label')
		 .each(function(){
		 		 jQuery(this).css('marginLeft', -jQuery(this).width()/2);
		 })

		 var values = sliderComponent.slider('values');
		 
		 if(isArray(values)){
		 		 $(values).each(function(i){
		 		 		 sliderComponent.find('.ui-slider-tooltip').eq(i).html( ttText(this) );
		 		 });
		 }
		 else {
		 		 sliderComponent.find('.ui-slider-tooltip').eq(0).html( ttText(values) );
		 }
		 
		 return this;
}




