From 1c0b797d9e7dee31aa25ee9f63f49ad3ade995f9 Mon Sep 17 00:00:00 2001 From: Bill Keese Date: Sat, 15 Feb 2020 07:13:37 +0900 Subject: [PATCH] Various fixes so widgets don't access document.body before it's created. Also avoid using domReady! as a plugin since Webpack can't handle it. Refs #520. --- Viewport.js | 3 +-- Widget.js | 33 +++++++++++++++++++-------------- activationTracker.js | 8 +++++--- hc.js | 12 +++++++----- tests/unit/Widget.js | 13 ++++++++----- uacss.js | 7 +++++-- 6 files changed, 45 insertions(+), 31 deletions(-) diff --git a/Viewport.js b/Viewport.js index 0ffa20d0c1..f2fb2d789b 100644 --- a/Viewport.js +++ b/Viewport.js @@ -15,8 +15,7 @@ */ define([ "ibm-decor/Evented", - "ibm-decor/sniff", // has("ios") - "requirejs-domready/domReady!" + "ibm-decor/sniff" // has("ios") ], function ( Evented, has diff --git a/Widget.js b/Widget.js index 9bf15809a8..3797d55fe9 100644 --- a/Widget.js +++ b/Widget.js @@ -65,6 +65,14 @@ define([ */ dir: "", + /** + * Direction inherited from document root (either `` or ``) at the time the element is attached + * to the document. Used if `dir` property not set explicitly. + * @member {string} + * @readonly + */ + inheritedDir: "", + /** * Actual direction of the widget, which can be set explicitly via `dir` property or inherited from the * setting on the document root (either `` or ``). @@ -107,11 +115,11 @@ define([ }, computeProperties: function (props) { - if ("dir" in props) { - if ((/^(ltr|rtl)$/i).test(this._get("dir"))) { - this.effectiveDir = this._get("dir").toLowerCase(); + if ("dir" in props || "inheritedDir" in props) { + if ((/^(ltr|rtl)$/i).test(this.dir)) { + this.effectiveDir = this.dir.toLowerCase(); } else { - this.effectiveDir = this.getInheritedDir(); + this.effectiveDir = this.inheritedDir; } } }, @@ -129,15 +137,6 @@ define([ this.rendered = true; }, - /** - * Return the direction setting for the page. - * @returns {string} "ltr" or "rtl" - * @protected - */ - getInheritedDir: function () { - return (this.ownerDocument.body.dir || this.ownerDocument.documentElement.dir || "ltr").toLowerCase(); - }, - // Override Invalidating#refreshRendering() to execute the template's refreshRendering() code, etc. refreshRendering: function (oldVals, justRendered) { if (this._templateHandle && !justRendered) { @@ -154,11 +153,17 @@ define([ this.toggleClass("d-rtl", this.effectiveDir === "rtl"); } if ("dir" in oldVals) { - this.style.direction = this._get("dir"); + this.style.direction = this.dir; } }, connectedCallback: function () { + // After widget is attached to document, find out which direction it inherits. Will be used if + // Widget#dir isn't set explicitly. For performance, we only check and , not other + // ancestor nodes. Also, we don't monitor changes to the "dir" attributes of or . + this.inheritedDir = (this.ownerDocument.body.dir || this.ownerDocument.documentElement.dir || + "ltr").toLowerCase(); + this.initializeInvalidating(); }, diff --git a/activationTracker.js b/activationTracker.js index 0c58d603f7..d585efe132 100644 --- a/activationTracker.js +++ b/activationTracker.js @@ -46,8 +46,8 @@ define([ "ibm-decor/Evented", "ibm-decor/sniff", "./on", - "requirejs-domready/domReady!" -], function (advise, dcl, Evented, has, on) { + "requirejs-domready/domReady" +], function (advise, dcl, Evented, has, on, domReady) { // Time of the last touch/mouse event. var lastPointerDownTime; @@ -388,7 +388,9 @@ define([ // Create singleton for top window var singleton = new ActivationTracker(); - singleton.registerWin(window); + domReady(function () { + singleton.registerWin(window); + }); return singleton; }); diff --git a/hc.js b/hc.js index e8caf1ab5f..f5ecd1d1fd 100644 --- a/hc.js +++ b/hc.js @@ -15,8 +15,8 @@ */ define([ "requirejs-dplugins/has", - "requirejs-domready/domReady!" -], function (has) { + "requirejs-domready/domReady" +], function (has, domReady) { has.add("highcontrast", function () { if (typeof window === "undefined") { @@ -43,9 +43,11 @@ define([ } }); - if (has("highcontrast")) { - document.body.className = (document.body.className + " d-hc").trim(); - } + domReady(function () { + if (has("highcontrast")) { + document.body.className = (document.body.className + " d-hc").trim(); + } + }); return has; }); diff --git a/tests/unit/Widget.js b/tests/unit/Widget.js index 877c37d37e..a55d34283d 100644 --- a/tests/unit/Widget.js +++ b/tests/unit/Widget.js @@ -179,16 +179,19 @@ define([ myWidget.dir = "ltr"; myWidget.deliver(); assert.strictEqual(myWidget.style.direction, "ltr", "style.direction 2"); - assert.isFalse(myWidget.classList.contains("d-rtl"), "doesn't have d-rtl class 1"); + assert.isFalse(myWidget.classList.contains("d-rtl"), "doesn't have d-rtl class"); + }, + "programmatic inherit dir": function () { var bodyOriginalDir = window.getComputedStyle(document.body).direction; + try { // setting dir to "" should inherit from document.body.dir = "rtl"; - myWidget.dir = ""; - myWidget.deliver(); - assert.strictEqual(myWidget.style.direction, "", "style.direction 3"); - assert(myWidget.classList.contains("d-rtl"), "has d-rtl class 2"); + var myWidget = new TestDir(); + container.appendChild(myWidget); + myWidget.connectedCallback(); + assert(myWidget.classList.contains("d-rtl"), "has d-rtl class"); } finally { // Revert changes made to body.dir. Should be able to just say dir = "" but due to // apparent bugs in Safari 7 (used during saucelabs testing), that leaves the browser diff --git a/uacss.js b/uacss.js index ec6c09fe39..406ad5ccfd 100644 --- a/uacss.js +++ b/uacss.js @@ -8,7 +8,7 @@ * * @module delite/uacss */ -define(["ibm-decor/sniff"], function (has) { +define(["ibm-decor/sniff", "requirejs-domready/domReady"], function (has, domReady) { var ie = has("ie"), maj = Math.floor, ff = has("ff"), @@ -40,7 +40,10 @@ define(["ibm-decor/sniff"], function (has) { classStr += clz + " "; } } - document.body.className = (document.body.className + " " + classStr).trim(); + + domReady(function () { + document.body.className = (document.body.className + " " + classStr).trim(); + }); return has; });