Skip to content

Commit 8e8bc9e

Browse files
committed
create sortElementsByHtmlOrder helper
1 parent 1b1b0ed commit 8e8bc9e

File tree

4 files changed

+114
-2
lines changed

4 files changed

+114
-2
lines changed

packages/twopoint5d-elements/src/components/GlitchPassElement.ts

-2
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,9 @@ export class GlitchPassElement extends TwoPoint5DElement implements PostProcessi
3939
const postProcessing = this.postProcessing;
4040
if (postProcessing != null) {
4141
this.logger?.log('add glitchPass to postProcessing', {postProcessing, self: this});
42-
// postProcessing.renderer.addPass(this.pass);
4342
postProcessing.addPassElement(this);
4443
return () => {
4544
this.logger?.log('remove glitchPass from postProcessing', {postProcessing, self: this});
46-
// postProcessing.renderer.removePass(this.pass);
4745
postProcessing.removePassElement(this);
4846
};
4947
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import {describe, expect, it} from 'vitest';
2+
import {sortElementsByHtmlOrder} from './sortElementsByHtmlOrder.js';
3+
4+
const createElement = (id: string, children: HTMLElement[] = []) => {
5+
const div = document.createElement('div');
6+
div.id = id;
7+
div.append(...children);
8+
return div;
9+
};
10+
11+
describe('sortElementsByHtmlOrder', () => {
12+
it('should sort elements by html order', () => {
13+
const A = createElement('A');
14+
const B = createElement('B');
15+
const C = createElement('C');
16+
const D = createElement('D');
17+
const E = createElement('E');
18+
const F = createElement('F');
19+
const G = createElement('G');
20+
const H = createElement('H');
21+
22+
const dAB = createElement('dAB', [A, B]);
23+
const dFAB = createElement('dFAB', [F, dAB]);
24+
const dG = createElement('dG', [G]);
25+
const dCD = createElement('dCD', [C, D]);
26+
const dCDE = createElement('dCDE', [dCD, E]);
27+
28+
const ROOT = createElement('ROOT', [dFAB, dG, H, dCDE]);
29+
30+
const children = sortElementsByHtmlOrder(ROOT, [A, B, C, D, E, F, G, H]);
31+
32+
expect(children).toHaveLength(8);
33+
expect(children).toEqual([F, A, B, G, H, C, D, E]);
34+
});
35+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
class ElementItem {
2+
container: HTMLElement;
3+
children: HTMLElement[];
4+
5+
constructor(container: HTMLElement, children: HTMLElement[] = []) {
6+
this.container = container;
7+
this.children = children;
8+
}
9+
10+
getParent(): HTMLElement {
11+
return this.container.parentElement!;
12+
}
13+
}
14+
15+
interface DepthLayer {
16+
leafs: ElementItem[];
17+
depth: number;
18+
}
19+
20+
export function sortElementsByHtmlOrder(root: HTMLElement, elements: HTMLElement[]): HTMLElement[] {
21+
const layers: DepthLayer[] = [];
22+
23+
const getDepth = (child: HTMLElement): number => {
24+
let depth = 0;
25+
let el = child;
26+
while (el !== root) {
27+
depth++;
28+
el = el.parentElement!;
29+
}
30+
return depth;
31+
};
32+
33+
const findOrCreateLayer = (depth: number): DepthLayer => {
34+
if (!layers[depth]) {
35+
layers[depth] = {leafs: [], depth};
36+
}
37+
return layers[depth];
38+
};
39+
40+
for (const leaf of elements.map((el) => new ElementItem(el, [el]))) {
41+
findOrCreateLayer(getDepth(leaf.container)).leafs.push(leaf);
42+
}
43+
44+
while (layers.length > 1) {
45+
const layer = layers.pop();
46+
if (!layer) continue;
47+
48+
const parents = new Set<HTMLElement>(layer.leafs.map((leaf) => leaf.getParent()));
49+
50+
for (const parent of parents) {
51+
const children = sortByHtmlOrder(
52+
parent,
53+
layer.leafs.filter((leaf) => leaf.getParent() === parent),
54+
);
55+
56+
findOrCreateLayer(getDepth(parent)).leafs.push(
57+
new ElementItem(
58+
parent,
59+
children.flatMap((leaf) => leaf.children),
60+
),
61+
);
62+
}
63+
}
64+
65+
return layers.length === 1 ? layers[0].leafs.flatMap((leaf) => leaf.children) : [];
66+
}
67+
68+
function sortByHtmlOrder(parent: HTMLElement, children: ElementItem[]): ElementItem[] {
69+
return Array.from(parent.children)
70+
.map((el) => children.find((item) => item.container === el))
71+
.filter(Boolean) as ElementItem[];
72+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import {defineConfig} from 'vitest/config';
2+
3+
export default defineConfig({
4+
test: {
5+
environment: 'happy-dom',
6+
},
7+
});

0 commit comments

Comments
 (0)