script.js 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. /* Copyright (c) 2017 Environmental Systems Research Institute, Inc.
  2. * Apache-2.0 */
  3. import { loadCss } from './utils/css';
  4. import utils from './utils/index';
  5. import { getCdnUrl } from './utils/url';
  6. var defaultOptions = {};
  7. function createScript(url) {
  8. var script = document.createElement('script');
  9. script.type = 'text/javascript';
  10. script.src = url;
  11. script.setAttribute('data-esri-loader', 'loading');
  12. return script;
  13. }
  14. // add a one-time load handler to script
  15. // and optionally add a one time error handler as well
  16. function handleScriptLoad(script, callback, errback) {
  17. var onScriptError;
  18. if (errback) {
  19. // set up an error handler as well
  20. onScriptError = handleScriptError(script, errback);
  21. }
  22. var onScriptLoad = function () {
  23. // pass the script to the callback
  24. callback(script);
  25. // remove this event listener
  26. script.removeEventListener('load', onScriptLoad, false);
  27. if (onScriptError) {
  28. // remove the error listener as well
  29. script.removeEventListener('error', onScriptError, false);
  30. }
  31. };
  32. script.addEventListener('load', onScriptLoad, false);
  33. }
  34. // add a one-time error handler to the script
  35. function handleScriptError(script, callback) {
  36. var onScriptError = function (e) {
  37. // reject the promise and remove this event listener
  38. callback(e.error || new Error("There was an error attempting to load " + script.src));
  39. // remove this event listener
  40. script.removeEventListener('error', onScriptError, false);
  41. };
  42. script.addEventListener('error', onScriptError, false);
  43. return onScriptError;
  44. }
  45. // allow the user to configure default script options rather than passing options to `loadModules` each time
  46. export function setDefaultOptions(options) {
  47. if (options === void 0) { options = {}; }
  48. defaultOptions = options;
  49. }
  50. // get the script injected by this library
  51. export function getScript() {
  52. return document.querySelector('script[data-esri-loader]');
  53. }
  54. // has ArcGIS API been loaded on the page yet?
  55. export function isLoaded() {
  56. var globalRequire = window['require'];
  57. // .on() ensures that it's Dojo's AMD loader
  58. return globalRequire && globalRequire.on;
  59. }
  60. // load the ArcGIS API on the page
  61. export function loadScript(options) {
  62. if (options === void 0) { options = {}; }
  63. // we would have liked to use spread like { ...defaultOptions, ...options }
  64. // but TS would inject a polyfill that would require use to configure rollup w content: 'window'
  65. // if we have another occasion to use spread, let's do that and replace this for...in
  66. var opts = {};
  67. [defaultOptions, options].forEach(function (obj) {
  68. for (var prop in obj) {
  69. if (Object.prototype.hasOwnProperty.call(obj, prop)) {
  70. opts[prop] = obj[prop];
  71. }
  72. }
  73. });
  74. // URL to load
  75. var version = opts.version;
  76. var url = opts.url || getCdnUrl(version);
  77. return new utils.Promise(function (resolve, reject) {
  78. var script = getScript();
  79. if (script) {
  80. // the API is already loaded or in the process of loading...
  81. // NOTE: have to test against scr attribute value, not script.src
  82. // b/c the latter will return the full url for relative paths
  83. var src = script.getAttribute('src');
  84. if (src !== url) {
  85. // potentially trying to load a different version of the API
  86. reject(new Error("The ArcGIS API for JavaScript is already loaded (" + src + ")."));
  87. }
  88. else {
  89. if (isLoaded()) {
  90. // the script has already successfully loaded
  91. resolve(script);
  92. }
  93. else {
  94. // wait for the script to load and then resolve
  95. handleScriptLoad(script, resolve, reject);
  96. }
  97. }
  98. }
  99. else {
  100. if (isLoaded()) {
  101. // the API has been loaded by some other means
  102. // potentially trying to load a different version of the API
  103. reject(new Error("The ArcGIS API for JavaScript is already loaded."));
  104. }
  105. else {
  106. // this is the first time attempting to load the API
  107. var css = opts.css;
  108. if (css) {
  109. var useVersion = css === true;
  110. // load the css before loading the script
  111. loadCss(useVersion ? version : css, opts.insertCssBefore);
  112. }
  113. // create a script object whose source points to the API
  114. script = createScript(url);
  115. // _currentUrl = url;
  116. // once the script is loaded...
  117. handleScriptLoad(script, function () {
  118. // update the status of the script
  119. script.setAttribute('data-esri-loader', 'loaded');
  120. // return the script
  121. resolve(script);
  122. }, reject);
  123. // load the script
  124. document.body.appendChild(script);
  125. }
  126. }
  127. });
  128. }