source: Dev/branches/rest-dojo-ui/client/dojox/form/FilePickerTextBox.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: 9.3 KB
Line 
1define([
2        "dojo/_base/lang",
3        "dojo/_base/array",
4        "dojo/_base/event",
5        "dojo/window",
6        "dijit/focus",
7        "dijit/registry",
8        "dijit/form/_TextBoxMixin",
9        "dijit/form/ValidationTextBox",
10        "dijit/_HasDropDown",
11        "dojox/widget/FilePicker",
12        "dojo/text!./resources/FilePickerTextBox.html",
13        "dojo/_base/declare",
14        "dojo/keys" // keys
15], function(lang, array, event, windowUtils, focus, registry, _TextBoxMixin, ValidationTextBox, _HasDropDown, FilePicker, template, declare, keys){
16
17        /*=====
18                ValidationTextBox = dijit.form.ValidationTextBox;
19                _HasDropDown = dijit._HasDropDown;
20        =====*/
21return declare( "dojox.form.FilePickerTextBox", [ValidationTextBox, _HasDropDown],
22        {
23                // summary:
24                //              A validating text box tied to a file picker popup
25
26                baseClass: "dojoxFilePickerTextBox",
27
28                templateString: template,
29
30                // searchDelay: Integer
31                //              Delay in milliseconds between when user types something and we start
32                //              searching based on that value
33                searchDelay: 500,
34
35                // valueItem: item
36                //              The item, in our store, of the directory relating to our value
37                valueItem: null,
38
39                // numPanes: number
40                //      The number of panes to display in our box (if we don't have any
41                //      minPaneWidth specified by our constraints)
42                numPanes: 2.25,
43
44                postMixInProperties: function(){
45                        this.inherited(arguments);
46                        this.dropDown = new FilePicker(this.constraints);
47                },
48
49                postCreate: function(){
50                        this.inherited(arguments);
51                        // Make our connections we want
52                        this.connect(this.dropDown, "onChange", this._onWidgetChange);
53                        this.connect(this.focusNode, "onblur", "_focusBlur");
54                        this.connect(this.focusNode, "onfocus", "_focusFocus");
55                        this.connect(this.focusNode, "ondblclick", function(){
56                                _TextBoxMixin.selectInputText(this.focusNode);
57                        });
58                },
59
60                _setValueAttr: function(/*string*/value, priorityChange, fromWidget){
61                        // summary: sets the value of this widget
62                        if(!this._searchInProgress){
63                                this.inherited(arguments);
64                                value = value || "";
65                                var tVal = this.dropDown.get("pathValue") || "";
66                                if(value !== tVal){
67                                        this._skip = true;
68                                        var fx = lang.hitch(this, "_setBlurValue");
69                                        this.dropDown._setPathValueAttr(value, !fromWidget,
70                                                                                        this._settingBlurValue ? fx : null);
71                                }
72                        }
73                },
74
75                _onWidgetChange: function(/*item*/item){
76                        // summary: called when the path gets changed in the dropdown
77                        if(!item && this.focusNode.value){
78                                this._hasValidPath = false;
79                                this.focusNode.value = "";
80                        }else{
81                                this.valueItem = item;
82                                var value = this.dropDown._getPathValueAttr(item);
83                                if(value){
84                                        this._hasValidPath = true;
85                                }
86                                if(!this._skip){
87                                        this._setValueAttr(value, undefined, true);
88                                }
89                                delete this._skip;
90                        }
91                        this.validate();
92                },
93
94                startup: function(){
95                        if(!this.dropDown._started){
96                                this.dropDown.startup();
97                        }
98                        this.inherited(arguments);
99                },
100
101                openDropDown: function(){
102                        // set width to 0 so that it will resize automatically
103                        this.dropDown.domNode.style.width="0px";
104                        if(!("minPaneWidth" in (this.constraints||{}))){
105                                this.dropDown.set("minPaneWidth", (this.domNode.offsetWidth / this.numPanes));
106                        }
107                        this.inherited(arguments);
108                },
109
110                toggleDropDown: function(){
111                        this.inherited(arguments);
112                        // Make sure our display is up-to-date with our value
113                        if(this._opened){
114                                this.dropDown.set("pathValue", this.get("value"));
115                        }
116                },
117
118                _focusBlur: function(/*Event*/ e){
119                        // summary: called when the focus node gets blurred
120                        if(e.explicitOriginalTarget == this.focusNode && !this._allowBlur){
121                                window.setTimeout(lang.hitch(this, function(){
122                                        if(!this._allowBlur){
123                                                this.focus();
124                                        }
125                                }), 1);
126                        }else if(this._menuFocus){
127                                this.dropDown._updateClass(this._menuFocus, "Item", {"Hover": false});
128                                delete this._menuFocus;
129                        }
130                },
131
132                _focusFocus: function(/*Event*/ e){
133                        // summary: called when the focus node gets focus
134                        if(this._menuFocus){
135                                this.dropDown._updateClass(this._menuFocus, "Item", {"Hover": false});
136                        }
137                        delete this._menuFocus;
138                        var focusNode = focus.curNode;
139                        if(focusNode){
140                                focusNode = registry.byNode(focusNode);
141                                if(focusNode){
142                                        this._menuFocus = focusNode.domNode;
143                                }
144                        }
145                        if(this._menuFocus){
146                                this.dropDown._updateClass(this._menuFocus, "Item", {"Hover": true});
147                        }
148                        delete this._allowBlur;
149                },
150
151                _onBlur: function(){
152                        // summary: called when focus is shifted away from this widget
153                        this._allowBlur = true;
154                        delete this.dropDown._savedFocus;
155                        this.inherited(arguments);
156                },
157
158                _setBlurValue: function(){
159                        // summary: sets the value of the widget once focus has left
160                        if(this.dropDown && !this._settingBlurValue){
161                                this._settingBlurValue = true;
162                                this.set("value", this.focusNode.value);
163                        }else{
164                                delete this._settingBlurValue;
165                                this.inherited(arguments);
166                        }
167                },
168
169                parse: function(/* String */ value, /* Object */ constraints){
170                        //      summary:
171                        //              Function to convert a formatted string to a value - we use
172                        //              it to verify that it *really* is a valid value
173                        if(this._hasValidPath || this._hasSelection){
174                                return value;
175                        }
176                        var dd = this.dropDown, topDir = dd.topDir, sep = dd.pathSeparator;
177                        var ddVal = dd.get("pathValue");
178                        var norm = function(v){
179                                if(topDir.length && v.indexOf(topDir) === 0){
180                                        v = v.substring(topDir.length);
181                                }
182                                if(sep && v[v.length - 1] == sep){
183                                        v = v.substring(0, v.length - 1);
184                                }
185                                return v;
186                        };
187                        ddVal = norm(ddVal);
188                        var val = norm(value);
189                        if(val == ddVal){
190                                return value;
191                        }
192                        return undefined;
193                },
194
195                _startSearchFromInput: function(){
196                        // summary: kicks off a search based off the current text value of the widget
197                        var dd = this.dropDown, fn = this.focusNode;
198                        var val = fn.value, oVal = val, topDir = dd.topDir;
199                        if(this._hasSelection){
200                                _TextBoxMixin.selectInputText(fn, oVal.length);
201                        }
202                        this._hasSelection = false;
203                        if(topDir.length && val.indexOf(topDir) === 0){
204                                val = val.substring(topDir.length);
205                        }
206                        var dirs = val.split(dd.pathSeparator);
207                        var setFromChain = lang.hitch(this, function(idx){
208                                var dir = dirs[idx];
209                                var child = dd.getChildren()[idx];
210                                var conn;
211                                this._searchInProgress = true;
212                                var _cleanup = lang.hitch(this, function(){
213                                        delete this._searchInProgress;
214                                });
215                                if((dir || child) && !this._opened){
216                                        this.toggleDropDown();
217                                }
218                                if(dir && child){
219                                        var fx = lang.hitch(this, function(){
220                                                if(conn){
221                                                        this.disconnect(conn);
222                                                }
223                                                delete conn;
224                                                var children = child._menu.getChildren();
225                                                var exact = array.filter(children, function(i){
226                                                        return i.label == dir;
227                                                })[0];
228                                                var first = array.filter(children, function(i){
229                                                        return (i.label.indexOf(dir) === 0);
230                                                })[0];
231                                                if(exact &&
232                                                        ((dirs.length > idx + 1 && exact.children) ||
233                                                        (!exact.children))){
234                                                        idx++;
235                                                        child._menu.onItemClick(exact, {type: "internal",
236                                                                                                        stopPropagation: function(){},
237                                                                                                        preventDefault: function(){}});
238                                                        if(dirs[idx]){
239                                                                setFromChain(idx);
240                                                        }else{
241                                                                _cleanup();
242                                                        }
243                                                }else{
244                                                        child._setSelected(null);
245                                                        if(first && dirs.length === idx + 1){
246                                                                dd._setInProgress = true;
247                                                                dd._removeAfter(child);
248                                                                delete dd._setInProgress;
249                                                                var targetString = first.label;
250                                                                if(first.children){
251                                                                        targetString += dd.pathSeparator;
252                                                                }
253                                                                targetString = targetString.substring(dir.length);
254                                                                window.setTimeout(function(){
255                                                                        windowUtils.scrollIntoView(first.domNode);
256                                                                }, 1);
257                                                                fn.value = oVal + targetString;
258                                                                _TextBoxMixin.selectInputText(fn, oVal.length);
259                                                                this._hasSelection = true;
260                                                                try{first.focusNode.focus();}catch(e){}
261                                                        }else{
262                                                                if(this._menuFocus){
263                                                                        this.dropDown._updateClass(this._menuFocus, "Item", {"Hover": false, "Focus": false});
264                                                                }
265                                                                delete this._menuFocus;
266                                                        }
267                                                        _cleanup();
268                                                }
269                                        });
270                                        if(!child.isLoaded){
271                                                conn = this.connect(child, "onLoad", fx);
272                                        }else{
273                                                fx();
274                                        }
275                                }else{
276                                        if(child){
277                                                child._setSelected(null);
278                                                dd._setInProgress = true;
279                                                dd._removeAfter(child);
280                                                delete dd._setInProgress;
281                                        }
282                                        _cleanup();
283                                }
284                        });
285                        setFromChain(0);
286                },
287
288                _onKey: function(/*Event*/ e){
289                        // summary: callback when the user presses a key on menu popup node
290                        if(this.disabled || this.readOnly){ return; }
291                        var c = e.charOrCode;
292                        if(c==keys.DOWN_ARROW){
293                                this._allowBlur = true;
294                        }
295                        if(c==keys.ENTER && this._opened){
296                                this.dropDown.onExecute();
297                                _TextBoxMixin.selectInputText(this.focusNode, this.focusNode.value.length);
298                                this._hasSelection = false;
299                                event.stop(e);
300                                return;
301                        }
302                        if((c==keys.RIGHT_ARROW || c==keys.LEFT_ARROW || c==keys.TAB) && this._hasSelection){
303                                this._startSearchFromInput();
304                                event.stop(e);
305                                return;
306                        }
307                        this.inherited(arguments);
308                        var doSearch = false;
309                        if((c==keys.BACKSPACE || c==keys.DELETE) && this._hasSelection){
310                                this._hasSelection = false;
311                        }else if(c==keys.BACKSPACE || c==keys.DELETE || c==" "){
312                                doSearch = true;
313                        }else{
314                                doSearch = e.keyChar !== "";
315                        }
316                        if(this._searchTimer){
317                                window.clearTimeout(this._searchTimer);
318                        }
319                        delete this._searchTimer;
320                        if(doSearch){
321                                this._hasValidPath = false;
322                                this._hasSelection = false;
323                                this._searchTimer = window.setTimeout(lang.hitch(this, "_startSearchFromInput"), this.searchDelay + 1);
324                        }
325                }
326        }
327);
328});
Note: See TracBrowser for help on using the repository browser.