/* Copyright (c) 2004-2006, The Dojo Foundation All Rights Reserved. Licensed under the Academic Free License version 2.1 or above OR the modified BSD license. For more information on Dojo licensing, see: http://dojotoolkit.org/community/licensing.shtml */ dojo.provide("dojo.widget.Slider"); // load dependencies dojo.require("dojo.event.*"); dojo.require("dojo.dnd.*"); // dojo.dnd.* doesn't include this package, because it's not in __package__.js dojo.require("dojo.dnd.HtmlDragMove"); dojo.require("dojo.widget.*"); dojo.require("dojo.html.layout"); dojo.widget.defineWidget ( "dojo.widget.Slider", dojo.widget.HtmlWidget, { // summary // Slider Widget. // // The slider widget comes in three forms: // 1. Base Slider widget which supports movement in x and y dimensions // 2. Vertical Slider (SliderVertical) widget which supports movement // only in the y dimension. // 3. Horizontal Slider (SliderHorizontal) widget which supports movement // only in the x dimension. // // The key objects in the widget are: // - a container div which displays a bar in the background (Slider object) // - a handle inside the container div, which represents the value // (sliderHandle DOM node) // - the object which moves the handle (_handleMove is of type // SliderDragMoveSource) // // The values for the slider are calculated by grouping pixels together, // based on the number of values to be represented by the slider. // The number of pixels in a group is called the _valueSize // e.g. if slider is 150 pixels long, and is representing the values // 0,1,...10 then pixels are grouped into lots of 15 (_valueSize), where: // value 0 maps to pixels 0 - 7 // 1 8 - 22 // 2 23 - 37 etc. // The accuracy of the slider is limited to the number of pixels // (i.e tiles > pixels will result in the slider not being able to // represent some values). // minimumX: Number // minimum value to be represented by slider in the horizontal direction minimumX: 0, // minimumY: Number // minimum value to be represented by slider in the vertical direction minimumY: 0, // maximumX: Number // maximum value to be represented by slider in the horizontal direction maximumX: 10, // maximumY: Number // maximum value to be represented by slider in the vertical direction maximumY: 10, // snapValuesX: Number // number of values to be represented by slider in the horizontal direction // =0 means no snapping snapValuesX: 0, // snapValuesY: Number // number of values to be represented by slider in the vertical direction // =0 means no snapping snapValuesY: 0, // should the handle snap to the grid or remain where it was dragged to? // FIXME: snapToGrid=false is logically in conflict with setting snapValuesX and snapValuesY _snapToGrid: true, // isEnableX: Boolean // enables (disables) sliding in the horizontal direction isEnableX: true, // isEnableY: Boolean // enables (disables) sliding in the vertical direction isEnableY: true, // value size (pixels) in the x dimension _valueSizeX: 0.0, // value size (pixels) in the y dimension _valueSizeY: 0.0, // left most edge of constraining container (pixels) in the X dimension _minX: 0, // top most edge of constraining container (pixels) in the Y dimension _minY: 0, // constrained slider size (pixels) in the x dimension _constraintWidth: 0, // constrained slider size (pixels) in the y dimension _constraintHeight: 0, // progress image right clip value (pixels) in the X dimension _clipLeft: 0, // progress image left clip value (pixels) in the X dimension _clipRight: 0, // progress image top clip value (pixels) in the Y dimension _clipTop: 0, // progress image bottom clip value (pixels) in the Y dimension _clipBottom: 0, // half the size of the slider handle (pixels) in the X dimension _clipXdelta: 0, // half the size of the slider handle (pixels) in the Y dimension _clipYdelta: 0, // initialValueX: Number // initial value in the x dimension initialValueX: 0, // initialValueY: Number // initial value in the y dimension initialValueY: 0, // flipX: Boolean // values decrease in the X dimension flipX: false, // flipY: Boolean // values decrease in the Y dimension flipY: false, // clickSelect: Boolean // enables (disables) the user to click on the slider to set the position clickSelect: true, // activeDrag: Boolean // disables (enables) the value to change while you are dragging, or just after drag finishes activeDrag: false, templateCssPath: dojo.uri.dojoUri ("src/widget/templates/Slider.css"), templatePath: dojo.uri.dojoUri ("src/widget/templates/Slider.html"), // This is set to true when a drag is started, so that it is not confused // with a click _isDragInProgress: false, // default user style attributes // bottomButtonSrc: String // down arrow graphic URL bottomButtonSrc: dojo.uri.dojoUri("src/widget/templates/images/slider_down_arrow.png"), // topButtonSrc: String // up arrow graphic URL topButtonSrc: dojo.uri.dojoUri("src/widget/templates/images/slider_up_arrow.png"), // leftButtonSrc: String // left arrow graphic URL leftButtonSrc: dojo.uri.dojoUri("src/widget/templates/images/slider_left_arrow.png"), // rightButtonSrc: String // right arrow graphic URL rightButtonSrc: dojo.uri.dojoUri("src/widget/templates/images/slider_right_arrow.png"), // backgroundSrc: String // slider background graphic URL backgroundSrc: dojo.uri.dojoUri("src/widget/templates/images/blank.gif"), // progressBackgroundSrc: String // slider background graphic URL to overlay the normal background to show progress progressBackgroundSrc: dojo.uri.dojoUri("src/widget/templates/images/blank.gif"), // backgroundSize: String // sizing style attributes for the background image backgroundSize: "width:200px;height:200px;", // backgroundStyle: String // style attributes (other than sizing) for the background image backgroundStyle: "", // buttonStyleX: String // style attributes for the left and right arrow images buttonStyleX: "", // buttonStyleY: String // style attributes for the up and down arrow images buttonStyleY: "", // handleStyle: String // style attributes for the moveable slider image handleStyle: "", // handleSrc: String // moveable slider graphic URL handleSrc: dojo.uri.dojoUri("src/widget/templates/images/slider-button.png"), // showButtons: Boolean // show (don't show) the arrow buttons showButtons: true, _eventCount: 0, _typamaticTimer: null, _typamaticFunction: null, // defaultTimeout: Number // number of milliseconds before a held key or button becomes typematic defaultTimeout: 500, // timeoutChangeRate: Number // fraction of time used to change the typematic timer between events // 1.0 means that each typematic event fires at defaultTimeout intervals // < 1.0 means that each typematic event fires at an increasing faster rate timeoutChangeRate: 0.90, _currentTimeout: this.defaultTimeout, // does the keyboard related stuff _handleKeyEvents: function(/*Event*/ evt){ if(!evt.key){ return; } if(!evt.ctrlKey && !evt.altKey){ switch(evt.key){ case evt.KEY_LEFT_ARROW: dojo.event.browser.stopEvent(evt); this._leftButtonPressed(evt); return; case evt.KEY_RIGHT_ARROW: dojo.event.browser.stopEvent(evt); this._rightButtonPressed(evt); return; case evt.KEY_DOWN_ARROW: dojo.event.browser.stopEvent(evt); this._bottomButtonPressed(evt); return; case evt.KEY_UP_ARROW: dojo.event.browser.stopEvent(evt); this._topButtonPressed(evt); return; } } this._eventCount++; }, _pressButton: function(/*DomNode*/ buttonNode){ buttonNode.className = buttonNode.className.replace("Outset","Inset"); }, _releaseButton: function(/*DomNode*/ buttonNode){ buttonNode.className = buttonNode.className.replace("Inset","Outset"); }, _buttonPressed: function(/*Event*/ evt, /*DomNode*/ buttonNode){ this._setFocus(); if(typeof evt == "object"){ if(this._typamaticTimer != null){ if(this._typamaticNode == buttonNode){ return; } clearTimeout(this._typamaticTimer); } this._buttonReleased(null); this._eventCount++; this._typamaticTimer = null; this._currentTimeout = this.defaultTimeout; dojo.event.browser.stopEvent(evt); }else if (evt != this._eventCount){ this._buttonReleased(null); return false; } if (buttonNode == this.leftButtonNode && this.isEnableX){ this._snapX(dojo.html.getPixelValue (this.sliderHandleNode,"left") - this._valueSizeX); } else if (buttonNode == this.rightButtonNode && this.isEnableX){ this._snapX(dojo.html.getPixelValue (this.sliderHandleNode,"left") + this._valueSizeX); } else if (buttonNode == this.topButtonNode && this.isEnableY){ this._snapY(dojo.html.getPixelValue (this.sliderHandleNode,"top") - this._valueSizeY); } else if (buttonNode == this.bottomButtonNode && this.isEnableY){ this._snapY(dojo.html.getPixelValue (this.sliderHandleNode,"top") + this._valueSizeY); } else { return false; } this._pressButton(buttonNode); this.notifyListeners(); this._typamaticNode = buttonNode; this._typamaticTimer = dojo.lang.setTimeout(this, "_buttonPressed", this._currentTimeout, this._eventCount, buttonNode); this._currentTimeout = Math.round(this._currentTimeout * this.timeoutChangeRate); return false; }, _bottomButtonPressed: function(/*Event*/ evt){ return this._buttonPressed(evt,this.bottomButtonNode); }, // IE sends these events when rapid clicking, mimic an extra single click _bottomButtonDoubleClicked: function(/*Event*/ evt){ var rc = this._bottomButtonPressed(evt); dojo.lang.setTimeout( this, "_buttonReleased", 50, null); return rc; }, _topButtonPressed: function(/*Event*/ evt){ return this._buttonPressed(evt,this.topButtonNode); }, // IE sends these events when rapid clicking, mimic an extra single click _topButtonDoubleClicked: function(/*Event*/ evt){ var rc = this._topButtonPressed(evt); dojo.lang.setTimeout( this, "_buttonReleased", 50, null); return rc; }, _leftButtonPressed: function(/*Event*/ evt){ return this._buttonPressed(evt,this.leftButtonNode); }, // IE sends these events when rapid clicking, mimic an extra single click _leftButtonDoubleClicked: function(/*Event*/ evt){ var rc = this._leftButtonPressed(evt); dojo.lang.setTimeout( this, "_buttonReleased", 50, null); return rc; }, _rightButtonPressed: function(/*Event*/ evt){ return this._buttonPressed(evt,this.rightButtonNode); }, // IE sends these events when rapid clicking, mimic an extra single click _rightButtonDoubleClicked: function(/*Event*/ evt){ var rc = this._rightButtonPressed(evt); dojo.lang.setTimeout( this, "_buttonReleased", 50, null); return rc; }, _buttonReleased: function(/*Event*/ evt){ if(typeof evt == "object" && evt != null && typeof evt.keyCode != "undefined" && evt.keyCode != null){ var keyCode = evt.keyCode; switch(keyCode){ case evt.KEY_LEFT_ARROW: case evt.KEY_RIGHT_ARROW: case evt.KEY_DOWN_ARROW: case evt.KEY_UP_ARROW: dojo.event.browser.stopEvent(evt); break; } } this._releaseButton(this.topButtonNode); this._releaseButton(this.bottomButtonNode); this._releaseButton(this.leftButtonNode); this._releaseButton(this.rightButtonNode); this._eventCount++; if(this._typamaticTimer != null){ clearTimeout(this._typamaticTimer); } this._typamaticTimer = null; this._currentTimeout = this.defaultTimeout; }, _mouseWheeled: function(/*Event*/ evt){ var scrollAmount = 0; if(typeof evt.wheelDelta == 'number'){ // IE scrollAmount = evt.wheelDelta; }else if (typeof evt.detail == 'number'){ // Mozilla+Firefox scrollAmount = -evt.detail; } if (this.isEnableY){ if(scrollAmount > 0){ this._topButtonPressed(evt); this._buttonReleased(evt); }else if (scrollAmount < 0){ this._bottomButtonPressed(evt); this._buttonReleased(evt); } } else if (this.isEnableX){ if(scrollAmount > 0){ this._rightButtonPressed(evt); this._buttonReleased(evt); }else if (scrollAmount < 0){ this._leftButtonPressed(evt); this._buttonReleased(evt); } } }, _discardEvent: function(/*Event*/ evt){ dojo.event.browser.stopEvent(evt); }, _setFocus: function(){ if (this.focusNode.focus){ this.focusNode.focus(); } }, // This function is called when the template is loaded fillInTemplate: function (/*Object*/ args, /*Object*/ frag) { var source = this.getFragNodeRef(frag); dojo.html.copyStyle(this.domNode, source); // the user's style for the widget might include border and padding // unfortunately, border isn't supported for inline elements // so I get to fake everyone out by setting the border and padding // of the outer table cells var padding = this.domNode.style.padding; if (dojo.lang.isString(padding) && padding != "" && padding != "0px" && padding != "0px 0px 0px 0px"){ this.topBorderNode.style.padding = this.bottomBorderNode.style.padding = padding; this.topBorderNode.style.paddingBottom = "0px"; this.bottomBorderNode.style.paddingTop = "0px"; this.rightBorderNode.style.paddingRight = this.domNode.style.paddingRight; this.leftBorderNode.style.paddingLeft= this.domNode.style.paddingLeft; this.domNode.style.padding = "0px 0px 0px 0px"; } var borderWidth = this.domNode.style.borderWidth; if (dojo.lang.isString(borderWidth) && borderWidth != "" && borderWidth != "0px" && borderWidth != "0px 0px 0px 0px"){ this.topBorderNode.style.borderStyle = this.rightBorderNode.style.borderStyle = this.bottomBorderNode.style.borderStyle = this.leftBorderNode.style.borderStyle = this.domNode.style.borderStyle; this.topBorderNode.style.borderColor = this.rightBorderNode.style.borderColor = this.bottomBorderNode.style.borderColor = this.leftBorderNode.style.borderColor = this.domNode.style.borderColor; this.topBorderNode.style.borderWidth = this.bottomBorderNode.style.borderWidth = borderWidth; this.topBorderNode.style.borderBottomWidth = "0px"; this.bottomBorderNode.style.borderTopWidth = "0px"; this.rightBorderNode.style.borderRightWidth = this.domNode.style.borderRightWidth; this.leftBorderNode.style.borderLeftWidth = this.domNode.style.borderLeftWidth; this.domNode.style.borderWidth = "0px 0px 0px 0px"; } // dojo.debug ("fillInTemplate - className = " + this.domNode.className); // setup drag-n-drop for the sliderHandle this._handleMove = new dojo.widget._SliderDragMoveSource (this.sliderHandleNode); this._handleMove.setParent (this); if (this.clickSelect){ dojo.event.connect (this.constrainingContainerNode, "onmousedown", this, "_onClick"); } if (this.isEnableX){ this.setValueX (!isNaN(this.initialValueX) ? this.initialValueX : (!isNaN(this.minimumX) ? this.minimumX : 0)); } if (!this.isEnableX || !this.showButtons){ this.rightButtonNode.style.width = "1px"; // allow the border to show this.rightButtonNode.style.visibility = "hidden"; this.leftButtonNode.style.width = "1px"; // allow the border to show this.leftButtonNode.style.visibility = "hidden"; } if (this.isEnableY){ this.setValueY (!isNaN(this.initialValueY) ? this.initialValueY : (!isNaN(this.minimumY) ? this.minimumY : 0)); } if (!this.isEnableY || !this.showButtons){ this.bottomButtonNode.style.width = "1px"; // allow the border to show this.bottomButtonNode.style.visibility = "hidden"; this.topButtonNode.style.width = "1px"; // allow the border to show this.topButtonNode.style.visibility = "hidden"; } if(this.focusNode.addEventListener){ // dojo.event.connect() doesn't seem to work with DOMMouseScroll this.focusNode.addEventListener('DOMMouseScroll', dojo.lang.hitch(this, "_mouseWheeled"), false); // Mozilla + Firefox + Netscape } }, // move the X value to the closest allowable value _snapX: function(/*Number*/ x){ if (x < 0){ x = 0; } else if (x > this._constraintWidth){ x = this._constraintWidth; } else { var selectedValue = Math.round (x / this._valueSizeX); x = Math.round (selectedValue * this._valueSizeX); } this.sliderHandleNode.style.left = x + "px"; if (this.flipX){ this._clipLeft = x + this._clipXdelta; } else { this._clipRight = x + this._clipXdelta; } this.progressBackgroundNode.style.clip = "rect("+this._clipTop+"px,"+this._clipRight+"px,"+this._clipBottom+"px,"+this._clipLeft+"px)"; }, // compute _valueSizeX & _constraintWidth & default snapValuesX _calc_valueSizeX: function (){ var constrainingCtrBox = dojo.html.getContentBox(this.constrainingContainerNode); var sliderHandleBox = dojo.html.getContentBox(this.sliderHandleNode); if (isNaN(constrainingCtrBox.width) || isNaN(sliderHandleBox.width) || constrainingCtrBox.width <= 0 || sliderHandleBox.width <= 0){ return false; } this._constraintWidth = constrainingCtrBox.width + dojo.html.getPadding(this.constrainingContainerNode).width - sliderHandleBox.width; if (this.flipX){ this._clipLeft = this._clipRight = constrainingCtrBox.width; } else { this._clipLeft = this._clipRight = 0; } this._clipXdelta = sliderHandleBox.width >> 1; if (!this.isEnableY){ this._clipTop = 0; this._clipBottom = constrainingCtrBox.height; } if (this._constraintWidth <= 0){ return false; } if (this.snapValuesX == 0){ this.snapValuesX = this._constraintWidth + 1; } this._valueSizeX = this._constraintWidth / (this.snapValuesX - 1); return true; }, // summary // move the handle horizontally to the specified value setValueX: function (/*Number*/ value){ if (0.0 == this._valueSizeX){ if (this._calc_valueSizeX () == false){ dojo.lang.setTimeout(this, "setValueX", 100, value); return; } } if (isNaN(value)){ value = 0; } if (value > this.maximumX){ value = this.maximumX; } else if (value < this.minimumX){ value = this.minimumX; } var pixelPercent = (value-this.minimumX) / (this.maximumX-this.minimumX); if (this.flipX){ pixelPercent = 1.0 - pixelPercent; } this._snapX (pixelPercent * this._constraintWidth); this.notifyListeners(); }, // summary // return the X value that the matches the position of the handle getValueX: function (){ var pixelPercent = dojo.html.getPixelValue (this.sliderHandleNode,"left") / this._constraintWidth; if (this.flipX){ pixelPercent = 1.0 - pixelPercent; } return Math.round (pixelPercent * (this.snapValuesX-1)) * ((this.maximumX-this.minimumX) / (this.snapValuesX-1)) + this.minimumX; }, // move the Y value to the closest allowable value _snapY: function (/*Number*/ y){ if (y < 0){ y = 0; } else if (y > this._constraintHeight){ y = this._constraintHeight; } else { var selectedValue = Math.round (y / this._valueSizeY); y = Math.round (selectedValue * this._valueSizeY); } this.sliderHandleNode.style.top = y + "px"; if (this.flipY){ this._clipTop = y + this._clipYdelta; } else { this._clipBottom = y + this._clipYdelta; } this.progressBackgroundNode.style.clip = "rect("+this._clipTop+"px,"+this._clipRight+"px,"+this._clipBottom+"px,"+this._clipLeft+"px)"; }, // compute _valueSizeY & _constraintHeight & default snapValuesY _calc_valueSizeY: function (){ var constrainingCtrBox = dojo.html.getContentBox(this.constrainingContainerNode); var sliderHandleBox = dojo.html.getContentBox(this.sliderHandleNode); if (isNaN(constrainingCtrBox.height) || isNaN(sliderHandleBox.height) || constrainingCtrBox.height <= 0 || sliderHandleBox.height <= 0){ return false; } this._constraintHeight = constrainingCtrBox.height + dojo.html.getPadding(this.constrainingContainerNode).height - sliderHandleBox.height; if (this.flipY){ this._clipTop = this._clipBottom = constrainingCtrBox.height; } else { this._clipTop = this._clipBottom = 0; } this._clipYdelta = sliderHandleBox.height >> 1; if (!this.isEnableX){ this._clipLeft = 0; this._clipRight = constrainingCtrBox.width; } if (this._constraintHeight <= 0){ return false; } if (this.snapValuesY == 0){ this.snapValuesY = this._constraintHeight + 1; } this._valueSizeY = this._constraintHeight / (this.snapValuesY - 1); return true; }, // summary // move the handle vertically to the specified value setValueY: function (/*Number*/ value){ if (0.0 == this._valueSizeY){ if (this._calc_valueSizeY () == false){ dojo.lang.setTimeout(this, "setValueY", 100, value); return; } } if (isNaN(value)){ value = 0; } if (value > this.maximumY){ value = this.maximumY; } else if (value < this.minimumY){ value = this.minimumY; } var pixelPercent = (value-this.minimumY) / (this.maximumY-this.minimumY); if (this.flipY){ pixelPercent = 1.0 - pixelPercent; } this._snapY (pixelPercent * this._constraintHeight); this.notifyListeners(); }, // summary // return the Y value that the matches the position of the handle getValueY: function (){ var pixelPercent = dojo.html.getPixelValue (this.sliderHandleNode,"top") / this._constraintHeight; if (this.flipY){ pixelPercent = 1.0 - pixelPercent; } return Math.round (pixelPercent * (this.snapValuesY-1)) * ((this.maximumY-this.minimumY) / (this.snapValuesY-1)) + this.minimumY; }, // set the position of the handle _onClick: function(/*Event*/ evt){ if (this._isDragInProgress){ return; } var parent = dojo.html.getAbsolutePosition(this.constrainingContainerNode, true, dojo.html.boxSizing.MARGIN_BOX); var content = dojo.html.getContentBox(this._handleMove.domNode); if (this.isEnableX){ var x = evt.pageX - parent.x - (content.width >> 1); this._snapX(x); } if (this.isEnableY){ var y = evt.pageY - parent.y - (content.height >> 1); this._snapY(y); } this.notifyListeners(); }, // summary // method to invoke user's onValueChanged method notifyListeners: function(){ this.onValueChanged(this.getValueX(), this.getValueY()); }, // summary // empty method to be overridden by user onValueChanged: function(/*Number*/ x, /*Number*/ y){ } } ); dojo.widget.defineWidget ( "dojo.widget.SliderHorizontal", dojo.widget.Slider, { // summary // the horizontal slider widget subclass isEnableX: true, isEnableY: false, // initialValue: Number // sets initialValueX. // TODO: should be called "value". Also, common attributes between SliderHorizontal/SliderVertical // should be consolidated to Slider1D base class initialValue: "", // snapValues: Number // sets snapValuesX snapValues: "", // minimum: Number // sets minimumX minimum: "", // maximum: Number // sets maximumX maximum: "", // buttonStyle: String // sets buttonStyleX buttonStyle: "", backgroundSize: "height:10px;width:200px;", backgroundSrc: dojo.uri.dojoUri("src/widget/templates/images/slider-bg.gif"), // flip: Boolean // sets flipX flip: false, postMixInProperties: function(){ dojo.widget.SliderHorizontal.superclass.postMixInProperties.apply(this, arguments); if (!isNaN(parseFloat(this.initialValue))){ this.initialValueX = parseFloat(this.initialValue); } if (!isNaN(parseFloat(this.minimum))){ this.minimumX = parseFloat(this.minimum); } if (!isNaN(parseFloat(this.maximum))){ this.maximumX = parseFloat(this.maximum); } if (!isNaN(parseInt(this.snapValues))){ this.snapValuesX = parseInt(this.snapValues); } if (dojo.lang.isString(this.buttonStyle) && this.buttonStyle != ""){ this.buttonStyleX = this.buttonStyle; } if (dojo.lang.isBoolean(this.flip)){ this.flipX = this.flip; } }, notifyListeners: function(){ this.onValueChanged(this.getValueX()); }, // summary // wrapper for getValueX() getValue: function (){ return this.getValueX (); }, // summary // wrapper for setValueX() setValue: function (/*Number*/ value){ this.setValueX (value); }, onValueChanged: function(/*Number*/ value){ } } ); /* ------------------------------------------------------------------------- */ dojo.widget.defineWidget ( "dojo.widget.SliderVertical", dojo.widget.Slider, { // summary // the vertical slider widget subclass isEnableX: false, isEnableY: true, // initialValue: Number // sets initialValueY initialValue: "", // snapValues: Number // sets snapValuesY snapValues: "", // minimum: Number // sets minimumY minimum: "", // Number // maximum: sets maximumY maximum: "", // buttonStyle: String // sets buttonStyleY buttonStyle: "", backgroundSize: "width:10px;height:200px;", backgroundSrc: dojo.uri.dojoUri("src/widget/templates/images/slider-bg-vert.gif"), // flip: Boolean // sets flipY flip: false, postMixInProperties: function(){ dojo.widget.SliderVertical.superclass.postMixInProperties.apply(this, arguments); if (!isNaN(parseFloat(this.initialValue))){ this.initialValueY = parseFloat(this.initialValue); } if (!isNaN(parseFloat(this.minimum))){ this.minimumY = parseFloat(this.minimum); } if (!isNaN(parseFloat(this.maximum))){ this.maximumY = parseFloat(this.maximum); } if (!isNaN(parseInt(this.snapValues))){ this.snapValuesY = parseInt(this.snapValues); } if (dojo.lang.isString(this.buttonStyle) && this.buttonStyle != ""){ this.buttonStyleY = this.buttonStyle; } if (dojo.lang.isBoolean(this.flip)){ this.flipY = this.flip; } }, notifyListeners: function(){ this.onValueChanged(this.getValueY()); }, // summary // wrapper for getValueY() getValue: function (){ return this.getValueY (); }, // summary // wrapper for setValueY() setValue: function (/*Number*/ value){ this.setValueY (value); }, onValueChanged: function(/*Number*/ value){ } } ); /* ------------------------------------------------------------------------- */ /** * This class extends the HtmlDragMoveSource class to provide * features for the slider handle. */ dojo.declare ( "dojo.widget._SliderDragMoveSource", dojo.dnd.HtmlDragMoveSource, { slider: null, /** Setup the handle for drag * Extends dojo.dnd.HtmlDragMoveSource by creating a SliderDragMoveSource */ onDragStart: function(/*Event*/ evt){ this.slider._isDragInProgress = true; var dragObj = this.createDragMoveObject (); this.slider.notifyListeners(); return dragObj; }, onDragEnd: function(/*Event*/ evt){ this.slider._isDragInProgress = false; this.slider.notifyListeners(); }, createDragMoveObject: function (){ //dojo.debug ("SliderDragMoveSource#createDragMoveObject - " + this.slider); var dragObj = new dojo.widget._SliderDragMoveObject (this.dragObject, this.type); dragObj.slider = this.slider; // this code copied from dojo.dnd.HtmlDragSource#onDragStart if (this.dragClass){ dragObj.dragClass = this.dragClass; } return dragObj; }, setParent: function (/*Widget*/ slider){ this.slider = slider; } }); /* ------------------------------------------------------------------------- */ /** * This class extends the HtmlDragMoveObject class to provide * features for the slider handle. */ dojo.declare ( "dojo.widget._SliderDragMoveObject", dojo.dnd.HtmlDragMoveObject, { // reference to dojo.widget.Slider slider: null, /** Moves the node to follow the mouse. * Extends functon HtmlDragObject by adding functionality to snap handle * to a discrete value */ onDragMove: function(/*Event*/ evt){ this.updateDragOffset (); if (this.slider.isEnableX){ var x = this.dragOffset.x + evt.pageX; this.slider._snapX(x); } if (this.slider.isEnableY){ var y = this.dragOffset.y + evt.pageY; this.slider._snapY(y); } if(this.slider.activeDrag){ this.slider.notifyListeners(); } } });