mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-25 00:02:41 +01:00
5efe7fb4c1
Summary: Ref T13559. To allow the client to make correct decisions about what buttons mean, track an explicit "Committed" content state. This is the last version of the comment that has been saved on the server, and does not exist if the comment has never been saved. Test Plan: Created comments, etc. See followups. Maniphest Tasks: T13559 Differential Revision: https://secure.phabricator.com/D21651
189 lines
4.9 KiB
JavaScript
189 lines
4.9 KiB
JavaScript
/**
|
|
* @provides javelin-resource
|
|
* @requires javelin-util
|
|
* javelin-uri
|
|
* javelin-install
|
|
*
|
|
* @javelin
|
|
*/
|
|
|
|
JX.install('Resource', {
|
|
|
|
statics: {
|
|
|
|
_loading: {},
|
|
_loaded: {},
|
|
_links: [],
|
|
_callbacks: [],
|
|
|
|
/**
|
|
* Loads one or many static resources (JavaScript or CSS) and executes a
|
|
* callback once these resources have finished loading.
|
|
*
|
|
* @param string|array static resource or list of resources to be loaded
|
|
* @param function callback when resources have finished loading
|
|
*/
|
|
load: function(list, callback) {
|
|
var resources = {},
|
|
uri, resource, path;
|
|
|
|
list = JX.$AX(list);
|
|
|
|
// In the event there are no resources to wait on, call the callback and
|
|
// exit. NOTE: it's better to do this check outside this function and not
|
|
// call through JX.Resource, but it's not always easy/possible to do so
|
|
if (!list.length) {
|
|
setTimeout(callback, 0);
|
|
return;
|
|
}
|
|
|
|
for (var ii = 0; ii < list.length; ii++) {
|
|
uri = new JX.URI(list[ii]);
|
|
resource = uri.toString();
|
|
path = uri.getPath();
|
|
resources[resource] = true;
|
|
|
|
if (JX.Resource._loaded[resource]) {
|
|
setTimeout(JX.bind(JX.Resource, JX.Resource._complete, resource), 0);
|
|
} else if (!JX.Resource._loading[resource]) {
|
|
JX.Resource._loading[resource] = true;
|
|
if (path.indexOf('.css') == path.length - 4) {
|
|
JX.Resource._loadCSS(resource);
|
|
} else {
|
|
JX.Resource._loadJS(resource);
|
|
}
|
|
}
|
|
}
|
|
|
|
JX.Resource._callbacks.push({
|
|
resources: resources,
|
|
callback: callback
|
|
});
|
|
},
|
|
|
|
_loadJS: function(uri) {
|
|
var script = document.createElement('script');
|
|
var load_callback = function() {
|
|
JX.Resource._complete(uri);
|
|
};
|
|
var error_callback = function() {
|
|
JX.$E('Resource: JS file download failure: ' + uri);
|
|
};
|
|
|
|
JX.copy(script, {
|
|
type: 'text/javascript',
|
|
src: uri
|
|
});
|
|
|
|
script.onload = load_callback;
|
|
script.onerror = error_callback;
|
|
script.onreadystatechange = function() {
|
|
var state = this.readyState;
|
|
if (state == 'complete' || state == 'loaded') {
|
|
load_callback();
|
|
}
|
|
};
|
|
document.getElementsByTagName('head')[0].appendChild(script);
|
|
},
|
|
|
|
_loadCSS: function(uri) {
|
|
var link = JX.copy(document.createElement('link'), {
|
|
type: 'text/css',
|
|
rel: 'stylesheet',
|
|
href: uri,
|
|
'data-href': uri // don't trust href
|
|
});
|
|
document.getElementsByTagName('head')[0].appendChild(link);
|
|
|
|
JX.Resource._links.push(link);
|
|
if (!JX.Resource._timer) {
|
|
JX.Resource._timer = setInterval(JX.Resource._poll, 20);
|
|
}
|
|
},
|
|
|
|
_poll: function() {
|
|
var sheets = document.styleSheets,
|
|
ii = sheets.length,
|
|
links = JX.Resource._links;
|
|
|
|
// Cross Origin CSS loading
|
|
// http://yearofmoo.com/2011/03/cross-browser-stylesheet-preloading/
|
|
while (ii--) {
|
|
var link = sheets[ii],
|
|
owner = link.ownerNode || link.owningElement,
|
|
jj = links.length;
|
|
if (owner) {
|
|
while (jj--) {
|
|
if (owner == links[jj]) {
|
|
JX.Resource._complete(links[jj]['data-href']);
|
|
links.splice(jj, 1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!links.length) {
|
|
clearInterval(JX.Resource._timer);
|
|
JX.Resource._timer = null;
|
|
}
|
|
},
|
|
|
|
_complete: function(uri) {
|
|
var list = JX.Resource._callbacks,
|
|
current, ii;
|
|
|
|
delete JX.Resource._loading[uri];
|
|
JX.Resource._loaded[uri] = true;
|
|
|
|
var errors = [];
|
|
for (ii = 0; ii < list.length; ii++) {
|
|
current = list[ii];
|
|
delete current.resources[uri];
|
|
if (!JX.Resource._hasResources(current.resources)) {
|
|
try {
|
|
current.callback();
|
|
} catch (error) {
|
|
errors.push(error);
|
|
}
|
|
list.splice(ii--, 1);
|
|
}
|
|
}
|
|
|
|
for (var jj = 0; jj < errors.length; jj++) {
|
|
JX.log(errors[jj]);
|
|
}
|
|
|
|
if (errors.length) {
|
|
throw errors[0];
|
|
}
|
|
},
|
|
|
|
_hasResources: function(resources) {
|
|
for (var hasResources in resources) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
},
|
|
|
|
initialize: function() {
|
|
var list = JX.$A(document.getElementsByTagName('link')),
|
|
ii = list.length,
|
|
node;
|
|
while ((node = list[--ii])) {
|
|
if (node.type == 'text/css' && node.href) {
|
|
JX.Resource._loaded[(new JX.URI(node.href)).toString()] = true;
|
|
}
|
|
}
|
|
|
|
list = JX.$A(document.getElementsByTagName('script'));
|
|
ii = list.length;
|
|
while ((node = list[--ii])) {
|
|
if (node.type == 'text/javascript' && node.src) {
|
|
JX.Resource._loaded[(new JX.URI(node.src)).toString()] = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
});
|