Skip to content
This repository was archived by the owner on Apr 4, 2020. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 16 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ know the name of the 'children' attribute).
};

var tree = Arborel.parse(wikipediaJsCategory, 'subcategories');

Also several children (or even the whole tree) can be added at the same time (syntax is similar as parse)

var tree = new Arboreal();
tree.children[1].appendChildren({category:'C#', subitems:[{category:'WPF'}]}, "subitems" );

### Traversal

Expand Down Expand Up @@ -98,7 +103,15 @@ rewritten as:
for (i = 1; i <= this.depth; i++) depth += ">>";
console.info([depth, this.data.category].join(" "));
}


Arboreal object can be iterated up to the root using method 'bubbleUp':

tree.children[2].children[0].bubbleUp(iterator)

// => >>>> JavaScript dialect engines
// >> JavaScript programming languages family
// JavaScript

### Search

In order to search for a single node into an arboreal object, one can use the `find`
Expand All @@ -122,7 +135,7 @@ it will try to find a node by id.
While traversing a tree, nodes can be deleted by calling the `remove`
method on the node object bound to the iterator function.

tree.length
tree.getLength();

// => 7

Expand All @@ -133,7 +146,7 @@ method on the node object bound to the iterator function.
}
});

tree.length;
tree.getLength();

// 5

Expand Down
44 changes: 32 additions & 12 deletions lib/arboreal.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
!function () {
'use strict';
(function () {

function include (array, item) {
return array.indexOf(item) > -1;
return indexOf(array, item) > -1;
}
function indexOf(array, item) {
for (var i = 0, j = array.length; i < j; i++) {
if (array[i] === item) { return i; }
}
return -1;
}

function _traverseDown (context, iterator) {
Expand Down Expand Up @@ -41,6 +46,14 @@
}
}

function _bubbleUp (context, iterator) {
var node;

while (context) {
if ( iterator(context) === false ) return;
context = context.parent;
}
}

function _traverse (context, iterator, callback) {
var visited = [],
Expand Down Expand Up @@ -96,7 +109,7 @@
this.children = [];
}

Arboreal.parse = function (object, childrenAttr) {
Arboreal.parse = function (object, childrenAttr, parent) {
var root, getNodeData = function (node) {
var attr, nodeData = {};
for (attr in node) {
Expand All @@ -119,9 +132,9 @@
walkDown(node[childrenAttr][i], newNode);
}
}
})(object);
})(object, parent);

return root;
return root || parent;

};

Expand All @@ -131,6 +144,10 @@
return this;
};

Arboreal.prototype.appendChildren = function (data, childrenAttr) {
return Arboreal.parse(data, childrenAttr, this);
};

Arboreal.prototype.removeChild = function (arg) {
if (typeof arg === 'number' && this.children[arg]) {
return this.children.splice(arg, 1).shift();
Expand Down Expand Up @@ -171,6 +188,10 @@
_traverse(this, iterator, _traverseDown);
};

Arboreal.prototype.bubbleUp = function (iterator) {
_traverse(this, iterator, _bubbleUp);
};

Arboreal.prototype.toString = function () {
var lines = [];

Expand Down Expand Up @@ -235,16 +256,15 @@
});
return nodeList;
};

Arboreal.prototype.__defineGetter__("length", function () {
Arboreal.prototype.getLength = function () {
return this.toArray().length;
});


};

if (typeof module !== 'undefined' && module.exports) {
module.exports = Arboreal;
} else {
this.Arboreal = Arboreal;
}

}(this);
}(this));
79 changes: 75 additions & 4 deletions test/specs/arboreal-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ describe("Arboreal", function () {
});


it("::parse()", function () {
describe("::parse()", function () {
var data = {
category: 'JavaScript',
subcategories: [
Expand All @@ -43,8 +43,29 @@ describe("Arboreal", function () {
{category: 'JavaScript based HTML editors'}
]
};
var tree = Arboreal.parse(data, 'subcategories');
expect(tree.length).toBe(7);
it("default parent", function () {
var tree = Arboreal.parse(data, 'subcategories');
expect(tree.getLength()).toBe(7);
});
it("Arboreal parent", function () {
var subData = {
category: 'C#',
subcategories: [
{category: 'WinForms'},
{category: 'WPF',
subcategories: [{
category: 'XAML markup'
}]
},

]
};
var tree = Arboreal.parse(data, 'subcategories');
var biggerTree = Arboreal.parse(subData, 'subcategories', tree.children[1]);
expect(biggerTree.children[0].getLength()).toBe(4);
expect(tree.getLength()).toBe(11);
expect(tree.children[1].children[0].data.category).toBe('C#');
});
});

it("#appendChild(null, 'bla')", function () {
Expand All @@ -54,7 +75,24 @@ describe("Arboreal", function () {
expect(tree.children[0].id).toBe("myId");
expect(tree.children[0].parent).toEqual(tree);
});


it("#appendChildren to root", function () {
var tree = new Arboreal();
tree.appendChildren({testAttr:'subroot', subitems:[{testAttr:'firstChild'}]}, "subitems" );
expect(tree.getLength()).toBe(3);
expect(tree.children[0].data.testAttr).toBe("subroot");
expect(tree.children[0].children[0].data.testAttr).toEqual('firstChild');
});

it("#appendChildren to children", function () {
var tree = new Arboreal();
tree.appendChild().appendChild()
tree.children[1].appendChildren({testAttr:'secondchild', subitems:[{testAttr:'third child'}]}, "subitems");
expect(tree.getLength()).toBe(5);
expect(tree.children[1].children[0].data.testAttr).toBe("secondchild");
expect(tree.children[1].children[0].children[0].data.testAttr).toEqual('third child');
});

it("#removeChild()", function () {
var tree = new Arboreal(),
thirdChild,
Expand Down Expand Up @@ -131,7 +169,40 @@ describe("Arboreal", function () {
});
expect(treeIds.length).toBe(3);
});

it("#bubbleUp", function () {
var tree = new Arboreal(),
callbackCounter=0,
treeIds = [],
spy1 = jasmine.createSpy(),
spy2 = jasmine.createSpy(),
appendId = function (node) {
treeIds.push(node.id);
};


appendSomeChildren(tree);
tree.bubbleUp(spy1);
//should iterate over itself
expect(spy1.callCount).toBe(1);

//should bubble up to the root
tree.children[0].children[1].bubbleUp(spy2);
expect(spy2.callCount).toBe(1+1+1);

//should bubble up in the right order
tree.children[0].children[1].bubbleUp(appendId);

expect(treeIds.shift()).toBe("0/0/1");

treeIds = [];
//should break when iterator returns a falsy value
tree.bubbleUp(function (node) {
appendId(node);
if (treeIds.length === 2) return false;
});
expect(treeIds.length).toBe(1);
});

it("#toArray", function () {
var tree = new Arboreal();
Expand Down