0

The code work properly here .. but according to problem its not work properly actually I want to validate the 00-00-00-0000 format a text in digit/alpha .. but this code work only first time fill the value then its work correct but after the clear text the fill the value validation work not properly.

var v = "0";
var v1 = "0";
var v2 = "0";

function myFunction() {
  var x = document.getElementById("vname");
  x.value = x.value.toUpperCase();
  var add = "-";
  var string = x.value;
  var str = "";
  var len = string.length;
  if (len > 13) {
    x.value = string.substring(0, 13);
  }
  if (len > 2 && v == "0") {
    var str = x.value;
    x.value = setCharAt(str, 2, '-');
    v = "1";
  }
  if (len > 5 && v1 == "0") {
    var str = x.value;
    x.value = setCharAt(str, 5, '-');
    v1 = "1";
  }
  if (len > 8 && v2 == "0") {
    var str = x.value;
    x.value = setCharAt(str, 8, '-');
    v2 = "1";
  }
}

function setCharAt(str, index, chr) {
  if (index > str.length - 1) return str;
  return str.substr(0, index) + chr + str.substr(index + 1);
}
<input type="text" oninput="myFunction()" id="vname" />
3limin4t0r
  • 19,353
  • 2
  • 31
  • 52
  • Try work with regex like this: https://stackoverflow.com/questions/50890663/html-form-validation-with-regex-in-javascript-using-getelementbyid – Oleg Sep 19 '19 at 06:38
  • You should use the validation API instead. https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/Form_validation – Brad Sep 19 '19 at 07:27
  • thank u so much for reply .. actually i want validation put hand to hand if (-) not enter at particular position then autoamtically - add in string – PRATIKSHA GOYAL Sep 19 '19 at 07:36
  • Would [this answer](https://stackoverflow.com/a/55010378/5459839) be useful? – trincot Sep 19 '19 at 14:14

3 Answers3

2

The issue you're currently facing is due to the fact that you set some state by changing the v, v1 and v2 variables. Your formatter should be stateless so it returns the same result every time you call it with the same input.

You could use a templating string. Then loop through the input value index, for each index check in the templating string what is allowed.

function myFunction(input) {
  const format = "xx-xx-xx-xxxx";

  var value = ""; // new value
  for (let i = 0; i < input.value.length; ++i) {
    switch (format[i]) {
      case "-":
        value += "-";
        break;
      case "x":
        value += input.value[i];
        break;
    }
  }
  
  input.value = value.toUpperCase();
}

document
  .getElementById("vname")
  .addEventListener("input", event => myFunction(event.target));
<input type="text" id="vname" />
3limin4t0r
  • 19,353
  • 2
  • 31
  • 52
  • 1
    Things go wrong when you put the cursor in the middle of the already present characters and start typing/deleting there. – trincot Sep 19 '19 at 14:53
  • @trincot true, but the intent of this answer is to keep the behaviour close to the question. Only providing what's actually asked. – 3limin4t0r Sep 19 '19 at 14:58
1

Try this regex, hope it will help you:

 ^([0-9]|[a-z])|([0-9]|[a-z])(\-)([0-9]|[a-z])|([0-9]|[a-z])(\-)([0-9]|[a-z])|([0-9]|[a-z])(\-)([0-9]|[a-z])|([0-9]|[a-z])([0-9]|[a-z])|([0-9]|[a-z])$
  • thanku so much for reply .. i want to perform oninput() hand to hand validate the text – PRATIKSHA GOYAL Sep 19 '19 at 07:29
  • you can try the below code: `function myFunction() { var x = document.getElementById("vname"); x.value = x.value.toUpperCase(); var add = "-"; var string = x.value; var len = string.length; var validationString = string.charAt(len-1); var re = new RegExp("^([a-z]|[0-9])$"); if(len == 3 || len == 6 || len == 9) { if(validationString != '-') return false; }else { return (re.test(validationString)); } }` – Mehedi Hasan Ovi Sep 19 '19 at 09:16
  • The `|` characters between two `([0-9]|[a-z])` groups shouldn't be there. It's hard to easily explain since it seems you're new to regex. Have a [look](https://regexper.com/#%5E%28%5B0-9%5D%7C%5Ba-z%5D%29%7C%28%5B0-9%5D%7C%5Ba-z%5D%29%28%5C-%29%28%5B0-9%5D%7C%5Ba-z%5D%29%7C%28%5B0-9%5D%7C%5Ba-z%5D%29%28%5C-%29%28%5B0-9%5D%7C%5Ba-z%5D%29%7C%28%5B0-9%5D%7C%5Ba-z%5D%29%28%5C-%29%28%5B0-9%5D%7C%5Ba-z%5D%29%7C%28%5B0-9%5D%7C%5Ba-z%5D%29%28%5B0-9%5D%7C%5Ba-z%5D%29%7C%28%5B0-9%5D%7C%5Ba-z%5D%29%24) for yourself. – 3limin4t0r Sep 19 '19 at 15:21
1

I wrote a more generic answer here on using a visible mask for a fixed-size formatted input. That should work for you, if you accept that the input mask is always visible. For it to work add the following attributes to your input:

<input placeholder="__-__-__-____" data-slots="_" data-accept="\w" size="13">

Note that it does not turn lower case into upper case (something I would advise against: you don't want people to think their CAPS-lock key is malfunctioning). If that is not how you want it to work (with the mask or with the lack of upper-casing), here is that code adapted to your requirements specifically:

const el = document.getElementById("vname"),
    pattern = "__-__-__-____",
    prev = [1, 2, 2, 4, 5, 5, 7, 8, 8, 10, 11, 12, 13],
    accept = /\w/g,
    clean = input => {
        input = input.match(accept) || [];
        return Array.from(pattern, c =>
            input[0] === c || c == "_" ? input.shift() || c : c
        );
    },
    format = () => {
        const [i, j] = [el.selectionStart, el.selectionEnd].map(i => {
            i = clean(el.value.slice(0, i)).indexOf("_");
            return i<0? prev[prev.length-1]: back? prev[i-1] || 0: i;
        });
        let s = clean(el.value).join``.toUpperCase();
        el.value = s.slice(0, (s+"_").indexOf("_"));
        el.setSelectionRange(i, j);
        back = false;
    };
    
let back = false;
el.addEventListener("keydown", (e) => back = e.key === "Backspace");
el.addEventListener("input", format);
<input type="text" id="vname" />

Like in the answer I referred to, this also deals with copy/paste (even if copied values do not have the hyphens), with selections, putting the cursor halfway, deleting characters there, ...etc.

trincot
  • 317,000
  • 35
  • 244
  • 286