Your JS Library                       Dan Webb AKA @danwrongTuesday, May 3, 2011
Tuesday, May 3, 2011
In the beginning...Tuesday, May 3, 2011
In the beginning...Tuesday, May 3, 2011
$("p.surprise").addClass("ohmy").show("slow");Tuesday, May 3, 2011
We all know what                       happened next...                                      jQuery                       ...
Why?Tuesday, May 3, 2011
Internals were not                       important...Tuesday, May 3, 2011
...what had John created                       was a great interfaceTuesday, May 3, 2011
"All programmers are                                     API designers"                       Joshua Bloch (http://lcsd05....
The API is priority #1Tuesday, May 3, 2011
❖ Predictability                       ❖ Simplicity                       ❖ FlexibilityTuesday, May 3, 2011
PredictabilityTuesday, May 3, 2011
Tuesday, May 3, 2011                       RTFM
Short attention spanTuesday, May 3, 2011
Think about your                       audience...Tuesday, May 3, 2011
...use conventions people                       already knowTuesday, May 3, 2011
Language conventions                       and standard libraryTuesday, May 3, 2011
THIS IS JAVASCRIPTTuesday, May 3, 2011
useCamelCase, yesReally.Tuesday, May 3, 2011
Be careful with polyfillsTuesday, May 3, 2011
Popular JS librariesTuesday, May 3, 2011
var paper = Raphael(10, 50, 320, 200);                       var c = paper.circle(50, 40, 10);                       c.att...
The problem domainTuesday, May 3, 2011
a.internal {                         color: #44e534;                         text-decoration: none;                       ...
Example: creating a                       DOM BuilderTuesday, May 3, 2011
node.innerHTML = <form method="post" action="/action"> +                                          <p> +                   ...
var html = {                         element: function(name, attributes, children) {                           var node = ...
var form = html.element(                          form,                          { action: /login, method: post }         ...
var form = html.form({ action: /login, method: post },                          [                            html.p({}, [ ...
function elementBuilder(name) {                         return function(attributes, children) {                           ...
SimplicityTuesday, May 3, 2011
Tuesday, May 3, 2011
Don’t make me                       RTFM again...Tuesday, May 3, 2011
Sensible defaultsTuesday, May 3, 2011
Tuesday, May 3, 2011
Tuesday, May 3, 2011
var evt = document.createEvent("MouseEvents");                       evt.initMouseEvent("click", true, true, window,      ...
element.addEventListener(input, function() {                         // do some front-end magic                       }, f...
var evt = document.createEvent("MouseEvents");                       evt.initMouseEvent("click", true, true, window,      ...
Use options hashes for                       optional argumentsTuesday, May 3, 2011
evt.initMouseEvent("click", {                         bubble: false,                         relatedTarget: thing         ...
http://blog.rebeccamurphey.com/objects-as-                       arguments-in-javascript-where-do-yTuesday, May 3, 2011
Function calls                       should read wellTuesday, May 3, 2011
// replace oldNode with newNode - DOM API                       oldNode.parentNode.replaceChild(newNode, oldNode);        ...
Mask complexity if                       possibleTuesday, May 3, 2011
var con = xd.connect({ src: http://danwebb.net/receiver });                       con.bind(ready, function() {            ...
xd.connect({ src: http://danwebb.net/receiver }, function(con) {                         rpc(con).call(getData, function(r...
var con = xd.connect({ src: http://danwebb.net/receiver });                       rpc(con).call(getData, function(result) ...
Back to the DOM BuilderTuesday, May 3, 2011
var form = html.form({ action: /login, method: post },                          [                            html.p({}, [ ...
var form = html.form({ method: post, action: /login },                          html.p(                            html.la...
function elementBuilder(name) {                         return function() {                           var attributes = {},...
FlexibilityTuesday, May 3, 2011
Tuesday, May 3, 2011
Tuesday, May 3, 2011
Tuesday, May 3, 2011
Remember: you cant                       please everyoneTuesday, May 3, 2011
Don’t try to second                       guess every use caseTuesday, May 3, 2011
Options hashes != flexibilityTuesday, May 3, 2011
28 options!Tuesday, May 3, 2011
Add hackabilityTuesday, May 3, 2011
public, internal, protectedTuesday, May 3, 2011
var lib = (function() {                         var private = function() {                            // you cant mess wit...
...using functionsTuesday, May 3, 2011
// https://github.com/ender-js/Ender                       $._select = function(selector, root) {                         ...
..inheritanceTuesday, May 3, 2011
// github.com/danwrong/loadrunner                       function Mustache(path) {                         this.path = path...
..duck typingTuesday, May 3, 2011
Meanwhile, back in                       DOM Builder land...Tuesday, May 3, 2011
function elementBuilder(name) {                         return function() {                           // code collapsed fo...
function Tweet(text, author, timestamp) {                         this.text = text;                         this.author = ...
Create a framework for                       solving your problem...Tuesday, May 3, 2011
...then build your library                       on top of thatTuesday, May 3, 2011
You got yourself a                       plugin systemTuesday, May 3, 2011
Build tools to solve the                       problemTuesday, May 3, 2011
❖   Design up front                       ❖   Make use of conventions                       ❖   Don’t make me think       ...
Questions?                       @danwrongTuesday, May 3, 2011
@jointheflock                       twitter.com/jobs                       dan@twitter.comTuesday, May 3, 2011
Eye of the BeholderTuesday, May 3, 2011
ChainingTuesday, May 3, 2011
Upcoming SlideShare
Loading in...5
×

Building Non-shit APIs with JavaScript

12,856

Published on

As given at JSConf 2011.

Published in: Technology
1 Comment
18 Likes
Statistics
Notes
  • POWERBOAT ADVENTURES SCHEVENINGEN
    POWERBOAT VAREN OP NOORDZEE VOOR DE KUST VAN SCHEVENINGEN
    JETSKI VERHUUR FUN-FANTASY
    BANAANBOOT VAREN OP SCHEVENINGEN
    POWERBOOT VAREN SCHEVENINGEN
    POWERBOAT ADVENTURES SCHEVENINGEN IS HET BEDRIJF VOOR
    EEN UITJE MET EEN POWERBOAT
    POWERBOATS VAN POWERBOATADVENTURES SCHEVENINGEN
    ZIJN GOED VOOER EEN RIT MET 10 PERSONEN TEGELIJK
    DUS EEN BEDRIJFS UITJE MET POWERBOATADVENTURES SCHEVENINGEN IS ZEKER EEN AANRADER
    POWERBOAT ADVENTURES
    JETSKI VERHUUR
    JETSKI HUREN
    WWW.FUN-FANTASY.NL
    WWW.POWERBOOTVAREN.NL
    WWW.POWERBOATADVENTURES.NL

    POWERBOAT ADVENTURES SCHEVENINGEN

    BEDRIJFS UITJE VRIJGEZELLEN FEEST

    FUN-FANTASY JETSKI VERHUUR SCHEVENINGEN

    POWERBOOT VAREN OP NOORDZEE

    INFO 0646711340

    WWW.FUN-FANTASY.NL
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
No Downloads
Views
Total Views
12,856
On Slideshare
0
From Embeds
0
Number of Embeds
4
Actions
Shares
0
Downloads
92
Comments
1
Likes
18
Embeds 0
No embeds

No notes for slide

Transcript of "Building Non-shit APIs with JavaScript"

  1. 1. Your JS Library Dan Webb AKA @danwrongTuesday, May 3, 2011
  2. 2. Tuesday, May 3, 2011
  3. 3. In the beginning...Tuesday, May 3, 2011
  4. 4. In the beginning...Tuesday, May 3, 2011
  5. 5. $("p.surprise").addClass("ohmy").show("slow");Tuesday, May 3, 2011
  6. 6. We all know what happened next... jQuery The RestTuesday, May 3, 2011
  7. 7. Why?Tuesday, May 3, 2011
  8. 8. Internals were not important...Tuesday, May 3, 2011
  9. 9. ...what had John created was a great interfaceTuesday, May 3, 2011
  10. 10. "All programmers are API designers" Joshua Bloch (http://lcsd05.cs.tamu.edu/slides/keynote.pdf)Tuesday, May 3, 2011
  11. 11. The API is priority #1Tuesday, May 3, 2011
  12. 12. ❖ Predictability ❖ Simplicity ❖ FlexibilityTuesday, May 3, 2011
  13. 13. PredictabilityTuesday, May 3, 2011
  14. 14. Tuesday, May 3, 2011 RTFM
  15. 15. Short attention spanTuesday, May 3, 2011
  16. 16. Think about your audience...Tuesday, May 3, 2011
  17. 17. ...use conventions people already knowTuesday, May 3, 2011
  18. 18. Language conventions and standard libraryTuesday, May 3, 2011
  19. 19. THIS IS JAVASCRIPTTuesday, May 3, 2011
  20. 20. useCamelCase, yesReally.Tuesday, May 3, 2011
  21. 21. Be careful with polyfillsTuesday, May 3, 2011
  22. 22. Popular JS librariesTuesday, May 3, 2011
  23. 23. var paper = Raphael(10, 50, 320, 200); var c = paper.circle(50, 40, 10); c.attr("fill", "#f00"); c.show();Tuesday, May 3, 2011
  24. 24. The problem domainTuesday, May 3, 2011
  25. 25. a.internal { color: #44e534; text-decoration: none; } $(a.external).css({ color: #44e534, textDecoration: none });Tuesday, May 3, 2011
  26. 26. Example: creating a DOM BuilderTuesday, May 3, 2011
  27. 27. node.innerHTML = <form method="post" action="/action"> + <p> + <label> + Username: <input type="text" name="username"> + </label> + <label> + Password: <input type="password" name="password"> + </label> + </p> + </form>; var form = document.createElement(form); var p = document.createElement(p); form.setAttribute(action, /login); form.setAttribute(method, post); var usernameLabel = document.createElement(label); var usernameText = document.createTextElement(Username: ); var usernameInput = document.createElement(input); usernameInput.setAttribute(type, text); usernameInput.setAttribute(name, username); form.appendChild(p); p.appendChild(usernameLabel); // ... at this point I decided to give // all this up and become a farmerTuesday, May 3, 2011
  28. 28. var html = { element: function(name, attributes, children) { var node = document.createElement(name); for (var attr in attributes) { node.setAttribute(attr, attributes[attr]); } for (var i=0, len=children.length; i < len; i++) { node.appendChild(children[i]); } return node; } }Tuesday, May 3, 2011
  29. 29. var form = html.element( form, { action: /login, method: post } [ html.element(p, {}, [ html.element(label, {}, [ document.createTextElement(Username: ), html.element(input, { type: text, name: username }, []), // ... you get the idea ]) ]) ] );Tuesday, May 3, 2011
  30. 30. var form = html.form({ action: /login, method: post }, [ html.p({}, [ html.label({}, [ document.createTextElement(Username: ), html.input({ type: text, name: username }, []), // ... you still get the idea, right? ]) ]) ] );Tuesday, May 3, 2011
  31. 31. function elementBuilder(name) { return function(attributes, children) { return html.element(name, attributes, children); } } function generateBuilderFunctions(elements) { for (var i=0, len=elements.length; i < len; i++) { html[elements[i]] = createElementBuilder(elements[i]); } } generateBuilderFunctions("p|div|span|strong|em|img|table|tr| td|th|thead|tbody|tfoot|pre|code|h1|h2|h3|h4|h5|h6|ul|ol|li| form|input|textarea|legend|fieldset|select|option| blockquote|cite|br|hr|dd|dl|dt|address|a|button|abbr| acronym|script|link|style|bdo|ins|del|object|param|col| colgroup|optgroup|caption|label|dfn|kbd|samp|var".split ("|"));Tuesday, May 3, 2011
  32. 32. SimplicityTuesday, May 3, 2011
  33. 33. Tuesday, May 3, 2011
  34. 34. Don’t make me RTFM again...Tuesday, May 3, 2011
  35. 35. Sensible defaultsTuesday, May 3, 2011
  36. 36. Tuesday, May 3, 2011
  37. 37. Tuesday, May 3, 2011
  38. 38. var evt = document.createEvent("MouseEvents"); evt.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);Tuesday, May 3, 2011
  39. 39. element.addEventListener(input, function() { // do some front-end magic }, false);Tuesday, May 3, 2011
  40. 40. var evt = document.createEvent("MouseEvents"); evt.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);Tuesday, May 3, 2011
  41. 41. Use options hashes for optional argumentsTuesday, May 3, 2011
  42. 42. evt.initMouseEvent("click", { bubble: false, relatedTarget: thing });Tuesday, May 3, 2011
  43. 43. http://blog.rebeccamurphey.com/objects-as- arguments-in-javascript-where-do-yTuesday, May 3, 2011
  44. 44. Function calls should read wellTuesday, May 3, 2011
  45. 45. // replace oldNode with newNode - DOM API oldNode.parentNode.replaceChild(newNode, oldNode); // Dojo dojo.place(newNode, oldNode, "replace"); // jQuery $(oldNode).replaceWith(newNode);Tuesday, May 3, 2011
  46. 46. Mask complexity if possibleTuesday, May 3, 2011
  47. 47. var con = xd.connect({ src: http://danwebb.net/receiver }); con.bind(ready, function() { rpc(con).call(getData, function(result) { alert(result); }); });Tuesday, May 3, 2011
  48. 48. xd.connect({ src: http://danwebb.net/receiver }, function(con) { rpc(con).call(getData, function(result) { alert(result); }); });Tuesday, May 3, 2011
  49. 49. var con = xd.connect({ src: http://danwebb.net/receiver }); rpc(con).call(getData, function(result) { alert(result); });Tuesday, May 3, 2011
  50. 50. Back to the DOM BuilderTuesday, May 3, 2011
  51. 51. var form = html.form({ action: /login, method: post }, [ html.p({}, [ html.label({}, [ document.createTextElement(Username: ), html.input({ type: text, name: username }, []), // ... you still get the idea, right? ]) ]) ] );Tuesday, May 3, 2011
  52. 52. var form = html.form({ method: post, action: /login }, html.p( html.label( Username: , html.input({ type: text, name: username }) ), html.label( Password: , html.input({ type: password, name: pass }) ), html.input({ type: submit, value: Login}) ) );Tuesday, May 3, 2011
  53. 53. function elementBuilder(name) { return function() { var attributes = {}, children = [], args = Array.prototype.slice.call(arguments); // if the first arg is not a element or a string then its an attributes hash if (!args[0].nodeType && typeof args[0] != string) { attributes = args.unshift(); } // children can be an array or remaining args if (Array.isArray(args[0])) { args = args[0]; } // add rest of args as children converting any strings to text nodes for (var i=0, len=args.length; i < len; i++) { if (typeof args[i] == string) { children.push(document.createTextNode(args[i])); } else { children.push(args[i]); } } return html.element(name, attributes, children); } }Tuesday, May 3, 2011
  54. 54. FlexibilityTuesday, May 3, 2011
  55. 55. Tuesday, May 3, 2011
  56. 56. Tuesday, May 3, 2011
  57. 57. Tuesday, May 3, 2011
  58. 58. Remember: you cant please everyoneTuesday, May 3, 2011
  59. 59. Don’t try to second guess every use caseTuesday, May 3, 2011
  60. 60. Options hashes != flexibilityTuesday, May 3, 2011
  61. 61. 28 options!Tuesday, May 3, 2011
  62. 62. Add hackabilityTuesday, May 3, 2011
  63. 63. public, internal, protectedTuesday, May 3, 2011
  64. 64. var lib = (function() { var private = function() { // you cant mess with me }; return { _internal: function() { // you probably shouldnt mess with me }, public: function() { // Im part of the API - call me sometime } } }());Tuesday, May 3, 2011
  65. 65. ...using functionsTuesday, May 3, 2011
  66. 66. // https://github.com/ender-js/Ender $._select = function(selector, root) { return Sizzle(selector, root); } $._select = function (selector, root) { return (root || document).querySelectorAll(selector); });Tuesday, May 3, 2011
  67. 67. ..inheritanceTuesday, May 3, 2011
  68. 68. // github.com/danwrong/loadrunner function Mustache(path) { this.path = path; } Mustache.prototype = new loadrunner.Dependency; Mustache.prototype.start = function() { var me = this; $.get(this.path, function(result) { var template = Mustache.parse(result); me.complete(template); }); } using(new Mustache(thing.mustache), function(template) { template.evaluate({ a: yep, b: nope }); });Tuesday, May 3, 2011
  69. 69. ..duck typingTuesday, May 3, 2011
  70. 70. Meanwhile, back in DOM Builder land...Tuesday, May 3, 2011
  71. 71. function elementBuilder(name) { return function() { // code collapsed for clarity // add rest of args as children // converting any strings to text nodes for (var i=0, len=args.length; i < len; i++) { if (typeof args[i] == string) { node = document.createTextNode(args[i]); } else { if (typeof args[i].toDOM == function) { node = args[i].toDOM(); } else { node = args[i]; } } children.push(node); } return html.element(name, attributes, children); } }Tuesday, May 3, 2011
  72. 72. function Tweet(text, author, timestamp) { this.text = text; this.author = author; this.timestamp = timestamp; } Tweet.prototype.toDOM = function() { return html.p( { class: tweet }, html.strong(this.author.name), this.text, html.span({ class: time }, this.timestamp) ); } var timeline = // an array of Tweet objects document.appendChild(html.div({ id: timeline }, timeline));Tuesday, May 3, 2011
  73. 73. Create a framework for solving your problem...Tuesday, May 3, 2011
  74. 74. ...then build your library on top of thatTuesday, May 3, 2011
  75. 75. You got yourself a plugin systemTuesday, May 3, 2011
  76. 76. Build tools to solve the problemTuesday, May 3, 2011
  77. 77. ❖ Design up front ❖ Make use of conventions ❖ Don’t make me think ❖ Build in hackabilityTuesday, May 3, 2011
  78. 78. Questions? @danwrongTuesday, May 3, 2011
  79. 79. @jointheflock twitter.com/jobs dan@twitter.comTuesday, May 3, 2011
  80. 80. Eye of the BeholderTuesday, May 3, 2011
  81. 81. ChainingTuesday, May 3, 2011
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×