Я уверен, что проблема в кодировке HTML-страницы, которую вы используете. Я попытался воспроизвести проблему и открыл старую демонстрацию, сохраненную в кодировке ANSI. После того, как я вставил тест yapı
в данные и сохранил, я смог воспроизвести проблему, но проверка кода показывает, что строка yapı
была сохранена как yapi
из-за кодировки ANSI. Затем я открыл ту же демонстрацию с помощью Блокнота (я работаю на компьютере с Windows), повторил то же самое и использовал SaveAs, чтобы иметь возможность выбирать кодировку UTF-8. Теперь можно было увидеть действительно yapı
строку, отображаемую в сетке вместо yapi
раньше, и я мог успешно отфильтровать строку. Конечно, во время обоих экспериментов у меня было <meta charset="utf-8">
.
Таким образом, вы должны убедиться, что не только <meta charset="utf-8">
существует в <head>
вашей HTML-страницы, но и данные также находятся в кодировке UTF-8. В случае встроенных данных (как в моем эксперименте) файл необходимо сохранить в формате UTF-8.
ОБНОВЛЕНО. Обсуждение в комментариях показывает, что основной проблемой была фильтрация турецкого текста без учета регистра.
Проблема была для меня совершенно новой, но в турецком языке есть два i
: один с точкой больше i
, а другой без точки ı
. Оба i
имеют соответствующие заглавные буквы I
: İ
и I
. Вся информация не отличается от многих других языков. Основная проблема заключается в выборе представления Unicode для 4 символов: турецкие символы i
и I
используют те же коды, что и латинские символы: U+0069
и U+0049
. На U+0131
и U+0130
будут отображаться только символы ı
и İ
(см. здесь ). Такое сопоставление делает невозможным реализацию сравнения без учета регистра или функций JavaScript .toUpperCase()
и .toLowerCase()
. Если входной текст содержит латинскую букву i
, тогда функция .toUpperCase()
должна преобразовать его в I
, но это неверно для турецкого языка и вместо этого должно быть İ
. Таким же образом .toLowerCase()
должен выдать ı
для турецкого текста и i
для английского текста.
Итак, первая важная информация: невозможно реализовать одну универсальную версию сравнения без учета регистра без знания языка ввода.
OK. А теперь вернемся к проблеме. Как реализовать поиск без учета регистра в турецких текстах? После изменения лицензионного соглашения на jqGrid в версии 4.7.1 я продолжаю разработку его бесплатной версии (по лицензии MIT и GPL v2) под названием free jqGrid. Я реализовал много новых функций в первом выпуске бесплатного jqGrid: версии 4.8. Функция «настраиваемой фильтрации», описанная в статья в вики может помочь в реализации.
На основе этой функции я создал следующую демонстрацию . В процессе реализации я исправил небольшие ошибки в коде бесплатного jqGrid. Поэтому в демонстрации я использую последние исходники с GitHub (http://rawgit.com/free-jqgrid/jqGrid/master/js/jquery.jqgrid.src.js
) (прочтите wiki об URL-адресах).
Я использовал следующие параметры в 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, который поддерживает параметры. Я тестировал это в Google Chrome
"i".localeCompare("İ", "tr", { sensitivity: "base" }) === 0
"i".localeCompare("I", "tr", { sensitivity: "base" }) === 1
"ı".localeCompare("I", "tr", { sensitivity: "base" }) === 0
"ı".localeCompare("İ", "tr", { sensitivity: "base" }) === -1
or
"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
возвращают 0
в IE11. Может случиться так, что можно использовать другое значение sensitivity
для получения ожидаемых результатов. IE9 вместо этого возвращает 1 или -1 для вышеуказанных вызовов localeCompare
. Я полагаю, что он учитывает только первый параметр и игнорирует "tr", { sensitivity: "base" }
часть. Результаты в Chrome выглядят так
Один и тот же результат в Firefox
но не в IE11
Еще один вариант - использовать класс ECMAScript Internationalization API. Intl.Collator (см. ecma-402 и здесь), например
new Intl.Collator("tr", { sensitivity: "base" }).compare("i", "İ")
например, но IE, кажется, не намного лучше в этом случае.
В любом случае, я полагаю, что можно улучшить вышеупомянутое решение, включив часть обнаружения браузера, которая выбирает закрытие для реализации сравнения и использования лучшей реализации внутри customSortOperations
позже. Тем не менее, приведенный выше код работает безопасно, но, вероятно, не так элегантен.
person
Oleg
schedule
02.04.2015