在我正在从事的一个项目中,我的团队最近在 JavaScript/Angular 中开发了一种“屏蔽”输入,该输入作为依赖于过滤器的指令,以便向用户显示美国格式的电话号码电话号码。由于我们的应用程序仅在美国使用,因此我们不必担心使其能够灵活地适应其他国家/地区的电话格式。
对于那些不熟悉的人来说,这是美国电话号码的常用格式:
(AAA) EEE-TTTT xXXXXX
地点:
- A:区号
- E:交换代码
- T:终端代码
- X:扩展
我最初要解决的问题是,尝试编辑区号会导致光标跳到电话号码的末尾。更深层次的问题是,由于我们当前对该指令的实现,尝试在电话号码中间插入任何信息都会导致光标跳到末尾!
以下是它的实现和使用方式:
标记:
<input type="text"
id="some-phone-number"
name="somePhoneNumber"
class="form-control"
data-ng-model="vm.somePhoneNumber"
phone-input />
指令:
angular.module('app').directive('phoneInput', [
'$filter', '$browser', phoneInputDir
]);
function phoneInputDir($filter, $browser) {
return {
require: 'ngModel',
link: function($scope, $element, $attrs, ngModelCtrl) {
var listener = function() {
var value = $element.val().replace(/[^0-9]/g, '');
$element.val($filter('tel')(value, false));
};
ngModelCtrl.$formatters.unshift(function (modelValue) {
return $filter('tel')(modelValue, false);
});
// This runs when we update the text field
ngModelCtrl.$parsers.push(function(viewValue) {
return viewValue.replace(/[^0-9]/g, '').slice(0, 15);
});
// This runs when the model gets updated on the scope directly and keeps our view in sync
ngModelCtrl.$render = function() {
$element.val($filter('tel')(ngModelCtrl.$viewValue, false));
};
$element.bind('change', listener);
$element.bind('keydown', function(event) {
var key = event.keyCode;
// If the keys include the CTRL, SHIFT, ALT, or META keys, or the arrow keys, do nothing.
// This lets us support copy and paste too
if (key == 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) {
return;
}
$browser.defer(listener); // Have to do this or changes don't get picked up properly
});
$element.bind('paste cut', function() {
$browser.defer(listener);
});
}
};
}
过滤器:
angular.module('app').filter('tel', function() {
return function(input) {
console.log(input);
if (!input) {
return '';
}
var value = input.toString().trim().replace(/^\+/, '');
if (value.match(/[^0-9]/)) {
return input;
}
// Phone number format:
// (AAA) EEE-TTTT xXXXXX...
var areaCode = value.slice(0, 3),
exchangeCode = value.slice(3, 6),
terminalCode = value.slice(6, 10),
extension = value.slice(10);
var result = '';
if (areaCode)
result += '(' + areaCode + ') ';
if (exchangeCode)
result += exchangeCode;
if (terminalCode)
result += '-' + terminalCode;
if (extension)
result += ' x' + extension;
return result;
};
});
问题:我可以通过什么方式更改此处的指令/过滤器以便能够进行内联编辑,而不是通过任何按键导致光标移动到输入的末尾?
最佳答案
由于您要动态更新输入中的文本,因此必须在更新之前存储光标位置,然后在更新后设置它。您还需要在光标位置添加 1 以考虑您要插入的字符。要实现此目的,您可以修改指令中的监听器函数,如下所示:
var listener = function() {
var cursorPos = $element[0].selectionStart + 1;
var value = $element.val().replace(/[^0-9]/g, '');
$element.val($filter('tel')(value, false));
$element[0].setSelectionRange(cursorPos, cursorPos);
};
由于 $element 是一个选择器,而不是实际的 HTML 元素本身,因此您需要引用第一个子元素(是 HTML 元素),这就是 $element[0] 的原因必须使用
。
关于javascript - 如何使过滤后的输入能够在其中进行编辑,而不是在最后进行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35989580/