基於地區的排序
讓我們刻板印象一下:第一語言(在許多情況下,例如我自己,是唯一語言)是英語的開發人員,並不總是像我們應該的那樣欣賞本地化問題。隨著世界各地的人們使用 DataTables(DataTables 核心有 68 個社群翻譯版本),作為一個函式庫開發人員,我非常清楚這一點。
雖然 DataTables 提供了本地化其使用的文字的選項,但我們還需要考慮表格中包含的資料。排序是其中一個被證明特別難以正確處理的領域,但幸運的是,隨著瀏覽器中現在可用的新 Javascript API,我們可以每次都絕對正確地進行基於地區的排序。
此外,不要錯誤地認為這篇文章僅適用於使用英語以外的語言進行開發的開發人員 - Intl
API 提供的排序選項對所有人都有用!
標準化
Javascript 中的字串排序通常是透過簡單比較 Unicode 代碼點來完成的,假設具有較高代碼點的字元應該在具有較低代碼點的字元之後排序。當然,這是無稽之談 - 它可能適用於許多情況(特別是 ASCII),但並不適合全球使用。
Javascript 1.2 引入了localCompare
,但它存在效能問題以及瀏覽器和平台之間的顯著差異。
這引導我們到ECMA-402 標準 - 一個用於 Javascript 的國際化 API。這個 API 基本上解決了在 Javascript 中排序本地化字串的所有問題。它甚至更進一步,提供了一些非常有用的功能,例如控制大小寫敏感度、忽略標點符號以及考慮字串中的數值。
使用 Intl API 排序
使用 Intl
API 排序是透過為相關地區建立一個校對器來完成的。這本質上是一個最佳化步驟,以確保我們只對語言和選項執行一次設定。產生的校對器物件有一個 compare
方法,我們可以使用它來排序資料,就像我們使用 Array.prototype.sort
一樣。例如
var collator = new Intl.Collator( 'fr' );
arrayToSort.sort( collator.compare );
就是這樣!MDN 文件詳細說明了可以提供給校對器建構函式的選項,所以我們現在需要做的就是將其包裝成 DataTables 可以使用的形式。
與 DataTables 的介面
DataTables 的字串排序是實作為一個簡單的程式碼點比較,正如上面提到的,這並不總是適合。因此,我們想要做的是用 Intl
API 提供的功能取代預設字串排序。我們可以透過簡單地覆寫 DataTables 中字串排序的預設 asc
和 desc
方法來做到這一點(這透過其標準的排序外掛 API公開)。
var collator = new window.Intl.Collator( ... );
var types = $.fn.dataTable.ext.type;
delete types.order['string-pre'];
types.order['string-asc'] = collator.compare;
types.order['string-desc'] = function ( a, b ) {
return collator.compare( a, b ) * -1;
};
這裡有兩點需要注意
- 我們刪除了 DataTables 使用的
string-pre
格式化函式。DataTables 中的預設排序是不區分大小寫的,這可能是我們想要的,也可能不是我們使用Intl
排序時想要的。 - 降序函式比升序函式更有趣一些 - 我們需要反轉校對器比較方法中的預設值 - 這只需將結果乘以 -1 即可完成。
現在我們將其包裝到一個可以像許多其他 DataTables 外掛一樣呼叫的函式中
$.fn.dataTable.ext.order.intl = function ( locales, options ) {
if ( window.Intl ) {
var collator = new window.Intl.Collator( locales, options );
var types = $.fn.dataTable.ext.type;
delete types.order['string-pre'];
types.order['string-asc'] = collator.compare;
types.order['string-desc'] = function ( a, b ) {
return collator.compare( a, b ) * -1;
};
}
};
對於不支援 Intl
API 的舊瀏覽器,上面的程式碼將不會執行任何操作;使用者只能使用舊的基於預設程式碼點的排序。所有目前的瀏覽器都支援這個 API,所以只有使用舊版瀏覽器的使用者才看不到好處。
使用方法
現在要實際在 DataTables 中使用 Intl
排序,我們需要執行上面定義的函式
$.fn.dataTable.ext.order.intl();
$('#myTable').DataTable();
以上將使用瀏覽器的預設地區設定。如果您想明確定義一個地區設定(這更有可能,因為您控制表格中顯示的資料,而不是使用者的瀏覽器!),您可以使用第一個參數來執行此操作(這與 Intl.Collator
的參數完全相同)
$.fn.dataTable.ext.order.intl( 'fr' ); // French locale
第二個可選參數是選項,使 Intl
API 真正有趣,不僅適用於本地化,而且適用於更好、更受控制的整體排序。值得注意的選項有
sensitivity
- 字串之間的哪些差異應該導致它們被單獨排序(例如重音)。此參數的值可以是base
、accent
、case
或variant
。ignorePuctuation
- 指示是否應忽略標點符號的旗標。numeric
- 允許將數值資料排序為數值,而不是字串。caseFirst
- 允許大寫或小寫在另一個之前排序的選項。它可以是upper
、lower
或false
。
我認為最有趣的可能是 numeric
選項,因為這在 DataTables 論壇中經常出現。如果您有混合的數值和字串資料,這個選項允許資料按自然順序排序,而不是嚴格按字串排序(例如 1, 2, 11
而不是 1, 11, 2
)。
CDN
這個外掛可以透過簡單地複製上面的程式碼來使用,或者您可以直接從 DataTales CDN 中包含它。
未來發展
Intl
不僅提供排序的選項,還提供篩選的選項 - 例如,篩選時如何處理重音是另一個有趣且困難的主題。雖然這篇文章沒有探討這方面的選項,但這是我未來將會研究的事情。
我也計畫在下一個主要版本的 DataTables 中內建對 Intl
API 的支援,而不是需要外掛。
盡情享受吧!