---
id: 66e028680eca7d21db7e1aee
title: Build a RegEx Sandbox
challengeType: 25
dashedName: lab-regex-sandbox
demoType: onClick
---

# --description--

For this lab, you start with the CSS and HTML already written for you. You will use JavaScript to enable the regex sandbox to test a regular expression against a string and highlight the results.
 
**Objective:** Fulfill the user stories below and get all the tests to pass to complete the lab.

**User Stories:**

1. You should access the `#pattern`, `#test-string`, `#test-btn`, and `#result` elements and save them in the variables `regexPattern`, `stringToTest`, `testButton`, and `testResult`, respectively.
1. You should access the `#i` and `#g` flag checkboxes and save them in the variables `caseInsensitiveFlag` and `globalFlag`, respectively.
1. You should have a function named `getFlags` that returns a string containing the flags from checked flag checkboxes, or an empty string if none of them have been checked.
1. When you click the `testButton` button, if the regex pattern matches the test string, the matched text should be highlighted. To highlight the matches, replace each match with the same text surrounded by a `span` element with the class of `highlight`. Note that the CSS for that has been already added for you.
1. When there's a match, the matched text should be displayed inside `#result`. In case of multiple matches, each matched text should be separated from the next one by a comma and a space.
1. When there's no match, the text `no match` should be displayed inside `#result`.

# --hints--

You should access the `#pattern` element and save it in the `regexPattern` variable.

```js
assert.equal(regexPattern, document.querySelector('#pattern'))
```

You should access the `#test-string` element and save it in the `stringToTest` variable.

```js
assert.equal(stringToTest, document.querySelector('#test-string'))
```

You should access the `#test-btn` element and save it in the `testButton` variable.

```js
assert.equal(testButton, document.querySelector('#test-btn'))
```

You should access the `#result` element and save it in the `testResult` variable.

```js
assert.equal(testResult, document.querySelector('#result'))
```

You should access the `#i` flag checkbox and save it in the `caseInsensitiveFlag`.

```js
assert.equal(caseInsensitiveFlag, document.querySelector('#i'))
```

You should access the `#g` flag checkbox and save it in the `globalFlag` variable.

```js
assert.equal(globalFlag, document.querySelector('#g'))
```

You should have a `getFlags` function.

```js
assert.isFunction(getFlags)
```

The `getFlags` function should return `"i"` if the `#i` checkbox is checked.

```js
caseInsensitiveFlag.checked = true;
globalFlag.checked = false;
assert.equal(getFlags(), "i")
```

The `getFlags` function should return `"g"` if the `#g` checkbox is checked.

```js
caseInsensitiveFlag.checked = false;
globalFlag.checked = true;
assert.equal(getFlags(), "g")
```

The `getFlags` function should return either `"ig"` or `"gi"` if both checkboxes are checked.

```js
caseInsensitiveFlag.checked = true;
globalFlag.checked = true;
const flags = getFlags();
assert.lengthOf(flags, 2);
assert.include(flags, "i");
assert.include(flags, "g");
```

The `getFlags` function should return an empty string if both checkboxes are not checked.

```js
caseInsensitiveFlag.checked = false;
globalFlag.checked = false;
assert.equal(getFlags(), "")
```

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.

```js
stringToTest.innerText = "Gu1n34 P1g5"
regexPattern.value = "\\d+";
caseInsensitiveFlag.checked = false;
globalFlag.checked = false;
const testBtn = document.getElementById("test-btn");
testBtn.dispatchEvent(new Event("click"));
let expected = 'Gu<span class="highlight">1</span>n34 P1g5';
assert.equal(stringToTest.innerHTML, expected);
```

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.

```js
stringToTest.innerText = "Gu1n34 P1g5"
regexPattern.value = "\\d+";
caseInsensitiveFlag.checked = false;
globalFlag.checked = true;
const testBtn = document.getElementById("test-btn");
testBtn.dispatchEvent(new Event("click"));
let expected = 'Gu<span class="highlight">1</span>n<span class="highlight">34</span> P<span class="highlight">1</span>g<span class="highlight">5</span>';
assert.equal(stringToTest.innerHTML, expected);
```

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.

```js
stringToTest.innerText = "Gu1n34 P1g5"
regexPattern.value = "G";
caseInsensitiveFlag.checked = true;
globalFlag.checked = true;
const testBtn = document.getElementById("test-btn");
testBtn.dispatchEvent(new Event("click"));
let expected = '<span class="highlight">G</span>u1n34 P1<span class="highlight">g</span>5';
assert.equal(stringToTest.innerHTML, expected);
```

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`. 

```js
stringToTest.innerText = "She sells seashells by the seashore."
regexPattern.value = "s[he]a?";
caseInsensitiveFlag.checked = true;
globalFlag.checked = true;
const testBtn = document.getElementById("test-btn");
testBtn.dispatchEvent(new Event("click"));
let expected = '<span class="highlight">Sh</span>e <span class="highlight">se</span>lls <span class="highlight">sea</span><span class="highlight">sh</span>ells by the <span class="highlight">sea</span><span class="highlight">sh</span>ore.';
assert.strictEqual(stringToTest.innerHTML, expected);

stringToTest.innerText = "She sells seashells by the seashore."
caseInsensitiveFlag.checked = false;
globalFlag.checked = true;
testBtn.dispatchEvent(new Event("click"));
expected = 'She <span class="highlight">se</span>lls <span class="highlight">sea</span><span class="highlight">sh</span>ells by the <span class="highlight">sea</span><span class="highlight">sh</span>ore.';
assert.strictEqual(stringToTest.innerHTML, expected);

stringToTest.innerText = "She sells seashells by the seashore."
globalFlag.checked = false;
testBtn.dispatchEvent(new Event("click"));
expected = 'She <span class="highlight">se</span>lls seashells by the seashore.';
assert.strictEqual(stringToTest.innerHTML, expected);

stringToTest.innerText = "She sells seashells by the seashore."
caseInsensitiveFlag.checked = true;
testBtn.dispatchEvent(new Event("click"));
expected = '<span class="highlight">Sh</span>e sells seashells by the seashore.';
assert.strictEqual(stringToTest.innerHTML, expected);
```

When there's no match, the test string shouldn't be modified.

```js
stringToTest.innerText = "She sells seashells by the seashore."
regexPattern.value = "sea\\s";
const testBtn = document.getElementById("test-btn");
testBtn.dispatchEvent(new Event("click"));
let expected = 'She sells seashells by the seashore.';
assert.strictEqual(stringToTest.innerHTML, expected);
```

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.

```js
const out = document.getElementById("result");
stringToTest.innerText = "Gu1n34 P1g5"
regexPattern.value = "\\d+";
caseInsensitiveFlag.checked = false;
globalFlag.checked = false;
const testBtn = document.getElementById("test-btn");
testBtn.dispatchEvent(new Event("click"));
let expected = "1"
assert.strictEqual(out.innerText, expected)
```

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.

```js
const out = document.getElementById("result");
stringToTest.innerText = "Gu1n34 P1g5"
regexPattern.value = "\\d+";
caseInsensitiveFlag.checked = false;
globalFlag.checked = true;
const testBtn = document.getElementById("test-btn");
testBtn.dispatchEvent(new Event("click"));
let expected = "1, 34, 1, 5"
assert.strictEqual(out.innerText, expected)
```

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

```js
const out = document.getElementById("result");
stringToTest.innerText = "She sells seashells by the seashore."
regexPattern.value = "s[he]a?";
caseInsensitiveFlag.checked = true;
globalFlag.checked = true;
const testBtn = document.getElementById("test-btn");
testBtn.dispatchEvent(new Event("click"));
let expected = "Sh, se, sea, sh, sea, sh"
assert.strictEqual(out.innerText, expected)

stringToTest.innerText = "She sells seashells by the seashore."
caseInsensitiveFlag.checked = false;
testBtn.dispatchEvent(new Event("click"));
expected = "se, sea, sh, sea, sh"
assert.strictEqual(out.innerText, expected)

stringToTest.innerText = "She sells seashells by the seashore."
globalFlag.checked = false;
testBtn.dispatchEvent(new Event("click"));
expected = "se"
assert.strictEqual(out.innerText, expected)

stringToTest.innerText = "She sells seashells by the seashore."
caseInsensitiveFlag.checked = true;
testBtn.dispatchEvent(new Event("click"));
expected = "Sh"
assert.strictEqual(out.innerText, expected)
```

When there's no match, the text `no match` should be displayed inside `#result`.

```js
const out = document.getElementById("result");
stringToTest.innerText = "She sells seashells by the seashore."
regexPattern.value = "sea\\s";
const testBtn = document.getElementById("test-btn");
testBtn.dispatchEvent(new Event("click"));
let expected = "no match";
assert.strictEqual(out.innerText, expected);
```

# --seed--

## --seed-contents--

```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>
```

```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;
}
```

```js

```

# --solutions--

```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>
```

```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;
}

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;
}
```

```js
const regexPattern = document.getElementById("pattern");
const caseInsensitiveFlag = document.getElementById("i");
const globalFlag = document.getElementById("g");
const testResult = document.getElementById("result");
const getFlags = () => {
    let flags = '';
    const flagArray = [caseInsensitiveFlag, globalFlag]
    flagArray.forEach((flag) => {
        if (flag.checked) flags += flag.id;
    })
    return flags
}
const stringToTest = document.getElementById("test-string");
const testButton = document.getElementById("test-btn")
testButton.addEventListener(
    "click",
    () => {
        let matched;
        let flags = getFlags();
        const regex = new RegExp(regexPattern.value, flags)
        if (flags.includes(globalFlag)) {
            stringToTest.innerHTML = stringToTest.innerText.replaceAll(regex, '<span class="highlight">$&</span>')
            matched = stringToTest.innerText.matchAll(regex)
        } else {
            stringToTest.innerHTML = stringToTest.innerText.replace(regex, '<span class="highlight">$&</span>')
            matched = stringToTest.innerText.match(regex);             
        }
        testResult.innerText = matched ? matched.join(", ") : 'no match';
    }
)
```
