<!doctype html>
<html id="html">
<head>
<script src="../../resources/js-test-pre.js"></script>
<style id="style">
* {
    background-color: white;
}
:focus-within {
    background-color: rgb(1, 2, 3);
}
</style>
</head>
<body id="body">
    <div id="webkit-test">
        <div id="container1">
            <div id="sibling1"></div>
            <div id="sibling2">
                <input id="target1">
            </div>
            <div id="sibling3"></div>
        </div>
        <div id="container2">
            <div id="sibling4"></div>
            <div id="sibling5">
                <textarea id="target2"></textarea>
            </div>
            <div id="sibling6"></div>
        </div>
    </div>
</body>
<script>
"use strict";
description('Check the basic features of the :focus-within pseudo class');

function elementsStyledWithFocusWithinSelector() {
    let elements = [];
    for (let element of document.querySelectorAll("*")) {
        if (getComputedStyle(element).backgroundColor === 'rgb(1, 2, 3)') {
            elements.push(element.id);
        }
    }
    return elements;
}

function elementsMatchingFocusWithinSelector() {
    let elements = [];
    for (let element of document.querySelectorAll(":focus-within")) {
        elements.push(element.id);
    }
    return elements;
}

debug("Initial State");
shouldBe('elementsStyledWithFocusWithinSelector()', '[]');
shouldBe('elementsMatchingFocusWithinSelector()', '[]');

debug("Focus target1");
var target1 = document.getElementById("target1");
target1.focus();
shouldBe('elementsStyledWithFocusWithinSelector()', '["html", "body", "webkit-test", "container1", "sibling2", "target1"]');
shouldBe('elementsMatchingFocusWithinSelector()', '["html", "body", "webkit-test", "container1", "sibling2", "target1"]');

debug("Focus target2");
var target2 = document.getElementById("target2");
target2.focus();
shouldBe('elementsStyledWithFocusWithinSelector()', '["html", "body", "webkit-test", "container2", "sibling5", "target2"]');
shouldBe('elementsMatchingFocusWithinSelector()', '["html", "body", "webkit-test", "container2", "sibling5", "target2"]');

debug("Set display none on target2");
target2.style.display = "none";
// NOTE: At the time of this writing, it is is critical that this behavior, keeping focus even if display is set to "none"
// does *not* change, despite the fact that the HTML standard currently mandates a change. In 2014, an attempt to change
// this broke the facebook.com website, which depended on the behavior. See <https://bugs.webkit.org/show_bug.cgi?id=29241>.
shouldBe('elementsStyledWithFocusWithinSelector()', '["html", "body", "webkit-test", "container2", "sibling5", "target2"]');
shouldBe('elementsMatchingFocusWithinSelector()', '["html", "body", "webkit-test", "container2", "sibling5", "target2"]');
shouldBeTrue('target2.matches(":focus")');

debug("Focus target1");
target1.focus();
shouldBe('elementsStyledWithFocusWithinSelector()', '["html", "body", "webkit-test", "container1", "sibling2", "target1"]');
shouldBe('elementsMatchingFocusWithinSelector()', '["html", "body", "webkit-test", "container1", "sibling2", "target1"]');

debug("Try to focus target2");
target2.focus();
shouldBe('elementsStyledWithFocusWithinSelector()', '["html", "body", "webkit-test", "container1", "sibling2", "target1"]');
shouldBe('elementsMatchingFocusWithinSelector()', '["html", "body", "webkit-test", "container1", "sibling2", "target1"]');
shouldBeTrue('target1.matches(":focus")');
shouldBeFalse('target2.matches(":focus")');

debug("Set display back on target2");
target2.style.display = "revert";
shouldBe('elementsStyledWithFocusWithinSelector()', '["html", "body", "webkit-test", "container1", "sibling2", "target1"]');
shouldBe('elementsMatchingFocusWithinSelector()', '["html", "body", "webkit-test", "container1", "sibling2", "target1"]');

debug("Focus target2");
target2.focus();
shouldBe('elementsStyledWithFocusWithinSelector()', '["html", "body", "webkit-test", "container2", "sibling5", "target2"]');
shouldBe('elementsMatchingFocusWithinSelector()', '["html", "body", "webkit-test", "container2", "sibling5", "target2"]');

debug("Set display none on container2");
var container2 = document.getElementById("container2");
container2.style.display = "none";
shouldBe('elementsStyledWithFocusWithinSelector()', '["html", "body", "webkit-test", "container2", "sibling5", "target2"]');
shouldBe('elementsMatchingFocusWithinSelector()', '["html", "body", "webkit-test", "container2", "sibling5", "target2"]');
shouldBeTrue('target2.matches(":focus")');

debug("Focus target1");
target1.focus();
shouldBe('elementsStyledWithFocusWithinSelector()', '["html", "body", "webkit-test", "container1", "sibling2", "target1"]');
shouldBe('elementsMatchingFocusWithinSelector()', '["html", "body", "webkit-test", "container1", "sibling2", "target1"]');

debug("Try to focus target2");
target2.focus();
shouldBe('elementsStyledWithFocusWithinSelector()', '["html", "body", "webkit-test", "container1", "sibling2", "target1"]');
shouldBe('elementsMatchingFocusWithinSelector()', '["html", "body", "webkit-test", "container1", "sibling2", "target1"]');
shouldBeTrue('target1.matches(":focus")');
shouldBeFalse('target2.matches(":focus")');

debug("Set display back on container2");
var container2 = document.getElementById("container2");
container2.style.display = "revert";
shouldBe('elementsStyledWithFocusWithinSelector()', '["html", "body", "webkit-test", "container1", "sibling2", "target1"]');
shouldBe('elementsMatchingFocusWithinSelector()', '["html", "body", "webkit-test", "container1", "sibling2", "target1"]');

debug("Detach container1 from the document");
var container1 = document.getElementById("container1");
container1.parentElement.removeChild(container1);
shouldBe('elementsStyledWithFocusWithinSelector()', '[]');
shouldBe('elementsMatchingFocusWithinSelector()', '[]');
shouldBe('container1.querySelectorAll(":focus-within").length', '0');
shouldBeFalse('target1.matches(":focus")');
shouldBeFalse('target2.matches(":focus")');

debug("Try to focus target1");
target1.focus();
shouldBe('elementsStyledWithFocusWithinSelector()', '[]');
shouldBe('elementsMatchingFocusWithinSelector()', '[]');
shouldBe('container1.querySelectorAll(":focus-within").length', '0');
shouldBeFalse('target1.matches(":focus")');
shouldBeFalse('target2.matches(":focus")');

debug("Focus target2");
target2.focus();
shouldBe('elementsStyledWithFocusWithinSelector()', '["html", "body", "webkit-test", "container2", "sibling5", "target2"]');
shouldBe('elementsMatchingFocusWithinSelector()', '["html", "body", "webkit-test", "container2", "sibling5", "target2"]');

debug("Attach container1 in container2");
container2.appendChild(container1);
shouldBe('elementsStyledWithFocusWithinSelector()', '["html", "body", "webkit-test", "container2", "sibling5", "target2"]');
shouldBe('elementsMatchingFocusWithinSelector()', '["html", "body", "webkit-test", "container2", "sibling5", "target2"]');

debug("Focus target1");
target1.focus();
shouldBe('elementsStyledWithFocusWithinSelector()', '["html", "body", "webkit-test", "container2", "container1", "sibling2", "target1"]');
shouldBe('elementsMatchingFocusWithinSelector()', '["html", "body", "webkit-test", "container2", "container1", "sibling2", "target1"]');

debug("Move target1 in container2");
container2.appendChild(target1);
shouldBe('elementsStyledWithFocusWithinSelector()', '[]');
shouldBe('elementsMatchingFocusWithinSelector()', '[]');
shouldBeFalse('target1.matches(":focus")');
shouldBeFalse('target2.matches(":focus")');

gc();

// Clean up the test.
document.getElementById("webkit-test").style.display = "none";
document.getElementById("style").innerHTML = "";

</script>
<script src="../../resources/js-test-post.js"></script>
</html>
