backbone-support 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- 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 [![Build Status](https://travis-ci.org/thoughtbot/backbone-support.png?branch=master)](https://travis-ci.org/thoughtbot/backbone-support) [![Gem Version](https://badge.fury.io/rb/backbone-support.png)](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
|
});
|