ISCPriceSlider = Class.create( ISCPriceDisplay, {
tlog: function(msg) { },
initialize: function( data, config ) {
this.search_constraints = data.search_constraints;
this.search_constraints.price_slider = this;
this.config = config;
},
setup: function() {
$('price_slider_display').show();
this.increment = this.search_constraints.isc.data.price_slider_incr || 5;
this.value_inputs = this.config.value_inputs;
this.currency_format = this.config.currency || {thou:',', dec:'.', symbol:'$'};
this.currency_regex = new RegExp('^[1-9][0-9]{0,2}(' + "\\" + this.currency_format.thou + '{0,1}[0-9]{3})*(' + "\\" + this.currency_format.dec + '[0-9]{2})?$');
this.symbol_regex = new RegExp("\\" + this.currency_format.symbol,'g');
this.additional_max_prices = false;
this.prev_val = [];
this.psPopup = new Popup( 'isc-priceslider-info-box', {
close_id: 'pricesliderPopupClose',
zIndex: 105,
links: [{
group: 'edp',
link_id: 'QMark98',
toggle: true,
anchor_align:  { x:  1, y: -1 },
popup_align: { x: -1, y: -1 },
offset: { x: 5, y: 0}
}]
});
this.create_price_data();
this.create_slider_control();
this.observe_slider();
},
reset: function() {
this.slider.reset_handles();
},
get_price_range: function(internal) {
var vals = [];
this.value_inputs.each( function(v,idx) {
var value = v.value;
if( !internal && v == this.has_focus ) {
value = this.prev_val[idx] + '';
}
value = this.scrub_separators(value);
if( value.match(/\+/) ) {
vals.push( this.actual_price.max );
}
else {
var to_push = Number(value);
if( isNaN( to_push ) ) {
to_push = this.prev_val[idx];
}
vals.push( to_push );
}
}.bind(this));
return vals;
},
register_on_price_change_handler: function( handler ) {
document.observe( 'price_slider:changed', handler );
},
create_slider_control: function() {
var ps = this;
this.slider = new Slider(this.config.parent, this.config.track, {
style: {
'handle':this.config.handle,
'max_z':50
},
type:this.config.type,
range: {
min:this.display_price.min/this.increment,
max:this.display_price.max/this.increment
},
snap_to: true,
onSlide: this.update_vals.bind(this),
onCreate: this.update_vals.bind(this)
});
this.eventChange = this.check_user_input.bindAsEventListener(this);
this.fieldFocus = this.accept_user_input.bindAsEventListener(this);
this.keyPress = this.check_keypress.bindAsEventListener(this);
this.value_inputs.each( function(v,idx) {
v.observe("change", ps.eventChange);
v.observe("focus", ps.fieldFocus);
v.observe("blur", ps.fieldFocus);
v.observe("keydown", ps.keyPress);
});
},
observe_slider: function() {
document.observe("slider:handle_clicked", function(event){
var input = event.memo.handle_type == 'min' ? 0 : 1;
this.slide_active = true;
this.value_inputs[input].addClassName('highlight');
click_track.log_datapoint( { price_slider_used: '', __log_only_once__: 'price_slider_used' } );
}.bind(this));
document.observe("slider:handle_released", function(event){
var input = event.memo.handle_type == 'min' ? 0 : 1;
this.slide_active = false;
this.value_inputs[input].removeClassName('highlight');
}.bind(this));
document.observe( 'slider:change', function(event){
var cur_val = this.get_price_range(true);
for( var i = 0 ; i < cur_val.length ; i++ ) {
if( cur_val[i] != this.prev_val[i] ) {
this.prev_val[i] = cur_val[i];
document.fire('price_slider:changed');
}
}
}.bind(this) );
},
update_vals: function(val) {
this.value_inputs[0].value = this.format_price(val[0]);
this.value_inputs[1].value = this.format_price(val[1]);
},
create_price_data: function() {
var enabled_tts = this.search_constraints.isc.edp.event.get_enabled_ticket_types();
var preferred = this.search_constraints.preferred;
var min_all_in_price;
var max_all_in_price;
var prices = [];
var handle_element = new Element('div');
handle_element.className = this.config.handle;
var dom_elem = $(this.config.parent).appendChild( handle_element );
var max_range = ($(this.config.track).getWidth() - dom_elem.getWidth()) * this.increment;
dom_elem.remove();
for( var i = 0 ; i < enabled_tts.length ; i ++ ) {
var tt = enabled_tts[i];
if( !tt.children ) {
for( var price_level in tt.real_price_breakdown ) {
var total_price = tt.real_price_breakdown[price_level].display_charges.total_price;
if( total_price < min_all_in_price || typeof min_all_in_price == 'undefined' ) {
min_all_in_price = total_price;
}
if( total_price > max_all_in_price || typeof max_all_in_price == 'undefined' ) {
max_all_in_price = total_price;
}
if( tt.ext_ticket_type == preferred.ext_ticket_type ) {
prices.push( total_price );
}
}
}
}
prices = prices.sort(function(a,b){return a - b;}).uniq();
this.actual_price = { min:Number( min_all_in_price ), max:Number( max_all_in_price ) };
var disp_max = this.calc_display_max( prices );
var disp_min = this.calc_display_min( min_all_in_price );
if( (disp_max - disp_min) > max_range ) {
var new_cutoff = max_range + disp_min;
disp_max = this.calc_display_max( prices, new_cutoff );
}
if( disp_max == disp_min ) {
disp_max = Math.ceil( prices[ prices.length - 1 ] / this.increment ) * this.increment;
if( disp_max >= this.actual_price.max && this.additional_max_prices ) {
this.additional_max_prices = false;
}
}
this.display_price = { min:disp_min, max:disp_max };
this.prev_val.push( this.display_price.min );
if( this.additional_max_prices ) {
this.prev_val.push( this.actual_price.max );
}
else {
this.prev_val.push( this.display_price.max );
}
},
format_price: function( val ) {
var price = val * this.increment;
var fprice;
var s_price = price.toString();
if( s_price.length <= 3 ) {
fprice = price + this.currency_format.dec + '00';
}
else {
var new_num = [];
var count = 1;
for( var i = s_price.length - 1 ; i >= 0 ; i-- ) {
new_num.push( s_price.charAt(i) );
if( count % 3 == 0 && i != 0 ) {
new_num.push( this.currency_format.thou );
}
count++;
}
fprice = new_num.reverse().join('') + this.currency_format.dec + '00';
}
if( price == this.display_price.max && this.additional_max_prices ) {
fprice += '+';
}
return fprice;
},
check_keypress: function(event) {
if( event.keyCode == Event.KEY_RETURN ) {
this.check_user_input(event);
}
},
accept_user_input: function(event) {
var field = event.element();
if( event.type == 'focus' ) {
this.old_val = field.value;
this.has_focus = field;
field.clear();
field.addClassName('highlight');
}
else {
var value = field.value.strip();
if( value.empty() ) {
field.value = this.old_val;
}
this.has_focus = null;
if( !this.slide_active ) {
field.removeClassName('highlight');
}
}
},
check_user_input: function(event) {
var input = event.element();
var type = this.value_inputs[0] == input ? 'min' : 'max';
var val = input.value;
val = val.strip().replace(this.symbol_regex,'');
if( val.empty() || !this.valid_currency(val) ) {
val = type == 'min' ? this.prev_val[0] : this.prev_val[1];
val += '';
}
val = Number( this.scrub_separators( val ) );
var comp_var;
if( type == 'min' ) {
comp_var = Number( this.scrub_separators( this.value_inputs[1].value.replace(/\+/g,'') ) );
}
else {
comp_var = Number( this.scrub_separators( this.value_inputs[0].value ) );
}
if( type == 'min' && val >= comp_var ) {
val = comp_var - this.increment;
}
if( type == 'max' && val <= comp_var ) {
val = comp_var + this.increment;
}
if( val % this.increment != 0 ) {
val = Math.round(val);
if( type == 'min' ) {
val = this.calc_display_min(val);
}
else {
val = val + ( this.increment - (val % this.increment) );
}
}
val = val / this.increment;
if( event.keyCode == Event.KEY_RETURN ) {
input.blur();
}
this.slider.input_update(type,val);
},
valid_currency: function(val) {
return ( val.match(/^(\d+)$/) || val.match(this.currency_regex) );
},
scrub_separators: function(val) {
if( this.currency_format.dec == ',' ) {
val = val.replace(/\./,'');
val = val.replace(/,/,'.');
}
else {
val = val.replace(/,/,'');
}
return val;
},
calc_display_min: function( val ) {
if( val < this.increment ) {
return 0;
}
else {
return val - ( val % this.increment );
}
},
calc_display_max: function( prices, new_cutoff ) {
var global_median = this.calc_median(prices).toFixed(2);
var q1_list = [];
prices.each( function(price) {
if( price <= global_median ) {
q1_list.push(price);
}
});
var q1 = this.calc_median(q1_list);
var cutoff = new_cutoff ? new_cutoff : ( ( prices[0] * 1 ) + ( 4 * q1 ) );
var display_max = 0;
for( var p = 0 ; p < prices.length ; p++ ) {
var price = Math.ceil( prices[p] );
if( price <= cutoff ) {
display_max = Math.ceil( price / this.increment ) * this.increment;
}
}
if( display_max < this.actual_price.max  ) {
this.additional_max_prices = true;
}
return display_max;
},
calc_median: function( list ) {
var middle = Math.floor(list.length / 2);
if( list.length % 2 != 0 ) {
return list[middle] * 1;
}
else {
return (list[middle - 1] + list[middle]) / 2;
}
}
} );

