Created
October 16, 2014 18:01
-
-
Save kkestell/ade30f868bd122707628 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
/* | |
Basic Usage | |
=========== | |
Assuming your markup looks like this: | |
<table id="table" class="table"></table> | |
<div id="pagination" class="text-center"></div> | |
And your JSON looks like this: | |
{ | |
total: 125, | |
results: [ | |
{ | |
name: 'John Doe', | |
age: 40, | |
admin: true | |
}, | |
{ | |
name: 'Jane Doe', | |
age: 25, | |
admin: false | |
} | |
] | |
} | |
You'd initialize the table like this: | |
$('#table').table({ | |
url: '/Users', | |
limit: 10, | |
pagination: '#pagination', | |
showPages: 5, | |
columns: [ | |
{ | |
label: 'Name', | |
key: 'name', | |
classes: 'class-here another-class' | |
}, | |
{ | |
label: 'Age', | |
key: 'age' | |
}, | |
{ | |
label: 'Admin', | |
key: 'admin', | |
format: function(item, val) { | |
return val === true ? 'Yes' : 'No'; | |
} | |
} | |
] | |
}); | |
Column Sorting | |
============== | |
To enable sorting on a column, add an allowSorting property to the column | |
definition. Two global options are also defined, sortBy, to control the | |
column to sort on by default, and sortDescending, which lets you control | |
the sort order. | |
$('#table').table({ | |
url: '/Users', | |
limit: 10, | |
pagination: '#pagination', | |
sortBy: 'name', | |
sortDescending: false, | |
columns: [ | |
{ | |
label: 'Name', | |
key: 'name', | |
allowSorting: true | |
}, | |
{ | |
label: 'Age', | |
key: 'age', | |
allowSorting: true | |
}, | |
{ | |
label: 'Admin', | |
key: 'admin', | |
format: function(item, val) { | |
return val === true ? 'Yes' : 'No'; | |
} | |
} | |
] | |
}); | |
Filtering | |
========= | |
Assuming your markup looks like this: | |
<form id="filters"> | |
<input type="text" name="name" /> | |
<select name="admin"> | |
<option value="true">Yes</option> | |
<option value="false">No</option> | |
</select> | |
<input type="submit" value="Filter" /> | |
</form> | |
<table id="table" class="table"></table> | |
<div id="pagination" class="text-center"></div> | |
You'd initialize the table like this: | |
$('#table').table({ | |
url: '/Users', | |
limit: 10, | |
listenTo: '#filters', | |
extraParams: function() { | |
return $('#filters').serializeToJS(); | |
}, | |
pagination: '#pagination', | |
columns: [ | |
{ | |
label: 'Name', | |
key: 'name' | |
}, | |
{ | |
label: 'Age', | |
key: 'age' | |
}, | |
{ | |
label: 'Admin', | |
key: 'admin', | |
format: function(item, val) { | |
return val === true ? 'Yes' : 'No'; | |
} | |
} | |
] | |
}); | |
And any time the filters form is submitted, your table will automatically | |
update. | |
The `extraParams` option takes a function which should return an object. This | |
object will be serialized and passed up to the server with the XHR request. | |
NOTE: In this example we're using `serializeToJS` which is provided by | |
~/Content/JS/Core/Serialization.js | |
*/ | |
(function ($) { | |
$.fn.table = function (options) { | |
var settings = $.extend({ | |
limit: 10, | |
showPages: 5, | |
sortBy: null, | |
sortDescending: false | |
}, options); | |
var $table = $(this); | |
var offset = 0; | |
// Build table row and header cells | |
function buildHead() { | |
var thead = ''; | |
thead += '<thead>'; | |
thead += '<tr>'; | |
settings.columns.forEach(function (col) { | |
var classes = ''; | |
if (typeof col.classes !== 'undefined') { | |
classes = col.classes; | |
} | |
if (settings.sortBy === col.key) { | |
thead += '<th data-key="' + col.key + '" class="active '+ classes +'">'; | |
thead += col.label; | |
if (settings.sortDescending === true) { | |
thead += ' V'; | |
} else { | |
thead += ' ^'; | |
} | |
thead += '</th>'; | |
} else { | |
thead += '<th data-key="' + col.key + '" class="' + classes + '">' + col.label + '</th>'; | |
} | |
}); | |
thead += '</tr>'; | |
thead += '</thead>'; | |
$table.find('thead').remove(); | |
$table.prepend(thead); | |
} | |
// Build table rows and body cells | |
function buildBody(items) { | |
var tbody = ''; | |
tbody += '<tbody>'; | |
items.forEach(function (item) { | |
tbody += '<tr>'; | |
settings.columns.forEach(function (col) { | |
var val = item[col.key]; | |
var classes = ''; | |
if (typeof col.classes !== 'undefined') { | |
classes = col.classes; | |
} | |
tbody += '<td class="'+ classes +'">'; | |
if (typeof col.format === 'function') { | |
tbody += col.format(item, val); | |
} else { | |
tbody += val; | |
} | |
tbody += '</td>'; | |
}); | |
tbody += '</tr>'; | |
}); | |
$table.find('tbody').remove(); | |
$table.append(tbody); | |
} | |
// Update pagination controls | |
function buildPagination(totalItems) { | |
var numPages = Math.ceil(totalItems / settings.limit), | |
currentPage = Math.ceil(offset / settings.limit), | |
ul = ''; | |
var pages = settings.showPages; | |
var prevPage = Math.floor(pages / 2); | |
ul += '<ul class="pagination">'; | |
// Add Left Arrow | |
if (currentPage > 0) { | |
ul += '<li><a data-page="' + (currentPage - 1) + '" href="#">«</a></li>'; | |
} else { | |
ul += '<li class="disabled"><a href="#">«</a></li>'; | |
} | |
if (numPages <= pages) { | |
for (var i = 0; i < numPages; i++) { | |
if (currentPage === i) { | |
ul += '<li class="active"><a href="#">' + (i + 1) + '</a></li>'; | |
} else { | |
ul += '<li><a data-page="' + i + '" href="#">' + (i + 1) + '</a></li>'; | |
} | |
} | |
} else { | |
// Display first 'x' number of links | |
if (currentPage < prevPage) { | |
for (var i = 0; i < pages; i++) { | |
if (currentPage === i) { | |
ul += '<li class="active"><a href="#">' + (i + 1) + '</a></li>'; | |
} else { | |
ul += '<li><a data-page="' + i + '" href="#">' + (i + 1) + '</a></li>'; | |
} | |
} | |
} | |
// Display last 'x' number of links | |
else if ((currentPage + 1) > (numPages - prevPage)) { | |
var page = (numPages - pages); | |
for (var i = 0; i < pages; i++) { | |
if (currentPage === page) { | |
ul += '<li class="active"><a href="#">' + (page + 1) + '</a></li>'; | |
} else { | |
ul += '<li><a data-page="' + page + '" href="#">' + (page + 1) + '</a></li>'; | |
} | |
page++; | |
} | |
} | |
// Display pages on either side of current page | |
else { | |
for (var i = 0; i < prevPage; i++) { | |
ul += '<li><a data-page="' + ((currentPage + 1) - (prevPage - i)) + '" href="#">' + ((currentPage + 1) - (prevPage - i)) + '</a></li>'; | |
} | |
ul += '<li class="active"><a href="#">' + (currentPage + 1) + '</a></li>'; | |
for (var i = 0; i < prevPage; i++) { | |
ul += '<li><a data-page="' + (currentPage + (i + 2)) + '" href="#">' + (currentPage + (i + 2)) + '</a></li>'; | |
} | |
} | |
} | |
if (currentPage < numPages - 1) { | |
ul += '<li><a data-page="' + (currentPage + 1) + '" href="#">»</a></li>'; | |
} else { | |
ul += '<li class="disabled"><a href="#">»</a></li>'; | |
} | |
/*if (currentPage > 0) { | |
ul += '<li><a data-page="' + (currentPage - 1) + '" href="#">«</a></li>'; | |
} else { | |
ul += '<li class="disabled"><a href="#">«</a></li>'; | |
} | |
for (var i = 0; i < showPages; i++) { | |
if (currentPage === i) { | |
ul += '<li class="active"><a href="#">' + (i + 1) + '</a></li>'; | |
} else { | |
ul += '<li><a data-page="' + i + '" href="#">' + (i + 1) + '</a></li>'; | |
} | |
} | |
if (currentPage < numPages - 1) { | |
ul += '<li><a data-page="' + (currentPage + 1) + '" href="#">»</a></li>'; | |
} else { | |
ul += '<li class="disabled"><a href="#">»</a></li>'; | |
} | |
*/ | |
ul += '</ul>'; | |
$(settings.pagination).html(ul); | |
} | |
// Update table data from server | |
function query() { | |
var extraParams = { | |
limit: settings.limit, | |
offset: offset, | |
sortBy: settings.sortBy, | |
sortDescending: settings.sortDescending | |
}; | |
if (typeof settings.extraParams === 'function') { | |
$.extend(extraParams, settings.extraParams()); | |
} | |
$.ajax(settings.url, { | |
data: extraParams, | |
type: 'GET', | |
success: function (data, textStatus, jqXHR) { | |
buildBody(data.results); | |
if (settings.pagination !== undefined) { | |
buildPagination(data.total); | |
} | |
}, | |
error: function (jqXHR, textStatus, errorThrown) { | |
alert('Error fetching data.'); | |
} | |
}); | |
} | |
// Listen to a form and automatically update when it's submitted | |
if (settings.listenTo !== undefined) { | |
$(settings.listenTo).submit(function (e) { | |
// Reset offset when filters change | |
offset = 0; | |
e.preventDefault(); | |
query(); | |
}); | |
} | |
// Update when pagination links are clicked | |
if (settings.pagination !== undefined) { | |
$(settings.pagination).on('click', 'a', function (e) { | |
e.preventDefault(); | |
var page = parseInt($(this).data('page')); | |
if (!isNaN(page)) { | |
offset = page * settings.limit; | |
query(); | |
} | |
}) | |
} | |
// Update sortBy and sortDescending when a table header is clicked | |
$table.on('click', 'th', function (e) { | |
e.preventDefault(); | |
var sortBy = $(this).data('key'); | |
var allowSorting = false; | |
settings.columns.forEach(function (col) { | |
if(col.key === sortBy) { | |
if (col.hasOwnProperty('allowSorting') === true && col.allowSorting === true) { | |
allowSorting = true; | |
} | |
} | |
}); | |
if (allowSorting === false) return; | |
if (settings.sortBy === sortBy) { | |
settings.sortDescending = !settings.sortDescending; | |
} else { | |
settings.sortDescending = false; | |
settings.sortBy = sortBy; | |
} | |
buildHead(); | |
query(); | |
}); | |
buildHead(); | |
query(); | |
return this; | |
}; | |
}(jQuery)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment