Don Smith
Senior Program Manager
Microsoft patterns & practices
Use arrow keys to navigate and Ctrl/Cmd -/+ to adjust text and positioning
Project Silk
Client-side Web
Development for
Modern Browsers
First step: Choose a library for DOM manipulation (jQuery)
Assertions in QUnit:
var ok = function ok(value, msg, results) {
var result = value ? 'pass' : 'fail';
$('<div class="test-result">').text(msg)
.addClass(result)
.appendTo(results);
};
ok(true, 'ok');
ok('100' == 100, 'equal');
ok('100' === 100, 'not equal');
// While using the 'new'
// keyword is possible
var obj = new Object();
// The object literal
// syntax is preferred
var obj = {},
t = typeof obj;
ok(t == 'object', ':-)');
// Defining properties
// and methods is easy
var obj = {
id: 44,
innerObj: {
prop: 'content',
run: function(arg) {
return 'done';
}
}, // beware of the commas
ary: [12,
'more',
{'even-more': 'items'}]
};
// Function expression (anonymous) - preferred
var func1 = function(args) { return 'result'; };
// Function expression (named) - needed during recursion
var func2 = function func2(args) { };
// Function statement (named & hoisted) - can safely avoid
function func3(args) { }
// And can be passed into and out of functions
var func4 = function(arg) { return arg; };
var result = func4( func1 )();
// Differ only in how parameters are passed
// function.call(objContext, arg1, arg2)
// function.apply(objContext, argArray)
var obj = { p: 'foo' },
func = function() { return this.p || 'default'; },
result = func.call(obj);
ok(result == 'foo', 'context changed');
var count = 0,
setupLinkHandler = function(link) {
link.addEventListener('click', function(e) {
this.text('Clicked ' + count + ' times');
e.preventDefault();
});
};
So variables can live beyond their scope
(function(app, $, undefined) {
var priv1 = 'foo',
priv2 = 'bar',
calc = function() {
return 'baz';
};
app.myObj = {
prop: priv1 + calc(),
memb: function() {
// impl
}
};
}(this.app = this.app || {}, jQuery));
Let's have a closer look at the QuickStart
Notable things about jQuery
$('selector')
'element'
'#id'
'.class'
'.class1.class2' // and
'.class1, class2' // or
'element decendent-element'
'#id > child-element'
'element[attribute]'
'element[attribute="value"]'
// And some useful extras
'element[attribute^="val"]'
'element[attribute$="lue"]'
':button'
':checked'
':even'
':nth-child(n)'
// To increase performance
$('selector', context)...
wrapper.find('selector')...
var wrappedElems = $(''),
wrappedElem = wrappedElems.first(),
nakedElem = wrappedElems[0];
ok(wrappedElem.css, 'wrapped');
ok(nakedElem.css, 'wrapped');
(function ($, undefined) {
var timer;
$.fn.tagger = function () {
return this.each(function () {
var $this = $(this);
$this
.addClass('qs-tagged')
.bind('mouseenter', function (evnt) {
})
.bind('mouseleave', function () {
});
});
};
} (jQuery));
(function ($, undefined) {
$.fn.infobox = function(options){
this.options = {
maxItems: 10,
dataUrl: 'http://feeds.delicious.com/v2/json/popular/'
};
$.extend(this.options, options);
};
} (jQuery));
Let's have a closer look at the QuickStart
(function ($, undefined) {
$.widget('qs.infobox'), {
displayTagLinks: function(){}
});
}(jQuery));
$('body').infobox();
$.widget = function(name, base, prototype) {
$.widget.bridge( name, $[ namespace ][ name ] );
};
$.widget.bridge = function( name, object ) {
$.fn[ name ] = function( options ) {
$.data( this, name, new object( options, this ) );
};
};
$('body').infobox('displayTagLinks', args);
$.widget('qs.tagger'), {
_create: function() {
this.element.addClass('qs-tagged');
}
displayTagLinks: function() { ... }
});
$.widget('qs.infobox'), {
destroy: function() {
// if using jQuery UI 1.8.x
$.Widget.prototype.destroy.call(this);
// if using jQuery UI 1.9.x
//this._destroy();
}
});
$.widget('qs.infobox', {
options: {
dataUrl: '',
maxItems: 10
}
});
$('body').infobox({
dataUrl: 'http://feeds.delicious.com/v2/json/popular/'
});
$.widget('qs.tagger', {
options: { activated: $.noop() }
});
$('span[data-tag]').tagger({
activated: function (event, data) {
infobox.infobox('displayTagLinks', event, data.name);
}
});
that._trigger('activated', event, {name: tag});
Let's have a closer look at the QuickStart
| JavaScript Objects | jQuery Plug-ins | jQuery UI Widgets | |
| Infrastructure Modules | Ideal | OK | No |
| Behavioral Modules | OK | Ideal | OK |
| UI Modules | No | OK | Ideal |
This presentation is online @
http://locksmithdon.net/talks/jsmodularity.html