Solved

Serialize On-Key-Up Functions

Posted on 2016-10-15
3
36 Views
Last Modified: 2016-10-25
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
Comment
Question by:Ray Paseur
  • 2
3 Comments
 
LVL 33

Accepted Solution

by:
ste5an earned 500 total points
ID: 41845161
What should happen when the input is pasted into your field? I think you should take a look at the change event instead.
0
 
LVL 108

Author Comment

by:Ray Paseur
ID: 41846148
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
 
LVL 108

Assisted Solution

by:Ray Paseur
Ray Paseur earned 0 total points
ID: 41858586
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

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
jQuery Animation faster 5 42
Split in Javascript 5 31
How to set a countdown by not using the PC time in PHP 36 44
Recordset containing single quotes 8 22
Introduction Got endorsements from your clients?  Great!  There is almost nothing better than word-of-mouth advertising.  But how can you do that on the internet?  Sure you can make a page for endorsement quotations and list them all, but who is …
International Data Corporation (IDC) prognosticates that before the current the year gets over disbursing on IT framework products to be sent in cloud environs will be $37.1B.
The viewer will learn how to dynamically set the form action using jQuery.
The viewer will learn the basics of jQuery including how to code hide show and toggles. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery…

910 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

23 Experts available now in Live!

Get 1:1 Help Now