thathashd
thathashd

Reputation: 1022

javascript format number

Completely noob in regexs...

I want to format a number like: 1234123412341234 in something like:

12 3412 3412 3412 34

Currently I have the following code:

<label for="num1">Formmatted Number</label>
<input id="num1" type="text" name="num1" />

function space(str, after) {
    if (!str) {
        return false;
    }
    after = after || 4;
    var v = str.replace(/[^\dA-Z]/g, ''),
        reg = new RegExp(".{" + after + "}", "g");
    return v.replace(reg, function (a) {
        return a + ' ';
    });
}

var el = document.getElementById('num1');
el.addEventListener('keyup', function () {
    this.value = space(this.value, 4);
});

This formats the number as:

1234 1234 1234 1234

Can you please help me with this?

Upvotes: 1

Views: 165

Answers (6)

Patrick Roberts
Patrick Roberts

Reputation: 51876

Here's a neat way to progressively format the input. This even keeps the current cursor position in the correct location when inserting or deleting characters from the middle of the string:

function count (str, re) {
  return str.split(re).length - 1
}

document.querySelector('input').addEventListener('input', function () {
  const { value, selectionStart } = this
  const oldIndex = selectionStart - count(value.slice(0, selectionStart), /\D/g)
  const numeric = value.replace(/\D/g, '')
  const sanitized = numeric
    .replace(/(\d{0,2})(\d{0,4})(\d{0,4})(\d{0,4})(\d{0,2}).*/, '$1 $2 $3 $4 $5')
    .trim()
  const newIndex = oldIndex + Math.floor((oldIndex + 2) / 4)

  this.value = sanitized
  this.setSelectionRange(newIndex, newIndex)
})
<input type="text">

Upvotes: 1

TheMaster
TheMaster

Reputation: 50453

var el = document.getElementById('num1'); 
el.addEventListener('keyup', function () { this.value = format(this.value); }); 

function format(s){ 
    return  Array.prototype.map.call(s,(e,i)=>(e=e.replace(/\s/g,""), 
        (i+3)%5==0 ? " "+e:e)).join("");
}

If it's always 16 chars, then you can use map fn with condition If index is equal to 2 or index is the 4th character.

Upvotes: -1

Nina Scholz
Nina Scholz

Reputation: 386578

You could replace with 2 starting digits and then add a space for all four digits.

var number = 1234123412341234,
    string = number.toString().replace(/^..|..../g, '$& ');
    
console.log(string);

Or you could use a regular expression with positive lookahead for a special length to the end of the string.

var number = 1234123412341234,
    string = number.toString().replace(/(?=(.{14}|.{10}|.{6}|.{2})$)/g, ' ');
    
console.log(string);

Upvotes: 1

thathashd
thathashd

Reputation: 1022

Just solved the problem :)... Thanks for your help anyway. As discussed in previous topics the length of 16 is not important as the field will only allow to insert 16 chars... otherwise that constraint could be included in the script.

function format(str, after) {
    var v = str.replace(/[^\dA-Z]/g, ''),
        reg = new RegExp(".{" + after + "}", "g");
    return v.replace(reg, function (a) {
        if (a.length > 2) {
            a = a.substring(0,2) + ' ' + a.substring(2,a.length);
        }
        return a;
    });
}

var el = document.getElementById('num1');
el.addEventListener('keyup', function () {
    this.value = format(this.value, 4);
});
<label for="num1">Formatted Number</label>
<input id="num1" type="text" name="num1" />

Upvotes: 0

Michał Turczyn
Michał Turczyn

Reputation: 37367

Try this pattern: \b(\d{2})(\d{4})(\d{4})(\d{4})(\d{2})\b, it will allow you to put particaler batches of your digits into separate group, then just replace it with \1 \2 \3 \4 \5, which will give you desired format.

Demo

Upvotes: 0

rdgd
rdgd

Reputation: 1446

Here is a solution that does not use regular expressions...

const fmtNum = (num) => [2, 7, 12, 17].reduce((acc, curr) => [acc.slice(0, curr), " ", acc.slice(curr)].join(""), String(num));

Take note that in order to accomplish this we must change the type from number to string.

This could be expanded to pass in an argument of different break indices where you specify where you want the spaces to be, like:

const fmtNum = (num, spacePoints) => spacePoints.reduce((acc, curr) => [acc.slice(0, curr), " ", acc.slice(curr)].join(""), String(num));

Invoking this would instead look like: fmtNum(1234123412341234, [2, 7, 12, 17])

Upvotes: 1

Related Questions