-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
516 additions
and
123 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
<link rel="import" href="cosmoz-tree.html"> | ||
<script> | ||
'use strict'; | ||
|
||
window.Cosmoz = window.Cosmoz || {}; | ||
|
||
function _objectValues(obj) { | ||
return Object.keys(obj).map(function (key) { | ||
return obj[key]; | ||
}); | ||
} | ||
|
||
/** | ||
* Cosmoz.DefaultTree | ||
* | ||
* @constructor | ||
*/ | ||
Cosmoz.DefaultTree = function (treeData) { | ||
Cosmoz.Tree.apply(this, arguments); | ||
this._treeData = treeData; | ||
this._roots = _objectValues(treeData); | ||
}; | ||
|
||
Cosmoz.DefaultTree.prototype = Object.create(Cosmoz.Tree.prototype); | ||
|
||
Cosmoz.DefaultTree.prototype.getNodeByProperty = function (propertyName, propertyValue) { | ||
if (propertyName === undefined || propertyValue === undefined) { | ||
return; | ||
} | ||
|
||
if (propertyName === 'pathLocator') { | ||
return this._getNodeByPathLocator(propertyValue); | ||
} | ||
|
||
return this._searchAllRoots(propertyName, propertyValue); | ||
}; | ||
|
||
Cosmoz.DefaultTree.prototype.getPath = function (node) { | ||
if (node === undefined) { | ||
return; | ||
} | ||
return this._getPathByPathLocator(node.pathLocator); | ||
}; | ||
|
||
Cosmoz.DefaultTree.prototype.getPathByProperty = function (propertyName, propertyValue) { | ||
if (propertyName === undefined || propertyValue === undefined) { | ||
return; | ||
} | ||
|
||
if (propertyName === 'pathLocator') { | ||
return this._getPathByPathLocator(propertyValue); | ||
} | ||
|
||
var node = this._searchAllRoots(propertyName, propertyValue); | ||
if (node !== undefined) { | ||
return this._getPathByPathLocator(node.pathLocator); | ||
} | ||
}; | ||
|
||
Cosmoz.DefaultTree.prototype.getChildren = function (node) { | ||
if (node === undefined) { | ||
return; | ||
} | ||
return _objectValues(node.children); | ||
}; | ||
|
||
Cosmoz.DefaultTree.prototype.getProperty = function (node, propertyName) { | ||
if (node === undefined || propertyName === undefined) { | ||
return; | ||
} | ||
|
||
return node[propertyName]; | ||
}; | ||
|
||
Cosmoz.DefaultTree.prototype._searchAllRoots = function (propertyName, propertyValue) { | ||
var i, | ||
node; | ||
|
||
for (i = 0; i < this._roots.length; i+=1) { | ||
node = this.search(this._roots[i], propertyName, propertyValue); | ||
if (node !== undefined) { | ||
return node; | ||
} | ||
} | ||
}; | ||
|
||
Cosmoz.DefaultTree.prototype._getNodeByPathLocator = function (pathLocator) { | ||
var node, | ||
path, | ||
i; | ||
|
||
for (i = 0; i < this._roots.length; i+=1) { | ||
node = this._roots[i]; | ||
if (node.pathLocator === pathLocator) { | ||
return node; | ||
} | ||
|
||
if (pathLocator.indexOf(node.pathLocator + '.') === 0) { | ||
path = pathLocator.slice(node.pathLocator.length + 1).split('.'); | ||
for (i = 0; i < path.length; i+=1) { | ||
if (node.children) { | ||
node = node.children[path[i]]; | ||
} else { | ||
node = null; | ||
} | ||
if (node === undefined || node === null) { | ||
break; | ||
} | ||
} | ||
|
||
if (node !== undefined && node !== null) { | ||
return node; | ||
} | ||
} | ||
} | ||
}; | ||
|
||
Cosmoz.DefaultTree.prototype._getPathByPathLocator = function (pathLocator) { | ||
var node, | ||
path, | ||
subPath, | ||
i; | ||
|
||
for (i = 0; i < this._roots.length; i+=1) { | ||
node = this._roots[i]; | ||
path = [node]; | ||
|
||
if (node.pathLocator === pathLocator) { | ||
return path; | ||
} | ||
|
||
if (pathLocator.indexOf(node.pathLocator + '.') === 0) { | ||
subPath = pathLocator.slice(node.pathLocator.length + 1).split('.'); | ||
for (i = 0; i < subPath.length; i+=1) { | ||
if (node.children) { | ||
node = node.children[subPath[i]]; | ||
} else { | ||
node = null; | ||
} | ||
if (node === undefined || node === null) { | ||
path = null; | ||
break; | ||
} else { | ||
path.push(node); | ||
} | ||
} | ||
|
||
if (path !== null) { | ||
return path; | ||
} | ||
} | ||
} | ||
}; | ||
|
||
|
||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,123 +1,77 @@ | ||
<script> | ||
'use strict'; | ||
|
||
if (typeof Cosmoz === 'undefined') { | ||
var Cosmoz = {}; | ||
} | ||
window.Cosmoz = window.Cosmoz || {}; | ||
|
||
|
||
/* eslint-disable no-unused-vars */ | ||
|
||
/** | ||
* Cosmoz.Tree | ||
* | ||
* @constructor | ||
*/ | ||
Cosmoz.Tree = function (node) { | ||
this._node = node; | ||
this._flattenedTree = this._flattenTree(node); | ||
this._pathLocatorSeparator = '.'; | ||
Cosmoz.Tree = function () { | ||
if (this.constructor === Cosmoz.Tree) { | ||
throw new Error('abstract'); | ||
} | ||
}; | ||
|
||
Cosmoz.Tree.prototype = { | ||
|
||
constructor: Cosmoz.Tree, | ||
|
||
findNodeById: function (id) { | ||
return this._flattenedTree[id]; | ||
getNodeByProperty: function (propertyName, propertyValue) { | ||
throw new Error('Must be implemented in derived object'); | ||
}, | ||
|
||
findNodeByPathLocator: function (pathLocator) { | ||
if (!pathLocator) { | ||
return; | ||
} | ||
return pathLocator | ||
.split(this._pathLocatorSeparator) | ||
.reduce(function (node, part) { | ||
if (node.children) { | ||
node = node.children; | ||
} | ||
if (node[part]) { | ||
node = node[part]; | ||
} | ||
return node; | ||
}, this._node); | ||
getPath: function (node) { | ||
throw new Error('Must be implemented in derived object'); | ||
}, | ||
|
||
getPath: function (keyId) { | ||
if (this.isGuid(keyId)) { | ||
return this.getPathByNodeId(keyId); | ||
} | ||
return this.getPathByLocator(keyId); | ||
getPathByProperty: function (propertyName, propertyValue) { | ||
throw new Error('Must be implemented in derived object'); | ||
}, | ||
|
||
getPathByNode: function (node) { | ||
if (!node || !node.pathLocator) { | ||
return; | ||
} | ||
var currentNode = this._node; | ||
return node.pathLocator | ||
.split(this._pathLocatorSeparator) | ||
.map(function (part) { | ||
var ret = currentNode; | ||
if (currentNode.children && currentNode.children[part]) { | ||
currentNode = currentNode.children[part]; | ||
} | ||
if (currentNode[part]) { | ||
currentNode = currentNode[part]; | ||
} | ||
if (ret === currentNode) { | ||
return; | ||
} | ||
return currentNode; | ||
}) | ||
.filter(function (part) { | ||
return part !== undefined; | ||
}); | ||
getChildren: function (node) { | ||
throw new Error('Must be implemented in derived object'); | ||
}, | ||
|
||
getPathByNodeId: function (nodeId) { | ||
var node = this.findNodeById(nodeId); | ||
return this.getPathByNode(node); | ||
getProperty: function (node, propertyName) { | ||
throw new Error('Must be implemented in derived object'); | ||
}, | ||
|
||
getPathByLocator: function (locator) { | ||
var node = this.findNodeByPathLocator(locator); | ||
return this.getPathByNode(node); | ||
getPathString: function (node, textPropertyName, separator) { | ||
var path = this.getPath(node); | ||
return path.map(function (n) { | ||
return this.getProperty(n, textPropertyName); | ||
}, this).join(separator); | ||
}, | ||
|
||
getPathString: function (path, separator) { | ||
if (!path || !Array.isArray(path) || path.length < 1) { | ||
return; | ||
getPathStringByProperty: function (propertyName, propertyValue, textPropertyName, separator) { | ||
var node = this.getNodeByProperty(propertyName, propertyValue); | ||
if (node !== undefined) { | ||
return this.getPathString(node, textPropertyName, separator); | ||
} | ||
return path.map(function (part) { | ||
return part.name; | ||
}).join(separator); | ||
}, | ||
|
||
isGuid: function (input) { // FIXME: GUID Check | ||
return input && input.length === 36; | ||
}, | ||
|
||
/** | ||
* Utility function to flatten the tree to ease node lookup. | ||
* Basic search for a node by one of its property | ||
*/ | ||
_flattenTree: function (tree, flattened) { | ||
if (!flattened) { | ||
flattened = {}; | ||
} | ||
|
||
if (tree === undefined) { | ||
return flattened; | ||
search: function (node, propertyName, propertyValue) { | ||
if (this.getProperty(node, propertyName) === propertyValue) { | ||
return node; | ||
} | ||
|
||
Object.keys(tree).forEach(function (key) { | ||
var node = tree[key]; | ||
flattened[node.id] = node; | ||
var children = this.getChildren(node), | ||
i = 0, | ||
n; | ||
|
||
if (node.children && Object.keys(node.children).length > 0) { | ||
this._flattenTree(node.children, flattened); | ||
if (children) { | ||
for (i = 0; i < children.length; i+=1) { | ||
n = this.search(children[i], propertyName, propertyValue); | ||
if (n !== undefined) { | ||
return n; | ||
} | ||
} | ||
|
||
}, this); | ||
|
||
return flattened; | ||
}, | ||
} | ||
} | ||
}; | ||
</script> | ||
</script> |
Oops, something went wrong.