andr-04 / jquery.inputmask-multi
Inputmask Multi 是一个插件,允许根据输入数据的前缀选择输入掩码(例如国际电话号码)
This package is not auto-updated.
Last update: 2024-09-28 18:37:11 UTC
README
=============== Inputmask Multi
此插件是为 jQuery 开发的,允许根据输入的电话号码前缀选择输入掩码。这种技术可以减少输入电话号码时的错误,并使其更加简单。此外,此插件还可以用于其他字段,其中输入规则可以表示为多个输入掩码。
简介
网站通常需要输入电话号码。如今,每个国家都有自己的拨号规则和号码长度。因此,不同国家的人在使用电话号码时容易混淆:一个人给出的号码从数字 8 开始,另一个人从 0 开始,第三个人从 + 开始。
现有解决方案的评估
为解决上述问题并统一电话号码格式,有三种主要解决方案可用
-
建议使用输入掩码输入电话号码。优点:电话号码的直观显示可以减少输入错误。缺点:每个国家都有自己的电话号码书写规则,长度不同。
-
建议选择国家并输入电话号码的剩余部分;也可以为电话号码的剩余部分使用输入掩码。优点:可以为每个国家(以及国家内的每个地区)使用不同的输入掩码。缺点:国家(以及每个国家内的地区)的列表可能很长;电话号码被分成两部分(在保存和显示电话号码之前需要额外的预处理)。
-
在电话号码前添加数字 +(在输入框外),并允许仅输入数字。优点:易于实现。缺点:电话号码没有直观的显示。
解决方案
因此,决定改进常用的输入掩码,使其根据已输入的电话号码进行更改。此外,建议在输入电话号码时显示国家(地区)名称。主观上,这种方法应该解决上述所有问题。
考虑到世界上有那么多国家,决定收集所有国家的输入掩码列表。电话号码规则的信息来源是国际电信联盟网站发布的信息。
收集这些信息的过程很复杂。需要考虑所有可能的电话号码情况,包括每个国家内部的差异。由于手动处理了大量的信息,因此收集的数据可能包含不准确之处。计划在以后的时间内对此进行修复。
实现
本项目使用的是 jquery.inputmask 的实现。此插件仍在持续开发中,并旨在使其能够为其编写扩展。但在本任务中,无法编写扩展。我决定不涉及或重写核心的源代码,以避免由于它持续开发而引起的任何冲突,因此我不得不编写一个核心的超级结构来监控(并中断)外部事件以更改数据。在核心之前嵌入外部事件处理器的插件是 jquery.bind-first。
允许输入的掩码排序
要选择一个比其他电话号码匹配度更高的输入掩码,必须以特殊方式对所有可能的掩码列表进行排序。在考虑规则时,接受了以下定义
-
掩码中的所有符号分为两类:重要符号(在我的情况下是符号
#
,它匹配任何数字,以及数字0-9
)和符号装饰器(所有其他符号)。 -
输入掩码中符号的另一种分割是模板符号(在我的情况下是符号
#
)和其他符号。
因此,编写了以下应用顺序的排序规则
-
比较两个输入掩码时,仅考虑重要符号(不是装饰器)。
-
不同的模板符号被视为等效,其他重要符号根据它们的代码进行比较。
-
非模板符号始终小于模板符号,并且它们在结果中位于上方。
-
输入掩码中的重要字符长度越短,输入掩码越小,并且位于结果上方。
搜索匹配的输入掩码
当将输入文本与排序列表中的每个输入掩码进行比较时,仅考虑输入掩码中的重要符号。如果文本比掩码长,尽管所有之前的掩码符号都匹配,此掩码也不匹配。如果输入文本与多个掩码匹配,则仅返回第一个。之后,将找到的掩码中的所有重要符号(包括非模板符号)替换为模板符号,该模板符号结合了任何模板符号允许的所有符号。
事件处理和操作
为了避免与核心处理器的冲突,以下事件被中断
-
keydown - 监控 Backspace 和 Delete 键的按下,以便在核心处理器删除文本中的一个符号之前更改当前输入掩码。此外,还监控 Insert 键的按下,以更改输入模式进行同步。
-
keypress - 由于输入的符号可能不允许原始掩码(因为所有重要符号都被替换为模板),需要检查新文本是否与允许的输入掩码匹配。如果找不到匹配的掩码,则取消输入的符号,否则更改当前输入掩码,并将此事件传递到核心。
-
paste、input - 从剪贴板粘贴文本。在将事件传递到核心之前,对新的文本进行掩码搜索。如果找不到输入掩码,则从文本末尾开始按符号剪切,直到找到匹配的掩码。此方法用于更改文本的 val() 函数之后,以及初始化时如果输入文本不为空也是如此。
-
dragdrop(拖放)和 drop(放下)的处理与粘贴相同。
-
blur - 当输入框失去焦点且不匹配输入掩码时,进行额外的处理。此事件在核心事件处理之后处理。
所有事件都在 inputmask 空间中处理。这允许在初始化此插件后调用 inputmask 方法时避免错误操作(因为核心的初始化会取消 inputmask 空间中的其他处理程序)。
使用示例
掩码列表的格式
掩码列表是一个包含具有相同(或类似)属性集的对象的 JavaScript 数组。数组中的所有对象都必须至少有一个包含输入掩码的属性。此属性的名称可以不同。以下是一个掩码列表的示例片段
[
…
{ "mask": "+7(###)###-##-##", "cc": "RU", "name_en": "Russia", "desc_en": "", "name_ru": "Россия", "desc_ru": "" },
{ "mask": "+250(###)###-###", "cc": "RW", "name_en": "Rwanda", "desc_en": "", "name_ru": "Руанда", "desc_ru": "" },
{ "mask": "+966-5-####-####", "cc": "SA", "name_en": "Saudi Arabia ", "desc_en": "mobile", "name_ru": "Саудовская Аравия ", "desc_ru": "мобильные" },
{ "mask": "+966-#-###-####", "cc": "SA", "name_en": "Saudi Arabia", "desc_en": "", "name_ru": "Саудовская Аравия", "desc_ru": "" },
…
]
插件连接参数
在使用插件之前,需要对掩码列表进行排序。可以通过调用以下函数来完成此操作
$.masksSort = function(maskList, defs, match, key)
- maskList - 输入掩码对象的数组(见上方);
- defs - 模板符号的数组(在我们的案例中是符号
#
); - match - 有效符号的正则表达式(在我们的案例中是
/[0-9]|#/
); - key - 包含输入掩码的数组对象中的属性名称。
在插件初始化时,传递一个设置其工作的对象。此对象包含以下参数集
- inputmask - 核心插件的参数对象;
- match - 除去模板符号之外的有效符号的正则表达式;
- replace - 将所有有效符号替换掉的模板符号;可以在输入掩码对象的定义对象中省略;
- list - 输入掩码对象的数组;
- listKey - 包含输入掩码的对象中的属性名称;
- onMaskChange - 当更新当前输入掩码时调用的函数(回调函数);第一个参数是一个包含适配掩码的对象,第二个参数是新掩码的精度:true - 掩码完全适配,false - 需要更多符号来确定真正的掩码。
要初始化插件,需要调用输入字段的 inputmasks:$.fn.inputmasks = function(maskOpts, mode)
- maskOpts - 设置插件工作的对象;
- mode - 可选;现在它可以具有值 isCompleted - 如果输入字段的文本已完全输入,则函数返回 true,在其他情况下返回 false。
插件使用示例
<input type="text" id="customer_phone" value="7" size="25"><br>
<input type="checkbox" id="phone_mask" checked>
<label id="descr" for="phone_mask">Маска ввода</label>
<script>
var maskList = $.masksSort($.masksLoad("phone-codes.json"), ['#'], /[0-9]|#/, "mask");
var maskOpts = {
inputmask: {
definitions: {
'#': {
validator: "[0-9]",
cardinality: 1
}
},
//clearIncomplete: true,
showMaskOnHover: false,
autoUnmask: true
},
match: /[0-9]/,
replace: '#',
list: maskList,
listKey: "mask",
onMaskChange: function(maskObj, completed) {
if (completed) {
var hint = maskObj.name_ru;
if (maskObj.desc_ru && maskObj.desc_ru != "") {
hint += " (" + maskObj.desc_ru + ")";
}
$("#descr").html(hint);
} else {
$("#descr").html("Маска ввода");
}
$(this).attr("placeholder", $(this).inputmask("getemptymask"));
}
};
$('#phone_mask').change(function() {
if ($('#phone_mask').is(':checked')) {
$('#customer_phone').inputmasks(maskOpts);
} else {
$('#customer_phone').inputmask("+[####################]", maskOpts.inputmask)
.attr("placeholder", $('#customer_phone').inputmask("getemptymask"));
$("#descr").html("Маска ввода");
}
});
$('#phone_mask').change();
</script>
演示
此插件的演示可在项目的 页面 上找到。