2
2
Copyright (c) 2010, Yahoo! Inc. All rights reserved.
3
3
Code licensed under the BSD License:
4
4
http://developer.yahoo.com/yui/license.html
9
9
* The YUI module contains the components required for building the YUI seed file.
34
36
/*global YUI_config*/
35
37
var YUI = function() {
37
var Y = this, a = arguments, i, l = a.length,
38
globalConfig = (typeof YUI_config !== 'undefined') && YUI_config;
40
// Allow instantiation without the new operator
42
gconf = (typeof YUI_config !== 'undefined') && YUI_config;
41
44
if (!(Y instanceof YUI)) {
48
47
// set up the core environment
51
Y._config(globalConfig);
56
52
// bind the specified additional modules for this instance
60
Y.applyConfig(args[i]);
66
72
BASE = 'http://yui.yahooapis.com/',
67
73
DOC_LABEL = 'yui3-js-enabled',
68
74
NOOP = function() {},
101
107
remove(window, 'load', handleLoad);
110
getLoader = function(Y, o) {
111
var loader = Y.Env._loader;
113
loader.ignoreRegistered = false;
115
// loader.attaching = null;
117
loader.required = [];
118
loader.loadType = null;
119
// loader._inspectPage();
121
loader = new Y.Loader(Y.config);
122
Y.Env._loader = loader;
128
clobber = function(r, s) {
130
if (s.hasOwnProperty(i)) {
105
136
// Stamp the documentElement (HTML) with a class of "yui-loaded" to
106
137
// enable styles that need to key off of JS being enabled.
115
146
if (VERSION.indexOf('@') > -1) {
116
VERSION = '3.0.0'; // dev time hack for cdn test
147
VERSION = '3.2.0pr1'; // dev time hack for cdn test
120
_config: function(o) {
152
* Applies a new configuration object to the YUI instance config.
153
* This will merge new group/module definitions, and will also
154
* update the loader cache if necessary. Updating Y.config directly
155
* will not update the cache.
156
* @method applyConfig
157
* @param the configuration object
160
applyConfig: function(o) {
125
167
config = this.config,
126
168
mods = config.modules,
127
groups = config.groups;
169
groups = config.groups,
171
loader = this.Env._loader;
128
173
for (name in o) {
130
if (mods && name == 'modules') {
131
for (detail in attr) {
132
mods[detail] = attr[detail];
134
} else if (groups && name == 'groups') {
135
for (detail in attr) {
136
groups[detail] = attr[detail];
138
} else if (name == 'win') {
139
config[name] = attr.contentWindow || attr;
140
config.doc = config[name].document;
174
if (o.hasOwnProperty(name)) {
176
if (mods && name == 'modules') {
178
} else if (groups && name == 'groups') {
179
clobber(groups, attr);
180
} else if (rls && name == 'rls') {
182
} else if (name == 'win') {
183
config[name] = attr.contentWindow || attr;
184
config.doc = config[name].document;
185
} else if (name == '_yuid') {
198
_config: function(o) {
172
getBase: function(srcPattern, comboPattern) {
229
getBase: G_ENV && G_ENV.getBase || function(srcPattern, comboPattern) {
173
230
var b, nodes, i, src, match;
174
231
// get from querystring
175
232
nodes = (doc && doc.getElementsByTagName('script')) || [];
176
233
for (i=0; i<nodes.length; i=i+1) {
177
234
src = nodes[i].src;
179
//src = "http://yui.yahooapis.com/combo?2.8.0r4/b
180
//uild/yuiloader-dom-event/yuiloader-dom-event.js
181
//&3.0.0/build/yui/yui-min.js"; // debug url
182
//Y.log('src) ' + src);
183
237
match = src.match(srcPattern);
184
238
b = match && match[1];
186
240
// this is to set up the path to the loader. The file
187
241
// filter for loader should match the yui include.
188
242
filter = match[2];
245
match = filter.indexOf('js');
248
filter = filter.substr(0, match);
189
252
// extract correct path for mixed combo urls
190
253
// http://yuilibrary.com/projects/yui3/ticket/2528423
191
254
match = src.match(comboPattern);
211
274
Env._yidx = ++G_ENV._yidx;
212
275
Env._guidp = ('yui_' + VERSION + '_' +
213
276
Env._yidx + '_' + time).replace(/\./g, '_');
277
} else if (typeof _YUI != 'undefined') {
280
Env._yidx += G_ENV._yidx;
281
Env._uidx += G_ENV._uidx;
283
for (prop in G_ENV) {
284
if (!(prop in Env)) {
285
Env[prop] = G_ENV[prop];
216
290
Y.id = Y.stamp(Y);
234
Y.config.base = YUI.config.base ||
312
config.base = YUI.config.base ||
235
313
Y.Env.getBase(/^(.*)yui\/yui([\.\-].*)js(\?.*)?$/,
236
314
/^(.*\?)(.*\&)(.*)yui\/yui[\.\-].*js(\?.*)?$/);
238
Y.config.loaderPath = YUI.config.loaderPath ||
316
config.loaderPath = YUI.config.loaderPath ||
239
317
'loader/loader' + (filter || '-min.') + 'js';
244
322
* Finishes the instance setup. Attaches whatever modules were defined
245
323
* when the yui modules was registered.
249
327
_setup: function(o) {
253
330
mods = YUI.Env.mods,
254
extras = Y.config.core || ['get', 'intl-base', 'loader', 'yui-log', 'yui-later', 'yui-throttle'];
331
extras = Y.config.core || [ 'get',
257
339
for (i=0; i<extras.length; i++) {
258
340
if (mods[extras[i]]) {
277
359
* @return {object} the return value from the applied method or null
279
361
applyTo: function(id, method, args) {
281
362
if (!(method in APPLY_TO_AUTH)) {
282
363
this.log(method + ': applyTo not allowed', 'warn', 'yui');
329
410
add: function(name, fn, version, details) {
330
411
details = details || {};
332
YUI.Env.mods[name] = {
422
env.mods[name] = mod;
423
env.versions[version] = env.versions[version] || {};
424
env.versions[version][name] = mod;
426
for (i in instances) {
427
if (instances.hasOwnProperty(i)) {
428
loader = instances[i].Env._loader;
430
if (!loader.moduleInfo[name]) {
431
loader.addModule(details, name);
348
446
_attach: function(r, fromLoader) {
349
var i, name, mod, details, req, use,
447
var i, name, mod, details, req, use,
350
448
mods = YUI.Env.mods,
351
done = this.Env._attached,
450
done = Y.Env._attached,
354
453
for (i=0; i<len; i++) {
362
461
use = details.use;
364
463
if (req && req.length) {
365
this._attach(this.Array(req));
464
if (!Y._attach(req)) {
368
// this.log('attaching ' + name, 'info', 'yui');
469
// Y.log('attaching ' + name, 'info', 'yui');
475
Y.error('Attach error: ' + name, e, name);
374
480
if (use && use.length) {
375
this._attach(this.Array(use));
481
if (!Y._attach(use)) {
422
532
if (!this.Array) {
423
533
this._attach(['yui-base']);
534
// this._attach( this.config.core || ['yui-base', 'get', 'intl-base', 'loader', 'yui-log', 'yui-later', 'yui-throttle']);
426
537
var len, loader, handleBoot,
438
549
boot = config.bootstrap,
441
554
fetchCSS = config.fetchCSS,
442
process = function(name) {
444
// add this module to full list of things to attach
447
// only attach a module once
555
process = function(names, skip) {
452
var m = mods[name], req, use;
456
req = m.details.requires;
459
// CSS files don't register themselves, see if it has been loaded
460
if (!G_ENV._loaded[VERSION][name]) {
561
YArray.each(names, function(name) {
563
// add this module to full list of things to attach
568
// only attach a module once
573
var m = mods[name], req, use;
577
req = m.details.requires;
463
used[name] = true; // probably css
467
if (req) { // make sure requirements are attached
468
YArray.each(YArray(req), process);
471
if (use) { // make sure we grab the submodule dependencies too
472
YArray.each(YArray(use), process);
580
// CSS files don't register themselves, see if it has been loaded
581
if (!G_ENV._loaded[VERSION][name]) {
584
used[name] = true; // probably css
588
if (req && req.length) { // make sure requirements are attached
592
if (use && use.length) { // make sure we grab the submodule dependencies too
598
notify = function(response) {
601
callback(Y, response);
603
Y.error('use callback error', e, args);
478
608
handleLoader = function(fromLoader) {
481
611
msg: 'not dynamic'
483
newData, redo, origMissing,
613
newData, redo, origMissing,
484
615
data = response.data;
486
617
Y._loading = false;
502
634
if (redo && data) {
503
// Y.log('redo: ' + r);
504
// Y.log('redo: ' + missing);
505
// Y.log('redo: ' + args);
506
newData = data.concat();
635
// Y.log('redo r: ' + r);
636
// Y.log('redo data: ' + data);
637
// Y.log('redo missing: ' + missing);
638
Y.log('redo args: ' + args);
640
// newData = data.concat();
641
// newData = args.concat();
642
newData = args.concat();
644
// newData = missing.concat();
507
646
newData.push(function() {
508
647
Y.log('Nested USE callback: ' + data, 'info', 'yui');
511
callback(Y, response);
648
if (Y._attach(data)) {
514
652
Y._loading = false;
515
653
Y.use.apply(Y, newData);
656
ret = Y._attach(data);
521
callback(Y, response);
546
684
// YUI().use('*'); // bind everything available
547
685
if (firstArg === "*") {
548
687
args = Y.Object.keys(mods);
690
// Y.log('before loader requirements: ' + args, 'info', 'yui');
551
692
// use loader to expand dependencies and sort the
552
693
// requirements if it is available.
554
loader = new Y.Loader(config);
694
if (boot && !star && Y.Loader && args.length) {
696
// Y.log('checking dependences with loader', 'info', 'yui');
698
loader = getLoader(Y);
555
699
loader.require(args);
556
700
loader.ignoreRegistered = true;
557
701
// loader.allowRollup = false;
558
702
loader.calculate(null, (fetchCSS) ? null : 'js');
559
703
args = loader.sorted;
705
// YUI.Env.loaders[Y.config._sig] = loader;
708
// Y.log('after loader requirements: ' + args, 'info', 'yui');
562
710
// process each requirement and any additional requirements
563
711
// the module metadata specifies
564
YArray.each(args, process);
566
Y.log('Module requirements: ' + args, 'info', 'yui');
714
// Y.log('args: ' + args , 'info', 'yui');
715
// Y.log('requires: ' + r, 'info', 'yui');
567
716
len = missing.length;
577
726
// Y.log('Using loader to fetch missing dependencies: ' + missing, 'info', 'yui');
578
727
Y.log('Using Loader', 'info', 'yui');
579
728
Y._loading = true;
580
loader = new Y.Loader(config);
729
// loader = new Y.Loader(config);
730
loader = getLoader(Y);
581
731
loader.onEnd = handleLoader;
582
732
loader.context = Y;
583
loader.attaching = args;
733
// loader.attaching = args;
584
734
loader.data = args;
585
735
loader.require((fetchCSS) ? missing : args);
586
736
loader.insert(null, (fetchCSS) ? null : 'js');
737
} else if (len && Y.config.use_rls) {
739
// server side loader service
740
Y.Get.script(Y._rls(args), {
587
747
} else if (boot && len && Y.Get && !Env.bootstrapped) {
589
749
Y._loading = true;
672
835
* @return {YUI} this YUI instance
674
837
error: function(msg, e) {
675
if (this.config.throwFail) {
841
if (Y.config.errorFn) {
842
ret = Y.config.errorFn.apply(Y, arguments);
845
if (Y.config.throwFail && !ret) {
676
846
throw (e || new Error(msg));
678
this.message(msg, "error"); // don't scrub this one
848
Y.message(msg, "error"); // don't scrub this one
703
873
* @return {string} The object's guid or null
705
875
stamp: function(o, readOnly) {
709
var uid = (typeof o === 'string') ? o : o._yuid;
881
// IE generates its own unique ID for dom nodes
882
// The uniqueID property of a document node returns a new ID
883
if (o.uniqueID && o.nodeType && o.nodeType !== 9) {
886
uid = (typeof o === 'string') ? o : o._yuid;
711
890
uid = this.guid();
724
// Give the YUI global the same properties as an instance.
725
// This makes it so that the YUI global can be used like the YAHOO
726
// global was used prior to 3.x. More importantly, the YUI global
727
// provides global metadata, so env needs to be configured.
903
YUI.prototype = proto;
732
905
// inheritance utilities are not available yet
906
for (prop in proto) {
907
if (proto.hasOwnProperty(prop)) {
908
YUI[prop] = proto[prop];
737
912
// set up the environment
763
938
* The config object contains all of the configuration options for
764
939
* the YUI instance. This object is supplied by the implementer
765
940
* when instantiating a YUI instance. Some properties have default
766
* values if they are not supplied by the implementer.
941
* values if they are not supplied by the implementer. This should
942
* not be updated directly because some values are cached. Use
943
* applyConfig() to update the config object on a YUI instance that
944
* has already been configured.
798
* A hash of log sources that should be not be logged. If specified, all sources are logged if not on this list.
976
* A hash of log sources that should be not be logged. If specified,
977
* all sources are logged if not on this list.
800
979
* @property logExclude
815
* If throwFail is set, Y.fail will generate or re-throw a JS Error. Otherwise the failure is logged.
994
* If throwFail is set, Y.error will generate or re-throw a JS Error.
995
* Otherwise the failure is logged.
817
997
* @property throwFail
1065
1238
* name, and the value is an object literal specifying the metdata
1066
1239
* for the module. * See Loader.addModule for the supported module
1067
1240
* metadata fields. Also @see groups, which provides a way to
1068
* configure the base and combo spec for a
1241
* configure the base and combo spec for a set of modules.
1071
1244
* mymod1: {
1177
1350
* Alternative console log function for use in environments without
1178
* a supported native console.
1351
* a supported native console. The function is executed in the
1352
* YUI instance context.
1180
1354
* @property logFn
1181
1355
* @type Function
1359
* A callback to execute when Y.error is called. It receives the
1360
* error message and an javascript error object if Y.error was
1361
* executed because a javascript error was caught. The function
1362
* is executed in the YUI instance context.
1370
* The parameter defaults for the remote loader service.
1371
* Requires the rls submodule. The properties that are
1374
* m: comma separated list of module requirements. This
1375
* must be the param name even for custom implemetations.
1376
* v: the version of YUI to load. Defaults to the version
1377
* of YUI that is being used.
1378
* gv: the version of the gallery to load (@see the gallery config)
1379
* env: comma separated list of modules already on the page.
1380
* this must be the param name even for custom implemetations.
1381
* lang: the languages supported on the page (@see the lang config)
1382
* '2in3v': the version of the 2in3 wrapper to use (@see the 2in3 config).
1383
* '2v': the version of yui2 to use in the yui 2in3 wrappers (@see the yui2 config)
1384
* filt: a filter def to apply to the urls (@see the filter config).
1385
* filts: a list of custom filters to apply per module (@see the filters config).
1386
* tests: this is a map of conditional module test function id keys with the values
1387
* of 1 if the test passes, 0 if not. This must be the name of the querystring
1388
* param in custom templates.
1396
* The base path to the remote loader service
1399
* @property rls_base
1403
* The template to use for building the querystring portion
1404
* of the remote loader service url. The default is determined
1405
* by the rls config -- each property that has a value will be
1408
* ex: m={m}&v={v}&env={env}&lang={lang}&filt={filt}&tests={tests}
1412
* @property rls_tmpl
1416
* Configure the instance to use a remote loader service instead of
1417
* the client loader.
1183
1422
YUI.add('yui-base', function(Y) {
1401
1641
return TYPES[typeof o] || TYPES[TOSTRING.call(o)] || (o ? OBJECT : NULL);
1645
* Lightweight version of @see Y.substitute... it uses the same template
1646
* structure as Y.substitute, but doesn't support recursion, auto-object
1647
* coersion, or formats
1651
L.sub = function (s, o) {
1652
return ((s.replace) ? s.replace(SUBREGEX, function (match, key) {
1653
return (!L.isUndefined(o[key])) ? o[key] : match;
1407
1660
* The YUI module contains the components required for building the YUI seed file.
1533
1786
YArray.hash = function(k, v) {
1534
1787
var o = {}, l = k.length, vl = v && v.length, i;
1535
1788
for (i=0; i<l; i=i+1) {
1537
o[k[i]] = (vl && vl > i) ? v[i] : true;
1789
o[k[i]] = (vl && vl > i) ? v[i] : true;
1851
2102
Y.cached = function(source, cache, refetch){
1852
2103
cache = cache || {};
1854
return function(arg1, arg2) {
2105
return function(arg1) {
1856
var k = (arg2) ? Array.prototype.join.call(arguments, DELIMITER) : arg1;
2107
var k = (arguments.length > 1) ?
2108
Array.prototype.join.call(arguments, DELIMITER) : arg1;
1858
2110
if (!(k in cache) || (refetch && cache[k] == refetch)) {
1859
2111
cache[k] = source.apply(source, arguments);
1898
2150
owns = function(o, k) {
1899
2151
return o && o.hasOwnProperty && o.hasOwnProperty(k);
2152
// return Object.prototype.hasOwnProperty.call(o, k);
1902
UNDEFINED = undefined,
1905
2158
* Extracts the keys, values, or size from an object
2001
2254
* Executes a function on each item. The function
2002
2255
* receives the value, the key, and the object
2003
* as paramters (in that order).
2256
* as parameters (in that order).
2006
2259
* @param o the object to iterate
2025
2278
* Executes a function on each item, but halts if the
2026
2279
* function returns true. The function
2027
2280
* receives the value, the key, and the object
2506
* Detects Apple iPad's OS version
2513
* Detects Apple iPhone's OS version
2520
* Detects Apples iPod's OS version
2527
* General truthy check for iPad, iPhone or iPod
2534
* Detects Googles Android OS version
2239
2542
* Google Caja version number or 0.
2292
2595
// Mobile browser check
2293
2596
if (/ Mobile\//.test(ua)) {
2294
2597
o.mobile = "Apple"; // iPhone or iPod Touch
2599
m = ua.match(/OS ([^\s]*)/);
2601
m = numberify(m[1].replace('_', '.'));
2603
o.ipad = (navigator.platform == 'iPad') ? m : 0;
2604
o.ipod = (navigator.platform == 'iPod') ? m : 0;
2605
o.iphone = (navigator.platform == 'iPhone') ? m : 0;
2606
o.ios = o.ipad || o.iphone || o.ipod;
2296
2608
m=ua.match(/NokiaN[^\/]*|Android \d\.\d|webOS\/\d\.\d/);
2298
2610
o.mobile = m[0]; // Nokia N-series, Android, webOS, ex: NokiaN95
2612
if (/ Android/.test(ua)) {
2613
o.mobile = 'Android';
2614
m = ua.match(/Android ([^\s]*);/);
2616
o.android = numberify(m[1]);
2302
2622
m=ua.match(/Chrome\/([^\s]*)/);