simonalexander2005
simonalexander2005

Reputation: 4577

regex for input mask - comma separated list of up to three characters per item

I have an input field, which I want to limit as follows:

  1. The input will be a comma-separated list
  2. Each string in the list must be limited to 1..3 characters
  3. The list can have as many items as the user wants

some examples:

1,4,6a,16b
1
abc,def,ghi,jkl,mno,pqr,stu,vwx,yzz

I have found the following jsfiddle: https://jsfiddle.net/2x8y1dhL/ which provides a starting point for creating an input mask, but it assumes a fixed number of items in the list, and a fixed length of each input.

What I want is the following logic:

Upvotes: 1

Views: 834

Answers (2)

zb226
zb226

Reputation: 10538

I have worked on the jsfiddle you have found. Some notes:

  • You have not specified valid/invalid characters, but the examples given seem to suggest "alpha-numeric plus comma"
  • Consecutive commas are allowed as it's not specified otherwise.

The meat of the matter are the two functions createMask and destroyMask:

function createMask(string){
    return string.replace(/(\w{3})(?!,)(.+)$/g,"$1,$2");
}

function destroyMask(string){
    return string.replace(/[^0-9A-Z,]/ig,'');
}

Update 1: Pasting input that is longer than six characters - i.e. needs to be split more than once - turned out to be problematic with the original answer. An explicit loop is needed as the g modifier does not help with that regex. Here's the updated fiddle:

function createMask(string){
  let s = string;
  let t;
  do {
    t = s;
    s = s.replace(/(\w{3})(?!,)(.+)$/,"$1,$2");    
  } while (s !== t)
  return s;
}

Update 2: However, we can get away without an explicit loop with this alternative regex that only uses a single capture - updated fiddle:

function createMask(string){
    return string.replace(/(\w{3})(?!,|$)/g,"$1,");
}

Upvotes: 1

The fourth bird
The fourth bird

Reputation: 163632

You can repeat optional repetitions of 3 word characters followed by a comma and then match 3 word characters asserting a word char to the right.

^(?:\w{3},)*\w{3}(?=\w)

Regex demo | Forked fiddle

In the replacement use the full match $& followed by a comma.

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

function createMask(string){
    return string.replace(/^(?:\w{3},)*\w{3}(?=\w)/g,"$&,");
}

function destroyMask(string){
    return string.replace(/[^0-9A-Z,]/ig,'');
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="text" name="masknumber" data-normalized="" size=64>

Or fiddle demo with a variant with 2 capture groups.

Upvotes: 0

Related Questions