Skip welcome & menu and move to editor
Welcome to JS Bin
Load cached copy from
 
<!DOCTYPE html>
<style>
table {
    width: 250px;
}
td {
    width: 242px;
}
.cell-specified-height {
    height: 202px;
}
.container {
    height: 100%;
    overflow-y: hidden;
}
.content {
    background-color: black;
    height: 2000px;
    width: 225px;
}
</style>
<table>
    <td class="cell-specified-height" data-expected-height=206>
        <div class="container" data-expected-height=204>
            <div class="content" data-expected-height=2000></div>
        </div>
    </td>
</table>
<div id="output"></div>
 
function insertAfter(nodeToAdd, referenceNode)
{
    if (referenceNode == document.body) {
        document.body.appendChild(nodeToAdd);
        return;
    }
    if (referenceNode.nextSibling)
        referenceNode.parentNode.insertBefore(nodeToAdd, referenceNode.nextSibling);
    else
        referenceNode.parentNode.appendChild(nodeToAdd);
}
function checkSubtreeExpectedValues(parent, failures)
{
    var checkedLayout = checkExpectedValues(parent, failures);
    Array.prototype.forEach.call(parent.childNodes, function(node) {
        checkedLayout |= checkSubtreeExpectedValues(node, failures);
    });
    return checkedLayout;
}
function checkAttribute(output, node, attribute)
{
    var result = node.getAttribute && node.getAttribute(attribute);
    output.checked |= !!result;
    return result;
}
function checkExpectedValues(node, failures)
{
    var output = { checked: false };
    var expectedWidth = checkAttribute(output, node, "data-expected-width");
    if (expectedWidth) {
        if (isNaN(expectedWidth) || Math.abs(node.offsetWidth - expectedWidth) >= 1)
            failures.push("Expected " + expectedWidth + " for width, but got " + node.offsetWidth + ". ");
    }
    var expectedHeight = checkAttribute(output, node, "data-expected-height");
    if (expectedHeight) {
        if (isNaN(expectedHeight) || Math.abs(node.offsetHeight - expectedHeight) >= 1)
            failures.push("Expected " + expectedHeight + " for height, but got " + node.offsetHeight + ". ");
    }
    var expectedOffset = checkAttribute(output, node, "data-offset-x");
    if (expectedOffset) {
        if (isNaN(expectedOffset) || Math.abs(node.offsetLeft - expectedOffset) >= 1)
            failures.push("Expected " + expectedOffset + " for offsetLeft, but got " + node.offsetLeft + ". ");
    }
    var expectedOffset = checkAttribute(output, node, "data-offset-y");
    if (expectedOffset) {
        if (isNaN(expectedOffset) || Math.abs(node.offsetTop - expectedOffset) >= 1)
            failures.push("Expected " + expectedOffset + " for offsetTop, but got " + node.offsetTop + ". ");
    }
    var expectedWidth = checkAttribute(output, node, "data-expected-client-width");
    if (expectedWidth) {
        if (isNaN(expectedWidth) || Math.abs(node.clientWidth - expectedWidth) >= 1)
            failures.push("Expected " + expectedWidth + " for clientWidth, but got " + node.clientWidth + ". ");
    }
    var expectedHeight = checkAttribute(output, node, "data-expected-client-height");
    if (expectedHeight) {
        if (isNaN(expectedHeight) || Math.abs(node.clientHeight - expectedHeight) >= 1)
            failures.push("Expected " + expectedHeight + " for clientHeight, but got " + node.clientHeight + ". ");
    }
    var expectedWidth = checkAttribute(output, node, "data-expected-scroll-width");
    if (expectedWidth) {
        if (isNaN(expectedWidth) || Math.abs(node.scrollWidth - expectedWidth) >= 1)
            failures.push("Expected " + expectedWidth + " for scrollWidth, but got " + node.scrollWidth + ". ");
    }
    var expectedHeight = checkAttribute(output, node, "data-expected-scroll-height");
    if (expectedHeight) {
        if (isNaN(expectedHeight) || Math.abs(node.scrollHeight - expectedHeight) >= 1)
            failures.push("Expected " + expectedHeight + " for scrollHeight, but got " + node.scrollHeight + ". ");
    }
    var expectedOffset = checkAttribute(output, node, "data-total-x");
    if (expectedOffset) {
        var totalLeft = node.clientLeft + node.offsetLeft;
        if (isNaN(expectedOffset) || Math.abs(totalLeft - expectedOffset) >= 1)
            failures.push("Expected " + expectedOffset + " for clientLeft+offsetLeft, but got " + totalLeft + ", clientLeft: " + node.clientLeft + ", offsetLeft: " + node.offsetLeft + ". ");
    }
    var expectedOffset = checkAttribute(output, node, "data-total-y");
    if (expectedOffset) {
        var totalTop = node.clientTop + node.offsetTop;
        if (isNaN(expectedOffset) || Math.abs(totalTop - expectedOffset) >= 1)
            failures.push("Expected " + expectedOffset + " for clientTop+offsetTop, but got " + totalTop + ", clientTop: " + node.clientTop + ", + offsetTop: " + node.offsetTop + ". ");
    }
    var expectedDisplay = checkAttribute(output, node, "data-expected-display");
    if (expectedDisplay) {
        var actualDisplay = getComputedStyle(node).display;
        if (actualDisplay != expectedDisplay)
            failures.push("Expected " + expectedDisplay + " for display, but got " + actualDisplay + ". ");
    }
    var expectedPaddingTop = checkAttribute(output, node, "data-expected-padding-top");
    if (expectedPaddingTop) {
        var actualPaddingTop = getComputedStyle(node).paddingTop;
        // Trim the unit "px" from the output.
        actualPaddingTop = actualPaddingTop.substring(0, actualPaddingTop.length - 2);
        if (actualPaddingTop != expectedPaddingTop)
            failures.push("Expected " + expectedPaddingTop + " for padding-top, but got " + actualPaddingTop + ". ");
    }
    var expectedPaddingBottom = checkAttribute(output, node, "data-expected-padding-bottom");
    if (expectedPaddingBottom) {
        var actualPaddingBottom = getComputedStyle(node).paddingBottom;
        // Trim the unit "px" from the output.
        actualPaddingBottom = actualPaddingBottom.substring(0, actualPaddingBottom.length - 2);
        if (actualPaddingBottom != expectedPaddingBottom)
            failures.push("Expected " + expectedPaddingBottom + " for padding-bottom, but got " + actualPaddingBottom + ". ");
    }
    var expectedPaddingLeft = checkAttribute(output, node, "data-expected-padding-left");
    if (expectedPaddingLeft) {
        var actualPaddingLeft = getComputedStyle(node).paddingLeft;
        // Trim the unit "px" from the output.
        actualPaddingLeft = actualPaddingLeft.substring(0, actualPaddingLeft.length - 2);
        if (actualPaddingLeft != expectedPaddingLeft)
            failures.push("Expected " + expectedPaddingLeft + " for padding-left, but got " + actualPaddingLeft + ". ");
    }
    var expectedPaddingRight = checkAttribute(output, node, "data-expected-padding-right");
    if (expectedPaddingRight) {
        var actualPaddingRight = getComputedStyle(node).paddingRight;
        // Trim the unit "px" from the output.
        actualPaddingRight = actualPaddingRight.substring(0, actualPaddingRight.length - 2);
        if (actualPaddingRight != expectedPaddingRight)
            failures.push("Expected " + expectedPaddingRight + " for padding-right, but got " + actualPaddingRight + ". ");
    }
    var expectedMarginTop = checkAttribute(output, node, "data-expected-margin-top");
    if (expectedMarginTop) {
        var actualMarginTop = getComputedStyle(node).marginTop;
        // Trim the unit "px" from the output.
        actualMarginTop = actualMarginTop.substring(0, actualMarginTop.length - 2);
        if (actualMarginTop != expectedMarginTop)
            failures.push("Expected " + expectedMarginTop + " for margin-top, but got " + actualMarginTop + ". ");
    }
    var expectedMarginBottom = checkAttribute(output, node, "data-expected-margin-bottom");
    if (expectedMarginBottom) {
        var actualMarginBottom = getComputedStyle(node).marginBottom;
        // Trim the unit "px" from the output.
        actualMarginBottom = actualMarginBottom.substring(0, actualMarginBottom.length - 2);
        if (actualMarginBottom != expectedMarginBottom)
            failures.push("Expected " + expectedMarginBottom + " for margin-bottom, but got " + actualMarginBottom + ". ");
    }
    var expectedMarginLeft = checkAttribute(output, node, "data-expected-margin-left");
    if (expectedMarginLeft) {
        var actualMarginLeft = getComputedStyle(node).marginLeft;
        // Trim the unit "px" from the output.
        actualMarginLeft = actualMarginLeft.substring(0, actualMarginLeft.length - 2);
        if (actualMarginLeft != expectedMarginLeft)
            failures.push("Expected " + expectedMarginLeft + " for margin-left, but got " + actualMarginLeft + ". ");
    }
    var expectedMarginRight = checkAttribute(output, node, "data-expected-margin-right");
    if (expectedMarginRight) {
        var actualMarginRight = getComputedStyle(node).marginRight;
        // Trim the unit "px" from the output.
        actualMarginRight = actualMarginRight.substring(0, actualMarginRight.length - 2);
        if (actualMarginRight != expectedMarginRight)
            failures.push("Expected " + expectedMarginRight + " for margin-right, but got " + actualMarginRight + ". ");
    }
    return output.checked;
}
window.checkLayout = function(selectorList, outputContainer)
{
    var result = true;
    if (!selectorList) {
        console.error("You must provide a CSS selector of nodes to check.");
        return;
    }
    var nodes = document.querySelectorAll(selectorList);
    nodes = Array.prototype.slice.call(nodes);
    nodes.reverse();
    var checkedLayout = false;
    Array.prototype.forEach.call(nodes, function(node) {
        var failures = [];
        checkedLayout |= checkExpectedValues(node.parentNode, failures);
        checkedLayout |= checkSubtreeExpectedValues(node, failures);
        var container = node.parentNode.className == 'container' ? node.parentNode : node;
        var pre = document.createElement('pre');
        if (failures.length) {
            pre.className = 'FAIL';
            result = false;
        }
        pre.appendChild(document.createTextNode(failures.length ? "FAIL:\n" + failures.join('\n') + '\n\n' + container.outerHTML : "PASS"));
        var referenceNode = container;
        if (outputContainer) {
            if (!outputContainer.lastChild) {
                // Inserting a text node so we have something to insertAfter.
                outputContainer.textContent = " ";
            }
            referenceNode = outputContainer.lastChild;
        }
        insertAfter(pre, referenceNode);
    });
    if (!checkedLayout) {
        document.body.innerHTML = "FAIL: No valid data-* attributes found in selector list : " + selectorList;
        return false;
    }
    var pre = document.querySelector('.FAIL');
    if (pre)
        setTimeout(function() { pre.previousSibling.scrollIntoView(); }, 0);
    return result;
}
window.checkLayout('.content', output);
window.checkLayout('.cell-specified-height', output);
window.checkLayout('.container', output);
Output

You can jump to the latest bin by adding /latest to your URL

Dismiss x
public
Bin info
anonymouspro
0viewers