Loading…

Flash Player 9 (or above) is needed to view presentations.
We have detected that you do not have it on your computer. To install it, go here.

Like this presentation? Why not share!

YUI 3: Below the Surface

on

  • 7,312 views

YUIConf 2010. A look at the how and why of YUI 3's module infrastructure and DOM abstraction layer (Node) and how to add special attributes, new methods, and synthetic DOM events for Node.

YUIConf 2010. A look at the how and why of YUI 3's module infrastructure and DOM abstraction layer (Node) and how to add special attributes, new methods, and synthetic DOM events for Node.

Statistics

Views

Total Views
7,312
Views on SlideShare
7,208
Embed Views
104

Actions

Likes
21
Downloads
213
Comments
1

5 Embeds 104

http://lanyrd.com 98
http://www.slideshare.net 3
http://twicli.neocat.jp 1
http://ja.favstar.fm 1
http://reader.livedoor.com 1

Accessibility

Upload Details

Uploaded via as Apple Keynote

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
  • Hi Luke! One question: how a windows user can use a download version of your presentation? Openoffice is free and can open ppt files but there seems to be no way of opening a keynote file on windows and I would love to see your presentation offline. Can you export it to a more convenient format? Thanks for sharing.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

YUI 3: Below the Surface Presentation Transcript

  • 1. YUI3: Below the surface Luke Smith @ls_n
  • 2. C12H22O11
  • 3. C12H22O11
  • 4. I'm not going to talk about C12H22O11
  • 5. I am going to talk about
  • 6. 1. Modules 2. DOM abstraction
  • 7. JavaScript!!!!
  • 8. 1.YUI().use(...); // WTF?
  • 9. JavaScript needs modules
  • 10. JavaScript needs modules
  • 11. <script>
  • 12. <script> • load + execute • synchronous by default • shared global context • ignorant of the system
  • 13. Inadequate control
  • 14. Modules can help
  • 15. Modules can help Did someone say "module pattern?"
  • 16. holy crap inte , the rne t in re was 200 an 3?
  • 17. w hile a ok t to tha
  • 18. "module pattern" var api = (function () { var privateProperty = "Neener neener neener!"; function privateFn() { return "You can't catch me!"; } return { publicProperty: "public", publicMethod: function () { return "I'm " + api.publicProperty; }, protectedMethod: function () { return privateProperty + " " + privateFn(); } }; })();
  • 19. http://snook.ca/archives/javascript/no-love-for-module-pattern Apr 2009
  • 20. Closure variations
  • 21. Closure variations (function () { var thisCanBeCompressed = "YAY!"; function asCanThis() { return "A smaller minified file!"; } })(); (function(){var A="YAY!";function B(){return "A smaller minified file!";}})();
  • 22. Closure variations undefined = "Oh no you didn't!"; (function (window, document, undefined) { /* window is the global object undefined is the REAL undefined */ })(this, this.document);
  • 23. Closure variations (function (original) { chef.cook = function (recipe) { recipe.add("Bacon"); return original.apply(this, arguments); } })(chef.cook);
  • 24. Closure variations And plenty more
  • 25. What we did with it YUI.add("my-awesome-module", function (Y) { var privateProperty = "Neener neener neener!"; function privateFn() { return "You can't catch me!"; } Y.api = { publicProperty: "public", publicMethod: function () { return "I'm " + this.publicProperty; }, protectedMethod: function () { return privateProperty + " " + privateFn(); } }; });
  • 26. What we did with it YUI.add("my-awesome-module", function (Y) { var privateProperty = "Neener neener neener!"; function privateFn() { return "You can't catch me!"; } Y.api = { publicProperty: "public", publicMethod: function () { return "I'm " + this.publicProperty; }, protectedMethod: function () { return privateProperty + " " + privateFn(); } }; });
  • 27. What we did with it YUI.add("my-awesome-module", function (Y) { var privateProperty = "Neener neener neener!"; function privateFn() { return "You can't catch me!"; } Y.api = { publicProperty: "public", publicMethod: function () { return "I'm " + this.publicProperty; }, protectedMethod: function () { return privateProperty + " " + privateFn(); } }; }); Look Ma, no execution!
  • 28. Register != execute <script src="my-dependency.js"></script> <script src="my-awesome-module.js"></script>
  • 29. Register != execute <script src="my-awesome-module.js"></script> <script src="my-dependency.js"></script>
  • 30. use() == execute Y.use('my-dependency', 'my-awesome-module'); Y? Be cau se it's aw eso me !
  • 31. Enter YUI() var Y = YUI();
  • 32. YUI is
  • 33. YUI is • Module registry YUI.add(...);
  • 34. YUI is • Module registry YUI.add(...); • Sandbox factory var Y = YUI();
  • 35. YUI is • Module registry YUI.add(...); • Sandbox factory var Y = YUI(); • A very talented Japanese musician
  • 36. YUI is • Module registry YUI.add(...); • Sandbox factory var Y = YUI();
  • 37. Y is • Module execution controller • YUI generated sandbox • Module API host
  • 38. Y executes modules var Y = YUI(); Y.use("autocomplete"); // execute! var autocomplete = new Y.AutoComplete({ inputNode: "#movie", source: yqlMovieQuery });
  • 39. Y is a YUI sandbox var Y = YUI(); Y.use("autocomplete"); var autocomplete = new Y.AutoComplete({ inputNode: "#movie", source: yqlMovieQuery });
  • 40. Y is a YUI sandbox YUI().use("autocomplete", function (Y) { var autocomplete = new Y.AutoComplete({ inputNode: "#movie", source: yqlMovieQuery }); ...
  • 41. Y is a YUI sandbox YUI().use("autocomplete", function (Y) { var autocomplete = new Y.AutoComplete({ inputNode: "#movie", source: yqlMovieQuery }); ...
  • 42. Y is a YUI sandbox YUI().use("autocomplete", function (Y) { var autocomplete = new Y.AutoComplete({ inputNode: "#movie", source: yqlMovieQuery }); Y.log("This is my Y. " + "There are many like it, " + "but this one is mine.");
  • 43. Y is where the APIs are // Step 1. Module registration YUI.add("autocomplete", function (Y) { Y.AutoComplete = function () { ... }; ... }); // Step 2. Module execution YUI().use("autocomplete", function (Y) { var autocomplete = new Y.AutoComplete(...); });
  • 44. Y is where the APIs are // Step 1. Module registration YUI.add("autocomplete", function (Y) { Y.AutoComplete = function () { ... }; ... }); // Step 2. Module execution YUI().use("autocomplete", function (Y) { var autocomplete = new Y.AutoComplete(...); });
  • 45. Y is where the APIs are YUI().use("autocomplete", function (Y) {
  • 46. Y is where the APIs are Y YUI().use("autocomplete", function (Y) {
  • 47. Y is where the APIs are Y YUI().use("autocomplete", function (Y) { autocomplete.js YUI.add("autocomplete", function (Y) { Y.AutoComplete = function () { ... }; ... });
  • 48. Y is where the APIs are Y YUI().use("autocomplete", function (Y) { autocomplete.js YUI.add("autocomplete", function (Y) { Y.AutoComplete = function () { ... }; ... });
  • 49. Y is where the APIs are Y YUI().use("autocomplete", function (Y) { autocomplete.js YUI.add("autocomplete", function (Y) { Y.AutoComplete = function () { ... }; ... });
  • 50. Y is where the APIs are Y YUI().use("autocomplete", function (Y) { autocomplete.js YUI.add("autocomplete", function (Y) { Y.AutoComplete = function () { ... }; ... });
  • 51. Y is where the APIs are Y YUI().use("autocomplete", function (Y) { autocomplete.js YUI.add("autocomplete", function (Y) { Y.AutoComplete = function () { ... }; ... });
  • 52. Y is where the APIs are YUI().use("autocomplete", function (Y) { var autocomplete = new Y.AutoComplete({ inputNode: "#movie", source: yqlMovieQuery });
  • 53. <script> • load + execute • synchronous by default • shared global context • ignorant of the system
  • 54. Modules • load + execute • synchronous by default • shared global context • ignorant of the system
  • 55. Modules • load + execute (register vs execute) • synchronous by default • shared global context • ignorant of the system
  • 56. Modules • load + execute (register vs execute) • synchronous by default (no need to be) • shared global context • ignorant of the system
  • 57. Modules • load + execute (register vs execute) • synchronous by default (no need to be) • shared global context (sandboxing) • ignorant of the system
  • 58. Just add meta YUI.add("autocomplete-base", function (Y) { /* Module API declared here */ }, // version '3.3.0pr1', // meta { optional: ['jsonp', 'yql'], requires: ['array-extras', 'base-build', 'event-valuechange', 'node-base'] });
  • 59. Modules • load + execute (register vs execute) • synchronous by default (no need to be) • shared global context (sandboxing) • ignorant of the system (just add meta)
  • 60. Modules can help • Loading decoupled from execution • Modules can be loaded out of order and asynchronously • Implementation context can be sandboxed • Metadata creates a structural relationship between modules
  • 61. But that's just the beginning
  • 62. While we're at it, load modules on demand Y.one("#tab2").on(["mouseenter","focus"], function () { Y.use("dd", function () { /* only needed if the user enters tab */ }); });
  • 63. While we're at it, resolve dependencies YUI().use("dd", function (Y) { /* dd and dependencies loaded */ });
  • 64. While we're at it, avoid duplication /** * Remove superceded modules and loaded modules. Called by * calculate() after we have the mega list of all dependencies * @method _reduce * @return {object} the reduced dependency hash. * @private */ _reduce: function(r) { r = r || this.required; var i, j, s, m, type = this.loadType; for (i in r) { if (r.hasOwnProperty(i)) { m = this.getModule(i); // remove if already loaded if (((this.loaded[i] || ON_PAGE[i]) && !this.forceMap[i] && !this.ignoreRegistered) || (type && m && m.type != type)) {
  • 65. While we're at it, combine requests for (i = 0; i < len; i++) { if (m && (m.type === type) && (m.combine || !m.ext)) { ... url += frag; if (i < (len - 1)) { url += '&'; } combining.push(m.name); } }
  • 66. While we're at it, leverage the CDN /** * Base path for the combo service * @property comboBase * @type string * @default http://yui.yahooapis.com/combo? */ self.comboBase = Y.Env.meta.comboBase;
  • 67. While we're at it, conditionally load browser specific logic "history": { "plugins": { "history-hash-ie": { "condition": { "trigger": "history-hash", "test": "history-hash-ie-test.js" }, ...
  • 68. ...you get the point (we're still at it)
  • 69. Old and busted <script src="one.js"></script> <script src="three.js"></script> <script src="two.js"></script> <script src="four.js"></script> <!--[if IE 6]> <script src="four-ie.js"></script> <![endif]> <script src="cheetos.js"></script> <script src="redbull.js"></script> <script src="mustache.js"></script> <script src="brownchicken.js"></script> <script> /* one, three, two? BOOM */ </script>
  • 70. New hotness <script src="yui-min.js"></script> <script> YUI().use("brownchicken", function (Y) { new Y.Cow({ color: "brown"}); }); </script>
  • 71. Oh yeah, and it works for CSS
  • 72. And in Node.js
  • 73. And in YQL
  • 74. YUI.add(...); YUI().use(...);
  • 75. 2. DOM isn't broken it's just misunderstood
  • 76. DOM level 3 was a W3C recommendation in April 2004
  • 77. DOM level 3 was a W3C recommendation in April 2004 • IE6 was 3 years old
  • 78. DOM level 3 was a W3C recommendation in April 2004 • IE6 was 3 years old • Firefox was 7 months from v1.0
  • 79. DOM level 3 was a W3C recommendation in April 2004 • IE6 was 3 years old • Firefox was 7 months from v1.0 • Opera was ...also around
  • 80. Today :) DOM specification
  • 81. Today :(
  • 82. They're close :)
  • 83. http://www.quirksmode.org/mobile/mobilemarket.html
  • 84. :(
  • 85. We need normalization
  • 86. YUI 2 Normalization by utility YAHOO.util.Dom.setAttribute(myLabel,'for','my-input');
  • 87. Browser DOM
  • 88. Y.u.Dom Browser DOM
  • 89. Implementation Y.u.Dom Browser DOM
  • 90. Problem:
  • 91. Problem: Implementation
  • 92. Problem: Implementation ??? Developers must know a utility method is needed
  • 93. YUI 3 Normalization by utility Y.DOM.setAttribute(myLabel,'for','my-input');
  • 94. YUI 3 Normalization by utility Y.DOM.setAttribute(myLabel,'for','my-input'); Utility by abstraction myLabelNode.setAttribute('for','my-input');
  • 95. Browser DOM
  • 96. Y.DOM S M? Browser DOM F
  • 97. Y.Node Y.DOM S M? Browser DOM F
  • 98. Implementation Y.Node * not to scale Y.DOM S M? Browser DOM F
  • 99. Oh look, an abstraction layer! Y.Node
  • 100. Abstraction FTW Y Load the optimal set of code for this environment Y.DOM Address specific DOM variances Provide convenience methods Y.Node Expose unified API and extension points
  • 101. Y.Node
  • 102. • Attributes • Methods • Events Y.Node
  • 103. Add custom attributes /** * Configuration for special attribute handling * * @property ATTRS * @static * ... */ Y.Node.ATTRS = {...}
  • 104. Add custom attributes Y.Node.ATTRS.outerHTML = { readOnly: true, getter: function () { var node = this._node, par = node.parentNode.cloneNode(false); par.appendChild(node.cloneNode(true)); return par.innerHTML; } };
  • 105. Add custom attributes YUI.add('node-outerhtml', function (Y) { Y.Node.ATTRS.outerHTML = {...} }, '0.0.1', { requires: ['node-base'] }); YUI().use('node-outerhtml', function (Y) { Y.one('body').get('outerHTML'); // <body...> });
  • 106. Add custom methods /** * Adds methods to the Y.Node prototype * * @method addMethod * @static * ... */ Y.Node.addMethod = function(name, fn) {...}
  • 107. Add custom methods Y.Node.addMethod('commonAncestor', function (me, other) { var ancestors = this.ancestors(), common = null; Y.one(other).ancestors().some(function (node) { if (ancestors.indexOf(node) > -1) { common = node; return true; } }); return common; });
  • 108. Add custom methods YUI.add('node-commonancestor', function (Y) { Y.Node.addMethod('commonAncestor', ...); }, '0.0.1', { requires: ['node-base'] }); YUI().use("node-commonancestor", "node-outerhtml", function (Y) { Y.one("#a").commonAncestor("#b").get("outerHTML"); });
  • 109. Preserve the abstraction Y.Node.addMethod = function(name, fn) { Y_Node.prototype[name] = function() { ... ret = fn.apply(node, args); if (ret) { ret = Y.Node.scrubVal(ret, node); } Y.Node.prototype.get = function(attr) { ... if (val) { val = Y.Node.scrubVal(val, this); } else ...
  • 110. Preserve the abstraction Y.Node.scrubVal = function(val, node) { // only truthy values are risky if (val) { // safari nodeList === function if (typeof val == 'object' || typeof val == 'function') { // node || window if (NODE_TYPE in val || Y.DOM.isWindow(val)) { val = Y.one(val); // NodeList, DOM collection, or array of DOM Nodes } else if ((val.item && !val._nodes) || (val[0] && val[0].nodeType)) val = Y.all(val); } } } else if (typeof val === 'undefined') { val = node; // for chaining } else if (val === null) { val = null; // IE: DOM null not the same as null } return val; };
  • 111. Code slides!
  • 112. In English, please Y.Node.scrubVal = function(val, node) { • Return a Node or NodeList instance };
  • 113. In English, please Y.Node.scrubVal = function(val, node) { • Return a Node or NodeList instance • or return the origin Node (chainable) };
  • 114. In English, please Y.Node.scrubVal = function(val, node) { • Return a Node or NodeList instance • or return the origin Node (chainable) • or return null };
  • 115. In English, please Y.Node.scrubVal = function(val, node) { • Return a Node or NodeList instance • or return the origin Node (chainable) • or return null • DO NOT return DOM nodes };
  • 116. Preserve the abstraction (Your part) document.createElement("p"); window.location.hash = "browns";
  • 117. Preserve the abstraction (Your part) document.createElement("p"); window.location.hash = "browns";
  • 118. Preserve the abstraction (Your part) Y.config.doc.createElement("p"); Y.config.win.location.hash = "browns";
  • 119. now.on("to", events);
  • 120. ...to be continued. Yay events! http://developer.yahoo.com/yui/theater/video.php?v=smith-yuiconf2009-events
  • 121. Add new DOM events Y.Env.evt.plugins.konami = Y.Node.DOM_EVENTS.konami = { on: function (type, fn, ctx) { var progress = {}, handlers = {}, keys = [38,38,40,40,37,39,37,39,66,65], ... node.on("keydown", _checkProgress); return detachHandle; } (circa 2009)
  • 122. Plumbing is there, but Have you seen me? API
  • 123. Add new DOM events Y.Event.define('yuiconf', { on: function (node, sub, notifier) { node.on("keyup", function (e) { var val = (this.get("value") || '').toLowerCase(); if (val.indexOf("yuiconf") > -1) { notifier.fire(e); } }); }, ... }); Y.one("#Nov8").on("yuiconf", horns); (today)
  • 124. Add new DOM events Y.Event.define('yuiconf', { on: function (node, sub, notifier) { sub.detachHandle = node.on("keyup", function (e) { ... }); }, detach: function (node, sub, notifier) { sub.detachHandle.detach(); }, ... }); Y.one("#Nov8").detach("yuiconf", horns); (today)
  • 125. Add new DOM events Y.Event.define('yuiconf', { on: function (node, sub, notifier) {...}, detach: function (node, sub, notifier) {...}, delegate: function (node, sub, notifier, filter) { ... }, }); Y.one("#calendar").delegate("yuiconf", horns, "input"); (today)
  • 126. Summary
  • 127. Modules are the future
  • 128. Modules are the future so sayeth the Crock
  • 129. The DOM is a mess
  • 130. The DOM is a mess again
  • 131. inadequate system + abstraction opportunity
  • 132. YUI 3 exposes that opportunity to you
  • 133. Thank you
  • 134. Borrowed Images • http://upload.wikimedia.org/wikipedia/commons/7/7d/Sucrose-rodmodel.png • http://www.look-good-feel-great-secrets.com/images/sugar.jpg • http://www.funonthenet.in/images/stories/forwards/Roller-Coaster/roller- coaster-2.jpg • http://jpopcdcovers.files.wordpress.com/2009/07/yui_again_cd.jpg? w=600&amp;h=600 • http://www.roger-moore.com/sirrogermoore/april27.jpg • http://redstatebluestate.mlblogs.com/assets_c/2009/05/Herve%20Villechaize- thumb-199x295-1187651.jpg • Browser icons via http://www.morcha.net/post/46.html and http:// browserversionicons.com/ • http://forsythe4kc.com/uploaded_images/HeadExplodeBig.gif • http://zbths99.weebly.com/uploads/1/9/3/5/1935885/398529.jpg?361x501