Solved

Serialize On-Key-Up Functions

Posted on 2016-10-15
3
59 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2
3 Comments
 
LVL 34

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 110

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 110

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

PeopleSoft Has Never Been Easier

PeopleSoft Adoption Made Smooth & Simple!

On-The-Job Training Is made Intuitive & Easy With WalkMe's On-Screen Guidance Tool.  Claim Your Free WalkMe Account Now

Question has a verified solution.

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

What is a Lightbox? A Lightbox is the effect you see when you click, for example, an image and the screen fades out and up pops the same image but in its full size dimensions. There are lots of Lightbox effects for jQuery. Problem is they are a…
PROBLEM: The other day I was working on adding an ajax request to a webpage that already had a dialog box on the page.  The dialog box was using relative positioning to be positioned next to a form field I had on the page.  Everything was working…
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…

705 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