text.js 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. define(["./_base/kernel", "require", "./has", "./has!host-browser?./request"], function(dojo, require, has, request){
  2. // module:
  3. // dojo/text
  4. var getText;
  5. if(has("host-browser")){
  6. getText= function(url, sync, load){
  7. request(url, {sync:!!sync, headers: { 'X-Requested-With': null } }).then(load);
  8. };
  9. }else{
  10. // Path for node.js and rhino, to load from local file system.
  11. // TODO: use node.js native methods rather than depending on a require.getText() method to exist.
  12. if(require.getText){
  13. getText= require.getText;
  14. }else{
  15. console.error("dojo/text plugin failed to load because loader does not support getText");
  16. }
  17. }
  18. var
  19. theCache = {},
  20. strip= function(text){
  21. //Strips <?xml ...?> declarations so that external SVG and XML
  22. //documents can be added to a document without worry. Also, if the string
  23. //is an HTML document, only the part inside the body tag is returned.
  24. if(text){
  25. text= text.replace(/^\s*<\?xml(\s)+version=[\'\"](\d)*.(\d)*[\'\"](\s)*\?>/im, "");
  26. var matches= text.match(/<body[^>]*>\s*([\s\S]+)\s*<\/body>/im);
  27. if(matches){
  28. text= matches[1];
  29. }
  30. }else{
  31. text = "";
  32. }
  33. return text;
  34. },
  35. notFound = {},
  36. pending = {};
  37. dojo.cache = function(/*String||Object*/module, /*String*/url, /*String||Object?*/value){
  38. // summary:
  39. // A getter and setter for storing the string content associated with the
  40. // module and url arguments.
  41. // description:
  42. // If module is a string that contains slashes, then it is interpretted as a fully
  43. // resolved path (typically a result returned by require.toUrl), and url should not be
  44. // provided. This is the preferred signature. If module is a string that does not
  45. // contain slashes, then url must also be provided and module and url are used to
  46. // call `dojo.moduleUrl()` to generate a module URL. This signature is deprecated.
  47. // If value is specified, the cache value for the moduleUrl will be set to
  48. // that value. Otherwise, dojo.cache will fetch the moduleUrl and store it
  49. // in its internal cache and return that cached value for the URL. To clear
  50. // a cache value pass null for value. Since XMLHttpRequest (XHR) is used to fetch the
  51. // the URL contents, only modules on the same domain of the page can use this capability.
  52. // The build system can inline the cache values though, to allow for xdomain hosting.
  53. // module: String||Object
  54. // If a String with slashes, a fully resolved path; if a String without slashes, the
  55. // module name to use for the base part of the URL, similar to module argument
  56. // to `dojo.moduleUrl`. If an Object, something that has a .toString() method that
  57. // generates a valid path for the cache item. For example, a dojo._Url object.
  58. // url: String
  59. // The rest of the path to append to the path derived from the module argument. If
  60. // module is an object, then this second argument should be the "value" argument instead.
  61. // value: String||Object?
  62. // If a String, the value to use in the cache for the module/url combination.
  63. // If an Object, it can have two properties: value and sanitize. The value property
  64. // should be the value to use in the cache, and sanitize can be set to true or false,
  65. // to indicate if XML declarations should be removed from the value and if the HTML
  66. // inside a body tag in the value should be extracted as the real value. The value argument
  67. // or the value property on the value argument are usually only used by the build system
  68. // as it inlines cache content.
  69. // example:
  70. // To ask dojo.cache to fetch content and store it in the cache (the dojo["cache"] style
  71. // of call is used to avoid an issue with the build system erroneously trying to intern
  72. // this example. To get the build system to intern your dojo.cache calls, use the
  73. // "dojo.cache" style of call):
  74. // | //If template.html contains "<h1>Hello</h1>" that will be
  75. // | //the value for the text variable.
  76. // | //Note: This is pre-AMD, deprecated syntax
  77. // | var text = dojo["cache"]("my.module", "template.html");
  78. // example:
  79. // To ask dojo.cache to fetch content and store it in the cache, and sanitize the input
  80. // (the dojo["cache"] style of call is used to avoid an issue with the build system
  81. // erroneously trying to intern this example. To get the build system to intern your
  82. // dojo.cache calls, use the "dojo.cache" style of call):
  83. // | //If template.html contains "<html><body><h1>Hello</h1></body></html>", the
  84. // | //text variable will contain just "<h1>Hello</h1>".
  85. // | //Note: This is pre-AMD, deprecated syntax
  86. // | var text = dojo["cache"]("my.module", "template.html", {sanitize: true});
  87. // example:
  88. // Same example as previous, but demonstrates how an object can be passed in as
  89. // the first argument, then the value argument can then be the second argument.
  90. // | //If template.html contains "<html><body><h1>Hello</h1></body></html>", the
  91. // | //text variable will contain just "<h1>Hello</h1>".
  92. // | //Note: This is pre-AMD, deprecated syntax
  93. // | var text = dojo["cache"](new dojo._Url("my/module/template.html"), {sanitize: true});
  94. // * (string string [value]) => (module, url, value)
  95. // * (object [value]) => (module, value), url defaults to ""
  96. //
  97. // * if module is an object, then it must be convertable to a string
  98. // * (module, url) module + (url ? ("/" + url) : "") must be a legal argument to require.toUrl
  99. // * value may be a string or an object; if an object then may have the properties "value" and/or "sanitize"
  100. var key;
  101. if(typeof module=="string"){
  102. if(/\//.test(module)){
  103. // module is a version 1.7+ resolved path
  104. key = module;
  105. value = url;
  106. }else{
  107. // module is a version 1.6- argument to dojo.moduleUrl
  108. key = require.toUrl(module.replace(/\./g, "/") + (url ? ("/" + url) : ""));
  109. }
  110. }else{
  111. key = module + "";
  112. value = url;
  113. }
  114. var
  115. val = (value != undefined && typeof value != "string") ? value.value : value,
  116. sanitize = value && value.sanitize;
  117. if(typeof val == "string"){
  118. //We have a string, set cache value
  119. theCache[key] = val;
  120. return sanitize ? strip(val) : val;
  121. }else if(val === null){
  122. //Remove cached value
  123. delete theCache[key];
  124. return null;
  125. }else{
  126. //Allow cache values to be empty strings. If key property does
  127. //not exist, fetch it.
  128. if(!(key in theCache)){
  129. getText(key, true, function(text){
  130. theCache[key]= text;
  131. });
  132. }
  133. return sanitize ? strip(theCache[key]) : theCache[key];
  134. }
  135. };
  136. return {
  137. // summary:
  138. // This module implements the dojo/text! plugin and the dojo.cache API.
  139. // description:
  140. // We choose to include our own plugin to leverage functionality already contained in dojo
  141. // and thereby reduce the size of the plugin compared to various foreign loader implementations.
  142. // Also, this allows foreign AMD loaders to be used without their plugins.
  143. //
  144. // CAUTION: this module is designed to optionally function synchronously to support the dojo v1.x synchronous
  145. // loader. This feature is outside the scope of the CommonJS plugins specification.
  146. // the dojo/text caches it's own resources because of dojo.cache
  147. dynamic: true,
  148. normalize: function(id, toAbsMid){
  149. // id is something like (path may be relative):
  150. //
  151. // "path/to/text.html"
  152. // "path/to/text.html!strip"
  153. var parts= id.split("!"),
  154. url= parts[0];
  155. return (/^\./.test(url) ? toAbsMid(url) : url) + (parts[1] ? "!" + parts[1] : "");
  156. },
  157. load: function(id, require, load){
  158. // id: String
  159. // Path to the resource.
  160. // require: Function
  161. // Object that include the function toUrl with given id returns a valid URL from which to load the text.
  162. // load: Function
  163. // Callback function which will be called, when the loading finished.
  164. // id is something like (path is always absolute):
  165. //
  166. // "path/to/text.html"
  167. // "path/to/text.html!strip"
  168. var
  169. parts= id.split("!"),
  170. stripFlag= parts.length>1,
  171. absMid= parts[0],
  172. url = require.toUrl(parts[0]),
  173. requireCacheUrl = "url:" + url,
  174. text = notFound,
  175. finish = function(text){
  176. load(stripFlag ? strip(text) : text);
  177. };
  178. if(absMid in theCache){
  179. text = theCache[absMid];
  180. }else if(require.cache && requireCacheUrl in require.cache){
  181. text = require.cache[requireCacheUrl];
  182. }else if(url in theCache){
  183. text = theCache[url];
  184. }
  185. if(text===notFound){
  186. if(pending[url]){
  187. pending[url].push(finish);
  188. }else{
  189. var pendingList = pending[url] = [finish];
  190. getText(url, !require.async, function(text){
  191. theCache[absMid]= theCache[url]= text;
  192. for(var i = 0; i<pendingList.length;){
  193. pendingList[i++](text);
  194. }
  195. delete pending[url];
  196. });
  197. }
  198. }else{
  199. finish(text);
  200. }
  201. }
  202. };
  203. });