代码: https://codepen.io/anon/pen/MmjgNR
问题:使用掩码编辑电话号码时,光标跳到末尾。
示例: (123) 456-7890
。当我尝试删除数字 5 并将其变为 7 时,光标立即移动到末尾:(123) 46-7890
。
如果您有任何疑问,请告诉我。
如果您投反对票,请注明原因,以便我纠正。
最佳答案
前言
我对 AngularJS 一无所知。我以前从未使用过它。这是我第一次看到它。我不知道它有什么作用。它所做的似乎只是添加一个巨大的抽象层来混淆代码,并证明增加对能够看穿这种混淆的“内部人员”的 IT 支出是合理的。如果没有 AngularJS,你的任务会简单得多。但是,正如我所说,我不知道 AngularJS 是什么,也不知道它做什么,所以我可能是错的。
基本解决方案
所报告行为的原因是您的脚本覆盖了 <input>
每次用户输入任何内容时的值。通常和基本的解决方案是在覆盖之前存储插入符位置 ( element.val(...)
):
var caretPosition = element[0].selectionStart;
...并立即恢复:
element[0].focus(); element[0].setSelectionRange(caretPosition, caretPosition);
您的脚本确实已经包含插入符号处理代码的 stub ,但它实际上什么也不做,它只是通过有意将插入符号移动到字符串末尾来重复其自己的意外行为。这种毫无意义的行为似乎是对任何重用该代码来编写自己的插入符处理代码的人的暗示。用我的代码替换该 stub 。
实例
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {$scope.name = 'Phone Number';});
app.directive('abcXyz', function($filter) {
var mobileFilter, mobileReverse;
mobileFilter = $filter('mobileFilter');
mobileReverse = $filter('mobileReverse');
return {
restrict: 'A',
require: 'ngModel',
link: function(scope, element, attrs, modelCtrl) {
var formatter, parser;
parser = function(value) {
var formatted;
formatted = mobileReverse(value);
/* solution */ var caretPosition = element[0].selectionStart;
/* solution */ if (caretPosition === 4) caretPosition += 3;
/* solution */ if (caretPosition === 10) ++caretPosition;
element.val(mobileFilter(formatted));
/* solution */ element[0].selectionStart = element[0].selectionEnd = caretPosition;
return formatted;
};
modelCtrl.$formatters.push(formatter);
return modelCtrl.$parsers.unshift(parser);
}
};
});
app.filter('mobileFilter', function() {
return function(value) {
var len, val;
if (!value) return;
val = value.toString().replace(/\D/g, "");
len = val.length;
if (len < 4) return val;
else if (3 < len && len < 7)
return "(" + (val.substr(0, 3)) + ") " + (val.substr(3));
else if (len > 6)
return "(" + (val.substr(0, 3)) + ") " + (val.substr(3, 3)) +
"-" + (val.substr(6, 4));
return value;
}
});
app.filter("mobileReverse", () => value => !!value && value.replace(/\D/g, "")
.substr(0, 10));
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.10/angular.min.js">
</script>
<html ng-app="plunker">
<body ng-controller="MainCtrl">
<p>{{name}}!</p>
<input type="tel" abc-xyz ng-model="formData.Phone" name="worktype"
maxlength="14" required="required" ng-pattern="(/[0-9-()]*[1-9][0-9-()]*/);"
autoComplete="off">
</body>
</html>
完整的解决方案
基本解决方案是一种改进,但它仍然并不完美。退格键失败。用户有时可以添加字母或删除强制破折号或括号。看来您需要一个复杂的插入符处理程序,它能够识别退格键、过滤器以及最后一个插入符位置,而不是一个,而是两个。我已经在基本示例中包含了简单的过滤器感知:
if (caretPosition === 4) caretPosition += 3;
if (caretPosition === 10) ++caretPosition;
但这还不够。目前,我无法向您提供完整的插入符号处理程序,但至少让我向您展示如何在 AngularJS 代码中包含退格意识:
- 添加属性
ng-keydown="registerBackspace($event)"
到 HTML 标签<input type="tel">
. - 替换您的
app.controller()
通过此调用进行调用:
app.controller('MainCtrl', function($scope) {
$scope.name = 'Phone Number';
$scope.registerBackspace = event => window.phoneBackspace = event.keyCode === 8;
});
- 现在你有一个全局变量
window.phoneBackspace
它指示在电话输入字段中按下的最后一个键是否是退格键(true
或false
)。
我不喜欢全局变量,但我对 AngularJS 一无所知,无法弄清楚如何使用它自己的函数传递此类信息(也不知道它是否允许这样做)。
最后一句话
如果您认为版主是白痴,请投票。
文献
关于javascript - 编辑电话号码时,光标跳到末尾,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43578019/