Subhanu Sankar Roy
Subhanu Sankar Roy

Reputation: 21

How to hide text in input field as you type each character?

I have an input field, that basically takes a confirmation code(alphanumerical) while logging into an application. I want to implement the below functionality: when you type each character, it appears in the text field for a fraction of time(say 1 second), and then it becomes an asterisk.

The reason I want this? This helps the user know what character he/she is typing in the input field and doesn't compromise on the security aspects.

What I have tried? I tried to make the input field type as "password" but that makes the character typed into an asterisk instantly. I don't want this, I want it to show for 1s then become an asterisk.

<input type=password placeholder="Please enter your alphanumerical code" /> 

Note: I don't want a display/hide toggle button implementation of the above, as I already am aware of that, and have seen answers about that, but it's not my intended implementation

I am working on a reactJS application, so an implementation based on react, JS, JSX, HTML, etc. would be preferred. Thanks :)

P.S This is my first question on stack overflow and I am very new to react, so please pardon me for any mistakes. Feel free to ask any doubts/queries you have regarding the question.

Upvotes: 2

Views: 2739

Answers (1)

RobG
RobG

Reputation: 147453

Consider the following algorithm:

On input:

  1. get the caret position,

  2. get the number of characters added or deleted

  3. If added,

    • get the added characters
    • insert them in the shaddow string // to do
    • after a defined time, or on next input, replace added characters with asterisks (*)
  4. If deleted

  • delete number deleted to the right of character pos in the shadow string

Masking the characters runs on a timeout. If something is entered before the timeout runs, the timeout is cancelled and the characters masked immediately. If you type really quickly, multiple characters are visible for a very short time. If multiple characters are pasted, they are all displayed for the timeout lag.

Here's an implementation:

let maskInput = (function() {
  // Keep reference to timeout
  let timeoutRef = null;
  // Set field to all asterisks, keep cursor at current position
  function blankField(el) {
    // Cancel timeout if there is one
    if (timeoutRef) {
      clearTimeout(timeoutRef);
      timeoutRef = null;
    }
    // Get cursor position
    let cursorPos = el.selectionStart;
    // Mask values
    el.value = el.value.replace(/./g, '*');
    // Put cursor back in position
    el.setSelectionRange(cursorPos, cursorPos);
  }

  return function (el) {
    // Get the shaddow element
    let inp = document.getElementById('i1');
    // Get current cursor position
    let cursorPos = el.selectionStart;
    // Get number of characters added
    let numAdded = el.value.length - inp.value.length;
    // If characters were added
    if (numAdded > 0) {
      // Get characters added
      let charsAdded = el.value.slice(cursorPos - numAdded, cursorPos);
      // Insert characaters in inp
      let insertIdx = cursorPos - numAdded;
      inp.value = inp.value.substring(0, insertIdx) +
                 charsAdded +
                 inp.value.substring(insertIdx, inp.value.length);
      timeoutRef = setTimeout(() => blankField(el), 250);
    // If characters were deleted, delete numAdded characters
    // to the right of the current cursor position in inp
    } else if (numAdded < 0) {
      inp.value = inp.value.substring(0, cursorPos) +
                  inp.value.substring(cursorPos - numAdded, inp.value.length);
    }
  }
}());
<input id="i0" oninput="maskInput(this)">Enter text<br>
<input id="i1" readonly>Shaddow text

This assumes that the listener is on an input element, plus the ID of the shadow input and masking character are hard coded. Both can easily be dynamic or set in a parameter object or similar.

Upvotes: 2

Related Questions