source: Dev/branches/rest-dojo-ui/client/dojox/help/_base.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: 12.5 KB
Line 
1dojo.provide("dojox.help._base");
2dojo.require("dojox.rpc.Service");
3dojo.require("dojo.io.script");
4
5dojo.experimental("dojox.help");
6console.warn("Script causes side effects (on numbers, strings, and booleans). Call dojox.help.noConflict() if you plan on executing code.");
7
8dojox.help = {
9        // summary:
10        //              Adds the help function to all variables.
11        locate: function(/*String*/ searchFor, /*String|Object|String[]|Object[]*/ searchIn, /*Number*/ maxResults){
12                // summary:
13                //              Search for dojo functionality that has something to do with the given string.
14                //  description:
15                //              Search for locally available data; variable names and any cached
16                //              documentation results for matches containing our search parameter
17                // searchFor
18                //              The string to search for.
19                // searchIn:
20                //              The namespaces to search in. Defaults to dojox.help._namespaces
21                // maxResults:
22                //              The maximum number of results.
23                maxResults = maxResults || 20;
24                var namespaces = [];
25                var roots = {};
26                var root;
27                if(searchIn){
28                        if(!dojo.isArray(searchIn)){
29                                searchIn = [searchIn];
30                        }
31                        for(var i = 0, namespace; namespace = searchIn[i]; i++){
32                                root = namespace;
33                                if(dojo.isString(namespace)){
34                                        namespace = dojo.getObject(namespace);
35                                        if(!namespace){
36                                                continue;
37                                        }
38                                }else if(dojo.isObject(namespace)){
39                                        root = namespace.__name__;
40                                }else{
41                                        continue;
42                                }
43                                // Add to a list of namespace objects (in object form)
44                                namespaces.push(namespace);
45                                if(root){
46                                        root = root.split(".")[0];
47                                        if(!roots[root] && dojo.indexOf(dojox.help._namespaces, root) == -1){
48                                                // Refresh anything that's not part of our global namespace list
49                                                dojox.help.refresh(root);
50                                        }
51                                        roots[root] = true;
52                                }
53                        }
54                }
55                if(!namespaces.length){
56                        namespaces.push({ __name__: "window" });
57                        dojo.forEach(dojox.help._namespaces, function(item){ roots[item] = true; });
58                }
59
60                var searchForLower = searchFor.toLowerCase();
61                var found = [];
62                out:
63                for(var i = 0, namespace; namespace = namespaces[i]; i++){
64                        var name = namespace.__name__ || "";
65                        var shorter = dojo.some(namespaces, function(item){
66                                // Return true if we find a namespace below
67                                // the current namespace
68                                item = item.__name__ || "";
69                                return (name.indexOf(item + ".") == 0);
70                        });
71                        if(name && !shorter){
72                                root = name.split(".")[0];
73                                var names = [];
74                                if(name == "window"){
75                                        for(root in dojox.help._names){
76                                                if(dojo.isArray(dojox.help._names[root])){
77                                                        names = names.concat(dojox.help._names[root]);
78                                                }
79                                        }
80                                }else{
81                                        names = dojox.help._names[root];
82                                }
83                                for(var j = 0, variable; variable = names[j]; j++){
84                                        if((name == "window" || variable.indexOf(name + ".") == 0) && variable.toLowerCase().indexOf(searchForLower) != -1){
85                                                if(variable.slice(-10) == ".prototype"){ continue; }
86                                                var obj = dojo.getObject(variable);
87                                                if(obj){
88                                                        found.push([variable, obj]);
89                                                        if(found.length == maxResults){
90                                                                break out;
91                                                        }
92                                                }
93                                        }
94                                }
95                        }
96                }
97
98                dojox.help._displayLocated(found);
99                if(!dojo.isMoz){
100                        return "";
101                }
102        },
103        refresh: function(/*String?*/ namespace, /*Boolean?*/ recursive){
104                // summary:
105                //              Useful if you reset some values, and want to restore their
106                //              help function
107                // namespace:
108                //              The string-representation of a namespace.
109                // recursive:
110                //              Whether to recurse through the namespace.
111                if(arguments.length < 2){
112                        recursive = true;
113                }
114                dojox.help._recurse(namespace, recursive);
115        },
116        noConflict: function(/*Object?*/ item){
117                // summary:
118                //              Use this function when you want to resolve the problems
119                //              created by including a dojox.help package.
120                // item:
121                //              If you pass an item, only that item will be cleaned
122                if(arguments.length){
123                        return dojox.help._noConflict(item);
124                }else{
125                        while(dojox.help._overrides.length){
126                                var override = dojox.help._overrides.pop();
127                                var parent = override[0];
128                                var key = override[1];
129                                var child = parent[key];
130                                parent[key] = dojox.help._noConflict(child);
131                        }
132                }
133        },
134        init: function(/*String[]*/ namespaces, /*Boolen?*/ noConflict){
135                // summary:
136                //              Should be called by one of the implementations. Runs startup code
137                // namespaces:
138                //              Any namespaces to add to the default (dojox.help._namespaces)
139                // noConflict:
140                //              Whether to start in noConflict mode
141                if(namespaces){
142                        dojox.help._namespaces.concat(namespaces);
143                }
144                dojo.addOnLoad(function(){
145                        dojo.require = (function(require){
146                                return function(){
147                                        dojox.help.noConflict();
148                                        require.apply(dojo, arguments);
149                                        if(dojox.help._timer){
150                                                clearTimeout(dojox.help._timer);
151                                        }
152                                        dojox.help._timer = setTimeout(function(){
153                                                dojo.addOnLoad(function(){
154                                                        dojox.help.refresh();
155                                                        dojox.help._timer = false;
156                                                });
157                                        }, 500);
158                                }
159                        })(dojo.require);
160
161                        dojox.help._recurse();
162                });
163        },
164        _noConflict: function(item){
165                if(item instanceof String){
166                        return item.toString();
167                }else if(item instanceof Number){
168                        return +item;
169                }else if(item instanceof Boolean){
170                        return (item == true);
171                }else if(dojo.isObject(item)){
172                        delete item.__name__;
173                        delete item.help;
174                }
175                return item;
176        },
177        _namespaces: ["dojo", "dojox", "dijit", "djConfig"],
178        _rpc: new dojox.rpc.Service(dojo.moduleUrl("dojox.rpc.SMDLibrary", "dojo-api.smd")),
179        _attributes: ["summary", "type", "returns", "parameters"],
180        _clean: function(self){
181                var obj = {};
182                for(var i = 0, attribute; attribute = dojox.help._attributes[i]; i++){
183                        var value = self["__" + attribute + "__"];
184                        if(value){
185                                obj[attribute] = value;
186                        }
187                }
188                return obj;
189        },
190        _displayLocated: function(located){
191                // summary:
192                //              Stub function to be overridden in one of the dojox.help packages
193                throw new Error("_displayLocated should be overridden in one of the dojox.help packages");
194        },
195        _displayHelp: function(loading, obj){
196                // summary:
197                //              Stub function to be overridden in one of the dojox.help packages
198                throw new Error("_displayHelp should be overridden in one of the dojox.help packages");
199        },
200        _addVersion: function(obj){
201                if(obj.name){
202                        obj.version = [dojo.version.major, dojo.version.minor, dojo.version.patch].join(".");
203                        var parts = obj.name.split(".");
204                        if(parts[0] == "dojo" || parts[0] == "dijit" || parts[0] == "dojox"){
205                                obj.project = parts[0];
206                        }
207                }
208                return obj;
209        },
210        _stripPrototype: function(original){
211                var name = original.replace(/\.prototype(\.|$)/g, ".");
212                var search = name;
213                if(name.slice(-1) == "."){
214                        search = name = name.slice(0, -1);
215                }else{
216                        name = original;
217                }
218                return [search, name];
219        },
220        _help: function(){
221                var name = this.__name__;
222                var search = dojox.help._stripPrototype(name)[0];
223                var attributes = [];
224                for(var i = 0, attribute; attribute = dojox.help._attributes[i]; i++){
225                        if(!this["__" + attribute + "__"]){
226                                attributes.push(attribute);
227                        }
228                }
229
230                dojox.help._displayHelp(true, { name: this.__name__ });
231
232                if(!attributes.length || this.__searched__){
233                        dojox.help._displayHelp(false, dojox.help._clean(this));
234                }else{
235                        this.__searched__ = true;
236                        dojox.help._rpc.get(dojox.help._addVersion({
237                                name: search,
238                                exact: true,
239                                attributes: attributes
240                        })).addCallback(this, function(data){
241                                if(this.toString === dojox.help._toString){
242                                        this.toString(data);
243                                }
244                                if(data && data.length){
245                                        data = data[0];
246                                        for(var i = 0, attribute; attribute = dojox.help._attributes[i]; i++){
247                                                if(data[attribute]){
248                                                        this["__" + attribute + "__"] = data[attribute];
249                                                }
250                                        }
251                                        dojox.help._displayHelp(false, dojox.help._clean(this));
252                                }else{
253                                        dojox.help._displayHelp(false, false);
254                                }
255                        });
256                }
257                if(!dojo.isMoz){
258                        return "";
259                }
260        },
261        _parse: function(data){
262                delete this.__searching__;
263                if(data && data.length){
264                        var parameters = data[0].parameters;
265
266                        if(parameters){
267                                var signature = ["function ", this.__name__, "("];
268                                this.__parameters__ = parameters;
269                                for(var i = 0, parameter; parameter = parameters[i]; i++){
270                                        if(i){
271                                                signature.push(", ");
272                                        }
273                                        signature.push(parameter.name);
274                                        if(parameter.types){
275                                                var types = [];
276                                                for(var j = 0, type; type = parameter.types[j]; j++){
277                                                        types.push(type.title);
278                                                }
279                                                if(types.length){
280                                                        signature.push(": ");
281                                                        signature.push(types.join("|"));
282                                                }
283                                        }
284                                        if(parameter.repeating){
285                                                signature.push("...");
286                                        }
287                                        if(parameter.optional){
288                                                signature.push("?");
289                                        }
290                                }
291                                signature.push(")");
292
293                                this.__source__ = this.__source__.replace(/function[^\(]*\([^\)]*\)/, signature.join(""));
294                        }
295
296                        if(this.__output__){
297                                delete this.__output__;
298                                console.log(this);
299                        }
300                }else{
301                        dojox.help._displayHelp(false, false);
302                }
303        },
304        _toStrings: {},
305        _toString: function(data){
306                if(!this.__source__){
307                        return this.__name__;
308                }
309
310                var first = (!this.__parameters__);
311                this.__parameters__ = [];
312
313                if(data){
314                        dojox.help._parse.call(this, data);
315                }else if(first){
316                        this.__searching__ = true;
317                        dojox.help._toStrings[dojox.help._stripPrototype(this.__name__)[0]] = this;
318                        if(dojox.help._toStringTimer){
319                                clearTimeout(dojox.help._toStringTimer);
320                        }
321                        dojox.help._toStringTimer = setTimeout(function(){ dojox.help.__toString(); }, 50);
322                }
323
324                if(!first || !this.__searching__){
325                        return this.__source__;
326                }
327
328                var message = "function Loading info for " + this.__name__ + "... (watch console for result) {}";
329
330                if(!dojo.isMoz){
331                        this.__output__ = true;
332                        return message;
333                }
334
335                return {
336                        toString: dojo.hitch(this, function(){
337                                // Detect if this was called by Firebug
338                                this.__output__ = true;
339                                return message;
340                        })
341                };
342        },
343        __toString: function(){
344                if(dojox.help._toStringTimer){
345                        clearTimeout(dojox.help._toStringTimer);
346                }
347
348                var names = [];
349                dojox.help.noConflict(dojox.help._toStrings);
350                for(var name in dojox.help._toStrings){
351                        names.push(name);
352                }
353                while(names.length){
354                        dojox.help._rpc.batch(dojox.help._addVersion({
355                                names: names.splice(-50, 50),
356                                exact: true,
357                                attributes: ["parameters"]
358                        })).addCallback(this, function(datas){
359                                for(var i = 0, data; data = datas[i]; i++){
360                                        var fn = dojox.help._toStrings[data.name];
361                                        if(fn){
362                                                dojox.help._parse.call(fn, [data]);
363                                                delete dojox.help._toStrings[data.name];
364                                        }
365                                }
366                        });
367                }
368        },
369        _overrides: [],
370        _recursions: [],
371        _names: {},
372        _recurse: function(/*String?*/ namespace, /*Boolean?*/ recursive){
373                if(arguments.length < 2){
374                        recursive = true;
375                }
376
377                var items = [];
378
379                if(namespace && dojo.isString(namespace)){
380                        dojox.help.__recurse(dojo.getObject(namespace), namespace, namespace, items, recursive);
381                }else{
382                        for(var i = 0, ns; ns = dojox.help._namespaces[i]; i++){
383                                if(window[ns]){
384                                        dojox.help._recursions.push([window[ns], ns, ns]);
385                                        window[ns].__name__ = ns;
386                                        if(!window[ns].help){
387                                                window[ns].help = dojox.help._help;
388                                        }
389                                }
390                        }
391                }
392
393                while(dojox.help._recursions.length){
394                        var recursion = dojox.help._recursions.shift();
395                        dojox.help.__recurse(recursion[0], recursion[1], recursion[2], items, recursive);
396                }
397
398                for(var i = 0, item; item = items[i]; i++){
399                        delete item.__seen__;
400                }
401        },
402        __recurse: function(namespace, root, name, items, recursive){
403                for(var key in namespace){
404                        if(key.match(/([^\w_.$]|__[\w_.$]+__)/)){
405                                continue;
406                        }
407
408                        var item = namespace[key];
409                        if(typeof item == "undefined"
410                                || item === document
411                                || item === window
412                                || item === dojox.help._toString
413                                || item === dojox.help._help
414                                || item === null
415                                || (+dojo.isIE && item.tagName)
416                                || item.__seen__
417                        ) {
418                                continue;
419                        }
420
421                        var isFunction = dojo.isFunction(item);
422                        var isObject = dojo.isObject(item) && !dojo.isArray(item) && !item.nodeType;
423
424                        var itemName = (name) ? (name + "." + key) : key;
425
426                        if(itemName == "dojo._blockAsync"){
427                                continue;
428                        }
429
430                        if(!item.__name__){
431                                var parent = null;
432                                if(dojo.isString(item)){
433                                        parent = String;
434                                }else if(typeof item == "number"){
435                                        parent = Number;
436                                }else if(typeof item == "boolean"){
437                                        parent = Boolean;
438                                }
439                                if(parent){
440                                        item = namespace[key] = new parent(item);
441                                }
442                        }
443
444                        item.__seen__ = true;
445                        item.__name__ = itemName;
446                        (dojox.help._names[root] = dojox.help._names[root] || []).push(itemName);
447                        items.push(item);
448                        if(!isFunction){
449                                dojox.help._overrides.push([namespace, key]);
450                        }
451
452                        if((isFunction || isObject) && recursive){
453                                dojox.help._recursions.push([item, root, itemName]);
454                        }
455
456                        if(isFunction){
457                                if(!item.__source__){
458                                        item.__source__ = item.toString().replace(/^function\b ?/, "function " + itemName);
459                                }
460                                if(item.toString === Function.prototype.toString){
461                                        item.toString = dojox.help._toString;
462                                }
463                        }
464
465                        if(!item.help){
466                                item.help = dojox.help._help;
467                        }
468                }
469        }
470};
Note: See TracBrowser for help on using the repository browser.