$(function() {
  var product_json_src = 'http://www.allsensors.com/js/products.json';
  var product_data = [];

	var range_scale_data = {
    global : {
      scale_px_width: 434,
      unit_sep: ' / ',
      min_range_width: 30
    },
		inh20 : {
      min : 0.25, max : 4152,
      visible_min : 0.2, visible_max: 5000,
      conversion : 249.0819355,
      log_val_lookup : []
    },
		cmh20 : {
      min : 0.64, max : 10546,
      visible_min : 0.6, visible_max: 11000,
      conversion : 98.06375414,
      log_val_lookup : []
    },
		psi : {
      min : 0.009, max : 150,
      visible_min : 0.009, visible_max: 200,
      conversion : 6894.757292,
      log_val_lookup : [],
      label: 'PSI'
    },
		mbar : {
      min : 0.621, max : 10342,
      visible_min : 0.6, visible_max: 11000,
      conversion : 100,
      log_val_lookup : [],
      label : 'mBar'
    },
		temp : {
      min : -40, max : 125,
      visible_min : -45, visible_max: 140
    },
    bar : {
      conversion: 100000,
      label : 'Bar'
    },
    pa : {
      conversion: 1,
      label : 'Pa'
    },
    kpa : {
      conversion: 1000,
      label : 'kPa'
    },
    mpa : {
      conversion: 1000000,
      label : 'MPa'
    },
    mmh20 : {
      conversion: 9.806375414,
      label : 'mmH<sub>2</sub>0'
    },
    mmhg : {
      conversion: 133.3223684,
      label : 'mmHg'
    },
    cmhg : {
      conversion: 1333.223684,
      label : 'cmHg'
    },
    inhg : {
      conversion: 3386.388158,
      label : 'inHg'
    },
    torr : {
      conversion: 133.3223684,
      label : 'Torr'
    },
    mtorr : {
      conversion: 0.1333223684,
      label : 'mTorr'
    }
	}

  // Holds all invalid selection options
  // Package -> Output -> Type -> True/False
  var package_matrix = {
    any :{
      any : {abs: true, gauge: true, diff: true, any: true},
      amp : {abs: true, gauge: true, diff: true, any: true},
      dig : {abs: true, gauge: false, diff: true, any: true},
      mill : {abs: true, gauge: true, diff: true, any: true}
    },
    a :{
      any : {abs: true, gauge: true, diff: true, any: true},
      amp : {abs: true, gauge: true, diff: true, any: true},
      dig : {abs: true, gauge: false, diff: true, any: true},
      mill : {abs: true, gauge: false, diff: true, any: true}
    },
    c :{
      any : {abs: true, gauge: true, diff: true, any: true},
      amp : {abs: false, gauge: false, diff: false, any: false},
      dig : {abs: false, gauge: false, diff: false, any: false},
      mill : {abs: true, gauge: true, diff: true, any: true}
    },
    n :{
      any : {abs: true, gauge: false, diff: true, any: true},
      amp : {abs: false, gauge: false, diff: false, any: false},
      dig : {abs: false, gauge: false, diff: false, any: false},
      mill : {abs: true, gauge: true, diff: true, any: true}
    },
    mini :{
      any : {abs: true, gauge: true, diff: true, any: true},
      amp : {abs: true, gauge: true, diff: true, any: true},
      dig : {abs: false, gauge: false, diff: false, any: false},
      mill : {abs: true, gauge: true, diff: true, any: true}
    },
    sm :{
      any : {abs: true, gauge: true, diff: false, any: true},
      amp : {abs: false, gauge: false, diff: false, any: false},
      dig : {abs: false, gauge: false, diff: false, any: false},
      mill : {abs: true, gauge: true, diff: true, any: true}
    }
  };

  // Handy object for defaulting to all false for a given package
  var pack_all_false = {
    any : {abs: false, gauge: false, diff: false, any: false},
    amp : {abs: false, gauge: false, diff: false, any: false},
    dig : {abs: false, gauge: false, diff: false, any: false},
    mill : {abs: false, gauge: false, diff: false, any: false}
  }

  var valid_matrix = {
    any : $.extend(true, {}, package_matrix),
    comp : $.extend(true, {}, package_matrix),
    uncomp : $.extend(true, {}, package_matrix)
  };

  // Set Uncompensated invalids
  $.each(valid_matrix.uncomp, function(i, pack){
    pack.amp.any=false; pack.amp.diff=false;
    pack.amp.gauge=false; pack.amp.abs=false;
    
    pack.dig.any=false; pack.dig.diff=false;
    pack.dig.gauge=false; pack.dig.abs=false;
  });

  valid_matrix.uncomp.c = pack_all_false;

  valid_matrix.uncomp.a.mill.any = false;
  
  // Set Compensated Invalids
  valid_matrix.comp.any.dig.gauge = false;

  valid_matrix.comp.sm = pack_all_false;

  // This variable should reflect the width in pixels of the sliders.
  // using this, the you can then set the exact pixel location of each option
  // above each slider
  var as_slider_max = 560;

  // Vars hold jQuery object for DOM target and associated data
  var as_units = $("#as-slider-units");
  var as_range_pressure = $('#as-slider-range');
  var as_type = $("#as-slider-type");
  var as_output = $("#as-slider-output");
  var as_compensation = $("#as-slider-compensation");
  var as_package = $("#as-slider-package");
  var as_reset = $("#as-slider-reset");

  var as_voltage = $("#as-slider-voltage");
  var as_range_temp = $("#as-slider-range-temp");
  //var as_temp = $("#as-slider-temp");
  
  var as_search = $('#as-search-prod');
  
  var as_results = $("#product-list");
  var as_search_header = $("#search-header");
  var result_cache = ''; // Stores resultsets to speed up DOM updating


  //
  // Data for each of the snapping sliders is setup here:
  // 'slider_options' is an array of each option, each option being a json data object
  //  --label: String, The text displayed for the item
  //  --title: string, Clean title used for search selection parameters
  //  --id: String, unique ID for non lable based reference
  //  --position: Integer, The pixel position from the left where the center of the item will be placed
  //  --labelonly: Optional boolean, sets if the item will appear normally, but not be selectable
  //  --disabled: Optional boolean, defaulted to false, when set to true, makes the value unselectable
  //

  // All the options share the same start/end positions
  var start_pos = 35;
  var end_pos = 495;

  as_units.data('slider_options', [
      {label: 'Units', position: start_pos, labelonly: true},
      {label: 'inH<sub>2</sub>0', position: 160, id: 'inh20', title: 'inH20'},
      {label: 'cmH<sub>2</sub>0', position: 275, id: 'cmh20', title: 'cmH20'},
      {label: 'psi', position: 387, id: 'psi', title: 'PSI'},
      {label: 'mbar', position: end_pos, id: 'mbar', title: 'mBar'}
    ]);
  as_units.data('option_change_callback', trigger_scale_change);

  as_type.data('slider_options', [
      {label: 'Type', position: start_pos, id: 'type_any', title: 'Any Type', type: 'label'},
      {label: 'Differential', position: 160, id: 'type_diff', title: 'Differential'},
      {label: 'Gauge', position: 328, id: 'type_gauge', title: 'Gauge'},
      {label: 'Absolute', position: end_pos, id: 'type_abs', title: 'Absolute'}
    ]);
  as_type.data('option_change_callback', trigger_type_change);

  as_output.data('slider_options', [
      {label: 'Output', position: start_pos, id: 'out_any', title: 'Any Output', type: 'label'},
      //{label: 'Basic', position: 160, id: 'out_basic', title: 'Basic'},
      {label: 'Millivolt', position: 160, id: 'out_mill', title: 'Millivolt'},
      {label: 'Amplified', position: 328, id: 'out_amp', title: 'Amplified'},
      {label: 'Digital', position: end_pos, id: 'out_dig', title: 'Digital'}
    ]);
  as_output.data('option_change_callback', trigger_type_change);

  as_compensation.data('slider_options', [
      {label: 'Compensation', position: start_pos, id: 'comp_any', title: 'Any Compensation', type: 'label'},
      //{label: 'Basic', position: 160, id: 'out_basic', title: 'Basic'},
      {label: 'Compensated', position: 237, id: 'comp_comp', title: 'Compensated'},
      {label: 'Uncompensated', position: 407, id: 'comp_uncomp', title: 'Uncompensated'}
    ]);
  as_compensation.data('option_change_callback', trigger_type_change);

  as_package.data('slider_options', [
      {label: 'Package', position: start_pos, id: 'pack_any', title: 'Any Package', type: 'label'},
      {label: 'A', position: 157, id: 'pack_a', title: 'A Package'},
      {label: 'Mini Side', position: 232, id: 'pack_mini', title: 'Miniature'},
      {label: 'CPC', position: 312, id: 'pack_c', title: 'CPC Package'},
      {label: 'Surface Mount', position: 410, id: 'pack_sm', title: 'Surface Mount'},
      {label: 'N', position: end_pos, id: 'pack_n', title: 'N Package'}
    ]);
  as_package.data('option_change_callback', trigger_type_change);
  
  as_voltage.data('slider_options', [
      {label: 'Supply Voltage', position: start_pos, id: 'volt_any', title: 'Any Voltage', type: 'label'},
      {label: '1.8V', position: 158, id: 'volt_1.8', title: '1.8 volts'},
      {label: '3.3V', position: 270, id: 'volt_3.3', title: '3.3 volts'},
      {label: '5V' , position: 382, id: 'volt_5', title: '5 volts'},
      {label: '12V', position: end_pos, id: 'volt_12', title: '12 volts'}
    ]);
  as_voltage.data('option_change_callback', trigger_type_change);

  /*as_temp.data('slider_options', [
      {label: 'Temp in &deg;C', position: start_pos, id: 'temp_any', title: 'Any Temperature'},
      {label: '-40 - 125', position: 157, id: 'temp_-40_125', title: 'Full'},
      {label: '-25 - 85', position: 233, id: 'temp_-25_85', title: 'Midrange'},
      {label: '0 - 70', position: 300, id: 'temp_0_70', title: 'Warm'},
      {label: '0 - 50', position: 360, id: 'temp_0_50', title: 'Warm Midrange'},
      {label: '5 - 50', position: 424, id: 'temp_5_50', title: 'Somewhat warm'},
      {label: '10 - 50', position: end_pos, id: 'temp_10_50', title: 'Hot'}
    ]);
  as_temp.data('option_change_callback', trigger_type_change);*/

  var click_dragging = false;
  
  // Initialize ranged slider
  init_range_sliders();

  // Initialize snapping sliders
  init_snap_sliders();

  // Initialize unit default
  snap_slideselect({target:as_units}, {value:as_units.slider('value')});
  
  // Initialize range labels
  trigger_range_adjust();

  // Grab product data
  // TODO: Add loader----
  
  $.jsonp({
    url: product_json_src,
    callback: 'products',
    error: function(options, status){
      console.log(status, options);
    },
    success: function(json, status) {
      product_data = json;
      trigger_update();
    }

  });



  // Bind click for various fiddley bits --------------------------------------
  // Additional search options
  $('#as-slider-additional').click(function(){
    var $arrow = $('span', this);
    var height = 660;
    var is_extended = false;

    if ($arrow.is('.inner-arrow-right')){ // Is Closed, open it
      $arrow.removeClass('inner-arrow-right').addClass('inner-arrow-down');
      $('strong', this).text('Hide Additional Search Options');
      is_extended = true;
      $('#as-slider-container').toggleClass('extended', is_extended);
    }else{ // Is Open, close it
      $arrow.removeClass('inner-arrow-down').addClass('inner-arrow-right');
      $('strong', this).text('Show Additional Search Options');
      is_extended = false;	  	  
      height = 495;
    }

    trigger_range_adjust();
    $('#product-finder').animate({'height': height}, 1000, function(){
      if (!is_extended){
        $('#as-slider-container').toggleClass('extended', is_extended);
		$('#conversion-tool span').removeClass('inner-arrow-down').addClass('inner-arrow-right');
      	$('#conversion-tool strong').text('Show Temperature Conversion'); 
      }
    });

    return false; // Cancel Click
  });
  
  // More units--------------------------------------------------------------

  // Setup
  var extra_units = ['bar', 'mbar', 'pa', 'kpa', 'mpa', 'mmh20', 'mmhg', 'cmhg', 'inhg', 'torr', 'mtorr'];
  var $more_units = $('#more-units-wrapper div');

  $.each(extra_units, function(i, val){
    $more_units.append('<span><strong>0</strong> ' + range_scale_data[val].label + '</span>');
    $('span:last', $more_units).data('id', val);
  });

  $('#more-units-wrapper a').click(function(){
    var $arrow = $('span', this);
    var time = 710;

    if ($arrow.is('.inner-arrow-right')){ // Is Closed, open it
      $arrow.removeClass('inner-arrow-right').addClass('inner-arrow-down');
      $more_units.removeClass('closed')
        .addClass('open')
        .show().width(0)
        .animate({'width': 82}, time);
      $(this).animate({'left': 98}, time);
      trigger_range_adjust(); // Updates the values immediately
    }else{ // Is Open, close it
      $arrow.removeClass('inner-arrow-down').addClass('inner-arrow-right');
      $more_units.removeClass('open')
        .addClass('closed')
        .animate({'width': 0}, time, function(){$(this).hide()});
      $(this).animate({'left': 0}, time);
    }

    //$('#product-list').animate({'width': width}, speed);

  });

  // Text Search --------------------------------------------------------------
  as_search.keydown(function(){
    window.setTimeout(function(){as_search.change()}, 1);
  }).change(function(){
    trigger_update(); // Updates the values immediately
  });


  // Product Previews ---------------------------------------------------------
  $('.as-slider-package-wrapper span').each(function(index){
    if (index !=0){
      $(this).attr('title', '<div class="product-preview/>').tooltip({effect: 'slide', tipClass: 'tooltip tooltip_' + $(this).text().toLowerCase()})	  
    }
  }).bind('mousedown click', function(event){
    event.preventDefault();
    if (event.type == 'click'){
      var item_value = parseInt($(this).css('left').slice(0, -2));
      snap_slidestop({target:as_package}, {value:item_value});
      snap_slideselect({target:as_package}, {value:item_value});
    }
  });

 //==========***************** FUNCTIONS *****************====================//

  function init_range_sliders(){
    // Setup Ranged Pressure Slider---------------------------------------------
    as_range_pressure.slider({
      range: true,
      min: 0,
      max: range_scale_data.global.scale_px_width,
      values: [0, range_scale_data.global.scale_px_width], // Default to full selection
      slide: function(event, ui) {
        /*/ Lock range width while dragging
        if (click_dragging) return false;*/

        // Limit the range width for dragging
        if ((ui.values[1] - ui.values[0]) <= range_scale_data.global.min_range_width){
          return false
        }

        trigger_range_adjust();
      },
      change: function(event, ui){
        trigger_range_adjust();
      },
      stop: function(){ // Update on stop only
        trigger_update();
      }
    });

    // Setup range handle labels
    $('.ui-slider-handle', as_range_pressure).html('<strong>0</strong>');
    
    // Setup the draggable interface for the range slider--------------
    $('.ui-slider-range', as_range_pressure).draggable({
      axis: "x",
      start: function(){
        // Override for IE to lock range width
        //click_dragging = true;
      },
      drag: function(event, ui){
        min_val = (ui.position.left * as_range_pressure.slider('option', 'max')) / as_range_pressure.width();
        max_val = ((ui.position.left + $(event.target).width()) * as_range_pressure.slider('option', 'max')) / as_range_pressure.width();
        as_range_pressure.slider('values', 0, min_val);
        as_range_pressure.slider('values', 1, max_val);

        trigger_range_adjust();
      },
      stop: function(){ // Update on stop only
        trigger_update();
      },
      containment: as_range_pressure
    }).html('<a href="#" class="range-drag-handle"></a>');

    $('.range-drag-handle', as_range_pressure).click(function(){
      return false;
    });

    $('#range-drag-handle, .ui-slider-range', as_range_pressure).mousedown(function(){
      //click_dragging = true;
    });
    
    $('.ui-slider-handle:last', as_range_pressure).addClass('ui-slider-handle-last');


    // Setup Ranged Temperature Slider---------------------------------------------
    //* < Add/remove slash to left to enable/disable
    as_range_temp.slider({
      range: true,
      min: 0,
      max: range_scale_data.global.scale_px_width,
      values: [147, 223], // Default to 20 to 45 degrees
      slide: function(event, ui) {
        // Limit the range width for dragging
        if ((ui.values[1] - ui.values[0]) <= range_scale_data.global.min_range_width){
          return false
        }
        trigger_range_adjust();
      },
      change: function(event, ui){
        trigger_range_adjust();
      },
      stop: function(){ // Update on stop only
        trigger_update();
      }
    });

    // Setup range handle labels
    $('.ui-slider-handle', as_range_temp).html('<strong>0</strong>');

    // Setup the draggable interface for the range slider--------------
    $('.ui-slider-range', as_range_temp).draggable({
      axis: "x",
      start: function(){
        // Override for IE to lock range width
        //click_dragging = true;
      },
      drag: function(event, ui){
        min_val = (ui.position.left * as_range_temp.slider('option', 'max')) / as_range_temp.width();
        max_val = ((ui.position.left + $(event.target).width()) * as_range_temp.slider('option', 'max')) / as_range_temp.width();
        as_range_temp.slider('values', 0, min_val);
        as_range_temp.slider('values', 1, max_val);
        trigger_range_adjust();
      },
      stop: function(){ // Update on stop only
        trigger_update();
      },
      containment: as_range_temp
    }).html('<a href="#" class="range-drag-handle"></a>');

    $('.range-drag-handle', as_range_temp).click(function(){
      return false;
    });

    $('.range-drag-handle, .ui-slider-range', as_range_temp).mousedown(function(){
      //click_dragging = true;
    });

    $('.ui-slider-handle:last', as_range_temp).addClass('ui-slider-handle-last');//*/
  }

  function init_snap_sliders(){
    as_units.slider({
      value: as_units.data('slider_options')[1].position,
      animate: true,
      min: 0,
      max: as_slider_max,
      stop: snap_slidestop,
      slide: snap_slideselect
    });

    as_type.slider({
      value: as_type.data('slider_options')[0].position,
      animate: true,
      min: 0,
      max: as_slider_max,
      stop: snap_slidestop,
      slide: snap_slideselect
    });

    as_output.slider({
      value: as_output.data('slider_options')[0].position,
      animate: true,
      min: 0,
      max: as_slider_max,
      stop: snap_slidestop,
      slide: snap_slideselect
    });

    as_compensation.slider({
      value: as_compensation.data('slider_options')[0].position,
      animate: true,
      min: 0,
      max: as_slider_max,
      stop: snap_slidestop,
      slide: snap_slideselect
    });

    as_package.slider({
      value: as_package.data('slider_options')[0].position,
      animate: true,
      min: 0,
      max: as_slider_max,
      stop: snap_slidestop,
      slide: snap_slideselect
    });

    as_voltage.slider({
      value: as_voltage.data('slider_options')[0].position,
      animate: true,
      min: 0,
      max: as_slider_max,
      stop: snap_slidestop,
      slide: snap_slideselect
    });

    /*as_temp.slider({
      value: as_temp.data('slider_options')[0].position,
      animate: true,
      min: 0,
      max: as_slider_max,
      stop: snap_slidestop,
      slide: snap_slideselect
    });*/

    // Build out slider position options
    $.each([as_units, as_type, as_output, as_compensation, as_package, as_voltage], function(i, slider){
      $.each(slider.data('slider_options'), function(i, option){
        slider.before('<span class="' +
          (i == 0 ? 'selected ' : '') +
          (option.type == 'label' ? 'label ' : '') +
          (option.labelonly ? 'labelonly ' : '') +
          (option.disabled ? 'disabled ' : '') +
          '" style="left:' + option.position + 'px">' +
          option.label +
          '</span>'
        );
        slider.siblings('span:last').data('id', option.id)
        slider.siblings('span:last').data('title', option.title);
      });
    });

    // Adjust position of labels to center for markers
    $('.as-slider-wrapper span').each(function(){
      var margin = -Math.round($(this).width()/2 - 7) + 'px';
      $(this).css('margin-left', margin);
    });

    // Add Unit conversion label placeholders
    as_units.siblings('span').not(':first').append('<strong>0' + range_scale_data.global.unit_sep + '0</strong>');

    // Bind click to reset sliders
    as_reset.click(function(){
      
      $.each([as_type, as_output, as_compensation, as_package, as_voltage], function(index, slider){
        snap_slidestop({target:slider}, {value:0});
        snap_slideselect({target:slider}, {value:0});
      });

      as_range_temp.slider("option", "values", [147, 223]);
      trigger_update();
      // Cancel link click
      return false;
    });
  }

  // Callback function to update option selected status during slide
  function snap_slideselect(event, ui){
    var slider = $(event.target);
    var snap_num = snap_nearest(ui.value, slider);
    slider.siblings('span').each(function(index){
      if (parseInt($(this).css('left')) == snap_num){
        if (!$(this).is('.selected')){
          $(this).addClass('selected');
          slider.data('option_change_callback')(slider.data('slider_options')[index]); // Run callback function
        }
      }else{
        if ($(this).is('.selected')){
          $(this).removeClass('selected');
        }
      }
    });
  }

  // Trigger for range changes
  function trigger_range_adjust(){
    // Trigger Changes for Pressure Range --------------------------------------

    var scale_id = as_units.siblings('span.selected').data('id');
    if (!scale_id) {
      scale_id = 'inh20';
    }
    
    // Pixel values..
    //var range_min_pix = Math.round((parseFloat($('.ui-slider-handle:first', as_range).css('left')) * range_scale_data.global.scale_px_width)/100);
    //var range_max_pix = Math.round((parseFloat($('.ui-slider-handle:last', as_range).css('left')) * range_scale_data.global.scale_px_width)/100);

    var log_min = log_val(as_range_pressure.slider('values')[0], scale_id);
    var log_max = log_val(as_range_pressure.slider('values')[1], scale_id);

    $('.ui-slider-handle strong:first', as_range_pressure).text(log_min);
    $('.ui-slider-handle strong:last', as_range_pressure).text(log_max);


    // Do the damn conversion!

    as_units.siblings('span').not(':first').each(function(){
      var conv_scale = $(this).data('id');
      var conv_multiplier = range_scale_data[scale_id].conversion / range_scale_data[conv_scale].conversion;
      var conv_min = trimmed_round(log_min * conv_multiplier);
      var conv_max = trimmed_round(log_max * conv_multiplier);
      
      var handle = $('.ui-slider-range', as_range_pressure);
      /*console.log('Actual Left', handle.css('left'), 'abs left',range_percent_to_abs(parseInt(handle.css('left'))));
      console.log('slider_val', $('#as-slider-range').slider('values')[0], 'half handle width', Math.round(handle.width()/2));*/
      var handle_center = range_percent_to_abs(parseInt(handle.css('left'))) + handle.width()/2;
      //var conv = trimmed_round(log_val(handle_center, scale_id) * conv_multiplier);
      var conv = conv_min + ' / ' + conv_max;

      update_more_units(handle_center, scale_id);

      $(this).children('strong').text(conv);
    });

    // Trigger Changes for Temp Range --------------------------------------
    //* < Add/remove slash to left to enable/disable
    var conversion = 2.63; //range_scale_data.global.scale_pix_width / 165;
    var min = Math.round((as_range_temp.slider('values')[0] / conversion) - 40);
    var max = Math.round((as_range_temp.slider('values')[1] / conversion) - 40);

    $('.ui-slider-handle strong:first', as_range_temp).text(min);
    $('.ui-slider-handle strong:last', as_range_temp).text(max);//*/

    // Don't trigger a search for every change (too cpu intensive), try on release
    //trigger_update();
  }

  // Trigger for type/output changes
  // Contains logic for diabling certain packages invalid for selection
  function trigger_type_change(option){

    var change_scope = option.id.split('_')[0];

    var vm = valid_matrix;
    var comp = as_compensation.siblings('span.selected').data('id').split('_')[1];
    var type = as_type.siblings('span.selected').data('id').split('_')[1];
    var output = as_output.siblings('span.selected').data('id').split('_')[1];
    var pack = as_package.siblings('span.selected').data('id').split('_')[1];

    //console.log(change_scope, pack, type, output);

    // Favor the change scope, change the other three sliders
    if (change_scope == 'comp'){ // Compensation Slider Changed
      $.each(as_type.data('slider_options'), function(index, option){
        option.disabled = !vm[comp][pack][output][option.id.split('_')[1]];
      });

      $.each(as_output.data('slider_options'), function(index, option){
        option.disabled = !vm[comp][pack][option.id.split('_')[1]][type];
      });

      $.each(as_package.data('slider_options'), function(index, option){
        option.disabled = !vm[comp][option.id.split('_')[1]][output][type];
      });

      update_options(as_output);
      update_options(as_package);
      update_options(as_type);
    }

    // Favor the change scope, change the other three sliders
    if (change_scope == 'type'){ // Type Slider Changed

      $.each(as_compensation.data('slider_options'), function(index, option){
        option.disabled = !vm[option.id.split('_')[1]][pack][output][type];
      });

      $.each(as_output.data('slider_options'), function(index, option){
        option.disabled = !vm[comp][pack][option.id.split('_')[1]][type];
      });

      $.each(as_package.data('slider_options'), function(index, option){
        option.disabled = !vm[comp][option.id.split('_')[1]][output][type];
      });

      update_options(as_output);
      update_options(as_package);
      update_options(as_compensation);
    }


    // Favor the change scope, change the other three sliders
    if (change_scope == 'pack'){ // Package Slider Changed

      $.each(as_compensation.data('slider_options'), function(index, option){
        option.disabled = !vm[option.id.split('_')[1]][pack][output][type];
      });

      $.each(as_type.data('slider_options'), function(index, option){
        option.disabled = !vm[comp][pack][output][option.id.split('_')[1]];
      });

      $.each(as_output.data('slider_options'), function(index, option){
        option.disabled = !vm[comp][pack][option.id.split('_')[1]][type];
      });

      update_options(as_type);
      update_options(as_output);
      update_options(as_compensation);
    }


    // Favor the change scope, change the other three sliders
    if (change_scope == 'out'){ // Output Slider Changed

      $.each(as_compensation.data('slider_options'), function(index, option){
        option.disabled = !vm[option.id.split('_')[1]][pack][output][type];
      });

      $.each(as_type.data('slider_options'), function(index, option){
        option.disabled = !vm[comp][pack][output][option.id.split('_')[1]];
      });

      $.each(as_package.data('slider_options'), function(index, option){
        option.disabled = !vm[comp][option.id.split('_')[1]][output][type];
      });

      update_options(as_type);
      update_options(as_package);
      update_options(as_compensation);
    }

    
    trigger_update(option);
  }

  // Move through all slider options and update disabled status
  function update_options(slider){
    slider.siblings('span').each(function(){
      var span = $(this);
      $.each(slider.data('slider_options'), function(index, option){
        if (option.id == span.data('id')) { // Matched the span to the option...
          if (option.disabled){// If it's disabled, or not, add or remove the class
            span.addClass('disabled');

            // If the option is selected and we're disabling it, move the slider to the closest option
            if (span.is('.selected')){
              snap_slidestop({target:slider}, {value:slider.slider('value')});
              snap_slideselect({target:slider}, {value:slider.slider('value')});
            }
          }else{
            span.removeClass('disabled');
          }
        }
      });
    });
  }


  /*function draw_scale(scale_id){
    var scale = $('#as-scale-markers');
    scale.html(''); // Clear any previous markers
    var multiplier_range = [0.01, 0.1, 1, 10, 100, 1000, 10000];

    //for(var scale_num = 0; scale_num <= range_scale_data.global.scale_px_width; scale_num++){
      //var val = trimmed_round(log_val(scale_num, scale_id, true));
      
      $.each(multiplier_range, function(index, multiplier){ // Loop through multipliers
        for(var num = 1; num <= 10; num++){ // Loop 1 to 10
          var num_match = trimmed_round(num * multiplier);
          var scale_num = log_val_to_scale(num_match, scale_id);

          if (!find_marker(scale_num)){
            scale.append('<strong/>');
            $('strong:last', scale).css('left', scale_num);
            $('strong:last', scale).data('value', num_match);
            $('strong:last', scale).data('position', scale_num);
          }
        }
      });
      
    //}
  }

  function find_marker(scale_position){
    var scale = $('#as-scale-markers');
    var found = false;
    $('strong', scale).each(function(){
      // a marker is found if the value, or the position is found
      if ($(this).data('position') == scale_position){
        found = true;
      }
    });

    return found;
  }*/

  // Trigger for scale changes
  function trigger_scale_change(option){
    // Remove the known unit type classes
     as_range_pressure.siblings('.as-scale-markers').removeClass('as-scale-markers-mbar as-scale-markers-cmh20 as-scale-markers-inh20 as-scale-markers-psi');
    
    // Add the current unit class
    as_range_pressure.siblings('.as-scale-markers').addClass('as-scale-markers-' + option.id);
    
    as_range_pressure.siblings('span.labelonly').html(option.label);
    
    trigger_range_adjust();

    trigger_update(option);
  }

  // Triggers the update for the list.
  function trigger_update(option){
    var debug_switch = false;
    var unit = as_units.siblings('span.selected').data('id');
    var range_min = parseFloat($('.ui-slider-handle strong:first', as_range_pressure).text());
    var range_max = parseFloat($('.ui-slider-handle strong:last', as_range_pressure).text());
    var type = as_type.siblings('span.selected').data('id').split('_')[1];
    var output = as_output.siblings('span.selected').data('id').split('_')[1];
    var compensation = as_compensation.siblings('span.selected').data('id').split('_')[1];
    var voltage = as_voltage.siblings('span.selected').data('id').split('_')[1];
    var pack = as_package.siblings('span.selected').data('id').split('_')[1];
    //  ^^ Turns out that "package" is a reserved keyword!

    var search = as_search.val();

    //var temp = as_temp.siblings('span.selected').data('id').split('_');
    //var temp_low = parseInt(temp[1]);
    //var temp_high = parseInt(temp[2]);

    var temp_low = parseInt($('.ui-slider-handle strong:first', as_range_temp).text());
    var temp_high = parseInt($('.ui-slider-handle strong:last', as_range_temp).text());

    var results = [];


    //var time_taken = +new Date();

    // Query the JSON DB
    var add, low, high, results = [];
    $.each(product_data, function(i, p){
      
      // Assume we'll add it to the list
      add = true;
      
      // Knock it off the list if it doesn't match the criteria
      // (Only test each if it hasn't failed any of the previous tests)
      
        
        if (p.t != type[0] && type !='any'){add = false;} // Type
	
	// The converter takes the first letter of the column's data and lower cases it; A = a, Mini Side = m, CPC = c, Surface Mount = s; N = n
	if ((p.p != pack[0] && p.pb != pack[0]) && pack !='any' && add){add = false;} // Package

        // Specialty check for output to allow millivolt because all basic
        // output is also millivolt output

        var outchk = p.o;
        if (outchk == 'b') outchk = 'm';
        if (outchk != output[0] && output !='any' && add){add = false;} // Output


        // If uncompensated, hide non basic output
        if (compensation == 'uncomp' && p.o != 'b' && add){add = false;}

        // If Compensated, hide basic output
        if (compensation == 'comp' && p.o == 'b' && add){add = false;}


        
        // Additional search options (only filter if we're showing the dropdown)
        if ($('#as-slider-additional span').is('.inner-arrow-down') && add){
          if (p.sv != voltage && voltage !='any' && add){add = false;} // Voltage

          // Low & High Temperature --------------------------------------------

          // If the product's low temp is higher than the selected, hide it
          if (parseInt(p.ctl) > temp_low && add){add = false;}

          // If the product's high temp is lower than the selected, hide it
          if (parseInt(p.cth) < temp_high && add){add = false;}
        }

        // Range
        if (add){
          switch (unit){
            case 'inh20':low = p.il;high = p.ih;break;
            case 'cmh20':low = p.cl;high = p.ch;break;
            case 'psi':low = p.pl;high = p.ph;break;
            case 'mbar':low = p.ml;high = p.mh;break;
          }

          /*if (range_max > high ){ add = false; }
          if (range_min < low && add){ add = false; }*/

          // From this point on, assume it won't get in, to flip it afterward
          add = false;

          if (high <= range_max && high >= range_min){add = true;}
          
          if (low <= range_max && low >= range_min) {add = true;}
          

        }

      // Filter by words (Last, as it's cpu intensive)
      if (add && search){
        // clean out case, spaces dashes and underscores from search term
        search = search.replace(/[- _]/g,'').toUpperCase();
        var pn_opts = p.pn + ' ' + p.xref + ' ' + p.ds.replace(/[- _]/g,'').toUpperCase();
        if (pn_opts.indexOf(search) == -1){
          add = false;
        }
      }

      // If it passed, put it in the results array
      //p.pn
      if (add){results.push(p.pndisp+"|"+p.pnurl);}
    });

    // Template the results into the HTML to be outputted
    var out = '';
    $.each(results, function(i, val){ 
	  len 		= 	val.length;
	  sep_index =	val.indexOf("|",0);
	  title 	= 	val.substring(0,sep_index);
	  url_title = 	val.substring(sep_index+1,len);	  
	  
      out = out + '<div ' + (i%2 ? '' : 'class="odd"') + '><a href="/products/'+url_title+'" style="text-decoration:none;">' + title + '</a></div>';
    });

    // Update result count
    $('h4 span', as_search_header).text(results.length);

    //console.log((+new Date())-time_taken);
    if (result_cache != out){
      result_cache = out;
      as_results.html(out);
    }
		
  }

  // Callback function for end slide on snap sliders
  function snap_slidestop(event, ui){
    var slider = $(event.target);
    var snap_to_percent = (snap_nearest(ui.value, slider) * 100) / slider.slider('option', 'max');
    var duration = 800; // Time for snap animation
    var handle = slider.find('a') // Get the handle

    snap_to_percent = typeof percent === 'string' ? snap_to_percent.replace('%', '') : snap_to_percent;
    slider.slider('disable').css('opacity', 1); // Disable it while animating

    handle.animate({
      left: (("" + snap_to_percent) + '%')
    }, duration, function() {
      slider.slider('enable');
    });
  }


  // Convert an absolute slider value to the logarithmic output
  // value: Absolute slider value to be converted
  // scale_id: a reference to the name in range_scale_data that describes the min, max etc for a given scale
  function log_val(value, scale_id, no_output_limit){

    var output = 0;

    // Value caching! Assuming it's easier to read a cached value than it is to calculate it again
    if (range_scale_data[scale_id].log_val_lookup[Math.round(value)] == undefined){
      // Absolute incoming value will be between 0 and global scale range width
      var min = 0;
      var max = range_scale_data.global.scale_px_width; // Usable range of the scales

      // The log result should be calculated between the visible minimum an visible_maximum
      var minv = Math.log(range_scale_data[scale_id].visible_min);
      var maxv = Math.log(range_scale_data[scale_id].visible_max);

      // calculate adjustment factor
      var scale = (maxv-minv) / (max-min);

      // Final calulated value
      output = trimmed_round(Math.exp(minv + scale*(value-min)));
      
      // Cache the value
      range_scale_data[scale_id].log_val_lookup[Math.round(value)] = output;
    }else{
      // Pull from cached value
      output = range_scale_data[scale_id].log_val_lookup[Math.round(value)];
    }

    // The final log result should be capped at the actual min and max
    if (!no_output_limit){
      if (output < range_scale_data[scale_id].min){
        output = range_scale_data[scale_id].min;
      }

      if (output > range_scale_data[scale_id].max){
        output = range_scale_data[scale_id].max;
      }
    }
    
    return output;
  }

  // Convert a logarithmic output to a slider value
  // log_value: log value for a given scale
  // scale_id: a reference to the name in range_scale_data that describes the min, max etc for a given scale
  // Returns a 0 based scale position. if the log value is invalid, returns false
  function log_val_to_scale(log_value, scale_id){

    var scale_position = -1;

    for (var i = 0; i<= range_scale_data.global.scale_px_width; i++){
      if (log_val(i, scale_id) >= log_value){
        scale_position = i;
        break;
      }
    };
    
    return scale_position;

  }

  // Convert a percentage and convert it into an absolute number mapped to the
  // range slider max
  function range_percent_to_abs(percentage){
    return Math.round((range_scale_data.global.scale_px_width * percentage)/100);
  }

  // Rounds a number to the nearest N based on val length
  function trimmed_round(val){
    var round_to = 1000;

    /* Standard Trimmed round for length
     * switch (true){
      case (val >= 1000):
        round_to = 1;
        break;
      case (val >= 100):
        round_to = 10;
        break;
      case (val >= 10):
        round_to = 100;
        break;
    }*/

    /* Trimmed round for avoiding decimals */
    if (val < 1){
      round_to = 100;
    }else{
      round_to = 1;
    }

    return Math.round(val * round_to)/round_to;
  }


  // Work out the nearest snap to value from the argument value
  function snap_nearest(num, slider){
    var snap_vals = [];

    $.each(slider.data('slider_options'), function(i, option){
      if (!option.disabled && !option.labelonly){
        snap_vals.push(parseInt(option.position));
      }
    });
    
    
    for(var i = 0; i<= snap_vals.length - 2; i++){
      var low = snap_vals[i];
      var high = snap_vals[i+1];
      
      //console.log('num:', num, low, high, (low + high) / 2);

      // If the number is exactly the high or low val, we're done
      if (num == low || num == high){
        return num;
      }

      // if the number is greater than the high value, move on
      if (num < high) {
        // If the num is greater or equal to the average, round up
        if (num >= (low + high) / 2){
          return high;
        }else{ // Otherwise, round down
          return low;
        }
      }else if (i == snap_vals.length - 2){ // Number is greater than high value and there's no more values
        return high;
      }
    }
    return false;
  }

  // Update the more units dropdown
  function update_more_units(val, scale_id){
    var $more_units = $('#more-units-wrapper div');
    if ($more_units.is('.open')){
      var handle = $('.ui-slider-range', as_range_pressure);
      var handle_center = range_percent_to_abs(parseInt(handle.css('left'))) + handle.width()/2;

      $more_units.children('span').each(function(){
        var conv_scale = $(this).data('id');
        var conv_multiplier = range_scale_data[scale_id].conversion / range_scale_data[conv_scale].conversion;
        var conv = trimmed_round(log_val(handle_center, scale_id) * conv_multiplier);

        $(this).children('strong').text(conv);
      });
    }
  }
   
  /*   Conversion Tool */
   $('#conversion-tool').click(function(){  		
    var $arrow = $('span', this);
    var height = 660;
    var is_extended = false;

    if ($arrow.is('.inner-arrow-right')){ // Is Closed, open it
      $arrow.removeClass('inner-arrow-right').addClass('inner-arrow-down');
      $('strong', this).text('Hide Temperature Conversion');
      is_extended = true;
	  $('#product-finder').animate({'height': height}, 1000, function(){      
         $('#as-slider-additional span').removeClass('inner-arrow-right').addClass('inner-arrow-down');
      	 $('#as-slider-additional strong').text('Hide Additional Search Options');
	     trigger_range_adjust();
      });		    
	  $('#temp_conversion').show();	  
      //$('#as-slider-container').toggleClass('extended', is_extended); 	   
    }else{ // Is Open, close it
      $arrow.removeClass('inner-arrow-down').addClass('inner-arrow-right');
      $('strong', this).text('Show Temperature Conversion');
      is_extended = false;      
	  $('#temp_conversion').hide();
    }
    
    return false; // Cancel Click

  });

  $('#more-temp-wrapper a').click(function(){
    var $arrow = $('span', this);
    var time = 700;
    if ($arrow.is('.inner-arrow-right')){
      $arrow.removeClass('inner-arrow-right').addClass('inner-arrow-down');
      $('#more-temp-wrapper div').removeClass('closed')
        .addClass('open')
        .show().width(0)
        .animate({'width': 82}, time);
      $(this).animate({'left': 98}, time);
    }else{
      $arrow.removeClass('inner-arrow-down').addClass('inner-arrow-right');
      $('#more-temp-wrapper div').removeClass('open')
        .addClass('closed')
        .animate({'width': 0}, time, function(){$(this).hide()});
      $(this).animate({'left': 0}, time);
    }
  }); 
});

	function updateTemprature(name, tempVal){
		if(name == "tempC"){
			var temp = parseFloat(tempVal) + 273.15;
			document.forms['temp'].tempF.value = Math.round((((temp - 273.15)*1.8)+32)*100)/100;
			document.forms['temp'].tempK.value = temp;
		}else if(name == "tempF"){
			var temp = Math.round((((parseFloat(tempVal)-32)/1.8) + 273.15)*100)/100;
			document.forms['temp'].tempC.value = (temp - 273.15);
			document.forms['temp'].tempK.value = temp;
		}else if(name == "tempK"){
			var temp = parseFloat(tempVal);
			document.forms['temp'].tempC.value = (temp - 273.15);
			document.forms['temp'].tempF.value = Math.round((((temp - 273.15)*1.8)+32)*100)/100;
		} 
	} 

