Build a RegEx Sandbox - Build a RegEx Sandbox

Tell us what’s happening:

I’m currently stuck on trying to fix a TypeError for the if-condition in the testButton addEventListener. I am unsure what is wrong with that line of code, as I have tried various different syntax alternatives. I am unable to test the logic of the rest of my code since an error is being thrown there and the rest of the program isn’t being executed.

Your code so far

<!-- file: index.html -->
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="styles.css">
    <title>Regex Sandbox</title>

</head>

<body>
    <h1>Regex Sandbox</h1>
    <main>
        <div id="regex-container">
            <label for="pattern">Regex Pattern:
                <div id="pattern-container">/<input type="text" id="pattern" name="pattern"
                        placeholder="Enter your regex pattern">/</div>
            </label>
            <div id="flags-container">
                <p>Flags: </p>
                <label for="i">
                    <input type="checkbox" name="flags" id="i"> i
                </label>
                <label for="g">
                    <input type="checkbox" name="flags" id="g"> g
                </label>
            </div>
        </div>
        <div id="test-container">
            <p>Test String:</p>
            <div id="test-string" placeholder="Enter your test string" contenteditable="true"></div>
        </div>
        <button class="btn" id="test-btn" type="button">Test Regex</button>
        <div id="result-container">
            <h2>Result:</h2>
            <p id="result">
            </p>
        </div>

    </main>
    <script src="script.js"></script>
</body>

</html>
/* file: styles.css */
*,
*::before,
*::after {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

:root {
    --dark-grey: #1b1b32;
    --light-grey: #f5f6f7;
    --golden-yellow: #fecc4c;
    --yellow: #ffcc4c;
    --gold: #feac32;
    --orange: #ffac33;
    --dark-orange: #f89808;
    --border: 0.2rem solid darkgrey;
    --padding: 0.3rem;
}

body {
    background-color: var(--dark-grey);
    color: var(--light-grey);
    font-size: 20px;
    font-family: "Lato", Helvetica, Arial, sans-serif;
    padding: 5px;
}

h1 {
    margin: 5rem auto 2rem;
    text-align: center;
}

p {
    padding: var(--padding);
}

#regex-container {
    max-width: 680px;
    margin: 20px auto;
    display: flex;
    justify-content: center;
    align-items: center;
    border: var(--border);
}

#regex-container>label {
    padding: var(--padding);
    flex: 1 1 auto;
}

#pattern-container {
    display: inline-block;
    color: var(--dark-grey);
    background-color: var(--light-grey);
    margin: 5px;
    border: var(--border);
}

#pattern {
    margin: 0.2rem;
    border: 0;
    font-size: 1rem;
    width: calc(100% - 1.2rem);
}

#pattern:focus {
    outline: none;
}

#flags-container {
    display: flex;
    align-items: center;
    flex: 1 1 auto;
}

#flags-container>label {
    padding: var(--padding);
    margin-right: 0.3rem;
}

#test-container {
    max-width: 680px;
    margin: 20px auto;
    display: flex;
    flex-direction: column;
    flex: 0 0 auto;
    border: var(--border);
}

#test-string {
    background-color: var(--light-grey);
    min-height: 5rem;
    color: var(--dark-grey);
    border-top: var(--border);
    font-size: 1.2rem;
}

[contenteditable=true]:empty:before {
    content: attr(placeholder);
    pointer-events: none;
    color: var(--dark-grey);
}

::placeholder {
    color: var(--dark-grey);
}


button {
    display: block;
    cursor: pointer;
    width: 8rem;
    margin: 0.2rem auto;
    color: var(--dark-grey);
    background-color: var(--gold);
    background-image: linear-gradient(var(--golden-yellow), var(--orange));
    border-color: var(--gold);
    border-width: 0.2rem;
    font-size: 1.1rem;
}

.btn:hover {
    background-image: linear-gradient(var(--yellow), var(--dark-orange));
}

#result-container {
    max-width: 680px;
    margin: 20px auto;
    display: flex;
    justify-content: center;
    align-items: center;
}

h2 {
    align-self: flex-start;
    margin: 0.4rem 0.2rem 0.2rem;
    flex: 0 1 auto;
}

#result {
    color: var(--dark-grey);
    background-color: var(--light-grey);
    font-size: 1.5rem;
    flex: 1 1 auto;
    margin: 0.2rem;
    border: var(--border);
    min-height: 3rem;
}

.highlight {
    background-color: lightgreen;
}
/* file: script.js */
const regexPattern = document.querySelector("#pattern");
const stringToTest = document.querySelector("#test-string");
const testButton = document.querySelector("#test-btn");
const testResult = document.querySelector("#result");
const caseInsensitiveFlag = document.querySelector("#i");
const globalFlag = document.querySelector("#g");

function getFlags() {
  if (caseInsensitiveFlag.checked && globalFlag.checked) {
    return "gi";
  } else if (caseInsensitiveFlag.checked) {
    return "i";
  } else if (globalFlag.checked) {
    return "g";
  } else {
    return "";
  }
}

testButton.addEventListener("click", () => {
  const stringVal = getFlags();

  // This if-condition is throwing a TypeError
  if (regexPattern.value.test(stringToTest.value) === true) {
    if (stringVal === "gi") {
      testResult.value = stringToTest.value.split("");
    } else if (stringVal === "i") {
      testResult.value = stringToTest.value.split("")[0];
    } else if (stringVal === "g") {
      const filteredArr = testResult.value.filter(char => {
        char !== char.toUpperCase();
      });

      // Get all characters that match
      testResult.value = filteredArr.split("");
    } else {
      const filteredArr = () => {
        for (const char of filteredArr) {
          if (char !== char.toUpperCase()) {
            return char;
          }
        }
      };

      // Only get first character that matches
      testResult.value = filteredArr.split("");
    }
  } else {
    testResult.value = "no match";
  } 
});

Challenge Information:

Build a RegEx Sandbox - Build a RegEx Sandbox

what is the full error you are gerring?

1 Like

This is the full error I am getting in the console:

Uncaught TypeError: regexPattern.value.test is not a function

Addition (Revised)

I made some revisions to my code that fixed logical flaws and an improper way of extracting the inputted text from the text field. I had assumed you would use .value but it seems you would use .textContent instead. I am unsure if this is how it’s always been or for this specific case. I ensured that I am first splitting the string into an array first before creating a filtered copy.

I deleted the previous post about revisions, as to avoid clutter and confusion. This code represents my up-to-date program with all the syntax.

Code:

const regexPattern = document.querySelector("#pattern");

const stringToTest = document.querySelector("#test-string");

const testButton = document.querySelector("#test-btn");

const testResult = document.querySelector("#result");

const caseInsensitiveFlag = document.querySelector("#i");

const globalFlag = document.querySelector("#g");




function getFlags() {

  if (caseInsensitiveFlag.checked && globalFlag.checked) {

    return "gi";

  } else if (caseInsensitiveFlag.checked) {

    return "i";

  } else if (globalFlag.checked) {

    return "g";

  } else {

    return "";

  }

}




testButton.addEventListener("click", () => {

  const stringVal = getFlags();

  const regexVal = new RegExp(regexPattern.value);




  if (regexVal.test(stringToTest.value) === true) {

    if (stringVal === "gi") {

      testResult.value = stringToTest.value.split("");

    } else if (stringVal === "i") {

      testResult.value = stringToTest.value.split("")[0];

    } else if (stringVal === "g") {

      // Check what user inputted || DEBUGGING || '.value' doesn't seem to work use '.textContent' instead

      console.log("User Input: " + stringToTest.textContent);




      // Split string into array first

      const arrEl = stringToTest.textContent.split("");




      // || DEBUGGING

      console.log("Initial Array: " + arrEl);




      // Then select character elements to extract

      const filteredArr = arrEl.filter(char => {

        char !== char.toUpperCase();

      });




      // || DEBUGGING

      console.log(typeof filteredArr);

      console.log("Filtered Array: " + filteredArr);




      for (const element of filteredArr) {

        testResult.value += `${element},`;

      }

    } else {

      // Check what user inputted || DEBUGGING || '.value' doesn't seem to work use '.textContent' instead

      console.log("User Input: " + stringToTest.textContent);

      

      // Split string into array first

      const arrEl = stringToTest.textContent.split("");




      // || DEBUGGING

      console.log("Initial Array: " + arrEl);




      // Then select character elements to extract

      const filteredArr = arrEl.filter(char => {

        char !== char.toUpperCase();

      });




      // || DEBUGGING

      console.log(typeof filteredArr);

      console.log("Filtered Array: " + filteredArr);




      for (const element of filteredArr) {

        testResult.value += `${element},`;

      }

    }

  } else {

    testResult.value = "no match";

  } 

}); 




// ## DEBUGGING CODE SAMPLE ##

/* const string = "test";

const stringArr = string.split("");

console.log(stringArr); */

The current issue I am facing is that filteredArr doesn’t seem to be storing any values at all even though the specified test cases should be passing when utilizing the .filter() callback function on the variable that contains the string converted to an array.

Console:

User Input: test 

Initial Array: t,e,s,t 

object 

Filtered Array:

Screenshot:

I am not sure what kind of logic you are following right now to get the matches, maybe you can explain it

my suggestion is, is maybe there a regex method that can tell you directly what are the matches of the regex pattern?

1 Like

Looking back at the modules, I believe the correct method would be .match()? With the ‘g’ or global flag being added to the regular expression so its all instances that match rather than just the first one.

So something like:

const match = stringToTest.match(regexVal);

Then match contains an object of key-value pairs, but with the global modifier the match returns just an array which I can access. I had originally thought of this idea, but didn’t think it would work or how to employ it in the program.

Current Logic:

As for my current logic, with a regular expression such as /[a-z]/ I am checking if each of the characters is uppercase by doing char !== char.toUpperCase(). This is in the instance where the ‘i’ flag was not selected and we’re only doing an alphabetical range with lowercase characters. The getFlags() function returns a string of the flags the user selected and that string is utilized in the if-elif branch sequence to determine what action to take. I am utilizing the new RegExp() constructor to convert the string inputted into the text field for the regular expression into an actual regular expression that can be used in expressions later on since I can’t directly convert the string since it is immutable. As mentioned earlier, I check if the character is uppercase if we’re dealing with lowercase and utilized the .filter() callback function to extract the character/element if it passes the specified test. After that I try to concatenate the elements into a string with a comma to be displayed in the testResult input field.

Additional Thought:
Say the user was to input a string to be tested like ‘example sample’. What the .match() method would return would be an array containing one element if the ‘g’ flag was selected.

const matched = stringToTest.match(regexVal);

console.log(matched);

Console Output:

[‘example’, ‘sample’]

The thing is that the characters that match should be displayed as individual elements instead of displaying the entire string.

Example:
e, x, a, m, p, l, e, s, a, m, p, l, e

Would be what is displayed in the result text field.

Original Design Result:

So, in order to accomplish that task you could parse the elements of the match as so:

let splitArr = [];
let finalArr = [];

for (const element of matched) {

  splitArr += element.split("");

    for (const element of splitArr) {
       finalArr += element;
   }

}

Then you could simply do testResult.value = […finalArr]. This ensures all the character elements are displayed as comma separated values in the result text field.

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.