Added support for search, sorting, numbers, localization

pull/264/head
Michael Ryvkin 9 years ago
parent 9875956e41
commit b533400ff2

@ -10,7 +10,7 @@ div.alphabet span {
color: #3174c7; color: #3174c7;
cursor: pointer; cursor: pointer;
text-align: center; text-align: center;
width: 3.5% width: 3.5%;
} }
div.alphabet span:hover { div.alphabet span:hover {
@ -25,7 +25,7 @@ div.alphabet span.empty {
color: red; color: red;
} }
div.alphabetInfo { div.alphabet_info {
display: block; display: block;
position: absolute; position: absolute;
background-color: #111; background-color: #111;
@ -37,3 +37,7 @@ div.alphabetInfo {
text-align: center; text-align: center;
z-index: 1; z-index: 1;
} }
tr.alphabet_group, tr.alphabet_group:hover {
background-color: rgba(0,0,0,0.15) !important;
}

@ -1,4 +1,4 @@
/*! AlphabetSearch for DataTables v1.0.0 /*! AlphabetSearch for DataTables v1.1.0
* 2014 SpryMedia Ltd - datatables.net/license * 2014 SpryMedia Ltd - datatables.net/license
*/ */
@ -6,16 +6,17 @@
* @summary AlphabetSearch * @summary AlphabetSearch
* @description Show an set of alphabet buttons alongside a table providing * @description Show an set of alphabet buttons alongside a table providing
* search input options * search input options
* @version 1.0.0 * @version 1.1.1
* @file dataTables.alphabetSearch.js * @file dataTables.alphabetSearch.js
* @author SpryMedia Ltd (www.sprymedia.co.uk) * @author SpryMedia Ltd (www.sprymedia.co.uk)
* @contact www.sprymedia.co.uk/contact * @contact www.sprymedia.co.uk/contact
* @copyright Copyright 2014 SpryMedia Ltd. * @copyright Copyright 2014 SpryMedia Ltd.
* *
* License MIT - http://datatables.net/license/mit * License MIT - http://datatables.net/license/mit
* *
* For more detailed information please see: * For more detailed information please see:
* http://datatables.net/blog/2014-09-22 * http://datatables.net/blog/2014-09-22
* http://www.gyrocode.com/articles/jquery-datatables-alphabetical-search
*/ */
(function(){ (function(){
@ -23,7 +24,7 @@
// Search function // Search function
$.fn.dataTable.Api.register( 'alphabetSearch()', function ( searchTerm ) { $.fn.dataTable.Api.register( 'alphabetSearch()', function ( searchTerm ) {
this.iterator( 'table', function ( context ) { this.iterator( 'table', function ( context ) {
context.alphabetSearch = searchTerm; context.alphabetSearch.letter = searchTerm;
} ); } );
return this; return this;
@ -34,7 +35,8 @@ $.fn.dataTable.Api.register( 'alphabetSearch.recalc()', function ( searchTerm )
this.iterator( 'table', function ( context ) { this.iterator( 'table', function ( context ) {
draw( draw(
new $.fn.dataTable.Api( context ), new $.fn.dataTable.Api( context ),
$('div.alphabet', this.table().container()) $('div.alphabet', this.table().container()),
context
); );
} ); } );
@ -45,18 +47,81 @@ $.fn.dataTable.Api.register( 'alphabetSearch.recalc()', function ( searchTerm )
// Search plug-in // Search plug-in
$.fn.dataTable.ext.search.push( function ( context, searchData ) { $.fn.dataTable.ext.search.push( function ( context, searchData ) {
// Ensure that there is a search applied to this table before running it // Ensure that there is a search applied to this table before running it
if ( ! context.alphabetSearch ) { if ( ! context.alphabetSearch.letterSearch ) {
return true; return true;
} }
if ( searchData[0].charAt(0) === context.alphabetSearch ) { var letter = searchData[context.alphabetSearch.column]
return true; .toString()
.replace(/<.*?>/g, '')
.charAt(0).toUpperCase();
if(context.alphabetSearch.letterSearch !== '#'){
if ( letter === context.alphabetSearch.letterSearch ) {
return true;
}
} else {
if(/\d/.test(letter)){
return true;
}
} }
return false; return false;
} ); } );
// Order plug-in
//
// NOTES: If sorting by alphabetized column
// there would be two calls to this method
$.fn.dataTable.ext.order['alphabetSearch'] = function ( context, col )
{
var order_col = this.api().order()[0][0];
var order_method = this.api().order()[0][1];
// If sorting by column other than the one being alphabetized
if(order_col !== context.alphabetSearch.column){
context.alphabetSearch.pass = 0;
}
var data = this.api().column( col, { order: 'index' } ).data().map( function (value, index) {
// If sorting by alphabetized column
return (order_col === context.alphabetSearch.column)
? (
// If first pass
( !context.alphabetSearch.pass )
// Ignore
?
''
// Otherwise, if it's a second pass
:
(
// If method is ascending sort
( order_method === 'asc' )
// Return first letter
? value.charAt(0)
: String.fromCharCode(65535 - value.charCodeAt(0))
)
)
// Otherwise, if sorting by column other than the one being alphabetized,
// return first letter
: value.charAt(0);
} );
// If sorting by alphabetized column
if(order_col === context.alphabetSearch.column){
// If pass is not defined, set it to 0
if(!context.alphabetSearchPass){ context.alphabetSearch.pass = 0; }
// Increment pass counter and reset it to 0 if it's a second pass
context.alphabetSearch.pass = (context.alphabetSearch.pass + 1) % 2;
}
return data;
};
// Private support methods // Private support methods
function bin ( data ) { function bin ( data ) {
var letter, bins = {}; var letter, bins = {};
@ -67,6 +132,8 @@ function bin ( data ) {
.replace(/<.*?>/g, '') .replace(/<.*?>/g, '')
.charAt(0).toUpperCase(); .charAt(0).toUpperCase();
if(/\d/.test(letter)){ letter = '#'; }
if ( bins[letter] ) { if ( bins[letter] ) {
bins[letter]++; bins[letter]++;
} }
@ -78,33 +145,67 @@ function bin ( data ) {
return bins; return bins;
} }
function draw ( table, alphabet ) function draw ( table, alphabet, context )
{ {
alphabet.empty(); alphabet.empty();
alphabet.append( 'Search: ' ); alphabet.append( context.oLanguage.alphabetSearch.infoDisplay + ': ' );
var columnData = table.column(0).data(); var columnData = table.column(context.alphabetSearch.column, { search: 'applied' } ).data();
var bins = bin( columnData ); var bins = bin( columnData );
$('<span class="clear active"/>') $('<span class="alphabet-clear' + ((!context.alphabetSearch.letter) ? ' active' : '') + '"/>')
.data( 'letter', '' ) .data( 'letter', '' )
.data( 'match-count', columnData.length ) .data( 'match-count', columnData.length )
.html( 'None' ) .html( context.oLanguage.alphabetSearch.infoAll )
.appendTo( alphabet ); .appendTo( alphabet );
for ( var i=0 ; i<26 ; i++ ) { for ( var i=0 ; i<context.oLanguage.alphabetSearch.alphabet.length ; i++ ) {
var letter = String.fromCharCode( 65 + i ); var letter = context.oLanguage.alphabetSearch.alphabet[i];
$('<span/>') $('<span/>')
.data( 'letter', letter ) .data( 'letter', letter )
.data( 'match-count', bins[letter] || 0 ) .data( 'match-count', bins[letter] || 0 )
.addClass( ! bins[letter] ? 'empty' : '' ) .addClass(
.html( letter ) (! bins[letter] ? 'empty' : '')
+ ((context.alphabetSearch.letter === letter) ? ' active' : '')
)
.html(
(letter === '#') ? '0-9' : letter
)
.appendTo( alphabet ); .appendTo( alphabet );
} }
$('<div class="alphabetInfo"></div>') $('<div class="alphabet_info"></div>')
.appendTo( alphabet ); .appendTo( alphabet );
// Perform second rendering
// needed to filter search results by letter
// NOTE: Future optimization is needed to avoid rendering twice
// when no search is performed
// If letter is selected
if(context.alphabetSearch.letter){
// Apply filtering by letter
context.alphabetSearch.letterSearch = context.alphabetSearch.letter;
// Redraw table
table.draw();
// Remove filtering by letter
context.alphabetSearch.letterSearch = '';
}
// Handle search event here only once
// when alphabet panel has been drawn
// because we are performing two-step rendering
// that could trigger search hanlder when not needed
table.one('search', function (e, context) {
var api = new $.fn.dataTable.Api( context );
// Redraw alphabet panel
api.alphabetSearch.recalc();
});
} }
@ -112,7 +213,76 @@ $.fn.dataTable.AlphabetSearch = function ( context ) {
var table = new $.fn.dataTable.Api( context ); var table = new $.fn.dataTable.Api( context );
var alphabet = $('<div class="alphabet"/>'); var alphabet = $('<div class="alphabet"/>');
draw( table, alphabet ); // Language
context.oLanguage.alphabetSearch =
$.extend(
{
'alphabet': '#ABCDEFGHIJKLMNOPQRSTUVXYZ',
'infoDisplay': 'Display',
'infoAll': 'All'
},
((context.oLanguage.alphabetSearch)
? context.oLanguage.alphabetSearch
: {}
)
);
// Convert alphabet to uppercase
context.oLanguage.alphabetSearch.alphabet.toUpperCase();
context.alphabetSearch =
$.extend(
{
column: 0
},
$.isPlainObject(context.oInit.alphabetSearch) ? context.oInit.alphabetSearch : {},
{
letter: '',
letterSearch: '',
pass: 0
}
);
// Set required "orderDataType" ("sSortDataType") for a column
if(context.alphabetSearch.column >= 0 && context.alphabetSearch.column < context.aoColumns.length){
context.aoColumns[context.alphabetSearch.column].sSortDataType = 'alphabetSearch';
}
// Add column containing names to a list of columns
// where ordering will be always applied to the table
if( context.hasOwnProperty('aaSortingFixed')
&& typeof context.aaSortingFixed === 'object' )
{
if( $.isArray(context.aaSortingFixed) ){
if( context.aaSortingFixed.length && !$.isArray( context.aaSortingFixed[0] ) ) {
// 1D array
context.aaSortingFixed = [[context.alphabetSearch.column, 'asc'], context.aaSortingFixed];
} else {
// 2D array
context.aaSortingFixed.unshift([context.alphabetSearch.column, 'asc']);
}
} else {
if( !context.aaSortingFixed.hasOwnProperty('pre') ){
context.aaSortingFixed.pre = [];
}
if( context.aaSortingFixed.pre.length && !$.isArray( context.aaSortingFixed.pre[0] ) ) {
// 1D array
context.aaSortingFixed.pre = [[context.alphabetSearch.column, 'asc'], context.aaSortingFixed.pre];
} else {
// 2D array
context.aaSortingFixed.pre.unshift([context.alphabetSearch.column, 'asc']);
}
}
} else {
context.aaSortingFixed = [context.alphabetSearch.column, 'asc'];
}
draw( table, alphabet, context );
// Trigger a search // Trigger a search
alphabet.on( 'click', 'span', function () { alphabet.on( 'click', 'span', function () {
@ -128,7 +298,7 @@ $.fn.dataTable.AlphabetSearch = function ( context ) {
alphabet alphabet
.on( 'mouseenter', 'span', function () { .on( 'mouseenter', 'span', function () {
alphabet alphabet
.find('div.alphabetInfo') .find('div.alphabet_info')
.css( { .css( {
opacity: 1, opacity: 1,
left: $(this).position().left, left: $(this).position().left,
@ -138,10 +308,41 @@ $.fn.dataTable.AlphabetSearch = function ( context ) {
} ) } )
.on( 'mouseleave', 'span', function () { .on( 'mouseleave', 'span', function () {
alphabet alphabet
.find('div.alphabetInfo') .find('div.alphabet_info')
.css('opacity', 0); .css('opacity', 0);
} ); } );
table.on('draw', function (e, context) {
var api = new $.fn.dataTable.Api( context );
// Total number of column nodes
var col_total = api.columns().nodes().length;
var rows = api.rows({ page: 'current' }).nodes();
var group_last = null;
api.column(context.alphabetSearch.column, { page: 'current' }).data().each(function (name, index){
var group = name.charAt(0).toUpperCase();
if (group_last !== group) {
$(rows).eq(index).before(
'<tr class="alphabet_group"><td colspan="' + col_total + '">' + group + '</td></tr>'
);
group_last = group;
}
});
// If there are no rows found and letter is selected
if(!rows.length && context.alphabetSearch){
var letter = (context.alphabetSearch.letter === '#') ? '0-9' : context.alphabetSearch.letter;
$(api.table().body()).prepend(
'<tr class="alphabet_group"><td colspan="' + col_total + '">' + letter + '</td></tr>'
);
}
});
// API method to get the alphabet container node // API method to get the alphabet container node
this.node = function () { this.node = function () {
return alphabet; return alphabet;
@ -162,4 +363,3 @@ $.fn.dataTable.ext.feature.push( {
}()); }());

File diff suppressed because one or more lines are too long
Loading…
Cancel
Save