2016-07-05 19:30:14 +03:00
|
|
|
import RSVP from 'rsvp';
|
2017-10-30 12:38:01 +03:00
|
|
|
import Service, {inject as service} from '@ember/service';
|
2022-02-03 01:11:11 +03:00
|
|
|
import classic from 'ember-classic-decorator';
|
2018-05-03 19:52:39 +03:00
|
|
|
import config from 'ghost-admin/config/environment';
|
2016-07-05 19:30:14 +03:00
|
|
|
|
2022-02-03 01:11:11 +03:00
|
|
|
@classic
|
|
|
|
export default class LazyLoaderService extends Service {
|
2022-02-03 22:04:43 +03:00
|
|
|
@service ajax;
|
|
|
|
@service ghostPaths;
|
2016-07-05 19:30:14 +03:00
|
|
|
|
|
|
|
// This is needed so we can disable it in unit tests
|
2022-02-03 01:11:11 +03:00
|
|
|
testing = undefined;
|
2016-07-05 19:30:14 +03:00
|
|
|
|
2022-02-03 01:11:11 +03:00
|
|
|
scriptPromises = null;
|
2017-11-24 21:53:19 +03:00
|
|
|
|
|
|
|
init() {
|
2022-02-03 01:11:11 +03:00
|
|
|
super.init(...arguments);
|
2017-11-24 21:53:19 +03:00
|
|
|
this.scriptPromises = {};
|
2018-01-02 13:19:59 +03:00
|
|
|
|
|
|
|
if (this.testing === undefined) {
|
2018-05-03 19:52:39 +03:00
|
|
|
this.testing = config.environment === 'test';
|
2018-01-02 13:19:59 +03:00
|
|
|
}
|
2022-02-03 01:11:11 +03:00
|
|
|
}
|
2016-07-05 19:30:14 +03:00
|
|
|
|
|
|
|
loadScript(key, url) {
|
2019-02-12 00:07:51 +03:00
|
|
|
if (this.testing) {
|
2016-07-05 19:30:14 +03:00
|
|
|
return RSVP.resolve();
|
|
|
|
}
|
|
|
|
|
2019-02-12 00:07:51 +03:00
|
|
|
if (this.scriptPromises[key]) {
|
|
|
|
return this.scriptPromises[key];
|
2016-07-05 19:30:14 +03:00
|
|
|
}
|
|
|
|
|
2019-02-12 00:07:51 +03:00
|
|
|
let scriptPromise = new RSVP.Promise((resolve, reject) => {
|
|
|
|
let script = document.createElement('script');
|
|
|
|
script.type = 'text/javascript';
|
|
|
|
script.async = true;
|
2023-07-17 14:44:50 +03:00
|
|
|
script.src = `${config.cdnUrl ? '' : this.ghostPaths.adminRoot}${url}`;
|
2019-02-12 00:07:51 +03:00
|
|
|
|
|
|
|
let el = document.getElementsByTagName('script')[0];
|
|
|
|
el.parentNode.insertBefore(script, el);
|
|
|
|
|
|
|
|
script.addEventListener('load', () => {
|
|
|
|
resolve();
|
|
|
|
});
|
|
|
|
|
|
|
|
script.addEventListener('error', () => {
|
|
|
|
reject(new Error(`${url} failed to load`));
|
|
|
|
});
|
2016-07-05 19:30:14 +03:00
|
|
|
});
|
|
|
|
|
2019-02-12 00:07:51 +03:00
|
|
|
this.scriptPromises[key] = scriptPromise;
|
2016-07-05 19:30:14 +03:00
|
|
|
|
|
|
|
return scriptPromise;
|
2022-02-03 01:11:11 +03:00
|
|
|
}
|
2016-07-05 19:30:14 +03:00
|
|
|
|
2017-03-03 19:14:33 +03:00
|
|
|
loadStyle(key, url, alternate = false) {
|
2019-02-12 00:07:51 +03:00
|
|
|
if (this.testing || document.querySelector(`#${key}-styles`)) {
|
2016-07-05 19:30:14 +03:00
|
|
|
return RSVP.resolve();
|
|
|
|
}
|
|
|
|
|
2017-03-03 19:13:22 +03:00
|
|
|
return new RSVP.Promise((resolve, reject) => {
|
|
|
|
let link = document.createElement('link');
|
|
|
|
link.id = `${key}-styles`;
|
2017-03-03 19:14:33 +03:00
|
|
|
link.rel = alternate ? 'alternate stylesheet' : 'stylesheet';
|
2023-07-17 14:44:50 +03:00
|
|
|
link.href = `${config.cdnUrl ? '' : this.ghostPaths.adminRoot}${url}`;
|
2017-03-03 19:14:33 +03:00
|
|
|
link.onload = () => {
|
2019-04-25 10:40:26 +03:00
|
|
|
link.onload = null;
|
2017-03-03 19:14:33 +03:00
|
|
|
if (alternate) {
|
|
|
|
// If stylesheet is alternate and we disable the stylesheet before injecting into the DOM,
|
|
|
|
// the onload handler never gets called. Thus, we should disable the link after it has finished loading
|
|
|
|
link.disabled = true;
|
|
|
|
}
|
|
|
|
resolve();
|
|
|
|
};
|
2017-03-03 19:13:22 +03:00
|
|
|
link.onerror = reject;
|
2017-03-03 19:14:33 +03:00
|
|
|
|
|
|
|
if (alternate) {
|
|
|
|
link.title = key;
|
|
|
|
}
|
|
|
|
|
2019-02-12 00:07:51 +03:00
|
|
|
document.querySelector('head').appendChild(link);
|
2017-03-03 19:13:22 +03:00
|
|
|
});
|
2016-07-05 19:30:14 +03:00
|
|
|
}
|
2022-02-03 01:11:11 +03:00
|
|
|
}
|