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;
cursor: pointer;
text-align: center;
width: 3.5%
width: 3.5%;
}
div.alphabet span:hover {
@ -25,7 +25,7 @@ div.alphabet span.empty {
color: red;
}
div.alphabetInfo {
div.alphabet_info {
display: block;
position: absolute;
background-color: #111;
@ -37,3 +37,7 @@ div.alphabetInfo {
text-align: center;
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
*/
@ -6,7 +6,7 @@
* @summary AlphabetSearch
* @description Show an set of alphabet buttons alongside a table providing
* search input options
* @version 1.0.0
* @version 1.1.1
* @file dataTables.alphabetSearch.js
* @author SpryMedia Ltd (www.sprymedia.co.uk)
* @contact www.sprymedia.co.uk/contact
@ -16,6 +16,7 @@
*
* For more detailed information please see:
* http://datatables.net/blog/2014-09-22
* http://www.gyrocode.com/articles/jquery-datatables-alphabetical-search
*/
(function(){
@ -23,7 +24,7 @@
// Search function
$.fn.dataTable.Api.register( 'alphabetSearch()', function ( searchTerm ) {
this.iterator( 'table', function ( context ) {
context.alphabetSearch = searchTerm;
context.alphabetSearch.letter = searchTerm;
} );
return this;
@ -34,7 +35,8 @@ $.fn.dataTable.Api.register( 'alphabetSearch.recalc()', function ( searchTerm )
this.iterator( 'table', function ( context ) {
draw(
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
$.fn.dataTable.ext.search.push( function ( context, searchData ) {
// Ensure that there is a search applied to this table before running it
if ( ! context.alphabetSearch ) {
if ( ! context.alphabetSearch.letterSearch ) {
return true;
}
if ( searchData[0].charAt(0) === context.alphabetSearch ) {
var letter = searchData[context.alphabetSearch.column]
.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;
} );
// 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
function bin ( data ) {
var letter, bins = {};
@ -67,6 +132,8 @@ function bin ( data ) {
.replace(/<.*?>/g, '')
.charAt(0).toUpperCase();
if(/\d/.test(letter)){ letter = '#'; }
if ( bins[letter] ) {
bins[letter]++;
}
@ -78,33 +145,67 @@ function bin ( data ) {
return bins;
}
function draw ( table, alphabet )
function draw ( table, alphabet, context )
{
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 );
$('<span class="clear active"/>')
$('<span class="alphabet-clear' + ((!context.alphabetSearch.letter) ? ' active' : '') + '"/>')
.data( 'letter', '' )
.data( 'match-count', columnData.length )
.html( 'None' )
.html( context.oLanguage.alphabetSearch.infoAll )
.appendTo( alphabet );
for ( var i=0 ; i<26 ; i++ ) {
var letter = String.fromCharCode( 65 + i );
for ( var i=0 ; i<context.oLanguage.alphabetSearch.alphabet.length ; i++ ) {
var letter = context.oLanguage.alphabetSearch.alphabet[i];
$('<span/>')
.data( 'letter', letter )
.data( 'match-count', bins[letter] || 0 )
.addClass( ! bins[letter] ? 'empty' : '' )
.html( letter )
.addClass(
(! bins[letter] ? 'empty' : '')
+ ((context.alphabetSearch.letter === letter) ? ' active' : '')
)
.html(
(letter === '#') ? '0-9' : letter
)
.appendTo( alphabet );
}
$('<div class="alphabetInfo"></div>')
$('<div class="alphabet_info"></div>')
.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 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
alphabet.on( 'click', 'span', function () {
@ -128,7 +298,7 @@ $.fn.dataTable.AlphabetSearch = function ( context ) {
alphabet
.on( 'mouseenter', 'span', function () {
alphabet
.find('div.alphabetInfo')
.find('div.alphabet_info')
.css( {
opacity: 1,
left: $(this).position().left,
@ -138,10 +308,41 @@ $.fn.dataTable.AlphabetSearch = function ( context ) {
} )
.on( 'mouseleave', 'span', function () {
alphabet
.find('div.alphabetInfo')
.find('div.alphabet_info')
.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
this.node = function () {
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