bv-ui-core 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc +40 -0
- package/.travis.yml +5 -0
- package/CONTRIBUTING.md +98 -0
- package/LICENSE.md +13 -0
- package/OWNERS +2 -0
- package/README.md +63 -0
- package/catalog-info.yaml +30 -0
- package/karma.conf.js +130 -0
- package/lib/README.md +61 -0
- package/lib/api/.babelrc +3 -0
- package/lib/api/.eslintrc +9 -0
- package/lib/api/README.md +134 -0
- package/lib/api/index.js +15 -0
- package/lib/api/statistics.js +148 -0
- package/lib/application/README.md +96 -0
- package/lib/application/index.js +171 -0
- package/lib/body/README.md +13 -0
- package/lib/body/index.js +19 -0
- package/lib/bvFetch/README.md +101 -0
- package/lib/bvFetch/index.js +383 -0
- package/lib/checkHighContrast/README.md +26 -0
- package/lib/checkHighContrast/index.js +36 -0
- package/lib/cookie/README.md +29 -0
- package/lib/cookie/index.js +111 -0
- package/lib/cookieConsent/README.md +41 -0
- package/lib/cookieConsent/index.js +227 -0
- package/lib/cssLoadChecker/README.md +19 -0
- package/lib/cssLoadChecker/index.js +72 -0
- package/lib/date.now/README.md +11 -0
- package/lib/date.now/index.js +40 -0
- package/lib/domainPolice/README.md +66 -0
- package/lib/domainPolice/index.js +95 -0
- package/lib/evented/README.md +42 -0
- package/lib/evented/index.js +135 -0
- package/lib/getOriginalConstructor/README.md +16 -0
- package/lib/getOriginalConstructor/index.js +52 -0
- package/lib/global/README.md +10 -0
- package/lib/global/index.js +48 -0
- package/lib/ie/README.md +13 -0
- package/lib/ie/index.js +25 -0
- package/lib/loader/README.md +73 -0
- package/lib/loader/index.js +358 -0
- package/lib/logger/README.md +82 -0
- package/lib/logger/index.js +180 -0
- package/lib/messageFormat/README.md +10 -0
- package/lib/messageFormat/index.js +42 -0
- package/lib/namespacer/README.md +57 -0
- package/lib/namespacer/index.js +98 -0
- package/lib/performance/README.md +35 -0
- package/lib/performance/entries.js +5 -0
- package/lib/performance/getEntries.js +42 -0
- package/lib/performance/getEntriesByName.js +61 -0
- package/lib/performance/getEntriesByType.js +55 -0
- package/lib/performance/index.js +11 -0
- package/lib/performance/mark.js +97 -0
- package/lib/performance/measure.js +106 -0
- package/lib/performance/now.js +63 -0
- package/lib/pixelsDisplayed/README.md +19 -0
- package/lib/pixelsDisplayed/index.js +113 -0
- package/lib/polyfills/README.md +39 -0
- package/lib/polyfills/fetch/Headers.js +3 -0
- package/lib/polyfills/fetch/Request.js +3 -0
- package/lib/polyfills/fetch/Response.js +3 -0
- package/lib/polyfills/fetch/fetch.js +3 -0
- package/lib/polyfills/fetch/index.js +57 -0
- package/lib/polyfills/promise.js +265 -0
- package/lib/queryShadowDom/README.md +50 -0
- package/lib/queryShadowDom/index.js +93 -0
- package/lib/region/README.md +64 -0
- package/lib/region/europe/index.js +94 -0
- package/lib/region/europe/territories.js +40 -0
- package/lib/region/index.js +123 -0
- package/lib/staticAssetLoader/README.md +116 -0
- package/lib/staticAssetLoader/index.js +248 -0
- package/lib/waitForBody/README.md +21 -0
- package/lib/waitForBody/index.js +36 -0
- package/mkdocs.yaml +5 -0
- package/package.json +55 -0
- package/test/.eslintrc +5 -0
- package/test/fixtures/lib.loader.document-is-wrong-in-ie8.js +5 -0
- package/test/fixtures/lib.loader.loadscript-attribute.js +3 -0
- package/test/fixtures/lib.loader.loadscript.js +3 -0
- package/test/fixtures/lib.loader.loadstylesheet.css +3 -0
- package/test/unit/api/.eslintrc +6 -0
- package/test/unit/api/index.spec.js +37 -0
- package/test/unit/api/response.json +67 -0
- package/test/unit/api/statistics.spec.js +218 -0
- package/test/unit/application/index.spec.js +313 -0
- package/test/unit/body/index.spec.js +15 -0
- package/test/unit/bvFetch/index.spec.js +246 -0
- package/test/unit/checkHighContrast/index.spec.js +16 -0
- package/test/unit/cookie/index.spec.js +191 -0
- package/test/unit/cookieConsent/index.spec.js +119 -0
- package/test/unit/cssLoadChecker/index.spec.js +75 -0
- package/test/unit/date.now/index.spec.js +21 -0
- package/test/unit/domainPolice/index.spec.js +141 -0
- package/test/unit/evented/index.spec.js +59 -0
- package/test/unit/getOriginalConstructor/index.spec.js +60 -0
- package/test/unit/global/index.spec.js +84 -0
- package/test/unit/ie/index.spec.js +14 -0
- package/test/unit/loader/index.spec.js +644 -0
- package/test/unit/logger/index.spec.js +141 -0
- package/test/unit/messageFormat/index.spec.js +31 -0
- package/test/unit/mochaInit.js +8 -0
- package/test/unit/namespacer/index.spec.js +100 -0
- package/test/unit/performance/getEntries.spec.js +30 -0
- package/test/unit/performance/getEntriesByName.spec.js +88 -0
- package/test/unit/performance/getEntriesByType.spec.js +48 -0
- package/test/unit/performance/index.spec.js +35 -0
- package/test/unit/performance/mark.spec.js +40 -0
- package/test/unit/performance/measure.spec.js +50 -0
- package/test/unit/performance/now.spec.js +21 -0
- package/test/unit/pixelsDisplayed/index.spec.js +271 -0
- package/test/unit/polyfills/fetch/Headers.js +12 -0
- package/test/unit/polyfills/fetch/Request.js +12 -0
- package/test/unit/polyfills/fetch/Response.js +12 -0
- package/test/unit/polyfills/fetch/fetch.js +12 -0
- package/test/unit/polyfills/fetch/index.js +61 -0
- package/test/unit/polyfills/promise.spec.js +48 -0
- package/test/unit/region/europe/index.spec.js +70 -0
- package/test/unit/region/index.spec.js +113 -0
- package/test/unit/staticAssetLoader/index.spec.js +215 -0
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Region
|
|
2
|
+
|
|
3
|
+
The `region` module is a module meant to standardize the detection of various
|
|
4
|
+
regions, such as EU or APAC. It exposes functions that can test if a locale
|
|
5
|
+
belongs to various regions. It can also simply lookup the region for a given
|
|
6
|
+
locale.
|
|
7
|
+
|
|
8
|
+
So far, the only region supported is EU, but the module is designed to be
|
|
9
|
+
easily extendable when the need to support other regions pops up.
|
|
10
|
+
|
|
11
|
+
## Usage Examples
|
|
12
|
+
|
|
13
|
+
Loading the root module:
|
|
14
|
+
```javascript
|
|
15
|
+
var region = require('bv-ui-core/lib/region');
|
|
16
|
+
|
|
17
|
+
region.hasLocale('europe', 'en_US'); // false
|
|
18
|
+
region.hasLocale('europe', 'en_GB'); // true
|
|
19
|
+
|
|
20
|
+
region.hasTerritory('europe', 'US'); // false
|
|
21
|
+
region.hasTerritory('europe', 'GB'); // true
|
|
22
|
+
|
|
23
|
+
region.lookupTerritory('US'); // unsupported
|
|
24
|
+
region.lookupTerritory('GB'); // europe
|
|
25
|
+
|
|
26
|
+
region.lookupLocale('en_US'); // unsupported
|
|
27
|
+
region.lookupLocale('en_GB'); // europe
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
This can be useful when you'll have to support detection of multiple regions.
|
|
31
|
+
As only the EU region is supported for now, it's not particularly useful yet.
|
|
32
|
+
|
|
33
|
+
Loading a specific region module:
|
|
34
|
+
```javascript
|
|
35
|
+
var europe = require('bv-ui-core/lib/region/europe');
|
|
36
|
+
|
|
37
|
+
europe.hasLocale('en_US'); // false
|
|
38
|
+
europe.hasLocale('en_GB'); // true
|
|
39
|
+
|
|
40
|
+
europe.hasTerritory('US'); // false
|
|
41
|
+
europe.hasTerritory('GB'); // true
|
|
42
|
+
|
|
43
|
+
// Get an Array with all the region's country codes.
|
|
44
|
+
var europeanTerritories = europe.listTerritories();
|
|
45
|
+
|
|
46
|
+
// If you prefer a map, you can require it directly.
|
|
47
|
+
var europeanTerritoryMap = require('bv-ui-core/lib/region/europe/territories');
|
|
48
|
+
```
|
|
49
|
+
This can be useful if you've no need for other regions and would like to shave
|
|
50
|
+
every last byte from your client-side code.
|
|
51
|
+
|
|
52
|
+
Errors will be thrown if invalid locale or territory codes are provided. This
|
|
53
|
+
is to protect the user against mistaking language codes for territory codes.
|
|
54
|
+
For example, 'fr' is the code for the French language, and 'FR' is the code
|
|
55
|
+
for France. To avoid the case where `region.hasTerritory('europe', 'fr');`
|
|
56
|
+
returns false, we throw an error.
|
|
57
|
+
|
|
58
|
+
```javascript
|
|
59
|
+
var region = require('bv-ui-core/lib/region');
|
|
60
|
+
|
|
61
|
+
// The user likely meant to check 'FR'. To avoid confusion, we throw an error
|
|
62
|
+
// instead of just returning false.
|
|
63
|
+
region.hasTerritory('europe', 'fr');
|
|
64
|
+
```
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module Module for determining if a locale is in the EU.
|
|
3
|
+
*
|
|
4
|
+
* Examples:
|
|
5
|
+
*
|
|
6
|
+
* // Example 1, loading this module directly:
|
|
7
|
+
* var europe = require('bv-ui-core/lib/region/europe');
|
|
8
|
+
* europe.hasLocale('en_US'); // false
|
|
9
|
+
* europe.hasLocale('en_GB'); // true
|
|
10
|
+
*
|
|
11
|
+
* europe.hasTerritory('US'); // false
|
|
12
|
+
* europe.hasTerritory('GB'); // true
|
|
13
|
+
*
|
|
14
|
+
* // Example 2, loading the region module:
|
|
15
|
+
* var region = require('bv-ui-core/lib/region');
|
|
16
|
+
* region.hasLocale('europe', 'en_US'); // false
|
|
17
|
+
* region.hasLocale('europe', 'en_GB'); // true
|
|
18
|
+
*
|
|
19
|
+
* region.hasTerritory('europe', 'US'); // false
|
|
20
|
+
* region.hasTerritory('europe', 'GB'); // true
|
|
21
|
+
*
|
|
22
|
+
* Errors will be thrown if an invalid locale or territory code is provided.
|
|
23
|
+
*
|
|
24
|
+
* Example 3, providing invalid input:
|
|
25
|
+
* var europe = require('bv-ui-core/lib/region/europe');
|
|
26
|
+
* europe.hasLocale('banana'); // throws an error
|
|
27
|
+
*
|
|
28
|
+
* // 'fr' is a language code. The correct French territory code is 'FR'.
|
|
29
|
+
* europe.hasTerritory('fr'); // throws an error.
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
// territories is a map that contains an entry for each valid EU country
|
|
33
|
+
// code, so territories[territory] will return either true or undefined.
|
|
34
|
+
// We just need to coerce that into a boolean value and we're good to go.
|
|
35
|
+
var territories = require('./territories');
|
|
36
|
+
|
|
37
|
+
// Some constant patterns for valid values.
|
|
38
|
+
var VALID_TERRITORY = /^[A-Z]{2}$/;
|
|
39
|
+
var VALID_LOCALE = /^[a-z]{2}[_-][A-Z]{2}$/;
|
|
40
|
+
|
|
41
|
+
module.exports = {
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Determine if a given territory is an EU territory.
|
|
45
|
+
*
|
|
46
|
+
* @param {String} territory - The locale to be tested. This function accepts
|
|
47
|
+
* territory codes of the XX format. Three letter territory codes are not
|
|
48
|
+
* (yet) supported.
|
|
49
|
+
*
|
|
50
|
+
* @return {Boolean} Returns true if the territory is an EU territory.
|
|
51
|
+
* Returns false otherwise.
|
|
52
|
+
*
|
|
53
|
+
* @throws
|
|
54
|
+
*/
|
|
55
|
+
hasTerritory: function (territory) {
|
|
56
|
+
|
|
57
|
+
if (!VALID_TERRITORY.test(territory)) {
|
|
58
|
+
throw new Error('Invalid territory code passed to hasTerritory.');
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return !!territories[territory];
|
|
62
|
+
},
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Determine if a given locale is an EU locale based on the territory code.
|
|
66
|
+
*
|
|
67
|
+
* @param {String} locale - The locale to be tested. This function accepts
|
|
68
|
+
* locales of the xx_XX format only.
|
|
69
|
+
*
|
|
70
|
+
* @return {Boolean} Returns true if the locale is an EU territory.
|
|
71
|
+
* Returns false otherwise.
|
|
72
|
+
*
|
|
73
|
+
* @throws
|
|
74
|
+
*/
|
|
75
|
+
hasLocale: function (locale) {
|
|
76
|
+
|
|
77
|
+
if (!VALID_LOCALE.test(locale)) {
|
|
78
|
+
throw new Error('Invalid locale code passed to hasLocale.');
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
var territory = locale.split(/[\_\-]/).pop();
|
|
82
|
+
|
|
83
|
+
return !!territories[territory];
|
|
84
|
+
},
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Return a list of country codes in this region.
|
|
88
|
+
*
|
|
89
|
+
* @return {Array} - A list of country codes in the european region.
|
|
90
|
+
*/
|
|
91
|
+
listTerritories: function () {
|
|
92
|
+
return Object.keys(territories);
|
|
93
|
+
}
|
|
94
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file List of country codes legally considered part of the EU region.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
var countryCodes = {
|
|
6
|
+
AT: true, // Austria
|
|
7
|
+
BE: true, // Belgium
|
|
8
|
+
BG: true, // Bulgaria
|
|
9
|
+
CH: true, // Switzerland
|
|
10
|
+
CY: true, // Republic of Cyprus
|
|
11
|
+
CZ: true, // Czech Republic
|
|
12
|
+
DE: true, // Germany
|
|
13
|
+
DK: true, // Denmark
|
|
14
|
+
ES: true, // Spain
|
|
15
|
+
EE: true, // Estonia
|
|
16
|
+
FI: true, // Finland
|
|
17
|
+
FR: true, // France
|
|
18
|
+
GB: true, // Great Britain / UK
|
|
19
|
+
GR: true, // Greece
|
|
20
|
+
HR: true, // Croatia
|
|
21
|
+
HU: true, // Hungary
|
|
22
|
+
IE: true, // Ireland
|
|
23
|
+
IS: true, // Iceland
|
|
24
|
+
IT: true, // Italy
|
|
25
|
+
LI: true, // Liechtenstein
|
|
26
|
+
LT: true, // Lithuania
|
|
27
|
+
LU: true, // Luxembourg
|
|
28
|
+
LV: true, // Latvia
|
|
29
|
+
MT: true, // Malta
|
|
30
|
+
NL: true, // Netherlands
|
|
31
|
+
NO: true, // Norway
|
|
32
|
+
PL: true, // Poland
|
|
33
|
+
PT: true, // Portugal
|
|
34
|
+
RO: true, // Romania
|
|
35
|
+
SE: true, // Sweden
|
|
36
|
+
SI: true, // Slovenia
|
|
37
|
+
SK: true // Slovakia
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
module.exports = countryCodes;
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module Used to determine if a given locale is part of a given region.
|
|
3
|
+
*
|
|
4
|
+
* Currently, the only supported region is EU, because it's the only region
|
|
5
|
+
* we have a need to support. However, this module was designed so that it'd
|
|
6
|
+
* be easy to add new regions, such as APAC, NA, LA, etc.
|
|
7
|
+
*
|
|
8
|
+
* This module is the "generic" module, and can be used to detect any region
|
|
9
|
+
* we support. If your project only needs to detect a specific region, you can
|
|
10
|
+
* require that region's module on its own to reduce file size.
|
|
11
|
+
*
|
|
12
|
+
* Examples:
|
|
13
|
+
*
|
|
14
|
+
* var region = require('bv-ui-core/lib/region');
|
|
15
|
+
* region.hasLocale('europe', 'en_US'); // false
|
|
16
|
+
* region.hasLocale('europe', 'en_GB'); // true
|
|
17
|
+
*
|
|
18
|
+
* region.hasTerritory('europe', 'US'); // false
|
|
19
|
+
* region.hasTerritory('europe', 'GB'); // true
|
|
20
|
+
*
|
|
21
|
+
* Errors will be thrown if an invalid locale or territory code is provided.
|
|
22
|
+
*
|
|
23
|
+
* Example 3, providing invalid input:
|
|
24
|
+
* var region = require('bv-ui-core/lib/region');
|
|
25
|
+
* region.hasLocale('europe', 'banana'); // throws an error
|
|
26
|
+
*
|
|
27
|
+
* // 'fr' is a language code. The correct French territory code is 'FR'.
|
|
28
|
+
* region.hasTerritory('europe', 'fr'); // throws an error.
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
var regions = {
|
|
32
|
+
europe: require('./europe')
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
module.exports = {
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Determine if a given territory is an EU territory.
|
|
39
|
+
*
|
|
40
|
+
* @param {String} region - The region to check for the territory in.
|
|
41
|
+
*
|
|
42
|
+
* @param {String} territory - The locale to be tested. This function accepts
|
|
43
|
+
* territory codes of the XX format. Three letter territory codes are not
|
|
44
|
+
* (yet) supported.
|
|
45
|
+
*
|
|
46
|
+
* @return {Boolean} Returns true if the territory is an EU territory.
|
|
47
|
+
* Returns false otherwise.
|
|
48
|
+
*/
|
|
49
|
+
hasTerritory: function (region, territory) {
|
|
50
|
+
|
|
51
|
+
if (!regions[region]) {
|
|
52
|
+
throw new Error('Invalid region passed to region.hasTerritory');
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Simply wrap around the individual region modules.
|
|
56
|
+
return regions[region].hasTerritory(territory);
|
|
57
|
+
},
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Determine if a given locale is an EU locale based on the territory code.
|
|
61
|
+
*
|
|
62
|
+
* @param {String} region - The region to check for the territory in.
|
|
63
|
+
*
|
|
64
|
+
* @param {String} locale - The locale to be tested. This function accepts
|
|
65
|
+
* locales of the xx_XX format only.
|
|
66
|
+
*
|
|
67
|
+
* @return {Boolean} Returns true if the locale is an EU territory.
|
|
68
|
+
* Returns false otherwise.
|
|
69
|
+
*/
|
|
70
|
+
hasLocale: function (region, locale) {
|
|
71
|
+
|
|
72
|
+
if (!regions[region]) {
|
|
73
|
+
throw new Error('Invalid region passed to region.hasLocale');
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Simply wrap around the individual region modules.
|
|
77
|
+
return regions[region].hasLocale(locale);
|
|
78
|
+
},
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Return the region of a specified territory.
|
|
82
|
+
*
|
|
83
|
+
* @param {String} territory - The name of the territory.
|
|
84
|
+
*
|
|
85
|
+
* @return {String} Returns the name of the region, or 'unsupported' if the
|
|
86
|
+
* territory is not part of a supported region.
|
|
87
|
+
*/
|
|
88
|
+
lookupTerritory: function (territory) {
|
|
89
|
+
|
|
90
|
+
// Loop through the regions looking for the territory.
|
|
91
|
+
var region;
|
|
92
|
+
for (region in regions) {
|
|
93
|
+
if (regions[region].hasTerritory(territory)) {
|
|
94
|
+
return region;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// If we get here, the territory isn't in any currently supported region.
|
|
99
|
+
return 'unsupported';
|
|
100
|
+
},
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Return the region of a specified locale.
|
|
104
|
+
*
|
|
105
|
+
* @param {String} locale - The name of the locale.
|
|
106
|
+
*
|
|
107
|
+
* @return {String} Returns the name of the region, or 'unsupported' if the
|
|
108
|
+
* locale is not part of a supported region.
|
|
109
|
+
*/
|
|
110
|
+
lookupLocale: function (locale) {
|
|
111
|
+
|
|
112
|
+
// Loop through the regions looking for the locale.
|
|
113
|
+
var region;
|
|
114
|
+
for (region in regions) {
|
|
115
|
+
if (regions[region].hasLocale(locale)) {
|
|
116
|
+
return region;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// If we get here, the locale isn't in any currently supported region.
|
|
121
|
+
return 'unsupported';
|
|
122
|
+
}
|
|
123
|
+
};
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# Static Asset Loader
|
|
2
|
+
|
|
3
|
+
This can be used by client-side web applications to request and receive the
|
|
4
|
+
static resources they require from a suitable static asset server. The
|
|
5
|
+
primary objective is to allow multiple discrete web applications on the same
|
|
6
|
+
page to converge on shared dependencies. Each dependency is only loaded
|
|
7
|
+
once and this reduces the overall page footprint.
|
|
8
|
+
|
|
9
|
+
## Basic Usage
|
|
10
|
+
|
|
11
|
+
### Configuration
|
|
12
|
+
|
|
13
|
+
The static asset loader must be configured with the following:
|
|
14
|
+
|
|
15
|
+
* A function to generate asset URLs from asset name and version strings.
|
|
16
|
+
* The name of the application namespace.
|
|
17
|
+
|
|
18
|
+
Applications sharing static assets must use the same namespace.
|
|
19
|
+
|
|
20
|
+
```javascript
|
|
21
|
+
var staticAssetLoaderFactory = require('bv-ui-core/lib/staticAssetLoader');
|
|
22
|
+
|
|
23
|
+
var staticAssetLoader = staticAssetLoaderFactory.create({
|
|
24
|
+
/**
|
|
25
|
+
* Convert one or more asset strings into a static asset service URL.
|
|
26
|
+
*
|
|
27
|
+
* The details depend on the static asset server capabilities. This is an
|
|
28
|
+
* example implementation for a server capable of delivering asset bundles.
|
|
29
|
+
*
|
|
30
|
+
* @param {String[]} An array of asset names and version: ['jQuery@2.0.0'].
|
|
31
|
+
* @return {String} The URL for the asset.
|
|
32
|
+
*/
|
|
33
|
+
generateUrl: function (assetNames, namespaceName) {
|
|
34
|
+
var filename = encodeURIComponent(assetNames.slice(0).sort().join('+')) + '.js';
|
|
35
|
+
|
|
36
|
+
namespaceName = encodeURIComponent(namespaceName);
|
|
37
|
+
return 'https://static.example.com/1/asset/' + namespaceName + '/' + filename;
|
|
38
|
+
},
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Provide the name of a namespace to hold the _staticAssetRegistry properties
|
|
42
|
+
* and methods. Applications sharing static assets must use the same
|
|
43
|
+
* namespace.
|
|
44
|
+
*/
|
|
45
|
+
namespaceName: 'EXAMPLE'
|
|
46
|
+
});
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Require Assets
|
|
50
|
+
|
|
51
|
+
When the application requires a resource of a supported type, use the client to
|
|
52
|
+
request that resource via the `require` method.
|
|
53
|
+
|
|
54
|
+
```javascript
|
|
55
|
+
// Request the desired assets. For example:
|
|
56
|
+
staticAssetLoader.require([
|
|
57
|
+
'underscore@1.0.0',
|
|
58
|
+
'jquery-custom@1.11.1',
|
|
59
|
+
'backbone@1.2.0'
|
|
60
|
+
], function (_, $, Backbone) {
|
|
61
|
+
// This callback will be invoked when all of the required assets have been
|
|
62
|
+
// resolved.
|
|
63
|
+
});
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Note that when requesting an asset that has dependency assets - for example,
|
|
67
|
+
Backbone depends on jQuery and either Underscore or Lodash - it is necessary to
|
|
68
|
+
request those dependencies in the same `require` call.
|
|
69
|
+
|
|
70
|
+
### Define Assets
|
|
71
|
+
|
|
72
|
+
Applications that ship with resources that might be useful to other applications
|
|
73
|
+
on the page can provide those resources via the static asset loader. This again
|
|
74
|
+
allows for a convergence of dependencies and reduced page weight.
|
|
75
|
+
|
|
76
|
+
```javascript
|
|
77
|
+
// After definition, staticAssetLoader.require('jquery-custom@1.11.1', callback)
|
|
78
|
+
// will call back immediately with the provided instance of jQuery.
|
|
79
|
+
staticAssetLoader.define('jquery-custom@1.11.1', jQuery);
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Order and Timing of Calls
|
|
83
|
+
|
|
84
|
+
Calls to `require` and `define` can be made in any order and at any time, for so
|
|
85
|
+
long as each call to `require` includes all needed dependency assets. Obviously
|
|
86
|
+
it is usually better to make these calls as early as possible in the application
|
|
87
|
+
initialization process so as to minimize lead time.
|
|
88
|
+
|
|
89
|
+
## Form of the Static Asset Service
|
|
90
|
+
|
|
91
|
+
The static assert service is a web service that can respond to requests such as:
|
|
92
|
+
|
|
93
|
+
`https://static.example.com/1/asset/namespace/jquery@1.11.1.js`
|
|
94
|
+
|
|
95
|
+
Importantly, the static asset service must be capable of serving bundles of
|
|
96
|
+
assets in response to a single request, with the assets listed in alphabetical
|
|
97
|
+
order. E.g.:
|
|
98
|
+
|
|
99
|
+
`https://static.example.com/1/asset/namespace/backbone@1.2.0+jquery@1.11.1.js`
|
|
100
|
+
|
|
101
|
+
The returned Javascript must both define the assets themselves and then provide
|
|
102
|
+
the asset to the static asset client in the same way as described above. For
|
|
103
|
+
example:
|
|
104
|
+
|
|
105
|
+
```javascript
|
|
106
|
+
(function (define) {
|
|
107
|
+
|
|
108
|
+
// Asset source code goes here.
|
|
109
|
+
//
|
|
110
|
+
// ...
|
|
111
|
+
|
|
112
|
+
// Then provide the asset or assets to the client.
|
|
113
|
+
define('asset@1.0.0', asset);
|
|
114
|
+
|
|
115
|
+
}(window[namespace]._staticAssetRegistry.define));
|
|
116
|
+
```
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileOverview
|
|
3
|
+
* A static asset loader to pull resources at particular versions from a static
|
|
4
|
+
* asset service. This could be as simple as an S3-backed CDN, or a webserver
|
|
5
|
+
* serving from a directory of files. E.g. a server that can respond to requests
|
|
6
|
+
* such as:
|
|
7
|
+
*
|
|
8
|
+
* https://static.example.com/1/asset/jquery@1.11.1.js
|
|
9
|
+
*
|
|
10
|
+
* Importantly, the static asset service must be capable of serving bundles of
|
|
11
|
+
* assets in a single request, where these assets are listed in alphabetical
|
|
12
|
+
* order. E.g.:
|
|
13
|
+
*
|
|
14
|
+
* https://static.example.com/1/asset/backbone@1.2.0+jquery@1.11.1.js
|
|
15
|
+
*
|
|
16
|
+
* This is primarily intended to reduce asset duplication among multiple
|
|
17
|
+
* distinct client applications running on the same page.
|
|
18
|
+
*
|
|
19
|
+
* The returned Javascript must both define the assets themselves and then
|
|
20
|
+
* provide the asset to the static asset client. For example:
|
|
21
|
+
*
|
|
22
|
+
* (function (define) {
|
|
23
|
+
*
|
|
24
|
+
* // Asset source code goes here.
|
|
25
|
+
* //
|
|
26
|
+
* // ...
|
|
27
|
+
*
|
|
28
|
+
* // Then provide the asset or assets to the client.
|
|
29
|
+
* define('asset@1.0.0', ['dependency@1.0.0'], asset);
|
|
30
|
+
*
|
|
31
|
+
* }(window[namespace]._staticAssetRegistry.define));
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
var loader = require('../loader');
|
|
35
|
+
var namespacer = require('../namespacer');
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Invoke the provided function on each element of the array.
|
|
39
|
+
*
|
|
40
|
+
* @param {Array} arr An array.
|
|
41
|
+
* @param {Function} fn Function to invoke as fn(element, index, array).
|
|
42
|
+
*/
|
|
43
|
+
function forEach (arr, fn) {
|
|
44
|
+
if (!arr || !arr.length) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
for (var index = 0; index < arr.length; index++) {
|
|
49
|
+
fn(arr[index], index, arr);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Create a new array containing the results of applying the provided function
|
|
55
|
+
* to each element.
|
|
56
|
+
*
|
|
57
|
+
* @param {Array} arr An array.
|
|
58
|
+
* @param {Function} fn Function to invoke as fn(element, index, array).
|
|
59
|
+
* @return {Array} The mapped array.
|
|
60
|
+
*/
|
|
61
|
+
function map (arr, fn) {
|
|
62
|
+
var mappedArray = [];
|
|
63
|
+
|
|
64
|
+
forEach(arr, function (val, index, originalArray) {
|
|
65
|
+
mappedArray.push(fn(val, index, originalArray));
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
return mappedArray;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
module.exports = {
|
|
72
|
+
/**
|
|
73
|
+
* A factory function for static asset loaders.
|
|
74
|
+
*
|
|
75
|
+
* See the documentation for the properties required for the configuration
|
|
76
|
+
* object.
|
|
77
|
+
*
|
|
78
|
+
* @param {Object} config Configuration.
|
|
79
|
+
* @return {Object} A static asset loader instance.
|
|
80
|
+
*/
|
|
81
|
+
create: function staticAssetLoaderFactory (config) {
|
|
82
|
+
var generateUrl = config.generateUrl;
|
|
83
|
+
var namespaceName = config.namespaceName;
|
|
84
|
+
|
|
85
|
+
if (!namespaceName) {
|
|
86
|
+
throw new Error('Cannot initialize staticAssetLoader without a namespace name.');
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (typeof generateUrl !== 'function') {
|
|
90
|
+
throw new Error('Cannot initialize staticAssetLoader without a URL generation function.');
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
var loaderOptions = config.loaderOptions || {};
|
|
94
|
+
var NS = namespacer.namespace(namespaceName);
|
|
95
|
+
var registry = NS._staticAssetRegistry = NS._staticAssetRegistry || {
|
|
96
|
+
// Stores defined entities by asset name. E.g.:
|
|
97
|
+
//
|
|
98
|
+
// {
|
|
99
|
+
// 'jquery@1.11.1': jquery,
|
|
100
|
+
// ...
|
|
101
|
+
// }
|
|
102
|
+
assets: {},
|
|
103
|
+
// Stores requests indexed by included asset, each of which can specify
|
|
104
|
+
// multiple assets. Has the form:
|
|
105
|
+
//
|
|
106
|
+
// {
|
|
107
|
+
// 'jquery@1.11.1': {
|
|
108
|
+
// assetNames: ['jquery@1.11.1', ...],
|
|
109
|
+
// callback: function (jQuery, ...),
|
|
110
|
+
// complete: false
|
|
111
|
+
// },
|
|
112
|
+
// ...
|
|
113
|
+
// }
|
|
114
|
+
requests: {},
|
|
115
|
+
// Set below to the _define function, so that loaded asset wrappers can
|
|
116
|
+
// use it to define assets.
|
|
117
|
+
define: undefined
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Given a request object, call back with the list of requested assets, in
|
|
122
|
+
* the same order as requested, if all assets are defined and the callback
|
|
123
|
+
* has not already occurred.
|
|
124
|
+
*
|
|
125
|
+
* @param {Object} request
|
|
126
|
+
*/
|
|
127
|
+
function callbackIfComplete (request) {
|
|
128
|
+
// Already called back?
|
|
129
|
+
if (request.complete) {
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
var complete = true;
|
|
134
|
+
var assets = map(request.assetNames, function (assetName) {
|
|
135
|
+
var asset = registry.assets[assetName];
|
|
136
|
+
|
|
137
|
+
if (!asset) {
|
|
138
|
+
complete = false;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return asset;
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
if (complete) {
|
|
145
|
+
request.complete = true;
|
|
146
|
+
if (typeof request.callback === 'function') {
|
|
147
|
+
request.callback.apply(null, assets);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Define assets. Usage is:
|
|
154
|
+
*
|
|
155
|
+
* _define('x@1.0.0', x);
|
|
156
|
+
*
|
|
157
|
+
* Later calls to _require() for this asset name will yield the defined
|
|
158
|
+
* asset.
|
|
159
|
+
*
|
|
160
|
+
* Any currently pending calls to _require() now satisfied will resolve.
|
|
161
|
+
*
|
|
162
|
+
* @param {String} assetName The name of the asset. E.g. 'jquery@1.11.1'.
|
|
163
|
+
* @param {Mixed} asset The asset.
|
|
164
|
+
*/
|
|
165
|
+
function _define (assetName, asset) {
|
|
166
|
+
// Ignore an attempt to redefine an asset. This can cause potentially
|
|
167
|
+
// interesting problems when some references point to instance A and
|
|
168
|
+
// others to instance B.
|
|
169
|
+
if (registry.assets[assetName]) {
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
registry.assets[assetName] = asset;
|
|
174
|
+
forEach(registry.requests[assetName], callbackIfComplete);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Require assets and provide a callback to be invoked when the assets are
|
|
179
|
+
* resolved.
|
|
180
|
+
*
|
|
181
|
+
* @param {String[]} assetNames An array of supported asset names.
|
|
182
|
+
* @param {Function} callback The callback to be called when the assets are
|
|
183
|
+
* resolved, with the assets as its arguments in the same order as the
|
|
184
|
+
* provided assets array.
|
|
185
|
+
*/
|
|
186
|
+
function _require (assetNames, callback) {
|
|
187
|
+
var request = {
|
|
188
|
+
assetNames: assetNames,
|
|
189
|
+
callback: callback,
|
|
190
|
+
complete: false
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
forEach(assetNames, function (assetName) {
|
|
194
|
+
registry.requests[assetName] = registry.requests[assetName] || [];
|
|
195
|
+
registry.requests[assetName].push(request);
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
// Are all the dependencies already in place, and so we can skip the
|
|
199
|
+
// loading of assets?
|
|
200
|
+
callbackIfComplete(request);
|
|
201
|
+
if (request.complete) {
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
var assetNamesToBeRequested = [];
|
|
206
|
+
|
|
207
|
+
forEach(assetNames, function (assetName) {
|
|
208
|
+
// The asset already exists.
|
|
209
|
+
if (registry.assets[assetName]) {
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
// There is already a pending request for this asset. So don't issue
|
|
213
|
+
// another request, just ensure that a response is delivered to this
|
|
214
|
+
// request when the pending request completes.
|
|
215
|
+
else if (registry.requests[assetName].length > 1) {
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
// There is no pending request; we need to queue it for requesting.
|
|
219
|
+
else {
|
|
220
|
+
assetNamesToBeRequested.push(assetName);
|
|
221
|
+
}
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
// If we queued any requests, now we need to make them.
|
|
225
|
+
if (assetNamesToBeRequested.length) {
|
|
226
|
+
loader.loadScript(
|
|
227
|
+
generateUrl(assetNamesToBeRequested, namespaceName),
|
|
228
|
+
loaderOptions,
|
|
229
|
+
function (error) {
|
|
230
|
+
if (error) {
|
|
231
|
+
throw new Error(
|
|
232
|
+
'Failed to load ' + assetNamesToBeRequested.join(', ') + ': ' + error.toString());
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// This is made available for responses from the static asset server to use.
|
|
240
|
+
registry.define = _define;
|
|
241
|
+
|
|
242
|
+
// Return the static asset loader interface.
|
|
243
|
+
return {
|
|
244
|
+
require: _require,
|
|
245
|
+
define: _define
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
};
|