diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..514acd3
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,20 @@
+The MIT License (MIT)
+
+Copyright (c) 2013 Steve
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/css/tree-control.css b/css/tree-control.css
new file mode 100644
index 0000000..f5f8861
--- /dev/null
+++ b/css/tree-control.css
@@ -0,0 +1,109 @@
+treecontrol {
+ /* prevent user selection */
+ -moz-user-select: -moz-none;
+ -khtml-user-select: none;
+ -webkit-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+
+ /* default */
+ font-family: Verdana, Helvetica, Arial, sans-serif;
+ font-size:13px;
+ color: #555;
+ text-decoration: none;
+}
+
+treecontrol ul {
+ margin: 0;
+ padding: 0;
+ list-style: none;
+ border: none;
+ overflow: hidden;
+}
+
+treecontrol li {
+ position: relative;
+ padding: 0 0 0 20px;
+ line-height: 20px;
+}
+
+treecontrol li.tree-expanded i.tree-normal, treecontrol li.tree-collapsed i.tree-normal {display:none;}
+treecontrol li.tree-expanded i.tree-has-children, treecontrol li.tree-collapsed i.tree-has-children {display:inline;}
+treecontrol li.tree-normal i.tree-has-children {display:none;}
+treecontrol li.tree-normal i.tree-normal {display:inline;}
+
+treecontrol li i {
+ cursor: pointer;
+}
+
+treecontrol li .tree-label {
+ cursor: pointer;
+ display: inline;
+}
+
+
+treecontrol.tree-classic li.tree-expanded i {
+ padding: 1px 10px;
+ background: url("../images/folder.png") no-repeat;
+}
+
+treecontrol.tree-classic li.tree-collapsed i {
+ padding: 1px 10px;
+ background: url("../images/folder-closed.png") no-repeat;
+}
+
+treecontrol.tree-classic li.tree-normal i {
+ padding: 1px 10px;
+ background: url("../images/file.png") no-repeat;
+}
+
+treecontrol.tree-classic li .tree-selected {
+ background-color: #aaddff;
+ font-weight: bold;
+}
+
+
+treecontrol.tree-light li.tree-expanded i {
+ padding: 1px 10px;
+ background: url("../images/node-opened-2.png") no-repeat;
+}
+
+treecontrol.tree-light li.tree-collapsed i {
+ padding: 1px 10px;
+ background: url("../images/node-closed-2.png") no-repeat;
+}
+
+treecontrol.tree-light li.tree-normal i {
+ padding: 1px 10px;
+ width: 16px; height: 16px;
+ background: none no-repeat;
+}
+
+treecontrol.tree-light li .tree-selected {
+ font-weight: bold;
+}
+
+
+treecontrol.tree-dark li.tree-expanded i {
+ padding: 1px 10px;
+ background: url("../images/node-opened-light.png") no-repeat;
+}
+
+treecontrol.tree-dark li.tree-collapsed i {
+ padding: 1px 10px;
+ background: url("../images/node-closed-light.png") no-repeat;
+}
+
+treecontrol.tree-dark li.tree-normal i {
+ padding: 1px 10px;
+ width: 16px; height: 16px;
+ background: none no-repeat;
+}
+
+treecontrol.tree-dark li .tree-selected {
+ font-weight: bold;
+}
+
+treecontrol.tree-dark {
+ color: #ddd;
+}
\ No newline at end of file
diff --git a/demo/tree-controll.html b/demo/tree-controll.html
new file mode 100644
index 0000000..0ae7dc0
--- /dev/null
+++ b/demo/tree-controll.html
@@ -0,0 +1,82 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Classic Tree
+
Selected: {{node1.label?node1.label:"N/A"}}
+
+ label: {{node.label}} ({{node.id}})
+
+
+
+
Light Tree
+
Selected: {{node2.label?node2.label:"N/A"}}
+
+ label: {{node.label}} ({{node.id}})
+
+
+
+
Dark Tree
+
Selected: {{node3.label?node2.label:"N/A"}}
+
+ label: {{node.label}} ({{node.id}})
+
+
+
+
Selection
+ Based on callback (on-selection): {{selected}}
+ Based on binding (selected-node): {{node1.label}}, {{node2.label}}, {{node3.label}}
+
Mutate the tree
+
add root
+
add child (to the first root of the tree)
+
+
+
+
\ No newline at end of file
diff --git a/images/file.png b/images/file.png
new file mode 100644
index 0000000..ffd22db
Binary files /dev/null and b/images/file.png differ
diff --git a/images/folder-closed.png b/images/folder-closed.png
new file mode 100644
index 0000000..9c8489c
Binary files /dev/null and b/images/folder-closed.png differ
diff --git a/images/folder.png b/images/folder.png
new file mode 100644
index 0000000..fdad546
Binary files /dev/null and b/images/folder.png differ
diff --git a/images/node-closed-2.png b/images/node-closed-2.png
new file mode 100644
index 0000000..dd92ffd
Binary files /dev/null and b/images/node-closed-2.png differ
diff --git a/images/node-closed-light.png b/images/node-closed-light.png
new file mode 100644
index 0000000..7fd25bc
Binary files /dev/null and b/images/node-closed-light.png differ
diff --git a/images/node-closed.png b/images/node-closed.png
new file mode 100644
index 0000000..d6d65a1
Binary files /dev/null and b/images/node-closed.png differ
diff --git a/images/node-opened-2.png b/images/node-opened-2.png
new file mode 100644
index 0000000..09ac4fc
Binary files /dev/null and b/images/node-opened-2.png differ
diff --git a/images/node-opened-light.png b/images/node-opened-light.png
new file mode 100644
index 0000000..47b558d
Binary files /dev/null and b/images/node-opened-light.png differ
diff --git a/images/node-opened.png b/images/node-opened.png
new file mode 100644
index 0000000..5b88e61
Binary files /dev/null and b/images/node-opened.png differ
diff --git a/tree-control.js b/tree-control.js
new file mode 100644
index 0000000..87c0b54
--- /dev/null
+++ b/tree-control.js
@@ -0,0 +1,119 @@
+(function ( angular ) {
+ 'use strict';
+
+ angular.module( 'treeControl', [] )
+ .directive( 'treecontrol', ['$compile', function( $compile ) {
+ return {
+ restrict: 'E',
+ require: "treecontrol",
+ transclude: true,
+ scope: {
+ treeModel: "=",
+ selectedNode: "=",
+ onSelection: "&",
+ nodeChildren: "@"
+ },
+ controller: function( $scope ) {
+
+ $scope.nodeChildren = $scope.nodeChildren || 'children';
+ $scope.expandedNodes = {};
+
+ $scope.headClass = function(node) {
+ if (node[$scope.nodeChildren].length && !$scope.expandedNodes[this.$id])
+ return "tree-collapsed";
+ else if (node[$scope.nodeChildren].length && $scope.expandedNodes[this.$id])
+ return "tree-expanded";
+ else
+ return "tree-normal"
+ };
+
+ $scope.nodeExpanded = function() {
+ return $scope.expandedNodes[this.$id];
+ };
+
+ $scope.selectNodeHead = function() {
+ $scope.expandedNodes[this.$id] = !$scope.expandedNodes[this.$id];
+ };
+
+ $scope.selectNodeLabel = function( selectedNode ){
+ $scope.selectedScope = this.$id;
+ $scope.selectedNode = selectedNode;
+ if ($scope.onSelection)
+ $scope.onSelection({node: selectedNode});
+ };
+
+ $scope.selectedClass = function() {
+ return (this.$id == $scope.selectedScope)?"tree-selected":"";
+ };
+
+ //tree template
+ var template =
+ '' +
+ '- ' +
+ '' +
+ '' +
+ '' +
+ '' +
+ '
' +
+ '
';
+
+ return {
+ templateRoot: $compile(template),
+ templateChild: $compile(template)
+ }
+ },
+ compile: function(element, attrs, childTranscludeFn) {
+ return function ( scope, element, attrs, treemodelCntr ) {
+
+ function updateNodeOnRootScope(newValue) {
+ if (angular.isArray(newValue)) {
+ scope.node = {};
+ scope.node[scope.nodeChildren] = newValue;
+ }
+ else {
+ scope.node = newValue;
+ }
+ }
+ scope.$watch("treeModel", updateNodeOnRootScope);
+ updateNodeOnRootScope(scope.treeModel);
+
+ //Rendering template for a root node
+ treemodelCntr.templateRoot( scope, function(clone) {
+ element.html('').append( clone );
+ });
+ // save the transclude function from compile (which is not bound to a scope as apposed to the one from link)
+ // we can fix this to work with the link transclude function with angular 1.2.6. as for angular 1.2.0 we need
+ // to keep using the compile function
+ scope.$treeTransclude = childTranscludeFn;
+ }
+ }
+ };
+ }])
+ .directive("treeitem", function() {
+ return {
+ restrict: 'E',
+ require: "^treecontrol",
+ link: function( scope, element, attrs, treemodelCntr) {
+
+ // Rendering template for the current node
+ treemodelCntr.templateChild(scope, function(clone) {
+ element.html('').append(clone);
+ });
+ }
+ }
+ })
+ .directive("treeTransclude", function() {
+ return {
+ link: function(scope, element, attrs, controller) {
+ scope.$treeTransclude(scope, function(clone) {
+ element.empty();
+ element.append(clone);
+ });
+ }
+ }
+ });
+})( angular );
+
+
+
+