Improve company productivity with a Business Account.Sign Up

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 74
  • Last Modified:

Serialize On-Key-Up Functions

I'm working on a half-baked jQuery script that uses .on("keyup", function(event){ to copy some data from an input control to JS variables and other selected form elements.  The objective here is to mimic the Apple way of handling passwords, obscuring all the characters except the last one typed.  I'm testing in Chrome; have not tried other browsers yet.

I've discovered that I can type fast enough that my fingers outrun the browser's ability to complete the function, resulting in goofy information as the event objects race forward.  The observed effect is that the number of characters submitted is correct, but some characters are duplicated and others may be lost.

You can see it in action here (type fast!)
https://iconoun.com/demo/password_reveal_intype.php

Is there a way to serialize these requests, or otherwise cause the on-key-up function to run to completion for each character that is entered?  Or is there a better way to process each keystroke as quickly as it occurs?
<?php // demo/password_reveal_intype.php
/**
 * Demonstrate how to reveal only the last character of a password
 * as it is being typed, similar to the way Apple devices work
 */
error_reporting(E_ALL);

$get = NULL;
if (!empty($_GET)) $get = print_r($_GET, TRUE);

$html = <<<EOD
<!DOCTYPE html>
<!-- demo/password_reveal_intype.html -->
<html dir="ltr" lang="en-US">
<head>
<meta charset="utf-8" />
<meta name="robots" content="noindex, nofollow" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">

<style type="text/css">
/* Stype Sheet Here */
</style>

<script type="text/javascript" src="https://code.jquery.com/jquery-latest.min.js"></script>
<script>
$(document).ready(function(){

    $("#pwinput").focus();

    $("#pwinput").on("keyup", function(event){
        if (event.which == 09) return;

        var star = "*";
        var text = "";
        var pwrd = $("#pwinput").val();
        var long = pwrd.length - 1;
        var char = pwrd.substr(long,1);
        var hidn = $("#pwhiddn").val();

        if (event.which == 08){
            var hlen = hidn.length - 1;
            if (hlen >= 0){
                $("#pwhiddn").val(hidn.substr(0,hlen));
            }
        }
        else{
            $("#pwhiddn").val(hidn + char);
        }

        if (pwrd){
            text = star.repeat(long) + char;
        }

        $("#pwinput").val(text);
    });
});
</script>

<title>HTML5 Page With jQuery in UTF-8 Encoding</title>
</head>
<body>

<noscript>Your browsing experience will be much better with JavaScript enabled!</noscript>

<p>
From the last request: $get
<form>
<input name="pw_4_display" id="pwinput" placeholder="Enter Password" type="text" autocomplete="off" />
<input name="pw_4_action"  id="pwhiddn" type="hidden" />
<br>
<input type="submit" />
</form>
</p>

</body>
</html>
EOD;

echo $html;

Open in new window

Thanks and regards, Ray
0
Ray Paseur
Asked:
Ray Paseur
  • 2
2 Solutions
 
ste5anSenior DeveloperCommented:
What should happen when the input is pasted into your field? I think you should take a look at the change event instead.
0
 
Ray PaseurAuthor Commented:
I've modified the script somewhat, and by using separate handlers for paste, keyup, and keypress, the race condition is gone, and I can type as fast as I want.  The only remaining hurdle is IE11 or below, where all I can do is shake my head and wonder what the Microsoft team is thinking.  IE handles the form submit correctly, but does not display anything in the visual input control field.
<?php // demo/password_reveal_intype.php
/**
 * Demonstrate how to reveal only the last character of a password
 * as it is being typed, similar to the way Apple devices work
 *
 * Using paste to collect input strings
 * Using keypress to collect input characters
 * Using keyup to handle backspace
 */
error_reporting(E_ALL);

$req = NULL;
if (!empty($_POST)) $req = print_r($_POST, TRUE);

$html = <<<EOD
<!DOCTYPE html>
<!-- demo/password_reveal_intype.html -->
<html dir="ltr" lang="en-US">
<head>
<meta charset="utf-8" />
<meta name="robots" content="noindex, nofollow" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">

<style type="text/css">
/* Stype Sheet Here */
</style>

<script type="text/javascript" src="https://code.jquery.com/jquery-latest.min.js"></script>
<script>
/* Clear Extraneous Display-Only Input on Submit */
function pw_clear_input(){
    $("#pwinput").remove();
}

$(document).ready(function(){

    /* Only One Input Control on this Page */
    $("#pwinput").focus();

    /* Handle "Paste" Functionality */
    $("#pwinput").on("paste", function(event){
        var star = "*";
        var text = "";
        var long = 0;
        var char = "?";

        event.preventDefault();

        /* The Prior Input, if Any */
        var hidn = $("#pwhiddn").val();

        /* Capture Clipboard before Paste Finishes */
        var clip = undefined;

        if (window.clipboardData && window.clipboardData.getData){ // IE
            clip = window.clipboardData.getData('Text');
        }
        else{
            var clipboardData = (event.originalEvent || event).clipboardData;
            if (clipboardData && clipboardData.getData){
                clip = clipboardData.getData('text/plain');
            }
        }

        /* Concatenate Clipboard to Existing Input (if any) and Save in Hidden Element */
        hidn = hidn + clip;
        $("#pwhiddn").val(hidn);

        /* Create Obscured Password - Last Character Showing */
        long = hidn.length - 1;
        char = hidn.substr(long,1);
        text = star.repeat(long) + char;

        $("#pwinput").val(text);
    });

    /* Handle Each New Character of Input */
    $("#pwinput").on("keypress", function(event){
        var star = "*";
        var text = "";
        var long = 0;
        var char = "?";

        // Ignore Backspace, Return (Enter), End, Delete Keys */
        if (event.which == 8)  return;
        if (event.which == 10) return;
        if (event.which == 13) return;
        if (event.which == 35) return;
        if (event.which == 46) return;

        event.preventDefault();

        var hidn = $("#pwhiddn").val();
        var char = String.fromCharCode(event.which);

        /* Concatenate Character to Existing Input (if any) and Save in Hidden Element */
        hidn = hidn + char;
        $("#pwhiddn").val(hidn);

        /* Create Obscured Password - Last Character Showing */
        long = hidn.length - 1;
        char = hidn.substr(long,1);
        text = star.repeat(long) + char;

        $("#pwinput").val(text);
    });

    /* Handle Backspace Character(s) */
    $("#pwinput").on("keyup", function(event){
        var star = "*";
        var text = "";
        var long = 0;
        var char = "?";

        if (event.which != 8) return; // Only handle backspace

        event.preventDefault();

        /* Remove Character from Existing Input (if any) and Save in Hidden Element */
        var hidn = $("#pwhiddn").val();
        long = hidn.length - 1;
        if (long >= 0){
            hidn = hidn.substr(0,long);
            $("#pwhiddn").val(hidn);
        }

        /* Create Obscured Password - Only last Character Showing */
        long = hidn.length - 1;
        if (long >= 0){
            char = hidn.substr(long,1);
            text = star.repeat(long) + char;
        }

        $("#pwinput").val(text);
    });

});
</script>

<title>HTML5 Page With jQuery in UTF-8 Encoding</title>
</head>
<body>

<noscript>Your browsing experience will be much better with JavaScript enabled!</noscript>

<p>
Arguments from the last request: $req
<form id="pwform" method="post" onSubmit="return pw_clear_input()">
<input name="pw_4_display" id="pwinput" placeholder="Enter Password" type="text" autocomplete="off" />
<input name="pw_4_action"  id="pwhiddn" type="hidden" />
<br>
<input type="submit" />
</form>
</p>

</body>
</html>
EOD;

echo $html;

Open in new window

0
 
Ray PaseurAuthor Commented:
The question and suggestions here led to an update to this article.  See Example #3.
https://www.experts-exchange.com/articles/19779/Passwords-in-HTML-Forms-Allow-the-Client-to-Show-or-Hide.html
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now