text.js 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. /**
  2. * Copyright © Magento, Inc. All rights reserved.
  3. * See COPYING.txt for license details.
  4. */
  5. /* inspired by http://github.com/requirejs/text */
  6. /*global XMLHttpRequest, XDomainRequest */
  7. define(['module'], function (module) {
  8. 'use strict';
  9. var xmlRegExp = /^\s*<\?xml(\s)+version=[\'\"](\d)*.(\d)*[\'\"](\s)*\?>/im,
  10. bodyRegExp = /<body[^>]*>\s*([\s\S]+)\s*<\/body>/im,
  11. stripReg = /!strip$/i,
  12. defaultConfig = module.config && module.config() || {};
  13. /**
  14. * Strips <?xml ...?> declarations so that external SVG and XML documents can be
  15. * added to a document without worry.
  16. * Also, if the string is an HTML document, only the part inside the body tag is returned.
  17. *
  18. * @param {String} external
  19. * @returns {String}
  20. */
  21. function stripContent(external) {
  22. var matches;
  23. if (!external) {
  24. return '';
  25. }
  26. matches = external.match(bodyRegExp);
  27. external = matches ?
  28. matches[1] :
  29. external.replace(xmlRegExp, '');
  30. return external;
  31. }
  32. /**
  33. * Checks that url match current location
  34. *
  35. * @param {String} url
  36. * @returns {Boolean}
  37. */
  38. function sameDomain(url) {
  39. var uProtocol, uHostName, uPort,
  40. xdRegExp = /^([\w:]+)?\/\/([^\/\\]+)/i,
  41. location = window.location,
  42. match = xdRegExp.exec(url);
  43. if (!match) {
  44. return true;
  45. }
  46. uProtocol = match[1];
  47. uHostName = match[2];
  48. uHostName = uHostName.split(':');
  49. uPort = uHostName[1] || '';
  50. uHostName = uHostName[0];
  51. return (!uProtocol || uProtocol === location.protocol) &&
  52. (!uHostName || uHostName.toLowerCase() === location.hostname.toLowerCase()) &&
  53. (!uPort && !uHostName || uPort === location.port);
  54. }
  55. /**
  56. * @returns {XMLHttpRequest|XDomainRequest|null}
  57. */
  58. function createRequest(url) {
  59. var xhr = new XMLHttpRequest();
  60. if (!sameDomain(url) && typeof XDomainRequest !== 'undefined') {
  61. xhr = new XDomainRequest();
  62. }
  63. return xhr;
  64. }
  65. /**
  66. * XHR requester. Returns value to callback.
  67. *
  68. * @param {String} url
  69. * @param {Function} callback
  70. * @param {Function} fail
  71. * @param {Object} headers
  72. */
  73. function getContent(url, callback, fail, headers) {
  74. var xhr = createRequest(url),
  75. header;
  76. xhr.open('GET', url);
  77. /*eslint-disable max-depth */
  78. if ('setRequestHeader' in xhr && headers) {
  79. for (header in headers) {
  80. if (headers.hasOwnProperty(header)) {
  81. xhr.setRequestHeader(header.toLowerCase(), headers[header]);
  82. }
  83. }
  84. }
  85. /**
  86. * @inheritdoc
  87. */
  88. xhr.onreadystatechange = function () {
  89. var status, err;
  90. //Do not explicitly handle errors, those should be
  91. //visible via console output in the browser.
  92. if (xhr.readyState === 4) {
  93. status = xhr.status || 0;
  94. if (status > 399 && status < 600) {
  95. //An http 4xx or 5xx error. Signal an error.
  96. err = new Error(url + ' HTTP status: ' + status);
  97. err.xhr = xhr;
  98. if (fail) {
  99. fail(err);
  100. }
  101. } else {
  102. callback(xhr.responseText);
  103. if (defaultConfig.onXhrComplete) {
  104. defaultConfig.onXhrComplete(xhr, url);
  105. }
  106. }
  107. }
  108. };
  109. /*eslint-enable max-depth */
  110. if (defaultConfig.onXhr) {
  111. defaultConfig.onXhr(xhr, url);
  112. }
  113. xhr.send();
  114. }
  115. /**
  116. * Main method used by RequireJs.
  117. *
  118. * @param {String} name - has format: some.module.filext!strip
  119. * @param {Function} req
  120. * @param {Function|undefined} onLoad
  121. */
  122. function loadContent(name, req, onLoad) {
  123. var toStrip = stripReg.test(name),
  124. url = req.toUrl(name.replace(stripReg, '')),
  125. headers = defaultConfig.headers;
  126. getContent(url, function (content) {
  127. content = toStrip ? stripContent(content) : content;
  128. onLoad(content);
  129. }, onLoad.error, headers);
  130. }
  131. return {
  132. load: loadContent,
  133. get: getContent
  134. };
  135. });