2014 年 8 月 26 日星期二

字母输入搜索 - 第一部分

搜索是 DataTables 的核心功能 - 实际上,它是 2007 年首批在代码中实现的功能,因为它是 DataTables 设计目标的关键:让用户快速轻松地在复杂数据集内查找信息。自这项最初的工作以来,DataTables 的搜索选项已经取得了长足的发展,并通过 search() 方法和其他方法提供了一系列选项。

然而,经常需要根据您自己的需求自定义 DataTables 的搜索选项。最简单的可能就是提供一个能与您网站的总体 UX 完美契合的自定义输入,或者使用一个复杂的搜索算法。

为了满足这一需求,DataTables 提供了一个自定义搜索 API,可用于执行任何您想要的搜索逻辑。在这三部分系列文章中,我将介绍此 API,展示如何使用它并提供与您的具体需求匹配的自定义搜索函数。作为工作示例,本系列文章将会开发一个字母搜索栏,为您展示 DataTables 插件系统工作的各个方面。

  • 第一部分(这篇博文):介绍自定义搜索并展示一个可点击的字母筛选器
  • 第二部分:添加用户信息,在筛选器中显示每个选项的搜索结果数
  • 第三部分:为 DataTables 创建一个功能插件,将先前开发的代码合并进去,以实现灵活的重用。

字母搜索

我们从最后开始,看看我们在本博文中要创建什么 - 一系列位于 DataTable 上方的字母,点击字母后,将激活一个表格搜索,查找第一列中以点击的字母开头的字符串

姓名职位办公室年龄开始日期工资
Tiger Nixon系统架构师爱丁堡612011-04-25$320,800
Garrett Winters会计东京632011-07-25$170,750
Ashton Cox初级技术撰稿人旧金山662009-01-12$86,000
Cedric Kelly高级 JavaScript 开发人员爱丁堡222012-03-29$433,060
Airi Satou会计东京332008-11-28$162,700
Brielle Williamson集成专家纽约612012-12-02$372,000
Herrod Chandler销售助理旧金山592012-08-06$137,500
Rhona Davidson集成专家东京552010-10-14$327,900
Colleen HurstJavaScript 开发人员旧金山392009-09-15$205,500
Sonya Frost软件工程师爱丁堡232008-12-13$103,600
Jena Gaines办公室经理伦敦302008-12-19$90,560
Quinn Flynn支持主管爱丁堡222013-03-03$342,000
Charde Marshall区域总监旧金山362008-10-16$470,600
Haley Kennedy高级营销设计师伦敦432012-12-18$313,500
Tatyana Fitzpatrick区域总监伦敦192010-03-17$385,750
Michael Silva营销设计师伦敦662012-11-27$198,500
Paul Byrd首席财务官 (CFO)纽约642010-06-09$725,000
Gloria Little系统管理员纽约592009-04-10$237,500
Bradley Greer软件工程师伦敦412012-10-13$132,000
Dai Rios人事主管爱丁堡352012-09-26$217,500
Jenette Caldwell开发主管纽约302011-09-03$345,000
Yuri Berry首席营销官 (CMO)纽约402009-06-25$675,000
Caesar Vance售前支持纽约212011-12-12$106,450
Doris Wilder销售助理悉尼232010-09-20$85,600
Angelica Ramos首席执行官 (CEO)伦敦472009-10-09$1,200,000
Gavin Joyce开发者爱丁堡422010-12-22$92,575
Jennifer Chang区域总监新加坡282010-11-14$357,650
Brenden Wagner软件工程师旧金山282011-06-07$206,850
Fiona Green首席运营官 (COO)旧金山482010-03-11$850,000
Shou Itou地区营销东京202011-08-14$163,000
Michelle House集成专家悉尼372011-06-02$95,400
Suki Burks开发者伦敦532009-10-22$114,500
Prescott Bartlett技术作者伦敦272011-05-07$145,000
Gavin Cortez团队领导旧金山222008-10-26$235,500
Martena Mccray售后支持爱丁堡462011-03-09$324,050
Unity Butler营销设计师旧金山472009-12-09$85,675
Howard Hatfield办公室经理旧金山512008-12-16$164,500
Hope Fuentes秘书旧金山412010-02-12$109,850
Vivian Harrell财务总监旧金山622009-02-14$452,500
Timothy Mooney办公室经理伦敦372008-12-11$136,200
Jackson Bradshaw董事纽约652008-09-26$645,750
Olivia Liang支持工程师新加坡642011-02-03$234,500
Bruno Nash软件工程师伦敦382011-05-03$163,500
Sakura Yamamoto支持工程师东京372009-08-19$139,575
Thor Walton开发者纽约612013-08-11$98,540
Finn Camacho支持工程师旧金山472009-07-07$87,500
Serge Baldwin数据协调员新加坡642012-04-09$138,575
Zenaida Frank软件工程师纽约632010-01-04$125,250
Zorita Serrano软件工程师旧金山562012-06-01$115,000
Jennifer Acosta初级 JavaScript 开发人员爱丁堡432013-02-01$75,650
Cara Stevens销售助理纽约462011-12-06$145,600
Hermione Butler区域总监伦敦472011-03-21$356,250
Lael Greer系统管理员伦敦212009-02-27$103,500
Jonas Alexander开发者旧金山302010-07-14$86,500
Shad Decker区域总监爱丁堡512008-11-13$183,000
Michael BruceJavaScript 开发人员新加坡292011-06-27$183,000
Donna Snider客户支持纽约272011-01-25$112,000
姓名职位办公室年龄开始日期工资

搜索插件

DataTables 的搜索插件附加到 $.fn.dataTable.ext.search 数组。只要向此数组 push() 一个函数后,DataTables 便会在执行搜索操作时,执行此函数作用于表中的每一行。然后此函数应返回 truefalse,告知 DataTables 该行是否应包含在结果集(true)中或不包含(false)。

对于字母搜索,我们只需检查数据第一列的第一个字母(可通过函数中传入的第二个参数与 charAt() 方法结合获得),并与存储了用户已对之激活搜索的字符(称为 _alphabetSearch)的变量进行对比。

这样,我们便得到了此简单的小函数

var _alphabetSearch;

$.fn.dataTable.ext.search.push( function ( settings, searchData ) {
    if ( ! _alphabetSearch ) { // No search term - all results shown
        return true;
    }

    if ( searchData[0].charAt(0) === _alphabetSearch ) {
        return true;
    }

    return false;
} );

如果您有兴趣详细了解此 API,DataTables 手册 中包含有关 搜索插件 API 的详细说明。

界面

我们要在此展示给最终用户的界面实际上非常简单。只是包含 A-Z 的字母列表。这里没有特定的 DataTables 代码,只有简单的 jQuery DOM 处理来创建一个包含一系列 spandiv 元素,每个字母一个,因此我不会详细介绍此代码,不过有几点值得注意

  • 包括一个 选项来清除搜索词,允许显示表中的所有条目。
  • 使用 String.formCharCode 来将 ASCII 代码转换为字母。
  • 使用数据属性 letter 来存储要用于搜索词的字母。
// DataTables initialisation
var table = $('#example').DataTable();

var alphabet = $('<div class="alphabet"/>').append( 'Search: ' );

$('<span class="clear active"/>')
    .data( 'letter', '' )
    .html( 'None' )
    .appendTo( alphabet );

for ( var i=0 ; i<26 ; i++ ) {
    var letter = String.fromCharCode( 65 + i );

    $('<span/>')
        .data( 'letter', letter )
        .html( letter )
        .appendTo( alphabet );
}

alphabet.insertBefore( table.table().container() );

上述情况是对仅使用拉丁字母的情况的一个简单案例,不过它很容易扩展为使用其他任何字母中的字符,或包括数字。

行为

为了激活搜索,我们会使用 标准 jQuery $().on() 点击控制器来侦听点击事件。侦听器将为该元素读取 letter 数据属性,并将其分配给我们上方搜索功能中定义的 _alphabetSearch 变量,然后使用 draw() 重绘表格,并让新的搜索项得到考虑。它还执行一点类操作,以直观显示哪个元素是活动搜索项。

alphabet.on( 'click', 'span', function () {
    alphabet.find( '.active' ).removeClass( 'active' );
    $(this).addClass( 'active' );

    _alphabetSearch = $(this).data('letter');
    table.draw();
} );

样式

为我们的字母列表,我们有一个非常简单的 DOM 结构,它包含一个带有 span 元素的 div。为了清晰显示,我们可以使用 CSS display: table 属性 将字母显示为灵活的宽度,明了地布置成网格。还添加了一些其他样式,只是给最终用户一些视觉反馈。

div.alphabet {
    display: table;
    width: 100%;
    margin-bottom: 1em;
}

div.alphabet span {
    display: table-cell;
    color: #3174c7;
    cursor: pointer;
    text-align: center;
    width: 3.5%
}

div.alphabet span:hover {
    text-decoration: underline;
}

div.alphabet span.active {
    color: black;
}

完整代码

上方所示的 Javascript 已经完整,但是如果你想要一个即复制即粘贴的解决方案,而不是要组装代码,则下方所示的是用于此例子的完整代码块

var _alphabetSearch = '';

$.fn.dataTable.ext.search.push( function ( settings, searchData ) {
    if ( ! _alphabetSearch ) {
        return true;
    }

    if ( searchData[0].charAt(0) === _alphabetSearch ) {
        return true;
    }

    return false;
} );


$(document).ready(function() {
    var table = $('#example').DataTable();

    var alphabet = $('<div class="alphabet"/>').append( 'Search: ' );

    $('<span class="clear active"/>')
        .data( 'letter', '' )
        .html( 'None' )
        .appendTo( alphabet );

    for ( var i=0 ; i<26 ; i++ ) {
        var letter = String.fromCharCode( 65 + i );

        $('<span/>')
            .data( 'letter', letter )
            .html( letter )
            .appendTo( alphabet );
    }

    alphabet.insertBefore( table.table().container() );

    alphabet.on( 'click', 'span', function () {
        alphabet.find( '.active' ).removeClass( 'active' );
        $(this).addClass( 'active' );

        _alphabetSearch = $(this).data('letter');
        table.draw();
    } );
} );