Skip to content

Commit

Permalink
fix(gameObject): move / remove dom nodes when add / remove children
Browse files Browse the repository at this point in the history
  • Loading branch information
straker committed Apr 17, 2024
1 parent a7157fd commit e6cdcb2
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 23 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"test": "karma start --single-run",
"test:watch": "karma start",
"test:permutations": "node test/permutations",
"test:ts": "tsc test/typings/*.ts",
"test:ts": "tsc test/typings/*.ts --noEmit",
"test:debug": "karma start --debug",
"eslint": "eslint ./{src,test}/",
"build": "gulp build",
Expand Down
18 changes: 17 additions & 1 deletion src/gameObject.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@ import { getContext } from './core.js';
import Updatable from './updatable.js';
import { on } from './events.js';
import { rotatePoint, clamp } from './helpers.js';
import { noop, removeFromArray } from './utils.js';
import {
noop,
removeFromArray,
addToDom,
getAllNodes
} from './utils.js';

/**
* The base class of most renderable classes. Handles things such as position, rotation, anchor, and the update and render life cycle.
Expand Down Expand Up @@ -578,6 +583,11 @@ class GameObject extends Updatable {
child.parent = this;
child._pc = child._pc || noop;
child._pc();

// dn = dom node
if (this._dn) {
this._dn.append(...getAllNodes(child));
}
});
}

Expand All @@ -593,6 +603,12 @@ class GameObject extends Updatable {
if (removeFromArray(this.children, child)) {
child.parent = null;
child._pc();

if (this._dn) {
getAllNodes(child).map(node => {
addToDom(node, this.context.canvas);
});
}
}
});
}
Expand Down
23 changes: 2 additions & 21 deletions src/scene.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,11 @@ import {
srOnlyStyle,
focusParams,
addToDom,
removeFromArray
removeFromArray,
getAllNodes
} from './utils.js';
import { collides } from './helpers.js';

/**
* Recursively get all objects HTML nodes.
* @param {Object} object - Root object.
*
* @returns {Object[]} All nested HTML nodes.
*/
function getAllNodes(object) {
let nodes = [];

if (object._dn) {
nodes.push(object._dn);
} else if (object.children) {
object.children.map(child => {
nodes = nodes.concat(getAllNodes(child));
});
}

return nodes;
}

/**
* A scene object for organizing a group of objects that will update and render together.
*
Expand Down
20 changes: 20 additions & 0 deletions src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,23 @@ export function removeFromArray(array, item) {
return true;
}
}

/**
* Recursively get all objects HTML nodes.
* @param {Object} object - Root object.
*
* @returns {Object[]} All nested HTML nodes.
*/
export function getAllNodes(object) {
let nodes = [];

if (object._dn) {
nodes.push(object._dn);
} else if (object.children) {
object.children.map(child => {
nodes = nodes.concat(getAllNodes(child));
});
}

return nodes;
}
71 changes: 71 additions & 0 deletions test/unit/gameObject.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -751,6 +751,40 @@ describe(
expect(child.world.x).to.equal(40);
expect(child.world.y).to.equal(60);
});

it('should move dom nodes', () => {
let child = GameObject({
x: 10,
y: 20,
_dn: document.createElement('button')
});
gameObject._dn = document.createElement('div');
document.body.appendChild(gameObject._dn);
gameObject.addChild(child);

expect(child._dn.parentNode).to.equal(gameObject._dn);
});

it('should move nested dom nodes', () => {
let child = GameObject({
x: 10,
y: 20
});
let grandchild = GameObject({
x: 10,
y: 20,
_dn: document.createElement('button')
});
child.addChild(grandchild);

gameObject._dn = document.createElement('div');
document.body.appendChild(gameObject._dn);
gameObject.addChild(child);

expect(grandchild._dn.parentNode).to.equal(
gameObject._dn
);
});
} else {
it('should not have addChild', () => {
expect(gameObject.addChild).to.not.exist;
Expand Down Expand Up @@ -830,6 +864,43 @@ describe(
expect(child.world.x).to.equal(10);
expect(child.world.y).to.equal(20);
});

it('should remove dom nodes', () => {
let child = GameObject({
x: 10,
y: 20,
_dn: document.createElement('button')
});
gameObject._dn = document.createElement('div');
document.body.appendChild(gameObject._dn);
gameObject.addChild(child);
gameObject.removeChild(child);

expect(child._dn.parentNode).to.not.equal(gameObject._dn);
});

it('should remove nested dom nodes', () => {
let child = GameObject({
x: 10,
y: 20
});
let grandchild = GameObject({
x: 10,
y: 20,
_dn: document.createElement('button')
});
child.addChild(grandchild);
gameObject.removeChild(child);

gameObject._dn = document.createElement('div');
document.body.appendChild(gameObject._dn);
gameObject.addChild(child);
gameObject.removeChild(child);

expect(grandchild._dn.parentNode).to.not.equal(
gameObject._dn
);
});
} else {
it('should not have removeChild', () => {
expect(gameObject.removeChild).to.not.exist;
Expand Down

0 comments on commit e6cdcb2

Please sign in to comment.