2. Carpal Tunnel Relief
Note: Don’t feel like you need to write all of
this 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 CSS
The reason I create and use CSS
frameworks is because I hate doing
mundane tasks repeatedly (yawn).
I’d rather be working in JavaScript.
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 magically
create “better” CSS. If you write
bad code, Sass won’t remedy it.
10. The same principles
apply to JavaScript
An important discipline when
using any framework is striving
to understand the underlying
language. In other words, use
it 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 language
that I’m aware of that people
feel they don’t need to learn
before they start using it.”
— Douglas Crockford
http://www.youtube.com/watch?v=hQVTIJBZook
17. Demystifying z-index
The default z-index value is 0, and it
only takes effect if an element is
position: fixed, relative, or absolute.
The default is position: static.
You don’t have to go overboard with
z-index: 99999. Just +1 higher than
another 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 by
using the same syntax either way: APP.foo() + APP.bar()
20. // Module pattern.
Module Pattern
var 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.init
jQuery(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.html
All the event wire-ups are ready, before
the page even has any content. Once
the content is loaded remotely via Ajax,
the elements respond to their respective
predefined .live() event listeners.
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 link's 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 link's 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();
});
}
});
32. It’s been awhile in the making...
“Future plans include a tutorial on how
to use jQuery to add styling hooks to
form elements, since I know from
experience that is no cup of tea.”
— Source = Me when announcing 960.gs in 2008!
— Excuse = New HTML5 elements set me back :)
33.
34. WebKit’s form styling secret sauce
select {
-webkit-appearance: none;
}
This gives you back a bit of control
for things like <select> drop-downs.
41. 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
42. James Padolsey's 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
43. Line number counts in Formalize JS
Dojo = 174 lines ExtJS = 168 lines
jQuery = 158 lines MooTools = 163 lines
Prototype = 171 lines YUI = 168 lines
“Write Less, Do More” FTW! :)
44. Basic structure of Formalize JS
var 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);
46. Basic structure of Formalize JS
// FORMALIZE.init.full_input_size
full_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 don't go wider than container.
! $('textarea, input.input_full')
.wrap('<span class="input_full_wrap"></span>');
},
...
47. Adding styling
// FORMALIZE.init.ie6_skin_inputs
ie6_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');
}
});
},
52. Additional Resources
jQuery Companion Libraries
jQuery UI – http://jqueryui.com
jQuery Mobile – http://jquerymobile.com
Amplify – http://amplifyjs.com
Underscore – http://documentcloud.github.com/underscore
Backbone – http://documentcloud.github.com/backbone
JS Testing
Jasmine – http://pivotal.github.com/jasmine
QUnit – http://docs.jquery.com/Qunit
If you want write Ruby-esque code that compiles to JS...
CoffeeScript – http://jashkenas.github.com/coffee-script
53. Recommended Books
Learning jQuery – https://www.packtpub.com/learning-jquery-1.3
jQuery Enlightenment – http://jqueryenlightenment.com
DOM Scripting – http://domscripting.com
JavaScript: The Good Parts – http://oreilly.com/catalog/9780596517748
JavaScript: The Definitive Guide – http://oreilly.com/catalog/9780596101992
High Performance JavaScript – http://oreilly.com/catalog/9780596802806
Pro JavaScript Design Patterns – http://jsdesignpatterns.com
Object-Oriented JavaScript – https://www.packtpub.com/object-oriented-javascript/book
The Art and Science of JavaScript – http://www.sitepoint.com/books/jsdesign1
Test-Driven JavaScript Development – http://tddjs.com
54. For questions – Or just to say hi :)
Contact – http://sonspring.com/contact
Twitter – http://twitter.com/nathansmith
http://www.slideshare.net/nathansmith/drupalcon-jquery
55. What did you think?
Locate this session on the DCC website:
http://chicago2011.drupal.org/sessions
Click the “Take the Survey” link.
Thanks!