mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-14 17:58:59 +00:00
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@5282 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
928 lines
28 KiB
JavaScript
928 lines
28 KiB
JavaScript
/*
|
|
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();
|
|
}
|
|
}
|
|
});
|