backbone-support 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +1 -0
- data/.jshintrc +38 -0
- data/.travis.yml +2 -2
- data/CHANGELOG +10 -1
- data/README.md +34 -27
- data/backbone-support.gemspec +1 -1
- data/bower.json +38 -0
- data/lib/assets/javascripts/backbone-support/composite_view.js +8 -8
- data/lib/assets/javascripts/backbone-support/observer.js +25 -13
- data/lib/assets/javascripts/backbone-support/swapping_router.js +1 -1
- data/lib/backbone-support/version.rb +1 -1
- data/spec/javascripts/composite_view_spec.js +46 -66
- data/spec/javascripts/helpers/helpers.js +0 -4
- data/spec/javascripts/observer_spec.js +12 -38
- data/spec/javascripts/support/jasmine.yml +84 -8
- data/spec/javascripts/support/jasmine_helper.rb +15 -0
- data/spec/javascripts/swapping_router_spec.js +29 -46
- data/vendor/assets/javascripts/backbone.js +216 -179
- data/vendor/assets/javascripts/underscore.js +673 -484
- metadata +21 -30
- data/Gemfile.lock +0 -46
- data/spec/javascripts/support/jasmine_config.rb +0 -23
- data/spec/javascripts/support/jasmine_runner.rb +0 -32
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: e9ffe52a5316ecd3a32212b66cfa6cdfb530ef8e
|
4
|
+
data.tar.gz: 4cc867fc3ece887b2f73fc3dc216c705e4e7b48c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: af84d8073f5b27a768b341dce5852f9ac1d8799ac8ee3be0c4c30a7bbf41aca6e7905f20387ece1364c9784e461856f5bf41e058c8d5a91cf7f324b8d04eceb7
|
7
|
+
data.tar.gz: 65e5644b534351753aaf045c3ecd8edfcc330613d228bcf6f331dfa9bda5f96ee1afa1f0a6d483340634b842dd4134813aeead2935eac6148d9803717f83392f
|
data/.gitignore
CHANGED
data/.jshintrc
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
{
|
2
|
+
"asi": false,
|
3
|
+
"bitwise": true,
|
4
|
+
"browser": true,
|
5
|
+
"camelcase": true,
|
6
|
+
"curly": true,
|
7
|
+
"forin": true,
|
8
|
+
"immed": true,
|
9
|
+
"latedef": "nofunc",
|
10
|
+
"maxlen": 80,
|
11
|
+
"newcap": true,
|
12
|
+
"noarg": true,
|
13
|
+
"noempty": true,
|
14
|
+
"nonew": true,
|
15
|
+
"predef": [
|
16
|
+
"$",
|
17
|
+
"jQuery",
|
18
|
+
|
19
|
+
"_",
|
20
|
+
"Backbone",
|
21
|
+
"Support",
|
22
|
+
|
23
|
+
"jasmine",
|
24
|
+
"beforeEach",
|
25
|
+
"afterEach",
|
26
|
+
"describe",
|
27
|
+
"expect",
|
28
|
+
"it",
|
29
|
+
|
30
|
+
"sinon",
|
31
|
+
|
32
|
+
"Helpers"
|
33
|
+
],
|
34
|
+
"quotmark": true,
|
35
|
+
"trailing": true,
|
36
|
+
"undef": true,
|
37
|
+
"unused": true
|
38
|
+
}
|
data/.travis.yml
CHANGED
data/CHANGELOG
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
0.5.0 (Feb 16, 2015)
|
2
|
+
|
3
|
+
- Update Backbone to v1.1.2
|
4
|
+
- Update Underscore to v1.7.0
|
5
|
+
- Set `parent` before rendering in `CompositeView#renderChild()` so child view
|
6
|
+
has access to `parent` for easier event bindings.
|
7
|
+
- Deprecate `Observer#bindTo()` and `Observer#unbindFromAll()` in favor of
|
8
|
+
Backbone's `Events#listenTo()` and `Events#stopListening()`.
|
9
|
+
|
1
10
|
0.4.0 (May 10, 2013)
|
2
11
|
|
3
12
|
- Update included Backbone to version 1.0
|
@@ -27,7 +36,7 @@ leave().
|
|
27
36
|
0.2.0
|
28
37
|
|
29
38
|
The version changes the order of when a view has render called on it when
|
30
|
-
being swapped by a SwappingRouter. This fixes an issue in some browsers which
|
39
|
+
being swapped by a SwappingRouter. This fixes an issue in some browsers which
|
31
40
|
would display a flash of unstyled content when performing certain actions in their
|
32
41
|
render, like changing the body class. It introduces the requirement that all
|
33
42
|
views return an instance of themselves when rendered (a fairly standard
|
data/README.md
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# Backbone Support [](https://travis-ci.org/thoughtbot/backbone-support) [](https://rubygems.org/gems/backbone-support)
|
2
2
|
|
3
|
+
## Summary
|
4
|
+
|
3
5
|
Backbone Support provides a collection of utility classes for use with
|
4
6
|
[Backbone.js][]. There's no built-in garbage collection for Backbone’s event
|
5
7
|
bindings, and forgetting to unbind can cause bugs and memory leaks. Backbone
|
@@ -30,34 +32,38 @@ Now, a `SwappingRouter` can take advantage of the `leave()` function, and
|
|
30
32
|
clean up any existing views before swapping to a new one. It swaps into a new
|
31
33
|
view by rendering that view into its own `el`:
|
32
34
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
35
|
+
``` js
|
36
|
+
swap: function(newView) {
|
37
|
+
if (this.currentView && this.currentView.leave) {
|
38
|
+
this.currentView.leave();
|
39
|
+
}
|
40
|
+
|
41
|
+
this.currentView = newView;
|
42
|
+
$(this.el).empty().append(this.currentView.render().el);
|
43
|
+
}
|
44
|
+
```
|
41
45
|
|
42
46
|
An example SwappingRouter would look as follows:
|
43
47
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
48
|
+
``` js
|
49
|
+
Trajectory.Routers.Stories = Support.SwappingRouter.extend({
|
50
|
+
initialize: function(options) {
|
51
|
+
this.el = $("div.primary_content");
|
52
|
+
},
|
53
|
+
routes: {
|
54
|
+
"stories": "index",
|
55
|
+
"stories/new": "newStory"
|
56
|
+
}
|
57
|
+
index: function() {
|
58
|
+
var view = new Trajectory.Views.StoriesIndex();
|
59
|
+
this.swap(view);
|
60
|
+
},
|
61
|
+
newStory: function() {
|
62
|
+
var view = new Trajectory.Views.StoryNew({ model: new Story() });
|
63
|
+
this.swap(view);
|
64
|
+
}
|
65
|
+
}
|
66
|
+
```
|
61
67
|
|
62
68
|
### CompositeView
|
63
69
|
|
@@ -119,7 +125,9 @@ advantage of the asset pipeline.
|
|
119
125
|
|
120
126
|
Add the gem to your Gemfile:
|
121
127
|
|
122
|
-
|
128
|
+
``` ruby
|
129
|
+
gem "backbone-support"
|
130
|
+
```
|
123
131
|
|
124
132
|
And then `bundle install`.
|
125
133
|
|
@@ -158,7 +166,6 @@ or:
|
|
158
166
|
### With Jammit
|
159
167
|
|
160
168
|
First off:
|
161
|
-
|
162
169
|
rails plugin install git@github.com:thoughtbot/backbone-support.git
|
163
170
|
|
164
171
|
In your `config/application.rb`:
|
data/backbone-support.gemspec
CHANGED
@@ -16,7 +16,7 @@ Gem::Specification.new do |s|
|
|
16
16
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
17
17
|
s.require_paths = ["lib"]
|
18
18
|
|
19
|
-
s.add_development_dependency('jasmine', '
|
19
|
+
s.add_development_dependency('jasmine', '~> 2.0')
|
20
20
|
s.add_development_dependency('rake')
|
21
21
|
s.add_development_dependency('headless')
|
22
22
|
end
|
data/bower.json
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
{
|
2
|
+
"name": "backbone-support",
|
3
|
+
"version": "0.4.0",
|
4
|
+
"description": "SwappingController and CompositeView for Backbone.js",
|
5
|
+
"main": [
|
6
|
+
"vendor/assets/javascripts/underscore.js",
|
7
|
+
"vendor/assets/javascripts/backbone.js",
|
8
|
+
"lib/assets/javascripts/backbone-support/support.js",
|
9
|
+
"lib/assets/javascripts/backbone-support/observer.js",
|
10
|
+
"lib/assets/javascripts/backbone-support/composite_view.js",
|
11
|
+
"lib/assets/javascripts/backbone-support/swapping_router.js"
|
12
|
+
],
|
13
|
+
"license": "MIT",
|
14
|
+
"ignore": [
|
15
|
+
"**/*.txt",
|
16
|
+
"**/.*",
|
17
|
+
".jshintrc",
|
18
|
+
"CHANGELOG",
|
19
|
+
"Gemfile",
|
20
|
+
"Gemfile.lock",
|
21
|
+
"LICENSE",
|
22
|
+
"README.md",
|
23
|
+
"Rakefile",
|
24
|
+
"backbone-support.gemspec",
|
25
|
+
"spec"
|
26
|
+
],
|
27
|
+
"homepage": "https://github.com/thoughtbot/backbone-support",
|
28
|
+
"authors": [
|
29
|
+
"thoughtbot (http://thoughtbot.com)"
|
30
|
+
],
|
31
|
+
"repository": {
|
32
|
+
"type": "git",
|
33
|
+
"url": "https://github.com/thoughtbot/backbone-support.git"
|
34
|
+
},
|
35
|
+
"keywords": [
|
36
|
+
"backbone"
|
37
|
+
]
|
38
|
+
}
|
@@ -14,31 +14,31 @@ _.extend(Support.CompositeView.prototype, Backbone.View.prototype, Support.Obser
|
|
14
14
|
},
|
15
15
|
|
16
16
|
renderChild: function(view) {
|
17
|
+
view.parent = this;
|
17
18
|
view.render();
|
18
19
|
this.children.push(view);
|
19
|
-
view.parent = this;
|
20
20
|
},
|
21
|
-
|
21
|
+
|
22
22
|
renderChildInto: function(view, container) {
|
23
23
|
this.renderChild(view);
|
24
|
-
this.$(container).
|
24
|
+
this.$(container).html(view.el);
|
25
25
|
},
|
26
26
|
|
27
27
|
appendChild: function(view) {
|
28
28
|
this.renderChild(view);
|
29
|
-
|
29
|
+
this.$el.append(view.el);
|
30
30
|
},
|
31
|
-
|
31
|
+
|
32
32
|
appendChildTo: function (view, container) {
|
33
33
|
this.renderChild(view);
|
34
34
|
this.$(container).append(view.el);
|
35
35
|
},
|
36
|
-
|
36
|
+
|
37
37
|
prependChild: function(view) {
|
38
38
|
this.renderChild(view);
|
39
|
-
|
39
|
+
this.$el.prepend(view.el);
|
40
40
|
},
|
41
|
-
|
41
|
+
|
42
42
|
prependChildTo: function (view, container) {
|
43
43
|
this.renderChild(view);
|
44
44
|
this.$(container).prepend(view.el);
|
@@ -1,16 +1,28 @@
|
|
1
|
-
|
1
|
+
(function() {
|
2
2
|
|
3
|
-
|
4
|
-
bindTo: function(source, event, callback) {
|
5
|
-
source.bind(event, callback, this);
|
6
|
-
this.bindings = this.bindings || [];
|
7
|
-
this.bindings.push({ source: source, event: event, callback: callback });
|
8
|
-
},
|
3
|
+
Support.Observer = function() {};
|
9
4
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
5
|
+
// `console` is not defined when the Developer Tools are not open in older
|
6
|
+
// versions of Internet Explorer
|
7
|
+
function deprecate(message) {
|
8
|
+
/* global console */
|
9
|
+
if ( console && console.warn ) {
|
10
|
+
console.warn(message);
|
11
|
+
}
|
15
12
|
}
|
16
|
-
|
13
|
+
|
14
|
+
_.extend(Support.Observer.prototype, {
|
15
|
+
bindTo: function(source, event, callback) {
|
16
|
+
deprecate("Using #bindTo has been deprecated. Use #listenTo instead.");
|
17
|
+
this.listenTo(source, event, callback);
|
18
|
+
},
|
19
|
+
|
20
|
+
unbindFromAll: function() {
|
21
|
+
deprecate(
|
22
|
+
"Using #unbindFromAll has been deprecated. Use #stopListening instead."
|
23
|
+
);
|
24
|
+
|
25
|
+
this.stopListening();
|
26
|
+
}
|
27
|
+
});
|
28
|
+
})();
|
@@ -9,7 +9,7 @@ _.extend(Support.SwappingRouter.prototype, Backbone.Router.prototype, {
|
|
9
9
|
}
|
10
10
|
|
11
11
|
this.currentView = newView;
|
12
|
-
$(this.el).
|
12
|
+
$(this.el).html(this.currentView.render().el);
|
13
13
|
|
14
14
|
if (this.currentView && this.currentView.swapped) {
|
15
15
|
this.currentView.swapped();
|
@@ -1,3 +1,4 @@
|
|
1
|
+
/* global Helpers, Support */
|
1
2
|
describe("Support.CompositeView", function() {
|
2
3
|
var orangeView = Support.CompositeView.extend({
|
3
4
|
render: function() {
|
@@ -37,8 +38,26 @@ describe("Support.CompositeView", function() {
|
|
37
38
|
expect($("#test1").text()).toEqual("Orange!");
|
38
39
|
expect($("#test2").text()).toEqual("Orange!");
|
39
40
|
});
|
41
|
+
|
42
|
+
it("sets parent before rendering child view", function() {
|
43
|
+
var view = new blankView();
|
44
|
+
var spy = sinon.spy(view, 'on');
|
45
|
+
var viewWithParentBinding = Support.CompositeView.extend({
|
46
|
+
render: function() {
|
47
|
+
this.listenTo(this.parent, 'foo', this.foo);
|
48
|
+
return this;
|
49
|
+
},
|
50
|
+
|
51
|
+
foo: function() {
|
52
|
+
}
|
53
|
+
});
|
54
|
+
|
55
|
+
view.renderChild(new viewWithParentBinding({ el: "#test1" }));
|
56
|
+
|
57
|
+
expect(spy.called).toBeTruthy();
|
58
|
+
});
|
40
59
|
});
|
41
|
-
|
60
|
+
|
42
61
|
describe("#renderChildInto", function() {
|
43
62
|
it("renders child into the given element and replaces content there", function() {
|
44
63
|
$("#test1").text("Replace this!");
|
@@ -57,7 +76,7 @@ describe("Support.CompositeView", function() {
|
|
57
76
|
var view = new blankView({el: $('<div><div class="inside"></div></div>')});
|
58
77
|
view.renderChildInto(new orangeView(), ".inside");
|
59
78
|
|
60
|
-
|
79
|
+
expect($(view.el).find('.inside').text()).toEqual("Orange!");
|
61
80
|
});
|
62
81
|
});
|
63
82
|
|
@@ -80,7 +99,7 @@ describe("Support.CompositeView", function() {
|
|
80
99
|
view.appendChildTo(new orangeView(), "#test1");
|
81
100
|
|
82
101
|
expect($("#test1").text()).toEqual("Append to this!Orange!");
|
83
|
-
|
102
|
+
|
84
103
|
$("#test1").remove();
|
85
104
|
expect($("#test").text()).toEqual("");
|
86
105
|
});
|
@@ -89,7 +108,7 @@ describe("Support.CompositeView", function() {
|
|
89
108
|
var view = new blankView({el: $('<div><div class="inside">Append to this!</div></div>')});
|
90
109
|
view.appendChildTo(new orangeView(), ".inside");
|
91
110
|
|
92
|
-
expect($(view.el).find('.inside').text()).toEqual("Append to this!Orange!");
|
111
|
+
expect($(view.el).find('.inside').text()).toEqual("Append to this!Orange!");
|
93
112
|
});
|
94
113
|
|
95
114
|
it("appends the element only to elements inside the view", function(){
|
@@ -101,27 +120,27 @@ describe("Support.CompositeView", function() {
|
|
101
120
|
expect($("#outside").text()).toEqual("");
|
102
121
|
});
|
103
122
|
});
|
104
|
-
|
123
|
+
|
105
124
|
describe("#prependChild", function() {
|
106
125
|
it("renders and prepends children views", function() {
|
107
126
|
var view = new blankView({el: "#test"});
|
108
127
|
view.prependChild(new orangeView());
|
109
128
|
view.prependChild(new normalView());
|
110
|
-
|
129
|
+
|
111
130
|
expect($("#test").text()).toEqual("Normal!Orange!");
|
112
131
|
});
|
113
132
|
});
|
114
|
-
|
133
|
+
|
115
134
|
describe("#prependChildTo", function() {
|
116
135
|
it("prepends child into the given element", function() {
|
117
136
|
$("#test1").text("Prepend to this!");
|
118
|
-
|
137
|
+
|
119
138
|
var view = new blankView({el: "#test"});
|
120
139
|
expect($("#test").text()).toEqual("");
|
121
140
|
|
122
141
|
$("#test").append($("#test1"));
|
123
142
|
view.prependChildTo(new orangeView(), "#test1");
|
124
|
-
|
143
|
+
|
125
144
|
expect($("#test1").text()).toEqual("Orange!Prepend to this!");
|
126
145
|
});
|
127
146
|
|
@@ -131,7 +150,7 @@ describe("Support.CompositeView", function() {
|
|
131
150
|
|
132
151
|
expect($(view.el).find('.inside').text()).toEqual("Orange!Prepend to this!");
|
133
152
|
});
|
134
|
-
|
153
|
+
|
135
154
|
it("prepends the element only to elements inside the view", function(){
|
136
155
|
var view = new blankView({el: $('<div><div class="main">Prepend to this!</div></div>')});
|
137
156
|
var div = $("<div class='main' id='outside'></div>");
|
@@ -147,29 +166,15 @@ describe("Support.CompositeView", function() {
|
|
147
166
|
var view = new orangeView();
|
148
167
|
var spy = sinon.spy(view, "unbind");
|
149
168
|
|
150
|
-
|
151
|
-
|
152
|
-
$("#test").append(view.el);
|
153
|
-
});
|
154
|
-
|
155
|
-
Helpers.sleep();
|
156
|
-
|
157
|
-
runs(function() {
|
158
|
-
expect($("#test").text()).toEqual("Orange!");
|
159
|
-
});
|
160
|
-
|
161
|
-
Helpers.sleep();
|
169
|
+
view.render();
|
170
|
+
$("#test").append(view.el);
|
162
171
|
|
163
|
-
|
164
|
-
view.leave();
|
165
|
-
});
|
172
|
+
expect($("#test").text()).toEqual("Orange!");
|
166
173
|
|
167
|
-
|
174
|
+
view.leave();
|
168
175
|
|
169
|
-
|
170
|
-
|
171
|
-
expect(spy.called).toBeTruthy();
|
172
|
-
});
|
176
|
+
expect($("#test").text()).toEqual("");
|
177
|
+
expect(spy.called).toBeTruthy();
|
173
178
|
});
|
174
179
|
|
175
180
|
it("removes children views on leave", function() {
|
@@ -197,7 +202,7 @@ describe("Support.CompositeView", function() {
|
|
197
202
|
it("removes self from parent if invoked on a child view", function() {
|
198
203
|
var view = new blankView();
|
199
204
|
var childView = new orangeView({el: "#test1"});
|
200
|
-
view.renderChild(childView)
|
205
|
+
view.renderChild(childView);
|
201
206
|
view.renderChild(new orangeView({el: "#test2"}));
|
202
207
|
|
203
208
|
expect($("#test1").size()).toEqual(1);
|
@@ -248,9 +253,9 @@ describe("Support.CompositeView", function() {
|
|
248
253
|
|
249
254
|
describe("#swapped", function() {
|
250
255
|
it("fires 'swapped' event", function() {
|
251
|
-
var eventListener = sinon.spy()
|
252
|
-
var view = new Support.CompositeView
|
253
|
-
view.bind('swapped', eventListener)
|
256
|
+
var eventListener = sinon.spy();
|
257
|
+
var view = new Support.CompositeView;
|
258
|
+
view.bind('swapped', eventListener);
|
254
259
|
|
255
260
|
view.swapped();
|
256
261
|
|
@@ -258,45 +263,20 @@ describe("Support.CompositeView", function() {
|
|
258
263
|
});
|
259
264
|
});
|
260
265
|
|
261
|
-
describe("#bindTo", function() {
|
262
|
-
var view = new orangeView();
|
263
|
-
var callback = sinon.spy();
|
264
|
-
var source = new Backbone.Model({
|
265
|
-
title: 'Model or Collection'
|
266
|
-
});
|
267
|
-
|
268
|
-
it("calls the unbindFromAll method when leaving the view", function() {
|
269
|
-
view.bindTo(source, 'foobar', callback);
|
270
|
-
expect(view.bindings.length).toEqual(1);
|
271
|
-
});
|
272
|
-
});
|
273
|
-
|
274
266
|
describe("#unbindFromAll", function() {
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
267
|
+
it("calls the unbindFromAll method when leaving the view", function() {
|
268
|
+
var view = new orangeView();
|
269
|
+
var spy = sinon.spy(view, 'unbindFromAll');
|
270
|
+
var callback = sinon.spy();
|
271
|
+
var source = new Backbone.Model({
|
279
272
|
title: 'Model or Collection'
|
280
|
-
|
273
|
+
});
|
281
274
|
|
282
|
-
runs(function() {
|
283
275
|
view.render();
|
284
276
|
view.bindTo(source, 'foo', callback);
|
285
|
-
expect(view.bindings.length).toEqual(1);
|
286
|
-
});
|
287
|
-
|
288
|
-
Helpers.sleep();
|
289
|
-
|
290
|
-
runs(function() {
|
291
277
|
view.leave();
|
292
|
-
});
|
293
|
-
|
294
|
-
Helpers.sleep();
|
295
278
|
|
296
|
-
|
297
|
-
runs(function() {
|
298
|
-
expect(spy.called).toBeTruthy();
|
299
|
-
});
|
279
|
+
expect(spy.called).toBeTruthy();
|
300
280
|
});
|
301
281
|
});
|
302
282
|
});
|