编辑电话号码时,光标跳到最后

时间:2017-04-24 00:29:37

标签: javascript html angularjs

代码: https://codepen.io/anon/pen/MmjgNR
问题:使用遮罩编辑电话号码时,光标跳到最后 示例: (123) 456-7890。当我尝试删除数字5并使其成为7时,光标会立即移动到结尾:(123) 46-7890

如果您有任何疑问,请与我联系 如果你投票,请提及原因,以便我能够纠正。

1 个答案:

答案 0 :(得分:1)

前言

我完全不知道AngularJS。我之前从未使用过它。这是我第一次看到它。我不知道它做了什么。它似乎所做的就是添加一个庞大的抽象层来混淆代码,并证明增加了对可以看透这种混淆的“内部人”的IT支出。没有AngularJS,你的任务会更简单。但是,正如我所说,我不知道AngularJS是什么,也不知道它是做什么的,所以我可能错了。

基本解决方案

报告行为的原因是每次用户键入任何内容时,您的脚本都会覆盖<input>值。通常和基本的解决方案是在覆盖行为(element.val(...))之前存储插入位置

var caretPosition = element[0].selectionStart;

...并在以下情况后立即恢复:

element[0].focus(); element[0].setSelectionRange(caretPosition, caretPosition);

你的脚本确实包含一个插入处理代码的存根,但它确实没有任何内容,它只是通过故意将插入符号移动到字符串的末尾而重复其自己的意外行为。这种毫无意义的行为似乎暗示了任何重用代码来编写自己的插入处理代码的人。用我的代码替换该存根。

实例

&#13;
&#13;
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));
&#13;
<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>
&#13;
&#13;
&#13;

完整的解决方案

基本解决方案是改进,但不完美。它失败了退格。用户有时可以添加字母或删除强制破折号或括号。您似乎需要一个复杂的插入处理程序,它具有退格,过滤器的意识,而不是两个最后一个插入位置。我已经在基本示例中包含了简单的过滤器感知:

if (caretPosition === 4) caretPosition += 3;
if (caretPosition === 10) ++caretPosition;

但这还不够。此时,我无法向您提供完整的插入处理程序,但至少让我告诉您如何在AngularJS代码中包含退格感知功能:

  1. 将属性ng-keydown="registerBackspace($event)"添加到HTML代码<input type="tel">
  2. 使用此电话替换您的app.controller()来电:
  3. app.controller('MainCtrl', function($scope) {
    $scope.name = 'Phone Number';
    $scope.registerBackspace = event => window.phoneBackspace = event.keyCode === 8;
    });
    1. 现在您有一个全局变量window.phoneBackspace,它指示在电话输入字段中按下的最后一个键是退格键(true还是false)。
    2. 我不喜欢全局变量,但我对AngularJS一无所知,想知道如何使用自己的函数传递这些信息(也不知道它是否允许这样做)。

      最后的话

      如果您认为主持人是白痴,请立即投票。

      文献