基于语言环境的排序
让我们刻板印象一下:开发人员的第一语言(在很多情况下,例如我本人,唯一语言)是英语,他们并不总是真正地意识到本地化问题。因为世界各地的用户都在使用 DataTables(68 种 DataTables 核心社区翻译),作为库开发人员,我非常清楚这点。
尽管 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
不仅提供排序选项,还提供筛选选项 - 例如如何处理重音符号在筛选时是另一个有趣而困难的话题。虽然此文章没有探讨此类选项,但这是我将在未来研究的内容。
我还计划为 Intl
API 在 DataTables 的下一个主要版本中提供支持,而不是要求插件。
享受吧!