Skip to content

Commit 6b7970b

Browse files
committed
window and document present normal resize events
1 parent a13de2c commit 6b7970b

4 files changed

Lines changed: 159 additions & 1 deletion

File tree

src/parsetree/features/on.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,9 @@ export class OnFeature extends Feature {
143143
eltData.observers.push(observer);
144144
}
145145

146-
if (eventSpec.resizeSpec) {
146+
if (eventSpec.resizeSpec && target instanceof Element) {
147+
// ResizeObserver only works on Elements, so `on resize from window`
148+
// (or document) falls through to the native `resize` event below.
147149
eventName = "hyperscript:resize";
148150
const observer = new ResizeObserver(function (entries) {
149151
for (const entry of entries) {

test/features/resize.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,15 @@ test.describe("on resize", () => {
3737
await expect(find('#out')).toHaveText("150");
3838
});
3939

40+
test("on resize from window uses native window resize event", async ({html, find, page}) => {
41+
await html(
42+
"<div id='out' _='on resize from window put \"fired\" into me'></div>"
43+
);
44+
// Native window resize isn't a ResizeObserver event; trigger it directly
45+
await page.evaluate(() => {
46+
window.dispatchEvent(new Event('resize'));
47+
});
48+
await expect(find('#out')).toHaveText("fired");
49+
});
50+
4051
});

test/manual/index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ <h1>Manual Tests</h1>
1313
<ul>
1414
<li><a href="/test/manual/connections.html">connections</a></li>
1515
<li><a href="/test/manual/intercept.html">intercept</a></li>
16+
<li><a href="/test/manual/resize-targets.html">resize-targets</a></li>
1617
<li><a href="/test/manual/view-transitions.html">view-transitions</a></li>
1718
<li><a href="/test/manual/workers.html">workers</a></li>
1819
</ul>

test/manual/resize-targets.html

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<title>Resize Target Test</title>
5+
<script type="module" src="../../src/_hyperscript.js"></script>
6+
<style>
7+
body { font-family: sans-serif; max-width: 48em; margin: 2em auto; padding: 0 1em; }
8+
.panel {
9+
border: 1px solid #ccc;
10+
padding: 1em;
11+
margin: 1em 0;
12+
background: #fafafa;
13+
}
14+
.status {
15+
font-family: monospace;
16+
padding: 0.5em;
17+
background: #eef;
18+
border-radius: 4px;
19+
margin: 0.5em 0;
20+
}
21+
#box {
22+
width: 200px;
23+
height: 100px;
24+
background: #2b6b1f;
25+
color: white;
26+
padding: 1em;
27+
resize: both;
28+
overflow: auto;
29+
}
30+
.instructions { color: #666; font-size: 0.9em; margin: 0.25em 0; }
31+
h2 { margin-top: 0; }
32+
</style>
33+
</head>
34+
<body>
35+
<h1>Resize Target Test</h1>
36+
<p>
37+
This page exercises the three distinct targets for <code>on resize</code>:
38+
<code>window</code> (native event), an explicit element via
39+
<code>from</code> (ResizeObserver), and the implicit <code>me</code>
40+
target (ResizeObserver).
41+
</p>
42+
43+
<div class="panel">
44+
<h2>1. <code>on resize from window</code> &mdash; native window event</h2>
45+
<p class="instructions">Resize the browser window. The counter should tick and the latest size should appear.</p>
46+
<div class="status" _="init set :count to 0
47+
on resize from window
48+
increment :count
49+
put `window resize #${:count}: ${window.innerWidth} × ${window.innerHeight}` into me
50+
end">
51+
(not fired yet)
52+
</div>
53+
</div>
54+
55+
<div class="panel">
56+
<h2>2. <code>on resize from body</code> &mdash; ResizeObserver on &lt;body&gt;</h2>
57+
<p class="instructions">Resize the window or scroll. The <code>body</code> element is an Element so ResizeObserver handles it.</p>
58+
<div class="status" _="init set :count to 0
59+
on resize from body
60+
increment :count
61+
put `body resize #${:count}: ${detail.width} × ${detail.height}` into me
62+
end">
63+
(not fired yet)
64+
</div>
65+
</div>
66+
67+
<div class="panel">
68+
<h2>3. <code>on resize</code> (implicit <code>me</code>) &mdash; ResizeObserver on the element itself</h2>
69+
<p class="instructions">Drag the corner of the green box below to resize it.</p>
70+
<div id="box" _="on resize put `${detail.width as Int} × ${detail.height as Int}` into me">
71+
drag my corner
72+
</div>
73+
</div>
74+
75+
<div class="panel">
76+
<h2>4. Combined: <code>on load or resize from window</code> &mdash; the original bug case</h2>
77+
<p class="instructions">Fires once on page load, then on each window resize. Tests that chained event specs with mixed native + synthetic targets work.</p>
78+
<div class="status" _="init set :count to 0
79+
on load or resize from window
80+
increment :count
81+
put `fired ${:count} time(s) (load or window resize)` into me
82+
end">
83+
(not fired yet)
84+
</div>
85+
</div>
86+
87+
<div class="panel">
88+
<h2>5. Combined: <code>on load or scroll from window or resize from body</code></h2>
89+
<p class="instructions">
90+
Load + native scroll + element ResizeObserver in one handler.
91+
Should fire once on load, again on any window scroll, and again on any body resize.
92+
</p>
93+
<div class="status" _="init set :count to 0
94+
on load or scroll from window or resize from body
95+
increment :count
96+
put `combined handler: ${:count} event(s)` into me
97+
end">
98+
(not fired yet)
99+
</div>
100+
</div>
101+
102+
<div class="panel">
103+
<h2>6. The exact bug report pattern</h2>
104+
<p class="instructions">
105+
<code>on load or scroll from window throttled at 16ms or resize from window or htmx:afterSettle from window</code><br>
106+
This was the failing case: all four events targeting <code>window</code>, including
107+
<code>resize from window</code> which the pre-fix code tried to hand to
108+
<code>ResizeObserver.observe(window)</code>. After the fix, window-targeted
109+
<code>resize</code> falls through to the native <code>resize</code> event.
110+
(The <code>htmx:afterSettle</code> spec is parsed and installed even though htmx
111+
isn't loaded -- it just never fires.)
112+
</p>
113+
<div class="status"
114+
_="init set :count to 0
115+
on load
116+
or scroll from window throttled at 16ms
117+
or resize from window
118+
or htmx:afterSettle from window
119+
increment :count
120+
put `bug-report pattern: ${:count} event(s)` into me
121+
end">
122+
(not fired yet)
123+
</div>
124+
</div>
125+
126+
<div class="panel">
127+
<h2>6. Modified bug report suggestion</h2>
128+
<p class="instructions">
129+
<code>on load or scroll from window throttled at 16ms or resize from window or htmx:afterSettle from window</code><br>
130+
</p>
131+
<div class="status"
132+
_="init set :count to 0
133+
on load
134+
or scroll from window throttled at 16ms
135+
or resize from body
136+
or htmx:afterSettle from window
137+
increment :count
138+
put `bug-report pattern: ${:count} event(s)` into me
139+
end">
140+
(not fired yet)
141+
</div>
142+
</div>
143+
</body>
144+
</html>

0 commit comments

Comments
 (0)