]>
git.wh0rd.org - tt-rss.git/blob - lib/dijit/form/HorizontalSlider.js
2 Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
3 Available via Academic Free License >= 2.1 OR the modified BSD license.
4 see: http://dojotoolkit.org/license for details
8 if(!dojo
._hasResource
["dijit.form.HorizontalSlider"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
9 dojo
._hasResource
["dijit.form.HorizontalSlider"] = true;
10 dojo
.provide("dijit.form.HorizontalSlider");
11 dojo
.require("dijit.form._FormWidget");
12 dojo
.require("dijit._Container");
13 dojo
.require("dojo.dnd.move");
14 dojo
.require("dijit.form.Button");
15 dojo
.require("dojo.number");
19 "dijit.form.HorizontalSlider",
20 [dijit
.form
._FormValueWidget
, dijit
._Container
],
23 // A form widget that allows one to select a value with a horizontally draggable handle
25 templateString
: dojo
.cache("dijit.form", "templates/HorizontalSlider.html", "<table class=\"dijit dijitReset dijitSlider dijitSliderH\" cellspacing=\"0\" cellpadding=\"0\" border=\"0\" rules=\"none\" dojoAttachEvent=\"onkeypress:_onKeyPress,onkeyup:_onKeyUp\"\n\t><tr class=\"dijitReset\"\n\t\t><td class=\"dijitReset\" colspan=\"2\"></td\n\t\t><td dojoAttachPoint=\"topDecoration\" class=\"dijitReset dijitSliderDecoration dijitSliderDecorationT dijitSliderDecorationH\"></td\n\t\t><td class=\"dijitReset\" colspan=\"2\"></td\n\t></tr\n\t><tr class=\"dijitReset\"\n\t\t><td class=\"dijitReset dijitSliderButtonContainer dijitSliderButtonContainerH\"\n\t\t\t><div class=\"dijitSliderDecrementIconH\" style=\"display:none\" dojoAttachPoint=\"decrementButton\"><span class=\"dijitSliderButtonInner\">-</span></div\n\t\t></td\n\t\t><td class=\"dijitReset\"\n\t\t\t><div class=\"dijitSliderBar dijitSliderBumper dijitSliderBumperH dijitSliderLeftBumper\" dojoAttachEvent=\"onmousedown:_onClkDecBumper\"></div\n\t\t></td\n\t\t><td class=\"dijitReset\"\n\t\t\t><input dojoAttachPoint=\"valueNode\" type=\"hidden\" ${!nameAttrSetting}\n\t\t\t/><div class=\"dijitReset dijitSliderBarContainerH\" role=\"presentation\" dojoAttachPoint=\"sliderBarContainer\"\n\t\t\t\t><div role=\"presentation\" dojoAttachPoint=\"progressBar\" class=\"dijitSliderBar dijitSliderBarH dijitSliderProgressBar dijitSliderProgressBarH\" dojoAttachEvent=\"onmousedown:_onBarClick\"\n\t\t\t\t\t><div class=\"dijitSliderMoveable dijitSliderMoveableH\"\n\t\t\t\t\t\t><div dojoAttachPoint=\"sliderHandle,focusNode\" class=\"dijitSliderImageHandle dijitSliderImageHandleH\" dojoAttachEvent=\"onmousedown:_onHandleClick\" role=\"slider\" valuemin=\"${minimum}\" valuemax=\"${maximum}\"></div\n\t\t\t\t\t></div\n\t\t\t\t></div\n\t\t\t\t><div role=\"presentation\" dojoAttachPoint=\"remainingBar\" class=\"dijitSliderBar dijitSliderBarH dijitSliderRemainingBar dijitSliderRemainingBarH\" dojoAttachEvent=\"onmousedown:_onBarClick\"></div\n\t\t\t></div\n\t\t></td\n\t\t><td class=\"dijitReset\"\n\t\t\t><div class=\"dijitSliderBar dijitSliderBumper dijitSliderBumperH dijitSliderRightBumper\" dojoAttachEvent=\"onmousedown:_onClkIncBumper\"></div\n\t\t></td\n\t\t><td class=\"dijitReset dijitSliderButtonContainer dijitSliderButtonContainerH\"\n\t\t\t><div class=\"dijitSliderIncrementIconH\" style=\"display:none\" dojoAttachPoint=\"incrementButton\"><span class=\"dijitSliderButtonInner\">+</span></div\n\t\t></td\n\t></tr\n\t><tr class=\"dijitReset\"\n\t\t><td class=\"dijitReset\" colspan=\"2\"></td\n\t\t><td dojoAttachPoint=\"containerNode,bottomDecoration\" class=\"dijitReset dijitSliderDecoration dijitSliderDecorationB dijitSliderDecorationH\"></td\n\t\t><td class=\"dijitReset\" colspan=\"2\"></td\n\t></tr\n></table>\n"),
27 // Overrides FormValueWidget.value to indicate numeric value
30 // showButtons: [const] Boolean
31 // Show increment/decrement buttons at the ends of the slider?
34 // minimum:: [const] Integer
35 // The minimum value the slider can be set to.
38 // maximum: [const] Integer
39 // The maximum value the slider can be set to.
42 // discreteValues: Integer
43 // If specified, indicates that the slider handle has only 'discreteValues' possible positions,
44 // and that after dragging the handle, it will snap to the nearest possible position.
45 // Thus, the slider has only 'discreteValues' possible values.
47 // For example, if minimum=10, maxiumum=30, and discreteValues=3, then the slider handle has
48 // three possible positions, representing values 10, 20, or 30.
50 // If discreteValues is not specified or if it's value is higher than the number of pixels
51 // in the slider bar, then the slider handle can be moved freely, and the slider's value will be
52 // computed/reported based on pixel position (in this case it will likely be fractional,
53 // such as 123.456789).
54 discreteValues
: Infinity
,
56 // pageIncrement: Integer
57 // If discreteValues is also specified, this indicates the amount of clicks (ie, snap positions)
58 // that the slider handle is moved via pageup/pagedown keys.
59 // If discreteValues is not specified, it indicates the number of pixels.
62 // clickSelect: Boolean
63 // If clicking the slider bar changes the value or not
66 // slideDuration: Number
67 // The time in ms to take to animate the slider handle from 0% to 100%,
68 // when clicking the slider bar to make the handle move.
69 slideDuration
: dijit
.defaultDuration
,
71 // Flag to _Templated (TODO: why is this here? I see no widgets in the template.)
72 widgetsInTemplate
: true,
74 attributeMap
: dojo
.delegate(dijit
.form
._FormWidget
.prototype.attributeMap
, {
78 baseClass
: "dijitSlider",
80 // Apply CSS classes to up/down arrows and handle per mouse state
82 incrementButton
: "dijitSliderIncrementButton",
83 decrementButton
: "dijitSliderDecrementButton",
84 focusNode
: "dijitSliderThumb"
87 _mousePixelCoord
: "pageX",
89 _startingPixelCoord
: "x",
90 _startingPixelCount
: "l",
91 _handleOffsetCoord
: "left",
92 _progressPixelSize
: "width",
94 _onKeyUp: function(/*Event*/ e
){
95 if(this.disabled
|| this.readOnly
|| e
.altKey
|| e
.ctrlKey
|| e
.metaKey
){ return; }
96 this._setValueAttr(this.value
, true);
99 _onKeyPress: function(/*Event*/ e
){
100 if(this.disabled
|| this.readOnly
|| e
.altKey
|| e
.ctrlKey
|| e
.metaKey
){ return; }
101 switch(e
.charOrCode
){
103 this._setValueAttr(this.minimum
, false);
106 this._setValueAttr(this.maximum
, false);
108 // this._descending === false: if ascending vertical (min on top)
109 // (this._descending || this.isLeftToRight()): if left-to-right horizontal or descending vertical
110 case ((this._descending
|| this.isLeftToRight()) ? dojo
.keys
.RIGHT_ARROW
: dojo
.keys
.LEFT_ARROW
):
111 case (this._descending
=== false ? dojo
.keys
.DOWN_ARROW
: dojo
.keys
.UP_ARROW
):
112 case (this._descending
=== false ? dojo
.keys
.PAGE_DOWN
: dojo
.keys
.PAGE_UP
):
115 case ((this._descending
|| this.isLeftToRight()) ? dojo
.keys
.LEFT_ARROW
: dojo
.keys
.RIGHT_ARROW
):
116 case (this._descending
=== false ? dojo
.keys
.UP_ARROW
: dojo
.keys
.DOWN_ARROW
):
117 case (this._descending
=== false ? dojo
.keys
.PAGE_UP
: dojo
.keys
.PAGE_DOWN
):
126 _onHandleClick: function(e
){
127 if(this.disabled
|| this.readOnly
){ return; }
129 // make sure you get focus when dragging the handle
130 // (but don't do on IE because it causes a flicker on mouse up (due to blur then focus)
131 dijit
.focus(this.sliderHandle
);
136 _isReversed: function(){
138 // Returns true if direction is from right to left
140 // protected extension
141 return !this.isLeftToRight();
144 _onBarClick: function(e
){
145 if(this.disabled
|| this.readOnly
|| !this.clickSelect
){ return; }
146 dijit
.focus(this.sliderHandle
);
148 var abspos
= dojo
.position(this.sliderBarContainer
, true);
149 var pixelValue
= e
[this._mousePixelCoord
] - abspos
[this._startingPixelCoord
];
150 this._setPixelValue(this._isReversed() ? (abspos
[this._pixelCount
] - pixelValue
) : pixelValue
, abspos
[this._pixelCount
], true);
151 this._movable
.onMouseDown(e
);
154 _setPixelValue: function(/*Number*/ pixelValue
, /*Number*/ maxPixels
, /*Boolean?*/ priorityChange
){
155 if(this.disabled
|| this.readOnly
){ return; }
156 pixelValue
= pixelValue
< 0 ? 0 : maxPixels
< pixelValue
? maxPixels
: pixelValue
;
157 var count
= this.discreteValues
;
158 if(count
<= 1 || count
== Infinity
){ count
= maxPixels
; }
160 var pixelsPerValue
= maxPixels
/ count
;
161 var wholeIncrements
= Math
.round(pixelValue
/ pixelsPerValue
);
162 this._setValueAttr((this.maximum
-this.minimum
)*wholeIncrements
/count
+ this.minimum
, priorityChange
);
165 _setValueAttr: function(/*Number*/ value
, /*Boolean?*/ priorityChange
){
167 // Hook so set('value', value) works.
168 this._set("value", value
);
169 this.valueNode
.value
= value
;
170 dijit
.setWaiState(this.focusNode
, "valuenow", value
);
171 this.inherited(arguments
);
172 var percent
= (value
- this.minimum
) / (this.maximum
- this.minimum
);
173 var progressBar
= (this._descending
=== false) ? this.remainingBar
: this.progressBar
;
174 var remainingBar
= (this._descending
=== false) ? this.progressBar
: this.remainingBar
;
175 if(this._inProgressAnim
&& this._inProgressAnim
.status
!= "stopped"){
176 this._inProgressAnim
.stop(true);
178 if(priorityChange
&& this.slideDuration
> 0 && progressBar
.style
[this._progressPixelSize
]){
179 // animate the slider
182 var start
= parseFloat(progressBar
.style
[this._progressPixelSize
]);
183 var duration
= this.slideDuration
* (percent
-start
/100);
184 if(duration
== 0){ return; }
185 if(duration
< 0){ duration
= 0 - duration
; }
186 props
[this._progressPixelSize
] = { start
: start
, end
: percent
*100, units
:"%" };
187 this._inProgressAnim
= dojo
.animateProperty({ node
: progressBar
, duration
: duration
,
188 onAnimate: function(v
){ remainingBar
.style
[_this
._progressPixelSize
] = (100-parseFloat(v
[_this
._progressPixelSize
])) + "%"; },
189 onEnd: function(){ delete _this
._inProgressAnim
; },
192 this._inProgressAnim
.play();
194 progressBar
.style
[this._progressPixelSize
] = (percent
*100) + "%";
195 remainingBar
.style
[this._progressPixelSize
] = ((1-percent
)*100) + "%";
199 _bumpValue: function(signedChange
, /*Boolean?*/ priorityChange
){
200 if(this.disabled
|| this.readOnly
){ return; }
201 var s
= dojo
.getComputedStyle(this.sliderBarContainer
);
202 var c
= dojo
._getContentBox(this.sliderBarContainer
, s
);
203 var count
= this.discreteValues
;
204 if(count
<= 1 || count
== Infinity
){ count
= c
[this._pixelCount
]; }
206 var value
= (this.value
- this.minimum
) * count
/ (this.maximum
- this.minimum
) + signedChange
;
207 if(value
< 0){ value
= 0; }
208 if(value
> count
){ value
= count
; }
209 value
= value
* (this.maximum
- this.minimum
) / count
+ this.minimum
;
210 this._setValueAttr(value
, priorityChange
);
213 _onClkBumper: function(val
){
214 if(this.disabled
|| this.readOnly
|| !this.clickSelect
){ return; }
215 this._setValueAttr(val
, true);
218 _onClkIncBumper: function(){
219 this._onClkBumper(this._descending
=== false ? this.minimum
: this.maximum
);
222 _onClkDecBumper: function(){
223 this._onClkBumper(this._descending
=== false ? this.maximum
: this.minimum
);
226 decrement: function(/*Event*/ e
){
231 this._bumpValue(e
.charOrCode
== dojo
.keys
.PAGE_DOWN
? -this.pageIncrement
: -1);
234 increment: function(/*Event*/ e
){
239 this._bumpValue(e
.charOrCode
== dojo
.keys
.PAGE_UP
? this.pageIncrement
: 1);
242 _mouseWheeled: function(/*Event*/ evt
){
244 // Event handler for mousewheel where supported
246 var janky
= !dojo
.isMozilla
;
247 var scroll
= evt
[(janky
? "wheelDelta" : "detail")] * (janky
? 1 : -1);
248 this._bumpValue(scroll
< 0 ? -1 : 1, true); // negative scroll acts like a decrement
252 if(this._started
){ return; }
254 dojo
.forEach(this.getChildren(), function(child
){
255 if(this[child
.container
] != this.containerNode
){
256 this[child
.container
].appendChild(child
.domNode
);
260 this.inherited(arguments
);
263 _typematicCallback: function(/*Number*/ count
, /*Object*/ button
, /*Event*/ e
){
265 this._setValueAttr(this.value
, true);
267 this[(button
== (this._descending
? this.incrementButton
: this.decrementButton
)) ? "decrement" : "increment"](e
);
271 buildRendering: function(){
272 this.inherited(arguments
);
273 if(this.showButtons
){
274 this.incrementButton
.style
.display
="";
275 this.decrementButton
.style
.display
="";
278 // find any associated label element and add to slider focusnode.
279 var label
= dojo
.query('label[for="'+this.id
+'"]');
281 label
[0].id
= (this.id
+"_label");
282 dijit
.setWaiState(this.focusNode
, "labelledby", label
[0].id
);
285 dijit
.setWaiState(this.focusNode
, "valuemin", this.minimum
);
286 dijit
.setWaiState(this.focusNode
, "valuemax", this.maximum
);
289 postCreate: function(){
290 this.inherited(arguments
);
292 if(this.showButtons
){
293 this._connects
.push(dijit
.typematic
.addMouseListener(
294 this.decrementButton
, this, "_typematicCallback", 25, 500));
295 this._connects
.push(dijit
.typematic
.addMouseListener(
296 this.incrementButton
, this, "_typematicCallback", 25, 500));
298 this.connect(this.domNode
, !dojo
.isMozilla
? "onmousewheel" : "DOMMouseScroll", "_mouseWheeled");
300 // define a custom constructor for a SliderMover that points back to me
301 var mover
= dojo
.declare(dijit
.form
._SliderMover
, {
304 this._movable
= new dojo
.dnd
.Moveable(this.sliderHandle
, {mover
: mover
});
306 this._layoutHackIE7();
310 this._movable
.destroy();
311 if(this._inProgressAnim
&& this._inProgressAnim
.status
!= "stopped"){
312 this._inProgressAnim
.stop(true);
314 this._supportingWidgets
= dijit
.findWidgets(this.domNode
); // tells destroy about pseudo-child widgets (ruler/labels)
315 this.inherited(arguments
);
319 dojo
.declare("dijit.form._SliderMover",
322 onMouseMove: function(e
){
323 var widget
= this.widget
;
324 var abspos
= widget
._abspos
;
326 abspos
= widget
._abspos
= dojo
.position(widget
.sliderBarContainer
, true);
327 widget
._setPixelValue_
= dojo
.hitch(widget
, "_setPixelValue");
328 widget
._isReversed_
= widget
._isReversed();
330 var coordEvent
= e
.touches
? e
.touches
[0] : e
, // if multitouch take first touch for coords
331 pixelValue
= coordEvent
[widget
._mousePixelCoord
] - abspos
[widget
._startingPixelCoord
];
332 widget
._setPixelValue_(widget
._isReversed_
? (abspos
[widget
._pixelCount
]-pixelValue
) : pixelValue
, abspos
[widget
._pixelCount
], false);
335 destroy: function(e
){
336 dojo
.dnd
.Mover
.prototype.destroy
.apply(this, arguments
);
337 var widget
= this.widget
;
338 widget
._abspos
= null;
339 widget
._setValueAttr(widget
.value
, true);