load-script.js.es6 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. import { ajax } from 'wizard/lib/ajax';
  2. const _loaded = {};
  3. const _loading = {};
  4. function loadWithTag(path, cb) {
  5. const head = document.getElementsByTagName('head')[0];
  6. let finished = false;
  7. let s = document.createElement('script');
  8. s.src = path;
  9. if (Ember.Test) {
  10. Ember.Test.registerWaiter(() => finished);
  11. }
  12. head.appendChild(s);
  13. s.onload = s.onreadystatechange = function(_, abort) {
  14. finished = true;
  15. if (abort || !s.readyState || s.readyState === "loaded" || s.readyState === "complete") {
  16. s = s.onload = s.onreadystatechange = null;
  17. if (!abort) {
  18. Ember.run(null, cb);
  19. }
  20. }
  21. };
  22. }
  23. export function loadCSS(url) {
  24. return loadScript(url, { css: true });
  25. }
  26. export default function loadScript(url, opts) {
  27. // TODO: Remove this once plugins have been updated not to use it:
  28. if (url === "defer/html-sanitizer-bundle") { return Ember.RSVP.Promise.resolve(); }
  29. opts = opts || {};
  30. $('script').each((i, tag) => {
  31. const src = tag.getAttribute('src');
  32. if (src && (opts.scriptTag || src !== url)) {
  33. _loaded[tag.getAttribute('src')] = true;
  34. }
  35. });
  36. return new Ember.RSVP.Promise(function(resolve) {
  37. url = Discourse.getURL(url);
  38. // If we already loaded this url
  39. if (_loaded[url]) { return resolve(); }
  40. if (_loading[url]) { return _loading[url].then(resolve);}
  41. let done;
  42. _loading[url] = new Ember.RSVP.Promise(function(_done){
  43. done = _done;
  44. });
  45. _loading[url].then(function(){
  46. delete _loading[url];
  47. });
  48. const cb = function(data) {
  49. if (opts && opts.css) {
  50. $("head").append("<style>" + data + "</style>");
  51. }
  52. done();
  53. resolve();
  54. _loaded[url] = true;
  55. };
  56. let cdnUrl = url;
  57. // Scripts should always load from CDN
  58. // CSS is type text, to accept it from a CDN we would need to handle CORS
  59. if (!opts.css && Discourse.CDN && url[0] === "/" && url[1] !== "/") {
  60. cdnUrl = Discourse.CDN.replace(/\/$/,"") + url;
  61. }
  62. // Some javascript depends on the path of where it is loaded (ace editor)
  63. // to dynamically load more JS. In that case, add the `scriptTag: true`
  64. // option.
  65. if (opts.scriptTag) {
  66. if (Ember.testing) {
  67. throw `In test mode scripts cannot be loaded async ${cdnUrl}`;
  68. }
  69. loadWithTag(cdnUrl, cb);
  70. } else {
  71. ajax({url: cdnUrl, dataType: opts.css ? "text": "script", cache: true}).then(cb);
  72. }
  73. });
  74. }