字母输入搜索 - 第三部分
在本系列文章的最后一部分,我们将探讨 DataTables 的一些搜索选项和 API 以扩展 DataTables,我将详细介绍如何将 字母搜索 (在本系列的前两部分中创建)转换为 DataTables 的 功能插件,并使用 API 扩展方法 来控制我们创建的新功能。
最终结果是 DataTables 的一个可自定义扩展,可以使用简单的初始化轻松地重用于任何网页上的一个或多个表格
var table = $('#example').DataTable( {
layout: {
top1: 'alphabetSearch'
}
} );
或者如果您使用的是旧版 DataTables 1.x
var table = $('#example').DataTable( {
dom: 'Alfrtip'
} );
请注意 dom
的使用,以指定使用的表格控件元素 - A
是我们的新插件。这就是使用它的全部内容!
在我们深入代码之前,最终结果现在可以在 DataTables CDN 上获得(Javascript / CSS),并且下面显示了结果表格的演示(其功能与 第二部分 中创建的功能相同)。
姓名 | 职位 | 办公室 | 年龄 | 开始日期 | 薪水 |
---|---|---|---|---|---|
Tiger Nixon | 系统架构师 | 爱丁堡 | 61 | 2011-04-25 | $320,800 |
Garrett Winters | 会计 | 东京 | 63 | 2011-07-25 | $170,750 |
Ashton Cox | 初级技术作家 | 旧金山 | 66 | 2009-01-12 | $86,000 |
Cedric Kelly | 高级 Javascript 开发人员 | 爱丁堡 | 22 | 2012-03-29 | $433,060 |
Airi Satou | 会计 | 东京 | 33 | 2008-11-28 | $162,700 |
Brielle Williamson | 集成专家 | 纽约 | 61 | 2012-12-02 | $372,000 |
Herrod Chandler | 销售助理 | 旧金山 | 59 | 2012-08-06 | $137,500 |
Rhona Davidson | 集成专家 | 东京 | 55 | 2010-10-14 | $327,900 |
Colleen Hurst | Javascript 开发人员 | 旧金山 | 39 | 2009-09-15 | $205,500 |
Sonya Frost | 软件工程师 | 爱丁堡 | 23 | 2008-12-13 | $103,600 |
Jena Gaines | 办公室经理 | 伦敦 | 30 | 2008-12-19 | $90,560 |
Quinn Flynn | 支持主管 | 爱丁堡 | 22 | 2013-03-03 | $342,000 |
Charde Marshall | 区域总监 | 旧金山 | 36 | 2008-10-16 | $470,600 |
Haley Kennedy | 高级营销设计师 | 伦敦 | 43 | 2012-12-18 | $313,500 |
Tatyana Fitzpatrick | 区域总监 | 伦敦 | 19 | 2010-03-17 | $385,750 |
Michael Silva | 营销设计师 | 伦敦 | 66 | 2012-11-27 | $198,500 |
Paul Byrd | 首席财务官 (CFO) | 纽约 | 64 | 2010-06-09 | $725,000 |
Gloria Little | 系统管理员 | 纽约 | 59 | 2009-04-10 | $237,500 |
Bradley Greer | 软件工程师 | 伦敦 | 41 | 2012-10-13 | $132,000 |
Dai Rios | 人事主管 | 爱丁堡 | 35 | 2012-09-26 | $217,500 |
Jenette Caldwell | 开发主管 | 纽约 | 30 | 2011-09-03 | $345,000 |
Yuri Berry | 首席营销官 (CMO) | 纽约 | 40 | 2009-06-25 | $675,000 |
Caesar Vance | 售前支持 | 纽约 | 21 | 2011-12-12 | $106,450 |
Doris Wilder | 销售助理 | 悉尼 | 23 | 2010-09-20 | $85,600 |
Angelica Ramos | 首席执行官 (CEO) | 伦敦 | 47 | 2009-10-09 | $1,200,000 |
Gavin Joyce | 开发人员 | 爱丁堡 | 42 | 2010-12-22 | $92,575 |
Jennifer Chang | 区域总监 | 新加坡 | 28 | 2010-11-14 | $357,650 |
Brenden Wagner | 软件工程师 | 旧金山 | 28 | 2011-06-07 | $206,850 |
Fiona Green | 首席运营官 (COO) | 旧金山 | 48 | 2010-03-11 | $850,000 |
Shou Itou | 区域营销 | 东京 | 20 | 2011-08-14 | $163,000 |
Michelle House | 集成专家 | 悉尼 | 37 | 2011-06-02 | $95,400 |
Suki Burks | 开发人员 | 伦敦 | 53 | 2009-10-22 | $114,500 |
Prescott Bartlett | 技术作家 | 伦敦 | 27 | 2011-05-07 | $145,000 |
Gavin Cortez | 团队领导 | 旧金山 | 22 | 2008-10-26 | $235,500 |
Martena Mccray | 售后支持 | 爱丁堡 | 46 | 2011-03-09 | $324,050 |
Unity Butler | 营销设计师 | 旧金山 | 47 | 2009-12-09 | $85,675 |
Howard Hatfield | 办公室经理 | 旧金山 | 51 | 2008-12-16 | $164,500 |
Hope Fuentes | 秘书 | 旧金山 | 41 | 2010-02-12 | $109,850 |
Vivian Harrell | 财务总监 | 旧金山 | 62 | 2009-02-14 | $452,500 |
Timothy Mooney | 办公室经理 | 伦敦 | 37 | 2008-12-11 | $136,200 |
Jackson Bradshaw | 总监 | 纽约 | 65 | 2008-09-26 | $645,750 |
Olivia Liang | 支持工程师 | 新加坡 | 64 | 2011-02-03 | $234,500 |
Bruno Nash | 软件工程师 | 伦敦 | 38 | 2011-05-03 | $163,500 |
Sakura Yamamoto | 支持工程师 | 东京 | 37 | 2009-08-19 | $139,575 |
Thor Walton | 开发人员 | 纽约 | 61 | 2013-08-11 | $98,540 |
Finn Camacho | 支持工程师 | 旧金山 | 47 | 2009-07-07 | $87,500 |
Serge Baldwin | 数据协调员 | 新加坡 | 64 | 2012-04-09 | $138,575 |
Zenaida Frank | 软件工程师 | 纽约 | 63 | 2010-01-04 | $125,250 |
Zorita Serrano | 软件工程师 | 旧金山 | 56 | 2012-06-01 | $115,000 |
Jennifer Acosta | 初级 Javascript 开发人员 | 爱丁堡 | 43 | 2013-02-01 | $75,650 |
Cara Stevens | 销售助理 | 纽约 | 46 | 2011-12-06 | $145,600 |
Hermione Butler | 区域总监 | 伦敦 | 47 | 2011-03-21 | $356,250 |
Lael Greer | 系统管理员 | 伦敦 | 21 | 2009-02-27 | $103,500 |
Jonas Alexander | 开发人员 | 旧金山 | 30 | 2010-07-14 | $86,500 |
Shad Decker | 区域总监 | 爱丁堡 | 51 | 2008-11-13 | $183,000 |
Michael Bruce | Javascript 开发人员 | 新加坡 | 29 | 2011-06-27 | $183,000 |
Donna Snider | 客户支持 | 纽约 | 27 | 2011-01-25 | $112,000 |
姓名 | 职位 | 办公室 | 年龄 | 开始日期 | 薪水 |
值得注意的是,我假设您熟悉在本系列的 第一部分 和 第二部分 中开发的代码。由于此功能插件所需的大部分代码已在这些文章中开发,因此我将缩短这些代码块。这篇文章只是关于将代码重新排列成 DataTables 的可重用插件。
功能插件
手册的 功能插件部分 详细描述了如何为 DataTables 创建功能插件。基本原理是,我们需要注册一个新的功能插件,该插件可以通过 dom
通过 $.fn.dataTable.ext.feature
数组使用。我们提供要注册的字母和一个回调函数,该函数在将插件用于 DataTable 时执行 - 此回调必须返回要插入文档中的控件节点,在本例中为字母搜索栏。
$.fn.dataTable.ext.feature.push( {
fnInit: function ( settings ) {
var search = new $.fn.dataTable.AlphabetSearch( settings );
return search.node();
},
cFeature: 'A'
} );
在上面的代码中,我们注册字符 A
并创建 $.fn.dataTable.AlphabetSearch
的新实例,从其自己的 API node()
方法返回节点。
$.fn.dataTable.AlphabetSearch
在我们的代码中是新的,但它只是先前开发的创建字母搜索输入节点的代码的封装
$.fn.dataTable.AlphabetSearch = function ( context ) {
var table = new $.fn.dataTable.Api( context );
var alphabet = $('<div class="alphabet"/>');
// Bin the data and create the alphabet search input element
...
// API method to get the alphabet container node
this.node = function () {
return alphabet;
};
};
请注意添加了 node()
API 方法,该方法可用于获取容器节点,如上文 DataTables 功能的注册中所做的那样。
备选初始化
值得指出的是,字母搜索也可以使用 new $.fn.dataTable.AlphabetSearch()
直接初始化,而不是使用 dom
选项。如果您愿意,这可以提高灵活性并更好地控制字母栏的插入位置
var table = $('#myTable').DataTable();
var search = new $.fn.dataTable.AlphabetSearch();
$( search.node() ).appendTo( ... ); // insert into document
搜索插件更新
以前,搜索插件 使用变量 _alphabetSearch
来确定要搜索的字母,但是该变量没有隔离到单个表格 - 它将应用于页面上的所有表格。这对于可重用组件不适用,因此我们需要使用其他方法来存储要搜索的字母。
为此,我们可以使用 DataTables 设置对象,该对象在页面上的每个表格中都是全局唯一的(在许多 API 文档中,设置对象被称为“上下文”)。通过简单地将我们的参数附加到设置对象,我们始终可以为该表格访问它。请考虑以下对我们在第一部分中开发的搜索插件的更新
$.fn.dataTable.ext.search.push( function ( context, searchData ) {
// Ensure that there is a search applied to this table before running it
if ( ! context.alphabetSearch ) {
return true;
}
if ( searchData[0].charAt(0) === context.alphabetSearch ) {
return true;
}
return false;
} );
更改只是使用 context.alphabetSearch
而不是 _alphabetSearch
。现在要触发搜索,我们只需要设置该参数,这就是 API 插件发挥作用的地方。
API 插件
一个 API 插件 可以扩展 DataTables 提供的 默认 API 方法集,在本例中,我们希望添加设置每个表格的 alphabetSearch
参数的功能。我们可以使用以下方法非常轻松地做到这一点
$.fn.dataTable.Api.register( 'alphabetSearch()', function ( searchTerm ) {
this.iterator( 'table', function ( context ) {
context.alphabetSearch = searchTerm;
} );
return this;
} );
上面 iterator()
方法用于遍历 API 实例上下文中每个表格并设置搜索词。尽管我们的功能插件没有利用 DataTables API 的多表格方面,但由于使用了 iterator()
,因此完全可以使用 $('table.dataTable').DataTable().alphabetSearch( 'A' );
在页面上的所有表格中搜索 A
。
为了完整起见,我们还创建了一个方法,该方法可用于重新绑定数据 - 更新每个字母的计数,如鼠标悬停时所示
$.fn.dataTable.Api.register( 'alphabetSearch.recalc()', function ( searchTerm ) {
this.iterator( 'table', function ( context ) {
draw(
new $.fn.dataTable.Api( context ),
$('div.alphabet', this.table().container()) );
);
} );
return this;
} );
这使用了 draw()
方法,该方法只是一个封装先前开发的绘制代码的函数。它传递当前表格的 API 实例和相关表格的字母搜索 DOM 节点。
最终代码
我们已经完成了对 DataTables 扩展世界的探索,我希望您发现这对于如何创建可重用插件以根据您的需要自定义 DataTables 很有用。
与往常一样,非常欢迎您对这篇文章以及 DataTables 的任何其他方面提供 反馈!
在本系列文章中开发的最终代码如下所示,并且可以在 DataTables CDN 上获得(Javascript / CSS)。
(function(){
// Search function
$.fn.dataTable.Api.register( 'alphabetSearch()', function ( searchTerm ) {
this.iterator( 'table', function ( context ) {
context.alphabetSearch = searchTerm;
} );
return this;
} );
// Recalculate the alphabet display for updated data
$.fn.dataTable.Api.register( 'alphabetSearch.recalc()', function ( searchTerm ) {
this.iterator( 'table', function ( context ) {
draw(
new $.fn.dataTable.Api( context ),
$('div.alphabet', this.table().container())
);
} );
return this;
} );
// 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 ) {
return true;
}
if ( searchData[0].charAt(0) === context.alphabetSearch ) {
return true;
}
return false;
} );
// Private support methods
function bin ( data ) {
var letter, bins = {};
for ( var i=0, ien=data.length ; i<ien ; i++ ) {
letter = data[i].charAt(0).toUpperCase();
if ( bins[letter] ) {
bins[letter]++;
}
else {
bins[letter] = 1;
}
}
return bins;
}
function draw ( table, alphabet )
{
alphabet.empty();
alphabet.append( 'Search: ' );
var columnData = table.column(0).data();
var bins = bin( columnData );
$('<span class="clear active"/>')
.data( 'letter', '' )
.data( 'match-count', columnData.length )
.html( 'None' )
.appendTo( alphabet );
for ( var i=0 ; i<26 ; i++ ) {
var letter = String.fromCharCode( 65 + i );
$('<span/>')
.data( 'letter', letter )
.data( 'match-count', bins[letter] || 0 )
.addClass( ! bins[letter] ? 'empty' : '' )
.html( letter )
.appendTo( alphabet );
}
$('<div class="alphabetInfo"></div>')
.appendTo( alphabet );
}
$.fn.dataTable.AlphabetSearch = function ( context ) {
var table = new $.fn.dataTable.Api( context );
var alphabet = $('<div class="alphabet"/>');
draw( table, alphabet );
// Trigger a search
alphabet.on( 'click', 'span', function () {
alphabet.find( '.active' ).removeClass( 'active' );
$(this).addClass( 'active' );
table
.alphabetSearch( $(this).data('letter') )
.draw();
} );
// Mouse events to show helper information
alphabet
.on( 'mouseenter', 'span', function () {
alphabet
.find('div.alphabetInfo')
.css( {
opacity: 1,
left: $(this).position().left,
width: $(this).width()
} )
.html( $(this).data('match-count') );
} )
.on( 'mouseleave', 'span', function () {
alphabet
.find('div.alphabetInfo')
.css('opacity', 0);
} );
// API method to get the alphabet container node
this.node = function () {
return alphabet;
};
};
$.fn.DataTable.AlphabetSearch = $.fn.dataTable.AlphabetSearch;
// Register a search plug-in
$.fn.dataTable.ext.feature.push( {
fnInit: function ( settings ) {
var search = new $.fn.dataTable.AlphabetSearch( settings );
return search.node();
},
cFeature: 'A'
} );
}());