Cannot change input field type in IE 8

Hi Guys,
I’m working on masking some input fields, for the credit card field requirement is that characters should be masked while you are typing in the field and also on focus out. So ofcourse I achieved that easily by converting the field to type password. But the next requirement is that when the user clicks back in the field (focus), it should should show the value but as soon as the user starts typing, the value should be masked. I’ve tried all sorts of things but I was finally stuck because of IE 8 , as it won’t let me change the type. Does anyone have a solution that will work in all browsers including IE 8?

Thank you!

Hi,

This would be how I would do it.

Does that work on IE8?
I don’t have IE installed, so can’t test.

<!DOCTYPE HTML>
<html>
  <head>
    <meta charset="utf-8">
    <title>Show password field on focus</title>
  </head>

  <body>
    <input id="maskedField" data-value="" type="password"/>

    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
    <script>
      function checkType(field){
        if(field.attr("type") === "text"){
          field.attr("type", "password");
        }
      }

      $("#maskedField").on("focus", function(){
        $(this).attr("type", "text");
        $(this).val($(this).data("value"));
      })

      $("#maskedField").on("blur", function(){
        $(this).attr("type", "password");
      });

      $("#maskedField").keyup(function(e) {
        checkType($(this));
        $(this).data("value", this.value);
      });
    </script>
  </body>
</html>

if you can’t change the type just change the whole input field :wink:

(function() {
    var keyup = false;
    $('form').on('blur', 'input[type=text]', function() {
        var $this = $(this),
            val = $this.val(),
            $pass = $('<input class="pwd" type="password" />');
        $pass.insertAfter(this);
        $this.remove();
        if (keyup) $pass.focus();
        keyup = false;
        $pass.val(val).addClass('ready');
    }).on('keyup', 'input[type=text]', function() {
        keyup = true;
        $(this).blur();
    }).on('focus', 'input[type=password].ready', function() {
        var $this = $(this),
            val = $this.val(),
            $txt = $('<input type="text" />');
        $txt.insertAfter(this);
        $this.remove();
        $txt.focus().val(val);
    });
})();

you will obviously need some more precise fields targeting and probably ignore some keyCodes on the keyup

jScript (IE8 and earlier) doesn’t allow you to change the type of an input after you create it.

As you are already using jQuery the jQuery solution already provided is the simplest solution.

For anyone who has this problem who isn’t using jQuery see http://javascriptexample.net/domform08.php for how to do it with plain J(ava)Script (JScript for IE8 and earlier and JavaScript for modern browsers)

Thanks for your replies, this didn’t work in IE8, I’m also using an older version of jQuery 1.4.2, right now I don’t have the flexibility to update it for the application. So sorry guys but none of the above have worked for me so far

So replace the .on() calls with deprecated .delegate() calls instead as that’s what older versions of jQuery used that .on() replaced in version 1.7

I like this solution, is it possible this can be modified to work in IE8 and jQuery 1.4.2 ?

This works perfect in chrome and firefox but I cannot get it to work with IE8 with jQuery 1.4.2

.on() was introduced in jQuery 1.7 as a replacement for .delegate() so with 1.4 you have to use ,delegate() instead.

Thanks for all your help so far guys, if the above is true then below should work, but it doesn’t . I have not even checked this in IE yet, only tested in chrome and it’s not working. So what do you think I’m missing? There are no errors in the console but just absolutely nothing happens when I type in the filed, it just acts as text field.


    var keyup = false;
    $('form').delegate('blur', 'input[type=text]', function() {
        var $this = $(this),
            val = $this.val(),
            $pass = $('<input class="pwd" type="password" />');
        $pass.insertAfter(this);
        $this.remove();
        if (keyup) $pass.focus();
        keyup = false;
        $pass.val(val).addClass('ready');
    }).delegate('keyup', 'input[type=text]', function() {
        keyup = true;
        $(this).blur();
    }).delegate('focus', 'input[type=password].ready', function() {
        var $this = $(this),
            val = $this.val(),
            $txt = $('<input type="text" />');
        $txt.insertAfter(this);
        $this.remove();
        $txt.focus().val(val);
    });
})();


you also need to switch the first two arguments http://jsfiddle.net/psUe4/18/

Hi there,

Working off of davidfregoli’s clever solution, you could do this in plain JS:

<!DOCTYPE HTML>
<html>
  <head>
    <meta charset="utf-8">
    <title>Show password field on focus</title>
    <style>
      label{ 
        display: block;
        margin: 8px;
        text-align:right;
        width: 250px;
      }
    </style>
  </head>

  <body>
    <form>
      <label>Masked: <input type="text" class="masked" /></label>
      <label>Not Masked: <input type="text" /></label>
      <label>Masked: <input type="text" class="masked" /></label>
    </form>

    <script>
      function bindEventListeners(field){
        field.addEventListener("focus", function(){
          reveal(this);
        }, false);

        field.addEventListener("keypress", function(){
          conceal(this);
        }, false);

        field.addEventListener("blur", function(){
            mask(this);
        }, false);
      }

      function createInput(type, initialValue){
        var inputElement = document.createElement("input");
        inputElement.type = type;
        inputElement.value = initialValue;

        return inputElement;
      }

      function mask(field){
        if (field.getAttribute("data-destroy") != "true"){
          var passwordField = createInput("password", field.value);
          bindEventListeners(passwordField);
          field.parentNode.replaceChild(passwordField, field);
        }
      }

      function conceal(field){
        if(field.type === "text"){
          var passwordField = createInput("password", field.value);
          field.setAttribute("data-destroy", "true");
          field.parentNode.replaceChild(passwordField, field);
          passwordField.focus();
          bindEventListeners(passwordField);
        }
      }

      function reveal(field){
        var textField = createInput("text", field.value);
        field.setAttribute("data-destroy", "true");
        field.parentNode.replaceChild(textField, field);
        textField.focus();
        bindEventListeners(textField);
      }

      var maskedFields = document.querySelectorAll('.masked');
      for(var i = 0, len = maskedFields.length; i < len; i++){
        bindEventListeners(maskedFields[i]);
      }
    </script>
  </body>
</html>

Here’s a demo.

Oh noes!

I just got hold of a copy of IE8 to test on and my demo is rather broken :frowning:

I couldn’t test David’s version as JSFiddle is equally as broken in IE8, but I’m sure that’ll be what you’re looking for.

If for some reason it doesn’t work, I’m sure I could debug mine.

Yes, your solution does not work in IE, don’t think it even does in IE9, haven’t checked 10 or 11.
I’m not sure what is wrong but I cannot get delegate to work, simple piece of code as below won’t even work. Nothing triggers, I’m not sure what is going on, possible you can check David’s solution on your Machine now that you have IE8? Appreciate the help!


$(document).ready(function(){
var keyup = false;
$('form').delegate('click', 'input[type=text]', function(){
		alert('test');
});

:stuck_out_tongue:

IE8 only runs JScript ands so only supports attachEvent and not addEventListener.

I already posted a link to a plain JavaScript version that does work even in IE5 back in post 4 of this thread.

JScript does not support changing the type attribute. It does support conditional comments so that you can use those to readily distinguish between browsers that run JavaScript and those that run JScript (IE9 slightly complicates things by supporting both).

omg sorry I thought I had copy/pasted the new code you provided but I was still using the old code. Now that I have the code updated it is somewhat working in IE 8, sometimes it has a weird behavior, the cursor jumps one character behind while you are typing, so messing up the input. In IE 9, it does not switch to password type at all while you are typing and also the cursor jumps back one character every time a character is typed in. I feel we’re almost there! I’ll keep looking into it, let me know if you any suggestions for this.

Hi felgall,

Yeah, sorry, I used a pollyfill for this. I don’t this wasn’t the problem (although anything is possible).

About that, I couldn’t get it to work on the latest Chrome on Linux.
I copied the source code verbatim from your page, but I get the following error when I try and run it:

Uncaught SyntaxError: Unexpected token ; temp.html:61

It seems you’ve missed the closing bracket of the IFFE, i.e.

(function() { ... }();

should be:

(function() { ... })();

but although adding that makes the error go away, then nothing happens at all when I click into the input field - it is just plain text.

My code:

<!DOCTYPE HTML>
<html>
  <head>
    <meta charset="utf-8">
    <title>MAske password</title>
  </head>

  <body>
    <input type="password" name="pass" id="pass">

    <script>
      if (window.addEventListener)
      addEvent = function(ob, type, fn ) {
      ob.addEventListener(type, fn, false );
      };
      else if (document.attachEvent)
      addEvent = function(ob, type, fn ) {
      var eProp = type + fn;
      ob['e'+eProp] = fn;
      ob[eProp] = function(){ob['e'+eProp]( window.event );};
      ob.attachEvent( 'on'+type, o[eProp]);
      };
       
      (function() {
      var p = document.getElementById('pass');
      /*@cc_on
        @if (@_jscript)
        @if (@_jscript_version < 9)
        var inp = document.createElement("<input name='pass'>");
        inp.id = 'pass1';
        inp.type = 'text';
        inp.value = 'password';
        p.parentNode.replaceChild(inp,p);
        p = document.getElementById('pass1');
        @else
        p.type = 'text';
        p.value = 'password';
        @end
      @else */
        p.type = 'text';
        p.value = 'password';
      /* @end @*/
      passFocus = function() {
      if ('text' === this.type) {
        /*@cc_on
          @if (@_jscript)
        var inp = document.createElement("<input name='pass'>");
          inp.id = 'pass';
          inp.type = 'password';
          inp.value = '';
          this.parentNode.replaceChild(inp,this);
          inp.focus();
        @else */
          this.value = '';
          this.type = 'password';
          this.focus();
        /* @end @*/
      }
      addEvent(p, 'focus', passFocus);
      }
      }();
    </script>
  </body>
</html>

Yeah, it utterly fails in IE, which was kind of disappointing.

Did you get David or felgall’s solution working?

There were two typos in my code - a missing ) and a } in the wrong place - now fixed.