Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > JavaScript: Общие вопросы > Контроль ввода


Автор: magelan 21.5.2012, 12:20
Столкнулся с проблемой - не дать пользователю вводить неправильные символы, либо перекодировать на лету, невзирая на выбор языка.
Первый подход с RegExp дал неутешительные результаты, современные браузеры на быстрых машинах проглатывают события, в результате не весь набор пользователя правильно прилетает.
RegExp возможно использовать, если кешировать ввод, а регулярку применять время от времени.
Однако выяснилось, что при работе с массивами, все браузеры успевают. Как не печально, нормального решения так и не нашел, хотя проблема казалось бы на поверхности.
Привожу рабочий пример, может кому-то будет полезно, оформлять "по модному" не стал, чтобы не запутывать идею.
Код

<!DOCTYPE html>
<html>
    <head>
        <title>coding</title>
        <script src="http://code.jquery.com/jquery-latest.js"></script>
<script type=text/javascript>
chartable_int_num = { 
    '0':'0', 
    '1':'1',
    '2':'2', 
    '3':'3', 
    '4':'4', 
    '5':'5',
    '6':'6', 
    '7':'7', 
    '8':'8', 
    '9':'9',
    ')':'0', 
    '!':'1',
    '@':'2', 
    '#':'3', 
    '$':'4', 
    '%':'5',
    '^':'6', 
    '&':'7', 
    '*':'8', 
    '(':'9',
    '"':'2', 
    '№':'3', 
    ';':'4', 
    ':':'6', 
    '?':'7'
};
chartable_float_num = { 
    '.':'.',
    '>':'.',
    'Ю':'.',
    'ю':'.'
};
$.extend(chartable_float_num, chartable_int_num);
chartable_ru_en = {
    'а': 'f', 
    'б': ',',
    'в': 'd',
    'г': 'u',
    'д': 'l',
    'е': 't',
    'ё': '`',
    'ж': ';',
    'з': 'p',
    'и': 'b',
    'й': 'q',
    'к': 'r',
    'л': 'k',
    'м': 'v',
    'н': 'y',
    'о': 'j',
    'п': 'g',
    'р': 'h',
    'с': 'c',
    'т': 'n',
    'у': 'e',
    'ф': 'a',
    'х': '[',
    'ц': 'w',
    'ч': 'x',
    'ш': 'i',
    'щ': 'o',
    'ъ': ']',
    'ы': 's',
    'ь': 'm',
    'э': '\'',
    'ю': '.',
    'я': 'z',
    'А': 'F',
    'Б': '<',
    'В': 'D',
    'Г': 'U',
    'Д': 'L',
    'Е': 'T',
    'Ё': '~',
    'Ж': ':',
    'З': 'P',
    'И': 'B',
    'Й': 'Q',
    'К': 'R',
    'Л': 'K',
    'М': 'V',
    'Н': 'Y',
    'О': 'J',
    'П': 'G',
    'Р': 'H',
    'С': 'C',
    'Т': 'N',
    'У': 'E',
    'Ф': 'A',
    'Х': '{',
    'Ц': 'W',
    'Ч': 'X',
    'Ш': 'I',
    'Щ': 'O',
    'Ъ': '}',
    'Ы': 'S',
    'Ь': 'M',
    'Э': '\"',
    'Ю': '>',
    'Я': 'Z'
};
chartable_en_ru = [];
for( var key in chartable_ru_en )
    chartable_en_ru[ chartable_ru_en[ key ]] = key;
    
var check_key = $.browser.msie 
? function(e, obj, func) {
    if(event.keyCode > 31)
    {    
        var len = 0;
        with(document.selection.createRange()) 
        {
            select();
            text = '';
            collapse(false);
            moveStart("textedit", -1);
            len = text.length + 1;
//            collapse(false);
            select();
            text += func(String.fromCharCode(event.keyCode));
            collapse(false);
        }
        event.keyCode = 0;    
        with(obj.createTextRange())
        {
            move("character", len);
            select();
        }
    }
    return false;
}
: function(e, obj, func){
    var code = e.which;
    if (code > 31 && (!(e.ctrlKey || e.altKey))) {
        if(e.preventDefault)
            e.preventDefault();
            
        var before = obj.value.substring(0, obj.selectionStart);
        var result = before + func(String.fromCharCode(code));
        
        var left = obj.scrollLeft;
        obj.value = result + obj.value.substr(obj.selectionEnd);
        var total = obj.value.length;
        
        obj.setSelectionRange(result.length, result.length);

        var scroll = obj.scrollWidth;        
        if( scroll > obj.clientWidth )
            obj.scrollLeft = parseInt(scroll * (before.length + 1)  / total) - obj.clientWidth + 1;
    }
    return false;
}

function toRU(s)
{
    return chartable_en_ru[s]?chartable_en_ru[s]:chartable_ru_en[s]?s:'';
}
function toEN(s)
{
    return chartable_ru_en[s]?chartable_ru_en[s]:chartable_en_ru[s]?s:'';
}
function toNUM(s)
{
    return chartable_int_num[s]?chartable_int_num[s]:'';
}
function toFNUM(s)
{
    return chartable_float_num[s]?chartable_float_num[s]:'';
}

$(document).ready( function(){
    $('input#i_1').keypress(function(e){
        check_key(e, this, toRU);
    });
    $('input#i_2').keypress(function(e){
        check_key(e, this, toEN);
    });
    $('input#i_3').keypress(function(e){
        check_key(e, this, toFNUM);
    });
});
</script>
    </head>
<body>
ru - <input id="i_1" /><br /><br />
en - <input id="i_2" /><br /><br />
f num - <input id="i_3" />        
</body>
</html>

Автор: ksnk 21.5.2012, 16:13
Если пользоваться jQuery, то e.which присутствует везде. Библиотека дополняет событие полями, если они отсутствуют.

А зачем нужно пользоваться selection'ами? Для ускорения фильтрации?

Ну и традиционно - никак не защищается cut&paste вставка - самое то, при редактировании блондинками smile 

P.S.
К тому-же как-то не понимаю надобность контроля за каждым символом. Контроль в конце ввода или по потере фокуса - самое правильное, imho...

Автор: Aliance 22.5.2012, 09:19
Будет полезно:
http://codeshit.com/post416

Автор: magelan 22.5.2012, 11:05
Цитата(ksnk @ 21.5.2012,  16:13)
Если пользоваться jQuery, то e.which присутствует везде. Библиотека дополняет событие полями, если они отсутствуют.

А зачем нужно пользоваться selection'ами? Для ускорения фильтрации?

Ну и традиционно - никак не защищается cut&paste вставка - самое то, при редактировании блондинками smile 

P.S.
К тому-же как-то не понимаю надобность контроля за каждым символом. Контроль в конце ввода или по потере фокуса - самое правильное, imho...

В таких особенностях jQuery как which пока плаваю,  за инфу спасибо.

ИЕ приблизительно в 10 раз  тормознее конкурентов в скриптах, поэтому да селекты, для ускорения.

На внешнее воздествие задачи нет, т.к. на этих полях еще работает валидация. ага жесть.

В обычной жизни я тоже не очень понимал нафига, но задача вводить мультиязычную форму имя/фамилия по русски имя/фамилия по английски... а тут такая штучка, помогает, реально. 

Автор: magelan 22.5.2012, 11:21
Цитата(Aliance)
Будет полезно:
http://codeshit.com/post416

Благодарю. Хотя скрипты там достаточно древние - хром, например, на document.all проверку пройдет.

Для того, чтобы отловить копирование, дропы, и все такое, можно использовать http://www.zurb.com/playground/jquery-text-change-custom-event. Я его пробывал он подгреб все браузеры кроме 9го IE на виндоуз фоне(но это экзотика). Событие от него запаздывает при быстром вводе, для защиты от извне - подойдет, для моей задачи - не очень.

Автор: Aliance 22.5.2012, 15:46
Цитата(magelan @  22.5.2012,  12:21 Найти цитируемый пост)
хром, например, на document.all проверку пройдет.

document.all там используется в единственном месте, которое завязано на описываемой там задачи с tinyMCE, реализация которой конкретно Вам не нужна как я понимаю. Ссылку дал скорее для того чтобы показать какие ситуации нужно обрабатывать и какие события они вызывают.

Автор: magelan 23.5.2012, 11:36
Цитата(Aliance @ 22.5.2012,  15:46)
document.all там используется в единственном месте, которое завязано на описываемой там задачи с tinyMCE, реализация которой конкретно Вам не нужна как я понимаю. Ссылку дал скорее для того чтобы показать какие ситуации нужно обрабатывать и какие события они вызывают.

Еще раз вам говорю, код древний и писан в плохом стиле.

Зачем делить браузеры по половой принадлежности, если без этого можно обойтись?
например, зачем писать:
Код
if (BEDetector.engine.is.Gecko || BEDetector.engine.is.WebKit || BEDetector.engine.is.Opera) {
        el.addEventListener('input',
когда можно написать:
Код
if ( el.addEventListener) {
        el.addEventListener('input',
и обойтись без древних библиотек.

Вы мне хотели рассказать этой статьей про события inputdragdropkeyuponpropertychange и DOMCharacterDataModified?
Или как? Вы думаете я не знаю, как проверить не положили ли в input что-то из буфера обмена? Вы не смотрели код того элегантного плагина, который я вам привел в ответ?

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)