TreeWalker Normalized Tree Demo
Using TreeWalker with normalized data tree
by actualwave
HTML
<script src="https://rawgit.com/burdiuz/mythology_demo_data/master/unaliased_genealogical_tree.js"></script>
<script src="https://unpkg.com/normalizr@3.2.4/dist/normalizr.umd.js"></script>
<link rel="stylesheet" href="https://unpkg.com/@actualwave/dom-console@0.0.2/console.css">
<script src="https://unpkg.com/@actualwave/dom-console@0.0.2/console.js"></script>
<script src="https://unpkg.com/@actualwave/tree-walker@1.0.6/dist/tree-walker.min.js"></script>
<script src="https://unpkg.com/@actualwave/walker-denormalize-adapter@0.0.3/index.min.js"></script>
<script src="https://unpkg.com/@actualwave/walker-property-handlers@0.0.1/index.min.js"></script>
JavaScript
const { normalize, schema } = normalizr;
const getID = (node) => {
const {label, alt, parents = 'None', shortlabel} = node;
const name = (shortlabel || label || alt)
.match(/^[\w\s]+/)[0]
.replace(/(^\s+|\s+$)/g, '');
return (`${node.parents || 'none'}/${name}`)
.toLowerCase();
};
const createNodeSchema = (level = 0, maxLevel = 25) =>
new schema.Entity('node', {
get children() {
if (level > maxLevel) {
return undefined;
}
return [createNodeSchema(level+1, maxLevel)];
},
}, {
idAttribute: getID
}
);
/**
"data" is the main data storage, contains all nodes from the tree in
single flat data structure(hash).
Original tree had many duplicates -- more than one node for same
entity with same information. Here tree stored in normalized state,
where one entity has only one node and child nodes referenced in
parents by their unique identifiers.
*/
const data = normalize(genealogical_tree, createNodeSchema());
const {
create,
addAugmentations,
nodeAugmentations,
listAugmentations,
setNamePrefix,
} = TreeWalker;
const {
createHandlers,
} = WalkerPropertyHandlers;
// add augmentations
addAugmentations(nodeAugmentations);
addAugmentations(listAugmentations);
/*
add a name prefix for node fields to access them easier
before: node.valueOf().label
after: node.$label
*/
setNamePrefix('$', createHandlers((item) => data.entities.node[item]));
const { createAdapter } = DenormalizeAdapter;
const adapter = Object.assign(
createAdapter(() => data.entities.node),
// add some changes to adapter, to handle properly this exact data structure
{
validateRoot: (item) => {
if(typeof item === 'string') return item;
return getID(item);
},
getName: (item) => item.match(/\/([^/]+)$/)[1],
});
const { log, info } = DOMConsole.create(document.body);
info('Thats how normalized data stored:');
log(data);
const root = create(data.result, adapter);
info('The root...