From d8f0a3f93ca80fa64435dde8100d0eae6110207c Mon Sep 17 00:00:00 2001 From: Thomas Fuchs Date: Sat, 29 Oct 2005 11:48:53 +0000 Subject: Update script.aculo.us to V1.5_rc4 git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@2802 5ecf4fe2-1ee6-0310-87b1-e25e094e27de --- railties/html/javascripts/slider.js | 282 ++++++++++++++++-------------------- 1 file changed, 125 insertions(+), 157 deletions(-) (limited to 'railties/html/javascripts/slider.js') diff --git a/railties/html/javascripts/slider.js b/railties/html/javascripts/slider.js index 1712b98943..736ed41a86 100644 --- a/railties/html/javascripts/slider.js +++ b/railties/html/javascripts/slider.js @@ -7,166 +7,182 @@ Control.Slider = Class.create(); // options: // axis: 'vertical', or 'horizontal' (default) -// increment: (default: 1) -// step: (default: 1) // // callbacks: // onChange(value) // onSlide(value) Control.Slider.prototype = { initialize: function(handle, track, options) { - this.handle = $(handle); + var slider = this; + + if(handle instanceof Array) { + this.handles = handle.collect( function(e) { return $(e) }); + } else { + this.handles = [$(handle)]; + } + this.track = $(track); - this.options = options || {}; this.axis = this.options.axis || 'horizontal'; this.increment = this.options.increment || 1; - this.step = parseInt(this.options.step) || 1; - this.value = 0; - - var defaultMaximum = Math.round(this.track.offsetWidth / this.increment); - if(this.isVertical()) defaultMaximum = Math.round(this.track.offsetHeight / this.increment); + this.step = parseInt(this.options.step || '1'); + this.range = this.options.range || $R(0,1); - this.maximum = this.options.maximum || defaultMaximum; - this.minimum = this.options.minimum || 0; - - // Will be used to align the handle onto the track, if necessary - this.alignX = parseInt (this.options.alignX) || 0; - this.alignY = parseInt (this.options.alignY) || 0; - - // Zero out the slider position - this.setCurrentLeft(Position.cumulativeOffset(this.track)[0] - Position.cumulativeOffset(this.handle)[0] + this.alignX); - this.setCurrentTop(this.trackTop() - Position.cumulativeOffset(this.handle)[1] + this.alignY); + this.value = 0; // assure backwards compat + this.values = this.handles.map( function() { return 0 }); + this.spans = this.options.spans ? this.options.spans.map(function(s){ return $(s) }) : false; + this.restricted = this.options.restricted || false; - this.offsetX = 0; - this.offsetY = 0; + this.maximum = this.options.maximum || this.range.end; + this.minimum = this.options.minimum || this.range.start; - this.originalLeft = this.currentLeft(); - this.originalTop = this.currentTop(); - this.originalZ = parseInt(this.handle.style.zIndex || "0"); - - // Prepopulate Slider value - this.setSliderValue(parseInt(this.options.sliderValue) || 0); + // Will be used to align the handle onto the track, if necessary + this.alignX = parseInt(this.options.alignX || '0'); + this.alignY = parseInt(this.options.alignY || '0'); + + this.trackLength = this.maximumOffset() - this.minimumOffset(); this.active = false; this.dragging = false; this.disabled = false; - // FIXME: use css - this.handleImage = $(this.options.handleImage) || false; - this.handleDisabled = this.options.handleDisabled || false; - this.handleEnabled = false; - if(this.handleImage) - this.handleEnabled = this.handleImage.src || false; - - if(this.options.disabled) - this.setDisabled(); - - // Value Array - this.values = this.options.values || false; // Add method to validate and sort?? + if(this.options.disabled) this.setDisabled(); - Element.makePositioned(this.handle); // fix IE + // Allowed values array + this.allowedValues = this.options.values ? this.options.values.sortBy(Prototype.K) : false; + if(this.allowedValues) { + this.minimum = this.allowedValues.min(); + this.maximum = this.allowedValues.max(); + } this.eventMouseDown = this.startDrag.bindAsEventListener(this); this.eventMouseUp = this.endDrag.bindAsEventListener(this); this.eventMouseMove = this.update.bindAsEventListener(this); - this.eventKeypress = this.keyPress.bindAsEventListener(this); - Event.observe(this.handle, "mousedown", this.eventMouseDown); + // Initialize handles + this.handles.each( function(h,i) { + slider.setValue(parseInt(slider.options.sliderValue || slider.range.start), i); + Element.makePositioned(h); // fix IE + Event.observe(h, "mousedown", slider.eventMouseDown); + }); + Event.observe(document, "mouseup", this.eventMouseUp); Event.observe(document, "mousemove", this.eventMouseMove); - Event.observe(document, "keypress", this.eventKeypress); }, dispose: function() { - Event.stopObserving(this.handle, "mousedown", this.eventMouseDown); + var slider = this; Event.stopObserving(document, "mouseup", this.eventMouseUp); Event.stopObserving(document, "mousemove", this.eventMouseMove); - Event.stopObserving(document, "keypress", this.eventKeypress); + this.handles.each( function(h) { + Event.stopObserving(h, "mousedown", slider.eventMouseDown); + }); }, setDisabled: function(){ this.disabled = true; - if(this.handleDisabled) - this.handleImage.src = this.handleDisabled; }, setEnabled: function(){ this.disabled = false; - if(this.handleEnabled) - this.handleImage.src = this.handleEnabled; }, - currentLeft: function() { - return parseInt(this.handle.style.left || '0'); - }, - currentTop: function() { - return parseInt(this.handle.style.top || '0'); - }, - setCurrentLeft: function(left) { - this.handle.style.left = left +"px"; - }, - setCurrentTop: function(top) { - this.handle.style.top = top +"px"; - }, - trackLeft: function(){ - return Position.cumulativeOffset(this.track)[0]; - }, - trackTop: function(){ - return Position.cumulativeOffset(this.track)[1]; - }, getNearestValue: function(value){ - if(this.values){ - var i = 0; - var offset = Math.abs(this.values[0] - value); - var newValue = this.values[0]; - - for(i=0; i < this.values.length; i++){ - var currentOffset = Math.abs(this.values[i] - value); - if(currentOffset < offset){ - newValue = this.values[i]; + if(this.allowedValues){ + if(value >= this.allowedValues.max()) return(this.allowedValues.max()); + if(value <= this.allowedValues.min()) return(this.allowedValues.min()); + + var offset = Math.abs(this.allowedValues[0] - value); + var newValue = this.allowedValues[0]; + this.allowedValues.each( function(v) { + var currentOffset = Math.abs(v - value); + if(currentOffset <= offset){ + newValue = v; offset = currentOffset; - } - } + } + }); return newValue; } + if(value > this.range.end) return this.range.end; + if(value < this.range.start) return this.range.start; return value; }, - setSliderValue: function(sliderValue){ - // First check our max and minimum and nearest values - sliderValue = this.getNearestValue(sliderValue); - if(sliderValue > this.maximum) sliderValue = this.maximum; - if(sliderValue < this.minimum) sliderValue = this.minimum; - var offsetDiff = (sliderValue - (this.value||this.minimum)) * this.increment; - - if(this.isVertical()){ - this.setCurrentTop(offsetDiff + this.currentTop()); - } else { - this.setCurrentLeft(offsetDiff + this.currentLeft()); + setValue: function(sliderValue, handleIdx){ + if(!this.active) { + this.activeHandle = this.handles[handleIdx]; + this.activeHandleIdx = handleIdx; + } + handleIdx = handleIdx || this.activeHandleIdx || 0; + if(this.restricted) { + if((handleIdx>0) && (sliderValuethis.values[handleIdx+1])) + sliderValue = this.values[handleIdx+1]; } - this.value = sliderValue; + sliderValue = this.getNearestValue(sliderValue); + this.values[handleIdx] = sliderValue; + this.value = this.values[0]; // assure backwards compat + + this.handles[handleIdx].style[ this.isVertical() ? 'top' : 'left'] = + this.translateToPx(sliderValue); + + this.drawSpans(); this.updateFinished(); - }, + }, + setValueBy: function(delta, handleIdx) { + this.setValue(this.values[handleIdx || this.activeHandleIdx || 0] + delta, + handleIdx || this.activeHandleIdx || 0); + }, + translateToPx: function(value) { + return Math.round((this.trackLength / (this.range.end - this.range.start)) * (value - this.range.start)) + "px"; + }, + translateToValue: function(offset) { + return ((offset/this.trackLength) * (this.range.end - this.range.start)) + this.range.start; + }, + getRange: function(range) { + var v = this.values.sortBy(Prototype.K); + range = range || 0; + return $R(v[range],v[range+1]); + }, minimumOffset: function(){ - return(this.isVertical() ? - this.trackTop() + this.alignY : - this.trackLeft() + this.alignX); + return(this.isVertical() ? this.alignY : this.alignX); }, maximumOffset: function(){ return(this.isVertical() ? - this.trackTop() + this.alignY + (this.maximum - this.minimum) * this.increment : - this.trackLeft() + this.alignX + (this.maximum - this.minimum) * this.increment); + this.track.offsetHeight - this.alignY : this.track.offsetWidth - this.alignX); }, isVertical: function(){ return (this.axis == 'vertical'); }, + drawSpans: function() { + var slider = this; + if(this.spans) + $R(0, this.spans.length-1).each(function(r) { slider.setSpan(r, slider.getRange(r)) }); + }, + setSpan: function(span, range) { + if(this.isVertical()) { + this.spans[span].style.top = this.translateToPx(range.start); + this.spans[span].style.height = this.translateToPx(range.end - range.start); + } else { + this.spans[span].style.left = this.translateToPx(range.start); + this.spans[span].style.width = this.translateToPx(range.end - range.start); + } + }, startDrag: function(event) { if(Event.isLeftClick(event)) { if(!this.disabled){ this.active = true; - var pointer = [Event.pointerX(event), Event.pointerY(event)]; - var offsets = Position.cumulativeOffset(this.handle); - this.offsetX = (pointer[0] - offsets[0]); - this.offsetY = (pointer[1] - offsets[1]); - this.originalLeft = this.currentLeft(); - this.originalTop = this.currentTop(); + + // find the handle (prevents issues with Safari) + var handle = Event.element(event); + while((this.handles.indexOf(handle) == -1) && handle.parentNode) + handle = handle.parentNode; + + this.activeHandle = handle; + this.activeHandleIdx = this.handles.indexOf(this.activeHandle); + + var pointer = [Event.pointerX(event), Event.pointerY(event)]; + var offsets = Position.cumulativeOffset(this.activeHandle); + this.offsetX = (pointer[0] - offsets[0]); + this.offsetY = (pointer[1] - offsets[1]); + } Event.stop(event); } @@ -174,10 +190,8 @@ Control.Slider.prototype = { update: function(event) { if(this.active) { if(!this.dragging) { - var style = this.handle.style; this.dragging = true; - if(style.position=="") style.position = "relative"; - style.zIndex = this.options.zindex; + if(this.activeHandle.style.position=="") style.position = "relative"; } this.draw(event); // fix AppleWebKit rendering @@ -187,43 +201,11 @@ Control.Slider.prototype = { }, draw: function(event) { var pointer = [Event.pointerX(event), Event.pointerY(event)]; - var offsets = Position.cumulativeOffset(this.handle); - - offsets[0] -= this.currentLeft(); - offsets[1] -= this.currentTop(); - - // Adjust for the pointer's position on the handle - pointer[0] -= this.offsetX; - pointer[1] -= this.offsetY; - var style = this.handle.style; - - if(this.isVertical()){ - if(pointer[1] > this.maximumOffset()) - pointer[1] = this.maximumOffset(); - if(pointer[1] < this.minimumOffset()) - pointer[1] = this.minimumOffset(); - - // Increment by values - if(this.values){ - this.value = this.getNearestValue(Math.round((pointer[1] - this.minimumOffset()) / this.increment) + this.minimum); - pointer[1] = this.trackTop() + this.alignY + (this.value - this.minimum) * this.increment; - } else { - this.value = Math.round((pointer[1] - this.minimumOffset()) / this.increment) + this.minimum; - } - style.top = pointer[1] - offsets[1] + "px"; - } else { - if(pointer[0] > this.maximumOffset()) pointer[0] = this.maximumOffset(); - if(pointer[0] < this.minimumOffset()) pointer[0] = this.minimumOffset(); - // Increment by values - if(this.values){ - this.value = this.getNearestValue(Math.round((pointer[0] - this.minimumOffset()) / this.increment) + this.minimum); - pointer[0] = this.trackLeft() + this.alignX + (this.value - this.minimum) * this.increment; - } else { - this.value = Math.round((pointer[0] - this.minimumOffset()) / this.increment) + this.minimum; - } - style.left = (pointer[0] - offsets[0]) + "px"; - } - if(this.options.onSlide) this.options.onSlide(this.value); + var offsets = Position.cumulativeOffset(this.track); + pointer[0] -= this.offsetX + offsets[0]; + pointer[1] -= this.offsetY + offsets[1]; + this.setValue(this.translateToValue( this.isVertical() ? pointer[1] : pointer[0] )); + if(this.options.onSlide) this.options.onSlide(this.values.length>1 ? this.values : this.value, this); }, endDrag: function(event) { if(this.active && this.dragging) { @@ -236,23 +218,9 @@ Control.Slider.prototype = { finishDrag: function(event, success) { this.active = false; this.dragging = false; - this.handle.style.zIndex = this.originalZ; - this.originalLeft = this.currentLeft(); - this.originalTop = this.currentTop(); this.updateFinished(); }, updateFinished: function() { - if(this.options.onChange) this.options.onChange(this.value); - }, - keyPress: function(event) { - if(this.active && !this.disabled) { - switch(event.keyCode) { - case Event.KEY_ESC: - this.finishDrag(event, false); - Event.stop(event); - break; - } - if(navigator.appVersion.indexOf('AppleWebKit')>0) Event.stop(event); - } + if(this.options.onChange) this.options.onChange(this.values.length>1 ? this.values : this.value, this); } } -- cgit v1.2.3