12 июля 2012 г.

Какое в вашей форме поле ввода номера телефона?

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

Лично я считаю, что чем проще форма тем лучше - просто оставить текстовое поле и попробовать сделать одним из двух вариантов:
  1. Задать шаблон в виде регулярного выражения атрибута pattern текстового поля (доступны в HTML5);
  2. Уже отправляя или получая данные, удалять из введенного пользователем значение, к примеру, все не цифровые знаки, распарсивая и приводя к нужной форме.
Начиная с HTML5 тесктовое поле input обзавелось атрибут pattern и сделало возможным проверку введенного значения регулярным выраженнием. (Если бы я не написал регулярное выражение для проверки корректности ввода номера телефона, то и начинать этот пост не было бы смысла.)
Но чтобы распарсить номер телефона надо иметь  модель "типового" номера телефона.
Поэтому приведу сразу какими могут быть номера телефона:
  • С или без указания кода страны +7, 28 или просто 8;
  • С или без указания кода оператора или кода города - 3 цифры (В Санкт-Петербурге других не встречал);
  • 7 цифр номера телефона c пробелами, через тире или все слитно (что то вроде 123-45-67, 1234567, 123 45 67).
Согласно этой модели привожу регулярное выражение которое удовлетворяет озвученным требованиям:
\s*(?:\+\d{1,2}|\d)?\s*(?:\(\s*\d{3}\s*\)\s*|\-?\d{3}(?:\-|\s)?)?\d{3}(?:\-|\s)?\d{2}(?:\-|\s)?\d{2}\s*
Описание с комментарием:
/\s*
(?:\+\d{1,2}|\d)? # +7, +38 или 8 или ничего из этого
\s* # пробелы, или ничего
(?:\(\s*\d{3}\s*\)\s*|\-?\d{3}(?:\-|\s)?)? # код города или оператора, может быть даже в скобочках
\d{3} # 3 обязательных числа
(?:\-|\s)?
\d{2} # 2 обязательных числа
(?:\-|\s)?
\d{2} # 2 обязательных числа
\s*/x
Регулярное выражение это можно использовать для выделения номеров телефона в произвольном тексте (Например если стану sms-спамером и буду писать граббер номеров телефонов с сайтов). Модифицировав выражение, можно извлекать различные части номера телефона.

Чтобы проверить работоспособность регулярного выражения мне нужна была большая выборка примеров номеров телефонов согласно созданной модели номера телефона. Для этой цели я использовал программу генератор seo текстов Seo Anchor Generator. Программа Seo Anchor Generator позволяет по заданному шаблону составить выборку всех возможных комбинаций по заданному шаблону.
Пример используемого в программе шаблона:
{+{7|38}|8|}{| }{({ |}012{ |}){ |}|{-|}012{ |-|}|}345{-| |}67{-| |}89{ |}
Таким образом я собрал 2160 примеров правильных комбинаций написания телефонов.

Javascript код для тестирования:
function isFormattedTelefon(str){
    return /^\s*(?:\+\d{1,2}|\d)?\s*(?:\(\s*\d{3}\s*\)\s*|\-?\d{3}(?:\-|\s)?)?\d{3}(?:\-|\s)?\d{2}(?:\-|\s)?\d{2}\s*$/.test(str);
}
// массив с различными комбинациями написания одного телефона
var testArray2=[ "+7( 012 ) 345-67-89","+7( 012 ) 345-67-89", ... , "345 67-89" ];
for(var i=0, len=testArray2.length;i<len;i++){
    console.log("#%s is: %s",i,isFormattedTelefon(testArray2[i]) );
}
Осталось только обкатать все это дело.