UNPKG

quixote

Version:

CSS unit and integration testing

182 lines (155 loc) 8.25 kB
// Copyright (c) 2014 Titanium I.T. LLC. All rights reserved. For license, see "README" or "LICENSE" file. "use strict"; var ensure = require("../util/ensure.js"); var PositionDescriptor = require("./position_descriptor.js"); var Position = require("../values/position.js"); var TOP = "top"; var RIGHT = "right"; var BOTTOM = "bottom"; var LEFT = "left"; var Me = module.exports = function PageEdge(edge, browsingContext) { var BrowsingContext = require("../browsing_context.js"); // break circular dependency ensure.signature(arguments, [ String, BrowsingContext ]); this.should = this.createShould(); if (edge === LEFT || edge === RIGHT) PositionDescriptor.x(this); else if (edge === TOP || edge === BOTTOM) PositionDescriptor.y(this); else ensure.unreachable("Unknown edge: " + edge); this._edge = edge; this._browsingContext = browsingContext; }; PositionDescriptor.extend(Me); Me.top = factoryFn(TOP); Me.right = factoryFn(RIGHT); Me.bottom = factoryFn(BOTTOM); Me.left = factoryFn(LEFT); Me.prototype.value = function value() { ensure.signature(arguments, []); var size = pageSize(this._browsingContext.contentDocument); switch(this._edge) { case TOP: return Position.y(0); case RIGHT: return Position.x(size.width); case BOTTOM: return Position.y(size.height); case LEFT: return Position.x(0); default: ensure.unreachable(); } }; Me.prototype.toString = function toString() { ensure.signature(arguments, []); switch(this._edge) { case TOP: return "top of page"; case RIGHT: return "right side of page"; case BOTTOM: return "bottom of page"; case LEFT: return "left side of page"; default: ensure.unreachable(); } }; function factoryFn(edge) { return function factory(browsingContext) { return new Me(edge, browsingContext); }; } // USEFUL READING: http://www.quirksmode.org/mobile/viewports.html // and http://www.quirksmode.org/mobile/viewports2.html // API SEMANTICS. // Ref https://developer.mozilla.org/en-US/docs/Web/API/CSS_Object_Model/Determining_the_dimensions_of_elements // getBoundingClientRect().width: sum of bounding boxes of element (the displayed width of the element, // including padding and border). Fractional. Applies transformations. // clientWidth: visible width of element including padding (but not border). EXCEPT on root element (html), where // it is the width of the viewport. Rounds to an integer. Doesn't apply transformations. // offsetWidth: visible width of element including padding, border, and scrollbars (if any). Rounds to an integer. // Doesn't apply transformations. // scrollWidth: entire width of element, including any part that's not visible due to scrollbars. Rounds to // an integer. Doesn't apply transformations. Not clear if it includes scrollbars, but I think not. Also // not clear if it includes borders or padding. (But from tests, apparently not borders. Except on root // element and body element, which have special results that vary by browser.) // TEST RESULTS: WIDTH // ✔ = correct answer // ✘ = incorrect answer and diverges from spec // ~ = incorrect answer, but matches spec // BROWSERS TESTED: Safari 6.2.0 (Mac OS X 10.8.5); Mobile Safari 7.0.0 (iOS 7.1); Firefox 32.0.0 (Mac OS X 10.8); // Firefox 33.0.0 (Windows 7); Chrome 38.0.2125 (Mac OS X 10.8.5); Chrome 38.0.2125 (Windows 7); IE 8, 9, 10, 11 // html width style smaller than viewport width; body width style smaller than html width style // NOTE: These tests were conducted when correct result was width of border. That has been changed // to "width of viewport." // html.getBoundingClientRect().width // ✘ IE 8, 9, 10: width of viewport // ✔ Safari, Mobile Safari, Chrome, Firefox, IE 11: width of html, including border // html.clientWidth // ~ Safari, Mobile Safari, Chrome, Firefox, IE 8, 9, 10, 11: width of viewport // html.offsetWidth // ✘ IE 8, 9, 10: width of viewport // ✔ Safari, Mobile Safari, Chrome, Firefox, IE 11: width of html, including border // html.scrollWidth // ✘ IE 8, 9, 10, 11, Firefox: width of viewport // ~ Safari, Mobile Safari, Chrome: width of html, excluding border // body.getBoundingClientRect().width // ~ Safari, Mobile Safari, Chrome, Firefox, IE 8, 9, 10, 11: width of body, including border // body.clientWidth // ~ Safari, Mobile Safari, Chrome, Firefox, IE 8, 9, 10, 11: width of body, excluding border // body.offsetWidth // ~ Safari, Mobile Safari, Chrome, Firefox, IE 8, 9, 10, 11: width of body, including border // body.scrollWidth // ✘ Safari, Mobile Safari, Chrome: width of viewport // ~ Firefox, IE 8, 9, 10, 11: width of body, excluding border // element width style wider than viewport; body and html width styles at default // BROWSER BEHAVIOR: html and body border extend to width of viewport and not beyond (except on Mobile Safari) // Correct result is element width + body border-left + html border-left (except on Mobile Safari) // Mobile Safari uses a layout viewport, so it's expected to include body border-right and html border-right. // html.getBoundingClientRect().width // ✔ Mobile Safari: element width + body border + html border // ~ Safari, Chrome, Firefox, IE 8, 9, 10, 11: viewport width // html.clientWidth // ✔ Mobile Safari: element width + body border + html border // ~ Safari, Chrome, Firefox, IE 8, 9, 10, 11: viewport width // html.offsetWidth // ✔ Mobile Safari: element width + body border + html border // ~ Safari, Chrome, Firefox, IE 8, 9, 10, 11: viewport width // html.scrollWidth // ✔ Mobile Safari: element width + body border + html border // ✘ Safari, Chrome: element width + body border-left (BUT NOT html border-left) // ✔ Firefox, IE 8, 9, 10, 11: element width + body border-left + html border-left // body.getBoundingClientRect().width // ~ Mobile Safari: element width + body border // ~ Safari, Chrome, Firefox, IE 8, 9, 10, 11: viewport width - html border // body.clientWidth // ~ Mobile Safari: element width // ~ Safari, Chrome, Firefox, IE 8, 9, 10, 11: viewport width - html border - body border // body.offsetWidth // ~ Mobile Safari: element width + body border // ~ Safari, Chrome, Firefox, IE 8, 9, 10, 11: viewport width - html border // body.scrollWidth // ✔ Mobile Safari: element width + body border + html border // ✔ Safari, Chrome: element width + body border-left + html border-left (matches actual browser) // ~ Firefox, IE 8, 9, 10, 11: element width // TEST RESULTS: HEIGHT // ✔ = correct answer // ✘ = incorrect answer and diverges from spec // ~ = incorrect answer, but matches spec // html height style smaller than viewport height; body height style smaller than html height style // NOTE: These tests were conducted when correct result was height of viewport. // html.clientHeight // ✔ Safari, Mobile Safari, Chrome, Firefox, IE 8, 9, 10, 11: height of viewport // element height style taller than viewport; body and html width styles at default // BROWSER BEHAVIOR: html and body border enclose entire element // Correct result is element width + body border-top + html border-top + body border-bottom + html border-bottom // html.clientHeight // ✔ Mobile Safari: element height + all borders // ~ Safari, Chrome, Firefox, IE 8, 9, 10, 11: height of viewport // html.scrollHeight // ✔ Firefox, IE 8, 9, 10, 11: element height + all borders // ✘ Safari, Mobile Safari, Chrome: element height + html border-bottom // body.scrollHeight // ✔ Safari, Mobile Safari, Chrome: element height + all borders // ~ Firefox, IE 8, 9, 10, 11: element height (body height - body border) function pageSize(document) { var html = document.documentElement; var body = document.body; // BEST WIDTH ANSWER SO FAR (ASSUMING VIEWPORT IS MINIMUM ANSWER): var width = Math.max(body.scrollWidth, html.scrollWidth); // BEST HEIGHT ANSWER SO FAR (ASSUMING VIEWPORT IS MINIMUM ANSWER): var height = Math.max(body.scrollHeight, html.scrollHeight); return { width: width, height: height }; }