diff --git a/exoskeleton.js b/exoskeleton.js index 6343f21..cbf710c 100644 --- a/exoskeleton.js +++ b/exoskeleton.js @@ -1438,6 +1438,9 @@ var View = Backbone.View = function(options) { // Set up all inheritable **Backbone.View** properties and methods. _.extend(View.prototype, Events, { + // In case you want to include jQuery with your app + // for *some* views and use native methods for other views. + useNative: false, // The default `tagName` of a View's element is `"div"`. tagName: 'div', @@ -1445,7 +1448,7 @@ _.extend(View.prototype, Events, { // jQuery delegate for element lookup, scoped to DOM elements within the // current view. This should be preferred to global lookups where possible. $: function(selector) { - return Backbone.$ ? this.$el.find(selector) : this.findAll(selector); + return Backbone.$ && !this.useNative ? this.$el.find(selector) : this.findAll(selector); }, // Exoskeleton-related DOM methods. @@ -1472,7 +1475,7 @@ _.extend(View.prototype, Events, { // applicable Backbone.Events listeners. remove: function() { var parent; - if (Backbone.$) { + if (Backbone.$ && !this.useNative) { this.$el.remove(); } else if (parent = this.el.parentNode) { parent.removeChild(this.el); @@ -1484,7 +1487,7 @@ _.extend(View.prototype, Events, { // Change the view's element (`this.el` property), including event // re-delegation. setElement: function(element, delegate) { - if (Backbone.$) { + if (Backbone.$ && !this.useNative) { if (this.$el) this.undelegateEvents(); this.$el = element instanceof Backbone.$ ? element : Backbone.$(element); this.el = this.$el[0]; @@ -1523,7 +1526,7 @@ _.extend(View.prototype, Events, { var match = key.match(delegateEventSplitter); var eventName = match[1], selector = match[2]; - if (Backbone.$) { + if (Backbone.$ && !this.useNative) { eventName += '.delegateEvents' + this.cid; method = method.bind(this); this.$el.on(eventName, (selector ? selector : null), method); @@ -1538,7 +1541,7 @@ _.extend(View.prototype, Events, { // You usually don't need to use this, but may wish to if you have multiple // Backbone views attached to the same DOM element. undelegateEvents: function() { - if (Backbone.$) { + if (Backbone.$ && !this.useNative) { this.$el.off('.delegateEvents' + this.cid); } else { utils.undelegate(this); diff --git a/lib/view.js b/lib/view.js index bd33bae..3726c84 100644 --- a/lib/view.js +++ b/lib/view.js @@ -34,6 +34,9 @@ var View = Backbone.View = function(options) { // Set up all inheritable **Backbone.View** properties and methods. _.extend(View.prototype, Events, { + // In case you want to include jQuery with your app + // for *some* views and use native methods for other views. + useNative: false, // The default `tagName` of a View's element is `"div"`. tagName: 'div', @@ -41,7 +44,7 @@ _.extend(View.prototype, Events, { // jQuery delegate for element lookup, scoped to DOM elements within the // current view. This should be preferred to global lookups where possible. $: function(selector) { - return Backbone.$ ? this.$el.find(selector) : this.findAll(selector); + return Backbone.$ && !this.useNative ? this.$el.find(selector) : this.findAll(selector); }, // Exoskeleton-related DOM methods. @@ -68,7 +71,7 @@ _.extend(View.prototype, Events, { // applicable Backbone.Events listeners. remove: function() { var parent; - if (Backbone.$) { + if (Backbone.$ && !this.useNative) { this.$el.remove(); } else if (parent = this.el.parentNode) { parent.removeChild(this.el); @@ -80,7 +83,7 @@ _.extend(View.prototype, Events, { // Change the view's element (`this.el` property), including event // re-delegation. setElement: function(element, delegate) { - if (Backbone.$) { + if (Backbone.$ && !this.useNative) { if (this.$el) this.undelegateEvents(); this.$el = element instanceof Backbone.$ ? element : Backbone.$(element); this.el = this.$el[0]; @@ -119,7 +122,7 @@ _.extend(View.prototype, Events, { var match = key.match(delegateEventSplitter); var eventName = match[1], selector = match[2]; - if (Backbone.$) { + if (Backbone.$ && !this.useNative) { eventName += '.delegateEvents' + this.cid; method = method.bind(this); this.$el.on(eventName, (selector ? selector : null), method); @@ -134,7 +137,7 @@ _.extend(View.prototype, Events, { // You usually don't need to use this, but may wish to if you have multiple // Backbone views attached to the same DOM element. undelegateEvents: function() { - if (Backbone.$) { + if (Backbone.$ && !this.useNative) { this.$el.off('.delegateEvents' + this.cid); } else { utils.undelegate(this); diff --git a/test/view-no-jq.js b/test/view-no-jq.js index 1322b67..5bbe7cc 100644 --- a/test/view-no-jq.js +++ b/test/view-no-jq.js @@ -371,4 +371,28 @@ el.parentNode.removeChild(el); }); + test("useNative for view-specific native DOM usage", 1, function() { + var el = document.createElement("p"); + el.innerHTML = ''; + document.body.appendChild(el); + + Backbone.$ = {}; + var View = Backbone.View.extend({ + useNative: true + }); + + ok((function() { + try { + var view = new View; + view.$('p'); + return true; + } catch(e) { + return false; + } + })()) + + Backbone.$ = undefined; + el.parentNode.removeChild(el); + }); + })();