Skip to content

Merge pull requests #15

Merged
merged 5 commits into from Apr 27, 2013
View
31 README.md
@@ -2,7 +2,7 @@
[![Build Status](https://travis-ci.org/thoughtbot/backbone-support.png?branch=master)](https://travis-ci.org/thoughtbot/backbone-support)
-There's no built-in garbage collection for Backbone’s event bindings, and
+There's no built-in garbage collection for Backbone’s event bindings, and
forgetting to unbind can cause bugs and memory leaks.
Backbone Support currently provides two utility classes, SwappingRouter and CompositeView,
@@ -72,7 +72,7 @@ parent view.
`CompositeView` maintains an array of its immediate children as
`this.children`. Using this reference, a parent view's `leave()`
-method will invoke `leave()` on all its children, ensuring that an entire
+method will invoke `leave()` on all its children, ensuring that an entire
tree of composed views is cleaned up properly.
For child views that can dismiss themselves, such as dialog boxes, children
@@ -81,12 +81,26 @@ maintain a back-reference at `this.parent`. This is used to reach up and call
## Dependencies
-You'll need these, but chances are you already have them in your app:
+Backbone Support requires the following dependencies:
* jQuery or Zepto
* Underscore
* Backbone
+### Included Versions
+
+For convenience, Backbone Support comes with a vendored copy of Backbone and
+Underscore to get you up and running as quickly as possible. If you want to
+use these included files, simply follow the instructions below in the
+[Installation][] section.
+
+### Alternate Versions
+
+If you require a different version of Backbone or Underscore than those provided
+by this gem, simply put them in `vendor/assets/javascripts` and they will
+take higher precedence than the versions provided by the gem thanks to the
+ordering of the [search paths in the asset pipeline][].
+
## Development
First:
@@ -122,13 +136,15 @@ This should be _above_ any usage of SwappingController or SwappingRouter, but
below the inclusion of Backbone.js, Underscore, and jQuery.
If you do not wish to include all of backbone-support, you can include
-individual pieces. First, require the main support file:
+individual pieces. Require the support file(s) and the individual assets you wish to use:
//= require backbone-support/support
+ //= require backbone-support/swapping_router
-Then require the individual assets you wish to use:
+or:
- //= require backbone-support/swapping_router
+ //= require backbone-support/support
+ //= require backbone-support/observer
//= require backbone-support/composite_view
### With Jammit
@@ -182,3 +198,6 @@ require("/vendor/plugins/backbone-support/lib/assets/javascripts/backbone-suppor
## License
Copyright 2012 thoughtbot. Please check LICENSE for more details.
+
+[Installation]: https://github.com/thoughtbot/backbone-support#installation
+[search paths in the asset pipeline]: http://edgeguides.rubyonrails.org/asset_pipeline.html#search-paths
View
6 lib/assets/javascripts/backbone-support/composite_view.js
@@ -41,7 +41,11 @@ _.extend(Support.CompositeView.prototype, Backbone.View.prototype, Support.Obser
prependChildTo: function (view, container) {
this.renderChild(view);
- $(container).prepend(view.el);
+ this.$(container).prepend(view.el);
+ },
+
+ swapped: function () {
+ this.trigger('swapped')
},
_leaveChildren: function() {
View
2 lib/assets/javascripts/backbone-support/support.js
@@ -1,2 +1,2 @@
-Support = {};
+window.Support = {};
Support.VERSION = "0.0.1";
View
4 lib/assets/javascripts/backbone-support/swapping_router.js
@@ -10,6 +10,10 @@ _.extend(Support.SwappingRouter.prototype, Backbone.Router.prototype, {
this.currentView = newView;
$(this.el).empty().append(this.currentView.render().el);
+
+ if (this.currentView && this.currentView.swapped) {
+ this.currentView.swapped();
+ }
}
});
View
42 spec/javascripts/composite_view_spec.js
@@ -91,6 +91,15 @@ describe("Support.CompositeView", function() {
expect($(view.el).find('.inside').text()).toEqual("Append to this!Orange!");
});
+
+ it("appends the element only to elements inside the view", function(){
+ var view = new blankView({el: $('<div><div class="main">Append to this!</div></div>')});
+ var div = $("<div class='main' id='outside'></div>");
+ view.appendChildTo(new orangeView(), ".main");
+
+ expect($(view.el).find('.main').text()).toEqual("Append to this!Orange!");
+ expect($("#outside").text()).toEqual("");
+ });
});
describe("#prependChild", function() {
@@ -108,11 +117,29 @@ describe("Support.CompositeView", function() {
$("#test1").text("Prepend to this!");
var view = new blankView({el: "#test"});
+ expect($("#test").text()).toEqual("");
+
+ $("#test").append($("#test1"));
view.prependChildTo(new orangeView(), "#test1");
- expect($("#test").text()).toEqual("");
expect($("#test1").text()).toEqual("Orange!Prepend to this!");
});
+
+ it("prepends child into a sub-element even if it is not added to the document", function() {
+ var view = new blankView({el: $('<div><div class="inside">Prepend to this!</div></div>')});
+ view.prependChildTo(new orangeView(), ".inside");
+
+ expect($(view.el).find('.inside').text()).toEqual("Orange!Prepend to this!");
+ });
+
+ it("prepends the element only to elements inside the view", function(){
+ var view = new blankView({el: $('<div><div class="main">Prepend to this!</div></div>')});
+ var div = $("<div class='main' id='outside'></div>");
+ view.prependChildTo(new orangeView(), ".main");
+
+ expect($(view.el).find('.main').text()).toEqual("Orange!Prepend to this!");
+ expect($("#outside").text()).toEqual("");
+ });
});
describe("#leave", function() {
@@ -219,6 +246,18 @@ describe("Support.CompositeView", function() {
});
});
+ describe("#swapped", function() {
+ it("fires 'swapped' event", function() {
+ var eventListener = sinon.spy()
+ var view = new Support.CompositeView
+ view.bind('swapped', eventListener)
+
+ view.swapped();
+
+ expect(eventListener.called).toBeTruthy();
+ });
+ });
+
describe("#bindTo", function() {
var view = new orangeView();
var callback = sinon.spy();
@@ -260,5 +299,4 @@ describe("Support.CompositeView", function() {
});
});
});
-
});
View
6 spec/javascripts/support/jasmine.yml
@@ -11,9 +11,9 @@
# - dist/**/*.js
#
src_files:
- - vendor/jquery.js
- - vendor/underscore.js
- - vendor/backbone.js
+ - spec/javascripts/support/jquery.js
+ - vendor/assets/javascripts/underscore.js
+ - vendor/assets/javascripts/backbone.js
- lib/assets/javascripts/backbone-support.js
- lib/assets/javascripts/backbone-support/support.js
- lib/assets/javascripts/backbone-support/observer.js
View
0 vendor/jquery.js → spec/javascripts/support/jquery.js
File renamed without changes.
View
18 spec/javascripts/swapping_router_spec.js
@@ -16,8 +16,8 @@ describe("Support.SwappingRouter", function() {
});
var leaveView = Backbone.View.extend({
- leave: function() {
- }
+ leave: function() {},
+ swapped: function() {},
});
var leaveViewInstance = new leaveView();
@@ -119,4 +119,18 @@ describe("Support.SwappingRouter", function() {
expect(spy.called).toBeTruthy();
});
});
+
+ it("calls .swapped on the view after swapping", function() {
+ var spy = sinon.spy(leaveViewInstance, "swapped");
+
+ runs(function() {
+ window.location.hash = "#leave"
+ });
+
+ Helpers.sleep()
+
+ runs(function() {
+ expect(spy.called).toBeTruthy()
+ });
+ });
});
View
0 vendor/backbone.js → vendor/assets/javascripts/backbone.js
File renamed without changes.
View
0 vendor/underscore.js → vendor/assets/javascripts/underscore.js
File renamed without changes.
Something went wrong with that request. Please try again.