source: Dev/trunk/src/client/dojo/has.js @ 532

Last change on this file since 532 was 483, checked in by hendrikvanantwerpen, 11 years ago

Added Dojo 1.9.3 release.

File size: 6.8 KB
Line 
1define(["require", "module"], function(require, module){
2        // module:
3        //              dojo/has
4        // summary:
5        //              Defines the has.js API and several feature tests used by dojo.
6        // description:
7        //              This module defines the has API as described by the project has.js with the following additional features:
8        //
9        //              - the has test cache is exposed at has.cache.
10        //              - the method has.add includes a forth parameter that controls whether or not existing tests are replaced
11        //              - the loader's has cache may be optionally copied into this module's has cahce.
12        //
13        //              This module adopted from https://github.com/phiggins42/has.js; thanks has.js team!
14
15        // try to pull the has implementation from the loader; both the dojo loader and bdLoad provide one
16        // if using a foreign loader, then the has cache may be initialized via the config object for this module
17        // WARNING: if a foreign loader defines require.has to be something other than the has.js API, then this implementation fail
18        var has = require.has || function(){};
19        if(!has("dojo-has-api")){
20                var
21                        isBrowser =
22                                // the most fundamental decision: are we in the browser?
23                                typeof window != "undefined" &&
24                                typeof location != "undefined" &&
25                                typeof document != "undefined" &&
26                                window.location == location && window.document == document,
27
28                        // has API variables
29                        global = this,
30                        doc = isBrowser && document,
31                        element = doc && doc.createElement("DiV"),
32                        cache = (module.config && module.config()) || {};
33
34                has = function(name){
35                        // summary:
36                        //              Return the current value of the named feature.
37                        //
38                        // name: String|Integer
39                        //              The name (if a string) or identifier (if an integer) of the feature to test.
40                        //
41                        // description:
42                        //              Returns the value of the feature named by name. The feature must have been
43                        //              previously added to the cache by has.add.
44
45                        return typeof cache[name] == "function" ? (cache[name] = cache[name](global, doc, element)) : cache[name]; // Boolean
46                };
47
48                has.cache = cache;
49
50                has.add = function(name, test, now, force){
51                        // summary:
52                        //              Register a new feature test for some named feature.
53                        // name: String|Integer
54                        //              The name (if a string) or identifier (if an integer) of the feature to test.
55                        // test: Function
56                        //               A test function to register. If a function, queued for testing until actually
57                        //               needed. The test function should return a boolean indicating
58                        //              the presence of a feature or bug.
59                        // now: Boolean?
60                        //               Optional. Omit if `test` is not a function. Provides a way to immediately
61                        //               run the test and cache the result.
62                        // force: Boolean?
63                        //              Optional. If the test already exists and force is truthy, then the existing
64                        //              test will be replaced; otherwise, add does not replace an existing test (that
65                        //              is, by default, the first test advice wins).
66                        // example:
67                        //              A redundant test, testFn with immediate execution:
68                        //      |       has.add("javascript", function(){ return true; }, true);
69                        //
70                        // example:
71                        //              Again with the redundantness. You can do this in your tests, but we should
72                        //              not be doing this in any internal has.js tests
73                        //      |       has.add("javascript", true);
74                        //
75                        // example:
76                        //              Three things are passed to the testFunction. `global`, `document`, and a generic element
77                        //              from which to work your test should the need arise.
78                        //      |       has.add("bug-byid", function(g, d, el){
79                        //      |               // g    == global, typically window, yadda yadda
80                        //      |               // d    == document object
81                        //      |               // el == the generic element. a `has` element.
82                        //      |               return false; // fake test, byid-when-form-has-name-matching-an-id is slightly longer
83                        //      |       });
84
85                        (typeof cache[name]=="undefined" || force) && (cache[name]= test);
86                        return now && has(name);
87                };
88
89                // since we're operating under a loader that doesn't provide a has API, we must explicitly initialize
90                // has as it would have otherwise been initialized by the dojo loader; use has.add to the builder
91                // can optimize these away iff desired
92                has.add("host-browser", isBrowser);
93                has.add("host-node", (typeof process == "object" && process.versions && process.versions.node && process.versions.v8));
94                has.add("host-rhino", (typeof load == "function" && (typeof Packages == "function" || typeof Packages == "object")));
95                has.add("dom", isBrowser);
96                has.add("dojo-dom-ready-api", 1);
97                has.add("dojo-sniff", 1);
98        }
99
100        if(has("host-browser")){
101                // Common application level tests
102                has.add("dom-addeventlistener", !!document.addEventListener);
103                has.add("touch", "ontouchstart" in document || window.navigator.msMaxTouchPoints > 0);
104                // I don't know if any of these tests are really correct, just a rough guess
105                has.add("device-width", screen.availWidth || innerWidth);
106
107                // Tests for DOMNode.attributes[] behavior:
108                //       - dom-attributes-explicit - attributes[] only lists explicitly user specified attributes
109                //       - dom-attributes-specified-flag (IE8) - need to check attr.specified flag to skip attributes user didn't specify
110                //       - Otherwise, in IE6-7. attributes[] will list hundreds of values, so need to do outerHTML to get attrs instead.
111                var form = document.createElement("form");
112                has.add("dom-attributes-explicit", form.attributes.length == 0); // W3C
113                has.add("dom-attributes-specified-flag", form.attributes.length > 0 && form.attributes.length < 40);    // IE8
114        }
115
116        has.clearElement = function(element){
117                // summary:
118                //       Deletes the contents of the element passed to test functions.
119                element.innerHTML= "";
120                return element;
121        };
122
123        has.normalize = function(id, toAbsMid){
124                // summary:
125                //       Resolves id into a module id based on possibly-nested tenary expression that branches on has feature test value(s).
126                //
127                // toAbsMid: Function
128                //       Resolves a relative module id into an absolute module id
129                var
130                        tokens = id.match(/[\?:]|[^:\?]*/g), i = 0,
131                        get = function(skip){
132                                var term = tokens[i++];
133                                if(term == ":"){
134                                        // empty string module name, resolves to 0
135                                        return 0;
136                                }else{
137                                        // postfixed with a ? means it is a feature to branch on, the term is the name of the feature
138                                        if(tokens[i++] == "?"){
139                                                if(!skip && has(term)){
140                                                        // matched the feature, get the first value from the options
141                                                        return get();
142                                                }else{
143                                                        // did not match, get the second value, passing over the first
144                                                        get(true);
145                                                        return get(skip);
146                                                }
147                                        }
148                                        // a module
149                                        return term || 0;
150                                }
151                        };
152                id = get();
153                return id && toAbsMid(id);
154        };
155
156        has.load = function(id, parentRequire, loaded){
157                // summary:
158                //              Conditional loading of AMD modules based on a has feature test value.
159                // id: String
160                //              Gives the resolved module id to load.
161                // parentRequire: Function
162                //              The loader require function with respect to the module that contained the plugin resource in it's
163                //              dependency list.
164                // loaded: Function
165                //       Callback to loader that consumes result of plugin demand.
166
167                if(id){
168                        parentRequire([id], loaded);
169                }else{
170                        loaded();
171                }
172        };
173
174        return has;
175});
Note: See TracBrowser for help on using the repository browser.