-
Notifications
You must be signed in to change notification settings - Fork 0
/
yui.js
11524 lines (10279 loc) · 331 KB
/
yui.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
YUI 3.11.0 (build d549e5c)
Copyright 2013 Yahoo! Inc. All rights reserved.
Licensed under the BSD License.
http://yuilibrary.com/license/
*/
/**
The YUI module contains the components required for building the YUI seed file.
This includes the script loading mechanism, a simple queue, and the core
utilities for the library.
@module yui
@main yui
@submodule yui-base
**/
/*jshint eqeqeq: false*/
if (typeof YUI != 'undefined') {
YUI._YUI = YUI;
}
/**
The YUI global namespace object. This is the constructor for all YUI instances.
This is a self-instantiable factory function, meaning you don't need to precede
it with the `new` operator. You can invoke it directly like this:
YUI().use('*', function (Y) {
// Y is a new YUI instance.
});
But it also works like this:
var Y = YUI();
The `YUI` constructor accepts an optional config object, like this:
YUI({
debug: true,
combine: false
}).use('node', function (Y) {
// Y.Node is ready to use.
});
See the API docs for the <a href="config.html">Config</a> class for the complete
list of supported configuration properties accepted by the YUI constuctor.
If a global `YUI` object is already defined, the existing YUI object will not be
overwritten, to ensure that defined namespaces are preserved.
Each YUI instance has full custom event support, but only if the event system is
available.
@class YUI
@uses EventTarget
@constructor
@global
@param {Object} [config]* Zero or more optional configuration objects. Config
values are stored in the `Y.config` property. See the
<a href="config.html">Config</a> docs for the list of supported properties.
**/
/*global YUI*/
/*global YUI_config*/
var YUI = function() {
var i = 0,
Y = this,
args = arguments,
l = args.length,
instanceOf = function(o, type) {
return (o && o.hasOwnProperty && (o instanceof type));
},
gconf = (typeof YUI_config !== 'undefined') && YUI_config;
if (!(instanceOf(Y, YUI))) {
Y = new YUI();
} else {
// set up the core environment
Y._init();
/**
Master configuration that might span multiple contexts in a non-
browser environment. It is applied first to all instances in all
contexts.
@example
YUI.GlobalConfig = {
filter: 'debug'
};
YUI().use('node', function (Y) {
// debug files used here
});
YUI({
filter: 'min'
}).use('node', function (Y) {
// min files used here
});
@property {Object} GlobalConfig
@global
@static
**/
if (YUI.GlobalConfig) {
Y.applyConfig(YUI.GlobalConfig);
}
/**
Page-level config applied to all YUI instances created on the
current page. This is applied after `YUI.GlobalConfig` and before
any instance-level configuration.
@example
// Single global var to include before YUI seed file
YUI_config = {
filter: 'debug'
};
YUI().use('node', function (Y) {
// debug files used here
});
YUI({
filter: 'min'
}).use('node', function (Y) {
// min files used here
});
@property {Object} YUI_config
@global
**/
if (gconf) {
Y.applyConfig(gconf);
}
// bind the specified additional modules for this instance
if (!l) {
Y._setup();
}
}
if (l) {
// Each instance can accept one or more configuration objects.
// These are applied after YUI.GlobalConfig and YUI_Config,
// overriding values set in those config files if there is a
// matching property.
for (; i < l; i++) {
Y.applyConfig(args[i]);
}
Y._setup();
}
Y.instanceOf = instanceOf;
return Y;
};
(function() {
var proto, prop,
VERSION = '3.11.0',
PERIOD = '.',
BASE = 'http://yui.yahooapis.com/',
/*
These CSS class names can't be generated by
getClassName since it is not available at the
time they are being used.
*/
DOC_LABEL = 'yui3-js-enabled',
CSS_STAMP_EL = 'yui3-css-stamp',
NOOP = function() {},
SLICE = Array.prototype.slice,
APPLY_TO_AUTH = { 'io.xdrReady': 1, // the functions applyTo
'io.xdrResponse': 1, // can call. this should
'SWF.eventHandler': 1 }, // be done at build time
hasWin = (typeof window != 'undefined'),
win = (hasWin) ? window : null,
doc = (hasWin) ? win.document : null,
docEl = doc && doc.documentElement,
docClass = docEl && docEl.className,
instances = {},
time = new Date().getTime(),
add = function(el, type, fn, capture) {
if (el && el.addEventListener) {
el.addEventListener(type, fn, capture);
} else if (el && el.attachEvent) {
el.attachEvent('on' + type, fn);
}
},
remove = function(el, type, fn, capture) {
if (el && el.removeEventListener) {
// this can throw an uncaught exception in FF
try {
el.removeEventListener(type, fn, capture);
} catch (ex) {}
} else if (el && el.detachEvent) {
el.detachEvent('on' + type, fn);
}
},
handleLoad = function() {
YUI.Env.windowLoaded = true;
YUI.Env.DOMReady = true;
if (hasWin) {
remove(window, 'load', handleLoad);
}
},
getLoader = function(Y, o) {
var loader = Y.Env._loader,
lCore = [ 'loader-base' ],
G_ENV = YUI.Env,
mods = G_ENV.mods;
if (loader) {
//loader._config(Y.config);
loader.ignoreRegistered = false;
loader.onEnd = null;
loader.data = null;
loader.required = [];
loader.loadType = null;
} else {
loader = new Y.Loader(Y.config);
Y.Env._loader = loader;
}
if (mods && mods.loader) {
lCore = [].concat(lCore, YUI.Env.loaderExtras);
}
YUI.Env.core = Y.Array.dedupe([].concat(YUI.Env.core, lCore));
return loader;
},
clobber = function(r, s) {
for (var i in s) {
if (s.hasOwnProperty(i)) {
r[i] = s[i];
}
}
},
ALREADY_DONE = { success: true };
// Stamp the documentElement (HTML) with a class of "yui-loaded" to
// enable styles that need to key off of JS being enabled.
if (docEl && docClass.indexOf(DOC_LABEL) == -1) {
if (docClass) {
docClass += ' ';
}
docClass += DOC_LABEL;
docEl.className = docClass;
}
if (VERSION.indexOf('@') > -1) {
VERSION = '3.5.0'; // dev time hack for cdn test
}
proto = {
/**
Applies a new configuration object to the config of this YUI instance. This
will merge new group/module definitions, and will also update the loader
cache if necessary. Updating `Y.config` directly will not update the cache.
@method applyConfig
@param {Object} o the configuration object.
@since 3.2.0
**/
applyConfig: function(o) {
o = o || NOOP;
var attr,
name,
// detail,
config = this.config,
mods = config.modules,
groups = config.groups,
aliases = config.aliases,
loader = this.Env._loader;
for (name in o) {
if (o.hasOwnProperty(name)) {
attr = o[name];
if (mods && name == 'modules') {
clobber(mods, attr);
} else if (aliases && name == 'aliases') {
clobber(aliases, attr);
} else if (groups && name == 'groups') {
clobber(groups, attr);
} else if (name == 'win') {
config[name] = (attr && attr.contentWindow) || attr;
config.doc = config[name] ? config[name].document : null;
} else if (name == '_yuid') {
// preserve the guid
} else {
config[name] = attr;
}
}
}
if (loader) {
loader._config(o);
}
},
/**
Old way to apply a config to this instance (calls `applyConfig` under the
hood).
@private
@method _config
@param {Object} o The config to apply
**/
_config: function(o) {
this.applyConfig(o);
},
/**
Initializes this YUI instance.
@private
@method _init
**/
_init: function() {
var filter, el,
Y = this,
G_ENV = YUI.Env,
Env = Y.Env,
prop;
/**
The version number of this YUI instance.
This value is typically updated by a script when a YUI release is built,
so it may not reflect the correct version number when YUI is run from
the development source tree.
@property {String} version
**/
Y.version = VERSION;
if (!Env) {
Y.Env = {
core: ['get', 'features', 'intl-base', 'yui-log', 'yui-later', 'loader-base', 'loader-rollup', 'loader-yui3'],
loaderExtras: ['loader-rollup', 'loader-yui3'],
mods: {}, // flat module map
versions: {}, // version module map
base: BASE,
cdn: BASE + VERSION + '/build/',
// bootstrapped: false,
_idx: 0,
_used: {},
_attached: {},
_missed: [],
_yidx: 0,
_uidx: 0,
_guidp: 'y',
_loaded: {},
// serviced: {},
// Regex in English:
// I'll start at the \b(simpleyui).
// 1. Look in the test string for "simpleyui" or "yui" or
// "yui-base" or "yui-davglass" or "yui-foobar" that comes after a word break. That is, it
// can't match "foyui" or "i_heart_simpleyui". This can be anywhere in the string.
// 2. After #1 must come a forward slash followed by the string matched in #1, so
// "yui-base/yui-base" or "simpleyui/simpleyui" or "yui-pants/yui-pants".
// 3. The second occurence of the #1 token can optionally be followed by "-debug" or "-min",
// so "yui/yui-min", "yui/yui-debug", "yui-base/yui-base-debug". NOT "yui/yui-tshirt".
// 4. This is followed by ".js", so "yui/yui.js", "simpleyui/simpleyui-min.js"
// 0. Going back to the beginning, now. If all that stuff in 1-4 comes after a "?" in the string,
// then capture the junk between the LAST "&" and the string in 1-4. So
// "blah?foo/yui/yui.js" will capture "foo/" and "blah?some/thing.js&3.3.0/build/yui-davglass/yui-davglass.js"
// will capture "3.3.0/build/"
//
// Regex Exploded:
// (?:\? Find a ?
// (?:[^&]*&) followed by 0..n characters followed by an &
// * in fact, find as many sets of characters followed by a & as you can
// ([^&]*) capture the stuff after the last & in \1
// )? but it's ok if all this ?junk&more_junk stuff isn't even there
// \b(simpleyui| after a word break find either the string "simpleyui" or
// yui(?:-\w+)? the string "yui" optionally followed by a -, then more characters
// ) and store the simpleyui or yui-* string in \2
// \/\2 then comes a / followed by the simpleyui or yui-* string in \2
// (?:-(min|debug))? optionally followed by "-min" or "-debug"
// .js and ending in ".js"
_BASE_RE: /(?:\?(?:[^&]*&)*([^&]*))?\b(simpleyui|yui(?:-\w+)?)\/\2(?:-(min|debug))?\.js/,
parseBasePath: function(src, pattern) {
var match = src.match(pattern),
path, filter;
if (match) {
path = RegExp.leftContext || src.slice(0, src.indexOf(match[0]));
// this is to set up the path to the loader. The file
// filter for loader should match the yui include.
filter = match[3];
// extract correct path for mixed combo urls
// http://yuilibrary.com/projects/yui3/ticket/2528423
if (match[1]) {
path += '?' + match[1];
}
path = {
filter: filter,
path: path
};
}
return path;
},
getBase: G_ENV && G_ENV.getBase ||
function(pattern) {
var nodes = (doc && doc.getElementsByTagName('script')) || [],
path = Env.cdn, parsed,
i, len, src;
for (i = 0, len = nodes.length; i < len; ++i) {
src = nodes[i].src;
if (src) {
parsed = Y.Env.parseBasePath(src, pattern);
if (parsed) {
filter = parsed.filter;
path = parsed.path;
break;
}
}
}
// use CDN default
return path;
}
};
Env = Y.Env;
Env._loaded[VERSION] = {};
if (G_ENV && Y !== YUI) {
Env._yidx = ++G_ENV._yidx;
Env._guidp = ('yui_' + VERSION + '_' +
Env._yidx + '_' + time).replace(/[^a-z0-9_]+/g, '_');
} else if (YUI._YUI) {
G_ENV = YUI._YUI.Env;
Env._yidx += G_ENV._yidx;
Env._uidx += G_ENV._uidx;
for (prop in G_ENV) {
if (!(prop in Env)) {
Env[prop] = G_ENV[prop];
}
}
delete YUI._YUI;
}
Y.id = Y.stamp(Y);
instances[Y.id] = Y;
}
Y.constructor = YUI;
// configuration defaults
Y.config = Y.config || {
bootstrap: true,
cacheUse: true,
debug: true,
doc: doc,
fetchCSS: true,
throwFail: true,
useBrowserConsole: true,
useNativeES5: true,
win: win,
global: Function('return this')()
};
//Register the CSS stamp element
if (doc && !doc.getElementById(CSS_STAMP_EL)) {
el = doc.createElement('div');
el.innerHTML = '<div id="' + CSS_STAMP_EL + '" style="position: absolute !important; visibility: hidden !important"></div>';
YUI.Env.cssStampEl = el.firstChild;
if (doc.body) {
doc.body.appendChild(YUI.Env.cssStampEl);
} else {
docEl.insertBefore(YUI.Env.cssStampEl, docEl.firstChild);
}
} else if (doc && doc.getElementById(CSS_STAMP_EL) && !YUI.Env.cssStampEl) {
YUI.Env.cssStampEl = doc.getElementById(CSS_STAMP_EL);
}
Y.config.lang = Y.config.lang || 'en-US';
Y.config.base = YUI.config.base || Y.Env.getBase(Y.Env._BASE_RE);
if (!filter || (!('mindebug').indexOf(filter))) {
filter = 'min';
}
filter = (filter) ? '-' + filter : filter;
Y.config.loaderPath = YUI.config.loaderPath || 'loader/loader' + filter + '.js';
},
/**
Finishes the instance setup. Attaches whatever YUI modules were defined
at the time that this instance was created.
@method _setup
@private
**/
_setup: function() {
var i, Y = this,
core = [],
mods = YUI.Env.mods,
extras = Y.config.core || [].concat(YUI.Env.core); //Clone it..
for (i = 0; i < extras.length; i++) {
if (mods[extras[i]]) {
core.push(extras[i]);
}
}
Y._attach(['yui-base']);
Y._attach(core);
if (Y.Loader) {
getLoader(Y);
}
},
/**
Executes the named method on the specified YUI instance if that method is
whitelisted.
@method applyTo
@param {String} id YUI instance id.
@param {String} method Name of the method to execute. For example:
'Object.keys'.
@param {Array} args Arguments to apply to the method.
@return {Mixed} Return value from the applied method, or `null` if the
specified instance was not found or the method was not whitelisted.
**/
applyTo: function(id, method, args) {
if (!(method in APPLY_TO_AUTH)) {
this.log(method + ': applyTo not allowed', 'warn', 'yui');
return null;
}
var instance = instances[id], nest, m, i;
if (instance) {
nest = method.split('.');
m = instance;
for (i = 0; i < nest.length; i = i + 1) {
m = m[nest[i]];
if (!m) {
this.log('applyTo not found: ' + method, 'warn', 'yui');
}
}
return m && m.apply(instance, args);
}
return null;
},
/**
Registers a YUI module and makes it available for use in a `YUI().use()` call or
as a dependency for other modules.
The easiest way to create a first-class YUI module is to use
<a href="http://yui.github.com/shifter/">Shifter</a>, the YUI component build
tool.
Shifter will automatically wrap your module code in a `YUI.add()` call along
with any configuration info required for the module.
@example
YUI.add('davglass', function (Y) {
Y.davglass = function () {
};
}, '3.4.0', {
requires: ['harley-davidson', 'mt-dew']
});
@method add
@param {String} name Module name.
@param {Function} fn Function containing module code. This function will be
executed whenever the module is attached to a specific YUI instance.
@param {YUI} fn.Y The YUI instance to which this module is attached.
@param {String} fn.name Name of the module
@param {String} version Module version number. This is currently used only for
informational purposes, and is not used internally by YUI.
@param {Object} [config] Module config.
@param {Array} [config.requires] Array of other module names that must be
attached before this module can be attached.
@param {Array} [config.optional] Array of optional module names that should
be attached before this module is attached if they've already been
loaded. If the `loadOptional` YUI option is `true`, optional modules
that have not yet been loaded will be loaded just as if they were hard
requirements.
@param {Array} [config.use] Array of module names that are included within
or otherwise provided by this module, and which should be attached
automatically when this module is attached. This makes it possible to
create "virtual rollup" modules that simply attach a collection of other
modules or submodules.
@return {YUI} This YUI instance.
**/
add: function(name, fn, version, details) {
details = details || {};
var env = YUI.Env,
mod = {
name: name,
fn: fn,
version: version,
details: details
},
//Instance hash so we don't apply it to the same instance twice
applied = {},
loader, inst,
i, versions = env.versions;
env.mods[name] = mod;
versions[version] = versions[version] || {};
versions[version][name] = mod;
for (i in instances) {
if (instances.hasOwnProperty(i)) {
inst = instances[i];
if (!applied[inst.id]) {
applied[inst.id] = true;
loader = inst.Env._loader;
if (loader) {
if (!loader.moduleInfo[name] || loader.moduleInfo[name].temp) {
loader.addModule(details, name);
}
}
}
}
}
return this;
},
/**
Executes the callback function associated with each required module,
attaching the module to this YUI instance.
@method _attach
@param {Array} r The array of modules to attach
@param {Boolean} [moot=false] If `true`, don't throw a warning if the module
is not attached.
@private
**/
_attach: function(r, moot) {
var i, name, mod, details, req, use, after,
mods = YUI.Env.mods,
aliases = YUI.Env.aliases,
Y = this, j,
cache = YUI.Env._renderedMods,
loader = Y.Env._loader,
done = Y.Env._attached,
len = r.length, loader, def, go,
c = [];
//Check for conditional modules (in a second+ instance) and add their requirements
//TODO I hate this entire method, it needs to be fixed ASAP (3.5.0) ^davglass
for (i = 0; i < len; i++) {
name = r[i];
mod = mods[name];
c.push(name);
if (loader && loader.conditions[name]) {
for (j in loader.conditions[name]) {
if (loader.conditions[name].hasOwnProperty(j)) {
def = loader.conditions[name][j];
go = def && ((def.ua && Y.UA[def.ua]) || (def.test && def.test(Y)));
if (go) {
c.push(def.name);
}
}
}
}
}
r = c;
len = r.length;
for (i = 0; i < len; i++) {
if (!done[r[i]]) {
name = r[i];
mod = mods[name];
if (aliases && aliases[name] && !mod) {
Y._attach(aliases[name]);
continue;
}
if (!mod) {
if (loader && loader.moduleInfo[name]) {
mod = loader.moduleInfo[name];
moot = true;
}
//if (!loader || !loader.moduleInfo[name]) {
//if ((!loader || !loader.moduleInfo[name]) && !moot) {
if (!moot && name) {
if ((name.indexOf('skin-') === -1) && (name.indexOf('css') === -1)) {
Y.Env._missed.push(name);
Y.Env._missed = Y.Array.dedupe(Y.Env._missed);
Y.message('NOT loaded: ' + name, 'warn', 'yui');
}
}
} else {
done[name] = true;
//Don't like this, but in case a mod was asked for once, then we fetch it
//We need to remove it from the missed list ^davglass
for (j = 0; j < Y.Env._missed.length; j++) {
if (Y.Env._missed[j] === name) {
Y.message('Found: ' + name + ' (was reported as missing earlier)', 'warn', 'yui');
Y.Env._missed.splice(j, 1);
}
}
/*
If it's a temp module, we need to redo it's requirements if it's already loaded
since it may have been loaded by another instance and it's dependencies might
have been redefined inside the fetched file.
*/
if (loader && cache && cache[name] && cache[name].temp) {
loader.getRequires(cache[name]);
req = [];
for (j in loader.moduleInfo[name].expanded_map) {
if (loader.moduleInfo[name].expanded_map.hasOwnProperty(j)) {
req.push(j);
}
}
Y._attach(req);
}
details = mod.details;
req = details.requires;
use = details.use;
after = details.after;
//Force Intl load if there is a language (Loader logic) @todo fix this shit
if (details.lang) {
req = req || [];
req.unshift('intl');
}
if (req) {
for (j = 0; j < req.length; j++) {
if (!done[req[j]]) {
if (!Y._attach(req)) {
return false;
}
break;
}
}
}
if (after) {
for (j = 0; j < after.length; j++) {
if (!done[after[j]]) {
if (!Y._attach(after, true)) {
return false;
}
break;
}
}
}
if (mod.fn) {
if (Y.config.throwFail) {
mod.fn(Y, name);
} else {
try {
mod.fn(Y, name);
} catch (e) {
Y.error('Attach error: ' + name, e, name);
return false;
}
}
}
if (use) {
for (j = 0; j < use.length; j++) {
if (!done[use[j]]) {
if (!Y._attach(use)) {
return false;
}
break;
}
}
}
}
}
}
return true;
},
/**
Delays the `use` callback until another event has taken place such as
`window.onload`, `domready`, `contentready`, or `available`.
@private
@method _delayCallback
@param {Function} cb The original `use` callback.
@param {String|Object} until Either an event name ('load', 'domready', etc.)
or an object containing event/args keys for contentready/available.
@return {Function}
**/
_delayCallback: function(cb, until) {
var Y = this,
mod = ['event-base'];
until = (Y.Lang.isObject(until) ? until : { event: until });
if (until.event === 'load') {
mod.push('event-synthetic');
}
return function() {
var args = arguments;
Y._use(mod, function() {
Y.on(until.event, function() {
args[1].delayUntil = until.event;
cb.apply(Y, args);
}, until.args);
});
};
},
/**
Attaches one or more modules to this YUI instance. When this is executed,
the requirements of the desired modules are analyzed, and one of several
things can happen:
* All required modules have already been loaded, and just need to be
attached to this YUI instance. In this case, the `use()` callback will
be executed synchronously after the modules are attached.
* One or more modules have not yet been loaded, or the Get utility is not
available, or the `bootstrap` config option is `false`. In this case,
a warning is issued indicating that modules are missing, but all
available modules will still be attached and the `use()` callback will
be executed synchronously.
* One or more modules are missing and the Loader is not available but the
Get utility is, and `bootstrap` is not `false`. In this case, the Get
utility will be used to load the Loader, and we will then proceed to
the following state:
* One or more modules are missing and the Loader is available. In this
case, the Loader will be used to resolve the dependency tree for the
missing modules and load them and their dependencies. When the Loader is
finished loading modules, the `use()` callback will be executed
asynchronously.
@example
// Loads and attaches dd and its dependencies.
YUI().use('dd', function (Y) {
// ...
});
// Loads and attaches dd and node as well as all of their dependencies.
YUI().use(['dd', 'node'], function (Y) {
// ...
});
// Attaches all modules that have already been loaded.
YUI().use('*', function (Y) {
// ...
});
// Attaches a gallery module.
YUI().use('gallery-yql', function (Y) {
// ...
});
// Attaches a YUI 2in3 module.
YUI().use('yui2-datatable', function (Y) {
// ...
});
@method use
@param {String|Array} modules* One or more module names to attach.
@param {Function} [callback] Callback function to be executed once all
specified modules and their dependencies have been attached.
@param {YUI} callback.Y The YUI instance created for this sandbox.
@param {Object} callback.status Object containing `success`, `msg` and
`data` properties.
@chainable
**/
use: function() {
var args = SLICE.call(arguments, 0),
callback = args[args.length - 1],
Y = this,
i = 0,
name,
Env = Y.Env,
provisioned = true;
// The last argument supplied to use can be a load complete callback
if (Y.Lang.isFunction(callback)) {
args.pop();
if (Y.config.delayUntil) {
callback = Y._delayCallback(callback, Y.config.delayUntil);
}
} else {
callback = null;
}
if (Y.Lang.isArray(args[0])) {
args = args[0];
}
if (Y.config.cacheUse) {
while ((name = args[i++])) {
if (!Env._attached[name]) {
provisioned = false;
break;
}
}
if (provisioned) {
if (args.length) {
}
Y._notify(callback, ALREADY_DONE, args);
return Y;
}
}
if (Y._loading) {
Y._useQueue = Y._useQueue || new Y.Queue();
Y._useQueue.add([args, callback]);
} else {
Y._use(args, function(Y, response) {
Y._notify(callback, response, args);
});
}
return Y;
},
/**
Handles Loader notifications about attachment/load errors.
@method _notify
@param {Function} callback Callback to pass to `Y.config.loadErrorFn`.
@param {Object} response Response returned from Loader.
@param {Array} args Arguments passed from Loader.
@private
**/
_notify: function(callback, response, args) {
if (!response.success && this.config.loadErrorFn) {
this.config.loadErrorFn.call(this, this, callback, response, args);
} else if (callback) {
if (this.Env._missed && this.Env._missed.length) {
response.msg = 'Missing modules: ' + this.Env._missed.join();
response.success = false;
}
if (this.config.throwFail) {
callback(this, response);
} else {
try {
callback(this, response);
} catch (e) {
this.error('use callback error', e, args);
}
}
}
},
/**
Called from the `use` method queue to ensure that only one set of loading
logic is performed at a time.
@method _use
@param {String} args* One or more modules to attach.
@param {Function} [callback] Function to call once all required modules have
been attached.
@private
**/
_use: function(args, callback) {
if (!this.Array) {
this._attach(['yui-base']);