22

I want to mask the text in an input box without changing the actual value. I can not use any plugins.

I am currently doing this - but as you can see the issue is that the actual value is changed on submit. How can I just change the display value?

$("input[name='number']").focusout(function(){
    var number = this.value.replace(/(\d{2})(\d{3})(\d{2})/,"$1-$2-$3");
    this.value = number;
}
4
  • The <input> element doesn't have a display value. The value of the input is what the user sees. You want to create 2 inputs: one is for the actual value, the other for the display and possibly taking input from the user. Commented Nov 9, 2016 at 19:00
  • How would you like the mask to format the content? Commented Nov 9, 2016 at 19:00
  • the mask would format same as the function above 00-000-00. Adding dashes to 8 numbers Commented Nov 9, 2016 at 19:02
  • @user1392897 I created a solution for you based on the format requested. Commented Nov 9, 2016 at 19:25

3 Answers 3

31

You need two inputs

Two inputs should get the job done. One input will contain the masked text and the other will be a hidden input that contains the real data.

<input type="text" name="masknumber">
<input type="text" name="number" style="display:none;">

The way I approached the masking is to build a function for both masking and unmasking the content so everything stays uniform.

$("input[name='masknumber']").on("keyup change", function(){
        $("input[name='number']").val(destroyMask(this.value));
    this.value = createMask($("input[name='number']").val());
})

function createMask(string){
    return string.replace(/(\d{2})(\d{3})(\d{2})/,"$1-$2-$3");
}

function destroyMask(string){
    return string.replace(/\D/g,'').substring(0,8);
}

Working JSFiddle

Sign up to request clarification or add additional context in comments.

2 Comments

string.replace(/(\d{2})(\d{3})(\d{2})/,"$1-$2-$3"); could you explain how this works exactly? Thanks
Definitely! This runs the string through a regex operation! In regex, ( ) are placed around "capture groups". We'll talk more about that in a moment but first, let me tell you that \d means "digit" and \d{2} means "two digits". Finally, $ followed by a number refers to a capture group, which one indicated by which number. So, as you've perhaps concluded, that code takes the first string of 7 digits it finds and splits it into the first two, then the middle three, then the last two (with - between). To learn more, check out regexr.com and their Cheatsheet in the left menu!
3

or also

<input type="text" onkeypress="handleMask(event, 'data: 99/99/9999 99:99 999 ok')" placeholder="data:  ok" size=40>

with

function handleMask(event, mask) {
    with (event) {
        stopPropagation()
        preventDefault()
        if (!charCode) return
        var c = String.fromCharCode(charCode)
        if (c.match(/\D/)) return
        with (target) {
            var val = value.substring(0, selectionStart) + c + value.substr(selectionEnd)
            var pos = selectionStart + 1
        }
    }
    var nan = count(val, /\D/, pos) // nan va calcolato prima di eliminare i separatori
    val = val.replace(/\D/g,'')

    var mask = mask.match(/^(\D*)(.+9)(\D*)$/)
    if (!mask) return // meglio exception?
    if (val.length > count(mask[2], /9/)) return

    for (var txt='', im=0, iv=0; im<mask[2].length && iv<val.length; im+=1) {
        var c = mask[2].charAt(im)
        txt += c.match(/\D/) ? c : val.charAt(iv++)
    }

    with (event.target) {
        value = mask[1] + txt + mask[3]
        selectionStart = selectionEnd = pos + (pos==1 ? mask[1].length : count(value, /\D/, pos) - nan)
    }

    function count(str, c, e) {
        e = e || str.length
        for (var n=0, i=0; i<e; i+=1) if (str.charAt(i).match(c)) n+=1
        return n
    }
}

Comments

3

A more robost version of accepted answer without having two input's which may pollute transmitted form fields and also being aware of key-repetitions and other quirks when pressing a key too long:

<input type="text" name="masknumber" data-normalized="">

and

$("input[name='masknumber']").on("input", function(){ // input event!
  let n = destroyMask(this.value);
  this.setAttribute("data-normalized", n); // saved as attribute instead 
  this.value = createMask(n);
})

function createMask(string){
    return string.replace(/(\d{2})(\d{3})(\d{2})/,"$1-$2-$3");
}

function destroyMask(string){
    return string.replace(/\D/g,'').substring(0, 7); // 7 instead of 8!
}

JSFiddle

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.