Skip to content

Commit

Permalink
web: Fix 100% height when that equals 0
Browse files Browse the repository at this point in the history
  • Loading branch information
danielhjacobs committed Sep 15, 2023
1 parent 7f416f8 commit 420c164
Show file tree
Hide file tree
Showing 5 changed files with 164 additions and 9 deletions.
25 changes: 20 additions & 5 deletions web/packages/core/src/polyfills.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { RuffleObject } from "./ruffle-object";
import { RuffleEmbed } from "./ruffle-embed";
import type { RufflePlayer } from "./ruffle-player";
import { installPlugin, FLASH_PLUGIN } from "./plugin-polyfill";
import { publicPath } from "./public-path";
import type { DataLoadOptions, URLLoadOptions } from "./load-options";
Expand Down Expand Up @@ -189,11 +190,25 @@ async function injectRuffle(
*/
function initMutationObserver(): void {
const observer = new MutationObserver(function (mutationsList) {
// If any nodes were added, re-run the polyfill to detect any new instances.
const nodesAdded = mutationsList.some(
(mutation) => mutation.addedNodes.length > 0,
);
if (nodesAdded) {
let objectOrEmbedAdded = false;
for (const mutation of mutationsList) {
for (const addedNode of mutation.addedNodes) {
const nodeName = addedNode.nodeName;
if (
["RUFFLE-PLAYER", "RUFFLE-EMBED", "RUFFLE-OBJECT"].includes(
nodeName,
)
) {
const rufflePlayer = addedNode as RufflePlayer;
rufflePlayer.updateResizeObserver();
} else {
objectOrEmbedAdded ||= ["EMBED", "OBJECT"].includes(
nodeName,
);
}
}
}
if (objectOrEmbedAdded) {
polyfillFlashInstances();
polyfillFrames();
}
Expand Down
65 changes: 61 additions & 4 deletions web/packages/core/src/ruffle-player.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ export class RufflePlayer extends HTMLElement {
private pointerMoveMaxDistance = 0;

private volumeSettings: VolumeControls;
private resizeObserver: ResizeObserver;

/**
* Triggered when a movie metadata has been loaded (such as movie width and height).
Expand Down Expand Up @@ -232,6 +233,15 @@ export class RufflePlayer extends HTMLElement {
*/
constructor() {
super();
this.resizeObserver = new ResizeObserver((entries) => {
for (const entry of entries) {
if (entry.target === this.parentElement) {
setTimeout(() => this.updateStyles(), 0);
break;
}
}
});
this.updateResizeObserver();

this.shadow = this.attachShadow({ mode: "open" });
this.shadow.appendChild(ruffleShadowTemplate.content.cloneNode(true));
Expand Down Expand Up @@ -552,6 +562,20 @@ export class RufflePlayer extends HTMLElement {
this.destroy();
}

/**
* Check if the style's height is defined using non-absolute units.
*
* @param style The HTMLStyleDeclaration whose height to check (or undefined).
* @returns true if the height is relative to other elements, otherwise false.
*/
private hasRelativeHeight(style: CSSStyleDeclaration | undefined): boolean {
if (!style) {
return true;
}
const absoluteHeightUnits = ["cm", "mm", "Q", "in", "pc", "pt", "px"];
return !absoluteHeightUnits.some((unit) => style.height.endsWith(unit));
}

/**
* Updates the internal shadow DOM to reflect any set attributes from
* this element.
Expand All @@ -560,9 +584,9 @@ export class RufflePlayer extends HTMLElement {
if (this.dynamicStyles.sheet) {
if (this.dynamicStyles.sheet.rules) {
for (
let i = 0;
i < this.dynamicStyles.sheet.rules.length;
i++
let i = this.dynamicStyles.sheet.rules.length - 1;
i >= 0;
i--
) {
this.dynamicStyles.sheet.deleteRule(i);
}
Expand All @@ -586,9 +610,31 @@ export class RufflePlayer extends HTMLElement {
heightAttr.value,
);
if (height !== null) {
this.dynamicStyles.sheet.insertRule(
const heightIndex = this.dynamicStyles.sheet.insertRule(
`:host { height: ${height}; }`,
);
// Using setTimeout with a timeout of 0 means insertRule takes effect first
setTimeout(() => {
if (
this.clientHeight === 0 &&
this.dynamicStyles.sheet
) {
const heightRule = this.dynamicStyles.sheet
.cssRules[heightIndex] as CSSStyleRule;
const parentElement = this.parentElement;
if (
this.hasRelativeHeight(heightRule?.style) &&
this.hasRelativeHeight(parentElement?.style)
) {
this.dynamicStyles.sheet.deleteRule(
heightIndex,
);
this.dynamicStyles.sheet.insertRule(
`:host { height: 200px; }`,
);
}
}
}, 0);
}
}
}
Expand Down Expand Up @@ -1034,6 +1080,17 @@ export class RufflePlayer extends HTMLElement {
}
}

/**
* Update resizeObserver to watch the RufflePlayer's parent element.
*
*/
updateResizeObserver(): void {
if (this.parentElement) {
this.resizeObserver.disconnect();
this.resizeObserver.observe(this.parentElement);
}
}

/**
* Requests the browser to make this player fullscreen.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<div id="result_1">200</div><div id="result_2">0</div><div id="result_3">50</div><div id="result_4">200</div><div id="result_5">50</div><div id="result_6">0</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>PERCENT-BASED-HEIGHT</title>
</head>
<body>
<div style="height: 0px;">
<div>
<embed id="content_1" width="100%" height="100%" src="/test_assets/example.swf"></embed>
</div>
</div>
<div style="height: 0px;">
<embed id="content_2" width="100%" height="100%" src="/test_assets/example.swf"></embed>
</div>
<div style="height: 50px;">
<embed id="content_3" width="100%" height="100%" src="/test_assets/example.swf"></embed>
</div>
<embed id="content_4" width="100%" height="100%" src="/test_assets/example.swf"></embed>
<embed id="content_5" width="100%" height="50px" src="/test_assets/example.swf"></embed>
<embed id="content_6" width="100%" height="0px" src="/test_assets/example.swf"></embed>
<div id="result"></div>
<script>
function writeResult(res, index) {
const resultDiv = document.createElement("div");
resultDiv.textContent = res;
resultDiv.id = "result_" + index;
const result = document.getElementById("result");
for (let i = index + 1; i <= 6; i++) {
const nextResult = document.getElementById("result_" + i);
if (nextResult) {
result.insertBefore(resultDiv, nextResult);
return;
}
}
result.appendChild(resultDiv);
}
function checkClientHeight(content) {
const index = parseInt(content.id.replace(/^\D+/g, ''));
setTimeout(() => writeResult(content.clientHeight, index), 1000);
}
document.addEventListener("DOMContentLoaded", () => {
const observer = new MutationObserver(function (mutationsList) {
for (const mutation of mutationsList) {
if (mutation && mutation.addedNodes && mutation.addedNodes.length > 0) {
const node = mutation.addedNodes[0];
if (node && node.nodeName === "RUFFLE-EMBED") {
node.addEventListener("loadeddata", () => checkClientHeight(node));
}
}
}
});
observer.observe(document, { childList: true, subtree: true });
});
</script>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
const { openTest, injectRuffleAndWait } = require("../../utils");
const { expect, use } = require("chai");
const chaiHtml = require("chai-html");
const fs = require("fs");

use(chaiHtml);

describe("Get correct sizes for Flash embeds with percent-based heights", () => {
it("loads the test", async () => {
await openTest(browser, __dirname);
});

it("is the correct height", async () => {
await injectRuffleAndWait(browser);
await browser.$("#result_1").waitForExist();
await browser.$("#result_2").waitForExist();
await browser.$("#result_3").waitForExist();
await browser.$("#result_4").waitForExist();
await browser.$("#result_5").waitForExist();
await browser.$("#result_6").waitForExist();
const actual = await browser.$("#result").getHTML(false);
const expected = fs.readFileSync(`${__dirname}/expected.html`, "utf8");
expect(actual).html.to.equal(expected);
});
});

0 comments on commit 420c164

Please sign in to comment.