Created
March 18, 2013 22:14
-
-
Save bfagundez/5191302 to your computer and use it in GitHub Desktop.
A CodePen by martian. Backbone Paginate+Filter mixin - Adds a mixin to a Backbone view to paginate and filter a collection.
Requires Cocktail.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script type="text/html" id="template-mappings_grid_view"> | |
<span class="the-number"></span> | |
<table class="table table-striped table-bordered table-condensed"> | |
<thead> | |
<tr> | |
<% _.each(colDefinition, function(col) { %> | |
<td><%= col.name %></td> | |
<% }); %> | |
</tr> | |
</thead> | |
<tbody> | |
<% _.each(record_list, function(row) { %> | |
<tr> | |
<% _.each(colDefinition, function(col) { %> | |
<td> | |
<%= row.get(col.key) %> | |
</td> | |
<% }); %> | |
</tr> | |
<% }); %> | |
</tbody> | |
</table> | |
</script> | |
<script type="text/html" id="template-pagination"> | |
<div class="pagination pagination-mini"> | |
<ul class="pull-right"> | |
<li class="<%= current_page == 1 ? 'disabled' : '' %> previous"><a href="#">Prev</a></li> | |
<% for(var i = 1; i <= total_pages; i++) { %> | |
<li class="<%= i == current_page ? 'active' : '' %> goto_page" data-pagenumber="<%= i %>"><a href="#"><%= i %></a></li> | |
<% } %> | |
<li class="<%= current_page == total_pages ? 'disabled' : '' %> next"><a href="#">Next</a></li> | |
</ul> | |
</div> | |
<div class="pull-right" style="margin:5px 0;clear:both;"><small><strong><%= total_records %></strong> records, showing from <strong><%= (current_page - 1 ) * records_per_page %></strong> to <strong><%= total_records > current_page * records_per_page ? current_page * records_per_page:total_records %></strong>, page <strong><%= current_page %></strong></small></div> | |
</script> | |
<div class="span8"> | |
<div id="the_grid"></div> | |
</div> | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Defines the structure of the records | |
MappingRecord = Backbone.Model.extend({}); | |
MappingCollection = Backbone.Collection.extend({model: MappingRecord }); | |
var MappingsGridView = Backbone.View.extend({ | |
template: $('#template-mappings_grid_view').html(), | |
initialize: function(){ | |
// This is needed for the PAGINATED MIXIN! | |
// instead of calling this.render, this.refreshPage must be called. | |
this.listenTo(this.collection, 'add', this.refreshPage); | |
this.listenTo(this.collection, 'remove', this.refreshPage); | |
this.$el = this.options.$el; | |
// add a container, so we are able to refresh just records | |
this.container_id = _.uniqueId('grid_container'); | |
this.$el.append('<div id="'+this.container_id +'"></div>'); | |
this.$container = $('#'+this.container_id); | |
}, | |
colDefinition: [ | |
{ name: 'A', key: 'record_a'}, | |
{ name: 'B', key: 'record_b' } | |
], | |
render: function(){ | |
this.$container.html(_.template(this.template, { 'record_list' : this.recordlist , 'colDefinition': this.colDefinition})); | |
this.delegateEvents(); | |
return this; | |
} | |
}); | |
var PaginateMixin = { | |
initialize: function() { | |
this.currentPage = 0; | |
this.recordsPerPage = this.options.recordsPerPage ? this.options.recordsPerPage : 20; | |
this.getPageItems(this.currentPage); | |
this.fields_to_filter = this.options.fields_to_filter ? this.options.fields_to_filter : ['name']; | |
_.each(this.collection.models, function(rec){ | |
rec.set('visible',true); | |
}); | |
this.paginator_id = _.uniqueId('paginator'); | |
this.filter_id = _.uniqueId('filter'); | |
this.$el.prepend('<div class="row"> \ | |
<div class="span2 pull-left" style="padding-top:15px"><div class="input-prepend"><span class="add-on">Filter</span><input class="span2 filter_grid" type="text" id="'+this.filter_id+'" ></div></div> \ | |
<div class="span2 pull-left"></div>\ | |
<div class="span4 pull-right"><div id="'+this.paginator_id+'"></div></div> \ | |
</div>'); | |
this.subcollection = this.collection; | |
}, | |
events: { | |
'keyup .filter_grid' : 'filterCollection', | |
'click .previous': 'goToPreviousPage', | |
'click .next': 'goToNextPage', | |
'click .goto_page' : 'goToPageNumber' | |
}, | |
goToPageNumber: function(ev){ | |
this.goToPage($(ev.target).text() - 1); | |
}, | |
render: function() { | |
var numberOfPages = this.numberOfPages(); | |
$('#'+this.paginator_id).html(_.template($('#template-pagination').html(),{ total_pages : numberOfPages , current_page: this.currentPage + 1, total_records: this.subcollection.length, records_per_page: this.recordsPerPage })); | |
return this; | |
}, | |
goToPage: function(page) { | |
var numberOfPages = this.numberOfPages(); | |
numberOfPages > 0 ? this.currentPage = Math.min(Math.max(page, 0), numberOfPages - 1) : this.currentPage = 0; | |
this.getPageItems(page); | |
this.render(); | |
return this.currentPage; | |
}, | |
filterCollection: function(event){ | |
var search_string = event ? $(event.currentTarget).val() : ''; | |
if(search_string != ''){ | |
var self = this; | |
var keys = this.fields_to_filter; | |
_.each(this.collection.models, function(rec){ | |
rec.set('visible',false); | |
_.each(keys, function(key){ | |
console.log(key,rec.get(key),rec); | |
if(rec.get(key).replace(/\s+/g, '').toLowerCase().indexOf(search_string.replace(/\s+/g, '').toLowerCase()) > -1 ){ | |
rec.set('visible',true); | |
} | |
}); | |
}); | |
} else { | |
var self = this; | |
_.each(this.collection.models, function(rec){ | |
rec.set('visible',true); | |
}); | |
} | |
this.getPageItems(); | |
this.render(); | |
}, | |
refreshPagination: function(){ | |
var numberOfPages = this.numberOfPages(); | |
$($(this.$el).find('.pagination')[0]).html(_.template($('#template-pagination').html(),{ total_pages : numberOfPages , current_page: this.currentPage + 1 , total_records: this.subcollection.length, records_per_page: this.recordsPerPage })); | |
}, | |
refreshPage: function(){ | |
this.goToPage(this.currentPage); | |
}, | |
goToNextPage: function() { | |
return this.goToPage(this.currentPage + 1); | |
}, | |
goToPreviousPage: function() { | |
return this.goToPage(this.currentPage - 1); | |
}, | |
getPageItems: function(page) { | |
page == null ? page = this.currentPage : '' ; | |
var start = this.recordsPerPage * page; | |
var end = this.recordsPerPage * page + this.recordsPerPage; | |
var subcollection = this.collection.where({ 'visible':true }); | |
end > subcollection.length ? end = subcollection.length : '' | |
this.recordlist = []; | |
for(var i = start; i < end; i++) { | |
this.recordlist.push(subcollection[i]); | |
} | |
// go back 1 page if this recordlist is empty | |
this.recordlist.length == 0 && subcollection.length > 0 ? this.goToPage(0) : ''; | |
this.subcollection = subcollection; | |
}, | |
numberOfPages: function() { | |
return Math.ceil(this.subcollection.length / this.recordsPerPage); | |
} | |
} | |
// Apply the mixin to the view | |
Cocktail.mixin(MappingsGridView, PaginateMixin); | |
huge_collection = new MappingCollection; | |
for(var i = 0; i < 98; i++) { | |
huge_collection.add({ 'record_a' : 'arec'+i, 'record_b' : 'brec'+i , 'visible': true }); | |
} | |
grid_view = new MappingsGridView({'collection':huge_collection, $el: $('#the_grid') , fields_to_filter : ['record_a','record_b']}); | |
grid_view.render(); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment