通过jqGrid filterToolbar进行不区分大小写的搜索无法找到特殊的土耳其语字符

我在使用jqGrid filterToolbar时遇到问题。 工具栏进行搜索,但无法找到包含"ı"的字符。 例如,我可以搜索"yapi"字,但搜索工具栏找不到"yapı"

 jQuery("#grid-table").jqGrid('filterToolbar', { stringResult: false, searchOperators: false, defaultSearch: "cn" }); 

我的页面编码是;

  

我的ajaxpost就在这里

$ .ajax({type:“Post”,url:“page / get.aspx,contentType:”application / json; charset = utf-8“,dataType:”json“,data:”{}“,success:function (){//},错误:function(){//}});

我确定问题出在您使用的HTML页面的编码中。 我试图重现问题并打开一个以ANSI编码保存的旧演示。 在我将测试yapı插入数据并保存后我可以重现问题,但validation代码显示字符串yapi由于ANSI编码而保存为yapi 。 然后我使用记事本打开相同的演示(我在Windows计算机上工作)重复相同,我使用SaveAs来选择UTF-8编码。 现在我可以看到网格中显示的yapı字符串而不是yapi ,我可以成功过滤字符串。 因为我在两个实验中都有

因此,您应该validationHTML页面的中不仅存在 ,而且数据也采用UTF-8编码。 对于嵌入数据(如我的实验),文件需要以UTF-8格式保存。

更新:评论中的讨论表明,主要问题是对土耳其文本进行不区分大小写的过滤

这个问题对我来说绝对是新的,但是土耳其语有两个 i :一个有点i和另一个没有ıi都有相应的资本III 。 所有信息都与许多其他语言没有什么不同。 主要问题在于选择4个字符的Unicode表示:土耳其字符iI使用相同的代码,如拉丁字符U+0069U+0049 。 只有字符ıİ将映射到U+0131U+0130 (见这里 )。 这种映射使得无法实现不区分大小写的比较或JavaScript函数.toUpperCase().toLowerCase() 。 如果输入文本包含拉丁字母i则函数.toUpperCase()应将其转换为I ,但对于土耳其语而言它应该是错误的。 以同样的方式.toLowerCase()应该为土耳其文本生成ı ,为英文文本生成i

因此,第一个重要信息: 在没有输入语言知识的情况下,不可能实现一个不区分大小写的通用版本

好。 现在回到问题所在。 如何在土耳其文本中实现不区分大小写的搜索? 在版本4.7.1中更改jqGrid的许可协议后,我继续开发免费版本(在MIT和GPL v2许可下),名称为free jqGrid。 我在免费jqGrid的第一个版本中实现了许多新function:版本4.8。 维基文章中描述的“自定义过滤”function可以帮助实现。

基于该function,我创建了以下演示 。 我在实现过程中在free jqGrid的代码中做了一些小bug修复。 所以我在演示中使用了GitHub的最新资源( http://rawgit.com/free-jqgrid/jqGrid/master/js/jquery.jqgrid.src.js )(阅读有关URL的wiki )。

我在jqGrid中使用了以下选项

 ignoreCase: false, customSortOperations: { teq: { operand: "==", text: "Turkish insensitive \"equal\"", filter: function (options) { var fieldData = String(options.item[options.cmName]).replace(/i/g,'İ').toUpperCase(), searchValue = options.searchValue.replace(/i/g,'İ').toUpperCase(); return fieldData === searchValue; } }, tne: { operand: "!=", text: "Turkish insensitive \"not equal\"", filter: function (options) { var fieldData = String(options.item[options.cmName]).replace(/i/g,'İ').toUpperCase(), searchValue = options.searchValue.replace(/i/g,'İ').toUpperCase(); return fieldData !== searchValue; } }, tbw: { operand: "^", text: "Turkish insensitive \"begins with\"", filter: function (options) { var fieldData = String(options.item[options.cmName]).replace(/i/g,'İ').toUpperCase(), searchValue = options.searchValue.replace(/i/g,'İ').toUpperCase(); return fieldData.substr(0,searchValue.length) === searchValue; } }, tbn: { operand: "!^", text: "Turkish insensitive \"does not begin with\"", filter: function (options) { var fieldData = String(options.item[options.cmName]).replace(/i/g,'İ').toUpperCase(), searchValue = options.searchValue.replace(/i/g,'İ').toUpperCase(); return fieldData.substr(0,searchValue.length) !== searchValue; } }, tew: { operand: "|", text: "Turkish insensitive \"end with\"", filter: function (options) { var fieldData = String(options.item[options.cmName]).replace(/i/g,'İ').toUpperCase(), searchValue = options.searchValue.replace(/i/g,'İ').toUpperCase(), searchLength = searchValue.length; return fieldData.substr(fieldData.length-searchLength,searchLength) === searchValue; } }, ten: { operand: "!@", text: "Turkish insensitive \"does not end with\"", filter: function (options) { var fieldData = String(options.item[options.cmName]).replace(/i/g,'İ').toUpperCase(), searchValue = options.searchValue.replace(/i/g,'İ').toUpperCase(), searchLength = searchValue.length; return fieldData.substr(fieldData.length-searchLength,searchLength) !== searchValue; } }, tcn: { operand: "~", text: "Turkish insensitive \"contains\"", filter: function (options) { var fieldData = String(options.item[options.cmName]).replace(/i/g,'İ').toUpperCase(), searchValue = options.searchValue.replace(/i/g,'İ').toUpperCase(); return fieldData.indexOf(searchValue,0) >= 0; } }, tnc: { operand: "!~", text: "Turkish insensitive \"does not contain\"", filter: function (options) { var fieldData = String(options.item[options.cmName]).replace(/i/g,'İ').toUpperCase(), searchValue = options.searchValue.replace(/i/g,'İ').toUpperCase(); return fieldData.indexOf(searchValue,0) < 0; } } } 

customSortOperations选项为土耳其文本的不区分大小写的比较定义了新的自定义操作。 要使用该选项,只需在搜索选项中为包含土耳其文本的列指定操作:

 searchoptions: { sopt: ["tcn", "tnc", "teq", "tne", "tbw", "tbn", "tew", "ten"] } 

结果,过滤使用“tcn”( Turkish insensitive "contains" )作为默认过滤操作。 如果使用searchOperators: true选项filterToolbar则可以选择另一个搜索操作。 我希望以上所有自定义比较操作都是正确的,并且可以在土耳其网格中使用。

更新2:我找到了另一个兴趣实现选项:方法localeCompare ,它支持参数。 我在谷歌浏览器中测试过

 "i".localeCompare("İ", "tr", { sensitivity: "base" }) === 0 "i".localeCompare("I", "tr", { sensitivity: "base" }) === 1 "ı".localeCompare("I", "tr", { sensitivity: "base" }) === 0 "ı".localeCompare("İ", "tr", { sensitivity: "base" }) === -1 

要么

 "i".localeCompare("İ", "tr", { sensitivity: "accent" }) === 0 "i".localeCompare("I", "tr", { sensitivity: "accent" }) === 1 "ı".localeCompare("I", "tr", { sensitivity: "accent" }) === 0 "ı".localeCompare("İ", "tr", { sensitivity: "accent" }) === -1 

但IE11中的相同测试与浏览器兼容性信息相反。 以上所有localeCompare调用在IE11中返回0 。 可以是可以使用另一个sensitivity值来获得预期结果。 对于localeCompare上述调用,IE9反而返回1或-1。 我想它只考虑第一个参数并忽略"tr", { sensitivity: "base" }部分。 Chrome中的结果看起来如此

在此处输入图像描述

一个在Firefox中具有相同的结果

在此处输入图像描述

但不是在IE11中

在此处输入图像描述

还有一个选择是使用ECMAScript国际化API类Intl.Collat​​or (参见ecma-402和这里 ),如

 new Intl.Collator("tr", { sensitivity: "base" }).compare("i", "İ") 

例如,但IE似乎在这种情况下并没有好多少。

无论如何,我认为可以通过包含浏览器检测部分来改进上述解决方案,该部分选择用于执行比较的闭包以及稍后在customSortOperations内部使用最佳实现。 尽管如此,上面的代码仍然安全,但它的原因可能并不那么优雅。