通过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
都有相应的资本I
: I
和I
。 所有信息都与许多其他语言没有什么不同。 主要问题在于选择4个字符的Unicode表示:土耳其字符i
和I
使用相同的代码,如拉丁字符 : U+0069
和U+0049
。 只有字符ı
和İ
将映射到U+0131
和U+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.Collator (参见ecma-402和这里 ),如
new Intl.Collator("tr", { sensitivity: "base" }).compare("i", "İ")
例如,但IE似乎在这种情况下并没有好多少。
无论如何,我认为可以通过包含浏览器检测部分来改进上述解决方案,该部分选择用于执行比较的闭包以及稍后在customSortOperations
内部使用最佳实现。 尽管如此,上面的代码仍然安全,但它的原因可能并不那么优雅。