Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make input type="tel" work as type="password"

When using the input tag as type="tel" the keyboard on touch devices correspond with the type of input box. However, I wish to keep the value in the input tag hidden (as with the password type). The normal behaviour would be to have each character hidden as the user is typing.

<input type="tel">
input [type="tel"] {
    -webkit-text-security: disc;
}

This solution works in most browsers, but not in IE.

<input type="password" pattern="[0-9]*" inputmode="numeric">

This solution doesn't work as expected.

Is there any way to accomplish what i'm trying to do?

like image 624
CodeMan Avatar asked Apr 29 '16 10:04

CodeMan


People also ask

How do you enter an input type password?

<input> elements of type password provide a way for the user to securely enter a password. The element is presented as a one-line plain text editor control in which the text is obscured so that it cannot be read, usually by replacing each character with a symbol such as the asterisk ("*") or a dot ("•").

How do you input a phone number in HTML?

The <input type="tel"> defines a field for entering a telephone number. Note: Browsers that do not support "tel" fall back to being a standard "text" input. Tip: Always add the <label> tag for best accessibility practices!

How do I change my password style in HTML?

You can't change the password masking character in the standard password field. You can fake it with a textbox, but it makes for a weak security model because you don't get the protection you do from the password textbox.


4 Answers

Update 2020-06-19

If all you're after is better usability for "pin" inputs, I'd now suggest sticking with the inputmode attribute that didn't work for OP in 2016. The browser support is still quite limited, but it's finally working at least on iOS Safari and as a solution it's much simpler and possibly more secure than avoiding input type="password" altoghether.

<input type="password" inputmode="tel" />

So for OP's specific use-case I'd now recommend the above even though browser support is not 100%. I know some people coming to this post are actually looking for type="password" alternatives for other reasons, like to circumvent password autocomplete, and my original answer below may still help them.

Also note that my password font project that I recommend below has had a few updates since I gave this answer and has a bit different installation instructions now.


Original answer

I know this already has a nice, working and accepted solution from jdgregson, but I really liked rybo111's idea of a custom font based solution and wanted to give it a try.

The idea is to create a font that only contains circles so that when the font family is applied to the input element, seemingly no characters are displayed.

So in case anyone's still interested in a non-JS solution with decent browser support and without the known issues with jdgregson's answer, I created a simple font for this.

GitHub repo: https://github.com/noppa/text-security

JSFiddle demo: https://jsfiddle.net/449Lamue/6/

The font can be used by including the dist/text-security.css either from cloned repo or from RawGit or something similar. After including the css you can use the font by setting the element's font-family to 'text-security-disc'.

<link rel="stylesheet" type="text/css" href="https://cdn.rawgit.com/noppa/text-security/master/dist/text-security.css">
<style>
     input [type="tel"] {
         font-family: "text-security-disc";
         -webkit-text-security: disc;
     }
</style>

In the spirit of "polyfilling" the -webkit-text-security, I also added the "circle" and "square" options to use as the hiding symbol.

I've tested this with Chrome v49, IE11, Microsoft Edge 25 and Chrome v50 on Android 5.0, in which the input of type "tel" opens the number keypad.

like image 58
noppa Avatar answered Oct 05 '22 06:10

noppa


There are several ways you can accomplish this:

1) -webkit-text-security

The most elegant solution is to use the builtin -webkit-text-security: circle; CSS style which is intended for this very thing. Unfortunately that is not portable, and isn't supported on IE or Edge. You can find a workaround to get support on other browsers here if you choose to use this approach.

2) Changing the type to password after it is selected

As Fidel90 and others have pointed out, you could try switching the type="tel" to type="password" after the user has selected it. I made a fiddle of that idea here. It works perfectly in iOS, but in Android it fails to launch the first tap, and then launches as the default keyboard on the second tap.

3) Using a font that has only one character

Another idea suggested by rybo111 in the comments which has been implemented by noppa below is to use a font that has only a password dot character. This is likely the most portable and least hackish solution. One drawback is that the user cannot see the character they just typed as is the usual behaviour for modern mobile password fields. A comprehensive fiddle of this is posted here.

4) Copy the text into a hidden input as the user types

My idea (below) is to use a second input to store the real number and then hide the number as the user types it. Note that this will filter all non-phone number characters from the final number, though you can modify the variable to accept whatever you want.

Tested and works on:

  • iOS 9 Safari
  • Android 6.0 Chrome
  • Internet Explorer 11
  • FireFox 45
  • Chrome 50
  • Opera 36
  • Microsoft Edge 25

var BACKSPACE_CHARS = [8, 46, 229];

function hideNumber(fakeInput, event) {
    var hideChar = '*';
    // add characters that you want to appear in the final number to this
    // string -- leave the string empty to allow all characters
    var phoneChars = '0123456789()-+';
    var keyCode = event.keyCode || event.charCode;
    var key = String.fromCharCode(keyCode)+'';
    var realInput = document.getElementById("hidden-number");
    var len = fakeInput.value.length;
    fakeInput.value = '';
    if(phoneChars.indexOf(key) > -1 || !phoneChars.length) {
        realInput.value += key;
    } else {
        if(BACKSPACE_CHARS.indexOf(keyCode) < 0) {
            --len;
        }
    }
    for(var i=0; i<len; i++) { // no String.repeat() in IE :(
        fakeInput.value += hideChar;
    }
    updateDisplay();
}

function backspace(event) {
    var keyCode = event.keyCode || event.charCode;
    var realInput = document.getElementById("hidden-number");
    if(BACKSPACE_CHARS.indexOf(keyCode) > -1) { // backspace or delete
        var len = realInput.value.length;
        realInput.value = realInput.value.slice(0, len-1);
    } 
    updateDisplay();
}

function updateDisplay() {
    var realInput = document.getElementById("hidden-number");
    var display = document.getElementById("display");
    display.innerHTML = realInput.value || '';
}
<input type="tel" name="number" id="number-hider" onkeypress="hideNumber(this, event)" onkeydown="backspace(event)" onblur="hideNumber(this)">
<input type="hidden" name="realnumber" id="hidden-number">
<div id="display"></div>

Known bugs:

  • If a user taps or clicks in the middle of the text box and types or backspaces, the characters will be added or deleted from the end of the real number.
like image 20
jdgregson Avatar answered Oct 05 '22 07:10

jdgregson


Using noppa's answer and his GitHub font and jdgregson's answer, here's a turnkey CSS solution (fiddle):

@font-face {
  font-family: "password-mask";
  src: url(data:font/woff;charset:utf-8;base64,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) format("woff");
}
.numeric-password {
  font-family: password-mask;
}
.numeric-password::placeholder {
  font-family: initial;
}
<input type="tel" class="numeric-password" placeholder="test" />

To support older iOS and Android devices, you would just need to add another data URI font-face definition with the ttf file for the password mask font. Same for IE with the eot font file but most modern browsers support woff and should work with this CSS.

like image 27
Alex W Avatar answered Oct 05 '22 06:10

Alex W


I created a fiddle that replaces the initial tel with an password input as soon as you focus it (jQuery needed):

var value = "",
	isPWD = false;

$('#wrap')
  .on("focus", "#input", function() {
  	if (!isPWD) {
      var pass = $('<input id="input" type="password">');
      $(this).replaceWith(pass);
      isPWD = true;
      pass.focus();
    }    
  })
  .on("change", "#input", function() {
  	value = $(this).val();
    $("#span").text(" = " + value);
  })
  .on("blur", "#input", function() {
  	var tel = $('<input id="input" type="tel">');
    $(this).replaceWith(tel);
    isPWD = false;
  });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="wrap">
  <input id="input" type="tel"/>
  <span id="span"></span>
</div>

I did not test this on a mobile device so far so I'm not sure if bringing the numeric pad up to the user works in every case.

EDIT: At least my mobile IE did not show a numeric pad but only the standard text field.

like image 38
Fidel90 Avatar answered Oct 05 '22 06:10

Fidel90