Отформатируйте номер телефона по мере ввода (ххх) ххх - хххх

Я пишу обычай bindingHandler в knockout отформатировать телефонные номера (США) в следующем формате по мере их ввода.

(ххх) ххх - хххх

HTML-код...

 <input type="text" data-bind="phoneNumber: phone" />

И обязательный обработчик...

 ko.bindingHandlers.phoneNumber = {
    init: function(element, valueAccessor, allBindings) {
        ko.bindingHandlers.value.init(element,valueAccessor, allBindings);
        },    
    update: function(element, valueAccessor) {
        var phone = ko.utils.unwrapObservable(valueAccessor());
        if (!phone) return;
        var output;
        input = phone;
        input = input.replace(/[^0-9]/g, '');
        var areaCode = input.substr(0, 3);
        var nextThreeDigits = input.substr(3, 3);
        var lastFourDigits = input.substr(6, 4); 

        if (areaCode.length < 3) {
            output = "(" + areaCode;
        } else if (areaCode.length == 3 && nextThreeDigits.length < 3) {
          output = "(" + areaCode + ")" + " " + nextThreeDigits;
        } else if (areaCode.length == 3 && nextThreeDigits.length == 3) {
          output = "(" + areaCode + ")" + " " + nextThreeDigits + "-" + lastFourDigits;
        }

        var phoneObs = valueAccessor();
        phoneObs(output);
    }
};

Следующий код работает как положено. Единственный способ такого подхода - удаление номера телефона с помощьюbackspace, Как только он удаляет последние четыре цифры и нажимает - он не может удалить - ни ( ) так как я динамически добавляю - а также ( ) на основе длины. Я могу использовать клавиши со стрелками или щелкнуть перед этими символами и начать удаление, или я могу выделить текстовое поле и удалить все сразу. Но мне нужно иметь возможность удалять символы путем возврата или симуляции и динамически удалять их из кода.

Любые предложения о том, как я могу решить эту проблему?

ОБНОВИТЬ

Вот JSFIDDLE. Единственная проблема, которая у меня возникла с этой скрипкой, это то, что она не обновляет значения при изменении значения. Он обновляется только в том случае, если вы нажмете ввод или выйдите из текстового поля. Не уверен, что я что-то упустил...

Я обновил свою логику, чтобы учесть проблему, с которой я столкнулся, которая устранена. Но я заметил, что у обеих логик есть еще одна проблема.

Если у меня есть номер телефона

(123) 456-7890

Если я уберу 1 из кода города, курсор не останется на том же месте (до 2). Он перемещается в конец строки, и все сдвигается на одну цифру вниз.

if (areaCode.length <= 3 && nextThreeDigits == "") {
    output = "(" + areaCode;
} else if (areaCode.length == 3 && nextThreeDigits < 3) {
    output = "(" + areaCode + ")" + " " + nextThreeDigits;
} else if (areaCode.length == 3 && nextThreeDigits.length <= 3 && lastFourDigits.length == "") {
    output = "(" + areaCode + ")" + " " + nextThreeDigits;
} else if (areaCode.length == 3 && nextThreeDigits.length == 3 && lastFourDigits.length <= 4) {
  output = "(" + areaCode + ")" + " " + nextThreeDigits + "-" + lastFourDigits;
}

2 ответа

Решение

Как насчет использования маски ввода (у jasny есть хорошая http://www.jasny.net/bootstrap/) и пользовательской привязки.

Вот скрипка, где я это сделал. http://jsfiddle.net/vL59q8e1/2/

вот javascript для привязки

ko.bindingHandlers.inputmask = {
  init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
    ko.bindingHandlers.value.init(element, valueAccessor, allBindings);

     $(element).inputmask({
        mask: '(999) 999-9999'
        });
  },
  update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
    var value = valueAccessor();
      }
};

Самый простой выход - добавить метки после достаточного количества символов, чтобы курсор всегда касался цифры. Поскольку в текстовое поле добавляются эти символы, эта ошибка возникает при добавлении нечисловых символов. Например, ошибка, которую вы упомянули с "-", также возникает, когда у вас есть только 3 числа и вы пытаетесь удалить один номер (он удаляет пробел, а затем добавляет пробел обратно). например: если 3 числа, (123 и это добавляет) после того, как они вводят в четвертом.

Другой способ - сохранить input = input.replace(/[^0-9]/g, ''); в поле данных на элементе и пропустите весь выходной каскад, если число не изменилось. например:

input = input.replace(/[^0-9]/g, '');
if(element.phone == input){ return; }
element.phone = input;
Другие вопросы по тегам