Build a RegEx Sandbox - Build a RegEx Sandbox

Tell us what’s happening:

I am currently stuck figuring out how to display the highlighted characters that match in the ‘Test String’ text-field without ONLY displaying those characters.

For example, a user inputs ‘[a-z]’ for the regular expression and ‘test’ for the string.

Currently, the ‘Test String’ text field will only contain the letter ‘t’ but highlighted. I want to keep the entire string the user inputted and only highlight the characters that matched. However, I am confused on how to apply that logic.

NOTE:

This is a repost to a previous post on the forums to this lab. I flagged the previous post for moderation, so it could potentially be taken down to avoid clutter and confusion. It was getting too long and I made too many revisions since the original code in the post.

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();
  // Using '.value' here since this is an input element
  const regexVal = new RegExp(regexPattern.value);
  const regexCaseVal = new RegExp(regexPattern.value, "i");
  const regexGlobalVal = new RegExp(regexPattern.value, "g");
  const regexAllVal = new RegExp(regexPattern.value, "gi"); 

  if (regexVal.test(stringToTest.value) === true && regexPattern.value !== "") {
    if (stringVal === "gi") {
      // Check what user inputted || DEBUGGING || '.value' doesn't seem to work use '.textContent' instead
      console.log("User Input: " + stringToTest.textContent);

      // Utilize .match() to access matched values
      const matched = stringToTest.textContent.match(regexAllVal);

      // || DEBUGGING
      console.log(matched);
      console.log("Match Object: " + matched);

      // Add highlight to matched text in 'Test String' input field || Add matched arr copy but as a string
      const matchedString = [...matched].join("");
      console.log("String: " + matchedString);
      stringToTest.innerHTML = `<span class='highlight'>${matchedString}</span>`;

      testResult.textContent = [...matched];
    } else if (stringVal === "i") {
      // Check what user inputted || DEBUGGING || using '.textContent' since this is a div with contenteditable attribute rather than input element
      console.log("User Input: " + stringToTest.textContent);

      // Utilize .match() to access matched values
      const matched = stringToTest.textContent.match(regexCaseVal);

      // || DEBUGGING
      console.log(matched);
      console.log("Match Object: " + matched);

      // Add highlight to matched text in 'Test String' input field || Add matched arr copy but as a string
      const matchedString = [...matched].join("");
      console.log("String: " + matchedString);
      stringToTest.innerHTML = `<span class='highlight'>${matchedString}</span>`;

      testResult.textContent = matched[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);

      // Utilize .match() to access matched values
      const matched = stringToTest.textContent.match(regexGlobalVal);

      // || DEBUGGING
      console.log(matched);
      console.log("Match Object: " + matched);

      // Add highlight to matched text in 'Test String' input field || Add matched arr copy but as a string
      const matchedString = [...matched].join("");
      console.log("String: " + matchedString);
      stringToTest.innerHTML = `<span class='highlight'>${matchedString}</span>`;

      testResult.textContent = [...matched];
    } else {
      // Check what user inputted || DEBUGGING || using '.textContent' since this is a div with contenteditable attribute rather than input element
      console.log("User Input: " + stringToTest.textContent);

      // Utilize .match() to access matched values
      const matched = stringToTest.textContent.match(regexVal);

      // || DEBUGGING
      console.log(matched);
      console.log("Match Object: " + matched);

      // Add highlight to matched text in 'Test String' input field || Add matched arr copy but as a string
      const matchedString = [...matched].join("");
      console.log("String: " + matchedString);
      stringToTest.innerHTML = `<span class='highlight'>${matchedString}</span>`;

      testResult.textContent = matched[0];
    }
  } else {
    testResult.textContent = "no match";
  } 
}); 

// ## DEBUGGING CODE SAMPLE ##
/* const string = "test";
const stringArr = string.split("");
console.log(stringArr); */

Failed Test Cases:

// running tests
12. When the inner HTML of stringToTest is Gu1n34 P1g5, the value of regexPattern is \d+,  and no flag is checked, stringToTest.innerHTML should become Gu<span class="highlight">1</span>n34 P1g5 by clicking the testButton button.
13. When the inner HTML of stringToTest is Gu1n34 P1g5, the value of regexPattern is \d+,  and the global flag is checked, stringToTest.innerHTML should become Gu<span class="highlight">1</span>n<span class="highlight">34</span> P<span class="highlight">1</span>g<span class="highlight">5</span> by clicking the testButton button.
14. When the inner HTML of stringToTest is Gu1n34 P1g5, the value of regexPattern is G,  and both the global and case insensitive flags are checked, stringToTest.innerHTML should become <span class="highlight">G</span>u1n34 P1<span class="highlight">g</span>5 by clicking the testButton button.
15. When you click the testButton button, if the regex pattern matches the test string, the matched text should be surrounded by a span element with the class of highlight.
17. When the inner HTML of stringToTest is Gu1n34 P1g5, the value of regexPattern is \d+,  and no flag is checked, the inner text of #result should become 1 by clicking the testButton button.
18. When the inner HTML of stringToTest is Gu1n34 P1g5, the value of regexPattern is \d+,  and the global flag is checked, the inner text of #result should become 1, 34, 1, 5 by clicking the testButton button.
19. When there's a match, the matched text should be displayed inside #result.
// tests completed


Example Scenario:

Before

After

Challenge Information:

Build a RegEx Sandbox - Build a RegEx Sandbox

Alright, I think I’m nearing the end here. I managed to dial down the amount of failed test cases to three. However, these failed test cases make no sense since my output looks exactly like it’s supposed to.

Example Visual:

My Program Visual (Exact same input):

My Script:

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();

  // Using '.value' here since this is an input element

  const regexVal = new RegExp(regexPattern.value);

  const regexCaseVal = new RegExp(regexPattern.value, "i");

  const regexGlobalVal = new RegExp(regexPattern.value, "g");

  const regexAllVal = new RegExp(regexPattern.value, "gi"); 




  if (regexVal.test(stringToTest.textContent) === true && regexPattern.value !== "") {

    // || DEBUG

    console.log("Checkpoint A");




    if (stringVal === "gi") {

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

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




      // Utilize .match() to access matched values

      const matched = stringToTest.textContent.match(regexAllVal);




      // || DEBUGGING

      console.log(matched);

      console.log("Match Object: " + matched);




      // Add highlight to matched text in 'Test String' input field || Add matched arr copy but as a string

      const matchedString = [...matched].join("");

      console.log("String: " + matchedString);

      

      // Store copy of stringToTest string

      const stringCopy = stringToTest.textContent;

      // Then clear the text for stringToTest

      stringToTest.textContent = "";

      

      for (const element of stringCopy) {

        // console.log("Current element: " + element);

        if (matchedString.includes(element) === true) {

          stringToTest.innerHTML += `<span class='highlight'>${element}</span>`

        } else {

          stringToTest.innerHTML += `${element}`;

        }

      }




      testResult.textContent = [...matched];

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

      // Check what user inputted || DEBUGGING || using '.textContent' since this is a div with contenteditable attribute rather than input element

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




      // Utilize .match() to access matched values

      const matched = stringToTest.textContent.match(regexCaseVal);




      // || DEBUGGING

      console.log(matched);

      console.log("Match Object: " + matched);




      // Add highlight to matched text in 'Test String' input field || Add matched arr copy but as a string

      const matchedString = [...matched].join("");

      console.log("String: " + matchedString);

      

      // Store copy of stringToTest string

      const stringCopy = stringToTest.textContent;

      // Then clear the text for stringToTest

      stringToTest.textContent = "";




      let count = 0;




      for (const element of stringCopy) {

        // console.log("Current element: " + element);

        if (matchedString.includes(element) === true && count === 0) {

          stringToTest.innerHTML += `<span class='highlight'>${element}</span>`

          count++;

        } else {

          stringToTest.innerHTML += `${element}`;

        }

      }




      testResult.textContent = matched[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);




      // Utilize .match() to access matched values

      const matched = stringToTest.textContent.match(regexGlobalVal);




      // || DEBUGGING

      console.log(matched);

      console.log("Match Object: " + matched);




      // Add highlight to matched text in 'Test String' input field || Add matched arr copy but as a string

      const matchedString = [...matched].join("");

      console.log("String: " + matchedString);

      

      // Store copy of stringToTest string

      const stringCopy = stringToTest.textContent;

      // Then clear the text for stringToTest

      stringToTest.textContent = "";




      for (const element of stringCopy) {

        // console.log("Current element: " + element);

        if (matchedString.includes(element) === true) {

          stringToTest.innerHTML += `<span class='highlight'>${element}</span>`

        } else {

          stringToTest.innerHTML += `${element}`;

        }

      }




      testResult.textContent = [...matched];

    } else {

      // || DEBUG

      console.log("Checkpoint A4");




      // Check what user inputted || DEBUGGING || using '.textContent' since this is a div with contenteditable attribute rather than input element

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




      // Utilize .match() to access matched values

      const matched = stringToTest.textContent.match(regexVal);




      // || DEBUGGING

      console.log(matched);

      console.log("Match Object: " + matched);




      // Add highlight to matched text in 'Test String' input field || Add matched arr copy but as a string

      const matchedString = [...matched].join("");

      console.log("String: " + matchedString);





      // Check what string contains || DEBUG

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

      

      // Store copy of stringToTest string

      const stringCopy = stringToTest.textContent;

      // Then clear the text for stringToTest

      stringToTest.textContent = "";




      let count = 0;




      for (const element of stringCopy) {

        // console.log("Current element: " + element);

        if (matchedString.includes(element) === true && count === 0) {

          stringToTest.innerHTML += `<span class='highlight'>${element}</span>`

          count++;

        } else {

          stringToTest.innerHTML += `${element}`;

        }

      }




      testResult.textContent = matched[0];

    }

  } else {

    // || DEBUG

    console.log("Checkpoint B");




    testResult.textContent = "no match";

  } 

}); 




// ## DEBUGGING CODE SAMPLE ##

/* const string = "test";

const stringArr = string.split("");

console.log(stringArr); */

Console Output:

Checkpoint A 

Checkpoint A4 

User Input: Gu1n34 P1g5 

[ '1', index: 2, input: 'Gu1n34 P1g5', groups: undefined ] 

Match Object: 1 

String: 1 

stringToTest: Gu1n34 P1g5

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