Skip to content
Merged
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
13 changes: 10 additions & 3 deletions API.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ item: `left` and `right`.
NestedSetModel
----

**constructor(`array` model)**
**constructor(`array` model, `object?` options)**

The constructor takes a single argument, which is a collection of sets
expressed as a single array.
The constructor takes a two arguments, a mandatory collection of sets
expressed as a single array and an optional object containing options.

The constructor sorts the collection by left nodes ascending.
This is done to optimize child lookups, as it only has to match
Expand All @@ -30,6 +30,13 @@ __Take note that utliple root nodes are not supported at this time.__
```javascript
var model = new NestedSetModel(my_array);
```

If your original data source uses keys other than `left` and `right` you can pass them into the constructor using `options`:

**Example**
```javascript
var model = new NestedSetModel(my_array, {left: 'l', right: 'r'});
```
----

**find(`object` partial, `boolean` strict)**
Expand Down
34 changes: 18 additions & 16 deletions nested-set-model.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,29 @@
// nested set model (l;r) parent search

var NestedSetModel = function(model) {
var NestedSetModel = function(model, options) {

options = options || {};
this.leftKey = options.left || 'left';
this.rightKey = options.right || 'key';

this.model = [];
this.index = {};

var self = this;

// sort the set for deterministic order
model.sort(function(a, b)
{
return a.left - b.left;
return a[self.leftKey] - b[self.leftKey];
});

var self = this;

// create an index
for(var index in model) {
if (!model.hasOwnProperty(index)) {
continue;
}

this.index[model[index].right] = index;
this.index[model[index][this.rightKey]] = index;
}

for(var entry in model) {
Expand Down Expand Up @@ -90,9 +95,6 @@ var NestedSetModelNode = function(node, model, index) {
this.model = model;
this.index = index;

if (typeof node !== 'object')
debugger;

var self = this;
Object.keys(node).forEach(function(prop) {
self[prop] = node[prop];
Expand All @@ -104,7 +106,7 @@ NestedSetModelNode.prototype.parents = function() {
var self = this;

this.model.map(function(node) {
if (self.left > node.left && self.right < node.right) {
if (self[self.model.leftKey] > node[self.model.leftKey] && self[self.model.rightKey] < node[self.model.rightKey]) {
parents.push(new NestedSetModelNode(node, self.model, self.index));
}
});
Expand All @@ -114,10 +116,10 @@ NestedSetModelNode.prototype.parents = function() {

NestedSetModelNode.prototype.descendants = function() {
var descendants = [];
var num_items = Math.floor((this.right - this.left) / 2);
var num_items = Math.floor((this.model.rightKey - this.model.leftKey) / 2);

for(var right in this.index) {
if (right < this.right && right > this.left) {
if (right < this.model.rightKey && right > this.model.leftKey) {
var node = this.model[this.index[right]];
descendants.push(new NestedSetModelNode(node, this.model, this.index));
}
Expand All @@ -128,32 +130,32 @@ NestedSetModelNode.prototype.descendants = function() {

NestedSetModelNode.prototype.children = function() {
var children = [];
var right = this.right - 1;
var right = this.model.rightKey - 1;

while(true) {
if (right === this.left) {
if (right === this.model.leftKey) {
break;
}

var child = this.model[this.index[right]];
children.push(new NestedSetModelNode(child, this.model, this.index));
right = child.left - 1;
right = child.model.leftKey - 1;
}

return children.reverse();
}


NestedSetModelNode.prototype.isLeaf = function() {
return this.right - this.left === 1;
return this.model.rightKey - this.model.leftKey === 1;
}

NestedSetModelNode.prototype.isParent = function() {
return !this.isLeaf();
}

NestedSetModelNode.prototype.isDescendant = function() {
return this.left > 0 && this.right < (this.model.length * 2);
return this.model.leftKey > 0 && this.model.rightKey < (this.model.length * 2);
}

// bootstrap
Expand Down