
var Slider = Class.create( {
tlog: function( msg ) { },
initialize: function( parent, track, options ) {
false;
false;
this.track = $(track);
this.parent = $(parent);
this.handles = [];
this.options = options || {};
this.axis = this.options.axis || 'horizontal';
this.type = this.options.type || 'single';
this.snap_to = this.options.snap_to || false;
this.handle_space = this.options.handle_space || 0;
this.zero_start = this.options.zero_start || false;
this.styles = this.options.style || {};
this.range = this.options.range ? $R(this.options.range.min, this.options.range.max) : $R(1,100);
this.track_length = parseFloat(this.track.getStyle('width').replace(/px$/,""));
this.track_height = parseFloat(this.track.getStyle('height').replace(/px$/,""));
this.track_offsets = $(this.track).cumulativeOffset();
this.track_set = false;
this.increment = 1;
this.dragging = false;
this.active = false;
this.position = [];
this.start_position = [];
this.prev_val = [];
this.max_z = this.styles.max_z || 100;
this.min_max_overlap = this.options.min_max_overlap || false;
this.make_handles();
this.make_values();
this.render();
},
make_handles: function() {
false;
var h_size = this.is_single() ? 1 : 2;
for( i = 1 ; i <= h_size ; i++ ) {
false;
var handle_element = new Element('div');
handle_element.className = this.styles.handle;
handle_element.id = 'handle' + i;
var dom_elem = this.parent.appendChild( handle_element );
this.base_z = dom_elem.getStyle('zIndex') || 1;
this.handle_width = parseFloat(dom_elem.getStyle('width').replace(/px$/,""));
this.handle_offset = this.handle_width / 2;
var start_point = i == 1 ? this.track.offsetLeft : (this.track_length - this.handle_width);
dom_elem.setStyle({left:start_point + 'px'});
this.position.push( start_point );
this.start_position.push( start_point );
this.handles.push( handle_element );
}
},
make_values: function() {
false;
var track_size = this.track_length - this.handle_width;
this.px_per_val = track_size / this.range.size();
this.tick_array = this.range.toArray();
this.prev_val = [this.range.start, this.range.end];
},
start_drag: function(event) {
this.check_offsets();
if( this.handles.include(event.element()) && Event.isLeftClick(event) ) {
false;
Event.observe(document.body, "mousemove", this.eventMouseMove);
this.active_handle = event.element();
this.active_handle_idx = this.handles.indexOf( this.active_handle );
this.activate_handle();
this.dragging = true;
this.active = true;
this.is_click = false;
Event.stop(event);
}
else if( Event.isLeftClick(event) ) {
false;
var pointer = { x : Event.pointerX(event), y : Event.pointerY(event) };
var my_pos = pointer.x - this.track_offsets.left;
this.dragging = true;
this.active = true;
this.is_click = true;
this.active_handle_idx = this.is_single() ? 0 :
( Math.abs(my_pos - this.position[0]) <= Math.abs(my_pos - this.position[1]) ? 0 : 1 );
this.active_handle = this.handles[ this.active_handle_idx ];
this.activate_handle(true);
this.update(event);
this.end_drag(event);
Event.stop(event);
}
},
end_drag: function(event) {
if( this.active && this.dragging ) {
false;
Event.stopObserving(document.body, "mousemove", this.eventMouseMove);
this.dragging = false;
this.active = false;
this.fire_slider_changed();
if( !this.is_click ) {
this.fire_handle_released();
}
Event.stop(event);
}
},
update: function(event,pointer) {
this.check_offsets();
if( this.dragging ) {
var pointer = { x : Event.pointerX(event), y : Event.pointerY(event) };
var track_offsets = this.track_offsets;
var my_pos = pointer.x - track_offsets.left - this.handle_offset;
if( my_pos <= this.start_position[1] && my_pos >= this.start_position[0] ) {
this.position[ this.active_handle_idx ] = my_pos;
}
else {
if( my_pos < this.start_position[0] ) {
this.position[ this.active_handle_idx ] = this.start_position[0];
}
else {
this.position[ this.active_handle_idx ] = this.start_position[1];
}
}
var cur_vals;
if( this.snap_to ) {
cur_vals = this.get_closest_val();
this.position[ this.active_handle_idx ] = this.get_closest_px( cur_vals[ this.active_handle_idx ] );
}
if( !this.min_max_overlap ) {
cur_vals = cur_vals ? cur_vals : this.get_closest_val();
if( this.active_handle_idx == 1 && cur_vals[ this.active_handle_idx ] == this.tick_array[0] ) {
this.position[ this.active_handle_idx ] = this.get_closest_px( 1 );
}
if( this.active_handle_idx == 0 && cur_vals[ this.active_handle_idx ] == this.tick_array[ this.tick_array.length - 1 ] ) {
this.position[ this.active_handle_idx ] = this.get_closest_px( (this.tick_array.length - 2) + this.tick_array[0] );
if( Math.abs( this.position[ this.active_handle_idx ] - this.position[1] ) > this.px_per_val  ) {
this.position[ this.active_handle_idx ] += this.px_per_val;
}
}
}
if( !this.is_single() ) {
var handle_space = this.handle_space;
handle_space += !this.min_max_overlap ? this.px_per_val : 0;
if( this.active_handle_idx == 1 && this.position[ this.active_handle_idx ] <= (this.position[0] + handle_space) ) {
this.position[ this.active_handle_idx ] = this.position[0] + handle_space;
}
if( this.active_handle_idx == 0 && this.position[ this.active_handle_idx ] >= (this.position[1] - handle_space) ) {
this.position[ this.active_handle_idx ] = this.position[1] - handle_space;
}
}
this.draw();
Event.stop(event);
}
},
draw: function() {
if( this.can_move() ) {
this.handles[ this.active_handle_idx ].style.left = this.position[ this.active_handle_idx ] + 'px';
var span_width = Math.ceil( this.position[1] - this.position[0] ) + 'px';
this.track.style.left = this.position[0] + this.handle_offset + 'px';
this.track.setStyle({width:span_width});
}
var return_vals = this.get_closest_val();
this.prev_val = return_vals;
if( this.options.onSlide ) {
this.options.onSlide( return_vals );
}
},
can_move: function() {
if( !this.snap_to ) {
return true;
}
var cur_vals = this.get_closest_val();
var can_move = cur_vals[ this.active_handle_idx ] != this.prev_val[ this.active_handle_idx ];
var comp_pos = this.start_position;
if( this.position[ this.active_handle_idx ] == comp_pos[ this.active_handle_idx ] || this.position[ this.active_handle_idx ] == comp_pos[ this.active_handle_idx ^ 1 ] ) {
return true;
}
else {
return can_move;
}
},
get_closest_val: function() {
var return_array = [];
var position_values = this.position;
for( var i = 0 ; i < position_values.length ; i++ ) {
var my_pos = position_values[i];
var val = (my_pos / (this.track_length - this.handle_width) * (this.range.end - this.range.start)) + this.range.start;
if( val > this.range.end ) {
val = this.range.end;
}
else if( val < this.range.start ) {
val = this.range.start;
}
return_array.push( Math.round(val) );
}
return return_array;
},
get_closest_px: function(tick_val) {
var tick_index = this.tick_array.indexOf( parseInt(tick_val) );
var val_range = [ this.range.start, this.range.end ];
var start_pos = [ this.start_position.min(), this.start_position.max() ];
var slide_px = (this.track_length - this.handle_width) / (val_range[1] - val_range[0]) * (tick_val - val_range[0]);
if( slide_px > start_pos[1] || tick_val >= val_range[1] ) {
slide_px = start_pos[1];
}
else if( slide_px < start_pos[0] || tick_val <= val_range[0] ) {
slide_px = start_pos[0];
}
return slide_px;
},
check_offsets: function() {
if( !this.track_set ) {
var new_offsets = this.track.cumulativeOffset();
if( this.track_offsets != new_offsets ) {
this.track_offsets = new_offsets;
this.track_set = true;
}
}
},
input_update: function(handle_type,tick_val) {
false;
this.active_handle_idx = this.is_single() || handle_type == 'min' ? 0 : 1;
this.active_handle = this.handles[ this.active_handle_idx ];
var slide_val = this.get_closest_px(tick_val);
this.position[ this.active_handle_idx ] = slide_val;
this.activate_handle(true);
this.draw();
this.fire_slider_changed();
},
activate_handle: function(not_drag) {
for( var i = 0 ; i < this.handles.length ; i++ ) {
this.handles[i].style.zIndex = i == this.active_handle_idx ? this.max_z : this.base_z;
}
if( !not_drag ) {
this.fire_handle_clicked();
}
},
reset_handles: function() {
for( var j = 0 ; j < this.handles.length ; j++ ) {
this.active_handle_idx = j;
this.active_handle = this.handles[j];
this.position[j] = this.start_position[j];
this.draw();
}
this.fire_slider_reset();
},
fire_slider_reset: function() {
this.track.fire('slider:reset');
},
fire_slider_changed: function() {
this.track.fire('slider:change');
},
fire_handle_clicked: function() {
var h_type = this.is_single() || this.active_handle_idx == 0 ? 'min' : 'max';
this.active_handle.fire('slider:handle_clicked',{ handle_type: h_type });
},
fire_handle_released: function() {
var h_type = this.is_single() || this.active_handle_idx == 0 ? 'min' : 'max';
this.active_handle.fire('slider:handle_released',{ handle_type: h_type });
},
register_on_price_change_handler: function( handler ) {
var slider_node = this.parent;
Event.observe( slider_node, 'slider:change', handler );
},
is_vertical: function() {
return this.axis == 'vertical';
},
is_single: function() {
return this.type == 'single';
},
render: function() {
var slider = this;
false;
this.eventMouseDown = this.start_drag.bindAsEventListener(this);
this.eventMouseUp   = this.end_drag.bindAsEventListener(this);
this.eventMouseMove = this.update.bindAsEventListener(this);
this.handles.each( function(h) {
h.observe("mousedown", slider.eventMouseDown);
});
this.parent.observe("mousedown", this.eventMouseDown);
Event.observe(document.body, "mouseup", this.eventMouseUp);
var return_vals = this.get_closest_val();
if( this.options.onCreate ) {
this.options.onCreate( return_vals );
}
}
} );

