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

时间:2015-04-02 14:30:02

标签: jquery jqgrid turkish free-jqgrid

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

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

我的页面编码是;

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

我的ajax帖子在这里

$。AJAX({                 类型:&#34;发布&#34;,                 url:&#34; page / get.aspx,                 contentType:&#34; application / json;字符集= UTF-8&#34 ;,                 dataType:&#34; json&#34;,                 数据:&#34; {}&#34;,                 成功:function(){                 //                 },                 错误:function(){                   //                 }             });

1 个答案:

答案 0 :(得分:1)

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

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

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

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

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

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

根据我创建的功能 the following demo 。我在实现过程中在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中为包含土耳其文本的列指定操作:

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中的相同测试与the information about the browser compatibility相反。以上localeCompare的所有调用都会在IE11中返回0。可以使用sensitivity的另一个值来获得预期结果。对于localeCompare的上述调用,IE9会返回1或-1。我想它只考虑第一个参数并忽略"tr", { sensitivity: "base" }部分。 Chrome中的结果看起来如此

enter image description here

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

enter image description here

但不是在IE11中

enter image description here

另一个选项是使用The ECMAScript Internationalization API课程Intl.Collator(请参阅ecma-402here),例如

new Intl.Collator("tr", { sensitivity: "base" }).compare("i", "İ")
例如,但在这种情况下,IE似乎并没有那么好。

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