Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Beyond Dojo: The Rise of Asynchronous Module Definition (AMD)

Beyond Dojo: The Rise of Asynchronous Module Definition (AMD)

IBM IMPACT session with Dylan Schiemann on the AMD module format.

James Thomas

May 08, 2012
Tweet

More Decks by James Thomas

Other Decks in Technology

Transcript

  1. © SitePen, Inc. All Rights Reserved Beyond Dojo: The Rise

    of Asynchronous Module Definition (AMD) presents Dylan Schiemann, CEO, SitePen James Thomas, UI Technical Lead, IBM IBM Impact 2012 Conference, TDW-2286 Tuesday, 8 May 2012
  2. © SitePen, Inc. All Rights Reserved Nice to Meet you

    Co-Founder of Dojo Toolkit CEO, SitePen, Inc. President, Dojo Foundation Dylan Schiemann @dylans @sitepen @dojo Tuesday, 8 May 2012
  3. © SitePen, Inc. All Rights Reserved Nice to Meet you

    IBMer & Dojo Committer UI Technical Lead - Watson Creator of Dojo Web Builder James Thomas @thomasj @dojo Tuesday, 8 May 2012
  4. © SitePen, Inc. All Rights Reserved The Basics Allows for

    asynchronous module loading and callback management Allows for loading of non-AMD modules, sometimes using plugins (HTML templates, JSON/config files, basic ".js" files) dojo/domReady! dojo/text! Works via script tag injection (or XHR) and onload events Tuesday, 8 May 2012
  5. © SitePen, Inc. All Rights Reserved The Benefits Works cross-domain

    We’re simply injecting <script> tags! Prevents the need for globals Provides excellent encapsulation Mix and match code from different projects Load only what you need, expose only what you should! Loads modules only once, caches them Simple API: define and require Tuesday, 8 May 2012
  6. © SitePen, Inc. All Rights Reserved Dojo Nano and AMD

    "Base-less" Dojo Only using the parts of Dojo you really need, on a much more granular level Dojo 1.7 AMD loader <4K gzip/minified Asynchronous Module Definition (AMD) A grassroots standard for interoperable code modules Client and Server Plugin framework for additional extensibility Default module system for Dojo 1.7+ Tuesday, 8 May 2012
  7. © SitePen, Inc. All Rights Reserved Squeezing Performance • Automated

    build with dependency resolution, AMD & has.js optimized builds. • All from one place with full licensing and support. Dojo Base Dijit (View) dojox Grid dojo/store (Model) Dojo Nano Tuesday, 8 May 2012
  8. © SitePen, Inc. All Rights Reserved AMD Toolkits and Modules

    Built-in AMD support Dojo 1.7+ jQuery Mobile 1.1+ Wink Toolkit 1.4+ EmbedJS Lightstreamer (next rev) OpenCoWeb PhoneGap/Cordova Firebug 1.8+ Zazl money.js dgrid has.js es5shim XStyle put-selector Persevere Pintura Perstore Tunguska Twine Tuesday, 8 May 2012
  9. © SitePen, Inc. All Rights Reserved AMD-Compatible With some finagling

    MooTools 2.0+ Shipyard Backbone.js jQuery Node.js Pretty much any JS toolkit or module set, with some work Tuesday, 8 May 2012
  10. © SitePen, Inc. All Rights Reserved Modules and Packages Organized

    JavaScript source code AMD creates two global functions, require and define Replaces dojo.provide, dojo.require, dojo.requireIf, dojo.requireAfterIf, dojo.platformRequire, & dojo.requireLocalization Modules are grouped into collections called packages Examples: dojo, dijit, and dojox Modules normally have a 1:1 mapping to files Except when production-optimized through a build Tuesday, 8 May 2012
  11. © SitePen, Inc. All Rights Reserved Loaders The source code

    that can load AMD modules efficiently Dojo Loader RequireJS curl.js Almond Others Tuesday, 8 May 2012
  12. © SitePen, Inc. All Rights Reserved Builder/Optimizer Code that combines

    modules into optimized resources to improve production performance Dojo builder (plus Dojo ShrinkSafe or Closure Compiler) Uglify RequireJS - r.js Zazl Tuesday, 8 May 2012
  13. © SitePen, Inc. All Rights Reserved Package Manager Listing/registry of

    available packages, and tools to download them cpm and Dojo Foundation Packages npm (for Node, not really AMD) volo ender Tuesday, 8 May 2012
  14. © SitePen, Inc. All Rights Reserved Dojo Foundation Packages Provides

    one-stop navigation to a variety of useful JavaScript packages 60 Packages and growing Will continue to grow once advertised Tuesday, 8 May 2012
  15. © SitePen, Inc. All Rights Reserved Module Identifiers Look like

    path fragments; e.g. dijit/form/Button Work a lot like paths relative path fragments like "./" and "../" can be used to refer to other modules within the same package Necessary for fully portable packages Can be aliased/overridden to point to different code Tuesday, 8 May 2012
  16. © SitePen, Inc. All Rights Reserved require() require takes three

    arguments: configuration: Optional, a configuration object for the loader dependencies: Optional, an array of strings as a list of module identifiers to load before calling the callback callback: Optional, a function to call when dependencies are loaded What does it do? Reconfigures the loader at runtime Loads modules and executes an optional callback when they are loaded, passing loaded modules into the Tuesday, 8 May 2012
  17. © SitePen, Inc. All Rights Reserved // We're not using

    the configuration object here, just an array of requirements and // a callback. dojo/domReady! is a plug-in that we will explain in a moment. require(["dojo/dom-construct", "dojo/domReady!"], function(domConstruct){ var newButton = domConstruct.create("button", {innerHTML: "foo"}); domConstruct.place(newButton, document.body, "last"); }); // The same code in the legacy system // dojo.require("dojo/dom"); //this module was included by default dojo.ready(function(){ var newButton = dojo.create("button", {innerHTML: "foo"}); dojo.place(newButton, document.body, "last"); }) require() Tuesday, 8 May 2012
  18. © SitePen, Inc. All Rights Reserved Defining Modules Use the

    define function Code contained within is not resolved until they are required (lazy instantiation) Factory is only called once; the return value is cached by the loader and shared between all modules Special plugin modules exist to extend loader functionality Tuesday, 8 May 2012
  19. © SitePen, Inc. All Rights Reserved define() define takes three

    arguments: moduleId: Optional, a string to explicitly identify the module dependencies: Optional, an array of strings as a list of module identifiers to load before calling the factory factory: The value of the module, or a function that returns the value of the module What does it do? Defines the value of a module Typically the moduleId is reserved for the build system - don't explicitly identify your modules! Tuesday, 8 May 2012
  20. © SitePen, Inc. All Rights Reserved // Creating a widget

    old style dojo.provide("populizr.TemplatedWidget"); dojo.require("dijit._WidgetBase"); dojo.require("dijit._TemplatedMixin"); dojo.declare("populizr.TemplatedWidget", [dijit._WidgetBase, dijit._TemplatedMixin], { templateString: dojo.cache("populizr","templates/ TemplatedWidget.html"); }); Creating a widget before Tuesday, 8 May 2012
  21. © SitePen, Inc. All Rights Reserved // Creating a widget

    with AMD define( ["dojo/_base/declare", "dijit/_WidgetBase", "dijit/_TemplatedMixin", "dojo/text!./templates/TemplatedWidget.html"], function(declare, _WidgetBase, _TemplatedMixin, template){ return declare([_WidgetBase, _TemplatedMixin], { templateString: template }); } ); // Note how the dependencies map into the function call! Creating a widget with define + declare Tuesday, 8 May 2012
  22. © SitePen, Inc. All Rights Reserved // Creating a widget

    with AMD define( ["dojo/_base/declare", "dijit/_WidgetBase", "dijit/_TemplatedMixin", "dojo/dom-class", "dojo/dom-style", "dojo/dom-attr", "dojo/_base/xhr", "dojo/_base/array", "dojo/_base/lang", "dojo/text!./templates/TemplatedWidget.html"], function(declare, _WidgetBase, _TemplatedMixin, domClass, domStyle, domAttr, array, xhr, lang, template){ ... module code goes here .... } ); // What’s wrong here?!? Tuesday, 8 May 2012
  23. © SitePen, Inc. All Rights Reserved // Creating a widget

    with AMD define( ["dojo/_base/declare", "dijit/_WidgetBase", "dijit/_TemplatedMixin", "dojo/dom-class", "dojo/dom-style", "dojo/dom-attr", "dojo/_base/xhr", "dojo/_base/array", "dojo/_base/lang", "dojo/text!./templates/TemplatedWidget.html"], function(declare, _WidgetBase, _TemplatedMixin, domClass, domStyle, domAttr, array, xhr, lang, template){ ... module code goes here .... } ); // What’s wrong here?!? Issue: Dependencies mis-match Tuesday, 8 May 2012
  24. © SitePen, Inc. All Rights Reserved // Creating a widget

    with AMD define( ["dojo/_base/declare", "dijit/_WidgetBase", "dijit/_TemplatedMixin", "dojo/dom-class", "dojo/dom-style", "dojo/dom-attr", "dojo/_base/xhr", "dojo/_base/array", "dojo/_base/lang", "dojo/text!./templates/TemplatedWidget.html"], function(declare, _WidgetBase, _TemplatedMixin){ return declare([_WidgetBase, _TemplatedMixin], { templateString: template, hide: function () { var domClass = require(“dojo/dom-class”); domClass.add(this.domNode, “dijitHidden”); } }); Solution #1: Don’t use (all of) them Tuesday, 8 May 2012
  25. © SitePen, Inc. All Rights Reserved // Creating a widget

    with AMD define( function(require, exports, module){ // Use requires on per-dependency basis var declare = require("dijit/_base/declare"), _WidgetBase = require("dijit/_WidgetBase"), _TemplatedMixin = require("dijit/_TemplatedMixin"), template = require("dojo/text!./template.html"); return declare([_WidgetBase, _TemplatedMixin], { templateString: template, hide: function () { var domClass = require(“dojo/dom-class”); domClass.add(this.domNode, “dijitHidden”); } }); Taking it further... Tuesday, 8 May 2012
  26. © SitePen, Inc. All Rights Reserved // an AMD module

    as a plain object define({ enabled: true, delay: 500 }); The value given for a module can also be just a plain object Modules defined as plain objects typically have no dependencies since there is no factory function that can use the references to those dependencies define() Tuesday, 8 May 2012
  27. © SitePen, Inc. All Rights Reserved Key differences between define,

    dojo.provide AMD is less verbose AMD is fully self-encapsulated No references to global variables or the module's own package name Faster scope lookups Better minification Impossible to forget a dependency and still have working code Zero global namespace pollution Completely portable Tuesday, 8 May 2012
  28. © SitePen, Inc. All Rights Reserved Verifying that define is

    AMD-compliant define.amd is used to indicate that define is actually an AMD-compatible loader and not some random function Tuesday, 8 May 2012
  29. © SitePen, Inc. All Rights Reserved Conditional requires Use cases

    for conditional requirements: Dependencies that cannot be determined until runtime dojox/gfx uses this concept to decide which rendering engine to use (VML, SVG, canvas, etc) Modules that you only want to load when a certain condition occurs (configuration, event, etc) Tuesday, 8 May 2012
  30. © SitePen, Inc. All Rights Reserved Context-sensitive require require Context

    sensitive require Resolves relative module ids with respect to the depending module; just like relative module ids are resolved in the module's dependency list Relative module lookups don't work with global require Tuesday, 8 May 2012
  31. © SitePen, Inc. All Rights Reserved define(["dojo/dom-construct", "dojo/on", "dojo/_base/window", "require",

    "dojo/domReady!" ], function (domConstruct, on, win, require) { var debugButton = domConstruct.create('input', { type: 'button', value: 'Debug' }, win.body()); on(debugButton, "click", function () { require([ "./debugger/console" ], function (console) { console.open(); }); }); }); Context-sensitive require Tuesday, 8 May 2012
  32. © SitePen, Inc. All Rights Reserved exports An object that

    is the initial value of the module Useful for managing circular dependencies exports is the implicitly returned object that represents the value of the module Tuesday, 8 May 2012
  33. © SitePen, Inc. All Rights Reserved // The following are

    similar define(["exports"], function(exports) { export.foo = "Hi"; }); define(function() { return { foo: "Hi" }; }); define(function (require, exports, module) { ... }); // will cause the factory to be scanned for require('dep'); calls and will pass require, exports and module to the factory. define([], function () { ... }); //will not scan the factory and will not pass anything to the factory. exports Tuesday, 8 May 2012
  34. © SitePen, Inc. All Rights Reserved Portable Modules moduleId should

    never be specified explicitly in a define call (it is for build tools) dojo.declare should never specify the name of the class being declared (unless creating declarative widgets) If you want to create private classes, remember you can just assign the return value of dojo.declare to a local variable Dependencies to modules within a package should always use relative module identifiers Tuesday, 8 May 2012
  35. © SitePen, Inc. All Rights Reserved Portable Modules Using global

    variables is verboten There are some areas where this is still required (some Dijits break the rules and declare multiple classes), but should improve beyond 1.7 This is especially relevant if you are defining a module without a factory function; if you have any direct dependencies, you should be using a factory function Conditional requires with relative module identifiers must use a context-sensitive require Tuesday, 8 May 2012
  36. © SitePen, Inc. All Rights Reserved require({ cacheBust:new Date(), waitSeconds:5

    }); Configuration data (like dojoConfig) Can be passed as the first parameter in require Configuration Object Tuesday, 8 May 2012
  37. © SitePen, Inc. All Rights Reserved Portable Modules How do

    you share portable modules with the community? Tuesday, 8 May 2012
  38. © SitePen, Inc. All Rights Reserved Portable Modules How do

    you share portable modules with the community? Publish them in the Dojo Foundation Package Repo! Tuesday, 8 May 2012
  39. © SitePen, Inc. All Rights Reserved Portable Modules How do

    you share portable modules with the community? Use or extend CJS module template to define your module Tuesday, 8 May 2012
  40. © SitePen, Inc. All Rights Reserved Portable Modules How do

    you share portable modules with the community? Use or extend CJS module template to define your module Fill out package.json Submit your package! http:// packages.dojofoundation.org/submit.html How do you share portable modules with the community? If you are defining a module without a factory function and you have any direct dependencies, you should be using a factory function Conditional requires with relative module identifiers must use a context-sensitive require Tuesday, 8 May 2012
  41. © SitePen, Inc. All Rights Reserved Plugins Extend AMD loaders

    in lots of useful ways Common plugins available with most loaders are "text", "i18n", and "domReady" Plugin dependencies are identified by the exclamation point in the module identifier: "dojo/ text!", "dojo/i18n!", "dojo/domReady!" Data to the left of the "!" identifies the plugin to load; data to the right of the "!" is passed to the plugin for processing Tuesday, 8 May 2012
  42. © SitePen, Inc. All Rights Reserved define([ "dojo/text!./quotes.txt" ], function

    (quotes) { // quotes will simply be the content of the file, // so we'll split on newlines var quotes = quotes.split("\n"); // Write out a random quote to the console console.log(quotes[Math.floor(quotes.length * Math.random ())]); }); Loads string from file (XHR if not built-in, cross-domain care is needed) Replaces dojo.cache Used mostly for loading template strings, but can load any string Build system interns strings loaded using dojo/text, just like dojo.cache Compatible with RequireJS's text plugin dojo/text Tuesday, 8 May 2012
  43. © SitePen, Inc. All Rights Reserved define( [ "dojo/i18n!dijit/nls/common", "dojo/i18n!dijit/nls/it/common"

    ], function (common, commonIT) { console.log(common.buttonCancel); // "Cancel" console.log(commonIT.buttonCancel); // "Annula" } ); Loads an internationalization bundle Replaces dojo.requireLocalization and dojo.getLocalization Compatible with RequireJS's i18n plugin dojo/i18n Tuesday, 8 May 2012
  44. © SitePen, Inc. All Rights Reserved require([ "dojo/domReady!" ], function

    () { console.log("DOM is ready!"); }); require(["dojo/ready", "dojo/parser", "dijit/registry", "dijit/Dialog"], function (ready, parser, registry){ ready(function(){ // This won't run until the DOM has loaded, the parser has run, and other // modules like dijit/hccss have also loaded. var dialog = registry.byId("myDialog"); ... }); }); Ensures the module does not resolve until the DOM is ready Replaces dojo.ready Compatible with RequireJS's domReady plugin dojo/domReady and dojo/ready Tuesday, 8 May 2012
  45. © SitePen, Inc. All Rights Reserved require([ "dojo/has!dom-addeventlistener?./events/w3cHandlers:./events/ ieHandlers" ],

    function (eventHandlers) { // Do something with eventHandlers }); Allows modules to be conditionally loaded, using has.js features Replaces dojo.requireIf dojo/has Tuesday, 8 May 2012
  46. © SitePen, Inc. All Rights Reserved Loading non-AMD code Special

    module identifiers can be used to load arbitrary, non-AMD scripts as dependencies, in which case the module's returned value will be undefined: Any identifier starting with "/" Any identifier starting with a protocol (e.g. "http:", "https:") Any identifier ending with ".js" curl.js and perhaps others use js! prefix (e.g. "js!https://ajax.googleapis.com/ajax/libs/mootools/1.4.1/ mootools-yui-compressed.js Tuesday, 8 May 2012
  47. © SitePen, Inc. All Rights Reserved Configuring AMD Loaders Given

    this directory structure, the configuration would look like so: require({ baseUrl: "js/", packages: [ { name: "dojo", location: "lib/dojo" }, { name: "dijit", location: "lib/dijit" }, { name: "dojox", location: "lib/dojox" }, { name: "my", location: "my" }, { name: "util", location: "util" }, { name: "external", location: "http://foo.com/external" } ] }); Tuesday, 8 May 2012
  48. © SitePen, Inc. All Rights Reserved Configuring AMD Loaders baseUrl:

    defines the base path for all modules; can be relative or absolute Relative values are relative to the HTML file in browsers and relative to the current working directory on servers packages: defines all of the packages registered for the application name is the name of the package location is the location of the package; relative paths are relative to baseUrl main is the name of the module that will be loaded if someone tries to require the package itself; this defaults to "main" (e.g. requiring "foo" will load the "foo/main" module) Tuesday, 8 May 2012
  49. © SitePen, Inc. All Rights Reserved // package configuration //

    Note that packageMap was recently renamed map in the AMD spec. { name: "my", location: "my", packageMap: { array: 'dojo/_base/array', xhr: 'dojo/ _base/xhr', ...} } // require or define that uses the map define(['array', 'xhr', 'query'], function (array, xhr, query) { }); A map that allows package names to be aliased to other locations for this particular package only Use two packages with the same name (e.g. multiple versions) at the same time, as long as the package authors followed best practices and did not use an explicit moduleId in their define calls Simply install the two packages to two different directories and then define each package with a unique name in the packages array. Mapping Packages Tuesday, 8 May 2012
  50. © SitePen, Inc. All Rights Reserved <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/dojo/1.7.2/dojo/dojo.js" data-dojo-config="async:

    true, packages: [ { name: 'jquery', location: 'http://ajax.googleapis.com/ajax/libs/jquery/ 1.7.2', main: 'jquery' } ]"> </script> <script type="text/javascript"> define.amd.jQuery = true; require(["jquery", "dojo/query", "dojo/NodeList-dom"], function(jquery, query){ jquery("#jquery").click(function () { jquery("#jquery > img").toggle(); }); query("#dojo").on("#click", function () { query("#dojo > img").toggleClass("hidden"); }); }); </script> dQuery (Dojo + jQuery) https://github.com/jthomas/amd_examples/tree/master/dojo_and_jquery Tuesday, 8 May 2012
  51. © SitePen, Inc. All Rights Reserved Dojools (MooTools + Dojo)

    https://github.com/jthomas/amd_examples/tree/master/dojo_and_mootools Tuesday, 8 May 2012
  52. © SitePen, Inc. All Rights Reserved Dojools (MooTools + Dojo)

    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/dojo/1.7.2/dojo/dojo.js" data-dojo-config="async: true, packages: [ { name: 'mootools', location: './mootools/amdified/'} ]"> </script> <script type="text/javascript"> require(["dojo/has", "dojo/query", "dojo/NodeList-dom"], function(has, query){ window.has = has; query("#dojo").on("#click", function () { query("#dojo > img").toggleClass("hidden"); }); require(["mootools/Element/Element", "mootools/Element/Element.Event"], function(Element, Event){ Element.$("mootools").addEvent("click", function () { Element.$$("#mootools > img").each(function (elem) { elem.toggleClass("hidden"); }); }); }); }); https://github.com/jthomas/amd_examples/tree/master/dojo_and_mootools Tuesday, 8 May 2012
  53. © SitePen, Inc. All Rights Reserved dgrid and Dojo Store

    https://github.com/SitePen/dgrid/blob/master/test/JsonRest.html Tuesday, 8 May 2012
  54. © SitePen, Inc. All Rights Reserved require(["dgrid/List", "dgrid/OnDemandGrid","dgrid/Selection", "dgrid/editor", "dgrid/Keyboard",

    "dgrid/tree", "dojo/_base/declare", "dojo/store/JsonRest", "dojo/ store/Observable", "dojo/store/Cache", "dojo/store/Memory", "dojo/domReady!"], function(List, Grid, Selection, editor, Keyboard, tree, declare, JsonRest, Observable, Cache, Memory){ var testStore = Observable(Cache(JsonRest({ target:"./data/rest.php?", idProperty: "id", query: function(query, options){ return JsonRest.prototype.query.call(this, query, options); } }), Memory())); testStore.getChildren = function(parent, options){ return testStore.query({parent: parent.id}, options); }; // ... dgrid and Dojo Store Tuesday, 8 May 2012
  55. © SitePen, Inc. All Rights Reserved // ... var columns

    = [ tree({label:'Name', field:'name', sortable: false}), {label:'Id', field:'id', sortable: false}, editor({label:'Comment', field:'comment', sortable: false}, "text"), editor({label:'Boolean', field:'boo', sortable: false, autoSave: true}, "checkbox") ]; window.grid = new (declare([Grid, Selection, Keyboard]))({ store: testStore, getBeforePut: false, columns: columns }, "grid"); }); dgrid and Dojo Store (continued) Tuesday, 8 May 2012
  56. © SitePen, Inc. All Rights Reserved dgrid and Dojo Store

    https://github.com/SitePen/dgrid/blob/master/test/JsonRest.html Tuesday, 8 May 2012
  57. © SitePen, Inc. All Rights Reserved require([ "wink/ui/layout/scroller/js/scroller.js", "dojox/mobile", "dojox/mobile/parser",

    "dojox/mobile/compat", "dojox/mobile/RadioButton", "dojox/mobile/Carousel", "dojox/mobile/Opener", "dojox/mobile/SpinWheel", "dojo/data/ItemFileReadStore", "wink/ui/xyz/coverflow/js/coverflow.js" ], function(Scroller, dojoMobile) { df.utils.sizeElements(); df.utils.positionElements(); // Parse the page dojoMobile.parser.parse(); // Display the right options if ( !wink.has('css-perspective')){ $('rb3').disabled = true; } }); Dojo Foundation Community App Tuesday, 8 May 2012
  58. © SitePen, Inc. All Rights Reserved define(["xstyle!./path/to/example.css"], function(){ // module

    starts after css is loaded }); A framework for shimming (or polyfilling) and extending CSS, to efficiently support various plugins for additional CSS functionality and backwards compatibility of newer features. A CSS loader plugin for AMD loaders xstyle Tuesday, 8 May 2012
  59. © SitePen, Inc. All Rights Reserved BBC News "On top

    of this we layer our JavaScript application. Each page has a block of inline JavaScript that checks the capabilities of the browser before deciding whether to kick start the enhanced experience. Progressive enhancement, really, at heart. The JavaScript will include curl.js into the page and then AMD modules will load additional functionality into the page (our drop-down section navigation for example). The USP of this UI is that it provide a news service that tailored to new hardware/software." Tuesday, 8 May 2012
  60. © SitePen, Inc. All Rights Reserved Landmarks: Goals AMD example

    application Shows off famous landmarks (Eiffel Tower, Golden Gate Bridge, etc.) ESRI map API (using Dojo 1.6, pre-AMD) Flickr image API Wikipedia content Work well on desktop, phones, and tablets WebKit, Firefox, iOS, and Android were the initial targets Tuesday, 8 May 2012
  61. © SitePen, Inc. All Rights Reserved { "name": "landmarks", "version":

    "1.0", "main": "main", "dependencies": { "dojo": "current", "dijit": "current", "dojox": "current", "util": "current" }, "description": "Landmarks. A demonstration of cross-platform Dojo technologies.", "licenses": [ { "type": "AFLv2.1", "url": "http://trac.dojotoolkit.org/browser/dojo/trunk/LICENSE#L43" }, { "type": "BSD", "url": "http://trac.dojotoolkit.org/browser/dojo/trunk/LICENSE#L13" } ], "dojoBuild": "app.profile.js" } package.json Tuesday, 8 May 2012
  62. © SitePen, Inc. All Rights Reserved require({ baseUrl: "", packages:

    [ "dojo", "dojox", "dijit", "app" ], selectorEngine: "lite" }, [ "app" ]); run.js Tuesday, 8 May 2012
  63. © SitePen, Inc. All Rights Reserved define([ "require" ], function(require){

    // Exposes the Dojo 1.6-based Esri API for AMD apps as an AMD loader plugin. var esriApi; return { load: function(moduleId, require, callback){ if(esriApi){ callback(esriApi); return; } // The Esri API *requires* the older djConfig variable name // for its configuration var oldDjConfig = window.djConfig; window.djConfig = { scopeMap: [ // Lowercase scope map names are used because of some // peculiar behaviour observed during testing where JSONP // requests would be sometimes returned with lowercase // callback names even though the original call used // mixed-case names [ "dojo", "esridojo" ], [ "dijit", "esridijit" ], [ "dojox", "esridojox" ] ] }; // ... esriApi.js Tuesday, 8 May 2012
  64. © SitePen, Inc. All Rights Reserved define([ "require", "dojo/_base/array", "dojo/has",

    "dojo/topic", "dojo/store/Observable", "./store/LocalStorage" ], function(require, arrayUtil, has, topic, makeObservable, LocalStorage){ var app = {}; has.add("sff", function(){ return screen.width < 1000 && screen.height < 1000; }); // store init var landmarkStore = app.landmarkStore = makeObservable(new LocalStorage()); // ui init var uiClass = has("touch") ? (has("sff") ? "Mobile" : "Tablet") : "Desktop"; document.body.className += " app" + uiClass; console.info("Loading UI " + uiClass); main.js Tuesday, 8 May 2012
  65. © SitePen, Inc. All Rights Reserved require([ "./ui/" + uiClass

    ], function(Ui){ app.ui = new Ui({ id: "container" }).placeAt(document.body); app.ui.startup(); navigator.geolocation && navigator.geolocation.getCurrentPosition(function (currentPosition){ var nearestXyDelta = Infinity, nearestLandmark; landmarkStore.query().forEach(function(landmark){ var xyDelta = Math.abs(currentPosition.coords.latitude - landmark.latitude) + Math.abs(currentPosition.coords.longitude - landmark.longitude); if(xyDelta < nearestXyDelta){ nearestXyDelta = xyDelta; nearestLandmark = landmark; } }); topic.publish("/landmark/selected", nearestLandmark); }); landmarkStore.query({}, { count: 1 }).forEach(function(landmark){ topic.publish("/landmark/selected", landmark); }); }); return app; }); main.js (continued) Tuesday, 8 May 2012
  66. © SitePen, Inc. All Rights Reserved Result: Modular Tools Tools

    to mix and match to create your app Separate data from UI logic simple and seamlessly Modular enough for very simple projects, flexible and consistent enough to handle the most challenging, feature-rich web apps Tuesday, 8 May 2012
  67. © SitePen, Inc. All Rights Reserved AMD Plans for Dojo

    1.8+ API Clean-up, Further Split of Features Compose (improved declare), xstyle, put-selector, Dijit/ Widget Remove weight of deprecated APIs Tighter dependencies DojoX completely moved to Dojo Foundation packages Releases Independent releases of packages, roll out package release sets Support major HTML5, mobile, modern browser features Web Builder and Dojo Foundation Packages Tuesday, 8 May 2012
  68. © SitePen, Inc. All Rights Reserved Getting Started AMD Spec:

    https://github.com/amdjs/amdjs-api/ wiki/AMD Why AMD?: http://requirejs.org/docs/ whyamd.html Define AMD Modules with Dojo: http:// dojotoolkit.org/documentation/tutorials/1.7/ modules/ Learn more about AMD: http://dojotoolkit.org/ blog/learn-more-about-amd Tuesday, 8 May 2012
  69. © SitePen, Inc. All Rights Reserved SitePen: We Build Extraordinary

    Apps. Desktop and Mobile Web App professional services Creators and leaders of open source web software Tuesday, 8 May 2012
  70. © SitePen, Inc. All Rights Reserved Thanks! Q&A SitePen sitepen.com

    Dojo Toolkit dojotoolkit.org Twitter: @dylans @thomasj @sitepen @dojo Tuesday, 8 May 2012