Friday, February 25, 2011

Dojo 1.6 - dojo.require (still) loads packages synchronously

I was under the impression that RequireJS was going to change the loader experience. In retrospect I now see the caveats and qualifiers (see links).

Given this block of code:
dojo.require("dojo.string");
dojo.ready(function () {
    alert(dojo.string.pad("hello", " ", 10));
});


What happens? Unfortunately it's the same thing that happened in 1.5. I was hoping the loader was modified to use RequireJS and load the package asynchronously but that is not the case. The dojo/string.js is loaded using http.open('GET', uri, false), which is a synchronous load:

  1. You can optionally provide a second parameter, omitModuleCheck, or rely on _global_omit_module_check, to determine if a test should be made to make sure "dojo.string" is actually defined after loaded.
  2. _loadedModules it tested to see if "dojo.string" is already loaded (it is not).
  3. _getModuleSymbols is called to convert "dojo.string" into a path (utilizes _modulePrefixes), resulting path is "./string.js"
  4. _loadPath("./string.js", "dojo.string") is called, because path is not absolute, baseUrl is used to calculate the uri, in my case this is "scripts/dojo/./string.js".
  5. Because omitModuleCheck was not true, _loadPath was called with a module name ("dojo.string") and because it was called with a module name it calls _loadUriAndCheck instead of _loadUri. Note that currentModule is assigned "dojo.string".
  6. _loadUriAndCheck calls _loadUri and later checks to make sure "dojo.string" was added to _loadedModules.
  7. _loadUri tests _loadedUrls to make sure "scripts/dojo/./string.js" is not already loaded. It then invokes _getText which does a synchronous GET and returns the javascript as a string. That value is dojo.eval'd, to load the code into memory.

NOTE: The currentModule was set for no apparent reason so I looked into it and found that it is also referenced by the "define" method (in loader.js) and used to convert "dojo.string" into "dojo/string". It only does this when two parameters are provided to the define method.


Related Links
RequireJS
RequireJS/AMD Module Forms

Friday, February 4, 2011

ESRI ArcGIS Javascript API

Adding Closable to InfoWindow

ESRI uses "hide" style to indicate the x in the corner of the infoWindow to dismiss/hide the infoWindow. If another .CSS gives meaning to "hide", such as display: none, then that little X will no longer appear in the infoWindow.

The problem with this is that esri.dijit.InfoWindow does not implement support for "closable".


Solution


coretech.ext.makeInfoWindowClosable = function(p) {
  var a = "closable",
      infoWindow = p.prototype;
  an = infoWindow._getAttrNames(a);
  infoWindow[an.s] = function(value) {
    this[a] = value;
    dojo.query(".user .titlebar .hide", this.domNode).forEach(function(n) {
      dojo.style(n, {
        display: value ? "block" : "none"
      });
    });
  };
  infoWindow[an.g] = function() {
    return this[a];
  };
};
coretech.ext.makeInfoWindowClosable(esri.dijit.InfoWindow);


Usage Example



var o = coretech.esriMap.infoWindow;
o.set("closable", false);
o.show(coretech.esriMap.extent.getCenter());


Links

ArcGIS JavaScript API