source: Dev/branches/rest-dojo-ui/client/dojox/mobile/ComboBox.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.9 KB
Line 
1define([
2        "dojo/_base/kernel",
3        "dojo/_base/declare",
4        "dojo/_base/lang",
5        "dojo/_base/window",
6        "dojo/dom-geometry",
7        "dojo/dom-style",
8        "dojo/window",
9        "dijit/form/_AutoCompleterMixin",
10        "dijit/popup",
11        "./_ComboBoxMenu",
12        "./TextBox",
13        "./sniff"
14], function(kernel, declare, lang, win, domGeometry, domStyle, windowUtils, AutoCompleterMixin, popup, ComboBoxMenu, TextBox, has){
15        kernel.experimental("dojox.mobile.ComboBox"); // should be using a more native search-type UI
16
17        /*=====
18                TextBox = dojox.mobile.TextBox;
19                AutoCompleterMixin = dijit.form._AutoCompleterMixin;
20        =====*/
21        return declare("dojox.mobile.ComboBox", [TextBox, AutoCompleterMixin], {
22                // summary:
23                //              A non-templated auto-completing text box widget
24                //
25
26                // dropDownClass: [protected extension] String
27                //              Name of the dropdown widget class used to select a date/time.
28                //              Subclasses should specify this.
29                dropDownClass: "dojox.mobile._ComboBoxMenu",
30
31                // initially disable selection since iphone displays selection handles that makes it hard to pick from the list
32                selectOnClick: false,
33                autoComplete: false,
34
35                // dropDown: [protected] Widget
36                //              The widget to display as a popup.  This widget *must* be
37                //              defined before the startup function is called.
38                dropDown: null,
39
40                // maxHeight: [protected] Integer
41                //              The max height for our dropdown.
42                //              Any dropdown taller than this will have scrollbars.
43                //              Set to -1 to limit height to available space in viewport
44                maxHeight: -1,
45
46                // dropDownPosition: [const] String[]
47                //              This variable controls the position of the drop down.
48                //              It's an array of strings with the following values:
49                //
50                //                      * before: places drop down to the left of the target node/widget, or to the right in
51                //                        the case of RTL scripts like Hebrew and Arabic
52                //                      * after: places drop down to the right of the target node/widget, or to the left in
53                //                        the case of RTL scripts like Hebrew and Arabic
54                //                      * above: drop down goes above target node
55                //                      * below: drop down goes below target node
56                //
57                //              The list is positions is tried, in order, until a position is found where the drop down fits
58                //              within the viewport.
59                //
60                dropDownPosition: ["below","above"],
61
62                _throttleOpenClose: function(){
63                        // prevent open/close in rapid succession
64                        if(this._throttleHandler){
65                                clearTimeout(this._throttleHandler);
66                        }
67                        this._throttleHandler = setTimeout(lang.hitch(this, function(){ this._throttleHandler = null; }), 500);
68                },
69
70                _onFocus: function(){
71                        this.inherited(arguments);
72                        if(!this._opened && !this._throttleHandler){
73                                this._startSearchAll(); // show dropdown if user is selecting Next/Previous from virtual keyboard
74                        }
75                },
76
77                onInput: function(e){
78                        this._onKey(e);
79                        this.inherited(arguments);
80                },
81
82                _setListAttr: function(v){
83                        this._set('list', v); // needed for Firefox 4+ to prevent HTML5 mode
84                },
85
86                closeDropDown: function(){
87                        // summary:
88                        //              Closes the drop down on this widget
89                        // tags:
90                        //              protected
91
92                        this._throttleOpenClose();
93                        if(this.startHandler){
94                                this.disconnect(this.startHandler);
95                                this.startHandler = null;
96                                if(this.moveHandler){ this.disconnect(this.moveHandler); }
97                                if(this.endHandler){ this.disconnect(this.endHandler); }
98                        }
99                        this.inherited(arguments);
100                        popup.close(this.dropDown);
101                        this._opened = false;
102                },
103
104                openDropDown: function(){
105                        // summary:
106                        //              Opens the dropdown for this widget.   To be called only when this.dropDown
107                        //              has been created and is ready to display (ie, it's data is loaded).
108                        // returns:
109                        //              return value of popup.open()
110                        // tags:
111                        //              protected
112
113                        var wasClosed = !this._opened;
114                        var dropDown = this.dropDown,
115                                ddNode = dropDown.domNode,
116                                aroundNode = this.domNode,
117                                self = this;
118
119
120                        // TODO: isn't maxHeight dependent on the return value from popup.open(),
121                        // ie, dependent on how much space is available (BK)
122
123                        if(!this._preparedNode){
124                                this._preparedNode = true;
125                                // Check if we have explicitly set width and height on the dropdown widget dom node
126                                if(ddNode.style.width){
127                                        this._explicitDDWidth = true;
128                                }
129                                if(ddNode.style.height){
130                                        this._explicitDDHeight = true;
131                                }
132                        }
133
134                        // Code for resizing dropdown (height limitation, or increasing width to match my width)
135                        var myStyle = {
136                                display: "",
137                                overflow: "hidden",
138                                visibility: "hidden"
139                        };
140                        if(!this._explicitDDWidth){
141                                myStyle.width = "";
142                        }
143                        if(!this._explicitDDHeight){
144                                myStyle.height = "";
145                        }
146                        domStyle.set(ddNode, myStyle);
147
148                        // Figure out maximum height allowed (if there is a height restriction)
149                        var maxHeight = this.maxHeight;
150                        if(maxHeight == -1){
151                                // limit height to space available in viewport either above or below my domNode
152                                // (whichever side has more room)
153                                var viewport = windowUtils.getBox(),
154                                        position = domGeometry.position(aroundNode, false);
155                                maxHeight = Math.floor(Math.max(position.y, viewport.h - (position.y + position.h)));
156                        }
157
158                        // Attach dropDown to DOM and make make visibility:hidden rather than display:none
159                        // so we call startup() and also get the size
160                        popup.moveOffScreen(dropDown);
161
162                        if(dropDown.startup && !dropDown._started){
163                                dropDown.startup(); // this has to be done after being added to the DOM
164                        }
165                        // Get size of drop down, and determine if vertical scroll bar needed
166                        var mb = domGeometry.position(this.dropDown.containerNode, false);
167                        var overHeight = (maxHeight && mb.h > maxHeight);
168                        if(overHeight){
169                                mb.h = maxHeight;
170                        }
171
172                        // Adjust dropdown width to match or be larger than my width
173                        mb.w = Math.max(mb.w, aroundNode.offsetWidth);
174                        domGeometry.setMarginBox(ddNode, mb);
175
176                        var retVal = popup.open({
177                                parent: this,
178                                popup: dropDown,
179                                around: aroundNode,
180                                orient: this.dropDownPosition,
181                                onExecute: function(){
182                                        self.closeDropDown();
183                                },
184                                onCancel: function(){
185                                        self.closeDropDown();
186                                },
187                                onClose: function(){
188                                        self._opened = false;
189                                }
190                        });
191                        this._opened=true;
192
193                        if(wasClosed){
194                                if(retVal.aroundCorner.charAt(0) == 'B'){ // is popup below?
195                                        this.domNode.scrollIntoView(true); // scroll to top
196                                }
197                                this.startHandler = this.connect(win.doc.documentElement, has('touch') ? "ontouchstart" : "onmousedown",
198                                        lang.hitch(this, function(){
199                                                var isMove = false;
200                                                this.moveHandler = this.connect(win.doc.documentElement, has('touch') ? "ontouchmove" : "onmousemove", function(){ isMove = true; });
201                                                this.endHandler = this.connect(win.doc.documentElement, has('touch') ? "ontouchend" : "onmouseup", function(){ if(!isMove){ this.closeDropDown(); } });
202                                        })
203                                );
204                        }
205                        return retVal;
206                },
207
208                postCreate: function(){
209                        this.inherited(arguments);
210                        this.connect(this.domNode, "onclick", "_onClick");
211                },
212
213                _onClick: function(/*Event*/ e){
214                        // throttle clicks to prevent double click from doing double actions
215                        if(!this._throttleHandler){
216                                if(this.opened){
217                                        this.closeDropDown();
218                                }else{
219                                        this._startSearchAll();
220                                }
221                        }
222                }
223        });
224});
Note: See TracBrowser for help on using the repository browser.