【问题标题】:Non latin characters replace on .keyup() does not work when typing fast快速键入时,.keyup() 上的非拉丁字符替换不起作用
【发布时间】:2015-03-12 14:28:26
【问题描述】:

我有用拉丁字符替换西里尔字母用户输入的 jQuery 代码。当用户输入不是太快(每分钟 60-70 个字符)时,这项工作正常,但当用户输入速度比这快时,它混合了西里尔字符和拉丁字符,可能是因为无法及时捕获 keyup 事件。我该如何解决这个问题?

$("input[name*=Name]").not("input[name*=Main]").keyup(function (e) {
            if (e.keyCode === 8 || e.keyCode === 46 || e.keyCode === 9 || e.keyCode === 13 || e.keyCode === 17 || e.keyCode === 18 || e.keyCode === 37 || e.keyCode === 38 || e.keyCode === 39 || e.keyCode === 40 || e.keyCode === 16 || e.keyCode === 20) {
                return false;
            } else {
                var englishchars = ["a", "b", "v", "g", "d", "e", "yo", "zh", "z", "i", "yi", "k", "l", "m", "n", "o", "p", "r", "s", "t", "u", "f", "kh", "c", "ch", "sh", "shch", "i", "e", "yu", "ya", ""];
                var slavicchars = ["а", "б", "в", "г", "д", "е", "ё", "ж", "з", "и", "й", "к", "л", "м", "н", "о", "п", "р", "с", "т", "у", "ф", "х", "ц", "ч", "ш", "щ", "ы", "э", "ю", "я", "ь"];
                var verified = String.fromCharCode(e.wich).match(/[^а-яё]/);
                if (verified) {
                    e.preventDefault();
                    var lastchar = this.value.length > 1 ? this.value.substr(-1) : this.value;
                    var russiancharindex = jQuery.inArray(lastchar, slavicchars);
                    if (russiancharindex > 0) {
                        var englishcharindex = englishchars[russiancharindex];
                        this.value = this.value.replace(lastchar, englishcharindex);
                    } else {
                        return false;
                    }
                } else {
                    return false;
                }
            }
        });

【问题讨论】:

    标签: javascript jquery user-input


    【解决方案1】:

    (...) 可能是因为无法及时捕捉到 keyup 事件 (...)

    这是因为释放键时捕获了keyup 事件,而按下键时字符被插入到文本框中。
    因此,短按两个键(快速键入),两个字符已经存在于文本框中,然后一个一个地释放键,您只检查输入 value 的最后一个字符,但第一个释放的键被寻址到最后一个字符之前的一个。

    var lastchar = this.value.length > 1 ? this.value.substr(-1) : this.value;
    var russiancharindex = jQuery.inArray(lastchar, slavicchars);
    // ...
    

    同样由于这个原因,当您向后移动光标以在文本中间插入一个字母时,它将不起作用。


    这个怎么样?

    在每个keyup 上,它将匹配字符串中的每个非ascii字符(而不是仅匹配最后一个字符)。
    注意。更新输入值将导致光标丢失其当前位置,并将在输入结束时移动。为防止这种情况发生(如果您在中间某处编辑该字段),请在更新之前存储其位置并在之后恢复。

    (缩短您的 if(e.keyCode ...) 条件并在 keyCodes 中添加一个空格 [32])

    // keep these variables outside of the handler, so that they're not redeclared unnecessarily:
    var charsObject = {
        'a' : 'а',
        'б' : 'b',
        'в' : 'v',
        // ...
    }, keyCodes = [8,46,9,13,17,18,32,37,38,39,40,16,20];
    
    $("input[name*=Name]:not([name*=Main])").keyup(function(e){
        if (keyCodes.indexOf( e.keyCode ) < 0) {
            // store current cursor position:
            var start = this.selectionStart, end = this.selectionEnd;
            $(this).val($(this).val().replace(/[^\u0000-\u007f]/g, function(char, key) {
                // return replacement letter, or the original letter if it's not a "charsObject" key:
                return charsObject[char] || char;
            }));
            // restore cursor position after field update:
            this.setSelectionRange(start, end);
        }
    });
    

    JSFiddle

    【讨论】:

    • 看起来很有趣。让我试试。
    • 我不明白为什么您的代码在 JSFiddle 中运行,而不是在我的浏览器中运行。
    • 您为拉丁字符编码工作(如在您的 JSFiddle 中),但是当数组的一部分是西里尔字符时,它不起作用。不,控制台中没有错误。
    • @andrey.shedko ,更新了答案中的代码(和小提琴)
    • 太棒了!非常感谢!
    【解决方案2】:

    最后我得到了更好的解决方案。

    $("input[name*=Name]:not([name*=Main])").focusout(function (e) {
                var englishchars = ["a", "b", "v", "g", "d", "e", "yo", "zh", "z", "i", "yi", "k", "l", "m", "n", "o", "p", "r", "s", "t", "u", "f", "kh", "c", "ch", "sh", "shch", "i", "e", "yu", "ya", "'"];
                var slavicchars = ["а", "б", "в", "г", "д", "е", "ё", "ж", "з", "и", "й", "к", "л", "м", "н", "о", "п", "р", "с", "т", "у", "ф", "х", "ц", "ч", "ш", "щ", "ы", "э", "ю", "я", "ь"];
                var t = $(this).val().toLowerCase();
                var word = new Array();
                $.each(t.split(""), function (key, val) {
                    var verified = String.fromCharCode(e.wich).match(/[^а-яё]/);
                    if (verified) {
                        e.preventDefault();
                        var russiancharindex = jQuery.inArray(val, slavicchars);
                        if (russiancharindex >= 0) {
                            var englishcharindex = englishchars[russiancharindex];
                            word.push(englishcharindex);
                        } else {
                            word.push(val);
                        }
                    } else {
                        return false;
                    }
                    return word;
                });
                $(this).val(word.join("").replace(",", ""));
            });
    

    【讨论】:

      猜你喜欢
      • 2013-01-20
      • 2012-10-08
      • 2023-04-07
      • 1970-01-01
      • 1970-01-01
      • 2022-01-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多