【问题标题】:Limit input to numbers and . on input field将输入限制为数字和 。在输入字段上
【发布时间】:2012-12-11 21:21:50
【问题描述】:

继我问的另一个问题之后,我似乎真的没有得到任何地方。由于我的无能。我选择这些人的答案是因为,他回答了我的问题。

我正在收集我没有问正确的问题因为我不知道该怎么做..

所以问题是我有输入元素。保持简单;

<input type="text" maxlength="12" name="price" id="price" class="foo">

我希望用户能够在该价格的任何位置只输入数字和一个句点 (.)。所以可能是 3.00 或 300.00 或 3000

有人能帮帮我吗,我要瞪大眼睛了。

问的较早的问题在这里Quick regex with alert

【问题讨论】:

  • 300. 怎么样?这是一个有效的输入吗?
  • @Anurag 是的,没关系。我们可以去掉 .如果没有任何东西跟随它服务器端
  • 只是 . 一个可接受的输入吗?
  • @Anurag 没有。我在想,可以将正则表达式(不是我理解或如何实现它)设置为期望一个数字(最小 1 个数字),然后是其他数字或一个句点的任意组合。
  • 可以是像 123.45 这样的数字还是小数点后的部分(如果存在)必须全为零?

标签: javascript html forms


【解决方案1】:

您可以在输入的change 事件中检查数字格式是否正确。此代码将尝试获取数字并删除其他任何内容:(我假设您使用 jQuery,如果没有,请这样做)

$('#price').change(function() {
    $(this).val($(this).val().match(/\d*\.?\d+/));
});

看到它工作here

编辑:如果你没有 jQuery,这段代码也是一样的(至少在 Chrome 中):

document.getElementById('price').onchange = function() {
    this.value = this.value.match(/\d*\.?\d+/);
};

编辑 2:不确定我是否遵循,但您也可以添加它以防止字母和其他字符change 事件之前:

$('#price').keypress(function(event) {
    var code = (event.keyCode ? event.keyCode : event.which);
    if (!(
            (code >= 48 && code <= 57) //numbers
            || (code == 46) //period
        )
        || (code == 46 && $(this).val().indexOf('.') != -1)
       )
        event.preventDefault();
});

【讨论】:

  • 我确实使用 jquery,但您的示例不适合我,我可以输入任何内容。 ??
  • 是的,它应该只保留数字。看看我的小提琴(我发布的链接)
  • 只看我的问题(我发布的问题)数字,只有一个时期
  • 感谢@cambraca 您的第二次编辑,导致无法输入。
  • 好的,谢谢,我会在客户端这样做,它很轻,只有白痴才会输入 bugger.it 哈哈
【解决方案2】:

这是我的解决方案(它还验证复制和粘贴的数据/值):

function InputValidator(input, validationType, validChars) {
if (input === null || input.nodeType !== 1 || input.type !== 'text' && input.type !== 'number')
    throw ('Please specify a valid input');

if (!(InputValidator.ValidationType.hasOwnProperty(validationType) || validationType))
    throw 'Please specify a valid Validation type';

input.InputValidator = this;

input.InputValidator.ValidCodes = [];

input.InputValidator.ValidCodes.Add = function (item) {
    this[this.length] = item;
};

input.InputValidator.ValidCodes.hasValue = function (value, target) {
    var i;
    for (i = 0; i < this.length; i++) {
        if (typeof (target) === 'undefined') {
            if (this[i] === value)
                return true;
        }
        else {
            if (this[i][target] === value)
                return true;
        }
    }

    return false;
};

var commandKeys = {
    'backspace': 8,
    'tab': 9,
    'enter': 13,
    'shift': 16,
    'ctrl': 17,
    'alt': 18,
    'pause/break': 19,
    'caps lock': 20,
    'escape': 27,
    'page up': 33,
    'page down': 34,
    'end': 35,
    'home': 36,
    'left arrow': 37,
    'up arrow': 38,
    'right arrow': 39,
    'down arrow': 40,
    'insert': 45,
    'delete': 46,
    'left window key': 91,
    'right window key': 92,
    'select key': 93,
    /*creates Confusion in IE */
    //'f1': 112,
    //'f2': 113,
    //'f3': 114,
    //'f4': 115,
    //'f5': 116,
    //'f6': 117,
    //'f7': 118,
    //'f8': 119,
    //'f9': 120,
    //'f10': 121,
    //'f11': 122,
    //'f12': 123,
    'num lock': 144,
    'scroll lock': 145,
};

commandKeys.hasValue = function (value) {
    for (var a in this) {
        if (this[a] === value)
            return true;
    }

    return false;
};

function getCharCodes(arrTarget, chars) {
    for (var i = 0; i < chars.length; i++) {
        arrTarget.Add(chars[i].charCodeAt(0));
    }
}

function triggerEvent(name, element) {
    if (document.createEventObject) {
        // dispatch for IE
        var evt = document.createEventObject();
        return element.fireEvent('on' + name, evt)
    }
    else {
        // dispatch for firefox + others
        var evt = document.createEvent("HTMLEvents");
        evt.initEvent(name, true, true); // event type,bubbling,cancelable
        return !element.dispatchEvent(evt);
    }
}

if (validationType == InputValidator.ValidationType.Custom) {
    if (typeof (validChars) === 'undefined')
        throw 'Please add valid characters';

    getCharCodes(input.InputValidator.ValidCodes, validChars);
}
else if (validationType == InputValidator.ValidationType.Decimal) {
    getCharCodes(input.InputValidator.ValidCodes, '0123456789.');
}
else if (validationType == InputValidator.ValidationType.Numeric) {
    getCharCodes(input.InputValidator.ValidCodes, '0123456789');
}

input.InputValidator.ValidateChar = function (c) {
    return this.ValidCodes.hasValue(c.charCodeAt(0));
}

input.InputValidator.ValidateString = function (s) {
    var arr = s.split('');

    for (var i = 0; i < arr.length; i++) {
        if (!this.ValidateChar(arr[i])) {
            arr[i] = '';
        }
    }

    return arr.join('');
}

function bindEvent(el, eventName, eventHandler) {
    if (el.addEventListener) {
        el.addEventListener(eventName, eventHandler, false);
    } else if (el.attachEvent) {
        el.attachEvent('on' + eventName, eventHandler);
    }
}

function getCaretPosition(i) {
    if (!i) return;

    if ('selectionStart' in i) {
        return i.selectionStart;
    }
    else {
        if (document.selection) {
            var sel = document.selection.createRange();
            var selLen = document.selection.createRange().text.length;
            sel.moveStart('character', -i.value.length);
            return sel.text.length - selLen;
        }
    }
}

function setCursor(node, pos) {
    var node = (typeof (node) === "string" || node instanceof String) ? document.getElementById(node) : node;

    if (!node) {
        return false;
    }
    else if (node.createTextRange) {
        var textRange = node.createTextRange();
        textRange.collapse(true);
        textRange.moveEnd(pos);
        textRange.moveStart(pos);
        textRange.select();
        return true;
    } else if (node.setSelectionRange) {
        node.setSelectionRange(pos, pos);
        return true;
    }

    return false;
}

function validateActive() {
    if (input.isActive) {
        var pos = getCaretPosition(input);

        var arr = input.value.split('');

        for (var i = 0; i < arr.length; i++) {
            if (!this.ValidateChar(arr[i])) {
                arr[i] = '';

                if (pos > i)
                    pos--;
            }
        }
        console.log('before : ' + input.value);

        input.value = arr.join('');
        console.log('after : ' + input.value, input);
        setCursor(input, pos);

        setTimeout(validateActive, 10);
    }
}

bindEvent(input, 'keypress', function (e) {
    var evt = e || window.event;
    var charCode = evt.which || evt.keyCode;

    if (!input.InputValidator.ValidCodes.hasValue(charCode) && !commandKeys.hasValue(charCode)) {
        if (evt.preventDefault) {
            evt.preventDefault();
            evt.stopPropagation();
        }
        return false;
    }
});

bindEvent(input, 'keyup', function (e) {
    var evt = e || window.event;
    var charCode = evt.which || evt.keyCode;

    if (!input.InputValidator.ValidCodes.hasValue(charCode) && !commandKeys.hasValue(charCode)) {
        if (evt.preventDefault) {
            evt.preventDefault();
            evt.stopPropagation();
        }
        return false;
    }
});

bindEvent(input, 'change', function (e) {
    var dt = input.value;

    input.value = input.InputValidator.ValidateString(input.value);

    if (input.value !== dt)
        triggerEvent('change', input);
});

bindEvent(input, 'blur', function (e) {
    var dt = input.value;
    input.value = input.InputValidator.ValidateString(input.value);

    input.isActive = false;

    if (input.value !== dt)
        triggerEvent('blur', input);
});

bindEvent(input, 'paste', function (e) {
    var evt = e || window.event;
    var svt = input.value;

    if (evt && evt.clipboardData && evt.clipboardData.getData) {// Webkit - get data from clipboard, put into editdiv, cleanup, then cancel event
        if (/text\/html/.test(evt.clipboardData.types)) {
            var dt = evt.clipboardData.getData('text/html');

            input.value = input.InputValidator.ValidateString(dt);
            if (input.value !== dt)
                triggerEvent('change', input);
        }
        else if (/text\/plain/.test(e.clipboardData.types)) {
            var dt = evt.clipboardData.getData('text/plain');

            input.value = input.InputValidator.ValidateString(dt);
            if (input.value !== dt)
                triggerEvent('change', input);
        }
        else {
            input.value = '';
        }
        waitforpastedata(input, svt);
        if (e.preventDefault) {
            e.stopPropagation();
            e.preventDefault();
        }
        return false;
    }
    else {// Everything else - empty editdiv and allow browser to paste content into it, then cleanup
        input.value = '';
        waitforpastedata(input, svt);
        return true;
    }
});

bindEvent(input, 'select', function (e) {
    var evt = e || window.event;

    if (evt.preventDefault) {
        evt.preventDefault();
        evt.stopPropagation();
    }
    return false;
});

bindEvent(input, 'selectstart', function (e) {
    var evt = e || window.event;

    if (evt.preventDefault) {
        evt.preventDefault();
        evt.stopPropagation();
    }
    return false;
});

/* no need to validate wile active,
   removing F keys fixed IE compatability*/
//bindEvent(input, 'fucus', function (e) {
//    input.isActive = true;
//    validateActive();
//});

//validate current value of the textbox
{
    var dt = input.value;
    input.value = input.InputValidator.ValidateString(input.value);

    //trigger event to indicate value has changed
    if (input.value !== dt)
        triggerEvent('change', input);
}

function waitforpastedata(elem, savedcontent) {
    if (elem.value !== '') {
        var dt = input.value;
        elem.value = elem.InputValidator.ValidateString(elem.value);

        if (input.value !== dt)
            triggerEvent('change', input);
    }
    else {
        var that = {
            e: elem,
            s: savedcontent
        }
        that.callself = function () {
            waitforpastedata(that.e, that.s)
        }
        setTimeout(that.callself, 10);
    }
}
}

InputValidator.ValidationType = new (function (types) {
    for (var i = 0; i < types.length; i++) {
        this[types[i]] = types[i];
    }
})(['Numeric', 'Custom', 'Decimal']);

要将其应用于输入,请执行以下操作:

new InputValidator(document.getElementById('txtValidate'), InputValidator.ValidationType.Decimal);/* Numeric or Custom */

如果您将自定义指定为验证类型,则必须指定有效字符。 例如:

new InputValidator(document.getElementById('txtValidate'), InputValidator.ValidationType.Custom,'1234abc');

【讨论】:

    【解决方案3】:

    Cambraca 方法是一种有效的方法,但最好的方法是最后提到的方法,您在按键出现之前取消过滤按键的按键事件,而不是撤消已经完成的操作。事后更改值的结果是它可能会影响插入符号在字段中的位置。

    这是一个以跨浏览器方式抽象概念的示例。有人应该将此移植到 jQuery 插件 http://www.qodo.co.uk/assets/files/javascript-restrict-keyboard-character-input.html

    好的,我想我会移植它。但我不是 jQuery 人,所以这是一个使用他们的代码的 untested 基本 jQuery 插件 http://jsfiddle.net/mendesjuan/VNSU7/3

    (function( $ ) {
        $.fn.restrict = function(regExp, additionalRestriction) {
            function restrictCharacters(myfield, e, restrictionType) {
                var code = e.which;
                var character = String.fromCharCode(code);
                // if they pressed esc... remove focus from field...
                if (code==27) { this.blur(); return false; }
                // ignore if they are press other keys
                // strange because code: 39 is the down key AND ' key...
                // and DEL also equals .
                if (!e.originalEvent.ctrlKey && code!=9 && code!=8 && code!=36 && code!=37 && code!=38 && (code!=39 || (code==39 && character=="'")) && code!=40) {
                    if (character.match(restrictionType)) {
                        return additionalRestriction(myfield.value, character);
                    } else {
                        return false;
                    }
                }
            }
            this.keypress(function(e){
                if (!restrictCharacters(this, e, regExp)) {
                    e.preventDefault();
                }
            });
        };
    })( jQuery );
    
    $('#field').restrict(/[0-9\.]/g, function (currentValue, newChar) {
        return !(currentValue.indexOf('.') != -1 && newChar == ".");    
    });
    

    【讨论】:

    • 问题仍然存在,多个时期。加上句号后的任意位数。悬停这种方法确实允许删除键
    • @422:再看看。现在它确实有一种不允许多个周期的方法并且它已经实现了。您可以通过将第二个参数修改为 restrict 来修改额外限制,使其仅允许句点后的数字