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...