Build a RegEx Sandbox

Ok, so I’ve tried this a few ways and I’m a bit stuck. Replacing a regex matched text in a string is a breeze when it’s just one match. But when it’s several matches, it gets tricky. I’m not sure why I’m not passing these tests:

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 .

I am surrounding the text with a span.

19. When there’s a match, the matched text should be displayed inside #result .

I am getting the result displayed, so this is odd.

I have made no changes to the HTML and CSS files already provided for by the exercise itself. Still, here is the 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>

Here is the 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;
}

And this is my Javascript:

const regexPattern = document.getElementById("pattern");
const stringToTest = document.getElementById("test-string");
const testButton = document.getElementById("test-btn");
const testResult = document.getElementById("result");
const caseInsensitiveFlag = document.getElementById("i");
const globalFlag = document.getElementById("g");

// flags based on checked checkboxes
const getFlags = () => {
  if(caseInsensitiveFlag.checked && globalFlag.checked) {
    return "ig";
  } else if(caseInsensitiveFlag.checked) {
    return "i";
  } else if(globalFlag.checked) {
    return "g";
  } else {
    return "";
  }
}

// supplementary function to get only "i" flag
const getiflag = () => {
  if(caseInsensitiveFlag.checked) {
    return "i";
  }
  return "";
}

// regex builder
const regexBuilder = (input) => {
  let flags = getFlags();
  let creation = new RegExp(input, flags);
  return creation;
}

// surround text with tags to highlight
const highlighter = (text) => {
  return `<span class="highlight">${text}</span>`;
}

// event listener
testButton.addEventListener('click', () => {
  let regexInput = regexPattern.value; // input from regex 
  console.log(regexInput)
  let lookarounds = "";
  if(regexInput.includes("\d+")) {
    lookarounds += `(?<!${regexInput})|(?!${regexInput})`;
  } else {
    lookarounds += `(?<=${regexInput})|(?=${regexInput})`;
  }
  let regex = regexBuilder(regexInput); // regex to check
  let iFlag = getiflag();
  let regexNoGlobal = new RegExp(regexInput, iFlag);
  let regex2 = regexBuilder(lookarounds); // regex to split testInput when global flags is on
  console.log(regex2);
  let testInput = stringToTest.innerText; // gets input from test string
  if(globalFlag.checked) { // rules to match when global flag is ON
    if(regex.test(testInput)) {
      // splits test string input to substrings with regex matched and unmatched items
      let testInputArr = [...testInput.split(regex2)];
      console.log(testInputArr);
      let convertedArr = []; // creates new array to build with converted substrings
      testInputArr.forEach((item) => {
        if(regexNoGlobal.test(item)) { // if substring includes regex
          let matchedText = item.match(regexNoGlobal); // gets matched text
          let highlightedText = highlighter(matchedText); // adds span tags to matched text
          let newItem = item.replace(matchedText, highlightedText); // replaces matched text with highlighted text
          convertedArr.push(newItem); // adds converted item to array
        } else {
          convertedArr.push(item); // adds original item to array
        }
      });
      let textToDisplay = convertedArr.join(""); // joins items as uninterrupted string
      stringToTest.innerHTML = textToDisplay; // sets html string to display
      let resultsArr = [];
      let resultsList = document.querySelectorAll(".highlight");
      for(let i = 0; i < resultsList.length; i++) {
        let keyItem = resultsList[i].innerText;
        resultsArr.push(keyItem);
      }
      testResult.innerText = resultsArr.join(", "); // shows matched items in Result
    } else {
    testResult.innerText = "no match";
    }
  } else if(!globalFlag.checked) { // rules to match when global flag is OFF
      if(regex.test(testInput)) {
        let matchText = testInput.match(regex)[0];
        let highlightedText = highlighter(matchText);
        let textToDisplay = testInput.replace(matchText, highlightedText);
        stringToTest.innerHTML = textToDisplay;
        testResult.innerText = matchText;
      } else {
        testResult.innerText = "no match";
      }
  }
})

hi, i’m not sure what this is about, would you mind posting a link to the lab/exercise please?

Sorry, I thought I had :sweat_smile:

Build a RegEx Sandbox: Build a RegEx Sandbox | freeCodeCamp.org

See if this post helps you track down the issue:

Build a RegEx Sandbox - Build a RegEx Sandbox - JavaScript - The freeCodeCamp Forum