字母輸入搜尋 - 第二部分
延續探索 DataTables 自訂搜尋選項、API 和功能外掛程式的三部分系列文章,這第二篇文章擴展了本系列第一部分中介紹的字母搜尋控制項,為最終使用者提供搜尋詞的快速視覺回饋。此視覺資訊將指示每個搜尋選項的表格中有多少筆記錄。這是透過使用 DataTables API 並使用 jQuery 顯示資訊元素來完成的。
字母搜尋
在探索這篇文章中的程式碼之前,以下範例顯示我們將在此建構的內容。
姓名 | 職位 | 辦公室 | 年齡 | 開始日期 | 薪資 |
---|---|---|---|---|---|
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 |
姓名 | 職位 | 辦公室 | 年齡 | 開始日期 | 薪資 |
滑鼠控制
首先考慮我們希望如何向最終使用者顯示額外的搜尋資訊。如您從上面的範例中看到的,當使用者將滑鼠移到字母上時,每個字母下方都會顯示一個帶有數字的簡單方塊。該數字指示該搜尋詞有多少筆記錄可用(如何計算該數字將在下面討論)。
這主要是簡單的 Javascript 和 jQuery,而不是 DataTables 特有的,因此我不會在這裡深入探討太多細節,但基本上我們所做的是將數字方塊的元素(下面的 info
)附加到字母容器(第一部分中開發的程式碼中的 alphabet
)。當滑鼠進入搜尋詞元素(span
標籤)時,資訊元素會顯示,其內容和位置會更新為適合搜尋詞。當滑鼠移開時,資訊元素也會被移除。
var info = $('<div class="alphabetInfo"></div>')
.appendTo( alphabet );
alphabet
.on( 'mouseenter', 'span', function () {
info
.css( {
opacity: 1,
left: $(this).position().left,
width: $(this).width()
} )
.html( $(this).data('match-count') )
} )
.on( 'mouseleave', 'span', function () {
info.css('opacity', 0);
} );
資料屬性
在上面的程式碼中,每個字母的搜尋計數是從資料屬性 match-count
讀取的 - 例如,您可以考慮 HTML 看起來像
<div class="alphabet">
<span data-match-count="57">None</span>
<span data-match-count="3">A</span>
<span data-match-count="4">B</span>
<span data-match-count="5">C</span>
...
</div>
我們現在的任務只是在建立字母元素時將這些資料屬性新增到它們。
若要取得第一欄中可用的資料,我們可以使用 DataTables 的 column().data()
方法。將索引 0
傳遞給 column()
方法會擷取第一欄的資料,然後可以逐一查看以計算每個字元在資料集中作為第一個字母出現的次數。
為此,我們可以編寫一個簡單的函式來分箱資料,產生一個物件,該物件具有每個字母的計數(物件中缺少字母表示計數為零)
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;
}
產生的物件可能看起來像
{
"A": 3,
"B": 4,
"C": 5,
...
}
最後,我們使用來自 column().data()
的資料呼叫該函式,然後在建立字母時使用分箱資料(請參閱第一部分)
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 );
}
第二部分完成程式碼
此頁面頂端範例所使用的完整程式碼,包括在 本系列第一部分中開發的程式碼如下所示
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;
} );
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;
}
$(document).ready(function() {
var table = $('#example').DataTable();
var alphabet = $('<div class="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 );
}
alphabet.insertBefore( table.table().container() );
alphabet.on( 'click', 'span', function () {
alphabet.find( '.active' ).removeClass( 'active' );
$(this).addClass( 'active' );
_alphabetSearch = $(this).data('letter');
table.draw();
} );
var info = $('<div class="alphabetInfo"></div>')
.appendTo( alphabet );
alphabet
.on( 'mouseenter', 'span', function () {
info
.css( {
opacity: 1,
left: $(this).position().left,
width: $(this).width()
} )
.html( $(this).data('match-count') )
} )
.on( 'mouseleave', 'span', function () {
info.css('opacity', 0);
} );
} );
CSS
div.alphabet {
position: relative;
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;
}
div.alphabet span.empty {
color: red;
}
div.alphabetInfo {
display: block;
position: absolute;
background-color: #111;
border-radius: 3px;
color: white;
top: 2em;
height: 1.8em;
padding-top: 0.4em;
text-align: center;
z-index: 1;
}
下一步
在本系列的最後一部分中,下週我們將使用此處開發的字母控制項,建立一個可重複使用的 DataTables 功能外掛程式,讓任何 DataTable 都可以透過單行程式碼使用此輸入控制項。