JSFiddle - React, Tailwind, and code Playground
HTML
<script src="http://cloud.github.com/downloads/wycats/handlebars.js/handlebars-1.0.0.beta.6.js"></script>
<script src="http://cloud.github.com/downloads/emberjs/ember.js/ember-1.0.pre.js"></script>
<script src="http://cloud.github.com/downloads/emberjs/data/ember-data-latest.js"></script>
<!DOCTYPE html>
<html>
<title>Users</title>
<body>
<script type="text/x-handlebars" data-template-name="application">
<div id="main">
{{ outlet }}
</div>
</script>
<script type="text/x-handlebars" data-template-name="person">
{{view PersonApp.SearchField placeholder="search..." valueBinding="searchText"}}
<table width="250px">
<thead>
{{#each context in controller.sortColumns}}
<th><a {{action sortby context href=true target="controller"}}>{{context.column}}</a></th>
{{/each}}
</thead>
<tbody>
{{#each person in controller.paginatedContent}}
<tr>
<td>{{person.id}}</td>
<td>{{view Ember.TextField valueBinding="person.username"}}</td>
</tr>
{{/each}}
</tbody>
</table>
<div name="prev"><a class="paginator" {{action prevPage href=true target="controller"}}>Prev</a></div>
<ul class="pagination gui-text">
{{#each pages}}
{{view PersonApp.PaginationItemView contentBinding="this"}}
{{/each}}
</ul>
<div name="next"><a class="paginator" {{action nextPage href=true target="controller"}}>Next</a></div>
</script>
<script type="text/x-handlebars" data-template-name="pagination_item">
{{#with view}}
<a {{action paginateUsers content href=true}}>
<span {{bindAttr class="spanClasses isActive:active"}}>{{content.page_id}}</span>
</a>
{{/with}}
</script>
</body>
</html>
JavaScript
var get = Ember.get;
Ember.SortablePaginationMixin = Ember.Mixin.create({
filterBy: '',
sortDirection: 'asc',
availableColumns: function() {
//hack for jsfiddle to work ...
return ["id","username"];
//return this.get('content').get('type.ClassMixin.ownerConstructor.attributes.keys').toArray();
}.property(),
sortColumns: function() {
var sortable = [];
var attributes = this.get('availableColumns');
for (var i = 0; i < attributes.length; i++) {
sortable.push({ column: attributes[i], dir: 'asc' });
}
return sortable;
}.property(),
sortby: function(event) {
var sortby = event.context.column;
var incomingDirection = event.context.dir;
var route = this.get('sortableRoute');
var currentSortBy = this.get('sortBy');
var currentSortDirection = this.get('sortDirection');
var direction = 'asc';
if (sortby === currentSortBy) {
if (incomingDirection === currentSortDirection) {
var direction = 'desc';
}
}
this.get('target').send(route, {column:sortby,dir:direction});
},
pages: function() {
var availablePages = this.get('availablePages'),
pages = [],
page;
for (i = 0; i < availablePages; i++) {
page = i + 1;
pages.push({ page_id: page.toString() });
}
return pages;
}.property('availablePages'),
currentPage: function() {
return parseInt(this.get('selectedPage'), 10) || 1;
}.property('selectedPage'),
nextPage: function() {
var nextPage = this.get('currentPage') + 1;
var availablePages = this.get('availablePages');
if (nextPage <= availablePages) { this.transitionTo(nextPage) }
},
prevPage: function() {
var prevPage = this.get('currentPage') - 1;
if (prevPage > 0) { this.transitionTo(prevPage) }
},
transitionTo: function(page) {
var pages = this.get('pages');
var route = this.get('paginationRoute');
this.get('target').send(route, pages[page - 1]);
},
...