1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/tests/mochitest/general/test_offsets.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,209 @@ 1.4 +var scrollbarWidth = 17, scrollbarHeight = 17; 1.5 + 1.6 +function testElements(baseid, callback) 1.7 +{ 1.8 + scrollbarWidth = scrollbarHeight = gcs($("scrollbox-test"), "width"); 1.9 + 1.10 + var elements = $(baseid).getElementsByTagName("*"); 1.11 + for (var t = 0; t < elements.length; t++) { 1.12 + var element = elements[t]; 1.13 + testElement(element); 1.14 + } 1.15 + 1.16 + var nonappended = document.createElement("div"); 1.17 + nonappended.id = "nonappended"; 1.18 + nonappended.setAttribute("_offsetParent", "null"); 1.19 + testElement(nonappended); 1.20 + 1.21 + checkScrolledElement($("scrollbox"), $("scrollchild")); 1.22 + 1.23 + var div = $("noscroll"); 1.24 + div.scrollLeft = 10; 1.25 + div.scrollTop = 10; 1.26 + is(element.scrollLeft, 0, element.id + " scrollLeft after nonscroll"); 1.27 + is(element.scrollTop, 0, element.id + " scrollTop after nonscroll"); 1.28 + 1.29 + callback(); 1.30 +} 1.31 + 1.32 +function toNearestAppunit(v) 1.33 +{ 1.34 + // 60 appunits per CSS pixel; round result to the nearest appunit 1.35 + return Math.round(v*60)/60; 1.36 +} 1.37 + 1.38 +function isEqualAppunits(a, b, msg) 1.39 +{ 1.40 + is(toNearestAppunit(a), toNearestAppunit(b), msg); 1.41 +} 1.42 + 1.43 +function testElement(element) 1.44 +{ 1.45 + var offsetParent = element.getAttribute("_offsetParent"); 1.46 + offsetParent = $(offsetParent == "null" ? null: (offsetParent ? offsetParent : "body")); 1.47 + 1.48 + var borderLeft = gcs(element, "borderLeftWidth"); 1.49 + var borderTop = gcs(element, "borderTopWidth"); 1.50 + var borderRight = gcs(element, "borderRightWidth"); 1.51 + var borderBottom = gcs(element, "borderBottomWidth"); 1.52 + var paddingLeft = gcs(element, "paddingLeft"); 1.53 + var paddingTop = gcs(element, "paddingTop"); 1.54 + var paddingRight = gcs(element, "paddingRight"); 1.55 + var paddingBottom = gcs(element, "paddingBottom"); 1.56 + var width = gcs(element, "width"); 1.57 + var height = gcs(element, "height"); 1.58 + 1.59 + if (element instanceof HTMLElement) 1.60 + checkOffsetState(element, -10000, -10000, 1.61 + borderLeft + paddingLeft + width + paddingRight + borderRight, 1.62 + borderTop + paddingTop + height + paddingBottom + borderBottom, 1.63 + offsetParent, element.id); 1.64 + 1.65 + var scrollWidth, scrollHeight, clientWidth, clientHeight; 1.66 + var doScrollCheck = true; 1.67 + if (element.id == "scrollbox") { 1.68 + var lastchild = $("lastline"); 1.69 + scrollWidth = lastchild.getBoundingClientRect().width + paddingLeft + paddingRight; 1.70 + var top = element.firstChild.getBoundingClientRect().top; 1.71 + var bottom = element.lastChild.getBoundingClientRect().bottom; 1.72 + var contentsHeight = bottom - top; 1.73 + scrollHeight = contentsHeight + paddingTop + paddingBottom; 1.74 + clientWidth = paddingLeft + width + paddingRight - scrollbarWidth; 1.75 + clientHeight = paddingTop + height + paddingBottom - scrollbarHeight; 1.76 + } else { 1.77 + clientWidth = paddingLeft + width + paddingRight; 1.78 + clientHeight = paddingTop + height + paddingBottom; 1.79 + if (element.id == "overflow-visible") { 1.80 + scrollWidth = 200; 1.81 + scrollHeight = 201; 1.82 + } else if (element.scrollWidth > clientWidth || 1.83 + element.scrollHeight > clientHeight) { 1.84 + // The element overflows. Don't check scrollWidth/scrollHeight since the 1.85 + // above calculation is not correct. 1.86 + doScrollCheck = false; 1.87 + } else { 1.88 + scrollWidth = clientWidth; 1.89 + scrollHeight = clientHeight; 1.90 + } 1.91 + } 1.92 + 1.93 + if (doScrollCheck) { 1.94 + if (element instanceof SVGElement) 1.95 + checkScrollState(element, 0, 0, 0, 0, element.id); 1.96 + else 1.97 + checkScrollState(element, 0, 0, scrollWidth, scrollHeight, element.id); 1.98 + } 1.99 + 1.100 + if (element instanceof SVGElement) 1.101 + checkClientState(element, 0, 0, 0, 0, element.id); 1.102 + else 1.103 + checkClientState(element, borderLeft, borderTop, clientWidth, clientHeight, element.id); 1.104 + 1.105 + var boundingrect = element.getBoundingClientRect(); 1.106 + isEqualAppunits(boundingrect.width, borderLeft + paddingLeft + width + paddingRight + borderRight, 1.107 + element.id + " bounding rect width"); 1.108 + isEqualAppunits(boundingrect.height, borderTop + paddingTop + height + paddingBottom + borderBottom, 1.109 + element.id + " bounding rect height"); 1.110 + isEqualAppunits(boundingrect.right - boundingrect.left, boundingrect.width, 1.111 + element.id + " bounding rect right"); 1.112 + isEqualAppunits(boundingrect.bottom - boundingrect.top, boundingrect.height, 1.113 + element.id + " bounding rect bottom"); 1.114 + 1.115 + var rects = element.getClientRects(); 1.116 + if (element.id == "div-displaynone" || element.id == "nonappended") { 1.117 + is(rects.length, 0, element.id + " getClientRects empty"); 1.118 + } 1.119 + else { 1.120 + is(rects[0].left, boundingrect.left, element.id + " getClientRects left"); 1.121 + is(rects[0].top, boundingrect.top, element.id + " getClientRects top"); 1.122 + is(rects[0].right, boundingrect.right, element.id + " getClientRects right"); 1.123 + is(rects[0].bottom, boundingrect.bottom, element.id + " getClientRects bottom"); 1.124 + } 1.125 +} 1.126 + 1.127 +function checkScrolledElement(element, child) 1.128 +{ 1.129 + var elemrect = element.getBoundingClientRect(); 1.130 + var childrect = child.getBoundingClientRect(); 1.131 + 1.132 + var topdiff = childrect.top - elemrect.top; 1.133 + 1.134 + element.scrollTop = 20; 1.135 + is(element.scrollLeft, 0, element.id + " scrollLeft after vertical scroll"); 1.136 + is(element.scrollTop, 20, element.id + " scrollTop after vertical scroll"); 1.137 + // If the viewport has been transformed, then we might have scrolled to a subpixel value 1.138 + // that's slightly different from what we requested. After rounding, however, it should 1.139 + // be the same. 1.140 + is(Math.round(childrect.top - child.getBoundingClientRect().top), 20, "child position after vertical scroll"); 1.141 + 1.142 + element.scrollTop = 0; 1.143 + is(element.scrollLeft, 0, element.id + " scrollLeft after vertical scroll reset"); 1.144 + is(element.scrollTop, 0, element.id + " scrollTop after vertical scroll reset"); 1.145 + // Scrolling back to the top should work precisely. 1.146 + is(child.getBoundingClientRect().top, childrect.top, "child position after vertical scroll reset"); 1.147 + 1.148 + element.scrollTop = 10; 1.149 + element.scrollTop = -30; 1.150 + is(element.scrollLeft, 0, element.id + " scrollLeft after vertical scroll negative"); 1.151 + is(element.scrollTop, 0, element.id + " scrollTop after vertical scroll negative"); 1.152 + is(child.getBoundingClientRect().top, childrect.top, "child position after vertical scroll negative"); 1.153 + 1.154 + element.scrollLeft = 18; 1.155 + is(element.scrollLeft, 18, element.id + " scrollLeft after horizontal scroll"); 1.156 + is(element.scrollTop, 0, element.id + " scrollTop after horizontal scroll"); 1.157 + is(Math.round(childrect.left - child.getBoundingClientRect().left), 18, "child position after horizontal scroll"); 1.158 + 1.159 + element.scrollLeft = -30; 1.160 + is(element.scrollLeft, 0, element.id + " scrollLeft after horizontal scroll reset"); 1.161 + is(element.scrollTop, 0, element.id + " scrollTop after horizontal scroll reset"); 1.162 + is(child.getBoundingClientRect().left, childrect.left, "child position after horizontal scroll reset"); 1.163 +} 1.164 + 1.165 +function checkOffsetState(element, left, top, width, height, parent, testname) 1.166 +{ 1.167 + checkCoords(element, "offset", left, top, width, height, testname); 1.168 + is(element.offsetParent, parent, testname + " offsetParent"); 1.169 +} 1.170 + 1.171 +function checkScrollState(element, left, top, width, height, testname) 1.172 +{ 1.173 + checkCoords(element, "scroll", left, top, width, height, testname); 1.174 +} 1.175 + 1.176 +function checkClientState(element, left, top, width, height, testname) 1.177 +{ 1.178 + checkCoords(element, "client", left, top, width, height, testname); 1.179 +} 1.180 + 1.181 +function checkCoord(element, type, val, testname) 1.182 +{ 1.183 + if (val != -10000) 1.184 + is(element[type], Math.round(val), testname + " " + type); 1.185 +} 1.186 + 1.187 +function checkCoords(element, type, left, top, width, height, testname) 1.188 +{ 1.189 + checkCoord(element, type + "Left", left, testname); 1.190 + checkCoord(element, type + "Top", top, testname); 1.191 + checkCoord(element, type + "Width", width, testname); 1.192 + checkCoord(element, type + "Height", height, testname); 1.193 + 1.194 + if (element instanceof SVGElement) 1.195 + return; 1.196 + 1.197 + if (element.id == "outerpopup" && !element.parentNode.open) // closed popup 1.198 + return; 1.199 + 1.200 + if (element.id == "div-displaynone" || element.id == "nonappended") // hidden elements 1.201 + ok(element[type + "Width"] == 0 && element[type + "Height"] == 0, 1.202 + element.id + " has zero " + type + " width and height"); 1.203 +} 1.204 + 1.205 +function gcs(element, prop) 1.206 +{ 1.207 + var propVal = (element instanceof SVGElement && (prop == "width" || prop == "height")) ? 1.208 + element.getAttribute(prop) : getComputedStyle(element, "")[prop]; 1.209 + if (propVal == "auto") 1.210 + return 0; 1.211 + return parseFloat(propVal); 1.212 +}