├── .gitignore
├── LICENSE
├── README.md
├── banner
├── bower.json
├── gruntfile.js
├── package.json
└── src
└── directives
└── dxTree.js
/.gitignore:
--------------------------------------------------------------------------------
1 | /distribution
2 | /build
3 |
4 | ## Ignore Visual Studio temporary files, build results, and
5 | ## files generated by popular Visual Studio add-ons.
6 |
7 | # User-specific files
8 | *.suo
9 | *.user
10 | *.sln.docstates
11 |
12 | # Build results
13 | [Dd]ebug/
14 | [Dd]ebugPublic/
15 | [Rr]elease/
16 | x64/
17 | build/
18 | bld/
19 | [Bb]in/
20 | [Oo]bj/
21 |
22 | # JetBrains IDEA
23 | .idea
24 |
25 | # MSTest test Results
26 | [Tt]est[Rr]esult*/
27 | [Bb]uild[Ll]og.*
28 |
29 | #NUNIT
30 | *.VisualState.xml
31 | TestResult.xml
32 |
33 | # Build Results of an ATL Project
34 | [Dd]ebugPS/
35 | [Rr]eleasePS/
36 | dlldata.c
37 |
38 | *_i.c
39 | *_p.c
40 | *_i.h
41 | *.ilk
42 | *.meta
43 | *.obj
44 | *.pch
45 | *.pdb
46 | *.pgc
47 | *.pgd
48 | *.rsp
49 | *.sbr
50 | *.tlb
51 | *.tli
52 | *.tlh
53 | *.tmp
54 | *.tmp_proj
55 | *.log
56 | *.vspscc
57 | *.vssscc
58 | .builds
59 | *.pidb
60 | *.svclog
61 | *.scc
62 |
63 | # Chutzpah Test files
64 | _Chutzpah*
65 |
66 | # Visual C++ cache files
67 | ipch/
68 | *.aps
69 | *.ncb
70 | *.opensdf
71 | *.sdf
72 | *.cachefile
73 |
74 | # Visual Studio profiler
75 | *.psess
76 | *.vsp
77 | *.vspx
78 |
79 | # TFS 2012 Local Workspace
80 | $tf/
81 |
82 | # Guidance Automation Toolkit
83 | *.gpState
84 |
85 | # ReSharper is a .NET coding add-in
86 | _ReSharper*/
87 | *.[Rr]e[Ss]harper
88 | *.DotSettings.user
89 |
90 | # JustCode is a .NET coding addin-in
91 | .JustCode
92 |
93 | # TeamCity is a build add-in
94 | _TeamCity*
95 |
96 | # DotCover is a Code Coverage Tool
97 | *.dotCover
98 |
99 | # NCrunch
100 | *.ncrunch*
101 | _NCrunch_*
102 | .*crunch*.local.xml
103 |
104 | # MightyMoose
105 | *.mm.*
106 | AutoTest.Net/
107 |
108 | # Web workbench (sass)
109 | .sass-cache/
110 |
111 | # Installshield output folder
112 | [Ee]xpress/
113 |
114 | # DocProject is a documentation generator add-in
115 | DocProject/buildhelp/
116 | DocProject/Help/*.HxT
117 | DocProject/Help/*.HxC
118 | DocProject/Help/*.hhc
119 | DocProject/Help/*.hhk
120 | DocProject/Help/*.hhp
121 | DocProject/Help/Html2
122 | DocProject/Help/html
123 |
124 | # Click-Once directory
125 | publish/
126 |
127 | # Publish Web Output
128 | *.[Pp]ublish.xml
129 | *.azurePubxml
130 |
131 | # NuGet Packages Directory
132 | packages/
133 | ## TODO: If the tool you use requires repositories.config uncomment the next line
134 | #!packages/repositories.config
135 |
136 | # Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets
137 | # This line needs to be after the ignore of the build folder (and the packages folder if the line above has been uncommented)
138 | !packages/build/
139 |
140 | # Windows Azure Build Output
141 | csx/
142 | *.build.csdef
143 |
144 | # Windows Store app package directory
145 | AppPackages/
146 |
147 | # Others
148 | sql/
149 | *.Cache
150 | ClientBin/
151 | [Ss]tyle[Cc]op.*
152 | ~$*
153 | *~
154 | *.dbmdl
155 | *.dbproj.schemaview
156 | *.pfx
157 | *.publishsettings
158 | node_modules/
159 |
160 | # RIA/Silverlight projects
161 | Generated_Code/
162 |
163 | # Backup & report files from converting an old project file to a newer
164 | # Visual Studio version. Backup files are not needed, because we have git ;-)
165 | _UpgradeReport_Files/
166 | Backup*/
167 | UpgradeLog*.XML
168 | UpgradeLog*.htm
169 |
170 | # SQL Server files
171 | *.mdf
172 | *.ldf
173 |
174 | # Business Intelligence projects
175 | *.rdl.data
176 | *.bim.layout
177 | *.bim_*.settings
178 |
179 | # Microsoft Fakes
180 | FakesAssemblies/
181 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014-2015 dotJEM
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | dotJEM Angular Tree
2 | ===================
3 |
4 | Small set of directives that helps to render templates based on tree's
5 | In reality calling it a tree-view is a bit missguided as rendering data like this is so incredible easy in angular.
6 |
7 | In essence, all we really need to do is something like:
8 |
9 | ```html
10 |
14 |
15 | ```
16 |
17 | So in essence, we don't really need any custom directives or that sort...
18 |
19 | But this doesn't entirely feel right... Why should we have to pass things through the template cache to achieve this, why can't we just provide the template directly in our html in a more natural way?...
20 |
21 | Angular Tree Repeat
22 | -------------------
23 |
24 | https://github.com/stackfull/angular-tree-repeat
25 |
26 | Angular Tree Repeat is another directive that solves this problem in a nice way.
27 |
28 | ```html
29 |
30 | -
31 | {{node.name}}
32 |
35 |
36 |
37 | ```
38 |
39 | But overall I felt the implementation could be done even more simple while also gaining all the functions of ng-repeat by reusing it as is.
40 |
41 | Inverting the idea
42 | -----------------
43 |
44 | So... Rather than focusing on the "repeater" part of it which becomes really complex really fast if we wish to keep up with the ng-repeat directive, dotJEM Angular Tree focuses only on the recursive delegation and instead leaves ng-repeat to do it's job on the nodes.
45 |
46 | So in essence we can do:
47 |
48 | ```html
49 |
50 | -
51 | {{ node.name }}
52 |
53 |
54 |
55 | ```
56 |
57 | So dx-connect will reuse the block defined by dx-start-with and provide the means to point to an actual child node.
58 |
59 | `dx-start-with` and `dx-connect` provides the variables:
60 |
61 | - `$dxPrior`: the object passed to `dx-start-with` or `dx-connect`.
62 | - `$dxIsRoot`: true if this is the root level, otherwise false.
63 | - `$dxLevel`: the level of recursion we are at starting at 0.
64 |
65 | `$dxPrior` can be aliased using the the same syntax known from controller as, as such you can name it more appropriately to the needs.
66 |
67 | ```html
68 |
69 | -
70 | {{ node.name }}
71 |
72 |
73 |
74 | ```
75 |
76 | IMPORTANT!:
77 |
78 | The template is the inner html of the dx-start-with directive, this is important to know so that you get it right when defining the dx-connect. as such if you put the dx-tree directly on the ul, the dx-node must also be an ul (or ol).
79 |
80 | ## Install
81 |
82 | Install with `bower`:
83 |
84 | ```shell
85 | bower install dotjem-angular-tree
86 | ```
87 |
88 | Add a `
92 | ```
93 |
94 | And add `dotjem.angular.tree` as a dependency for your app:
95 |
96 | ```javascript
97 | angular.module('myApp', ['dotjem.angular.tree']);
98 | ```
99 |
100 |
--------------------------------------------------------------------------------
/banner:
--------------------------------------------------------------------------------
1 | /**
2 | * @license dotJEM Angular Tree
3 | * (c) 2014-2015 dotJEM (Jens Melgaard)
4 | * License: MIT
5 | *
6 | * @module dotjem.angular.tree
7 | */
8 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "dotjem-angular-tree",
3 | "version": "0.1.0",
4 | "main": "./dotjem-angular-tree.js",
5 | "dependencies": {
6 | "angular": ">= 1.2.16"
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/gruntfile.js:
--------------------------------------------------------------------------------
1 | /*global module:false*/
2 | module.exports = function (grunt) {
3 | "use strict";
4 |
5 | // Project configuration.
6 | grunt.initConfig({
7 | pkg: grunt.file.readJSON('package.json'),
8 | banner: grunt.file.read('banner'),
9 |
10 | clean: {
11 | src: ['build', 'temp']
12 | },
13 |
14 | concat: {
15 | options: {
16 | banner: '<%= banner %>',
17 | stripBanners: true
18 | },
19 | core: {
20 | src: 'src/directives/dxTree.js',
21 | dest: 'build/<%= pkg.name %>.js'
22 | }
23 | },
24 |
25 | uglify: {
26 | options: {
27 | banner: '<%= banner %>'
28 | },
29 | core: {
30 | src: '<%= concat.core.dest %>',
31 | dest: 'build/<%= pkg.name %>.min.js'
32 | }
33 | },
34 |
35 | watch: {
36 | dev: {
37 | files: [
38 | 'src/**/*.js'
39 | ],
40 | tasks: ['build']
41 | }
42 | },
43 |
44 | ngdocs: {
45 | options: {
46 | dest: 'temp',
47 | title: "dotJEM Angular Tree",
48 | html5Mode: false
49 | },
50 | all: ['src/**/*.js']
51 | },
52 |
53 | copy: {
54 | disribution: {
55 | files: [
56 | { src: ['build/*','LICENSE', 'package.json', 'README.md'], dest: 'distribution/', expand: true, flatten: true }
57 | ]
58 | }
59 | }
60 | });
61 |
62 | // These plugins provide necessary tasks.
63 | grunt.loadNpmTasks('grunt-contrib-clean');
64 | grunt.loadNpmTasks('grunt-contrib-concat');
65 | grunt.loadNpmTasks('grunt-contrib-uglify');
66 | grunt.loadNpmTasks('grunt-contrib-watch');
67 | grunt.loadNpmTasks('grunt-contrib-connect');
68 | grunt.loadNpmTasks('grunt-contrib-copy');
69 | grunt.loadNpmTasks('grunt-ngdocs');
70 |
71 | grunt.registerTask('default', ['clean', 'build']);
72 | grunt.registerTask('develop', ['clean', 'build', 'connect', 'watch']);
73 | grunt.registerTask('build', ['concat', 'uglify']);
74 |
75 | grunt.registerTask('dist', ['build', 'copy']);
76 |
77 |
78 | };
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "dotjem-angular-tree",
3 | "title": "dotJEM Angular Tree",
4 | "description": "Directives for creating recursion.",
5 | "version": "0.2.3",
6 | "homepage": "https://github.com/dotJEM/angular-tree",
7 | "author": {
8 | "name": "dotjem",
9 | "url": "https://github.com/dotJEM"
10 | },
11 | "repository": {
12 | "type": "git",
13 | "url": "https://github.com/dotJEM/angular-tree.git"
14 | },
15 | "bugs": {
16 | "url": "https://github.com/dotJEM/angular-tree/issues"
17 | },
18 | "licenses": [
19 | {
20 | "type": "MIT",
21 | "url": "https://github.com/dotJEM/angular-tree/blob/master/LICENSE"
22 | }
23 | ],
24 | "dependencies": {},
25 | "devDependencies": {
26 | "grunt": "~0.4.2",
27 | "grunt-contrib-concat": "~0.3.0",
28 | "grunt-contrib-clean": "~0.5.0",
29 | "grunt-contrib-uglify": "~0.2.7",
30 | "grunt-contrib-watch": "~0.5.2",
31 | "grunt-contrib-connect": "~0.6.0",
32 | "grunt-contrib-copy": "~0.5.0",
33 | "grunt-ngdocs": "~0.1.9"
34 | },
35 | "keywords": []
36 | }
37 |
--------------------------------------------------------------------------------
/src/directives/dxTree.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | var comp = angular.module('dotjem.angular.tree', []),
3 | SW_REGEX = /^(\S+)(\s+as\s+(\w+))?$/;
4 |
5 | comp.controller("dxStartWithCtrl", [function () {}]);
6 |
7 | function $RootNodeDirective() {
8 | return {
9 | restrict: 'AEC',
10 | require: 'dxStartWith',
11 | controller: 'dxStartWithCtrl',
12 |
13 | scope: true,
14 | terminal: true,
15 | transclude: true,
16 | multiElement: true,
17 |
18 | $$tlb: true,
19 |
20 | compile: function (elm, attr) {
21 | var exp = attr['dxStartWith'] || attr.root,
22 | match = exp.match(SW_REGEX),
23 | watch = match[1],
24 | alias = match[3] || '';
25 |
26 | return function $RootNodeDirectiveLink(scope, elm, attr, ctrl, $transclude) {
27 | ctrl.alias = alias;
28 | ctrl.transclude = $transclude;
29 | ctrl.transclude(scope, function (clone, scope) {
30 | elm.append(clone);
31 | scope.$dxLevel = 0;
32 | scope.$dxIsRoot = true;
33 | function updatePrior(value) {
34 | scope.$dxPrior = value;
35 | if (alias !== '') {
36 | scope[alias] = value;
37 | }
38 | }
39 | scope.$watch(watch, updatePrior);
40 | });
41 | };
42 | }
43 | };
44 | }
45 |
46 | function $NodeDirective() {
47 | return {
48 | restrict: 'AEC',
49 | require: '^dxStartWith',
50 |
51 | scope: true,
52 | terminal: true,
53 | multiElement: true,
54 |
55 | compile: function (elm, attr) {
56 | var watch = attr['dxConnect'] || attr.connect;
57 |
58 | return function $NodeDirectiveLink(scope, elm, attr, ctrl) {
59 | alias = ctrl.alias || '';
60 | ctrl.transclude(scope, function (clone, scope) {
61 | elm.append(clone);
62 |
63 | scope.$dxLevel = scope.$dxLevel + 1;
64 | scope.$dxIsRoot = false;
65 | function updatePrior(value) {
66 | scope.$dxPrior = value;
67 | if (alias !== '') {
68 | scope[alias] = value;
69 | }
70 | }
71 |
72 | scope.$watch(watch, updatePrior);
73 | });
74 | };
75 | }
76 | };
77 | }
78 |
79 | comp.directive('dxStartWith', $RootNodeDirective);
80 | comp.directive('dxConnect', $NodeDirective);
81 | }());
--------------------------------------------------------------------------------