Your SlideShare is downloading. ×

DrupalCon jQuery

9,032
views

Published on

Presentation from DrupalCon 2011 in Chicago

Presentation from DrupalCon 2011 in Chicago

Published in: Design

0 Comments
12 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
9,032
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
90
Comments
0
Likes
12
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. CRAFTING APPINTERFACES WITH Presented by Nathan Smith
  • 2. Carpal Tunnel ReliefNote: Don’t feel like you need to write all ofthis down. The slides are available here...http://www.slideshare.net/nathansmith/drupalcon-jquery
  • 3. “Allow myself to... introduce myself” I work (from home) for HP as a front-end developer. I’m best known for making a helpful 5.6 KB CSS file.
  • 4. Shh... My secret in-house code reviewer Note: This was shot hastily with a camera phone. I make no claims of being a decent photographer.
  • 5. FYI – I don’t especially love CSSThe reason I create and use CSSframeworks is because I hate doingmundane tasks repeatedly (yawn).I’d rather be working in JavaScript.
  • 6. JavaScript books I’ve worked on... Co-author Tech editor Tech editorjQueryEnlightenment.com JavaScriptEnlightenment.com oreilly.com/catalog/9780596159788
  • 7. Our team at HP uses Sass to expedite writing CSS http://www.sass-lang.com
  • 8. Sass compiles down to CSS...$blue: #3bbfce #foo {$margin: 20px border-color: #3bbfce; color: #2b9eab;#foo } border-color: $blue color: darken($blue, 9%) #foo .bar { .bar border-color: #3bbfce; border-color: $blue padding: 10px; margin: 10px; padding: $margin / 2 } margin: $margin / 2
  • 9. But Sass isn’t a magic bullet (Because no framework is)Assuming you already know CSS,Sass can help you write CSS faster.But using Sass doesn’t magicallycreate “better” CSS. If you writebad code, Sass won’t remedy it.
  • 10. The same principles apply to JavaScriptAn important discipline whenusing any framework is strivingto understand the underlyinglanguage. In other words, useit as a tool – Not a black box
  • 11. Veteran “ninjas” master a variety of tools – Not just one. FRAMEWORK BY H AND Use a framework as an extension of yourself – Not just as a crutch. http://imdb.com/title/tt1046173
  • 12. A day to learn, A lifetime to master“JavaScript is the only languagethat I’m aware of that peoplefeel they don’t need to learnbefore they start using it.”— Douglas Crockfordhttp://www.youtube.com/watch?v=hQVTIJBZook
  • 13. Today, I’ll discuss two examples...jQuery Desktop Formalize.Me http://desktop.sonspring.com http://formalize.me
  • 14. jQuery DesktopFun with z-index
  • 15. jQuery DesktopFun with z-index
  • 16. Demystifying z-index http://sonspring.com/journal/jquery-desktop
  • 17. Demystifying z-indexThe default z-index value is 0, and itonly takes effect if an element isposition: fixed, relative, or absolute.The default is position: static.You don’t have to go overboard withz-index: 99999. Just +1 higher thananother element will suffice.
  • 18. CDN & Local Fallback => Best of both worlds<body>...<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"></script><script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.10/jquery-ui.min.js"></script><script> if (!window.jQuery) { document.write(unescape(%3Cscript src="assets/javascripts/jquery.js"%3E%3C/script%3E)); document.write(unescape(%3Cscript src="assets/javascripts/jquery.ui.js"%3E%3C/script%3E)); }</script><script src="assets/javascripts/jquery.desktop.js"></script>...</body> http://desktop.sonspring.com
  • 19. Singleton Pattern = Object-oriented JS Nested JS objects versus dot-notation => Same result, but different approaches var APP = {};var APP = { foo: function() { APP.foo = function() { // Do stuff. // Do stuff. }, }; bar: function() { // Do more stuff. APP.bar = function() { } // Do more stuff.} };I prefer the one on the left, but you would call methods byusing the same syntax either way: APP.foo() + APP.bar()
  • 20. // Module pattern. Module Patternvar APP = (function($, window, document, undefined) { // For use only inside APP. var PRIVATE_CONSTANT_1 = foo; << init example var PRIVATE_CONSTANT_2 = bar; // Expose contents of APP. return { go: function() { for (var i in APP.init) { APP.init[i](); Using a module pattern exposes } }, only one global variable, in this // APP.init init: { case “APP” – with the rest of call_automatically: function() { // Called when DOM is ready. your methods within an object. // Can still be called individually, via: // APP.init.call_automatically(); }, // etc. }, It gives you the ability to use // APP.misc misc: { private “constant” variables call_specifically: function() { // Must be called individually, via: // APP.misc.call_specifically(); inside your appʼs function scope. }, // etc. } }; Nesting functions within an “init”// Alias window, document.})(jQuery, this, this.document); object allows them to be called// Automatically run all functions in APP.initjQuery(document).ready(function() { automatically on DOM ready. APP.go();});
  • 21. .live() is Awesome. Use it. Love it.$(div.window).live(mousedown, function() { // Bring window to front. JQD.util.window_flat(); $(this).addClass(window_stack);}).live(mouseenter, function() { $(this).die(mouseenter).draggable({ // Confine to desktop. // Movable via top bar only. cancel: a, containment: parent, handle: div.window_top }).resizable({ containment: parent, minWidth: 400, minHeight: 200 }); // etc.});
  • 22. Live (pun intended) example of .live()http://desktop.sonspring.com/ajax_load.htmlAll the event wire-ups are ready, beforethe page even has any content. Oncethe content is loaded remotely via Ajax,the elements respond to their respectivepredefined .live() event listeners.
  • 23. Basic structure of jQuery Desktopvar JQD = (function($, window, document, undefined) { return { go: function() { for (var i in JQD.init) { JQD.init[i](); } }, init: { frame_breaker: function() {/* ... */}, clock: function() {/* ... */}, desktop: function() {/* ... */}, wallpaper: function() {/* ... */} }, util: { clear_active: function() {/* ... */}, window_flat: function() {/* ... */}, window_resize: function() {/* ... */} }})(jQuery, this, this.document);
  • 24. Event listeners at the document level// Cancel mousedown, right-click.$(document).mousedown(function(ev) { var tags = [a, button, input, select, textarea]; if (!$(ev.target).closest(tags).length) { JQD.util.clear_active(); ev.preventDefault(); ev.stopPropagation(); }}).bind(contextmenu, function() { return false;});
  • 25. External links open in a new window // Relative or remote links? $(a).live(click, function(ev) { var url = $(this).attr(href); this.blur(); if (url.match(/^#/)) { ev.preventDefault(); ev.stopPropagation(); } else { $(this).attr(target, _blank); } });
  • 26. Top level drop-down menus// Make top menus active.$(a.menu_trigger).live(mousedown, function() { if ($(this).next(ul.menu).is(:hidden)) { JQD.util.clear_active(); $(this).addClass(active).next(ul.menu).show(); } else { JQD.util.clear_active(); }}).live(mouseenter, function() { // Transfer focus, if already open. if ($(ul.menu).is(:visible)) { JQD.util.clear_active(); $(this).addClass(active).next(ul.menu).show(); }});
  • 27. Making desktop icons interactive // Desktop icons. $(a.icon).live(mousedown, function() { // Highlight the icon. JQD.util.clear_active(); $(this).addClass(active); }).live(dblclick, function() { // Get the links target. var x = $(this).attr(href); var y = $(x).find(a).attr(href); // Show the taskbar button. if ($(x).is(:hidden)) { $(x).remove().appendTo(#dock); $(x).show(fast); } // Bring window to front. JQD.util.window_flat(); $(y).addClass(window_stack).show(); }).live(mouseenter, function() { $(this).die(mouseenter).draggable({ revert: true, containment: parent }); });
  • 28. Taskbar / Dock buttons// Taskbar buttons.$(#dock a).live(click, function() { // Get the links target. var x = $($(this).attr(href)); // Hide, if visible. if (x.is(:visible)) { x.hide(); } else { // Bring window to front. JQD.util.window_flat(); x.show().addClass(window_stack); }});
  • 29. Manipulating the “windows”// Minimize the window.$(a.window_min).live(click, function() { $(this).closest(div.window).hide();});// Maximize or restore the window.$(a.window_resize).live(click, function() { JQD.util.window_resize(this);});// Close the window.$(a.window_close).live(click, function() { $(this).closest(div.window).hide(); $($(this).attr(href)).hide(fast);});
  • 30. Clicking the Show Desktop button// Show desktop button, ala Windows OS.$(#show_desktop).live(click, function() { // If any windows are visible, hide all. if ($(div.window:visible).length) { $(div.window).hide(); } else { // Otherwise, reveal hidden windows that are open. $(#dock li:visible a).each(function() { $($(this).attr(href)).show(); }); }});
  • 31. To prevent developers fromwasting countless hours onstyling dumb form elements
  • 32. It’s been awhile in the making...“Future plans include a tutorial on howto use jQuery to add styling hooks toform elements, since I know fromexperience that is no cup of tea.”— Source = Me when announcing 960.gs in 2008!— Excuse = New HTML5 elements set me back :)
  • 33. WebKit’s form styling secret sauceselect { -webkit-appearance: none;}This gives you back a bit of controlfor things like <select> drop-downs.
  • 34. document.write(ad) with position:absolute
  • 35. document.write(ad) with position:absolute
  • 36. document.write(ad) with position:absolute<script> document.write(unescape(%3Cscr + ipt src="http://adn.fusionads.net/... + M</script><span id="fusion_link"> <a href="http://fusionads.net/">Ads by Fusion</a></span>...</body>
  • 37. Base64 encode background imagesheader[role="banner"] h1 { background-repeat: no-repeat; background-position: center 20px; background-image: url(../images/logo.png); background-image: url(data:imagepng;base64, iVBORw0KGgoAAA...); color: transparent; font-size: 0; overflow: hidden; text-indent: -99999px; height: 130px;} http://formalize.me http://www.motobit.com/util/base64-decoder-encoder.asp
  • 38. Pre-load JavaScript files<body>...<!-- Pre-load JavaScript libraries --><script src="http://ajax.googleapis.com/ajax/libs/dojo/1.5.0/dojo/dojo.xd.js"></script><script src="http://ajax.googleapis.com/ajax/libs/ext-core/3.1.0/ext-core.js"></script><script src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"></script><script src="http://ajax.googleapis.com/ajax/libs/mootools/1.3.0/mootools-yui-compressed.js"<script src="http://ajax.googleapis.com/ajax/libs/prototype/1.7.0.0/prototype.js"></script><script src="http://yui.yahooapis.com/3.3.0/build/simpleyui/simpleyui-min.js"></script><!-- Pre-load Formalize files --><script src="assets/javascripts/dojo.formalize.js"></script><script src="assets/javascripts/extjs.formalize.js"></script><script src="assets/javascripts/jquery.formalize.js"></script><script src="assets/javascripts/mootools.formalize.js"></script><script src="assets/javascripts/prototype.formalize.js"></script><script src="assets/javascripts/yui.formalize.js"></script></body>http://formalize.me/demo.html
  • 39. Pre-load JavaScript files<body>...<!-- Pre-load JavaScript libraries --><script src="http://ajax.googleapis.com/ajax/libs/dojo/1.5.0/dojo/dojo.xd.js"></script><script src="http://ajax.googleapis.com/ajax/libs/ext-core/3.1.0/ext-core.js"></script><script src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"></script><script src="http://ajax.googleapis.com/ajax/libs/mootools/1.3.0/mootools-yui-compressed.js"<script src="http://ajax.googleapis.com/ajax/libs/prototype/1.7.0.0/prototype.js"></script><script src="http://yui.yahooapis.com/3.3.0/build/simpleyui/simpleyui-min.js"></script><!-- Pre-load Formalize files --><script src="assets/javascripts/dojo.formalize.js"></script><script src="assets/javascripts/extjs.formalize.js"></script><script src="assets/javascripts/jquery.formalize.js"></script><script src="assets/javascripts/mootools.formalize.js"></script><script src="assets/javascripts/prototype.formalize.js"></script><script src="assets/javascripts/yui.formalize.js"></script></body>http://formalize.me/demo.html
  • 40. IE detection for Prototype.js Prevents false positives since Opera can be made to impersonate IE. Note: I did this because Prototype doesn’t detect IE version number.var IE6 = IE(6);var IE7 = IE(7);// Internet Explorer detection.function IE(version) { var b = document.createElement(b); b.innerHTML = <!--[if IE + version + ]><br><![endif]-->; return !!b.getElementsByTagName(br).length;} http://formalize.me/assets/javascripts/prototype.formalize.js
  • 41. James Padolseys IE detection (whoa!)var ie = (function() { var undef, v = 3, div = document.createElement(div), all = div.getElementsByTagName(i); while ( div.innerHTML = <!--[if gt IE + (++v) + ]><i></i><![endif]-->, all[0] ); return v > 4 ? v : undef;}()); https://gist.github.com/527683
  • 42. Line number counts in Formalize JS Dojo = 174 lines ExtJS = 168 lines jQuery = 158 lines MooTools = 163 linesPrototype = 171 lines YUI = 168 lines “Write Less, Do More” FTW! :)
  • 43. Basic structure of Formalize JSvar FORMALIZE = (function($, window, document, undefined) { // Private constants.! var PLACEHOLDER_SUPPORTED = placeholder in document.createElement(input);! var AUTOFOCUS_SUPPORTED = autofocus in document.createElement(input);! var WEBKIT = webkitAppearance in document.createElement(select).style;! var IE6 = !!($.browser.msie && parseInt($.browser.version, 10) === 6);! var IE7 = !!($.browser.msie && parseInt($.browser.version, 10) === 7); // Expose innards of FORMALIZE. return { go: function() {/* ... */}, init: { detect_webkit: function() {/* ... */}, full_input_size: function() {/* ... */}, ie6_skin_inputs: function() {/* ... */}, autofocus: function() {/* ... */}, placeholder: function() {/* ... */} }, misc: { add_placeholder: function() {/* ... */} } };})(jQuery, this, this.document);
  • 44. Detecting WebKit// FORMALIZE.init.detect_webkitdetect_webkit: function() {! if (!WEBKIT) {! ! return;! }! // Tweaks for Safari + Chrome.! $(html).addClass(is_webkit);},...
  • 45. Basic structure of Formalize JS// FORMALIZE.init.full_input_sizefull_input_size: function() {! if (!IE7 || !$(textarea, input.input_full).length) {! ! return;! }! // This fixes width: 100% on <textarea> and class="input_full".! // It ensures that form elements dont go wider than container.! $(textarea, input.input_full) .wrap(<span class="input_full_wrap"></span>);},...
  • 46. Adding styling// FORMALIZE.init.ie6_skin_inputsie6_skin_inputs: function() { // Test for Internet Explorer 6. if (!IE6 || !$(input, select, textarea).length) { // Exit if the browser is not IE6, // or if no form elements exist. return; hooks for IE6 } // For <input type="submit" />, etc. var button_regex = /button|submit|reset/; // For <input type="text" />, etc. var type_regex = /date|datetime|datetime-local|email|month|number|password|range|search|tel|text|time|url|week/; $(input).each(function() { var el = $(this); // Is it a button? if (this.getAttribute(type).match(button_regex)) { el.addClass(ie6_button); /* Is it disabled? */ if (this.disabled) { el.addClass(ie6_button_disabled); } } // Or is it a textual input? else if (this.getAttribute(type).match(type_regex)) { el.addClass(ie6_input); /* Is it disabled? */ if (this.disabled) { el.addClass(ie6_input_disabled); } } }); $(textarea, select).each(function() { /* Is it disabled? */ if (this.disabled) { $(this).addClass(ie6_input_disabled); } });},
  • 47. Adding HTML5 autofocus support// FORMALIZE.init.autofocusautofocus: function() {! if (AUTOFOCUS_SUPPORTED || !$(:input[autofocus]).length) {! ! return;! }! $(:input[autofocus]:visible:first).focus();},...
  • 48. Adding HTML5 placeholder support // FORMALIZE.init.placeholder placeholder: function() { ! if (PLACEHOLDER_SUPPORTED || !$(:input[placeholder]).length) { ! ! // Exit if placeholder is supported natively, ! ! // or if page does not have any placeholder. ! ! return; ! } ! FORMALIZE.misc.add_placeholder(); ! $(:input[placeholder]).each(function() { ! ! var el = $(this); ! ! var text = el.attr(placeholder); ! ! el.focus(function() { ! ! ! if (el.val() === text) { ! ! ! ! el.val().removeClass(placeholder_text); ! ! ! } ! ! }).blur(function() { ! ! ! FORMALIZE.misc.add_placeholder(); ! ! }); ! ! // Prevent <form> from accidentally ! ! // submitting the placeholder text. ! ! el.closest(form).submit(function() { ! ! ! if (el.val() === text) { ! ! ! ! el.val().removeClass(placeholder_text); ! ! ! } ! ! }).bind(reset, function() { ! ! ! setTimeout(FORMALIZE.misc.add_placeholder, 50); ! ! }); ! }); }
  • 49. Moved outside of init, for easier reuse // FORMALIZE.misc misc: { ! // FORMALIZE.misc.add_placeholder ! add_placeholder: function() { ! ! if (PLACEHOLDER_SUPPORTED || !$(:input[placeholder]).length) { ! ! ! // Exit if placeholder is supported natively, ! ! ! // or if page does not have any placeholder. ! ! ! return; ! ! } ! ! $(:input[placeholder]).each(function() { ! ! ! var el = $(this); ! ! ! var text = el.attr(placeholder); ! ! ! if (!el.val() || el.val() === text) { ! ! ! ! el.val(text).addClass(placeholder_text); ! ! ! } ! ! }); ! } }
  • 50. http://jeromeetienne.github.com/jquery-mobile-960
  • 51. Additional ResourcesjQuery Companion LibrariesjQuery UI – http://jqueryui.comjQuery Mobile – http://jquerymobile.comAmplify – http://amplifyjs.comUnderscore – http://documentcloud.github.com/underscoreBackbone – http://documentcloud.github.com/backboneJS TestingJasmine – http://pivotal.github.com/jasmineQUnit – http://docs.jquery.com/QunitIf you want write Ruby-esque code that compiles to JS...CoffeeScript – http://jashkenas.github.com/coffee-script
  • 52. Recommended BooksLearning jQuery – https://www.packtpub.com/learning-jquery-1.3jQuery Enlightenment – http://jqueryenlightenment.comDOM Scripting – http://domscripting.comJavaScript: The Good Parts – http://oreilly.com/catalog/9780596517748JavaScript: The Definitive Guide – http://oreilly.com/catalog/9780596101992High Performance JavaScript – http://oreilly.com/catalog/9780596802806Pro JavaScript Design Patterns – http://jsdesignpatterns.comObject-Oriented JavaScript – https://www.packtpub.com/object-oriented-javascript/bookThe Art and Science of JavaScript – http://www.sitepoint.com/books/jsdesign1Test-Driven JavaScript Development – http://tddjs.com
  • 53. For questions – Or just to say hi :) Contact – http://sonspring.com/contact Twitter – http://twitter.com/nathansmithhttp://www.slideshare.net/nathansmith/drupalcon-jquery
  • 54. What did you think?Locate this session on the DCC website:http://chicago2011.drupal.org/sessionsClick the “Take the Survey” link.Thanks!