【问题标题】:How to auto-format telephone numbers in an HTML text input type field using JavaScript?如何使用 JavaScript 在 HTML 文本输入类型字段中自动格式化电话号码?
【发布时间】:2019-04-28 06:46:15
【问题描述】:

我需要一个解决方案来解决我面临的以下 3 部分挑战。

在网页表单上,我有一个 input type = “text” 字段,它要求用户输入一个 10 位数的电话号码。我需要该字段能够在用户输入数据时执行以下操作(通过从键盘键入或复制和粘贴数据手动输入数据):

只允许输入 10 个数字。示例:当用户输入电话号码时,不小心在文本字段中插入了字母、符号字符或空格键,这些无效字符将被忽略/删除。示例:用户输入 q01234 56789p,字段中只应取 0123456789。

如果在电话号码的开头检测到 27,则必须将其转换为 0,但仍必须能够捕获最后一位数字。这主要是因为当用户粘贴以27开头的数据时,它必须捕获27之后的整个数字并且不能省略最后一个数字,因为以27开头的电话号码会使电话号码总共11位数字,因此超过 10 位限制 1 位。 (例如:27123456789 必须变为 0123456789 而不仅仅是 012345678)。当用户将数据粘贴到字段中而不是等待用户首先放松对字段的关注时,有没有一种方法可以做到这一点,或者即使用户失去对字段的关注,也可以这样做?我问,因为我担心限制不会从包含 11 位的复制值中插入最后一位,因为它以 27 开头。

所有上述条件都必须验证和更正用户数据,因为用户尝试通过按 Enter、Tab 或单击下一个输入字段进入下一个输入字段。

此表单的预期用途是供用户即时输入数据或从各种外部日志中复制和粘贴数据,这些日志要么省略了前导零,要么包含 +27 国际拨号代码。

我打算将此表单主要用于 Firefox(66x Quantum 版本)。

无论如何,如果我的 html 冲突或与实现此功能所需的 JS 代码不兼容,我不介意更改它,只要它仍然是一个文本框并且不需要更改为“文本字段”或“数字”输入类型。

<form>
<label>Phone Number</label><br>
<input id="PhoneNumber" type="text" minlength="10" maxlength="10" pattern="[0][0-9]" required>
</form>

【问题讨论】:

  • 你能不能稍微细化你的问题,让文字更少,以便更快地阅读和回答。
  • 我对“必须立即验证和更正用户数据”感到困惑:如果用户开始输入一个空输入并输入 1,那么应该立即在数字前面加上前缀有9个零!?在我看来,只有当用户以某种方式表明他们已经完成输入了他们想要的数字时,才会发生这种操作。
  • @Cryptopat - 谢谢你的建议,我会考虑电话输入。
  • @Alicia - 抱歉,我已经重新编辑了我的帖子并尽可能地缩短了它(我认为)。我倾向于过度思考这些事情:P

标签: javascript


【解决方案1】:

其实有一个输入类型tel,可以省去很多麻烦。使用&lt;input type="tel" ... 是正确的方法,它还允许您使用pattern 属性指定一个正则表达式来验证电话号码是否符合您的规范。

例如

<input type="tel" >

参考:https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/tel

值得注意的是,当然,您仍然需要服务器端验证。您应该在客户端和服务器上使用相同的正则表达式。

现在得到广泛支持,但如果您担心,请参阅this answer

【讨论】:

    【解决方案2】:

    首先,我建议不要立即删除字符,因为这可能违反用户的直觉:您不希望他们认为他们的键盘坏了。

    其次,您的某些要求是矛盾的。两个例子:

    输入仍然必须在该电话号码的开头附加一个零,使其总共有 10 位数字

    [...]

    上述所有条件都必须在用户输入数据时立即验证和更正用户数据

    这意味着如果用户开始在空输入字段中输入并输入“1”,则该规则应立即生效并使该电话号码总共为 10 位数。

    另一个矛盾:

    只允许输入数字。 [...] 无效字符将被忽略/删除

    [...]

    从电话号码中去除国际拨号代码,[...] +27123456789 应变为 0123456789

    但是如果用户只能输入数字,那么他们将永远无法输入 +27:当他们输入“+”时,它就会被删除。

    这当然不是预期的行为。因此,至少当用户以某种方式表明他们已完成输入电话号码时,才应应用一些规则。这可以在他们将选择移动到下一个输入字段时完成。

    这是一个实现,其中除数字和“+”之外的字符被立即忽略/去除,“+”只能作为最左边的字符输入。

    国际拨号代码的删除,以及用零填充,只会在焦点改变时应用:

    const el = document.querySelector("#PhoneNumber");
    
    const littleClean = input => input.replace(/(\d)\D+|^[^\d+]/g, "$1")
                                      .slice(0, 12);
    const bigClean = input => !input ? ""
                                     : input.replace(/^\+(27)?/, "")
                                            .padStart(10, "0")
                                            .slice(0, 10);
    const format = clean => {
        const [i, j] = [el.selectionStart, el.selectionEnd].map(i => 
            clean(el.value.slice(0, i)).length
        );
        el.value = clean(el.value);
        el.setSelectionRange(i, j);
    };
    el.addEventListener("input", () => format(littleClean));
    el.addEventListener("focus", () => format(bigClean));
    el.addEventListener("blur", () => format(bigClean));
    <form>
        <label>Phone Number<br>
        <input id="PhoneNumber" type="tel" minlength="10" required></label><br>
        <label>Name<br>
        <input id="Name" type="text" required></label><br>
    </form>

    【讨论】:

    • 非常感谢您的建议——这正是我所需要的。是否可以让您的示例中的字段总共只接受 10 位数字?还是只在 html 中添加 maxlength=10 就可以解决这个问题?
    • 我刚刚添加了 slice 调用,以便在用户输入时最多允许 12 个字符(以允许“+27”),一旦用户离开输入字段,最多允许 10 个字符。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-07
    • 1970-01-01
    • 2023-01-07
    • 1970-01-01
    相关资源
    最近更新 更多