Skip to content

Commit cd0788e

Browse files
committed
Added an autosort option to the CollectionBinder with an example.
1 parent bdd3b73 commit cd0788e

File tree

3 files changed

+176
-8
lines changed

3 files changed

+176
-8
lines changed

Backbone.CollectionBinder.js

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,16 @@
1212
throw 'Please include Backbone.ModelBinder.js before Backbone.CollectionBinder.js';
1313
}
1414

15-
Backbone.CollectionBinder = function(elManagerFactory){
15+
Backbone.CollectionBinder = function(elManagerFactory, options){
1616
_.bindAll(this);
1717

1818
this._elManagerFactory = elManagerFactory;
1919
if(!this._elManagerFactory) throw 'elManagerFactory must be defined.';
2020

2121
// Let the factory just use the trigger function on the view binder
2222
this._elManagerFactory.trigger = this.trigger;
23+
24+
this._options = options || {};
2325
};
2426

2527
Backbone.CollectionBinder.VERSION = '0.1.1';
@@ -34,9 +36,7 @@
3436
this._collection = collection;
3537
this._elManagerFactory.setParentEl(parentEl);
3638

37-
this._collection.each(function(model){
38-
this._onCollectionAdd(model);
39-
}, this);
39+
this._onCollectionReset();
4040

4141
this._collection.on('add', this._onCollectionAdd, this);
4242
this._collection.on('remove', this._onCollectionRemove, this);
@@ -85,6 +85,10 @@
8585
_onCollectionAdd: function(model){
8686
this._elManagers[model.cid] = this._elManagerFactory.makeElManager(model);
8787
this._elManagers[model.cid].createEl();
88+
89+
if(this._options['autoSort']){
90+
this.sortRootEls();
91+
}
8892
},
8993

9094
_onCollectionRemove: function(model){
@@ -116,6 +120,21 @@
116120
this._elManagers[model.cid].removeEl();
117121
delete this._elManagers[model.cid];
118122
}
123+
},
124+
125+
sortRootEls: function(){
126+
this._collection.each(function(model, modelIndex){
127+
var modelElManager = this.getManagerForModel(model);
128+
if(modelElManager){
129+
var modelEl = modelElManager.getEl();
130+
var currentRootEls = this._elManagerFactory.getParentEl().children();
131+
132+
if(currentRootEls[modelIndex] !== modelEl[0]){
133+
modelEl.detach();
134+
modelEl.insertBefore(currentRootEls[modelIndex]);
135+
}
136+
}
137+
}, this);
119138
}
120139
});
121140

@@ -136,6 +155,10 @@
136155
this._parentEl = parentEl;
137156
},
138157

158+
getParentEl: function(){
159+
return this._parentEl;
160+
},
161+
139162
makeElManager: function(model){
140163

141164
var elManager = {
@@ -206,6 +229,10 @@
206229
this._parentEl = parentEl;
207230
},
208231

232+
getParentEl: function(){
233+
return this._parentEl;
234+
},
235+
209236
makeElManager: function(model){
210237
var elManager = {
211238

@@ -238,6 +265,10 @@
238265
return this._model;
239266
},
240267

268+
getView: function(){
269+
return this._view;
270+
},
271+
241272
getEl: function(){
242273
return this._view.el;
243274
}

Backbone.CollectionBinder.min.js

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/CollectionBinder_sorted.html

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2+
<html xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">
3+
<head>
4+
<meta content="text/html;charset=UTF-8" http-equiv="Content-Type"/>
5+
<title>Test the CollectionBinder Sorting Capabilities</title>
6+
7+
<!-- include source files here... -->
8+
<script type="text/javascript" src="../public/javascripts/underscore.js"></script>
9+
<script type="text/javascript" src="../public/javascripts/jquery.js"></script>
10+
<script type="text/javascript" src="../public/javascripts/backbone.js"></script>
11+
<script type="text/javascript" src="../Backbone.ModelBinder.js"></script>
12+
<script type="text/javascript" src="../Backbone.CollectionBinder.js"></script>
13+
14+
<script>
15+
$().ready(function () {
16+
collection = new Backbone.Collection();
17+
18+
collection.comparator = function(model){
19+
return model.get('order');
20+
}
21+
22+
collection.reset([
23+
{id: 0, firstName: 'Adam', lastName: 'Zebra', order: 10},
24+
{id: 1, firstName: 'Bob', phone: '1234567', order: 9}
25+
]);
26+
27+
collection.on('change:order', function(){
28+
collection.sort();
29+
});
30+
31+
// Display the collection content
32+
displayCollectionContent = function(){
33+
var collectionVals = collection.reduce(function(memo, model){
34+
return memo + ' (firstName=' + model.get('firstName') + ' order=' + model.get('order') + '), ';
35+
}, '');
36+
$('#collectionContent').html(collectionVals);
37+
};
38+
39+
displayCollectionContent();
40+
41+
$('#refreshCollectionContent').click(displayCollectionContent);
42+
43+
// Just create a simple view and attach the view's element to an existing DOM element
44+
view = new Backbone.View();
45+
view.setElement($('#viewContent'));
46+
47+
// Normally this will be in a separate html template file
48+
var rowHtml = '<tr><td data-name="firstName"></td><td data-name="lastName"></td><td data-name="phone"></td><td data-name="order"></td></tr>';
49+
50+
// The managerFactory helps to generate element managers - an el manager creates/removes elements when models are added to a collection
51+
// The 1st arg is the html template that is used to generate view elements for each model in the collection
52+
// The 2nd arg is the DOM element attribute that is used to bind between the Model attributes and DOM elements - it's optional
53+
var elManagerFactory = new Backbone.CollectionBinder.ElManagerFactory(rowHtml, "data-name");
54+
55+
collectionBinder = new Backbone.CollectionBinder(elManagerFactory, {autoSort: true});
56+
57+
// This is very similar to the ModelBinder.bind() function but the collectionBinder will also create nested element views
58+
collectionBinder.bind(collection, view.$('tbody'));
59+
60+
61+
62+
// Demonstrating that the CollectionBinder has create/remove events you can listen to
63+
collectionBinder.on('elCreated', function(model, el){
64+
console.log('The collectionBinder created an element ', model, el);
65+
});
66+
67+
collectionBinder.on('elRemoved', function(model, el){
68+
console.log('The collectionBinder removed an element ', model, el);
69+
});
70+
71+
//////////////////////////////////////////////////////////////////////////////////////////////////
72+
// The handlers below just help demonstrate that the rows in the table are bound to the collection
73+
modelCreateCount = 2;
74+
$('#createModel').on('click', function(){
75+
collection.add({id: modelCreateCount, firstName: 'Jon ' + modelCreateCount, lastName: 'Doe ' + modelCreateCount, phone: 'xxx ', order: 10-collection.length});
76+
modelCreateCount++;
77+
});
78+
79+
$('#removeModel').on('click', function(){
80+
if(collection.length > 0){
81+
collection.remove(collection.at(collection.length - 1));
82+
}
83+
});
84+
85+
modelUpdateCount = 0;
86+
$('#updateModel').on('click', function(){
87+
if(collection.length > 0){
88+
collection.at(collection.length - 1).set({phone: 'xxx ' + modelUpdateCount});
89+
modelUpdateCount++;
90+
}
91+
});
92+
93+
$('#resetCollection').on('click', function(){
94+
collection.reset();
95+
});
96+
97+
});
98+
99+
</script>
100+
101+
</head>
102+
<body>
103+
<input type="button" id="refreshCollectionContent" value="Refresh"/>
104+
Collection content: <div id="collectionContent"></div>
105+
<br>
106+
Testing actions:
107+
<br>
108+
<input type="button" id="createModel" value="Create Model"/>
109+
<input type="button" id="removeModel" value="Remove Last Model"/>
110+
<input type="button" id="updateModel" value="Update Last Model's Phone"/>
111+
&nbsp;&nbsp;&nbsp;
112+
<input type="button" id="resetCollection" value="Reset Collection"/>
113+
<br>
114+
<br>
115+
116+
View content: (sorted by the Order attribute)<hr>
117+
<div id="viewContent">
118+
119+
<table>
120+
<thead>
121+
<tr>
122+
<th>First Name</th>
123+
<th>Last Name</th>
124+
<th>Phone</th>
125+
<th>Order</th>
126+
</tr>
127+
</thead>
128+
129+
<tbody>
130+
131+
</tbody>
132+
</table>
133+
</div>
134+
135+
136+
</body>
137+
</html>

0 commit comments

Comments
 (0)