• 1 Using JavaScript
    • 1.1 Absolute Frequency Items
    • 1.2 Script to grey out Next button

1 Using JavaScript

The base structure of JavaScript syntax in Qualtrics is as follows:

Qualtrics.SurveyEngine.addOnload(function()
{
    /*Place your JavaScript here to run when the page loads*/

});

Qualtrics.SurveyEngine.addOnReady(function()
{
    /*Place your JavaScript here to run when the page is fully displayed*/

});

Qualtrics.SurveyEngine.addOnUnload(function()
{
    /*Place your JavaScript here to run when the page is unloaded*/

});

1.1 Absolute Frequency Items

Absolute frequency items have three columns:

  1. “amount”, i.e., number of times per interval
  2. “timeframe”, i.e., per day/week, in the past month, in the past year
  3. “not in the past year”

where respondents are expected to fill in the first two columns and check the third column if they have not experienced the event in the past year. That is, the respondent should fill in EITHER the first two columns OR check the third column. The JavaScript code below is used to ensure that if the third column is checked, the first two columns are hidden and cleared. It also ensures that at least one of the first two columns is filled in or that the third column is checked before allowing the survey next button to be clicked to advance the survey to the next page. It allows for this advancement logic to function for three blocks of absolute frequency questions on the same page. If you would like to add additional blocks, identify their QID by clicking Preview in Qualtrics, right clicking, and selecting “Inspect”. Then click on the survey block you want to identify and enter the QID where it says “add any additional blocks here” below.

Qualtrics.SurveyEngine.addOnReady(function () {
    console.log("✅ SBS script running for", this.questionId);

    /* ------------------------------------------------------------------
       1.  === per-row formatting + checkbox-hide logic ===
    ------------------------------------------------------------------ */

    var matrix = this.getQuestionContainer();
    var rows   = matrix.querySelectorAll("tr.Choice");
    var that   = this;

    var headerCell = matrix.querySelector("th");
    if (headerCell) headerCell.style.width = "300px";

    for (var r = 0; r < rows.length; r++) {
        (function (row) {
            var cells = row.querySelectorAll("td");
            if (cells.length < 9) return;

            var textCell     = cells[2];      // text input
            var dropdownCell = cells[5];      // dropdown
            var checkboxCell = cells[8];      // checkbox
            var checkbox     = checkboxCell.querySelector("input[type='checkbox']");
            var inputField   = textCell.querySelector("input[type='text']");
            var dropdownFld  = dropdownCell.querySelector("select");

            var labelCell = row.querySelector("td:first-child");
            if (labelCell) labelCell.style.width = "300px";

            textCell.style.width     = "100px";
            dropdownCell.style.width = "160px";
            checkboxCell.style.width = "120px";
            checkboxCell.style.textAlign = "center";
            textCell.style.borderRight   = "none";
            dropdownCell.style.borderRight = "none";

            for (var i = 0; i < cells.length; i++) {
                if (cells[i].className.indexOf("Separator") !== -1) {
                    cells[i].style.display   = "";
                    cells[i].style.minWidth  = "1px";
                    cells[i].style.width     = "1px";
                    cells[i].style.borderRight = "1px solid #ccc";
                    cells[i].style.borderLeft  = "none";
                    if (cells[i].innerHTML.trim() === "") cells[i].innerHTML = "&nbsp;";
                }
            }

            //  -- initial hide if checkbox pre-checked
            if (checkbox && checkbox.checked) {
                textCell.style.visibility     = "hidden";
                dropdownCell.style.visibility = "hidden";
                textCell.style.border         = "none";
                dropdownCell.style.border     = "none";
                if (inputField)  inputField.value          = "";
                if (dropdownFld) dropdownFld.selectedIndex = 0;
            }

            //  -- live hide/show when checkbox toggled
            if (checkbox) {
                checkbox.addEventListener("change", function () {
                    var hide = checkbox.checked;

                    textCell.style.visibility     = hide ? "hidden" : "visible";
                    dropdownCell.style.visibility = hide ? "hidden" : "visible";
                    textCell.style.border         = hide ? "none" : "";
                    dropdownCell.style.border     = hide ? "none" : "";

                    if (hide) {
                        if (inputField)  inputField.value          = "";
                        if (dropdownFld) dropdownFld.selectedIndex = 0;
                    }
                });
            }
        })(rows[r]);
    }

    /* ------------------------------------------------------------------
       2. === global “all 3 blocks must be complete” validation =========
    ------------------------------------------------------------------ */

    /* create the shared tracker once (first time any block loads) */
    if (!window.SBSCompletion) {
        window.SBSCompletion = { "QID1": false, "QID10": false, "QID12": false };
    }

    function rowIsValid(cells) {
        var textInput  = cells[2].querySelector("input[type='text']");
        var dropdown   = cells[5].querySelector("select");
        var checkbox   = cells[8].querySelector("input[type='checkbox']");

        var inputHas   = textInput  && textInput.value.trim() !== "";
        var dropHas    = dropdown   && dropdown.value.trim()  !== "";
        var checkHas   = checkbox   && checkbox.checked;

        return (inputHas && dropHas) || checkHas;
    }

    function validateThisBlock() {
        var everyRowValid = true;
        for (var r = 0; r < rows.length; r++) {
            var cells = rows[r].querySelectorAll("td");
            if (cells.length < 9) continue;
            if (!rowIsValid(cells)) { everyRowValid = false; }
        }

        /* store this block’s status */
        window.SBSCompletion[that.questionId] = everyRowValid;

        /* check all three blocks */
        var allDone = window.SBSCompletion["QID1"] &&
                      window.SBSCompletion["QID10"] &&
                      window.SBSCompletion["QID12"]; /* add any additional blocks here */

        if (allDone) { that.enableNextButton(); }
        else         { that.disableNextButton(); }
    }

    /* disable Next on first load */
    that.disableNextButton();
    
    /* attach listeners */
    setTimeout(validateThisBlock, 300);
    matrix.addEventListener("input",  validateThisBlock);
    matrix.addEventListener("change", validateThisBlock);
    
        // set up interval for rechecking validation; this re-enables the script in case Qualtrics overrides it after some time interval
    var validationInterval = setInterval(validateThisBlock, 5000);

    // clean up interval on page unload
    Qualtrics.SurveyEngine.addOnUnload(function () {
        clearInterval(validationInterval);
    });
});

1.2 Script to grey out Next button

Qualtrics.SurveyEngine.addOnReady(function () {
    console.log("✅ SBS script running for", this.questionId);

    /* ------------------------------------------------------------------
       1.  === your original per-row formatting + checkbox-hide logic ===
           (unchanged except for one comment line to show where it ends)
    ------------------------------------------------------------------ */

    var matrix = this.getQuestionContainer();
    var rows   = matrix.querySelectorAll("tr.Choice");   // works in your SBS
    var that   = this;

    var headerCell = matrix.querySelector("th");
    if (headerCell) headerCell.style.width = "300px";

    for (var r = 0; r < rows.length; r++) {
        (function (row) {
            var cells = row.querySelectorAll("td");
            if (cells.length < 9) return;

            var textCell     = cells[2];      // text input
            var dropdownCell = cells[5];      // dropdown
            var checkboxCell = cells[8];      // checkbox
            var checkbox     = checkboxCell.querySelector("input[type='checkbox']");
            var inputField   = textCell.querySelector("input[type='text']");
            var dropdownFld  = dropdownCell.querySelector("select");

            var labelCell = row.querySelector("td:first-child");
            if (labelCell) labelCell.style.width = "300px";

            textCell.style.width     = "100px";
            dropdownCell.style.width = "160px";
            checkboxCell.style.width = "120px";
            checkboxCell.style.textAlign = "center";
            textCell.style.borderRight   = "none";
            dropdownCell.style.borderRight = "none";

            for (var i = 0; i < cells.length; i++) {
                if (cells[i].className.indexOf("Separator") !== -1) {
                    cells[i].style.display   = "";
                    cells[i].style.minWidth  = "1px";
                    cells[i].style.width     = "1px";
                    cells[i].style.borderRight = "1px solid #ccc";
                    cells[i].style.borderLeft  = "none";
                    if (cells[i].innerHTML.trim() === "") cells[i].innerHTML = "&nbsp;";
                }
            }

            //  -- initial hide if checkbox pre-checked
            if (checkbox && checkbox.checked) {
                textCell.style.visibility     = "hidden";
                dropdownCell.style.visibility = "hidden";
                textCell.style.border         = "none";
                dropdownCell.style.border     = "none";
                if (inputField)  inputField.value          = "";
                if (dropdownFld) dropdownFld.selectedIndex = 0;
            }

            //  -- live hide/show when checkbox toggled
            if (checkbox) {
                checkbox.addEventListener("change", function () {
                    var hide = checkbox.checked;

                    textCell.style.visibility     = hide ? "hidden" : "visible";
                    dropdownCell.style.visibility = hide ? "hidden" : "visible";
                    textCell.style.border         = hide ? "none" : "";
                    dropdownCell.style.border     = hide ? "none" : "";

                    if (hide) {
                        if (inputField)  inputField.value          = "";
                        if (dropdownFld) dropdownFld.selectedIndex = 0;
                    }
                });
            }
        })(rows[r]);
    }
    /* ------------------------ end original section ------------------- */


    /* ------------------------------------------------------------------
       2. === global “all 3 blocks must be complete” validation =========
    ------------------------------------------------------------------ */

    /* create the shared tracker once (first time any block loads) */
    if (!window.SBSCompletion) {
        window.SBSCompletion = { "QID1": false, "QID10": false, "QID12": false };
    }

    function rowIsValid(cells) {
        var textInput  = cells[2].querySelector("input[type='text']");
        var dropdown   = cells[5].querySelector("select");
        var checkbox   = cells[8].querySelector("input[type='checkbox']");

        var inputHas   = textInput  && textInput.value.trim() !== "";
        var dropHas    = dropdown   && dropdown.value.trim()  !== "";
        var checkHas   = checkbox   && checkbox.checked;

        return (inputHas && dropHas) || checkHas;
    }

    function validateThisBlock() {
        var everyRowValid = true;
        for (var r = 0; r < rows.length; r++) {
            var cells = rows[r].querySelectorAll("td");
            if (cells.length < 9) continue;
            if (!rowIsValid(cells)) { everyRowValid = false; }
        }

        /* store this block’s status */
        window.SBSCompletion[that.questionId] = everyRowValid;

        /* check all three blocks */
        var allDone = window.SBSCompletion["QID1"] &&
                      window.SBSCompletion["QID10"] &&
                      window.SBSCompletion["QID12"];

        if (allDone) { that.enableNextButton(); }
        else         { that.disableNextButton(); }
    }

    /* disable Next on first load */
    that.disableNextButton();

    /* delay initial validation slightly to ensure elements are rendered */
    setTimeout(validateThisBlock, 100);  // 100ms delay ensures all DOM elements are accessible

    /* attach listeners */
    matrix.addEventListener("input",  validateThisBlock);
    matrix.addEventListener("change", validateThisBlock);
});
LS0tCnRpdGxlOiAiUXVhbHRyaWNzIE1hbnVhbCIKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZSA9IEZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoCiAgZWNobyA9IFRSVUUsCiAgZXJyb3IgPSBUUlVFLAogIGNvbW1lbnQgPSAiIikKYGBgCgojIFVzaW5nIEphdmFTY3JpcHQgeyNqYXZhc2NyaXB0fQoKVGhlIGJhc2Ugc3RydWN0dXJlIG9mIEphdmFTY3JpcHQgc3ludGF4IGluIFF1YWx0cmljcyBpcyBhcyBmb2xsb3dzOgoKYGBgamF2YXNjcmlwdApRdWFsdHJpY3MuU3VydmV5RW5naW5lLmFkZE9ubG9hZChmdW5jdGlvbigpCnsKCS8qUGxhY2UgeW91ciBKYXZhU2NyaXB0IGhlcmUgdG8gcnVuIHdoZW4gdGhlIHBhZ2UgbG9hZHMqLwoKfSk7CgpRdWFsdHJpY3MuU3VydmV5RW5naW5lLmFkZE9uUmVhZHkoZnVuY3Rpb24oKQp7CgkvKlBsYWNlIHlvdXIgSmF2YVNjcmlwdCBoZXJlIHRvIHJ1biB3aGVuIHRoZSBwYWdlIGlzIGZ1bGx5IGRpc3BsYXllZCovCgp9KTsKClF1YWx0cmljcy5TdXJ2ZXlFbmdpbmUuYWRkT25VbmxvYWQoZnVuY3Rpb24oKQp7CgkvKlBsYWNlIHlvdXIgSmF2YVNjcmlwdCBoZXJlIHRvIHJ1biB3aGVuIHRoZSBwYWdlIGlzIHVubG9hZGVkKi8KCn0pOwpgYGAKCiMjIEFic29sdXRlIEZyZXF1ZW5jeSBJdGVtcyB7I2Fic29sdXRlRnJlcXVlbmN5fQoKQWJzb2x1dGUgZnJlcXVlbmN5IGl0ZW1zIGhhdmUgdGhyZWUgY29sdW1uczoKCjEuICJhbW91bnQiLCBpLmUuLCBudW1iZXIgb2YgdGltZXMgcGVyIGludGVydmFsCjEuICJ0aW1lZnJhbWUiLCBpLmUuLCBwZXIgZGF5L3dlZWssIGluIHRoZSBwYXN0IG1vbnRoLCBpbiB0aGUgcGFzdCB5ZWFyCjEuICJub3QgaW4gdGhlIHBhc3QgeWVhciIKCndoZXJlIHJlc3BvbmRlbnRzIGFyZSBleHBlY3RlZCB0byBmaWxsIGluIHRoZSBmaXJzdCB0d28gY29sdW1ucyBhbmQgY2hlY2sgdGhlIHRoaXJkIGNvbHVtbiBpZiB0aGV5IGhhdmUgbm90IGV4cGVyaWVuY2VkIHRoZSBldmVudCBpbiB0aGUgcGFzdCB5ZWFyLgpUaGF0IGlzLCB0aGUgcmVzcG9uZGVudCBzaG91bGQgZmlsbCBpbiBFSVRIRVIgdGhlIGZpcnN0IHR3byBjb2x1bW5zIE9SIGNoZWNrIHRoZSB0aGlyZCBjb2x1bW4uClRoZSBKYXZhU2NyaXB0IGNvZGUgYmVsb3cgaXMgdXNlZCB0byBlbnN1cmUgdGhhdCBpZiB0aGUgdGhpcmQgY29sdW1uIGlzIGNoZWNrZWQsIHRoZSBmaXJzdCB0d28gY29sdW1ucyBhcmUgaGlkZGVuIGFuZCBjbGVhcmVkLgpJdCBhbHNvIGVuc3VyZXMgdGhhdCBhdCBsZWFzdCBvbmUgb2YgdGhlIGZpcnN0IHR3byBjb2x1bW5zIGlzIGZpbGxlZCBpbiBvciB0aGF0IHRoZSB0aGlyZCBjb2x1bW4gaXMgY2hlY2tlZCBiZWZvcmUgYWxsb3dpbmcgdGhlIHN1cnZleSBuZXh0IGJ1dHRvbiB0byBiZSBjbGlja2VkIHRvIGFkdmFuY2UgdGhlIHN1cnZleSB0byB0aGUgbmV4dCBwYWdlLgpJdCBhbGxvd3MgZm9yIHRoaXMgYWR2YW5jZW1lbnQgbG9naWMgdG8gZnVuY3Rpb24gZm9yIHRocmVlIGJsb2NrcyBvZiBhYnNvbHV0ZSBmcmVxdWVuY3kgcXVlc3Rpb25zIG9uIHRoZSBzYW1lIHBhZ2UuCklmIHlvdSB3b3VsZCBsaWtlIHRvIGFkZCBhZGRpdGlvbmFsIGJsb2NrcywgaWRlbnRpZnkgdGhlaXIgUUlEIGJ5IGNsaWNraW5nIFByZXZpZXcgaW4gUXVhbHRyaWNzLCByaWdodCBjbGlja2luZywgYW5kIHNlbGVjdGluZyAiSW5zcGVjdCIuClRoZW4gY2xpY2sgb24gdGhlIHN1cnZleSBibG9jayB5b3Ugd2FudCB0byBpZGVudGlmeSBhbmQgZW50ZXIgdGhlIFFJRCB3aGVyZSBpdCBzYXlzICJhZGQgYW55IGFkZGl0aW9uYWwgYmxvY2tzIGhlcmUiIGJlbG93LgoKYGBgamF2YXNjcmlwdApRdWFsdHJpY3MuU3VydmV5RW5naW5lLmFkZE9uUmVhZHkoZnVuY3Rpb24gKCkgewogICAgY29uc29sZS5sb2coIuKchSBTQlMgc2NyaXB0IHJ1bm5pbmcgZm9yIiwgdGhpcy5xdWVzdGlvbklkKTsKCiAgICAvKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KICAgICAgIDEuICA9PT0gcGVyLXJvdyBmb3JtYXR0aW5nICsgY2hlY2tib3gtaGlkZSBsb2dpYyA9PT0KICAgIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAqLwoKICAgIHZhciBtYXRyaXggPSB0aGlzLmdldFF1ZXN0aW9uQ29udGFpbmVyKCk7CiAgICB2YXIgcm93cyAgID0gbWF0cml4LnF1ZXJ5U2VsZWN0b3JBbGwoInRyLkNob2ljZSIpOwogICAgdmFyIHRoYXQgICA9IHRoaXM7CgogICAgdmFyIGhlYWRlckNlbGwgPSBtYXRyaXgucXVlcnlTZWxlY3RvcigidGgiKTsKICAgIGlmIChoZWFkZXJDZWxsKSBoZWFkZXJDZWxsLnN0eWxlLndpZHRoID0gIjMwMHB4IjsKCiAgICBmb3IgKHZhciByID0gMDsgciA8IHJvd3MubGVuZ3RoOyByKyspIHsKICAgICAgICAoZnVuY3Rpb24gKHJvdykgewogICAgICAgICAgICB2YXIgY2VsbHMgPSByb3cucXVlcnlTZWxlY3RvckFsbCgidGQiKTsKICAgICAgICAgICAgaWYgKGNlbGxzLmxlbmd0aCA8IDkpIHJldHVybjsKCiAgICAgICAgICAgIHZhciB0ZXh0Q2VsbCAgICAgPSBjZWxsc1syXTsgICAgICAvLyB0ZXh0IGlucHV0CiAgICAgICAgICAgIHZhciBkcm9wZG93bkNlbGwgPSBjZWxsc1s1XTsgICAgICAvLyBkcm9wZG93bgogICAgICAgICAgICB2YXIgY2hlY2tib3hDZWxsID0gY2VsbHNbOF07ICAgICAgLy8gY2hlY2tib3gKICAgICAgICAgICAgdmFyIGNoZWNrYm94ICAgICA9IGNoZWNrYm94Q2VsbC5xdWVyeVNlbGVjdG9yKCJpbnB1dFt0eXBlPSdjaGVja2JveCddIik7CiAgICAgICAgICAgIHZhciBpbnB1dEZpZWxkICAgPSB0ZXh0Q2VsbC5xdWVyeVNlbGVjdG9yKCJpbnB1dFt0eXBlPSd0ZXh0J10iKTsKICAgICAgICAgICAgdmFyIGRyb3Bkb3duRmxkICA9IGRyb3Bkb3duQ2VsbC5xdWVyeVNlbGVjdG9yKCJzZWxlY3QiKTsKCiAgICAgICAgICAgIHZhciBsYWJlbENlbGwgPSByb3cucXVlcnlTZWxlY3RvcigidGQ6Zmlyc3QtY2hpbGQiKTsKICAgICAgICAgICAgaWYgKGxhYmVsQ2VsbCkgbGFiZWxDZWxsLnN0eWxlLndpZHRoID0gIjMwMHB4IjsKCiAgICAgICAgICAgIHRleHRDZWxsLnN0eWxlLndpZHRoICAgICA9ICIxMDBweCI7CiAgICAgICAgICAgIGRyb3Bkb3duQ2VsbC5zdHlsZS53aWR0aCA9ICIxNjBweCI7CiAgICAgICAgICAgIGNoZWNrYm94Q2VsbC5zdHlsZS53aWR0aCA9ICIxMjBweCI7CiAgICAgICAgICAgIGNoZWNrYm94Q2VsbC5zdHlsZS50ZXh0QWxpZ24gPSAiY2VudGVyIjsKICAgICAgICAgICAgdGV4dENlbGwuc3R5bGUuYm9yZGVyUmlnaHQgICA9ICJub25lIjsKICAgICAgICAgICAgZHJvcGRvd25DZWxsLnN0eWxlLmJvcmRlclJpZ2h0ID0gIm5vbmUiOwoKICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjZWxscy5sZW5ndGg7IGkrKykgewogICAgICAgICAgICAgICAgaWYgKGNlbGxzW2ldLmNsYXNzTmFtZS5pbmRleE9mKCJTZXBhcmF0b3IiKSAhPT0gLTEpIHsKICAgICAgICAgICAgICAgICAgICBjZWxsc1tpXS5zdHlsZS5kaXNwbGF5ICAgPSAiIjsKICAgICAgICAgICAgICAgICAgICBjZWxsc1tpXS5zdHlsZS5taW5XaWR0aCAgPSAiMXB4IjsKICAgICAgICAgICAgICAgICAgICBjZWxsc1tpXS5zdHlsZS53aWR0aCAgICAgPSAiMXB4IjsKICAgICAgICAgICAgICAgICAgICBjZWxsc1tpXS5zdHlsZS5ib3JkZXJSaWdodCA9ICIxcHggc29saWQgI2NjYyI7CiAgICAgICAgICAgICAgICAgICAgY2VsbHNbaV0uc3R5bGUuYm9yZGVyTGVmdCAgPSAibm9uZSI7CiAgICAgICAgICAgICAgICAgICAgaWYgKGNlbGxzW2ldLmlubmVySFRNTC50cmltKCkgPT09ICIiKSBjZWxsc1tpXS5pbm5lckhUTUwgPSAiJm5ic3A7IjsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQoKICAgICAgICAgICAgLy8gIC0tIGluaXRpYWwgaGlkZSBpZiBjaGVja2JveCBwcmUtY2hlY2tlZAogICAgICAgICAgICBpZiAoY2hlY2tib3ggJiYgY2hlY2tib3guY2hlY2tlZCkgewogICAgICAgICAgICAgICAgdGV4dENlbGwuc3R5bGUudmlzaWJpbGl0eSAgICAgPSAiaGlkZGVuIjsKICAgICAgICAgICAgICAgIGRyb3Bkb3duQ2VsbC5zdHlsZS52aXNpYmlsaXR5ID0gImhpZGRlbiI7CiAgICAgICAgICAgICAgICB0ZXh0Q2VsbC5zdHlsZS5ib3JkZXIgICAgICAgICA9ICJub25lIjsKICAgICAgICAgICAgICAgIGRyb3Bkb3duQ2VsbC5zdHlsZS5ib3JkZXIgICAgID0gIm5vbmUiOwogICAgICAgICAgICAgICAgaWYgKGlucHV0RmllbGQpICBpbnB1dEZpZWxkLnZhbHVlICAgICAgICAgID0gIiI7CiAgICAgICAgICAgICAgICBpZiAoZHJvcGRvd25GbGQpIGRyb3Bkb3duRmxkLnNlbGVjdGVkSW5kZXggPSAwOwogICAgICAgICAgICB9CgogICAgICAgICAgICAvLyAgLS0gbGl2ZSBoaWRlL3Nob3cgd2hlbiBjaGVja2JveCB0b2dnbGVkCiAgICAgICAgICAgIGlmIChjaGVja2JveCkgewogICAgICAgICAgICAgICAgY2hlY2tib3guYWRkRXZlbnRMaXN0ZW5lcigiY2hhbmdlIiwgZnVuY3Rpb24gKCkgewogICAgICAgICAgICAgICAgICAgIHZhciBoaWRlID0gY2hlY2tib3guY2hlY2tlZDsKCiAgICAgICAgICAgICAgICAgICAgdGV4dENlbGwuc3R5bGUudmlzaWJpbGl0eSAgICAgPSBoaWRlID8gImhpZGRlbiIgOiAidmlzaWJsZSI7CiAgICAgICAgICAgICAgICAgICAgZHJvcGRvd25DZWxsLnN0eWxlLnZpc2liaWxpdHkgPSBoaWRlID8gImhpZGRlbiIgOiAidmlzaWJsZSI7CiAgICAgICAgICAgICAgICAgICAgdGV4dENlbGwuc3R5bGUuYm9yZGVyICAgICAgICAgPSBoaWRlID8gIm5vbmUiIDogIiI7CiAgICAgICAgICAgICAgICAgICAgZHJvcGRvd25DZWxsLnN0eWxlLmJvcmRlciAgICAgPSBoaWRlID8gIm5vbmUiIDogIiI7CgogICAgICAgICAgICAgICAgICAgIGlmIChoaWRlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpbnB1dEZpZWxkKSAgaW5wdXRGaWVsZC52YWx1ZSAgICAgICAgICA9ICIiOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoZHJvcGRvd25GbGQpIGRyb3Bkb3duRmxkLnNlbGVjdGVkSW5kZXggPSAwOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICB9CiAgICAgICAgfSkocm93c1tyXSk7CiAgICB9CgogICAgLyogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiAgICAgICAyLiA9PT0gZ2xvYmFsIOKAnGFsbCAzIGJsb2NrcyBtdXN0IGJlIGNvbXBsZXRl4oCdIHZhbGlkYXRpb24gPT09PT09PT09CiAgICAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gKi8KCiAgICAvKiBjcmVhdGUgdGhlIHNoYXJlZCB0cmFja2VyIG9uY2UgKGZpcnN0IHRpbWUgYW55IGJsb2NrIGxvYWRzKSAqLwogICAgaWYgKCF3aW5kb3cuU0JTQ29tcGxldGlvbikgewogICAgICAgIHdpbmRvdy5TQlNDb21wbGV0aW9uID0geyAiUUlEMSI6IGZhbHNlLCAiUUlEMTAiOiBmYWxzZSwgIlFJRDEyIjogZmFsc2UgfTsKICAgIH0KCiAgICBmdW5jdGlvbiByb3dJc1ZhbGlkKGNlbGxzKSB7CiAgICAgICAgdmFyIHRleHRJbnB1dCAgPSBjZWxsc1syXS5xdWVyeVNlbGVjdG9yKCJpbnB1dFt0eXBlPSd0ZXh0J10iKTsKICAgICAgICB2YXIgZHJvcGRvd24gICA9IGNlbGxzWzVdLnF1ZXJ5U2VsZWN0b3IoInNlbGVjdCIpOwogICAgICAgIHZhciBjaGVja2JveCAgID0gY2VsbHNbOF0ucXVlcnlTZWxlY3RvcigiaW5wdXRbdHlwZT0nY2hlY2tib3gnXSIpOwoKICAgICAgICB2YXIgaW5wdXRIYXMgICA9IHRleHRJbnB1dCAgJiYgdGV4dElucHV0LnZhbHVlLnRyaW0oKSAhPT0gIiI7CiAgICAgICAgdmFyIGRyb3BIYXMgICAgPSBkcm9wZG93biAgICYmIGRyb3Bkb3duLnZhbHVlLnRyaW0oKSAgIT09ICIiOwogICAgICAgIHZhciBjaGVja0hhcyAgID0gY2hlY2tib3ggICAmJiBjaGVja2JveC5jaGVja2VkOwoKICAgICAgICByZXR1cm4gKGlucHV0SGFzICYmIGRyb3BIYXMpIHx8IGNoZWNrSGFzOwogICAgfQoKICAgIGZ1bmN0aW9uIHZhbGlkYXRlVGhpc0Jsb2NrKCkgewogICAgICAgIHZhciBldmVyeVJvd1ZhbGlkID0gdHJ1ZTsKICAgICAgICBmb3IgKHZhciByID0gMDsgciA8IHJvd3MubGVuZ3RoOyByKyspIHsKICAgICAgICAgICAgdmFyIGNlbGxzID0gcm93c1tyXS5xdWVyeVNlbGVjdG9yQWxsKCJ0ZCIpOwogICAgICAgICAgICBpZiAoY2VsbHMubGVuZ3RoIDwgOSkgY29udGludWU7CiAgICAgICAgICAgIGlmICghcm93SXNWYWxpZChjZWxscykpIHsgZXZlcnlSb3dWYWxpZCA9IGZhbHNlOyB9CiAgICAgICAgfQoKICAgICAgICAvKiBzdG9yZSB0aGlzIGJsb2Nr4oCZcyBzdGF0dXMgKi8KICAgICAgICB3aW5kb3cuU0JTQ29tcGxldGlvblt0aGF0LnF1ZXN0aW9uSWRdID0gZXZlcnlSb3dWYWxpZDsKCiAgICAgICAgLyogY2hlY2sgYWxsIHRocmVlIGJsb2NrcyAqLwogICAgICAgIHZhciBhbGxEb25lID0gd2luZG93LlNCU0NvbXBsZXRpb25bIlFJRDEiXSAmJgogICAgICAgICAgICAgICAgICAgICAgd2luZG93LlNCU0NvbXBsZXRpb25bIlFJRDEwIl0gJiYKICAgICAgICAgICAgICAgICAgICAgIHdpbmRvdy5TQlNDb21wbGV0aW9uWyJRSUQxMiJdOyAvKiBhZGQgYW55IGFkZGl0aW9uYWwgYmxvY2tzIGhlcmUgKi8KCiAgICAgICAgaWYgKGFsbERvbmUpIHsgdGhhdC5lbmFibGVOZXh0QnV0dG9uKCk7IH0KICAgICAgICBlbHNlICAgICAgICAgeyB0aGF0LmRpc2FibGVOZXh0QnV0dG9uKCk7IH0KICAgIH0KCiAgICAvKiBkaXNhYmxlIE5leHQgb24gZmlyc3QgbG9hZCAqLwogICAgdGhhdC5kaXNhYmxlTmV4dEJ1dHRvbigpOwoJCiAgICAvKiBhdHRhY2ggbGlzdGVuZXJzICovCglzZXRUaW1lb3V0KHZhbGlkYXRlVGhpc0Jsb2NrLCAzMDApOwogICAgbWF0cml4LmFkZEV2ZW50TGlzdGVuZXIoImlucHV0IiwgIHZhbGlkYXRlVGhpc0Jsb2NrKTsKICAgIG1hdHJpeC5hZGRFdmVudExpc3RlbmVyKCJjaGFuZ2UiLCB2YWxpZGF0ZVRoaXNCbG9jayk7CgkKCSAgICAvLyBzZXQgdXAgaW50ZXJ2YWwgZm9yIHJlY2hlY2tpbmcgdmFsaWRhdGlvbjsgdGhpcyByZS1lbmFibGVzIHRoZSBzY3JpcHQgaW4gY2FzZSBRdWFsdHJpY3Mgb3ZlcnJpZGVzIGl0IGFmdGVyIHNvbWUgdGltZSBpbnRlcnZhbAogICAgdmFyIHZhbGlkYXRpb25JbnRlcnZhbCA9IHNldEludGVydmFsKHZhbGlkYXRlVGhpc0Jsb2NrLCA1MDAwKTsKCiAgICAvLyBjbGVhbiB1cCBpbnRlcnZhbCBvbiBwYWdlIHVubG9hZAogICAgUXVhbHRyaWNzLlN1cnZleUVuZ2luZS5hZGRPblVubG9hZChmdW5jdGlvbiAoKSB7CiAgICAgICAgY2xlYXJJbnRlcnZhbCh2YWxpZGF0aW9uSW50ZXJ2YWwpOwogICAgfSk7Cn0pOwpgYGAKCiMjIFNjcmlwdCB0byBncmV5IG91dCBOZXh0IGJ1dHRvbgpgYGBqYXZhc2NyaXB0ClF1YWx0cmljcy5TdXJ2ZXlFbmdpbmUuYWRkT25SZWFkeShmdW5jdGlvbiAoKSB7CiAgICBjb25zb2xlLmxvZygi4pyFIFNCUyBzY3JpcHQgcnVubmluZyBmb3IiLCB0aGlzLnF1ZXN0aW9uSWQpOwoKICAgIC8qIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQogICAgICAgMS4gID09PSB5b3VyIG9yaWdpbmFsIHBlci1yb3cgZm9ybWF0dGluZyArIGNoZWNrYm94LWhpZGUgbG9naWMgPT09CiAgICAgICAgICAgKHVuY2hhbmdlZCBleGNlcHQgZm9yIG9uZSBjb21tZW50IGxpbmUgdG8gc2hvdyB3aGVyZSBpdCBlbmRzKQogICAgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICovCgogICAgdmFyIG1hdHJpeCA9IHRoaXMuZ2V0UXVlc3Rpb25Db250YWluZXIoKTsKICAgIHZhciByb3dzICAgPSBtYXRyaXgucXVlcnlTZWxlY3RvckFsbCgidHIuQ2hvaWNlIik7ICAgLy8gd29ya3MgaW4geW91ciBTQlMKICAgIHZhciB0aGF0ICAgPSB0aGlzOwoKICAgIHZhciBoZWFkZXJDZWxsID0gbWF0cml4LnF1ZXJ5U2VsZWN0b3IoInRoIik7CiAgICBpZiAoaGVhZGVyQ2VsbCkgaGVhZGVyQ2VsbC5zdHlsZS53aWR0aCA9ICIzMDBweCI7CgogICAgZm9yICh2YXIgciA9IDA7IHIgPCByb3dzLmxlbmd0aDsgcisrKSB7CiAgICAgICAgKGZ1bmN0aW9uIChyb3cpIHsKICAgICAgICAgICAgdmFyIGNlbGxzID0gcm93LnF1ZXJ5U2VsZWN0b3JBbGwoInRkIik7CiAgICAgICAgICAgIGlmIChjZWxscy5sZW5ndGggPCA5KSByZXR1cm47CgogICAgICAgICAgICB2YXIgdGV4dENlbGwgICAgID0gY2VsbHNbMl07ICAgICAgLy8gdGV4dCBpbnB1dAogICAgICAgICAgICB2YXIgZHJvcGRvd25DZWxsID0gY2VsbHNbNV07ICAgICAgLy8gZHJvcGRvd24KICAgICAgICAgICAgdmFyIGNoZWNrYm94Q2VsbCA9IGNlbGxzWzhdOyAgICAgIC8vIGNoZWNrYm94CiAgICAgICAgICAgIHZhciBjaGVja2JveCAgICAgPSBjaGVja2JveENlbGwucXVlcnlTZWxlY3RvcigiaW5wdXRbdHlwZT0nY2hlY2tib3gnXSIpOwogICAgICAgICAgICB2YXIgaW5wdXRGaWVsZCAgID0gdGV4dENlbGwucXVlcnlTZWxlY3RvcigiaW5wdXRbdHlwZT0ndGV4dCddIik7CiAgICAgICAgICAgIHZhciBkcm9wZG93bkZsZCAgPSBkcm9wZG93bkNlbGwucXVlcnlTZWxlY3Rvcigic2VsZWN0Iik7CgogICAgICAgICAgICB2YXIgbGFiZWxDZWxsID0gcm93LnF1ZXJ5U2VsZWN0b3IoInRkOmZpcnN0LWNoaWxkIik7CiAgICAgICAgICAgIGlmIChsYWJlbENlbGwpIGxhYmVsQ2VsbC5zdHlsZS53aWR0aCA9ICIzMDBweCI7CgogICAgICAgICAgICB0ZXh0Q2VsbC5zdHlsZS53aWR0aCAgICAgPSAiMTAwcHgiOwogICAgICAgICAgICBkcm9wZG93bkNlbGwuc3R5bGUud2lkdGggPSAiMTYwcHgiOwogICAgICAgICAgICBjaGVja2JveENlbGwuc3R5bGUud2lkdGggPSAiMTIwcHgiOwogICAgICAgICAgICBjaGVja2JveENlbGwuc3R5bGUudGV4dEFsaWduID0gImNlbnRlciI7CiAgICAgICAgICAgIHRleHRDZWxsLnN0eWxlLmJvcmRlclJpZ2h0ICAgPSAibm9uZSI7CiAgICAgICAgICAgIGRyb3Bkb3duQ2VsbC5zdHlsZS5ib3JkZXJSaWdodCA9ICJub25lIjsKCiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY2VsbHMubGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgICAgIGlmIChjZWxsc1tpXS5jbGFzc05hbWUuaW5kZXhPZigiU2VwYXJhdG9yIikgIT09IC0xKSB7CiAgICAgICAgICAgICAgICAgICAgY2VsbHNbaV0uc3R5bGUuZGlzcGxheSAgID0gIiI7CiAgICAgICAgICAgICAgICAgICAgY2VsbHNbaV0uc3R5bGUubWluV2lkdGggID0gIjFweCI7CiAgICAgICAgICAgICAgICAgICAgY2VsbHNbaV0uc3R5bGUud2lkdGggICAgID0gIjFweCI7CiAgICAgICAgICAgICAgICAgICAgY2VsbHNbaV0uc3R5bGUuYm9yZGVyUmlnaHQgPSAiMXB4IHNvbGlkICNjY2MiOwogICAgICAgICAgICAgICAgICAgIGNlbGxzW2ldLnN0eWxlLmJvcmRlckxlZnQgID0gIm5vbmUiOwogICAgICAgICAgICAgICAgICAgIGlmIChjZWxsc1tpXS5pbm5lckhUTUwudHJpbSgpID09PSAiIikgY2VsbHNbaV0uaW5uZXJIVE1MID0gIiZuYnNwOyI7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIC8vICAtLSBpbml0aWFsIGhpZGUgaWYgY2hlY2tib3ggcHJlLWNoZWNrZWQKICAgICAgICAgICAgaWYgKGNoZWNrYm94ICYmIGNoZWNrYm94LmNoZWNrZWQpIHsKICAgICAgICAgICAgICAgIHRleHRDZWxsLnN0eWxlLnZpc2liaWxpdHkgICAgID0gImhpZGRlbiI7CiAgICAgICAgICAgICAgICBkcm9wZG93bkNlbGwuc3R5bGUudmlzaWJpbGl0eSA9ICJoaWRkZW4iOwogICAgICAgICAgICAgICAgdGV4dENlbGwuc3R5bGUuYm9yZGVyICAgICAgICAgPSAibm9uZSI7CiAgICAgICAgICAgICAgICBkcm9wZG93bkNlbGwuc3R5bGUuYm9yZGVyICAgICA9ICJub25lIjsKICAgICAgICAgICAgICAgIGlmIChpbnB1dEZpZWxkKSAgaW5wdXRGaWVsZC52YWx1ZSAgICAgICAgICA9ICIiOwogICAgICAgICAgICAgICAgaWYgKGRyb3Bkb3duRmxkKSBkcm9wZG93bkZsZC5zZWxlY3RlZEluZGV4ID0gMDsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgLy8gIC0tIGxpdmUgaGlkZS9zaG93IHdoZW4gY2hlY2tib3ggdG9nZ2xlZAogICAgICAgICAgICBpZiAoY2hlY2tib3gpIHsKICAgICAgICAgICAgICAgIGNoZWNrYm94LmFkZEV2ZW50TGlzdGVuZXIoImNoYW5nZSIsIGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgICAgICAgICB2YXIgaGlkZSA9IGNoZWNrYm94LmNoZWNrZWQ7CgogICAgICAgICAgICAgICAgICAgIHRleHRDZWxsLnN0eWxlLnZpc2liaWxpdHkgICAgID0gaGlkZSA/ICJoaWRkZW4iIDogInZpc2libGUiOwogICAgICAgICAgICAgICAgICAgIGRyb3Bkb3duQ2VsbC5zdHlsZS52aXNpYmlsaXR5ID0gaGlkZSA/ICJoaWRkZW4iIDogInZpc2libGUiOwogICAgICAgICAgICAgICAgICAgIHRleHRDZWxsLnN0eWxlLmJvcmRlciAgICAgICAgID0gaGlkZSA/ICJub25lIiA6ICIiOwogICAgICAgICAgICAgICAgICAgIGRyb3Bkb3duQ2VsbC5zdHlsZS5ib3JkZXIgICAgID0gaGlkZSA/ICJub25lIiA6ICIiOwoKICAgICAgICAgICAgICAgICAgICBpZiAoaGlkZSkgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAoaW5wdXRGaWVsZCkgIGlucHV0RmllbGQudmFsdWUgICAgICAgICAgPSAiIjsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRyb3Bkb3duRmxkKSBkcm9wZG93bkZsZC5zZWxlY3RlZEluZGV4ID0gMDsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgfQogICAgICAgIH0pKHJvd3Nbcl0pOwogICAgfQogICAgLyogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIGVuZCBvcmlnaW5hbCBzZWN0aW9uIC0tLS0tLS0tLS0tLS0tLS0tLS0gKi8KCgogICAgLyogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiAgICAgICAyLiA9PT0gZ2xvYmFsIOKAnGFsbCAzIGJsb2NrcyBtdXN0IGJlIGNvbXBsZXRl4oCdIHZhbGlkYXRpb24gPT09PT09PT09CiAgICAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gKi8KCiAgICAvKiBjcmVhdGUgdGhlIHNoYXJlZCB0cmFja2VyIG9uY2UgKGZpcnN0IHRpbWUgYW55IGJsb2NrIGxvYWRzKSAqLwogICAgaWYgKCF3aW5kb3cuU0JTQ29tcGxldGlvbikgewogICAgICAgIHdpbmRvdy5TQlNDb21wbGV0aW9uID0geyAiUUlEMSI6IGZhbHNlLCAiUUlEMTAiOiBmYWxzZSwgIlFJRDEyIjogZmFsc2UgfTsKICAgIH0KCiAgICBmdW5jdGlvbiByb3dJc1ZhbGlkKGNlbGxzKSB7CiAgICAgICAgdmFyIHRleHRJbnB1dCAgPSBjZWxsc1syXS5xdWVyeVNlbGVjdG9yKCJpbnB1dFt0eXBlPSd0ZXh0J10iKTsKICAgICAgICB2YXIgZHJvcGRvd24gICA9IGNlbGxzWzVdLnF1ZXJ5U2VsZWN0b3IoInNlbGVjdCIpOwogICAgICAgIHZhciBjaGVja2JveCAgID0gY2VsbHNbOF0ucXVlcnlTZWxlY3RvcigiaW5wdXRbdHlwZT0nY2hlY2tib3gnXSIpOwoKICAgICAgICB2YXIgaW5wdXRIYXMgICA9IHRleHRJbnB1dCAgJiYgdGV4dElucHV0LnZhbHVlLnRyaW0oKSAhPT0gIiI7CiAgICAgICAgdmFyIGRyb3BIYXMgICAgPSBkcm9wZG93biAgICYmIGRyb3Bkb3duLnZhbHVlLnRyaW0oKSAgIT09ICIiOwogICAgICAgIHZhciBjaGVja0hhcyAgID0gY2hlY2tib3ggICAmJiBjaGVja2JveC5jaGVja2VkOwoKICAgICAgICByZXR1cm4gKGlucHV0SGFzICYmIGRyb3BIYXMpIHx8IGNoZWNrSGFzOwogICAgfQoKICAgIGZ1bmN0aW9uIHZhbGlkYXRlVGhpc0Jsb2NrKCkgewogICAgICAgIHZhciBldmVyeVJvd1ZhbGlkID0gdHJ1ZTsKICAgICAgICBmb3IgKHZhciByID0gMDsgciA8IHJvd3MubGVuZ3RoOyByKyspIHsKICAgICAgICAgICAgdmFyIGNlbGxzID0gcm93c1tyXS5xdWVyeVNlbGVjdG9yQWxsKCJ0ZCIpOwogICAgICAgICAgICBpZiAoY2VsbHMubGVuZ3RoIDwgOSkgY29udGludWU7CiAgICAgICAgICAgIGlmICghcm93SXNWYWxpZChjZWxscykpIHsgZXZlcnlSb3dWYWxpZCA9IGZhbHNlOyB9CiAgICAgICAgfQoKICAgICAgICAvKiBzdG9yZSB0aGlzIGJsb2Nr4oCZcyBzdGF0dXMgKi8KICAgICAgICB3aW5kb3cuU0JTQ29tcGxldGlvblt0aGF0LnF1ZXN0aW9uSWRdID0gZXZlcnlSb3dWYWxpZDsKCiAgICAgICAgLyogY2hlY2sgYWxsIHRocmVlIGJsb2NrcyAqLwogICAgICAgIHZhciBhbGxEb25lID0gd2luZG93LlNCU0NvbXBsZXRpb25bIlFJRDEiXSAmJgogICAgICAgICAgICAgICAgICAgICAgd2luZG93LlNCU0NvbXBsZXRpb25bIlFJRDEwIl0gJiYKICAgICAgICAgICAgICAgICAgICAgIHdpbmRvdy5TQlNDb21wbGV0aW9uWyJRSUQxMiJdOwoKICAgICAgICBpZiAoYWxsRG9uZSkgeyB0aGF0LmVuYWJsZU5leHRCdXR0b24oKTsgfQogICAgICAgIGVsc2UgICAgICAgICB7IHRoYXQuZGlzYWJsZU5leHRCdXR0b24oKTsgfQogICAgfQoKICAgIC8qIGRpc2FibGUgTmV4dCBvbiBmaXJzdCBsb2FkICovCiAgICB0aGF0LmRpc2FibGVOZXh0QnV0dG9uKCk7CgogICAgLyogZGVsYXkgaW5pdGlhbCB2YWxpZGF0aW9uIHNsaWdodGx5IHRvIGVuc3VyZSBlbGVtZW50cyBhcmUgcmVuZGVyZWQgKi8KICAgIHNldFRpbWVvdXQodmFsaWRhdGVUaGlzQmxvY2ssIDEwMCk7ICAvLyAxMDBtcyBkZWxheSBlbnN1cmVzIGFsbCBET00gZWxlbWVudHMgYXJlIGFjY2Vzc2libGUKCiAgICAvKiBhdHRhY2ggbGlzdGVuZXJzICovCiAgICBtYXRyaXguYWRkRXZlbnRMaXN0ZW5lcigiaW5wdXQiLCAgdmFsaWRhdGVUaGlzQmxvY2spOwogICAgbWF0cml4LmFkZEV2ZW50TGlzdGVuZXIoImNoYW5nZSIsIHZhbGlkYXRlVGhpc0Jsb2NrKTsKfSk7CmBgYAo=



Developmental Psychopathology Lab