Reputation: 21
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
Reputation: 147453
Consider the following algorithm:
On input:
get the caret position,
get the number of characters added or deleted
If added,
If deleted
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