4
\$\begingroup\$

I created a form that formats phone numbers, allows only allowable keys to be pressed, and converts a lettered entry into its corresponding phone keypad number. Is there some cleanup or better coding that can be done? There is no business need for international phone numbers as it is a local business.

function pageLoad() {
 $(".PhoneSelection").keypress(function (e) {
 // Only allow number entry
 var regex = new RegExp("^[0-9]+$");
 var key = String.fromCharCode(!e.charCode ? e.which : e.charCode);
 if (!regex.test(key)) {
 // If not a number, is it a letter?
 var regex2 = new RegExp("^[A-Za-z]+$");
 if (regex2.test(key)) {
 // Convert the letter typed to the number on the phone keypad
 $(this).val($(this).val() + letterPos(key));
 return false;
 }
 else { return false; }
 }
 });
 $(".PhoneNum").text(function (i, text) {
 // returns (999) 555-1234 from 9995551234
 return text.replace(/(\d{3})?(\d{3})(\d{4})$/,
 function (0,ドル 1,ドル 2,ドル 3ドル) {
 var formatted = ""; if (1ドル) { formatted += "(" + 1ドル + ") "; } if (2ドル) { formatted += 2ドル + "-"; } if (3ドル) { formatted += 3ドル; } return formatted;
 }
 );
 });
}
function letterPos(val) {
 var alphaMap = { 'ABC': '2', 'DEF': '3', 'GHI': '4', 'JKL': '5', 'MNO': '6', 'PQRS': '7', 'TUV': '8', 'WXYZ': '9' };
 var number = "";
 $.each(alphaMap, function (key, value) {
 if (key.toLowerCase().indexOf(val.toLowerCase()) > -1)
 { number = value; }
 });
 return number;
}

Here is how it is consumed in the view form:

<div class='PhoneNum'>9995551234</div>
<input id="ContactPhone" class="PhoneSelection nextField" type="text" placeholder="Phone" value="9995551234"></input>

Results on display:

(999) 555-1234

Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Sep 10, 2015 at 20:17
\$\endgroup\$
6
  • \$\begingroup\$ I can't think of any situation where converting alphabet characters into digits would improve the user's experience. Block non-digits if you must, but don't convert them into something else. Aren't people even allowed to put spaces between numbers? What if they have to add an extension number? (Also, you should be using <input type="tel" ...> for phone numbers.) \$\endgroup\$ Commented Sep 10, 2015 at 20:28
  • \$\begingroup\$ Thanks. No spaces allowed on entry. But will allow 555-CODE and it immediately converts the letters to the numbers to be saved in the DB. Extensions are in another input. The entry is done by well trained inhouse end users, not the general public (haha). The type=tel caused issues in iPad Safari \$\endgroup\$ Commented Sep 10, 2015 at 21:32
  • \$\begingroup\$ For example, suppose you type in 1-800-CALL-SAUL and the input field comes up with 180022558285. In terms of visual feedback, this is completely useless. You're not only displaying different characters from what was typed in, but the number of characters is also different. And on top of that, your chance of detecting the typo in the ninth digit is almost zero. I'm sorry, but this whole idea is just ghastly. You would be better off sorting out your issues with iPads than going down this route. \$\endgroup\$ Commented Sep 10, 2015 at 21:55
  • \$\begingroup\$ Some people prefer digits to letters on the phone. Making this completely useful! The input is only shown when editing. On save, the div displays the formatted number for the end user enjoyment. \$\endgroup\$ Commented Sep 10, 2015 at 22:37
  • \$\begingroup\$ I have addressed the iPad issue by presenting my own numeric keypad instead of having the large keyboard appear in the wrong layout, but that's another topic ;) \$\endgroup\$ Commented Sep 10, 2015 at 22:47

1 Answer 1

1
\$\begingroup\$

Here are some points regarding your code:

  • Decide on a style regarding the if-statements, and stick to it. Don't collapse else statements like the } else { return false; }
  • Avoid multiple statements on one line, like the var formatted = ...
  • When both branches does the same, extract the return outside of it
  • You can inline regexp's when they are simple, (see Detect numbers or letters with jquery/javascript)
  • Additionaly when using regexp against a single key you don't need to use anchors or multiple match options. Instead of ^[0-9]+$, simply use [0-9]
  • When replacing text you can enter the replacement text directly, instead of using a function. And the function you use is somewhat complicated
  • Edit: Switched to a simpler letterToNumber() using the lowercase character code (with the code of a subtracted) to index into a numbered variant of the alphabet.

In this jsfiddle I've corrected for my comments:

$(".PhoneSelection").keypress(function (e) {
 // Only allow number entry
 var key = String.fromCharCode(!e.charCode ? e.which : e.charCode);
 if (!/[0-9]/.test(key)) {
 // If not a number, is it a letter?
 if (/[A-za-z]/.test(key)) {
 // Convert the letter typed to the number on the phone keypad
 $(this).val($(this).val() + letterToNumber(key));
 }
 return false;
 }
});
$(".PhoneNum").text(function (i, text) {
 // returns (999) 555-1234 from 9995551234
 return text.replace(/(\d{3})?(\d{3})(\d{4})$/, "(1ドル) 2ドル-3ドル")
 .replace(/\(\) /, "");
});
function letterToNumber(val) {
 charIndex = val.toLowerCase().charCodeAt(0) - 97;
 return "22233344455566677778889999"[charIndex];
}

However there are still some comments to be made:

  • To remove illegal characters, i.e. non-letters, and transforming letters to numbers, whilst you are typing is frowned upon in some camps. It would be better to present a normalised number next to the input field, or after it has been submitted
  • The transformation of the input also removes the visual feedback of whether the user has entered the correct telephone number
  • Your code as it stands does not connect the input field and the output field, which might be by design, but it threw me of whilst testing it for a while
  • You are bypassing backspacing and/or movement of cursor. As an example start entering a number using letters, i.e. xxjjjmmmm, and then you realise that you forgot the first x, so you move the cursor over there and enter it x. Now the code will add that at the end, bummer...

Edit: In original research I found Code golf: Letters in phone numbers and How to convert an alphanumeric phone number to digits), where the shortest, not very readable version of alternateLetterToNumber() is (with addition of lowercasing the character):

function alternateLetterToNumber(y) {
 y = y.toLowerCase().charCodeAt(0) - 91;
 return y > 27 ? 9 : y > 24 ? 8 : y > 20 ? 7 : ~~ (y / 3);
}
answered Sep 14, 2015 at 14:54
\$\endgroup\$
0

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.