documentcloud/backbone — Issue #1038: this.$(someElement) Doesn't Work
Author: machineghost
Created: 2012-02-22 21:57:21+00:00
State: open

Somewhere between 0.5 and 0.9 Backbone changed the definition of the delegator (this.$()) from:

return $(selector, this.el);

to:

return this.$el.find(selector);

Now as the jQuery site itself says:

"Selector context is implemented with the .find() method; therefore, $('li.item-ii').find('li') is equivalent to $('li', 'li.item-ii')."

so that change should be perfectly safe, right? Well, it is, but only:
A) for jQuery >= 1.6
B) if the selector is a string

If however you try to do:
var model = new Backbone.Model.extend({
....someFunc: function() {
........var elem = document.getElementById("foo");
........var $elem = this.$(elem);
....}
}) ()
before jQuery 1.6, it won't work, because find isn't expecting to take an element (why would you try and find something you already have?).

Now similarly, in Backbone it makes no sense to do this.$(elem) when you can just as easily do $(elem) (and the latter works). But sometimes you might have a variable that could be a string or could be an element ... or you might just have some legacy code that does the former, and it's a pain to change.

All of this can be solved ... well in two ways (that I see):
1) Add a line to the Backbone documentation that says something to the effect of "While Backbone 0.9 works with all versions of jQuery, jQuery 1.6 or greater is recommended; using earlier versions of jQuery may cause problems in certain corner cases."
2) Add a quick type check to the delegate function, and use the old style if the selector isn't a string:
$: function(selector) {
.... if (typeof selector != "string") return $(selector, this.$el);
....return this.$el.find(selector);
},