|
1 /* |
|
2 YUI 3.10.3 (build 2fb5187) |
|
3 Copyright 2013 Yahoo! Inc. All rights reserved. |
|
4 Licensed under the BSD License. |
|
5 http://yuilibrary.com/license/ |
|
6 */ |
|
7 |
|
8 YUI.add('features', function (Y, NAME) { |
|
9 |
|
10 var feature_tests = {}; |
|
11 |
|
12 /** |
|
13 Contains the core of YUI's feature test architecture. |
|
14 @module features |
|
15 */ |
|
16 |
|
17 /** |
|
18 * Feature detection |
|
19 * @class Features |
|
20 * @static |
|
21 */ |
|
22 |
|
23 Y.mix(Y.namespace('Features'), { |
|
24 |
|
25 /** |
|
26 * Object hash of all registered feature tests |
|
27 * @property tests |
|
28 * @type Object |
|
29 */ |
|
30 tests: feature_tests, |
|
31 |
|
32 /** |
|
33 * Add a test to the system |
|
34 * |
|
35 * ``` |
|
36 * Y.Features.add("load", "1", {}); |
|
37 * ``` |
|
38 * |
|
39 * @method add |
|
40 * @param {String} cat The category, right now only 'load' is supported |
|
41 * @param {String} name The number sequence of the test, how it's reported in the URL or config: 1, 2, 3 |
|
42 * @param {Object} o Object containing test properties |
|
43 * @param {String} o.name The name of the test |
|
44 * @param {Function} o.test The test function to execute, the only argument to the function is the `Y` instance |
|
45 * @param {String} o.trigger The module that triggers this test. |
|
46 */ |
|
47 add: function(cat, name, o) { |
|
48 feature_tests[cat] = feature_tests[cat] || {}; |
|
49 feature_tests[cat][name] = o; |
|
50 }, |
|
51 /** |
|
52 * Execute all tests of a given category and return the serialized results |
|
53 * |
|
54 * ``` |
|
55 * caps=1:1;2:1;3:0 |
|
56 * ``` |
|
57 * @method all |
|
58 * @param {String} cat The category to execute |
|
59 * @param {Array} args The arguments to pass to the test function |
|
60 * @return {String} A semi-colon separated string of tests and their success/failure: 1:1;2:1;3:0 |
|
61 */ |
|
62 all: function(cat, args) { |
|
63 var cat_o = feature_tests[cat], |
|
64 // results = {}; |
|
65 result = []; |
|
66 if (cat_o) { |
|
67 Y.Object.each(cat_o, function(v, k) { |
|
68 result.push(k + ':' + (Y.Features.test(cat, k, args) ? 1 : 0)); |
|
69 }); |
|
70 } |
|
71 |
|
72 return (result.length) ? result.join(';') : ''; |
|
73 }, |
|
74 /** |
|
75 * Run a sepecific test and return a Boolean response. |
|
76 * |
|
77 * ``` |
|
78 * Y.Features.test("load", "1"); |
|
79 * ``` |
|
80 * |
|
81 * @method test |
|
82 * @param {String} cat The category of the test to run |
|
83 * @param {String} name The name of the test to run |
|
84 * @param {Array} args The arguments to pass to the test function |
|
85 * @return {Boolean} True or false if the test passed/failed. |
|
86 */ |
|
87 test: function(cat, name, args) { |
|
88 args = args || []; |
|
89 var result, ua, test, |
|
90 cat_o = feature_tests[cat], |
|
91 feature = cat_o && cat_o[name]; |
|
92 |
|
93 if (!feature) { |
|
94 Y.log('Feature test ' + cat + ', ' + name + ' not found'); |
|
95 } else { |
|
96 |
|
97 result = feature.result; |
|
98 |
|
99 if (Y.Lang.isUndefined(result)) { |
|
100 |
|
101 ua = feature.ua; |
|
102 if (ua) { |
|
103 result = (Y.UA[ua]); |
|
104 } |
|
105 |
|
106 test = feature.test; |
|
107 if (test && ((!ua) || result)) { |
|
108 result = test.apply(Y, args); |
|
109 } |
|
110 |
|
111 feature.result = result; |
|
112 } |
|
113 } |
|
114 |
|
115 return result; |
|
116 } |
|
117 }); |
|
118 |
|
119 // Y.Features.add("load", "1", {}); |
|
120 // Y.Features.test("load", "1"); |
|
121 // caps=1:1;2:0;3:1; |
|
122 |
|
123 /* This file is auto-generated by (yogi loader --yes --mix --start ../) */ |
|
124 /*jshint maxlen:900, eqeqeq: false */ |
|
125 var add = Y.Features.add; |
|
126 // app-transitions-native |
|
127 add('load', '0', { |
|
128 "name": "app-transitions-native", |
|
129 "test": function (Y) { |
|
130 var doc = Y.config.doc, |
|
131 node = doc ? doc.documentElement : null; |
|
132 |
|
133 if (node && node.style) { |
|
134 return ('MozTransition' in node.style || 'WebkitTransition' in node.style || 'transition' in node.style); |
|
135 } |
|
136 |
|
137 return false; |
|
138 }, |
|
139 "trigger": "app-transitions" |
|
140 }); |
|
141 // autocomplete-list-keys |
|
142 add('load', '1', { |
|
143 "name": "autocomplete-list-keys", |
|
144 "test": function (Y) { |
|
145 // Only add keyboard support to autocomplete-list if this doesn't appear to |
|
146 // be an iOS or Android-based mobile device. |
|
147 // |
|
148 // There's currently no feasible way to actually detect whether a device has |
|
149 // a hardware keyboard, so this sniff will have to do. It can easily be |
|
150 // overridden by manually loading the autocomplete-list-keys module. |
|
151 // |
|
152 // Worth noting: even though iOS supports bluetooth keyboards, Mobile Safari |
|
153 // doesn't fire the keyboard events used by AutoCompleteList, so there's |
|
154 // no point loading the -keys module even when a bluetooth keyboard may be |
|
155 // available. |
|
156 return !(Y.UA.ios || Y.UA.android); |
|
157 }, |
|
158 "trigger": "autocomplete-list" |
|
159 }); |
|
160 // dd-gestures |
|
161 add('load', '2', { |
|
162 "name": "dd-gestures", |
|
163 "trigger": "dd-drag", |
|
164 "ua": "touchEnabled" |
|
165 }); |
|
166 // dom-style-ie |
|
167 add('load', '3', { |
|
168 "name": "dom-style-ie", |
|
169 "test": function (Y) { |
|
170 |
|
171 var testFeature = Y.Features.test, |
|
172 addFeature = Y.Features.add, |
|
173 WINDOW = Y.config.win, |
|
174 DOCUMENT = Y.config.doc, |
|
175 DOCUMENT_ELEMENT = 'documentElement', |
|
176 ret = false; |
|
177 |
|
178 addFeature('style', 'computedStyle', { |
|
179 test: function() { |
|
180 return WINDOW && 'getComputedStyle' in WINDOW; |
|
181 } |
|
182 }); |
|
183 |
|
184 addFeature('style', 'opacity', { |
|
185 test: function() { |
|
186 return DOCUMENT && 'opacity' in DOCUMENT[DOCUMENT_ELEMENT].style; |
|
187 } |
|
188 }); |
|
189 |
|
190 ret = (!testFeature('style', 'opacity') && |
|
191 !testFeature('style', 'computedStyle')); |
|
192 |
|
193 return ret; |
|
194 }, |
|
195 "trigger": "dom-style" |
|
196 }); |
|
197 // editor-para-ie |
|
198 add('load', '4', { |
|
199 "name": "editor-para-ie", |
|
200 "trigger": "editor-para", |
|
201 "ua": "ie", |
|
202 "when": "instead" |
|
203 }); |
|
204 // event-base-ie |
|
205 add('load', '5', { |
|
206 "name": "event-base-ie", |
|
207 "test": function(Y) { |
|
208 var imp = Y.config.doc && Y.config.doc.implementation; |
|
209 return (imp && (!imp.hasFeature('Events', '2.0'))); |
|
210 }, |
|
211 "trigger": "node-base" |
|
212 }); |
|
213 // graphics-canvas |
|
214 add('load', '6', { |
|
215 "name": "graphics-canvas", |
|
216 "test": function(Y) { |
|
217 var DOCUMENT = Y.config.doc, |
|
218 useCanvas = Y.config.defaultGraphicEngine && Y.config.defaultGraphicEngine == "canvas", |
|
219 canvas = DOCUMENT && DOCUMENT.createElement("canvas"), |
|
220 svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1")); |
|
221 return (!svg || useCanvas) && (canvas && canvas.getContext && canvas.getContext("2d")); |
|
222 }, |
|
223 "trigger": "graphics" |
|
224 }); |
|
225 // graphics-canvas-default |
|
226 add('load', '7', { |
|
227 "name": "graphics-canvas-default", |
|
228 "test": function(Y) { |
|
229 var DOCUMENT = Y.config.doc, |
|
230 useCanvas = Y.config.defaultGraphicEngine && Y.config.defaultGraphicEngine == "canvas", |
|
231 canvas = DOCUMENT && DOCUMENT.createElement("canvas"), |
|
232 svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1")); |
|
233 return (!svg || useCanvas) && (canvas && canvas.getContext && canvas.getContext("2d")); |
|
234 }, |
|
235 "trigger": "graphics" |
|
236 }); |
|
237 // graphics-svg |
|
238 add('load', '8', { |
|
239 "name": "graphics-svg", |
|
240 "test": function(Y) { |
|
241 var DOCUMENT = Y.config.doc, |
|
242 useSVG = !Y.config.defaultGraphicEngine || Y.config.defaultGraphicEngine != "canvas", |
|
243 canvas = DOCUMENT && DOCUMENT.createElement("canvas"), |
|
244 svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1")); |
|
245 |
|
246 return svg && (useSVG || !canvas); |
|
247 }, |
|
248 "trigger": "graphics" |
|
249 }); |
|
250 // graphics-svg-default |
|
251 add('load', '9', { |
|
252 "name": "graphics-svg-default", |
|
253 "test": function(Y) { |
|
254 var DOCUMENT = Y.config.doc, |
|
255 useSVG = !Y.config.defaultGraphicEngine || Y.config.defaultGraphicEngine != "canvas", |
|
256 canvas = DOCUMENT && DOCUMENT.createElement("canvas"), |
|
257 svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1")); |
|
258 |
|
259 return svg && (useSVG || !canvas); |
|
260 }, |
|
261 "trigger": "graphics" |
|
262 }); |
|
263 // graphics-vml |
|
264 add('load', '10', { |
|
265 "name": "graphics-vml", |
|
266 "test": function(Y) { |
|
267 var DOCUMENT = Y.config.doc, |
|
268 canvas = DOCUMENT && DOCUMENT.createElement("canvas"); |
|
269 return (DOCUMENT && !DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") && (!canvas || !canvas.getContext || !canvas.getContext("2d"))); |
|
270 }, |
|
271 "trigger": "graphics" |
|
272 }); |
|
273 // graphics-vml-default |
|
274 add('load', '11', { |
|
275 "name": "graphics-vml-default", |
|
276 "test": function(Y) { |
|
277 var DOCUMENT = Y.config.doc, |
|
278 canvas = DOCUMENT && DOCUMENT.createElement("canvas"); |
|
279 return (DOCUMENT && !DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") && (!canvas || !canvas.getContext || !canvas.getContext("2d"))); |
|
280 }, |
|
281 "trigger": "graphics" |
|
282 }); |
|
283 // history-hash-ie |
|
284 add('load', '12', { |
|
285 "name": "history-hash-ie", |
|
286 "test": function (Y) { |
|
287 var docMode = Y.config.doc && Y.config.doc.documentMode; |
|
288 |
|
289 return Y.UA.ie && (!('onhashchange' in Y.config.win) || |
|
290 !docMode || docMode < 8); |
|
291 }, |
|
292 "trigger": "history-hash" |
|
293 }); |
|
294 // io-nodejs |
|
295 add('load', '13', { |
|
296 "name": "io-nodejs", |
|
297 "trigger": "io-base", |
|
298 "ua": "nodejs" |
|
299 }); |
|
300 // json-parse-shim |
|
301 add('load', '14', { |
|
302 "name": "json-parse-shim", |
|
303 "test": function (Y) { |
|
304 var _JSON = Y.config.global.JSON, |
|
305 Native = Object.prototype.toString.call(_JSON) === '[object JSON]' && _JSON, |
|
306 nativeSupport = Y.config.useNativeJSONParse !== false && !!Native; |
|
307 |
|
308 function workingNative( k, v ) { |
|
309 return k === "ok" ? true : v; |
|
310 } |
|
311 |
|
312 // Double check basic functionality. This is mainly to catch early broken |
|
313 // implementations of the JSON API in Firefox 3.1 beta1 and beta2 |
|
314 if ( nativeSupport ) { |
|
315 try { |
|
316 nativeSupport = ( Native.parse( '{"ok":false}', workingNative ) ).ok; |
|
317 } |
|
318 catch ( e ) { |
|
319 nativeSupport = false; |
|
320 } |
|
321 } |
|
322 |
|
323 return !nativeSupport; |
|
324 }, |
|
325 "trigger": "json-parse" |
|
326 }); |
|
327 // json-stringify-shim |
|
328 add('load', '15', { |
|
329 "name": "json-stringify-shim", |
|
330 "test": function (Y) { |
|
331 var _JSON = Y.config.global.JSON, |
|
332 Native = Object.prototype.toString.call(_JSON) === '[object JSON]' && _JSON, |
|
333 nativeSupport = Y.config.useNativeJSONStringify !== false && !!Native; |
|
334 |
|
335 // Double check basic native functionality. This is primarily to catch broken |
|
336 // early JSON API implementations in Firefox 3.1 beta1 and beta2. |
|
337 if ( nativeSupport ) { |
|
338 try { |
|
339 nativeSupport = ( '0' === Native.stringify(0) ); |
|
340 } catch ( e ) { |
|
341 nativeSupport = false; |
|
342 } |
|
343 } |
|
344 |
|
345 |
|
346 return !nativeSupport; |
|
347 }, |
|
348 "trigger": "json-stringify" |
|
349 }); |
|
350 // scrollview-base-ie |
|
351 add('load', '16', { |
|
352 "name": "scrollview-base-ie", |
|
353 "trigger": "scrollview-base", |
|
354 "ua": "ie" |
|
355 }); |
|
356 // selector-css2 |
|
357 add('load', '17', { |
|
358 "name": "selector-css2", |
|
359 "test": function (Y) { |
|
360 var DOCUMENT = Y.config.doc, |
|
361 ret = DOCUMENT && !('querySelectorAll' in DOCUMENT); |
|
362 |
|
363 return ret; |
|
364 }, |
|
365 "trigger": "selector" |
|
366 }); |
|
367 // transition-timer |
|
368 add('load', '18', { |
|
369 "name": "transition-timer", |
|
370 "test": function (Y) { |
|
371 var DOCUMENT = Y.config.doc, |
|
372 node = (DOCUMENT) ? DOCUMENT.documentElement: null, |
|
373 ret = true; |
|
374 |
|
375 if (node && node.style) { |
|
376 ret = !('MozTransition' in node.style || 'WebkitTransition' in node.style || 'transition' in node.style); |
|
377 } |
|
378 |
|
379 return ret; |
|
380 }, |
|
381 "trigger": "transition" |
|
382 }); |
|
383 // widget-base-ie |
|
384 add('load', '19', { |
|
385 "name": "widget-base-ie", |
|
386 "trigger": "widget-base", |
|
387 "ua": "ie" |
|
388 }); |
|
389 // yql-jsonp |
|
390 add('load', '20', { |
|
391 "name": "yql-jsonp", |
|
392 "test": function (Y) { |
|
393 /* Only load the JSONP module when not in nodejs or winjs |
|
394 TODO Make the winjs module a CORS module |
|
395 */ |
|
396 return (!Y.UA.nodejs && !Y.UA.winjs); |
|
397 }, |
|
398 "trigger": "yql", |
|
399 "when": "after" |
|
400 }); |
|
401 // yql-nodejs |
|
402 add('load', '21', { |
|
403 "name": "yql-nodejs", |
|
404 "trigger": "yql", |
|
405 "ua": "nodejs", |
|
406 "when": "after" |
|
407 }); |
|
408 // yql-winjs |
|
409 add('load', '22', { |
|
410 "name": "yql-winjs", |
|
411 "trigger": "yql", |
|
412 "ua": "winjs", |
|
413 "when": "after" |
|
414 }); |
|
415 |
|
416 }, '3.10.3', {"requires": ["yui-base"]}); |