Why does my replace work properly in javascript when I use "and" or "or" but not when I use "&" or "/" or "+"

Viewed 124

I have a first name input in a HTML form and sometimes a user will input two first names and I need to strip out the second name and the word or character used to join them. If I use the word "and" or the word "or" my javascript works fine and strips out the second name and the word used to join them. However, if I use an ampersand (&) or a plus sign (+) or a forward slash (/), no matter how I code it, it will only strip out the last character of the second name and not the joining character or any af the second name except the last character.

I have tried using string functions, regular expressions, testing my regular expression at regex.com (they work there and properly select the words and the joining words), a dozen different variations of my regular expression that all work properly at regex, com to select the text I want removed, but none of this works in my actual form.

For instance if I input: "Bob and Dave" I get "Bob" - Correct "Bob or Dave" I get "Bob" - Correct

But if I input: "Bob & Dave" I get "Bob & Dav" - Incorrect "Bob + Dave" I get "Bob + Dav" - Incorrect "Bob / Dave" I get "Bob " - Incorrect but Acceptable "Bob, Dave" I get "Bob, Dav" - Incorrect

This is some of the code I have used, several different approaches have worked for the first two, nothing has worked for the last four.

Works for "Bob and Dave":

function noExtraNames() {
var pattern=document.forms[0].first_name.value;
var z = pattern.search(/(\s)*\w+/gi)
var x = pattern.search("AND", z+1)
if (z < x) {
    alert('Please only enter ONLY ONE FIRST NAME')
    document.forms[0].first_name.focus();
    return document.forms[0].first_name.value=pattern.replace(/\s(AND)*\w+/gi, "");
}
}

Works for "Bob or Dave":

function noExtraNames() {
var pattern=document.forms[0].first_name.value;
var z = pattern.search(/\s(OR)*\w+/gi)
var x = pattern.search("OR", z+1)
if (z < x) {
    alert('Please only enter ONLY ONE FIRST NAME')
    document.forms[0].first_name.focus();
    return document.forms[0].first_name.value=pattern.replace(/\s(or)*\w+/gi, "");
}
}

This also worked for "Bob and Dave" and changing the corresponding word "and" for "or", worked for "Bob or Dave":

function noExtraNames() {
var pattern=document.forms[0].first_name.value;
var z = pattern.search("and")
var x = pattern.search("and")
if (z < x) {
    alert('Please only enter ONLY ONE FIRST NAME')
    document.forms[0].first_name.focus();
    return document.forms[0].first_name.value=pattern.slice(0, z);
}
}

However, this worked for the incorrect but acceptable "Bob, Dave", but did not work for "Bob & Dave" or "Bob / Dave", when the appropriate characters were substituted:

function noExtraNames() {
var pattern=document.forms[0].first_name.value;
var z = pattern.search(/(,\s+)/gi);
var x = pattern.search((/(,\s+)/gi), z-1);
if (z < x) {
    alert('Please only enter ONLY ONE FIRST NAME');
    document.forms[0].first_name.focus();
    return document.forms[0].first_name.value=pattern.replace(/(,\s+)/gi);
}
}

And this yielded the same incorrect result with "&" and "/":

function noExtraNames() {
var pattern=document.forms[0].first_name.value;
var z = pattern.search(/(\s&)/gi);
var x = pattern.search(/(\s&\s.[a-z].+)/gi, z-1);
if (x < z) {
    alert('Please only enter ONLY ONE FIRST NAME');
    document.forms[0].first_name.focus();
    return document.forms[0].first_name.value=pattern.replace(/(\s&\s.[a-z].+)/gi, "");
}
}

The regular expressions all worked to select the proper text at regex.com, but never work in my form and I am almost out of hair to pull in frustration.

Why is this happening and more importantly how can I fix it. I have tried several other solutions I found on this site such as:

function noExtraNames() {
var pattern=document.forms[0].first_name.value;
var z = pattern.search(/(,\s+)/gi);
var x = pattern.search((/(,\s+)/gi), z-1);
if (x < z) {
    alert('Please only enter ONLY ONE FIRST NAME');
    document.forms[0].first_name.focus();
    var s = document.forms[0].first_name.value;
    var n = s.indexOf('&');
    s = s.substring(0, n != -1 & n : s.length);
    return document.forms[0].first_name.value = s;
}
}

All for no joy.

The expected output is: Bob The actual output is: Bob & Dav

2 Answers

It seems like this would be better handled by splitting on the regex and returning the first item. This pattern should take care of the cases mentioned in your post:

var pattern = /(\s*[\+|&|\,|\/]\s*|\s+(and|or)\s+)/i;

then splitting and always returning the first element.

function noExtraNames(name) {
  var pattern = /(\s*[\+|&|\,|\/]\s*|\s+(and|or)\s+)/i;
  var items = name.split(pattern);
  if (items.length > 1) {
    console.log('Please only enter ONLY ONE FIRST NAME');
    return items[0];
  }
  return name;
}

let tests = [
  'Bob',
  'Billy Bob',
  'Bob and Dave',
  'Bob + Dave',
  'Bob & Dave',
  'Bob / Dave',
  'Bob, Dave',
  'Igor',
  'Andy',
  'Bob+Dave',
];

for (let test of tests) {
  console.log(test, '===> ', noExtraNames(test));
}

const pattern = /(.*(?=(\s+(and|or)\s+)|(\s*[\&\+,\/\\])))|.*/i;
const patternMatch = str.match(pattern);
if (patternMatch[1]) {
  alert('Please only enter ONLY ONE FIRST NAME');
}
const replaceValue = patternMatch[0].trim();
document.forms[0].first_name.value = replaceValue;

I guess that's what you need.

Related