source: Dev/branches/rest-dojo-ui/client/dojox/mobile/Switch.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.5 KB
Line 
1define([
2        "dojo/_base/array",
3        "dojo/_base/connect",
4        "dojo/_base/declare",
5        "dojo/_base/event",
6        "dojo/_base/window",
7        "dojo/dom-class",
8        "dijit/_Contained",
9        "dijit/_WidgetBase",
10        "./sniff"
11], function(array, connect, declare, event, win, domClass, Contained, WidgetBase, has){
12
13/*=====
14        Contained = dijit._Contained;
15        WidgetBase = dijit._WidgetBase;
16=====*/
17
18        // module:
19        //              dojox/mobile/Switch
20        // summary:
21        //              A toggle switch with a sliding knob.
22
23        return declare("dojox.mobile.Switch", [WidgetBase, Contained],{
24                // summary:
25                //              A toggle switch with a sliding knob.
26                // description:
27                //              Switch is a toggle switch with a sliding knob. You can either
28                //              tap or slide the knob to toggle the switch. The onStateChanged
29                //              handler is called when the switch is manipulated.
30
31                // value: String
32                //              The initial state of the switch. "on" or "off". The default
33                //              value is "on".
34                value: "on",
35
36                // name: String
37                //              A name for a hidden input field, which holds the current value.
38                name: "",
39
40                // leftLabel: String
41                //              The left-side label of the switch.
42                leftLabel: "ON",
43
44                // rightLabel: String
45                //              The right-side label of the switch.
46                rightLabel: "OFF",
47
48                /* internal properties */       
49                _width: 53,
50
51                buildRendering: function(){
52                        this.domNode = win.doc.createElement("DIV");
53                        var c = (this.srcNodeRef && this.srcNodeRef.className) || this.className || this["class"];
54                        this._swClass = (c || "").replace(/ .*/,"");
55                        this.domNode.className = "mblSwitch";
56                        var nameAttr = this.name ? " name=\"" + this.name + "\"" : "";
57                        this.domNode.innerHTML =
58                                  '<div class="mblSwitchInner">'
59                                +       '<div class="mblSwitchBg mblSwitchBgLeft">'
60                                +               '<div class="mblSwitchText mblSwitchTextLeft"></div>'
61                                +       '</div>'
62                                +       '<div class="mblSwitchBg mblSwitchBgRight">'
63                                +               '<div class="mblSwitchText mblSwitchTextRight"></div>'
64                                +       '</div>'
65                                +       '<div class="mblSwitchKnob"></div>'
66                                +       '<input type="hidden"'+nameAttr+'></div>'
67                                + '</div>';
68                        var n = this.inner = this.domNode.firstChild;
69                        this.left = n.childNodes[0];
70                        this.right = n.childNodes[1];
71                        this.knob = n.childNodes[2];
72                        this.input = n.childNodes[3];
73                },
74
75                postCreate: function(){
76                        this.connect(this.domNode, "onclick", "onClick");
77                        this.connect(this.domNode, has('touch') ? "touchstart" : "onmousedown", "onTouchStart");
78                        this._initialValue = this.value; // for reset()
79                },
80
81                _changeState: function(/*String*/state, /*Boolean*/anim){
82                        var on = (state === "on");
83                        this.left.style.display = "";
84                        this.right.style.display = "";
85                        this.inner.style.left = "";
86                        if(anim){
87                                domClass.add(this.domNode, "mblSwitchAnimation");
88                        }
89                        domClass.remove(this.domNode, on ? "mblSwitchOff" : "mblSwitchOn");
90                        domClass.add(this.domNode, on ? "mblSwitchOn" : "mblSwitchOff");
91       
92                        var _this = this;
93                        setTimeout(function(){
94                                _this.left.style.display = on ? "" : "none";
95                                _this.right.style.display = !on ? "" : "none";
96                                domClass.remove(_this.domNode, "mblSwitchAnimation");
97                        }, anim ? 300 : 0);
98                },
99
100                startup: function(){
101                        if(this._swClass.indexOf("Round") != -1){
102                                var r = Math.round(this.domNode.offsetHeight / 2);
103                                this.createRoundMask(this._swClass, r, this.domNode.offsetWidth);
104                        }
105                },
106       
107                createRoundMask: function(className, r, w){
108                        if(!has("webkit") || !className){ return; }
109                        if(!this._createdMasks){ this._createdMasks = []; }
110                        if(this._createdMasks[className]){ return; }
111                        this._createdMasks[className] = 1;
112       
113                        var ctx = win.doc.getCSSCanvasContext("2d", className+"Mask", w, 100);
114                        ctx.fillStyle = "#000000";
115                        ctx.beginPath();
116                        ctx.moveTo(r, 0);
117                        ctx.arcTo(0, 0, 0, 2*r, r);
118                        ctx.arcTo(0, 2*r, r, 2*r, r);
119                        ctx.lineTo(w - r, 2*r);
120                        ctx.arcTo(w, 2*r, w, r, r);
121                        ctx.arcTo(w, 0, w - r, 0, r);
122                        ctx.closePath();
123                        ctx.fill();
124                },
125       
126                onClick: function(e){
127                        if(this._moved){ return; }
128                        this.value = this.input.value = (this.value == "on") ? "off" : "on";
129                        this._changeState(this.value, true);
130                        this.onStateChanged(this.value);
131                },
132       
133                onTouchStart: function(e){
134                        // summary:
135                        //              Internal function to handle touchStart events.
136                        this._moved = false;
137                        this.innerStartX = this.inner.offsetLeft;
138                        if(!this._conn){
139                                this._conn = [];
140                                this._conn.push(connect.connect(this.inner, has('touch') ? "touchmove" : "onmousemove", this, "onTouchMove"));
141                                this._conn.push(connect.connect(this.inner, has('touch') ? "touchend" : "onmouseup", this, "onTouchEnd"));
142                        }
143                        this.touchStartX = e.touches ? e.touches[0].pageX : e.clientX;
144                        this.left.style.display = "";
145                        this.right.style.display = "";
146                        event.stop(e);
147                },
148       
149                onTouchMove: function(e){
150                        // summary:
151                        //              Internal function to handle touchMove events.
152                        e.preventDefault();
153                        var dx;
154                        if(e.targetTouches){
155                                if(e.targetTouches.length != 1){ return false; }
156                                dx = e.targetTouches[0].clientX - this.touchStartX;
157                        }else{
158                                dx = e.clientX - this.touchStartX;
159                        }
160                        var pos = this.innerStartX + dx;
161                        var d = 10;
162                        if(pos <= -(this._width-d)){ pos = -this._width; }
163                        if(pos >= -d){ pos = 0; }
164                        this.inner.style.left = pos + "px";
165                        if(Math.abs(dx) > d){
166                                this._moved = true;
167                        }
168                },
169       
170                onTouchEnd: function(e){
171                        // summary:
172                        //              Internal function to handle touchEnd events.
173                        array.forEach(this._conn, connect.disconnect);
174                        this._conn = null;
175                        if(this.innerStartX == this.inner.offsetLeft){
176                                if(has('touch')){
177                                        var ev = win.doc.createEvent("MouseEvents");
178                                        ev.initEvent("click", true, true);
179                                        this.inner.dispatchEvent(ev);
180                                }
181                                return;
182                        }
183                        var newState = (this.inner.offsetLeft < -(this._width/2)) ? "off" : "on";
184                        this._changeState(newState, true);
185                        if(newState != this.value){
186                                this.value = this.input.value = newState;
187                                this.onStateChanged(newState);
188                        }
189                },
190       
191                onStateChanged: function(/*String*/newState){
192                        // summary:
193                        //              Stub function to connect to from your application.
194                        // description:
195                        //              Called when the state has been changed.
196                },
197       
198                _setValueAttr: function(/*String*/value){
199                        this._changeState(value, false);
200                        if(this.value != value){
201                                this.onStateChanged(value);
202                        }
203                        this.value = this.input.value = value;
204                },
205       
206                _setLeftLabelAttr: function(/*String*/label){
207                        this.leftLabel = label;
208                        this.left.firstChild.innerHTML = this._cv ? this._cv(label) : label;
209                },
210       
211                _setRightLabelAttr: function(/*String*/label){
212                        this.rightLabel = label;
213                        this.right.firstChild.innerHTML = this._cv ? this._cv(label) : label;
214                },
215
216                reset: function(){
217                        // summary:
218                        //              Reset the widget's value to what it was at initialization time
219                        this.set("value", this._initialValue);
220                }
221        });
222});
Note: See TracBrowser for help on using the repository browser.