深度連結至 DataTables
在論壇中經常出現的一個問題是「如何深度連結至 DataTable?」 這通常是在 SEO 的情境下被問到,您想要確保表格中的所有資料都能被索引,但它也適用於您想要顯示一個預先設定特定搜尋詞的表格的應用程式中。
通常這個問題的答案是使用初始化參數,從搜尋字串設定所需的任何選項,但這是一個很常見的需求,所以我們應該將其一般化。為此,我在此提供一個短腳本,可用於從搜尋字串中提取參數,並使用它們來填充 DataTable。
讓我們首先看看它的實際運作方式 - 請按照下面的連結來觀察示範表格上的行為
姓名 | 職位 | 辦公室 | 年齡 | 開始日期 | 薪資 |
---|---|---|---|---|---|
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 |
姓名 | 職位 | 辦公室 | 年齡 | 開始日期 | 薪資 |
這個範例的程式碼很簡單
$('#myTable').DataTable( $.fn.dataTable.ext.deepLink( [
'search.search', 'order', 'displayStart'
] ) );
您還需要在您的頁面上加入深度連結腳本
使用方式
在您自己的頁面上使用此腳本的關鍵元素是 $.fn.dataTable.ext.deepLink
函數。它接受一個參數:您希望搜尋參數指定的選項陣列,並將返回一個包含這些初始化選項的物件,該物件可以直接傳遞給 DataTable,如上面的範例所示。
使用白名單方法來限制哪些選項可以被使用,以確保安全性。例如,您不太可能希望允許使用者修改 ajax
、serverSide
或 scrollY
參數。如果給定的參數不在白名單中,則會被忽略。話雖如此,如果您在希望可以使用任何和所有參數的環境中使用您的應用程式,您可以指定 all
作為該函數的唯一參數,這將允許所有參數。
一個簡單的範例:允許從搜尋字串設定 search.search
參數
$('#myTable').DataTable( $.fn.dataTable.ext.deepLink( [
'search.search'
] );
擴充預設值
由於 deepLink()
函數只會返回一個物件,因此您可以提供預設值,這些預設值可以選擇性地被搜尋字串覆寫,反之亦然,可以使用一個可選擇的參數來覆寫搜尋字串中的任何參數。這可以使用 jQuery.extend()
函數和返回的物件來完成
var searchOptions = $.fn.dataTable.ext.deepLink( [
'order'
];
var defaultOptions = {
order: [[ 2, 'desc' ]]
};
$('#myTable').DataTable(
$.extend( defaultOptions, searchOptions )
);
它是如何運作的?
現在我們知道如何使用它,如果您對它的運作方式感興趣,請繼續閱讀。它其實非常簡單!讓我們首先回到我在論壇中的標準回應,即應該使用搜尋字串來設定參數值。如果我們假設整個搜尋字串將用於搜尋表格 (例如 /table?mySearchTerm
),我們可以這樣做
$('#myTable').DataTable( {
search: {
search: location.search.replace(/^\?/, '')
}
} );
現在的關鍵是將搜尋字串分解為鍵值對。令人有點驚訝的是,瀏覽器中沒有用於此目的的 API,但是使用 String.prototype.split
和 decodeURIComponent()
來執行此操作非常簡單
$.fn.dataTable.ext.deepLink = function(whitelist) {
var search = location.search.replace(/^\?/, '').split('&');
var out = {};
for (var i = 0, ien = search.length; i < ien; i++) {
var pair = search[i].split('=');
var key = decodeURIComponent(pair[0]);
var value = decodeURIComponent(pair[1]);
...
}
return out;
};
### Casting values
The query string can only directly hold string values (it is a string itself after all), unless we use a data schema such as JSON. JSON isn't pretty to look at in a URL, so we want to avoid that here. The type always being a string is an issue in this case as certain DataTables parameters expect other types - for example `-init displayStart` must be a `Number` and not a `String` while `-init paging` is a Boolean. As such we need to [cast](https://en.wikipedia.org/wiki/Type_conversion) the string values into their typed counterparts:
```js
if (value === 'true') {
value = true;
}
else if (value === 'false') {
value = false;
}
else if (!value.match(/[^\d]/)) {
value = value * 1;
}
else if (value.indexOf('{') === 0 || value.indexOf('[') === 0) {
// Try to JSON parse for arrays and obejcts
try {
value = $.parseJSON( value );
}
catch(e){}
}
這樣做的缺點是,不可能將 search.search
設定為 true
,因為它會被上面的程式碼轉換為布林值。我覺得這是一個相對不太可能遇到的情況,但如果您真的遇到了,則需要修改上面的程式碼以滿足您的需求。
寫入巢狀值
您可能已經注意到在上面的範例中,search.search
被大量使用,因為這是我預期在此腳本中最常用的參數之一。但是,它的 Javascript 物件版本實際上是 { search: { search: ... } }
- 即一個巢狀物件。要從字串表示法轉換,我們可以使用 DataTables 內建的函數,基於點分隔的字串來建立巢狀物件:$.fn.dataTable.ext.internal._fnSetObjectDataFn
(它用於 columns.data
)。此函數不是一個已記載的 API,但是下一個主要版本將會將其提升為 API (儘管具有更易於存取的名稱),因為它對於外掛程式和附加腳本非常有用!
var setBuilder = $.fn.dataTable.ext.internal._fnSetObjectDataFn;
if (whitelist === 'all' || $.inArray(key, whitelist) !== -1) {
var setter = setBuilder(key);
setter(out, value);
}
原始碼和 Git
此腳本的完整文件化原始碼可以在 GitHub 上找到。如果您對如何增強它有任何想法,歡迎提出 pull request!