Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/phabricator
Path: blob/master/webroot/rsrc/externals/javelin/lib/Resource.js
12242 views
1
/**
2
* @provides javelin-resource
3
* @requires javelin-util
4
* javelin-uri
5
* javelin-install
6
*
7
* @javelin
8
*/
9
10
JX.install('Resource', {
11
12
statics: {
13
14
_loading: {},
15
_loaded: {},
16
_links: [],
17
_callbacks: [],
18
19
/**
20
* Loads one or many static resources (JavaScript or CSS) and executes a
21
* callback once these resources have finished loading.
22
*
23
* @param string|array static resource or list of resources to be loaded
24
* @param function callback when resources have finished loading
25
*/
26
load: function(list, callback) {
27
var resources = {},
28
uri, resource, path;
29
30
list = JX.$AX(list);
31
32
// In the event there are no resources to wait on, call the callback and
33
// exit. NOTE: it's better to do this check outside this function and not
34
// call through JX.Resource, but it's not always easy/possible to do so
35
if (!list.length) {
36
setTimeout(callback, 0);
37
return;
38
}
39
40
for (var ii = 0; ii < list.length; ii++) {
41
uri = new JX.URI(list[ii]);
42
resource = uri.toString();
43
path = uri.getPath();
44
resources[resource] = true;
45
46
if (JX.Resource._loaded[resource]) {
47
setTimeout(JX.bind(JX.Resource, JX.Resource._complete, resource), 0);
48
} else if (!JX.Resource._loading[resource]) {
49
JX.Resource._loading[resource] = true;
50
if (path.indexOf('.css') == path.length - 4) {
51
JX.Resource._loadCSS(resource);
52
} else {
53
JX.Resource._loadJS(resource);
54
}
55
}
56
}
57
58
JX.Resource._callbacks.push({
59
resources: resources,
60
callback: callback
61
});
62
},
63
64
_loadJS: function(uri) {
65
var script = document.createElement('script');
66
var load_callback = function() {
67
JX.Resource._complete(uri);
68
};
69
var error_callback = function() {
70
JX.$E('Resource: JS file download failure: ' + uri);
71
};
72
73
JX.copy(script, {
74
type: 'text/javascript',
75
src: uri
76
});
77
78
script.onload = load_callback;
79
script.onerror = error_callback;
80
script.onreadystatechange = function() {
81
var state = this.readyState;
82
if (state == 'complete' || state == 'loaded') {
83
load_callback();
84
}
85
};
86
document.getElementsByTagName('head')[0].appendChild(script);
87
},
88
89
_loadCSS: function(uri) {
90
var link = JX.copy(document.createElement('link'), {
91
type: 'text/css',
92
rel: 'stylesheet',
93
href: uri,
94
'data-href': uri // don't trust href
95
});
96
document.getElementsByTagName('head')[0].appendChild(link);
97
98
JX.Resource._links.push(link);
99
if (!JX.Resource._timer) {
100
JX.Resource._timer = setInterval(JX.Resource._poll, 20);
101
}
102
},
103
104
_poll: function() {
105
var sheets = document.styleSheets,
106
ii = sheets.length,
107
links = JX.Resource._links;
108
109
// Cross Origin CSS loading
110
// http://yearofmoo.com/2011/03/cross-browser-stylesheet-preloading/
111
while (ii--) {
112
var link = sheets[ii],
113
owner = link.ownerNode || link.owningElement,
114
jj = links.length;
115
if (owner) {
116
while (jj--) {
117
if (owner == links[jj]) {
118
JX.Resource._complete(links[jj]['data-href']);
119
links.splice(jj, 1);
120
}
121
}
122
}
123
}
124
125
if (!links.length) {
126
clearInterval(JX.Resource._timer);
127
JX.Resource._timer = null;
128
}
129
},
130
131
_complete: function(uri) {
132
var list = JX.Resource._callbacks,
133
current, ii;
134
135
delete JX.Resource._loading[uri];
136
JX.Resource._loaded[uri] = true;
137
138
var errors = [];
139
for (ii = 0; ii < list.length; ii++) {
140
current = list[ii];
141
delete current.resources[uri];
142
if (!JX.Resource._hasResources(current.resources)) {
143
try {
144
current.callback();
145
} catch (error) {
146
errors.push(error);
147
}
148
list.splice(ii--, 1);
149
}
150
}
151
152
for (var jj = 0; jj < errors.length; jj++) {
153
JX.log(errors[jj]);
154
}
155
156
if (errors.length) {
157
throw errors[0];
158
}
159
},
160
161
_hasResources: function(resources) {
162
for (var hasResources in resources) {
163
return true;
164
}
165
return false;
166
}
167
168
},
169
170
initialize: function() {
171
var list = JX.$A(document.getElementsByTagName('link')),
172
ii = list.length,
173
node;
174
while ((node = list[--ii])) {
175
if (node.type == 'text/css' && node.href) {
176
JX.Resource._loaded[(new JX.URI(node.href)).toString()] = true;
177
}
178
}
179
180
list = JX.$A(document.getElementsByTagName('script'));
181
ii = list.length;
182
while ((node = list[--ii])) {
183
if (node.type == 'text/javascript' && node.src) {
184
JX.Resource._loaded[(new JX.URI(node.src)).toString()] = true;
185
}
186
}
187
}
188
189
});
190
191