|
|
@ -1,5 +1,4 @@
|
|
|
|
// TODO
|
|
|
|
// TODO
|
|
|
|
// - Tidy up class names
|
|
|
|
|
|
|
|
// - Option to have vertical layout class
|
|
|
|
// - Option to have vertical layout class
|
|
|
|
// - Number of horizontal panels class options
|
|
|
|
// - Number of horizontal panels class options
|
|
|
|
// - Threshold option - require that there is duplicate information in a column before it is used
|
|
|
|
// - Threshold option - require that there is duplicate information in a column before it is used
|
|
|
@ -43,16 +42,19 @@ var DataTable = $.fn.dataTable;
|
|
|
|
function SearchPanes ( settings, opts ) {
|
|
|
|
function SearchPanes ( settings, opts ) {
|
|
|
|
var that = this;
|
|
|
|
var that = this;
|
|
|
|
var table = new DataTable.Api( settings );
|
|
|
|
var table = new DataTable.Api( settings );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this.classes = $.extend( true, {}, SearchPanes.classes );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this.dom = {
|
|
|
|
|
|
|
|
container: $('<div/>')
|
|
|
|
|
|
|
|
.addClass( this.classes.container )
|
|
|
|
|
|
|
|
.appendTo( opts.container )
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
this.s = {
|
|
|
|
this.s = {
|
|
|
|
dt: table
|
|
|
|
dt: table
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
this.dom = {
|
|
|
|
|
|
|
|
container: $('<div class="dt-searchPane"/>')
|
|
|
|
|
|
|
|
.appendTo( opts.container )
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
table.columns(opts.columns).eq(0).each( function ( idx ) {
|
|
|
|
table.columns(opts.columns).eq(0).each( function ( idx ) {
|
|
|
|
that._pane( idx );
|
|
|
|
that._pane( idx );
|
|
|
|
} );
|
|
|
|
} );
|
|
|
@ -61,37 +63,26 @@ function SearchPanes ( settings, opts ) {
|
|
|
|
.on( 'click', 'li', function () {
|
|
|
|
.on( 'click', 'li', function () {
|
|
|
|
that._toggle( this );
|
|
|
|
that._toggle( this );
|
|
|
|
} )
|
|
|
|
} )
|
|
|
|
.on( 'click', 'button.close', function () {
|
|
|
|
.on( 'click', 'button.'+this.classes.clear, function () {
|
|
|
|
that._clear( $(this).closest('div.pane') );
|
|
|
|
that._clear( $(this).closest('div.'+that.classes.pane.container) );
|
|
|
|
} );
|
|
|
|
} );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$.extend( SearchPanes.prototype, {
|
|
|
|
$.extend( SearchPanes.prototype, {
|
|
|
|
_binData: function ( data, tags ) {
|
|
|
|
_binData: function ( data ) {
|
|
|
|
var out = {};
|
|
|
|
var out = {};
|
|
|
|
var add = function ( d ) {
|
|
|
|
|
|
|
|
if ( ! out[ d ] ) {
|
|
|
|
|
|
|
|
out[ d ] = 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else {
|
|
|
|
|
|
|
|
out[ d ]++;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
data.each( function (d) {
|
|
|
|
data.each( function (d) {
|
|
|
|
if ( ! d ) {
|
|
|
|
if ( ! d ) {
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if ( tags ) {
|
|
|
|
if ( ! out[ d ] ) {
|
|
|
|
var a = d.split(',');
|
|
|
|
out[ d ] = 1;
|
|
|
|
for ( var i=0, ien=a.length ; i<ien ; i++ ) {
|
|
|
|
|
|
|
|
add( a[i] );
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
else {
|
|
|
|
add( d );
|
|
|
|
out[ d ]++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} );
|
|
|
|
} );
|
|
|
|
|
|
|
|
|
|
|
@ -99,8 +90,11 @@ $.extend( SearchPanes.prototype, {
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
_clear: function ( pane ) {
|
|
|
|
_clear: function ( pane ) {
|
|
|
|
pane.find( 'li.selected' ).removeClass( 'selected' );
|
|
|
|
var classes = this.classes;
|
|
|
|
pane.removeClass('filtering');
|
|
|
|
var itemSelected = classes.item.selected;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pane.find( 'li.'+itemSelected ).removeClass( itemSelected );
|
|
|
|
|
|
|
|
pane.removeClass( classes.pane.active );
|
|
|
|
|
|
|
|
|
|
|
|
this.s.dt
|
|
|
|
this.s.dt
|
|
|
|
.column( pane.data('column') )
|
|
|
|
.column( pane.data('column') )
|
|
|
@ -109,11 +103,13 @@ $.extend( SearchPanes.prototype, {
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
_pane: function ( idx ) {
|
|
|
|
_pane: function ( idx ) {
|
|
|
|
|
|
|
|
var classes = this.classes;
|
|
|
|
|
|
|
|
var itemClasses = classes.item;
|
|
|
|
|
|
|
|
var paneClasses = classes.pane;
|
|
|
|
var table = this.s.dt;
|
|
|
|
var table = this.s.dt;
|
|
|
|
var column = table.column( idx );
|
|
|
|
var column = table.column( idx );
|
|
|
|
var list = $('<ul/>');
|
|
|
|
var list = $('<ul/>');
|
|
|
|
var tags = $( column.header() ).hasClass('tags');
|
|
|
|
var bins = this._binData( column.data().flatten() );
|
|
|
|
var bins = this._binData( column.data().flatten(), tags );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// On initialisation, do we need to set a filtering value from a
|
|
|
|
// On initialisation, do we need to set a filtering value from a
|
|
|
|
// saved state or init option?
|
|
|
|
// saved state or init option?
|
|
|
@ -122,19 +118,17 @@ $.extend( SearchPanes.prototype, {
|
|
|
|
search[0].substr( 1, search[0].length-2 ).split('|') :
|
|
|
|
search[0].substr( 1, search[0].length-2 ).split('|') :
|
|
|
|
[];
|
|
|
|
[];
|
|
|
|
|
|
|
|
|
|
|
|
var data = tags ?
|
|
|
|
var data = column.data().unique().sort().toArray();
|
|
|
|
table.ajax.json().tags :
|
|
|
|
|
|
|
|
column.data().unique().sort().toArray();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for ( var i=0, ien=data.length ; i<ien ; i++ ) {
|
|
|
|
for ( var i=0, ien=data.length ; i<ien ; i++ ) {
|
|
|
|
if ( data[i] ) {
|
|
|
|
if ( data[i] ) {
|
|
|
|
var li = $('<li/>')
|
|
|
|
var li = $('<li/>')
|
|
|
|
.html( '<span class="label">'+data[i]+'</span>' )
|
|
|
|
.html( '<span class="'+itemClasses.label+'">'+data[i]+'</span>' )
|
|
|
|
.data( 'filter', data[i] )
|
|
|
|
.data( 'filter', data[i] )
|
|
|
|
.append( $('<span class="count" />').html( bins[ data[i] ] ) );
|
|
|
|
.append( $('<span/>').addClass( itemClasses.count ).html( bins[ data[i] ] ) );
|
|
|
|
|
|
|
|
|
|
|
|
if ( $.inArray( data[i], search ) !== -1 ) {
|
|
|
|
if ( $.inArray( data[i], search ) !== -1 ) {
|
|
|
|
li.addClass('selected');
|
|
|
|
li.addClass(itemClasses.selected);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
list.append( li );
|
|
|
|
list.append( li );
|
|
|
@ -142,33 +136,36 @@ $.extend( SearchPanes.prototype, {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
$(this.dom.container).append(
|
|
|
|
$(this.dom.container).append(
|
|
|
|
$('<div class="pane"/>')
|
|
|
|
$('<div/>')
|
|
|
|
.data( 'column', idx )
|
|
|
|
.data( 'column', idx )
|
|
|
|
.addClass( search.length ? 'filtering' : '' )
|
|
|
|
.addClass( paneClasses.container )
|
|
|
|
.append( '<button type="button" class="close">×</button>' )
|
|
|
|
.addClass( search.length ? paneClasses.active : '' )
|
|
|
|
.append( $('<div class="title"/>').html( $(column.header()).text() ) )
|
|
|
|
.append( $('<button type="button">×</button>').addClass(this.classes.clear) )
|
|
|
|
.append( $('<div class="scroller"/>').append( list ) )
|
|
|
|
.append( $('<div/>').addClass(paneClasses.title).html( $(column.header()).text() ) )
|
|
|
|
|
|
|
|
.append( $('<div/>').addClass(paneClasses.scroller).append( list ) )
|
|
|
|
);
|
|
|
|
);
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
_toggle: function ( li ) {
|
|
|
|
_toggle: function ( li ) {
|
|
|
|
|
|
|
|
var classes = this.classes;
|
|
|
|
|
|
|
|
var itemSelected = classes.item.selected;
|
|
|
|
var table = this.s.dt;
|
|
|
|
var table = this.s.dt;
|
|
|
|
var li = $(li);
|
|
|
|
var li = $(li);
|
|
|
|
var pane = li.closest('div.pane');
|
|
|
|
var pane = li.closest('div.'+classes.pane.container);
|
|
|
|
|
|
|
|
|
|
|
|
li.toggleClass( 'selected', ! li.hasClass( 'selected' ) );
|
|
|
|
li.toggleClass( itemSelected, ! li.hasClass( itemSelected ) );
|
|
|
|
|
|
|
|
|
|
|
|
var filters = pane.find( 'li.selected' );
|
|
|
|
var filters = pane.find( 'li.'+itemSelected );
|
|
|
|
|
|
|
|
|
|
|
|
if ( filters.length === 0 ) {
|
|
|
|
if ( filters.length === 0 ) {
|
|
|
|
pane.removeClass('filtering');
|
|
|
|
pane.removeClass( classes.pane.active );
|
|
|
|
table
|
|
|
|
table
|
|
|
|
.column( pane.data('column') )
|
|
|
|
.column( pane.data('column') )
|
|
|
|
.search('')
|
|
|
|
.search('')
|
|
|
|
.draw();
|
|
|
|
.draw();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
else {
|
|
|
|
pane.addClass('filtering');
|
|
|
|
pane.addClass( classes.pane.active );
|
|
|
|
table
|
|
|
|
table
|
|
|
|
.column( pane.data('column') )
|
|
|
|
.column( pane.data('column') )
|
|
|
|
.search( $.map( filters, function (filter) {
|
|
|
|
.search( $.map( filters, function (filter) {
|
|
|
@ -179,6 +176,22 @@ $.extend( SearchPanes.prototype, {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} );
|
|
|
|
} );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
SearchPanes.classes = {
|
|
|
|
|
|
|
|
container: 'dt-searchPanes',
|
|
|
|
|
|
|
|
clear: 'clear',
|
|
|
|
|
|
|
|
pane: {
|
|
|
|
|
|
|
|
active: 'filtering',
|
|
|
|
|
|
|
|
container: 'pane',
|
|
|
|
|
|
|
|
title: 'title',
|
|
|
|
|
|
|
|
scroller: 'scroller'
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
item: {
|
|
|
|
|
|
|
|
selected: 'selected',
|
|
|
|
|
|
|
|
label: 'label',
|
|
|
|
|
|
|
|
count: 'count'
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$(document).on( 'init.dt', function (e, settings, json) {
|
|
|
|
$(document).on( 'init.dt', function (e, settings, json) {
|
|
|
|