11import { A } from '@ember/array' ;
2- import { get } from '@ember/object' ;
3- import { isPresent , isEmpty } from '@ember/utils' ;
4- import ObjectProxy from '@ember/object/proxy' ;
2+ import { get , set } from '@ember/object' ;
3+ import { isEmpty } from '@ember/utils' ;
54
65/* Build a tree (nested objects) from a plain array
76 * using `id` and `parentId` as references for the
@@ -18,38 +17,24 @@ export function buildTree(model, options) {
1817 return roots ;
1918 }
2019
21- let element = model [ 0 ] || get ( model , 'firstObject' ) ;
22- if ( typeof element !== 'object' ) {
23- // Not a model of objects, hence it should be a flat list
24- return buildFlatList ( model ) ;
25- }
26-
27- // Add all nodes to tree
20+ // Set defaults and add all nodes to tree
2821 model . forEach ( node => {
29- let child = {
30- content : node ,
31- children : A ( ) ,
32- isSelected : false ,
33- isVisible : true
34- } ;
35-
3622 // Alternative name for `id`
3723 if ( options . valueKey ) {
38- child . id = get ( node , options . valueKey ) ;
24+ set ( node , 'id' , get ( node , options . valueKey ) ) ;
3925 }
4026
4127 // Alternative name for `name`
4228 if ( options . labelKey ) {
43- child . name = get ( node , options . labelKey ) ;
29+ set ( node , ' name' , get ( node , options . labelKey ) ) ;
4430 }
4531
46- // Decide if node is expanded
47- if ( isPresent ( options . isExpanded ) ) {
48- child . isExpanded = options . isExpanded ;
49- }
32+ // Defaults
33+ set ( node , 'children' , A ( ) ) ;
34+ set ( node , 'isVisible' , get ( node , 'isVisible' ) || true ) ;
35+ set ( node , 'isExpanded' , get ( node , 'isExpanded' ) || false ) ;
5036
51- // Proxy options to keep model intact
52- tree [ get ( child , 'id' ) ] = ObjectProxy . create ( child ) ;
37+ tree [ get ( node , 'id' ) ] = node ;
5338 } ) ;
5439
5540 // Connect all children to their parent
@@ -58,35 +43,59 @@ export function buildTree(model, options) {
5843 let parent = get ( node , 'parentId' ) ;
5944
6045 if ( isEmpty ( parent ) ) {
61- roots . push ( child ) ;
46+ roots . pushObject ( child ) ;
6247 } else {
63- tree [ parent ] . children . push ( child ) ;
48+ get ( tree [ parent ] , ' children' ) . pushObject ( child ) ;
6449 }
6550 } ) ;
6651
6752 return roots ;
6853}
6954
70- // Builds a list of proxies from a model of values
71- export function buildFlatList ( model ) {
72- let list = model . map ( node => ObjectProxy . create ( {
73- content : node ,
74- id : node ,
75- name : node ,
76- isSelected : false ,
77- isVisible : true
78- } ) ) ;
79-
80- return A ( list ) ;
55+ // Gets all descendents of a tree (array)
56+ // Returns a flat list of all descenents, including the top level of the tree
57+ export function getDescendents ( tree , depth = - 1 ) {
58+ let descendents = A ( ) ;
59+
60+ if ( depth < 0 ) { // Unlimited depth
61+ tree . forEach ( node => {
62+ descendents . pushObject ( node ) ;
63+ descendents . pushObjects ( getDescendents ( node . children ) ) ;
64+ } ) ;
65+ } else if ( depth > 0 ) {
66+ tree . forEach ( node => {
67+ descendents . pushObject ( node ) ;
68+ descendents . pushObjects ( getDescendents ( node . children , depth - 1 ) ) ;
69+ } ) ;
70+ }
71+
72+ return descendents ;
8173}
8274
83- export function getDescendents ( tree ) {
84- let descendents = A ( ) ;
75+ // Gets all ancestors of a childNode given a tree (array)
76+ // Returns a flat list of ancestors, including the childNode
77+ export function getAncestors ( tree , childNode ) {
78+ let ancestors = A ( ) ;
79+ let childId = childNode . get ( 'id' ) ;
8580
8681 tree . forEach ( node => {
87- descendents . pushObject ( node ) ;
88- descendents . pushObjects ( getDescendents ( node . children ) ) ;
82+ if ( ! ancestors . isAny ( 'id' , childId ) ) {
83+ if ( node . id === childId ) {
84+ ancestors . pushObject ( node ) ;
85+ } else if ( node . children . length > 0 ) {
86+ ancestors . pushObjects ( getAncestors ( node . children , childNode ) ) ;
87+ if ( ancestors . length > 0 ) {
88+ ancestors . pushObject ( node ) ;
89+ }
90+ }
91+ }
8992 } ) ;
9093
91- return descendents ;
94+ return ancestors ;
9295}
96+
97+ // Gets the direct parent of a childNode given a flat list
98+ // Returns single object (parent) or undefined
99+ export function getParent ( list , childNode ) {
100+ return list . find ( x => x . children . find ( y => y . id === childNode . get ( 'id' ) ) ) ;
101+ }
0 commit comments