All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.smartclient.debug.public.sc.client.widgets.Slider.js Maven / Gradle / Ivy

The newest version!
/*
 * Isomorphic SmartClient
 * Version SC_SNAPSHOT-2011-08-08 (2011-08-08)
 * Copyright(c) 1998 and beyond Isomorphic Software, Inc. All rights reserved.
 * "SmartClient" is a trademark of Isomorphic Software, Inc.
 *
 * [email protected]
 *
 * http://smartclient.com/license
 */

 
/*---------->    isc.Slider.js    <----------*/

//	The Slider class was developed as an instructional/documentation example of
//	creating a new widget class, covering a broad range of ISC client-side
//	framework concepts and conventions.

// Questions: [email protected]





//----------  Description  ----------\\
//> @class Slider
//	The Slider class implements a GUI slider widget allowing the user to select a numeric 
//  value from within a range by dragging a visual indicator up and down a track.
//	

// The slider will generate events as the user interacts with it and changes its value. // If slider.sliderTarget is specified, moving the slider thumb generates a custom // event named 'sliderMove', sent to the sliderTarget. // If a sliderMove handler stringMethod is defined on the target, it will be // fired when the slider is moved. The second parameter (available via the variable name // eventInfo if the handler is a string) is a pointer back to the slider. //

// The slider will also fire a valueChanged() method whenever its value is // changed. This can be observed or overridden on the Slider instance to perform some action. // // @treeLocation Client Reference/Control // @visibility external // @example slider //< //---------- Create the class ----------\\ isc.ClassFactory.defineClass("Slider", isc.Canvas); //---------- Define static properties ----------\\ isc.Slider.addClassProperties({ // isc.Slider.DOWN down state for the slider thumb DOWN:"down", // isc.Slider.UP up (enabled) state for the slider thumb UP:"", // isc.Slider.EVENTNAME name of event sent to sliderTarget when thumb moved EVENTNAME:"sliderMove" }); //---------- Define instance properties ----------\\ isc.Slider.addProperties({ //> @attr slider.title (String : "Set Value" : [IRW]) // Optional display title for the slider. // @see attr:showTitle // @visibility external //< title:"Set Value", //> @attr slider.length (integer : 200 : [IRW]) // Used to set slider height if vertical, slider width if horizontal. // Applied to the slider track, not necessarily the entire widget. // Overridden by an explicit width/height specification for the widget. // @visibility external //< length:200, //> @attr slider.vertical (boolean : true : [IRW]) // Indicates whether this is a vertical or horizontal slider. // @visibility external // @example slider //< vertical:true, //> @attr slider.thumbThickWidth (integer : 23 : [IRW]) // The dimension of the thumb perpendicular to the slider track. // @visibility external //< thumbThickWidth:23, //> @attr slider.thumbThinWidth (integer : 17 : [IRW]) // The dimension of the thumb parallel to the slider track. // @visibility external //< thumbThinWidth:17, //> @attr slider.trackWidth (integer : 7 : [IRW]) // The thickness of the track. This is the width, for a vertical slider, or the height, for // a horizontal slider. // @visibility external //< trackWidth:7, //> @attr slider.hThumbStyle (CSSStyleName : null : IR) // Optional CSS style for the thumb for a horizontally oriented slider. //

// Will have the suffix "down" added when the mouse is down on the thumb, and "Disabled" // added when the slider is disabled. // // @visibility external //< //> @attr slider.vThumbStyle (CSSStyleName : null : IR) // Optional CSS style for the thumb for a vertically oriented slider. See // +link{hThumbStyle} for state suffixes. // @visibility external //< //> @attr slider.hTrackStyle (CSSStyleName : null : IR) // Optional CSS style for the track for a horizontally oriented slider. //

// Will have the suffix "Disabled" added when the slider is disabled. // // @visibility external //< //> @attr slider.vTrackStyle (CSSStyleName : null : IR) // Optional CSS style for the track for a vertically oriented slider. //

// Will have the suffix "Disabled" added when the slider is disabled. // @visibility external //< // skinImgDir subdirectory for slider skin images skinImgDir:"images/Slider/", //> @attr slider.thumbSrc (String : "thumb.gif" : [IRW]) // The base filename for the slider thumb images. // The filenames for the thumb icons are assembled from this base filename and the state of the // thumb, as follows:
// Assume the thumbSrc is set to {baseName}.{extension}
// The full set of images to be displayed is:
// For horizontal sliders: //

    //
  • h{baseName}.{extension}: default enabled appearance. //
  • h{baseName}_down.{extension}: appearance when the slider is enabled and the // thumb is clicked. //
  • h{baseName}_Disabled.{extension}: appearance when the slider is disabled. //
// For vertical sliders: //
    //
  • v{baseName}.{extension}: default enabled appearance. //
  • v{baseName}_down.{extension}: appearance when the slider is enabled and the // thumb is clicked. //
  • v{baseName}_Disabled.{extension}: appearance when the slider is disabled. //
// @visibility external //< thumbSrc:"thumb.gif", //> @attr slider.trackSrc (String : "track.gif" : [IRW]) // The base filename for the slider track images. // The filenames for the track icons are assembled from this base filename and the state of the // slider, as follows:
// Assume the trackSrc is set to {baseName}.{extension}
// The full set of images to be displayed is:
// For horizontal sliders: //
    //
  • h{baseName}_start.{extension}: start (left edge) of the track for a slider // that is enabled. //
  • h{baseName}_stretch.{extension}: the track for an enabled slider; this may // be centered, tiled, or stretched. //
  • h{baseName}_end.{extension}: end (right edge) of the track for a slider // that is enabled. //
  • h{baseName}_Disabled_start.{extension}: start (left edge) of the track for a slider // that is disabled. //
  • h{baseName}_Disabled_stretch.{extension}: the track for a disabled slider; this // may be centered, tiled, or stretched. //
  • h{baseName}_Disabled_end.{extension}: end (right edge) of the track for a slider // that is disabled. //
// For vertical sliders: //
    //
  • v{baseName}_start.{extension}: start (bottom edge) of the track for a slider // that is enabled. //
  • v{baseName}_stretch.{extension}: the track for an enabled slider; this may // be centered, tiled, or stretched. //
  • v{baseName}_end.{extension}: end (top edge) of the track for a slider // that is enabled. //
  • v{baseName}_Disabled_start.{extension}: start (bottom edge) of the track for a slider // that is disabled. //
  • v{baseName}_Disabled_stretch.{extension}: the track for a disabled slider; this // may be centered, tiled, or stretched. //
  • v{baseName}_end.{extension}: end (top edge) of the track for a slider // that is disabled. //
// @see attr:trackImageType // @visibility external //< trackSrc:"track.gif", //> @attr slider.trackCapSize (integer : 6 : [IRW]) // The height of vertical slider start and end images, or width of horizontal slider start and // end images. // @visibility external //< trackCapSize:6, //> @attr slider.trackImageType (ImageStyle : "stretch" : [IRW]) // The imageType setting for the slider track. // @see type:ImageStyle // @see attr:stretchImg.imageType // @visibility external //< trackImageType:isc.Img.STRETCH, //> @attr slider.showTitle (boolean : true : [IRW]) // Indicates whether the slider's title should be displayed. The default position for this label // is to the left of a horizontal slider, or above a vertical slider. // @see attr:title // @visibility external //< showTitle:true, //> @attr slider.showRange (boolean : true : [IRW]) // Indicates whether labels for the min and max values of the slider should be displayed. The // default positions for these labels are below the start/end of a horizontal slider, or to the // right of the start/end of a vertical slider. // @see attr:minValueLabel // @see attr:maxValueLabel // @visibility external //< showRange:true, //> @attr slider.showValue (boolean : true : [IRW]) // Indicates whether a label for the value of the slider should be displayed. The // default position for this label is to the right of a horizontal slider, or below a vertical // slider. // @see attr:value // @visibility external //< showValue:true, //> @attr slider.labelWidth (integer : 50 : [IRW]) // The width of the labels used to display the minimum, maximum and current values of the // slider. // @visibility external //< labelWidth:50, //> @attr slider.labelHeight (integer : 20 : [IRW]) // The height of the labels used to display the minimum, maximum and current values of the // slider. // @visibility external //< labelHeight:20, //> @attr slider.labelSpacing (integer : 5 : [IRW]) // The space around the labels used to display the minimum, maximum and current values of the // slider. // @visibility external //< labelSpacing:5, titleStyle:"sliderTitle", rangeStyle:"sliderRange", valueStyle:"sliderValue", //XXX need to create and use these CSS styles //XXX need mechanism for overriding default layouts //> @attr slider.value (float : 1 : [IRW]) // The slider value. This value should lie between the minValue and maxValue and increases as // the thumb is moved up (for a vertical slider) or right (for a horizontal slider) unless // flipValues is set to true. // @see attr:minValue // @see attr:maxValue // @see attr:flipValues // @see attr:showValue // @visibility external //< value:1, //> @attr slider.minValue (float : 1 : [IRW]) // The minimum slider value. The slider value is equal to minValue when the thumb is at the // bottom or left of the slider (unless flipValues is true, in which case the minimum value // is at the top/right of the slider) // @see attr:slider.flipValues // @visibility external // @example slider //< minValue:1, //> @attr slider.minValueLabel (String : null : [IRW]) // The text displayed in the label for the minimum value of the slider. If left as null, then // slider.minValue will be displayed. // @see attr:showRange // @see attr:minValue // @visibility external //< //> @attr slider.maxValue (float : 100 : [IRW]) // The maximum slider value. The slider value is equal to maxValue when the thumb is at the // top or right of the slider (unless flipValues is true, in which case the maximum value // is at the bottom/left of the slider) // @see attr:slider.flipValues // @visibility external // @example slider //< maxValue:100, //> @attr slider.maxValueLabel (String : null : [IRW]) // The text displayed in the label for the maximum value of the slider. If left as null, then // slider.maxValue will be displayed. // @see attr:showRange // @see attr:maxValue // @visibility external //< //> @attr slider.numValues (integer : null : [IRW]) // The number of discrete values represented by slider. If specified, the range of valid // values (between minValue and maxValue) will be divided into // this many steps. As the thumb is moved along the track it will only select these values // and appear to jump between the steps. // @visibility external // @example slider //< //> @attr slider.roundValues (boolean : true : [IRW]) // Specifies whether the slider value should be rounded to the nearest integer. If set to // false, values will be rounded to a fixed number of decimal places controlled by // +link{roundPrecision}. // // @visibility external //< roundValues:true, //> @attr slider.roundPrecision (integer : 1 : [IRW]) // If +link{slider.roundValues} is false, the slider value will be rounded to this number of // decimal places. If set to null the value will not be rounded // @visibility external //< roundPrecision:1, //> @attr slider.flipValues (boolean : false : [IRW]) // Specifies whether the value range of the slider should be flipped so that values increase as // the thumb is moved down (for a vertical slider) or to the left (for a horizontal slider). // @visibility external //< flipValues:false, //> @attr slider.sliderTarget (Canvas : null : [IRW]) // The target widget for the sliderMove event generated when the slider thumb // is moved. // @visibility external //< //> @attr slider.canFocus (boolean : true : [IRW]) // Indicates whether keyboard manipulation of the slider is allowed. // @visibility external //< canFocus:true, //> @attr slider.stepPercent (float : 5 : [IRW]) // The percentage of the total slider that constitutes one discrete step. The slider will move // one step when the appropriate arrow key is pressed. // @visibility external //< stepPercent:5, //> @attr slider.animateThumb (boolean : true : [IRW]) // Should the thumb be animated to its new position when the value is changed programmatically, // or by clicking in the slider track. // @visibility animation // @group animation //< //animateThumb:false, //> @attr slider.animateThumbTime (integer : 250 : [IRW]) // Duration of thumb animation, in milliseconds. // @visibility animation // @group animation //< animateThumbTime:250, //> @attr slider.animateThumbInit (boolean : false : [IRW]) // If thumb animation is enabled, should the thumb be animated to its initial value? // @visibility animation // @group animation //< //animateThumbInit:false, // undocumented for now; possibly make this internal animateThumbAcceleration:"slowStartandEnd", valueChangedOnDrag:true, // default false may be more appropriate, but has backcompat problems valueChangedOnRelease:true, // can set this to false to exactly match the pre-5.5 behavior valueChangedOnClick:true // actually on mouseUp, but that is too confusable with thumb release }); //!>Deferred //---------- Define instance methods ----------\\ isc.Slider.addMethods({ //------ initWidget() // Extends superclass initWidget() to set slider dimensions, create the track and thumb child // widgets, and initialize the slider's target, value, and enabled state. initWidget : function () { this.Super("initWidget", arguments); // If passed a minValue that's greater than a max value, swap them. // If they are equal just leave them for now - we'll always return that value. if (!(this.minValue <= this.maxValue)) { this.logWarn("Slider specified with minValue:"+ this.minValue + ", greater than maxValue:"+ this.maxValue + " - reversing max and min value."); var minValue = this.minValue; this.minValue = this.maxValue; this.maxValue = minValue; } // Enforce rounding precision on min/max values. if (this.minValue != null) this.minValue = this._getRoundedValue(this.minValue); if (this.maxValue != null) this.maxValue = this._getRoundedValue(this.maxValue); this.setUpSize(); // create track and thumb this._createTrackLayout(); // create title, range, value labels if specified if (this.showTitle) this._titleLabel = this.addChild(this._createTitleLabel()); if (this.showRange) { this._minLabel = this.addChild(this._createRangeLabel("min")); this._maxLabel = this.addChild(this._createRangeLabel("max")); } if (this.showValue) { this._valueLabel = this._thumb.addPeer(this._createValueLabel()); this._valueLabel.sendToBack(); // Ensure the valueLabel is drawn at the correct position. this._updateValueLabel(); } // If an event is sent with a null target, the event handling system determines the // target based on the last mouse event. We definitely don't want that, so make this // slider the target if no target has been specified. this.setValue(this.value, !(this.animateThumbInit==true)); }, // setUpSize() - sets up width/height/length (track length) // If width / height is explicitly specified, determine length from this // Otherwise determine width/height based on specified length setUpSize : function () { var specifiedWidth = this._userWidth, specifiedHeight = this._userHeight; // If the user didn't specify a width / height, default them based on which components are // being shown. if (this.vertical) { if (specifiedWidth == null) { var width = Math.max(this.thumbThickWidth, this.trackWidth); // value shows on one side of the slider, range (min/max labels) show on the // other side if (this.showValue) width += this.labelWidth + this.labelSpacing; if (this.showRange) width += this.labelWidth + this.labelSpacing; // Note: titleLabel width is derived from the width of the slider so no need to account // for it here //>DEBUG this.logInfo("defaulting width to " + width + "px"); // this.thumbThinWidth)) { height += (this.labelHeight-this.thumbThinWidth); } //>DEBUG this.logInfo("no specified height on vertical Slider - defaulting to:" + height + " based on slider.length of " + this.length); // this.thumbThinWidth)) { this.length -= (this.labelHeight-this.thumbThinWidth); } //>DEBUG this.logInfo("setting slider track length to:"+ this.length + ", based on specified height"); //DEBUG this.logInfo("defaulting height to " + height + "px"); // this.thumbThinWidth)) { width += (this.labelWidth - this.thumbThinWidth); } //>DEBUG this.logInfo("no specified width on horizontal Slider - defaulting to:" + width + " based on slider.length of " + this.length); // this.thumbThinWidth)) { // We use a small label width for the horizontal valueLabel and // allow the content to overflow if necessary this.length -= (this.hValueLabelWidth - this.thumbThinWidth); } //>DEBUG this.logInfo("setting slider track length to:"+ this.length + ", based on specified width"); // 1) { this._stepSize = this._usableLength/(this.numValues-1); } }, // Override resizeBy to resize the track. // setWidth / setHeight / setRect et al. fall through to this method resizeBy : function (deltaX, deltaY) { this.Super("resizeBy", arguments); if (!this._track) return; var vertical = this.vertical; if ((vertical && deltaY != 0) || (!vertical && deltaX != 0)) { // Update length / usable length for caculations... this.length += vertical ? deltaY : deltaX; this._usableLength = this.length-this.thumbThinWidth; // resize the track if (vertical) this._track.resizeBy(0, deltaY) else this._track.resizeBy(deltaX, 0); // re-calculate stepSize if numValues is defined if (this.numValues && this.numValues > 1) { this._stepSize = this._usableLength/(this.numValues-1); } // fire setValue to update the thumb. this.setValue(this.value, true, true); // no animation, no logical value change // Also move the max (or min) marker if (this.showRange) { if (this.vertical) { var endMarker = this.flipValues ? this._maxLabel : this._minLabel; endMarker.moveBy(0, deltaY); } else { var endMarker = this.flipValues ? this._minLabel : this._maxLabel; endMarker.moveBy(deltaX, 0); } } } }, //------ _createRangeLabel(minOrMax) // Creates, initializes, and returns a new Label widget to be the slider's mix or max value // label. minOrMax must be the string "min" or "max". _createRangeLabel : function (minOrMax) { var labelLeft, labelTop, labelAlign, labelValign, // Should the label be at the start (top / left) or end (bottom/right) of the slider? atStartPosition = (this.vertical ? minOrMax == "max" : minOrMax == "min"); if (this.flipValues) atStartPosition = !atStartPosition; // For vertical sliders, range labels appear to the right of the slider track // for horizontal sliders, they appear below the slider track. if (this.vertical) { labelLeft = Math.max(this.thumbThickWidth, this.trackWidth) + this.labelSpacing + (this.showValue ? this.labelWidth + this.labelSpacing : 0); labelAlign = isc.Canvas.LEFT; if (atStartPosition) { labelTop = (this.showTitle ? this.labelHeight + this.labelSpacing : 0); labelValign = isc.Canvas.TOP; } else { labelTop = (this.showTitle ? this.labelHeight + this.labelSpacing: 0) + (this.length - this.labelHeight); labelValign = isc.Canvas.BOTTOM; } } else { // this.horizontal labelTop = Math.max(this.thumbThickWidth, this.trackWidth) + this.labelSpacing + (this.showValue ? this.labelHeight + this.labelSpacing : 0); labelValign = isc.Canvas.TOP; if (atStartPosition) { labelLeft = (this.showTitle ? this.labelWidth + this.labelSpacing : 0); labelAlign = isc.Canvas.LEFT; } else { labelLeft = (this.showTitle ? this.labelWidth + this.labelSpacing : 0) + this.length - this.labelWidth; labelAlign = isc.Canvas.RIGHT; } } return isc.Label.create({ ID:this.getID()+"_"+minOrMax+"Label", autoDraw:false, left:labelLeft, top:labelTop, width:this.labelWidth, height:this.labelHeight, wrap:false, align:labelAlign, valign:labelValign, className:this.rangeStyle, contents:(minOrMax == "min" ? (this.minValueLabel ? this.minValueLabel : this.minValue) : (this.maxValueLabel ? this.maxValueLabel : this.maxValue) ) }); }, //------ _createTitleLabel() // Creates, initializes, and returns a new Label widget to be the slider's title label. _createTitleLabel : function () { // Title label will always float at 0,0 within the slider. var labelAlign = (this.vertical ? isc.Canvas.CENTER : isc.Canvas.RIGHT); return isc.Label.create({ ID:this.getID()+"_titleLabel", autoDraw:false, left:0, top:0, width:(this.vertical ? this.getWidth() : this.labelWidth), height:(this.vertical ? this.labelHeight : this.getHeight()), align:labelAlign, className:this.titleStyle, contents:this.title }); }, //------ _createValueLabel() // Creates, initializes, and returns a new Label widget to be the slider's dynamic value label. hValueLabelWidth:5, _createValueLabel : function () { var labelLeft, labelTop, labelWidth, labelAlign, labelValign; if (this.vertical) { labelLeft = this._thumb.getLeft() - this.labelWidth - this.labelSpacing; // align the center of the label with the center of the thumb labelTop = this._thumb.getTop() + parseInt(this._thumb.getHeight()/2 - this.labelHeight/2); labelAlign = isc.Canvas.RIGHT; labelValign = isc.Canvas.CENTER; labelWidth = this.labelWidth; } else { labelLeft = this._thumb.getLeft() + parseInt(this._thumb.getWidth()/2 - this.labelWidth/2); labelTop = this._thumb.getTop() - this.labelHeight - this.labelSpacing; labelAlign = isc.Canvas.CENTER; labelValign = isc.Canvas.BOTTOM; // Specify a small size for the label, and allow it's content to // overflow. labelWidth = this.hValueLabelWidth; } var label = isc.Label.create({ ID:this.getID()+"_valueLabel", autoDraw:false, left:labelLeft, top:labelTop, width:labelWidth, height:this.labelHeight, wrap:false, align:labelAlign, className:this.valueStyle, contents:this.value, mouseUp:function () { return false; }, moveWithMaster:false, // We'll explicitly handle moving the valueLabel observes:[{source:this, message:"valueChanged", action:"this._updateValueLabel();"}] }); if (!this.vertical) { isc.addMethods(label, { // Override draw() to reposition the label after drawing. // we have to do this as we don't know the drawn size of the label until it has been // drawn in the DOM, and the desired position depends on the drawn size. draw : function () { var prevVis = this.visibility // avoid a flash by drawing with visibility hidden initially this.hide(); this.Super("draw", arguments); this.parentElement._updateValueLabel(); this.setVisibility(this.prevVis); } }); }; return label; }, //_createTrackLayout() // Internal function fired once at init time to create the track and thumb for the slider _createTrackLayout : function () { // Determine the rect for the trackLayout. We will center the thumb and track along the // long axis of this rect. var layoutRect = this._getTrackLayoutPos(), trackLeft, trackTop, trackWidth = (this.vertical ? this.trackWidth : this.length), trackHeight = (this.vertical ? this.length : this.trackWidth), thumbLeft, thumbTop, thumbWidth = (this.vertical ? this.thumbThickWidth : this.thumbThinWidth), thumbHeight = (this.vertical ? this.thumbThinWidth : this.thumbThickWidth) ; var thumbThicker = this.thumbThickWidth > this.trackWidth; if (thumbThicker) { if (this.vertical) { thumbLeft = layoutRect[0]; trackLeft = thumbLeft + parseInt(this.thumbThickWidth/2 - this.trackWidth/2); trackTop = layoutRect[1]; // Doesn't really matter where we put the thumb vertically - it'll be shifted via // 'setValue()' thumbTop = layoutRect[1]; } else { thumbTop = layoutRect[1]; trackTop = thumbTop + parseInt(this.thumbThickWidth/2 - this.trackWidth/2); trackLeft = layoutRect[0]; thumbLeft = layoutRect[0]; } // track is thicker than the thumb } else { if (this.vertical) { trackLeft = layoutRect[0]; thumbLeft = trackLeft + parseInt(this.trackWidth/2 - this.thumbThinWidth/2); trackTop = layoutRect[1]; thumbTop = layoutRect[1]; } else { trackTop = layoutRect[1]; thumbTop = trackTop + parseInt(this.trackWidth/2 - this.thumbThinWidth/2); trackLeft = layoutRect[0]; thumbLeft = layoutRect[0]; } } //>DEBUG this.logDebug("calculated coords for track:"+ [trackLeft, trackTop, trackWidth, trackHeight]); this.logDebug("calculated coords for thumb:"+ [thumbLeft, thumbTop, thumbWidth, thumbHeight]); // this.thumbThinWidth)) top += Math.round((this.labelHeight - this.thumbThinWidth)/2); if (this.horizontal && (this.labelWidth > this.thumbThinWidth)) left += Math.round((this.labelWidth - this.thumbThinWidth)/2); } return [left, top]; }, //------ _createTrack() // Creates, initializes, and returns a new StretchImg widget to be the slider's track. trackConstructor:"StretchImg", _createTrack : function (top, left, width, height) { return this.createAutoChild("track", { left:left, top:top, width:width, height:height, vertical:this.vertical, // image-based appearance: StretchImg props capSize:this.trackCapSize, src:"[SKIN]" + (this.vertical ? "v" : "h") + this.trackSrc, skinImgDir:this.skinImgDir, imageType:this.trackImageType, // allows a Label to be used with pure CSS styling styleName:this[(this.vertical ? "v" : "h") + "TrackStyle"], overflow:"hidden", showDisabled:true, // allow the thumb and the track to have focus, but set exclude them from the tab order // this allows for bubbling of keypress events after the user has clicked on the thumb or // track of the slider canFocus:true, tabIndex:-1, cacheImageSizes: false //backgroundColor:"#666666" // in case images aren't available }); }, //------ _createThumb() // Creates, initializes, and returns a new Img widget to be the slider's thumb. thumbConstructor:"Img", _createThumb : function (top, left, width, height) { var vPrefix return this.createAutoChild("thumb", { left:left, top:top, width:width, height:height, // image-based appearance: Img props src:"[SKIN]" + (this.vertical ? "v" : "h") + this.thumbSrc, skinImgDir:this.skinImgDir, // allows a Label to be used with pure CSS styling overflow:"hidden", showDisabled:true, styleName:this[(this.vertical ? "v" : "h") + "ThumbStyle"], canDrag:true, dragAppearance:isc.EventHandler.NONE, cursor:isc.Canvas.HAND, dragMove:function () { this.parentElement._thumbMove(); return false }, // We want the thumb to move with the track, but NOT resize with it. _resizeWithMaster:false, dragStart:function(){ var EH = isc.EventHandler; EH.dragOffsetX = -1 * (this.getPageLeft() - EH.mouseDownEvent.x); EH.dragOffsetY = -1 * (this.getPageTop() - EH.mouseDownEvent.y); this.parentElement._thumbIsDragging = true; return EH.STOP_BUBBLING; }, dragStop:function(){ this.parentElement._thumbIsDragging = false; this.setState(isc.Slider.UP); if (this.parentElement.valueChangedOnRelease) { this.parentElement.valueChanged(this.parentElement.value); } return false; }, mouseDown:function () { this.setState(isc.Slider.DOWN) }, mouseUp:function () { this.setState(isc.Slider.UP); return false }, // allow the thumb and the track to have focus, but set exclude them from the tab order // this allows for bubbling of keypress events after the user has clicked on the thumb or // track of the slider canFocus:true, tabIndex:-1 //backgroundColor:"#AAAAAA" // in case images aren't available }); }, //------ _thumbMove() // Called by the dragMove handler for the slider thumb (this._thumb). Calculates // the new thumb position, and if the position has changed: moves the thumb widget, // calculates the new slider value (this.value) and sends the 'sliderMove' event // to the target (this.sliderTarget). // The 'fromClick' parameter indicates whether this movement is called from a click // (eg elsewhere on the track) instead of a drag, in which case we might animate the thumb. _thumbMove : function (fromClick) { var thumbPosition, rawValue; if (this.vertical) { var trackTop = this._track.getTop(), trackEnd = this._usableLength + trackTop; // determine the desired position on the track thumbPosition = isc.EventHandler.getY() - isc.EventHandler.dragOffsetY - this.getPageTop(); thumbPosition = Math.max(trackTop, Math.min(trackEnd, thumbPosition)); // for values calculations we want positions relative to trackTop var thumbOffset = thumbPosition - trackTop; if (this.numValues) { // do not round thumbOffset yet, since it is used to calculate the raw value below thumbOffset = Math.round(thumbOffset/this._stepSize) * this._stepSize; thumbPosition = Math.round(thumbOffset) + trackTop; } if (thumbPosition == this._thumb.getTop()) return; // no thumb movement //>DEBUG this.logDebug("drag-moving thumb to:"+ thumbPosition) //DEBUG this.logDebug("drag-moving thumb to:"+ thumbPosition) //DEBUG this.logDebug("slider value from drag-move:"+ this.value); // this.getWidth()) { desiredLeft = this.getWidth() - width; //this.logWarn("width:" + width + ", would overflow so clamping:" + desiredLeft); } if (desiredLeft < 0) desiredLeft = 0; label.setLeft(desiredLeft); } }, mouseUp : function() { isc.EventHandler.dragOffsetX = isc.EventHandler.dragOffsetY = Math.floor(this.thumbThinWidth/2); if (this.valueChangedOnClick) this._thumbMove(true); }, //------ setValue(newValue) //> @method slider.setValue() ([]) // Sets the slider value to newValue and moves the slider thumb to the appropriate position for this // value. Sends the 'sliderMove' event to the sliderTarget. // // @param newValue (float) the new value // @param noAnimation (boolean) do not animate the slider thumb to the new value // @visibility external //< setValue : function (newValue, noAnimation, noValueChange) { var rawValue, thumbOffset; if (!isc.isA.Number(newValue)) return; // Ensure minValue<=newValue<=maxValue. newValue = Math.max(this.minValue, (Math.min(newValue, this.maxValue))); // Set value, rounding if specified. newValue = this._getRoundedValue(newValue); this.value = newValue; // Calculate rawValue and resulting thumbOffset. if (this.minValue == this.maxValue) rawValue = 1; else rawValue = (this.value-this.minValue)/(this.maxValue-this.minValue); thumbOffset = rawValue * this._usableLength; // Set the thumb position. var thumbPosition; if (this.vertical) { thumbPosition = this._track.getTop() + parseInt(this.flipValues ? thumbOffset : this._usableLength - thumbOffset); if (this.animateThumb && !noAnimation) { this._thumbAnimation = this._thumb.animateMove(this._thumb.getLeft(), thumbPosition, null, this.animateThumbTime, this.animateThumbAcceleration); } else { this._thumb.setTop(thumbPosition); } } else { thumbPosition = this._track.getLeft() + parseInt(this.flipValues ? this._usableLength - thumbOffset : thumbOffset); if (this.animateThumb && !noAnimation) { this._thumbAnimation = this._thumb.animateMove(thumbPosition, this._thumb.getTop(), null, this.animateThumbTime, this.animateThumbAcceleration); } else { this._thumb.setLeft(thumbPosition); } } if (!noValueChange) this.valueChanged(this.value); // observable method if (this.sliderTarget) isc.EventHandler.handleEvent(this.sliderTarget, isc.Slider.EVENTNAME, this); }, //------ getValue() //> @method slider.getValue() ([]) // Returns the current slider value. // // @return (float) current slider value // @visibility external //< getValue : function () { return this.value; }, //------ valueChanged() //> @method slider.valueChanged() ([A]) // This method is called when the slider value changes. This occurs when the setValue method is // called, or when the slider is moved. Observe this method to be notified when the slider value // changes. // // @param value (number) the new value // // @see method:class.observe // @visibility external // @example slider //< valueChanged : function (value) { }, //> @method slider.valueIsChanging() ([A]) // Call this method in your +link{slider.valueChanged()} handler to determine whether the // value change is due to an ongoing drag interaction (true) or due to a thumb-release, // mouse click, keypress, or programmatic event (false). You may choose to execute temporary or // partial updates while the slider thumb is dragged, and final updates or persistence of the value // in response to the other events. // // @return (boolean) true if user is still dragging the slider thumb, false otherwise // // @visibility external //< valueIsChanging : function () { return (this._thumbIsDragging == true); }, // HandleKeyPress: // If Home, End, or the arrow keys are pressed while this slider has focus, move the slider // appropriately. // 20050912: Thumb animation is explicitly disabled by setting the noAnimation parameter of // setValue(), because the thumb jumps around when one of the arrow keys is held down. Not worth // tracking down, since the effect is already pretty close to an animation in this case. handleKeyPress : function (event, eventInfo) { var keyName = event.keyName; // Note: if this.flipValues is true, vertical sliders will start at the top, and increase // toward the bottom, horizontal sliders will start at the right and increase towards the // left // "Home" will move the slider all the way to the min value (may be either end depending on // flipValues) if (keyName == "Home") { this.setValue(this.minValue, true); return false; } // "End" will move the slider all the way to the max value if (keyName == "End") { this.setValue(this.maxValue, true); return false; } // If an arrow key was pressed, move the slider one step in the direction indicated // Calculate one step from this.stepPercent: var change = (this.maxValue - this.minValue) * this.stepPercent / 100; // if roundValues is enabled, ensure we always move (a change < 1 could be rounded to no // change) if (this.roundValues && change < 1) change = 1; if (this.vertical) { if ((this.flipValues && keyName == "Arrow_Up") || (!this.flipValues && keyName == "Arrow_Down")) { this.setValue(this.getValue() - change, true); return false; } else if ( (this.flipValues && keyName == "Arrow_Down") || (!this.flipValues && keyName == "Arrow_Up")) { this.setValue(this.getValue() + change, true); return false } } else { if ((this.flipValues && keyName == "Arrow_Left") || (!this.flipValues && keyName == "Arrow_Right")) { this.setValue(this.getValue() + change, true) return false; } else if ( (this.flipValues && keyName == "Arrow_Right") || (!this.flipValues && keyName == "Arrow_Left")) { this.setValue(this.getValue() - change, true) return false; } } if (this.keyPress) { this.convertToMethod("keyPress"); return this.keyPress(event, eventInfo); } }, // override setCanFocus to set the canFocus property on the track and the thumb as well setCanFocus : function (canFocus) { this.Super("canFocus", arguments); if (this._thumb != null) this._thumb.setCanFocus(canFocus); if (this._track != null) this._track.setCanFocus(canFocus); }, //> @method slider.setMinValue() ([]) // Sets the +link{slider.minValue, minimum value} of the slider // // @param newValue (float) the new minimum value // @visibility external //< setMinValue : function (newValue) { newValue = this._getRoundedValue(newValue); this.minValue = newValue; if (this._minLabel) this._minLabel.setContents(newValue); this.setValue(this.minValue); }, //> @method slider.setMaxValue() ([]) // Sets the +link{slider.maxValue, maximum value} of the slider // // @param newValue (float) the new maximum value // @visibility external //< setMaxValue : function (newValue) { // If we're rounding, round the min/max value as well newValue = this._getRoundedValue(newValue); this.maxValue = newValue; if (this._maxLabel) this._maxLabel.setContents(newValue); this.setValue(this.minValue); }, //> @method slider.setNumValues() ([]) // Sets the +link{slider.numValues, number of values} for the slider // // @param newNumValues (float) the new number of values // @visibility external //< setNumValues : function (newNumValues) { this.numValues = newNumValues; this._stepSize = this._usableLength/(this.numValues-1); this.setValue(this.minValue); }, //> @method slider.setTitle() // Sets the +link{title} of the slider // // @param newTitle (string) new title for the slider // @visibility external //< setTitle : function (newTitle) { this._titleLabel.setContents(newTitle); }, //> method slider.setLength() // Sets the +link{length} of the slider // // @param newLength (number) the new length to set the slider to // @visibility external //< setLength : function (newLength) { this.length = newLength; this.setUpSize(); }, _refreshChildren : function () { this._titleLabel.destroy(); this._track.destroy(); this._thumb.destroy(); this._valueLabel.destroy(); this._minLabel.destroy(); this._maxLabel.destroy(); this.initWidget(); }, //> @method slider.setVertical() // Sets the +link{vertical} property of the slider // // @param isVertical (boolean) is the slider vertical // @visibility external //< setVertical : function (isVertical) { this.vertical = isVertical; this._refreshChildren(); }, //> @method slider.setThumbThickWidth() // Sets the +link{thumbThickWidth} property of the slider // // @param newWidth (number) new thumbThickWidth // @visibility external //< setThumbThickWidth : function (newWidth) { this.thumbThickWidth = newWidth; this._refreshChildren(); }, //> @method slider.setThumbThinWidth() // Sets the +link{thumbThinWidth} property of the slider // // @param newWidth (number) new thumbThinWidth // @visibility external //< setThumbThinWidth : function (newWidth) { this.thumbThinWidth = newWidth; this._refreshChildren(); }, //> @method slider.setTrackWidth() // Sets the +link{trackWidth} property of the slider // // @param newWidth (number) new trackWidth // @visibility external //< setTrackWidth : function (newWidth) { this.trackWidth = newWidth; this._refreshChildren(); }, //> @method slider.setThumbSrc() // Sets the +link{thumbSrc} property of the slider // // @param newSrc (string) new thumbSrc // @visibility external //< setThumbSrc : function (newSrc) { this.thumbSrc = newSrc; this._refreshChildren(); }, //> @method slider.setTrackSrc() // Sets the +link{trackSrc} property of the slider // // @param newSrc (string) new trackSrc // @visibility external //< setTrackSrc : function (newSrc) { this.trackSrc = newSrc; this._refreshChildren(); }, //> @method slider.setTrackCapSize() // Sets the +link{trackCapSize} property of the slider // // @param newSize (number) new trackCapSize // @visibility external //< setTrackCapSize : function (newSize) { this.trackCapSize = newSize; this._refreshChildren(); }, //> @method slider.setTrackImageType() // Sets the +link{trackImageType} property of the slider // // @param newType (string) new trackImageType // @visibility external //< setTrackImageType : function (newType) { this.trackImageType = newType; this._refreshChildren(); }, //> @method slider.setShowTitle() // Sets the +link{showTitle} property of the slider // // @param showTitle (boolean) show the slider title? // @visibility external //< setShowTitle : function (showTitle) { this.showTitle = showTitle; this._refreshChildren(); }, //> @method slider.setShowRange() // Sets the +link{showRange} property of the slider // // @param showRange (boolean) show the slider range? // @visibility external //< setShowRange : function (showRange) { this.showRange = showRange; this._refreshChildren(); }, //> @method slider.setShowValue() // Sets the +link{showValue} property of the slider // // @param showValue (boolean) show the slider value? // @visibility external //< setShowValue : function (showValue) { this.showValue = showValue; this._refreshChildren(); }, //> @method slider.setLabelWidth() // Sets the +link{labelWidth} property of the slider // // @param labelWidth (number) new label width // @visibility external //< setLabelWidth : function (labelWidth) { this.labelWidth = labelWidth; this._refreshChildren(); }, //> @method slider.setLabelHeight() // Sets the +link{labelHeight} property of the slider // // @param newHeight (number) new label height // @visibility external //< setLabelHeight : function (newHeight) { this.labelHeight = newHeight; this._refreshChildren(); }, //> @method slider.setLabelSpacing() // Sets the +link{labelSpacing} property of the slider // // @param labelWidth (number) new label spacing // @visibility external //< setLabelSpacing : function (newSpacing) { this.labelSpacing = newSpacing; this._refreshChildren(); }, //> @method slider.setMaxValueLabel() // Sets the +link{maxValueLabel} property of the slider // // @param labelText (string) new label text // @visibility external //< setMaxValueLabel : function (labelText) { this._maxLabel.setContents(labelText); }, //> @method slider.setRoundValues() // Sets the +link{roundValues} property of the slider // // @param roundValues (boolean) round slider values? // @visibility external //< setRoundValues : function (roundValues) { this.roundValues = roundValues; this._refreshChildren(); }, //> @method slider.setRoundPrecision() // Sets the +link{roundPrecision} property of the slider // // @param roundPrecision (number) new round precision // @visibility external //< setRoundPrecision : function (roundPrecision) { this.roundPrecision = roundPrecision; this._refreshChildren(); }, //> @method slider.setFlipValues() // Sets the +link{flipValues} property of the slider // // @param flipValues (boolean) flip slider values? // @visibility external //< setFlipValues : function (flipValues) { this.flipValues = flipValues; this._refreshChildren(); }, //> @method slider.setStepPercent() // Sets the +link{stepPercent} property of the slider // // @param stepPercent (number) new slider step percent // @visibility external //< setStepPercent : function (stepPercent) { this.stepPercent = stepPercent; this._refreshChildren(); } }); isc.Slider.registerStringMethods({ valueChanged : "value" }) //!




© 2015 - 2024 Weber Informatics LLC | Privacy Policy