Your SlideShare is downloading. ×
Building Non-shit APIs with JavaScript
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×

Saving this for later?

Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime - even offline.

Text the download link to your phone

Standard text messaging rates apply

Building Non-shit APIs with JavaScript

12,406
views

Published on

As given at JSConf 2011.

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,406
On Slideshare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
89
Comments
1
Likes
18
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. Your JS Library Dan Webb AKA @danwrongTuesday, May 3, 2011
  • 2. Tuesday, May 3, 2011
  • 3. In the beginning...Tuesday, May 3, 2011
  • 4. In the beginning...Tuesday, May 3, 2011
  • 5. $("p.surprise").addClass("ohmy").show("slow");Tuesday, May 3, 2011
  • 6. We all know what happened next... jQuery The RestTuesday, May 3, 2011
  • 7. Why?Tuesday, May 3, 2011
  • 8. Internals were not important...Tuesday, May 3, 2011
  • 9. ...what had John created was a great interfaceTuesday, May 3, 2011
  • 10. "All programmers are API designers" Joshua Bloch (http://lcsd05.cs.tamu.edu/slides/keynote.pdf)Tuesday, May 3, 2011
  • 11. The API is priority #1Tuesday, May 3, 2011
  • 12. ❖ Predictability ❖ Simplicity ❖ FlexibilityTuesday, May 3, 2011
  • 13. PredictabilityTuesday, May 3, 2011
  • 14. Tuesday, May 3, 2011 RTFM
  • 15. Short attention spanTuesday, May 3, 2011
  • 16. Think about your audience...Tuesday, May 3, 2011
  • 17. ...use conventions people already knowTuesday, May 3, 2011
  • 18. Language conventions and standard libraryTuesday, May 3, 2011
  • 19. THIS IS JAVASCRIPTTuesday, May 3, 2011
  • 20. useCamelCase, yesReally.Tuesday, May 3, 2011
  • 21. Be careful with polyfillsTuesday, May 3, 2011
  • 22. Popular JS librariesTuesday, May 3, 2011
  • 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. The problem domainTuesday, May 3, 2011
  • 25. a.internal { color: #44e534; text-decoration: none; } $(a.external).css({ color: #44e534, textDecoration: none });Tuesday, May 3, 2011
  • 26. Example: creating a DOM BuilderTuesday, May 3, 2011
  • 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. 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. 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. 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. 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. SimplicityTuesday, May 3, 2011
  • 33. Tuesday, May 3, 2011
  • 34. Don’t make me RTFM again...Tuesday, May 3, 2011
  • 35. Sensible defaultsTuesday, May 3, 2011
  • 36. Tuesday, May 3, 2011
  • 37. Tuesday, May 3, 2011
  • 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. element.addEventListener(input, function() { // do some front-end magic }, false);Tuesday, May 3, 2011
  • 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. Use options hashes for optional argumentsTuesday, May 3, 2011
  • 42. evt.initMouseEvent("click", { bubble: false, relatedTarget: thing });Tuesday, May 3, 2011
  • 43. http://blog.rebeccamurphey.com/objects-as- arguments-in-javascript-where-do-yTuesday, May 3, 2011
  • 44. Function calls should read wellTuesday, May 3, 2011
  • 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. Mask complexity if possibleTuesday, May 3, 2011
  • 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. xd.connect({ src: http://danwebb.net/receiver }, function(con) { rpc(con).call(getData, function(result) { alert(result); }); });Tuesday, May 3, 2011
  • 49. var con = xd.connect({ src: http://danwebb.net/receiver }); rpc(con).call(getData, function(result) { alert(result); });Tuesday, May 3, 2011
  • 50. Back to the DOM BuilderTuesday, May 3, 2011
  • 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. 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. 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. FlexibilityTuesday, May 3, 2011
  • 55. Tuesday, May 3, 2011
  • 56. Tuesday, May 3, 2011
  • 57. Tuesday, May 3, 2011
  • 58. Remember: you cant please everyoneTuesday, May 3, 2011
  • 59. Don’t try to second guess every use caseTuesday, May 3, 2011
  • 60. Options hashes != flexibilityTuesday, May 3, 2011
  • 61. 28 options!Tuesday, May 3, 2011
  • 62. Add hackabilityTuesday, May 3, 2011
  • 63. public, internal, protectedTuesday, May 3, 2011
  • 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. ...using functionsTuesday, May 3, 2011
  • 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. ..inheritanceTuesday, May 3, 2011
  • 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. ..duck typingTuesday, May 3, 2011
  • 70. Meanwhile, back in DOM Builder land...Tuesday, May 3, 2011
  • 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. 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. Create a framework for solving your problem...Tuesday, May 3, 2011
  • 74. ...then build your library on top of thatTuesday, May 3, 2011
  • 75. You got yourself a plugin systemTuesday, May 3, 2011
  • 76. Build tools to solve the problemTuesday, May 3, 2011
  • 77. ❖ Design up front ❖ Make use of conventions ❖ Don’t make me think ❖ Build in hackabilityTuesday, May 3, 2011
  • 78. Questions? @danwrongTuesday, May 3, 2011
  • 79. @jointheflock twitter.com/jobs dan@twitter.comTuesday, May 3, 2011
  • 80. Eye of the BeholderTuesday, May 3, 2011
  • 81. ChainingTuesday, May 3, 2011