source: Dev/branches/rest-dojo-ui/client/dojox/mobile/Slider.js @ 256

Last change on this file since 256 was 256, checked in by hendrikvanantwerpen, 13 years ago

Reworked project structure based on REST interaction and Dojo library. As
soon as this is stable, the old jQueryUI branch can be removed (it's
kept for reference).

File size: 6.8 KB
Line 
1define([
2        "dojo/_base/array",
3        "dojo/_base/connect",
4        "dojo/_base/declare",
5        "dojo/_base/lang",
6        "dojo/_base/window",
7        "dojo/dom-class",
8        "dojo/dom-construct",
9        "dojo/dom-geometry",
10        "dojo/dom-style",
11        "dijit/_WidgetBase",
12        "dijit/form/_FormValueMixin"
13],
14        function(array, connect, declare, lang, win, domClass, domConstruct, domGeometry, domStyle, WidgetBase, FormValueMixin){
15
16        /*=====
17                WidgetBase = dijit._WidgetBase;
18                FormValueMixin = dijit.form._FormValueMixin;
19        =====*/
20        return declare("dojox.mobile.Slider", [WidgetBase, FormValueMixin], {
21                // summary:
22                //              A non-templated Slider widget similar to the HTML5 INPUT type=range.
23                //
24
25                // value: [const] Number
26                //              The current slider value.
27                value: 0,
28
29                // min: [const] Number
30                //              The first value the slider can be set to.
31                min: 0,
32
33                // max: [const] Number
34                //              The last value the slider can be set to.
35                max: 100,
36
37                // step: [const] Number
38                //              The delta from 1 value to another.
39                //              This causes the slider handle to snap/jump to the closest possible value.
40                //              A value of 0 means continuous (as much as allowed by pixel resolution).
41                step: 1,
42
43                baseClass: "mblSlider",
44
45                // flip: [const] Boolean
46                //              Specifies if the slider should change its default: ascending <--> descending.
47                flip: false,
48
49                // orientation: [const] String
50                //              The slider direction.
51                //              "H": horizontal
52                //              "V": vertical
53                //              "auto": use width/height comparison at instantiation time (default is "H" if width/height are 0)
54                orientation: "auto",
55
56                // halo: Number
57                //              Size of the boundary that extends beyond the edges of the slider
58                //              to make it easier to touch.
59                halo: "8pt",
60
61                buildRendering: function(){
62                        this.focusNode = this.domNode = domConstruct.create("div", {});
63                        this.valueNode = domConstruct.create("input", (this.srcNodeRef && this.srcNodeRef.name) ? { type: "hidden", name: this.srcNodeRef.name } : { type: "hidden" }, this.domNode, "last");
64                        var relativeParent = domConstruct.create("div", { style: { position:"relative", height:"100%", width:"100%" } }, this.domNode, "last");
65                        this.progressBar = domConstruct.create("div", { style:{ position:"absolute" }, "class":"mblSliderProgressBar" }, relativeParent, "last");
66                        this.touchBox = domConstruct.create("div", { style:{ position:"absolute" }, "class":"mblSliderTouchBox" }, relativeParent, "last");
67                        this.handle = domConstruct.create("div", { style:{ position:"absolute" }, "class":"mblSliderHandle" }, relativeParent, "last");
68                        this.inherited(arguments);
69                },
70
71                _setValueAttr: function(/*Number*/ value, /*Boolean?*/ priorityChange){
72                        // summary:
73                        //              Hook so set('value', value) works.
74                        var fromPercent = (this.value - this.min) * 100 / (this.max - this.min);
75                        this.valueNode.value = value;
76                        this.inherited(arguments);
77                        if(!this._started){ return; } // don't move images until all the properties are set
78                        this.focusNode.setAttribute("aria-valuenow", value);
79                        var toPercent = (value - this.min) * 100 / (this.max - this.min);
80                        // now perform visual slide
81                        var horizontal = this.orientation != "V";
82                        if(priorityChange === true){
83                                domClass.add(this.handle, "mblSliderTransition");
84                                domClass.add(this.progressBar, "mblSliderTransition");
85                        }else{
86                                domClass.remove(this.handle, "mblSliderTransition");
87                                domClass.remove(this.progressBar, "mblSliderTransition");
88                        }
89                        domStyle.set(this.handle, this._attrs.handleLeft, (this._reversed ? (100-toPercent) : toPercent) + "%");
90                        domStyle.set(this.progressBar, this._attrs.width, toPercent + "%");
91                },
92
93                postCreate: function(){
94                        this.inherited(arguments);
95
96                        function beginDrag(e){
97                                function getEventData(e){
98                                        point = isMouse ? e[this._attrs.pageX] : (e.touches ? e.touches[0][this._attrs.pageX] : e[this._attrs.clientX]);
99                                        pixelValue = point - startPixel;
100                                        pixelValue = Math.min(Math.max(pixelValue, 0), maxPixels);
101                                        var discreteValues = this.step ? ((this.max - this.min) / this.step) : maxPixels;
102                                        if(discreteValues <= 1 || discreteValues == Infinity ){ discreteValues = maxPixels; }
103                                        var wholeIncrements = Math.round(pixelValue * discreteValues / maxPixels);
104                                        value = (this.max - this.min) * wholeIncrements / discreteValues;
105                                        value = this._reversed ? (this.max - value) : (this.min + value);
106                                }
107                                function continueDrag(e){
108                                        e.preventDefault();
109                                        lang.hitch(this, getEventData)(e);
110                                        this.set('value', value, false);
111                                }
112               
113                                function endDrag(e){
114                                        e.preventDefault();
115                                        array.forEach(actionHandles, lang.hitch(this, "disconnect"));
116                                        actionHandles = [];
117                                        this.set('value', this.value, true);
118                                }
119
120                                e.preventDefault();
121                                var isMouse = e.type == "mousedown";
122                                var box = domGeometry.position(node, false); // can't use true since the added docScroll and the returned x are body-zoom incompatibile
123                                var bodyZoom = domStyle.get(win.body(), "zoom") || 1;
124                                if(isNaN(bodyZoom)){ bodyZoom = 1; }
125                                var nodeZoom = domStyle.get(node, "zoom") || 1;
126                                if(isNaN(nodeZoom)){ nodeZoom = 1; }
127                                var startPixel = box[this._attrs.x] * nodeZoom * bodyZoom + domGeometry.docScroll()[this._attrs.x];
128                                var maxPixels = box[this._attrs.w] * nodeZoom * bodyZoom;
129                                lang.hitch(this, getEventData)(e);
130                                if(e.target == this.touchBox){
131                                        this.set('value', value, true);
132                                }
133                                array.forEach(actionHandles, connect.disconnect);
134                                var root = win.doc.documentElement;
135                                var actionHandles = [
136                                        this.connect(root, isMouse ? "onmousemove" : "ontouchmove", continueDrag),
137                                        this.connect(root, isMouse ? "onmouseup" : "ontouchend", endDrag)
138                                ];
139                        }
140
141                        var point, pixelValue, value;
142                        var node = this.domNode;
143                        if(this.orientation == "auto"){
144                                 this.orientation = node.offsetHeight <= node.offsetWidth ? "H" : "V";
145                        }
146                        // add V or H suffix to baseClass for styling purposes
147                        domClass.add(this.domNode, array.map(this.baseClass.split(" "), lang.hitch(this, function(c){ return c+this.orientation; })));
148                        var horizontal = this.orientation != "V";
149                        var ltr = horizontal ? this.isLeftToRight() : false;
150                        var flip = this.flip;
151                        // _reversed is complicated since you can have flipped right-to-left and vertical is upside down by default
152                        this._reversed = !(horizontal && ((ltr && !flip) || (!ltr && flip))) || (!horizontal && !flip);
153                        this._attrs = horizontal ? { x:'x', w:'w', l:'l', r:'r', pageX:'pageX', clientX:'clientX', handleLeft:"left", left:this._reversed ? "right" : "left", width:"width" } : { x:'y', w:'h', l:'t', r:'b', pageX:'pageY', clientX:'clientY', handleLeft:"top", left:this._reversed ? "bottom" : "top", width:"height" };
154                        this.progressBar.style[this._attrs.left] = "0px";
155                        this.connect(this.touchBox, "touchstart", beginDrag);
156                        this.connect(this.touchBox, "onmousedown", beginDrag); // in case this works
157                        this.connect(this.handle, "touchstart", beginDrag);
158                        this.connect(this.handle, "onmousedown", beginDrag); // in case this works
159                        this.startup();
160                        this.set('value', this.value);
161                }
162        });
163});
Note: See TracBrowser for help on using the repository browser.