jQuery Patterns
jquery patterns
requery - avoid requery by using jQuery chaining
/* Title: requery
* Description: avoid requery by using jQuery chaining
*/
// antipattern
// create and append your element
$(document.body).append("<div class='baaron' />");
// requery to bind stuff
$("div.baaron").click(function () {
});
// preferred
// swap to appendTo to hold your element
$("<div class='baaron' />")
.appendTo(document.body)
.click(function () {
});
// References
// http://paulirish.com/2009/perf/
append - use string concatenate and set innerHTML
/* Title: append
* Description: use string concatenate and set innerHTML
*/
// antipattern
// appending inside
$.each(reallyLongArray, function (count, item) {
var newLI = '<li>' + item + '</li>';
$('#ballers').append(newLI);
});
// documentFragment off-DOM
var frag = document.createDocumentFragment();
$.each(reallyLongArray, function (count, item) {
var newLI = $('<li>' + item + '</li>');
frag.appendChild(newLI[0]);
});
$('#ballers')[0].appendChild(frag);
// string concatenate and set innerHTML
var myhtml = '';
$.each(reallyLongArray, function (count, item) {
myhtml += '<li>' + item + '</li>';
});
$('#ballers').html(myhtml);
// References
// http://paulirish.com/2009/perf/
data - pattern and antipattern of using data
/* Title: data
* Description: pattern and antipattern of using data
*/
// antipattern
$(elem).data(key, value);
// preferred
$.data(elem, key, value);
// References
// http://paulirish.com/2009/perf/
context and find - use find over context
/* Title: context and find
* Description: better to choose `find` over `context`
*/
var arms = $('div.robotarm', '#container');
$('.reply_form', $(this).closest('.comment')).hide();
// no performance gain over doing this, but a preferred pattern for readability reason
var arms = $('#container').find('div.robotarm');
$(this).closest('.comment').find('.reply_form').hide();
// References
// http://paulirish.com/2009/perf/
detach - take element off the DOM while manipulating them
/* Title: detach
* Description: take element off the DOM while manipulating them
*/
var table = $('#some-table');
var parent = table.parent();
table.detach();
table.addLotsAndLotsOfRows();
parent.append(table);
// References
// http://paulirish.com/2009/perf/
event delegation - event delegation pattern and antipattern
/* Title: event delegation
Description: event delegation pattern and antipattern
*/
// antipattern
$('a.trigger', $('#container')[0]).live('click', handlerFn);
// preferred
$('#container').on('click', 'a.trigger', handlerFn);
// .bind()
// .live() - best used for simple scenario, it functions the best with a supply selector only, it's not chainable
// .delegate() - it gives you a more focused way, it can better filter the elements, for example, table row
// References
// http://paulirish.com/2009/perf/
selector cache - using selector cache to avoid requery
/* Title: selector cache
Description: using selector cache to avoid requery
*/
// antipattern
$('.list-item').click(function () {
$('.photo').hide();
});
// preferred
var $photo;
// prefix the cache with $ to help identify it as a selector cache later
$('.list-item').click(function () {
$photo = $photo || $('.photo');
$photo.hide();
});
// References
// http://ejohn.org/blog/learning-from-twitter/
window scroll event - avoid attaching handlers to the window scroll event
/* Title: window scroll event
* Description: avoid attaching handlers to the window scroll event
*/
// antipattern
$(window).scroll(function () {
$('.foo').something();
});
// preferred
var outerPane = $details.find(".details-pane-outer"),
didScroll = false;
$(window).scroll(function () {
didScroll = true;
});
setInterval(function () {
if (didScroll) {
didScroll = false;
// Check your page position and then
// Load in more results
// outerPane.html();
}
}, 250);
// preferred v2, timeout instead of interval - no unnecessary ticks
var scrollTimeout; // global for any pending scrollTimeout
var outerPane = $details.find(".details-pane-outer");
$(window).scroll(function () {
if (scrollTimeout) {
// clear the timeout, if one is pending
clearTimeout(scrollTimeout);
scrollTimeout = null;
}
scrollTimeout = setTimeout(scrollHandler, 250);
});
scrollHandler = function () {
// Check your page position and then
// Load in more results
// outerPane.html();
};
// References
// http://ejohn.org/blog/learning-from-twitter/
Selector
#### Left and Right - specific on the right, light on the left ```js
/* Title: Left and Right * Description: specific on the right, light on the left */
// antipattern $(‘div.data .brad’)
// preferred $(‘.data td.brad’)
// References // http://paulirish.com/2009/perf/
#### **Decending from id** - be more specific
```js
/* Title: Decending from id
* Description: be more specific, better to descend from an id
*/
// antipattern
var arms = $('.container div.robotarm');
// better
var arms = $('#container div.robotarm');
// preferred
var arms = $('#container').find('div.robotarm');
// References
// http://paulirish.com/2009/perf/
#### Universal Selector - use of universal selector ```js /* Title: Universal Selector * Description: better use of universal selector */
// antipattern 1 $(‘.buttons > *’)
// preferred 1 $(‘.buttons’).children()
// antipattern 2 $(‘.gender :radio’) $(‘.gender *:radio’)
// preferred 2 $(‘.gender input:radio’)
// References
// http://paulirish.com/2009/perf/
#### **Be Specific when Needed** - be specific only when needed
js
/* Title: Be Specific when Needed
* Description: no need to be over-specific
*/
// antipattern var arms = $(‘.data table.attendees td.brad’);
// preferred var arms = $(‘.data td.brad’);
// References // http://paulirish.com/2009/perf/s
### Publish–subscribe
#### **Method 1** - custom events using .on() and .off()
```js
/* Title: Custom events using .on() and .off()
* Description: A really tiny pub/sub implementation for jQuery 1.7 using the two new methods(since jQuery 1.7): .on() and .off().
*/
/* jQuery Tiny Pub/Sub - v0.7 - 10/27/2011
* http://benalman.com/
* Copyright (c) 2011 "Cowboy" Ben Alman; Licensed MIT, GPL */
(function($) {
var o = $({});
$.subscribe = function() {
o.on.apply(o, arguments);
};
$.unsubscribe = function() {
o.off.apply(o, arguments);
};
$.publish = function() {
o.trigger.apply(o, arguments);
};
}(jQuery));
// Usage:
// Super-basic example:
function handle(e, a, b, c) {
// `e` is the event object, you probably don't care about it.
console.log(a + b + c);
};
$.subscribe("/some/topic", handle);
$.publish("/some/topic", [ "a", "b", "c" ]);
// logs: abc
$.unsubscribe("/some/topic", handle); // Unsubscribe just this handler
// Or:
$.subscribe("/some/topic", function(e, a, b, c) {
console.log(a + b + c);
});
$.publish("/some/topic", [ "a", "b", "c" ]);
// logs: abc
// Unsubscribe all handlers for this topic
$.unsubscribe("/some/topic");
// References
// https://gist.github.com/1321768
Method 2 - using jQuery 1.7’s $.Callbacks() feature
#### Method 3 - using jQuery UI $.Observable #### Method 4 - third-party plugins