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

11,211 views

Published on

Beyond Dojo: The Rise of Asynchronous Module Definition (AMD)
Presented at IBM Impact 2012

Published in: Technology, Design
2 Comments
9 Likes
Statistics
Notes
No Downloads
Views
Total views
11,211
On SlideShare
0
From Embeds
0
Number of Embeds
5
Actions
Shares
0
Downloads
0
Comments
2
Likes
9
Embeds 0
No embeds

No notes for slide
  • \n
  • \n
  • \n
  • \n
  • \n
  • Note that the exclamation indicates usage as a plugin\n
  • Older versions of the Dojo Toolkit used Synchronous XHR to load modules, and a special XDomain build type for CDNs\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Point out that in this case, domConstruct is now local, not global, much faster lookups\n
  • \n
  • Explicitly identifying your modules makes it harder to relocate your modules for other apps and can cause name collisions.\n
  • \n
  • Point out the plugin to replace dojo.cache\nAlso point out that we don't have to give an explicit name, though this has potential issue if we're trying to use this widget declaratively\n
  • Sample module with lots of dependenciesCommon bug new users run into and complain about....\n
  • Mis-match between factory arguments and dependencies list, “array” available via “xhr” and vice-versa. Usually not caught until runtime, can be frustrating.\n
  • We can skip factory arguments and use require when needed.Module already loaded so result is returned second time round.Less likely to require wrong module at the expense of more code...\n
  • Loader even supports not providing explicit dependencies Automatically scan module source for “require” calls and loadNot really recommended....\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Point out "require" in the deps. Emphasize that it works like normal require, except that it can work with relative module IDs in this scenario\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • uses XHR so doesn't work cross-domain without a build\n
  • \n
  • \n
  • Point out that eventHandlers will be *either* the w3cHandlers OR the ieHandlers, dependent on the has check\n
  • \n
  • \n
  • \n
  • \n
  • tlmSiblingOfDojo: Top-level Module Sibling of Dojo\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • dojoBuild property indicates a javascript file that contains extra information as a logical extension of package.json for metadata that aren't possible to express with json. used by dojo's build tool.\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Introduce SitePen; more details are on the next slide.\n
  • \n\n\n
  • \n
  • Beyond Dojo: The Rise of Asynchronous Module Definition (AMD)

    1. 1. presents Beyond Dojo: The Rise of Asynchronous Module Definition (AMD) Dylan Schiemann, CEO, SitePen James Thomas, UI Technical Lead, IBM IBM Impact 2012 Conference, TDW-2286© SitePen, Inc. All Rights Reserved
    2. 2. Nice to Meet you Dylan Schiemann Co-Founder of Dojo Toolkit CEO, SitePen, Inc. President, Dojo Foundation @dylans @sitepen @dojo© SitePen, Inc. All Rights Reserved
    3. 3. Nice to Meet you James Thomas IBMer & Dojo Committer UI Technical Lead - Watson Creator of Dojo Web Builder @thomasj @dojo© SitePen, Inc. All Rights Reserved
    4. 4. AMD© SitePen, Inc. All Rights Reserved
    5. 5. Purpose© SitePen, Inc. All Rights Reserved
    6. 6. 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© SitePen, Inc. All Rights Reserved
    7. 7. 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© SitePen, Inc. All Rights Reserved
    8. 8. AMD in the wild© SitePen, Inc. All Rights Reserved
    9. 9. © SitePen, Inc. All Rights Reserved
    10. 10. 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+© SitePen, Inc. All Rights Reserved
    11. 11. Squeezing Performance • Automated build Dojo Nano with dependency Dojo Base resolution, AMD & dojo/store (Model) has.js optimized builds. • All from one place with full licensing and Dijit (View) support. dojox Grid© SitePen, Inc. All Rights Reserved
    12. 12. AMD Toolkits and Modules Built-in AMD support money.js Dojo 1.7+ dgrid jQuery Mobile 1.1+ has.js Wink Toolkit 1.4+ es5shim EmbedJS XStyle Lightstreamer (next put-selector rev) Persevere OpenCoWeb Pintura PhoneGap/Cordova Perstore Firebug 1.8+ Tunguska Zazl Twine© SitePen, Inc. All Rights Reserved
    13. 13. 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© SitePen, Inc. All Rights Reserved
    14. 14. Key Components© SitePen, Inc. All Rights Reserved
    15. 15. 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© SitePen, Inc. All Rights Reserved
    16. 16. Loaders The source code that can load AMD modules efficiently Dojo Loader RequireJS curl.js Almond Others© SitePen, Inc. All Rights Reserved
    17. 17. 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© SitePen, Inc. All Rights Reserved
    18. 18. 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© SitePen, Inc. All Rights Reserved
    19. 19. Dojo Foundation Packages Provides one-stop 60 Packages and growing navigation to a variety of Will continue to grow useful JavaScript once advertised packages© SitePen, Inc. All Rights Reserved
    20. 20. Creating and Distributing Modules© SitePen, Inc. All Rights Reserved
    21. 21. 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© SitePen, Inc. All Rights Reserved
    22. 22. 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© SitePen, Inc. All Rights Reserved
    23. 23. require() // Were 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"); })© SitePen, Inc. All Rights Reserved
    24. 24. 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© SitePen, Inc. All Rights Reserved
    25. 25. 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 - dont explicitly identify your modules!© SitePen, Inc. All Rights Reserved
    26. 26. Creating a widget before // 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"); });© SitePen, Inc. All Rights Reserved
    27. 27. Creating a widget with define + declare // 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!© SitePen, Inc. All Rights Reserved
    28. 28. // 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?!?© SitePen, Inc. All Rights Reserved
    29. 29. Issue: Dependencies mis-match // 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?!?© SitePen, Inc. All Rights Reserved
    30. 30. Solution #1: Don’t use (all of) them // 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”); } });© SitePen, Inc. All Rights Reserved
    31. 31. Taking it further... // 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”); } });© SitePen, Inc. All Rights Reserved
    32. 32. define() 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 // an AMD module as a plain object define({ enabled: true, delay: 500 });© SitePen, Inc. All Rights Reserved
    33. 33. Key differences between define, dojo.provide AMD is less verbose AMD is fully self-encapsulated No references to global variables or the modules own package name Faster scope lookups Better minification Impossible to forget a dependency and still have working code Zero global namespace pollution Completely portable© SitePen, Inc. All Rights Reserved
    34. 34. 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© SitePen, Inc. All Rights Reserved
    35. 35. 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)© SitePen, Inc. All Rights Reserved
    36. 36. 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 modules dependency list Relative module lookups dont work with global require© SitePen, Inc. All Rights Reserved
    37. 37. Context-sensitive require 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(); }); }); });© SitePen, Inc. All Rights Reserved
    38. 38. 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© SitePen, Inc. All Rights Reserved
    39. 39. exports // The following are similar define(["exports"], function(exports) { exports.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.© SitePen, Inc. All Rights Reserved
    40. 40. 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© SitePen, Inc. All Rights Reserved
    41. 41. 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© SitePen, Inc. All Rights Reserved
    42. 42. Configuration Object Configuration data (like dojoConfig) Can be passed as the first parameter in require require({ cacheBust:new Date(), waitSeconds:5 });© SitePen, Inc. All Rights Reserved
    43. 43. Portable Modules How do you share portable modules with the community?© SitePen, Inc. All Rights Reserved
    44. 44. Portable Modules How do you share portable modules with the community? Publish them in the Dojo Foundation Package Repo!© SitePen, Inc. All Rights Reserved
    45. 45. Portable Modules How do you share portable modules with the community? Use or extend CJS module template to define your module© SitePen, Inc. All Rights Reserved
    46. 46. Module Templatehttps://github.com/kriszyp/commonjs-package-template/blob/master/component.js© SitePen, Inc. All Rights Reserved
    47. 47. 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© SitePen, Inc. All Rights Reserved
    48. 48. Plugins© SitePen, Inc. All Rights Reserved
    49. 49. 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© SitePen, Inc. All Rights Reserved
    50. 50. dojo/text 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 RequireJSs text plugin define([ "dojo/text!./quotes.txt" ], function (quotes) { // quotes will simply be the content of the file, // so well 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())]); });© SitePen, Inc. All Rights Reserved
    51. 51. dojo/i18n Loads an internationalization bundle Replaces dojo.requireLocalization and dojo.getLocalization Compatible with RequireJSs i18n plugin 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" } );© SitePen, Inc. All Rights Reserved
    52. 52. dojo/domReady and dojo/ready Ensures the module does not resolve until the DOM is ready Replaces dojo.ready Compatible with RequireJSs domReady plugin 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 wont run until the DOM has loaded, the parser has run, and other // modules like dijit/hccss have also loaded. var dialog = registry.byId("myDialog"); ... }); });© SitePen, Inc. All Rights Reserved
    53. 53. dojo/has Allows modules to be conditionally loaded, using has.js features Replaces dojo.requireIf require([ "dojo/has!dom-addeventlistener?./events/w3cHandlers:./events/ ieHandlers" ], function (eventHandlers) { // Do something with eventHandlers });© SitePen, Inc. All Rights Reserved
    54. 54. Loading non-AMD code Special module identifiers can be used to load arbitrary, non-AMD scripts as dependencies, in which case the modules 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© SitePen, Inc. All Rights Reserved
    55. 55. Loader Configuration© SitePen, Inc. All Rights Reserved
    56. 56. 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" }   ] });© SitePen, Inc. All Rights Reserved
    57. 57. 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)© SitePen, Inc. All Rights Reserved
    58. 58. Mapping Packages 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. // 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) { });© SitePen, Inc. All Rights Reserved
    59. 59. Demos© SitePen, Inc. All Rights Reserved
    60. 60. dQuery (Dojo + jQuery)https://github.com/jthomas/amd_examples/tree/master/dojo_and_jquery© SitePen, Inc. All Rights Reserved
    61. 61. dQuery (Dojo + jQuery) <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> https://github.com/jthomas/amd_examples/tree/master/dojo_and_jquery© SitePen, Inc. All Rights Reserved
    62. 62. Dojools (MooTools + Dojo)https://github.com/jthomas/amd_examples/tree/master/dojo_and_mootools© SitePen, Inc. All Rights Reserved
    63. 63. 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© SitePen, Inc. All Rights Reserved
    64. 64. dgrid and Dojo Storehttps://github.com/SitePen/dgrid/blob/master/test/JsonRest.html© SitePen, Inc. All Rights Reserved
    65. 65. dgrid and Dojo Store 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); }; // ...© SitePen, Inc. All Rights Reserved
    66. 66. dgrid and Dojo Store (continued) // ... 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"); });© SitePen, Inc. All Rights Reserved
    67. 67. dgrid and Dojo Storehttps://github.com/SitePen/dgrid/blob/master/test/JsonRest.html© SitePen, Inc. All Rights Reserved
    68. 68. Dojo Foundation Community Apphttp://vepi-2k3208aja.acs.cnet-caen.fr/df/© SitePen, Inc. All Rights Reserved
    69. 69. Dojo Foundation Community App 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; } });© SitePen, Inc. All Rights Reserved
    70. 70. xstyle 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 define(["xstyle!./path/to/example.css"], function(){ // module starts after css is loaded });© SitePen, Inc. All Rights Reserved
    71. 71. BBC News and BBC iPlayerhttp://blog.responsivenews.co.uk/post/18948466399/cutting-the-mustard© SitePen, Inc. All Rights Reserved
    72. 72. 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."© SitePen, Inc. All Rights Reserved
    73. 73. Landmarks© SitePen, Inc. All Rights Reserved
    74. 74. 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© SitePen, Inc. All Rights Reserved
    75. 75. package.json { "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" }© SitePen, Inc. All Rights Reserved
    76. 76. run.js require({ baseUrl: "", packages: [ "dojo", "dojox", "dijit", "app" ], selectorEngine: "lite" }, [ "app" ]);© SitePen, Inc. All Rights Reserved
    77. 77. esriApi.js 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" ] ] }; // ...© SitePen, Inc. All Rights Reserved
    78. 78. main.js 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);© SitePen, Inc. All Rights Reserved
    79. 79. main.js (continued) 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; });© SitePen, Inc. All Rights Reserved
    80. 80. Result: Modular Tools Tools to mix and match to Modular enough for very create your app simple projects, flexible Separate data from UI and consistent enough to logic simple and handle the most seamlessly challenging, feature-rich© SitePen, Inc. All Rights Reserved web apps
    81. 81. Plans and Docs© SitePen, Inc. All Rights Reserved
    82. 82. 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© SitePen, Inc. All Rights Reserved
    83. 83. Migration Cheat Sheet (Drafts)https://docs.google.com/spreadsheet/ccc?key=0Avm8Hjje-xiXdFBVSURNdFpHSmNzOXlMcnU5V3k1Rmc#gid=0 andhttp://livedocs.dojotoolkit.org/releasenotes/migration-2.0© SitePen, Inc. All Rights Reserved
    84. 84. 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© SitePen, Inc. All Rights Reserved
    85. 85. © SitePen, Inc. All Rights Reserved
    86. 86. SitePen: We Build Extraordinary Apps. Desktop and Mobile Web App professional services Creators and leaders of open source web software© SitePen, Inc. All Rights Reserved
    87. 87. Thanks! Q&A SitePen sitepen.com Dojo Toolkit dojotoolkit.org Twitter: @dylans @thomasj @sitepen @dojo© SitePen, Inc. All Rights Reserved

    ×