loader.js 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816
  1. /*
  2. Copyright (c) 2004-2012, The Dojo Foundation All Rights Reserved.
  3. Available via Academic Free License >= 2.1 OR the modified BSD license.
  4. see: http://dojotoolkit.org/license for details
  5. */
  6. if(!dojo._hasResource["dojo.foo"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  7. dojo._hasResource["dojo.foo"] = true;
  8. /*
  9. * loader.js - A bootstrap module. Runs before the hostenv_*.js file. Contains
  10. * all of the package loading methods.
  11. */
  12. (function(){
  13. var d = dojo, currentModule;
  14. d.mixin(d, {
  15. _loadedModules: {},
  16. _inFlightCount: 0,
  17. _hasResource: {},
  18. _modulePrefixes: {
  19. dojo: { name: "dojo", value: "." },
  20. // dojox: { name: "dojox", value: "../dojox" },
  21. // dijit: { name: "dijit", value: "../dijit" },
  22. doh: { name: "doh", value: "../util/doh" },
  23. tests: { name: "tests", value: "tests" }
  24. },
  25. _moduleHasPrefix: function(/*String*/module){
  26. // summary: checks to see if module has been established
  27. var mp = d._modulePrefixes;
  28. return !!(mp[module] && mp[module].value); // Boolean
  29. },
  30. _getModulePrefix: function(/*String*/module){
  31. // summary: gets the prefix associated with module
  32. var mp = d._modulePrefixes;
  33. if(d._moduleHasPrefix(module)){
  34. return mp[module].value; // String
  35. }
  36. return module; // String
  37. },
  38. _loadedUrls: [],
  39. //WARNING:
  40. // This variable is referenced by packages outside of bootstrap:
  41. // FloatingPane.js and undo/browser.js
  42. _postLoad: false,
  43. //Egad! Lots of test files push on this directly instead of using dojo.addOnLoad.
  44. _loaders: [],
  45. _unloaders: [],
  46. _loadNotifying: false
  47. });
  48. dojo._loadPath = function(/*String*/relpath, /*String?*/module, /*Function?*/cb){
  49. // summary:
  50. // Load a Javascript module given a relative path
  51. //
  52. // description:
  53. // Loads and interprets the script located at relpath, which is
  54. // relative to the script root directory. If the script is found but
  55. // its interpretation causes a runtime exception, that exception is
  56. // not caught by us, so the caller will see it. We return a true
  57. // value if and only if the script is found.
  58. //
  59. // relpath:
  60. // A relative path to a script (no leading '/', and typically ending
  61. // in '.js').
  62. // module:
  63. // A module whose existance to check for after loading a path. Can be
  64. // used to determine success or failure of the load.
  65. // cb:
  66. // a callback function to pass the result of evaluating the script
  67. var uri = ((relpath.charAt(0) == '/' || relpath.match(/^\w+:/)) ? "" : d.baseUrl) + relpath;
  68. try{
  69. currentModule = module;
  70. return !module ? d._loadUri(uri, cb) : d._loadUriAndCheck(uri, module, cb); // Boolean
  71. }catch(e){
  72. console.error(e);
  73. return false; // Boolean
  74. }finally{
  75. currentModule = null;
  76. }
  77. }
  78. dojo._loadUri = function(/*String*/uri, /*Function?*/cb){
  79. // summary:
  80. // Loads JavaScript from a URI
  81. // description:
  82. // Reads the contents of the URI, and evaluates the contents. This is
  83. // used to load modules as well as resource bundles. Returns true if
  84. // it succeeded. Returns false if the URI reading failed. Throws if
  85. // the evaluation throws.
  86. // uri: a uri which points at the script to be loaded
  87. // cb:
  88. // a callback function to process the result of evaluating the script
  89. // as an expression, typically used by the resource bundle loader to
  90. // load JSON-style resources
  91. if(d._loadedUrls[uri]){
  92. return true; // Boolean
  93. }
  94. d._inFlightCount++; // block addOnLoad calls that arrive while we're busy downloading
  95. var contents = d._getText(uri, true);
  96. if(contents){ // not 404, et al
  97. d._loadedUrls[uri] = true;
  98. d._loadedUrls.push(uri);
  99. if(cb){
  100. //conditional to support script-inject i18n bundle format
  101. contents = /^define\(/.test(contents) ? contents : '('+contents+')';
  102. }else{
  103. //Only do the scoping if no callback. If a callback is specified,
  104. //it is most likely the i18n bundle stuff.
  105. contents = d._scopePrefix + contents + d._scopeSuffix;
  106. }
  107. if(!d.isIE){ contents += "\r\n//@ sourceURL=" + uri; } // debugging assist for Firebug
  108. var value = d["eval"](contents);
  109. if(cb){ cb(value); }
  110. }
  111. // Check to see if we need to call _callLoaded() due to an addOnLoad() that arrived while we were busy downloading
  112. if(--d._inFlightCount == 0 && d._postLoad && d._loaders.length){
  113. // We shouldn't be allowed to get here but Firefox allows an event
  114. // (mouse, keybd, async xhrGet) to interrupt a synchronous xhrGet.
  115. // If the current script block contains multiple require() statements, then after each
  116. // require() returns, inFlightCount == 0, but we want to hold the _callLoaded() until
  117. // all require()s are done since the out-of-sequence addOnLoad() presumably needs them all.
  118. // setTimeout allows the next require() to start (if needed), and then we check this again.
  119. setTimeout(function(){
  120. // If inFlightCount > 0, then multiple require()s are running sequentially and
  121. // the next require() started after setTimeout() was executed but before we got here.
  122. if(d._inFlightCount == 0){
  123. d._callLoaded();
  124. }
  125. }, 0);
  126. }
  127. return !!contents; // Boolean: contents? true : false
  128. }
  129. // FIXME: probably need to add logging to this method
  130. dojo._loadUriAndCheck = function(/*String*/uri, /*String*/moduleName, /*Function?*/cb){
  131. // summary: calls loadUri then findModule and returns true if both succeed
  132. var ok = false;
  133. try{
  134. ok = d._loadUri(uri, cb);
  135. }catch(e){
  136. console.error("failed loading " + uri + " with error: " + e);
  137. }
  138. return !!(ok && d._loadedModules[moduleName]); // Boolean
  139. }
  140. dojo.loaded = function(){
  141. // summary:
  142. // signal fired when initial environment and package loading is
  143. // complete. You should use dojo.addOnLoad() instead of doing a
  144. // direct dojo.connect() to this method in order to handle
  145. // initialization tasks that require the environment to be
  146. // initialized. In a browser host, declarative widgets will
  147. // be constructed when this function finishes runing.
  148. d._loadNotifying = true;
  149. d._postLoad = true;
  150. var mll = d._loaders;
  151. //Clear listeners so new ones can be added
  152. //For other xdomain package loads after the initial load.
  153. d._loaders = [];
  154. for(var x = 0; x < mll.length; x++){
  155. mll[x]();
  156. }
  157. d._loadNotifying = false;
  158. //Make sure nothing else got added to the onload queue
  159. //after this first run. If something did, and we are not waiting for any
  160. //more inflight resources, run again.
  161. if(d._postLoad && d._inFlightCount == 0 && mll.length){
  162. d._callLoaded();
  163. }
  164. }
  165. dojo.unloaded = function(){
  166. // summary:
  167. // signal fired by impending environment destruction. You should use
  168. // dojo.addOnUnload() instead of doing a direct dojo.connect() to this
  169. // method to perform page/application cleanup methods. See
  170. // dojo.addOnUnload for more info.
  171. var mll = d._unloaders;
  172. while(mll.length){
  173. (mll.pop())();
  174. }
  175. }
  176. d._onto = function(arr, obj, fn){
  177. if(!fn){
  178. arr.push(obj);
  179. }else if(fn){
  180. var func = (typeof fn == "string") ? obj[fn] : fn;
  181. arr.push(function(){ func.call(obj); });
  182. }
  183. }
  184. dojo.ready = dojo.addOnLoad = function(/*Object*/obj, /*String|Function?*/functionName){
  185. // summary:
  186. // Registers a function to be triggered after the DOM and dojo.require() calls
  187. // have finished loading.
  188. //
  189. // description:
  190. // Registers a function to be triggered after the DOM has finished
  191. // loading and `dojo.require` modules have loaded. Widgets declared in markup
  192. // have been instantiated if `djConfig.parseOnLoad` is true when this fires.
  193. //
  194. // Images and CSS files may or may not have finished downloading when
  195. // the specified function is called. (Note that widgets' CSS and HTML
  196. // code is guaranteed to be downloaded before said widgets are
  197. // instantiated, though including css resouces BEFORE any script elements
  198. // is highly recommended).
  199. //
  200. // example:
  201. // Register an anonymous function to run when everything is ready
  202. // | dojo.addOnLoad(function(){ doStuff(); });
  203. //
  204. // example:
  205. // Register a function to run when everything is ready by pointer:
  206. // | var init = function(){ doStuff(); }
  207. // | dojo.addOnLoad(init);
  208. //
  209. // example:
  210. // Register a function to run scoped to `object`, either by name or anonymously:
  211. // | dojo.addOnLoad(object, "functionName");
  212. // | dojo.addOnLoad(object, function(){ doStuff(); });
  213. d._onto(d._loaders, obj, functionName);
  214. //Added for xdomain loading. dojo.addOnLoad is used to
  215. //indicate callbacks after doing some dojo.require() statements.
  216. //In the xdomain case, if all the requires are loaded (after initial
  217. //page load), then immediately call any listeners.
  218. if(d._postLoad && d._inFlightCount == 0 && !d._loadNotifying){
  219. d._callLoaded();
  220. }
  221. }
  222. //Support calling dojo.addOnLoad via djConfig.addOnLoad. Support all the
  223. //call permutations of dojo.addOnLoad. Mainly useful when dojo is added
  224. //to the page after the page has loaded.
  225. var dca = d.config.addOnLoad;
  226. if(dca){
  227. d.addOnLoad[(dca instanceof Array ? "apply" : "call")](d, dca);
  228. }
  229. dojo._modulesLoaded = function(){
  230. if(d._postLoad){ return; }
  231. if(d._inFlightCount > 0){
  232. console.warn("files still in flight!");
  233. return;
  234. }
  235. d._callLoaded();
  236. }
  237. dojo._callLoaded = function(){
  238. // The "object" check is for IE, and the other opera check fixes an
  239. // issue in Opera where it could not find the body element in some
  240. // widget test cases. For 0.9, maybe route all browsers through the
  241. // setTimeout (need protection still for non-browser environments
  242. // though). This might also help the issue with FF 2.0 and freezing
  243. // issues where we try to do sync xhr while background css images are
  244. // being loaded (trac #2572)? Consider for 0.9.
  245. if(typeof setTimeout == "object" || (d.config.useXDomain && d.isOpera)){
  246. setTimeout(
  247. d.isAIR ? function(){ d.loaded(); } : d._scopeName + ".loaded();",
  248. 0);
  249. }else{
  250. d.loaded();
  251. }
  252. }
  253. dojo._getModuleSymbols = function(/*String*/modulename){
  254. // summary:
  255. // Converts a module name in dotted JS notation to an array
  256. // representing the path in the source tree
  257. var syms = modulename.split(".");
  258. for(var i = syms.length; i>0; i--){
  259. var parentModule = syms.slice(0, i).join(".");
  260. if(i == 1 && !d._moduleHasPrefix(parentModule)){
  261. // Support default module directory (sibling of dojo) for top-level modules
  262. syms[0] = "../" + syms[0];
  263. }else{
  264. var parentModulePath = d._getModulePrefix(parentModule);
  265. if(parentModulePath != parentModule){
  266. syms.splice(0, i, parentModulePath);
  267. break;
  268. }
  269. }
  270. }
  271. return syms; // Array
  272. }
  273. dojo._global_omit_module_check = false;
  274. dojo.loadInit = function(/*Function*/init){
  275. // summary:
  276. // Executes a function that needs to be executed for the loader's dojo.requireIf
  277. // resolutions to work. This is needed mostly for the xdomain loader case where
  278. // a function needs to be executed to set up the possible values for a dojo.requireIf
  279. // call.
  280. // init:
  281. // a function reference. Executed immediately.
  282. // description: This function is mainly a marker for the xdomain loader to know parts of
  283. // code that needs be executed outside the function wrappper that is placed around modules.
  284. // The init function could be executed more than once, and it should make no assumptions
  285. // on what is loaded, or what modules are available. Only the functionality in Dojo Base
  286. // is allowed to be used. Avoid using this method. For a valid use case,
  287. // see the source for dojox.gfx.
  288. init();
  289. }
  290. dojo._loadModule = dojo.require = function(/*String*/moduleName, /*Boolean?*/omitModuleCheck){
  291. // summary:
  292. // loads a Javascript module from the appropriate URI
  293. //
  294. // moduleName: String
  295. // module name to load, using periods for separators,
  296. // e.g. "dojo.date.locale". Module paths are de-referenced by dojo's
  297. // internal mapping of locations to names and are disambiguated by
  298. // longest prefix. See `dojo.registerModulePath()` for details on
  299. // registering new modules.
  300. //
  301. // omitModuleCheck: Boolean?
  302. // if `true`, omitModuleCheck skips the step of ensuring that the
  303. // loaded file actually defines the symbol it is referenced by.
  304. // For example if it called as `dojo.require("a.b.c")` and the
  305. // file located at `a/b/c.js` does not define an object `a.b.c`,
  306. // and exception will be throws whereas no exception is raised
  307. // when called as `dojo.require("a.b.c", true)`
  308. //
  309. // description:
  310. // Modules are loaded via dojo.require by using one of two loaders: the normal loader
  311. // and the xdomain loader. The xdomain loader is used when dojo was built with a
  312. // custom build that specified loader=xdomain and the module lives on a modulePath
  313. // that is a whole URL, with protocol and a domain. The versions of Dojo that are on
  314. // the Google and AOL CDNs use the xdomain loader.
  315. //
  316. // If the module is loaded via the xdomain loader, it is an asynchronous load, since
  317. // the module is added via a dynamically created script tag. This
  318. // means that dojo.require() can return before the module has loaded. However, this
  319. // should only happen in the case where you do dojo.require calls in the top-level
  320. // HTML page, or if you purposely avoid the loader checking for dojo.require
  321. // dependencies in your module by using a syntax like dojo["require"] to load the module.
  322. //
  323. // Sometimes it is useful to not have the loader detect the dojo.require calls in the
  324. // module so that you can dynamically load the modules as a result of an action on the
  325. // page, instead of right at module load time.
  326. //
  327. // Also, for script blocks in an HTML page, the loader does not pre-process them, so
  328. // it does not know to download the modules before the dojo.require calls occur.
  329. //
  330. // So, in those two cases, when you want on-the-fly module loading or for script blocks
  331. // in the HTML page, special care must be taken if the dojo.required code is loaded
  332. // asynchronously. To make sure you can execute code that depends on the dojo.required
  333. // modules, be sure to add the code that depends on the modules in a dojo.addOnLoad()
  334. // callback. dojo.addOnLoad waits for all outstanding modules to finish loading before
  335. // executing.
  336. //
  337. // This type of syntax works with both xdomain and normal loaders, so it is good
  338. // practice to always use this idiom for on-the-fly code loading and in HTML script
  339. // blocks. If at some point you change loaders and where the code is loaded from,
  340. // it will all still work.
  341. //
  342. // More on how dojo.require
  343. // `dojo.require("A.B")` first checks to see if symbol A.B is
  344. // defined. If it is, it is simply returned (nothing to do).
  345. //
  346. // If it is not defined, it will look for `A/B.js` in the script root
  347. // directory.
  348. //
  349. // `dojo.require` throws an exception if it cannot find a file
  350. // to load, or if the symbol `A.B` is not defined after loading.
  351. //
  352. // It returns the object `A.B`, but note the caveats above about on-the-fly loading and
  353. // HTML script blocks when the xdomain loader is loading a module.
  354. //
  355. // `dojo.require()` does nothing about importing symbols into
  356. // the current namespace. It is presumed that the caller will
  357. // take care of that.
  358. //
  359. // example:
  360. // To use dojo.require in conjunction with dojo.ready:
  361. //
  362. // | dojo.require("foo");
  363. // | dojo.require("bar");
  364. // | dojo.addOnLoad(function(){
  365. // | //you can now safely do something with foo and bar
  366. // | });
  367. //
  368. // example:
  369. // For example, to import all symbols into a local block, you might write:
  370. //
  371. // | with (dojo.require("A.B")) {
  372. // | ...
  373. // | }
  374. //
  375. // And to import just the leaf symbol to a local variable:
  376. //
  377. // | var B = dojo.require("A.B");
  378. // | ...
  379. //
  380. // returns:
  381. // the required namespace object
  382. omitModuleCheck = d._global_omit_module_check || omitModuleCheck;
  383. //Check if it is already loaded.
  384. var module = d._loadedModules[moduleName];
  385. if(module){
  386. return module;
  387. }
  388. // convert periods to slashes
  389. var relpath = d._getModuleSymbols(moduleName).join("/") + '.js';
  390. var modArg = !omitModuleCheck ? moduleName : null;
  391. var ok = d._loadPath(relpath, modArg);
  392. if(!ok && !omitModuleCheck){
  393. throw new Error("Could not load '" + moduleName + "'; last tried '" + relpath + "'");
  394. }
  395. // check that the symbol was defined
  396. // Don't bother if we're doing xdomain (asynchronous) loading.
  397. if(!omitModuleCheck && !d._isXDomain){
  398. // pass in false so we can give better error
  399. module = d._loadedModules[moduleName];
  400. if(!module){
  401. throw new Error("symbol '" + moduleName + "' is not defined after loading '" + relpath + "'");
  402. }
  403. }
  404. return module;
  405. }
  406. dojo.provide = function(/*String*/ resourceName){
  407. // summary:
  408. // Register a resource with the package system. Works in conjunction with `dojo.require`
  409. //
  410. // description:
  411. // Each javascript source file is called a resource. When a
  412. // resource is loaded by the browser, `dojo.provide()` registers
  413. // that it has been loaded.
  414. //
  415. // Each javascript source file must have at least one
  416. // `dojo.provide()` call at the top of the file, corresponding to
  417. // the file name. For example, `js/dojo/foo.js` must have
  418. // `dojo.provide("dojo.foo");` before any calls to
  419. // `dojo.require()` are made.
  420. //
  421. // For backwards compatibility reasons, in addition to registering
  422. // the resource, `dojo.provide()` also ensures that the javascript
  423. // object for the module exists. For example,
  424. // `dojo.provide("dojox.data.FlickrStore")`, in addition to
  425. // registering that `FlickrStore.js` is a resource for the
  426. // `dojox.data` module, will ensure that the `dojox.data`
  427. // javascript object exists, so that calls like
  428. // `dojo.data.foo = function(){ ... }` don't fail.
  429. //
  430. // In the case of a build where multiple javascript source files
  431. // are combined into one bigger file (similar to a .lib or .jar
  432. // file), that file may contain multiple dojo.provide() calls, to
  433. // note that it includes multiple resources.
  434. //
  435. // resourceName: String
  436. // A dot-sperated string identifying a resource.
  437. //
  438. // example:
  439. // Safely create a `my` object, and make dojo.require("my.CustomModule") work
  440. // | dojo.provide("my.CustomModule");
  441. //Make sure we have a string.
  442. resourceName = resourceName + "";
  443. return (d._loadedModules[resourceName] = d.getObject(resourceName, true)); // Object
  444. }
  445. //Start of old bootstrap2:
  446. dojo.platformRequire = function(/*Object*/modMap){
  447. // summary:
  448. // require one or more modules based on which host environment
  449. // Dojo is currently operating in
  450. // description:
  451. // This method takes a "map" of arrays which one can use to
  452. // optionally load dojo modules. The map is indexed by the
  453. // possible dojo.name_ values, with two additional values:
  454. // "default" and "common". The items in the "default" array will
  455. // be loaded if none of the other items have been choosen based on
  456. // dojo.name_, set by your host environment. The items in the
  457. // "common" array will *always* be loaded, regardless of which
  458. // list is chosen.
  459. // example:
  460. // | dojo.platformRequire({
  461. // | browser: [
  462. // | "foo.sample", // simple module
  463. // | "foo.test",
  464. // | ["foo.bar.baz", true] // skip object check in _loadModule (dojo.require)
  465. // | ],
  466. // | default: [ "foo.sample._base" ],
  467. // | common: [ "important.module.common" ]
  468. // | });
  469. var common = modMap.common || [];
  470. var result = common.concat(modMap[d._name] || modMap["default"] || []);
  471. for(var x=0; x<result.length; x++){
  472. var curr = result[x];
  473. if(curr.constructor == Array){
  474. d._loadModule.apply(d, curr);
  475. }else{
  476. d._loadModule(curr);
  477. }
  478. }
  479. }
  480. dojo.requireIf = function(/*Boolean*/ condition, /*String*/ resourceName){
  481. // summary:
  482. // If the condition is true then call `dojo.require()` for the specified
  483. // resource
  484. //
  485. // example:
  486. // | dojo.requireIf(dojo.isBrowser, "my.special.Module");
  487. if(condition === true){
  488. // FIXME: why do we support chained require()'s here? does the build system?
  489. var args = [];
  490. for(var i = 1; i < arguments.length; i++){
  491. args.push(arguments[i]);
  492. }
  493. d.require.apply(d, args);
  494. }
  495. }
  496. dojo.requireAfterIf = d.requireIf;
  497. dojo.registerModulePath = function(/*String*/module, /*String*/prefix){
  498. // summary:
  499. // Maps a module name to a path
  500. // description:
  501. // An unregistered module is given the default path of ../[module],
  502. // relative to Dojo root. For example, module acme is mapped to
  503. // ../acme. If you want to use a different module name, use
  504. // dojo.registerModulePath.
  505. // example:
  506. // If your dojo.js is located at this location in the web root:
  507. // | /myapp/js/dojo/dojo/dojo.js
  508. // and your modules are located at:
  509. // | /myapp/js/foo/bar.js
  510. // | /myapp/js/foo/baz.js
  511. // | /myapp/js/foo/thud/xyzzy.js
  512. // Your application can tell Dojo to locate the "foo" namespace by calling:
  513. // | dojo.registerModulePath("foo", "../../foo");
  514. // At which point you can then use dojo.require() to load the
  515. // modules (assuming they provide() the same things which are
  516. // required). The full code might be:
  517. // | <script type="text/javascript"
  518. // | src="/myapp/js/dojo/dojo/dojo.js"></script>
  519. // | <script type="text/javascript">
  520. // | dojo.registerModulePath("foo", "../../foo");
  521. // | dojo.require("foo.bar");
  522. // | dojo.require("foo.baz");
  523. // | dojo.require("foo.thud.xyzzy");
  524. // | </script>
  525. d._modulePrefixes[module] = { name: module, value: prefix };
  526. };
  527. dojo.requireLocalization = function(/*String*/moduleName, /*String*/bundleName, /*String?*/locale, /*String?*/availableFlatLocales){
  528. // summary:
  529. // Declares translated resources and loads them if necessary, in the
  530. // same style as dojo.require. Contents of the resource bundle are
  531. // typically strings, but may be any name/value pair, represented in
  532. // JSON format. See also `dojo.i18n.getLocalization`.
  533. //
  534. // description:
  535. // Load translated resource bundles provided underneath the "nls"
  536. // directory within a package. Translated resources may be located in
  537. // different packages throughout the source tree.
  538. //
  539. // Each directory is named for a locale as specified by RFC 3066,
  540. // (http://www.ietf.org/rfc/rfc3066.txt), normalized in lowercase.
  541. // Note that the two bundles in the example do not define all the
  542. // same variants. For a given locale, bundles will be loaded for
  543. // that locale and all more general locales above it, including a
  544. // fallback at the root directory. For example, a declaration for
  545. // the "de-at" locale will first load `nls/de-at/bundleone.js`,
  546. // then `nls/de/bundleone.js` and finally `nls/bundleone.js`. The
  547. // data will be flattened into a single Object so that lookups
  548. // will follow this cascading pattern. An optional build step can
  549. // preload the bundles to avoid data redundancy and the multiple
  550. // network hits normally required to load these resources.
  551. //
  552. // moduleName:
  553. // name of the package containing the "nls" directory in which the
  554. // bundle is found
  555. //
  556. // bundleName:
  557. // bundle name, i.e. the filename without the '.js' suffix. Using "nls" as a
  558. // a bundle name is not supported, since "nls" is the name of the folder
  559. // that holds bundles. Using "nls" as the bundle name will cause problems
  560. // with the custom build.
  561. //
  562. // locale:
  563. // the locale to load (optional) By default, the browser's user
  564. // locale as defined by dojo.locale
  565. //
  566. // availableFlatLocales:
  567. // A comma-separated list of the available, flattened locales for this
  568. // bundle. This argument should only be set by the build process.
  569. //
  570. // example:
  571. // A particular widget may define one or more resource bundles,
  572. // structured in a program as follows, where moduleName is
  573. // mycode.mywidget and bundleNames available include bundleone and
  574. // bundletwo:
  575. // | ...
  576. // | mycode/
  577. // | mywidget/
  578. // | nls/
  579. // | bundleone.js (the fallback translation, English in this example)
  580. // | bundletwo.js (also a fallback translation)
  581. // | de/
  582. // | bundleone.js
  583. // | bundletwo.js
  584. // | de-at/
  585. // | bundleone.js
  586. // | en/
  587. // | (empty; use the fallback translation)
  588. // | en-us/
  589. // | bundleone.js
  590. // | en-gb/
  591. // | bundleone.js
  592. // | es/
  593. // | bundleone.js
  594. // | bundletwo.js
  595. // | ...etc
  596. // | ...
  597. //
  598. d.require("dojo.i18n");
  599. d.i18n._requireLocalization.apply(d.hostenv, arguments);
  600. };
  601. var ore = new RegExp("^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?$"),
  602. ire = new RegExp("^((([^\\[:]+):)?([^@]+)@)?(\\[([^\\]]+)\\]|([^\\[:]*))(:([0-9]+))?$");
  603. dojo._Url = function(/*dojo._Url|String...*/){
  604. // summary:
  605. // Constructor to create an object representing a URL.
  606. // It is marked as private, since we might consider removing
  607. // or simplifying it.
  608. // description:
  609. // Each argument is evaluated in order relative to the next until
  610. // a canonical uri is produced. To get an absolute Uri relative to
  611. // the current document use:
  612. // new dojo._Url(document.baseURI, url)
  613. var n = null,
  614. _a = arguments,
  615. uri = [_a[0]];
  616. // resolve uri components relative to each other
  617. for(var i = 1; i<_a.length; i++){
  618. if(!_a[i]){ continue; }
  619. // Safari doesn't support this.constructor so we have to be explicit
  620. // FIXME: Tracked (and fixed) in Webkit bug 3537.
  621. // http://bugs.webkit.org/show_bug.cgi?id=3537
  622. var relobj = new d._Url(_a[i]+""),
  623. uriobj = new d._Url(uri[0]+"");
  624. if(
  625. relobj.path == "" &&
  626. !relobj.scheme &&
  627. !relobj.authority &&
  628. !relobj.query
  629. ){
  630. if(relobj.fragment != n){
  631. uriobj.fragment = relobj.fragment;
  632. }
  633. relobj = uriobj;
  634. }else if(!relobj.scheme){
  635. relobj.scheme = uriobj.scheme;
  636. if(!relobj.authority){
  637. relobj.authority = uriobj.authority;
  638. if(relobj.path.charAt(0) != "/"){
  639. var path = uriobj.path.substring(0,
  640. uriobj.path.lastIndexOf("/") + 1) + relobj.path;
  641. var segs = path.split("/");
  642. for(var j = 0; j < segs.length; j++){
  643. if(segs[j] == "."){
  644. // flatten "./" references
  645. if(j == segs.length - 1){
  646. segs[j] = "";
  647. }else{
  648. segs.splice(j, 1);
  649. j--;
  650. }
  651. }else if(j > 0 && !(j == 1 && segs[0] == "") &&
  652. segs[j] == ".." && segs[j-1] != ".."){
  653. // flatten "../" references
  654. if(j == (segs.length - 1)){
  655. segs.splice(j, 1);
  656. segs[j - 1] = "";
  657. }else{
  658. segs.splice(j - 1, 2);
  659. j -= 2;
  660. }
  661. }
  662. }
  663. relobj.path = segs.join("/");
  664. }
  665. }
  666. }
  667. uri = [];
  668. if(relobj.scheme){
  669. uri.push(relobj.scheme, ":");
  670. }
  671. if(relobj.authority){
  672. uri.push("//", relobj.authority);
  673. }
  674. uri.push(relobj.path);
  675. if(relobj.query){
  676. uri.push("?", relobj.query);
  677. }
  678. if(relobj.fragment){
  679. uri.push("#", relobj.fragment);
  680. }
  681. }
  682. this.uri = uri.join("");
  683. // break the uri into its main components
  684. var r = this.uri.match(ore);
  685. this.scheme = r[2] || (r[1] ? "" : n);
  686. this.authority = r[4] || (r[3] ? "" : n);
  687. this.path = r[5]; // can never be undefined
  688. this.query = r[7] || (r[6] ? "" : n);
  689. this.fragment = r[9] || (r[8] ? "" : n);
  690. if(this.authority != n){
  691. // server based naming authority
  692. r = this.authority.match(ire);
  693. this.user = r[3] || n;
  694. this.password = r[4] || n;
  695. this.host = r[6] || r[7]; // ipv6 || ipv4
  696. this.port = r[9] || n;
  697. }
  698. }
  699. dojo._Url.prototype.toString = function(){ return this.uri; };
  700. dojo.moduleUrl = function(/*String*/module, /*dojo._Url||String*/url){
  701. // summary:
  702. // Returns a `dojo._Url` object relative to a module.
  703. // example:
  704. // | var pngPath = dojo.moduleUrl("acme","images/small.png");
  705. // | console.dir(pngPath); // list the object properties
  706. // | // create an image and set it's source to pngPath's value:
  707. // | var img = document.createElement("img");
  708. // | // NOTE: we assign the string representation of the url object
  709. // | img.src = pngPath.toString();
  710. // | // add our image to the document
  711. // | dojo.body().appendChild(img);
  712. // example:
  713. // you may de-reference as far as you like down the package
  714. // hierarchy. This is sometimes handy to avoid lenghty relative
  715. // urls or for building portable sub-packages. In this example,
  716. // the `acme.widget` and `acme.util` directories may be located
  717. // under different roots (see `dojo.registerModulePath`) but the
  718. // the modules which reference them can be unaware of their
  719. // relative locations on the filesystem:
  720. // | // somewhere in a configuration block
  721. // | dojo.registerModulePath("acme.widget", "../../acme/widget");
  722. // | dojo.registerModulePath("acme.util", "../../util");
  723. // |
  724. // | // ...
  725. // |
  726. // | // code in a module using acme resources
  727. // | var tmpltPath = dojo.moduleUrl("acme.widget","templates/template.html");
  728. // | var dataPath = dojo.moduleUrl("acme.util","resources/data.json");
  729. var loc = d._getModuleSymbols(module).join('/');
  730. if(!loc){ return null; }
  731. if(loc.lastIndexOf("/") != loc.length-1){
  732. loc += "/";
  733. }
  734. //If the path is an absolute path (starts with a / or is on another
  735. //domain/xdomain) then don't add the baseUrl.
  736. var colonIndex = loc.indexOf(":");
  737. if(loc.charAt(0) != "/" && (colonIndex == -1 || colonIndex > loc.indexOf("/"))){
  738. loc = d.baseUrl + loc;
  739. }
  740. return new d._Url(loc, url); // dojo._Url
  741. };
  742. })();
  743. }