Skip to content

Commit e4224c2

Browse files
author
Greg Whitworth
committed
Initial commit with everything the same as the spec from WICG
1 parent 7f135be commit e4224c2

25 files changed

Lines changed: 3463 additions & 0 deletions

resize-observer/CONTRIBUTING.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Web Platform Incubator Community Group
2+
3+
This repository is being used for work in the Web Platform Incubator Community Group, governed by the [W3C Community License
4+
Agreement (CLA)](http://www.w3.org/community/about/agreements/cla/). To contribute, you must join
5+
the CG.
6+
7+
If you are not the sole contributor to a contribution (pull request), please identify all
8+
contributors in the pull request's body or in subsequent comments.
9+
10+
To add a contributor (other than yourself, that's automatic), mark them one per line as follows:
11+
12+
```
13+
+@github_username
14+
```
15+
16+
If you added a contributor by mistake, you can remove them in a comment with:
17+
18+
```
19+
-@github_username
20+
```
21+
22+
If you are making a pull request on behalf of someone else but you had no part in designing the
23+
feature, you can remove yourself with the above syntax.
24+
25+
# Tests
26+
27+
For normative changes, a corresponding
28+
[web-platform-tests](https://github.com/web-platform-tests/wpt) PR is highly appreciated. Typically,
29+
both PRs will be merged at the same time. Note that a test change that contradicts the spec should
30+
not be merged before the corresponding spec change. If testing is not practical, please explain why
31+
and if appropriate [file an issue](https://github.com/web-platform-tests/wpt/issues/new) to follow
32+
up later. Add the `type:untestable` or `type:missing-coverage` label as appropriate.

resize-observer/LICENSE.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
All Reports in this Repository are licensed by Contributors under the
2+
[W3C Software and Document
3+
License](http://www.w3.org/Consortium/Legal/2015/copyright-software-and-document). Contributions to
4+
Specifications are made under the [W3C CLA](https://www.w3.org/community/about/agreements/cla/).
5+

resize-observer/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Resize Observer
2+
3+
[Explainer Doc](./explainer.md)
4+
5+
[Draft Spec](https://wicg.github.io/ResizeObserver/)

resize-observer/demo.html

Lines changed: 331 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,331 @@
1+
<!doctype html>
2+
<head>
3+
<title>Map tiles and a canvas</title>
4+
<style>
5+
/* * {
6+
box-sizing: border-box;
7+
}*/
8+
.resize {
9+
border: 20px solid rgba(0,255,0, 0.5);
10+
background-color: #DDD;
11+
width: 300.49px;
12+
height: 200.5px;
13+
overflow: hidden;
14+
position:relative;
15+
display:inline-block;
16+
}
17+
.yellowBorder {
18+
border-width: 1px;
19+
border-style: solid;
20+
}
21+
22+
.maptiles {
23+
overflow:
24+
}
25+
26+
.maptiles::after {
27+
content: "map tiles";
28+
position: relative;
29+
top: 20px;
30+
}
31+
32+
.elipse {
33+
border: 20px solid rgba(100,255,100, 0.5);
34+
}
35+
.elipse::after {
36+
content: "canvas";
37+
position: relative;
38+
top: -100px;
39+
}
40+
.domMunch {
41+
background-color: orange;
42+
}
43+
.domMunch > div {
44+
display: inline-block;
45+
width: 20px;
46+
height: 20px;
47+
border: 1px solid black;
48+
}
49+
.domMunch::after {
50+
content: "domMunch";
51+
position: relative;
52+
top: 20px;
53+
}
54+
</style>
55+
56+
<script>
57+
'use strict';
58+
function log(msg) { var e = document.querySelector('#log'); e.textContent = e.innerText + '\n' + msg;}
59+
60+
window.onerror = function(event) {
61+
log("global error" + event.message);
62+
};
63+
64+
if (!window.ResizeObserver)
65+
log('no document.ResizeObserver');
66+
67+
var range = 1.5;
68+
69+
function setRange() {
70+
range = Math.max(0.5, parseInt(document.querySelector('#rangeInput').value));
71+
}
72+
73+
function grow() {
74+
for (var el of document.querySelectorAll('.resize')) {
75+
let s = window.getComputedStyle(el);
76+
let w = parseFloat(s.width);
77+
let h = parseFloat(s.height);
78+
el.style.width = (w + range) + 'px';
79+
el.style.height = (h + range * 2 / 3) + 'px';
80+
}
81+
}
82+
function shrink() {
83+
for (var el of document.querySelectorAll('.resize')) {
84+
let s = window.getComputedStyle(el);
85+
let w = parseFloat(s.width);
86+
let h = parseFloat(s.height);
87+
el.style.width = (w - range) + 'px';
88+
el.style.height = (h - range * 2 / 3) + 'px';
89+
}
90+
}
91+
function move() {
92+
var moveCount = 60;
93+
var el = document.querySelector('.maptiles');
94+
el.style.position = "absolute";
95+
console.time("move");
96+
var moveHelper = _ => {
97+
if (moveCount-- == 0) {
98+
el.style.top = "";
99+
el.style.left = "";
100+
el.style.position = "relative";
101+
el.style.zIndex = "";
102+
console.timeEnd("move");
103+
} else {
104+
el.style.zIndex = 1;
105+
el.style.top = (parseFloat(el.style.top) + range || 0) + 'px';
106+
el.style.left = (parseFloat(el.style.left) + range || 0) + 'px';
107+
window.requestAnimationFrame(moveHelper);
108+
}
109+
}
110+
window.setTimeout(moveHelper, 0);
111+
}
112+
</script>
113+
</head>
114+
<body>
115+
<h1 style="display:none">ResizeObserver unexpected error</h1>
116+
<pre id='log' style="display:none">log:
117+
</pre>
118+
<pre style="position:absolute; right: 0px">
119+
Notify:<span id="notifyCount"></span>
120+
</pre>
121+
<p>
122+
<label><input id="observe" type="checkbox" onclick="toggleObserve()">observe</label>
123+
<button onclick="disconnect()">disconnect</button>
124+
<button onclick="removeTargets()">remove</button>
125+
<button onclick="addTargets()">add</button>
126+
</p>
127+
<p>
128+
<button onclick="grow()">grow</button>
129+
<button onclick="shrink()">shrink</button>
130+
<button onclick="move()">move</button>
131+
<label>size increment:<input type="number" id="rangeInput" min="1" max="40"></label>
132+
</p>
133+
<p>#maptiles places tiles inside an </p>
134+
<p>#elipse draws an elipse in a canvas</p>
135+
<div class="resize maptiles" ></div>
136+
<canvas class="resize elipse"></canvas>
137+
<div class="resize domMunch"></div>
138+
<script>
139+
'use strict';
140+
141+
var ro;
142+
try {
143+
ro = new ResizeObserver( entries => {
144+
// console.log("resized");
145+
document.querySelector("#notifyCount").innerText = entries.length;
146+
for (let entry of entries) {
147+
if (!entry.target || !entry.target.parentNode)
148+
console.error("detected resize on removed element");
149+
if (entry.target.onresize)
150+
entry.target.onresize(entry);
151+
}
152+
});
153+
}
154+
catch(ex) {
155+
log("Exception:" + ex.message);
156+
console.error(ex.message);
157+
}
158+
159+
// ACTIONS
160+
161+
var isObserving = false;
162+
function toggleObserve() {
163+
if (isObserving) {
164+
isObserving = false;
165+
for (let el of document.querySelectorAll('.resize'))
166+
ro.unobserve(el);
167+
}
168+
else {
169+
isObserving = true;
170+
for (let el of document.querySelectorAll('.resize'))
171+
ro.observe(el);
172+
}
173+
document.querySelector('#observe').checked = isObserving;
174+
}
175+
176+
function disconnect() {
177+
isObserving = false;
178+
ro.disconnect();
179+
document.querySelector('#observe').checked = isObserving;
180+
}
181+
182+
function removeTargets() {
183+
for (let el of document.querySelectorAll('.resize'))
184+
el.parentNode.removeChild(el);
185+
}
186+
187+
function addTargets() {
188+
let nines = document.createElement('div');
189+
nines.classList.add('resize');
190+
nines.classList.add('maptiles');
191+
document.body.appendChild(nines);
192+
let elipse = document.createElement('canvas');
193+
elipse.classList.add('resize');
194+
elipse.classList.add('elipse');
195+
document.body.appendChild(elipse);
196+
initResizeHandlers();
197+
toggleObserve();
198+
toggleObserve(); // intentional, reverts to original.
199+
}
200+
201+
// DRAWING
202+
203+
function nextColor() {
204+
if (!nextColor.colors) {
205+
nextColor.colors = {red: 255, green: 0, blue: 255};
206+
}
207+
nextColor.colors.red = nextColor.colors.red < 20 ? 255 : nextColor.colors.red - 10;
208+
nextColor.colors.blue = nextColor.colors.blue < 30 ? 255 : nextColor.colors.blue - 20;
209+
nextColor.colors.green = nextColor.colors.green > 200 ? 0 : nextColor.colors.green + 10;
210+
return "rgb(" + nextColor.colors.red + "," + nextColor.colors.green + "," + nextColor.colors.blue + ")";
211+
};
212+
213+
var TileWidth = 100;
214+
var TileHeight = TileWidth * 2 / 3;
215+
216+
// Tiles the element with map tiles
217+
function mapTiles(entry) {
218+
let el = entry.target;
219+
let color = nextColor();
220+
221+
let cols = Math.ceil(entry.clientWidth / TileWidth);
222+
let rows = Math.ceil(entry.clientHeight / TileHeight);
223+
let tileCount = cols * rows;
224+
while (el.childNodes.length > tileCount)
225+
el.removeChild(el.firstChild);
226+
while (el.childNodes.length < tileCount)
227+
el.appendChild(document.createElement('div'));
228+
let colWidth = entry.clientWidth / cols;
229+
let rowHeight = entry.clientHeight / rows;
230+
231+
for (let r=0; r<rows; r++)
232+
for (let c=0; c<cols; c++) {
233+
let tile = el.childNodes.item(r * cols + c);
234+
tile.innerText = r + "." + c;
235+
tile.style.boxSizing = 'border-box';
236+
tile.style.position = 'absolute';
237+
tile.style.left = `${c * colWidth}px`;
238+
tile.style.width = `${colWidth}px`;
239+
tile.style.top = `${r * rowHeight}px`;
240+
tile.style.height = `${rowHeight}px`;
241+
tile.style.borderColor = color;
242+
tile.classList.add('yellowBorder');
243+
}
244+
}
245+
246+
function elipse(entry) {
247+
entry.target.width = entry.target.clientWidth;
248+
entry.target.height = entry.target.clientHeight;
249+
let ctx = entry.target.getContext('2d');
250+
let rx = entry.target.clientWidth / 2;
251+
let ry = entry.target.clientHeight / 2;
252+
253+
ctx.beginPath();
254+
ctx.clearRect(0,0, entry.target.clientWidth, entry.target.clientHeight);
255+
ctx.arc(rx, ry, 10, 0, 2 * Math.PI);
256+
ctx.stroke();
257+
258+
ctx.beginPath();
259+
ctx.ellipse(rx, ry, rx, ry, 0, 0, 2 * Math.PI);
260+
ctx.stroke();
261+
}
262+
263+
function domMunch(entry) {
264+
const munchSize = 3;
265+
var target = entry.target;
266+
if (target.childNodes.length < munchSize) {
267+
var div = document.createElement('div');
268+
div.innerText = `${target.childNodes.length}`;
269+
target.appendChild(div);
270+
}
271+
if (target.childNodes.length == munchSize)
272+
while (target.childNodes.length > 0)
273+
target.removeChild(target.firstChild);
274+
}
275+
276+
function initResizeHandlers() {
277+
for (let el of document.querySelectorAll('.maptiles'))
278+
el.onresize = mapTiles;
279+
for (let el of document.querySelectorAll('.elipse'))
280+
el.onresize = elipse;
281+
for (let el of document.querySelectorAll('.domMunch'))
282+
el.onresize = domMunch;
283+
}
284+
285+
// Initialization
286+
initResizeHandlers();
287+
toggleObserve();
288+
289+
let rangeEl = document.querySelector("#rangeInput");
290+
rangeEl.addEventListener('change', _ => { setRange(); });
291+
rangeEl.value = range;
292+
293+
function throttleRaf(fn) {
294+
if (throttleRaf.waiting)
295+
return;
296+
else {
297+
throttleRaf.waiting = true;
298+
window.requestAnimationFrame( _ => {
299+
throttleRaf.waiting = false;
300+
fn();
301+
});
302+
}
303+
}
304+
305+
document.body.addEventListener('keydown', ev => {
306+
switch(ev.key) {
307+
case "ArrowRight":
308+
throttleRaf(grow);
309+
break;
310+
case "ArrowLeft":
311+
throttleRaf(shrink);
312+
break;
313+
case "ArrowUp":
314+
rangeEl.value = parseFloat(rangeEl.value) + 1;
315+
setRange();
316+
ev.preventDefault();
317+
break;
318+
case "ArrowDown":
319+
rangeEl.value = parseFloat(rangeEl.value) - 1;
320+
setRange();
321+
ev.preventDefault();
322+
break;
323+
default:
324+
break;
325+
}
326+
});
327+
328+
329+
330+
</script>
331+
</body>

0 commit comments

Comments
 (0)