Как сделать тип ввода = "tel" работать как type = "password"

При использовании тега input как type="tel" клавиатура на сенсорных устройствах соответствует типу ввода. Однако я хочу сохранить значение в теге input скрытым (как и с типом password). Обычное поведение будет заключаться в том, чтобы каждый символ был скрыт, когда пользователь печатает.

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

Это решение работает в большинстве браузеров, но не в IE.

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

Это решение работает не так, как ожидалось.

Есть ли способ выполнить то, что я пытаюсь сделать?

Ответ 1

Я знаю, что у этого уже есть приятное, работающее и принятое решение от jdgregson, но мне очень понравилась идея rybo111 настраиваемого решения на основе шрифтов и хотела попробовать.

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

Таким образом, если кто-то еще интересуется не-JS-решением с достойной поддержкой браузера и без известных проблем с ответом jdgregson, я создал простой шрифт для этого.

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

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

Шрифт можно использовать, включая dist/text-security.css либо из клонированного репо, либо из RawGit или что-то подобное. После включения css вы можете использовать шрифт, установив элемент font-family в '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>

В духе "polyfilling" -webkit-text-security я также добавил опции "круг" и "квадрат" для использования в качестве скрытого символа.

Я тестировал это с помощью Chrome v49, IE11, Microsoft Edge 25 и Chrome v50 на Android 5.0, в котором ввод типа "tel" открывает цифровую клавиатуру.

Ответ 2

Есть несколько способов сделать это:

1) -webkit-text-security

Самое элегантное решение - использовать встроенный стиль -webkit-text-security: circle; CSS, который предназначен именно для этого. К сожалению, это не переносимо и не поддерживается в IE или Edge. Вы можете найти обходной путь, чтобы получить поддержку в других браузерах здесь, если вы решите использовать этот подход.

2) Изменение типа пароля после его выбора

Как указывали Fidel90 и другие, вы можете попробовать переключить type="tel" на type="password" после того, как пользователь его выбрал. Я сделал скрипку этой идеи здесь. Он отлично работает в iOS, но в Android он не запускает первый кран, а затем запускается как клавиатура по умолчанию во втором кране.

3) Используя шрифт, который имеет только один символ

Еще одна идея, предложенная rybo111 в комментариях, которая была реализована noppa ниже, - это использовать шрифт, который имеет только символ точки паролей. Это, пожалуй, самое портативное и наименее хакерское решение. Один из недостатков заключается в том, что пользователь не может видеть характер, который они только что напечатали, как обычное поведение для современных мобильных полей пароля. Об этом говорится в здесь.

4) Скопируйте текст в скрытый ввод, когда пользователь набирает

Моя идея (ниже) заключается в том, чтобы использовать второй вход для хранения реального числа, а затем скрыть номер, когда пользователь его вводит. Обратите внимание, что это позволит отфильтровать все не номера телефонных номеров из последнего номера, хотя вы можете изменить эту переменную, чтобы принять все, что хотите.

Протестировано и работает над:

  • Safari iOS 9
  • 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>

Ответ 3

Я создал fiddle, который заменяет исходный tel на вход password, как только вы его фокусируете (jQuery необходимо ):

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>