1
1
export function searchById ( id ) {
2
2
return ( item ) => item . id === id ;
3
3
}
4
+
5
+
6
+ export interface IIndex < T > {
7
+ id ?: number ;
8
+ node ?: T ;
9
+ parent ?: number ;
10
+ prev ?: number ;
11
+ next ?: number ;
12
+ [ x : string ] : any ; // default: children: []
13
+ }
14
+ export interface IIndexs < T > {
15
+ [ index : number ] : IIndex < T > ;
16
+ }
17
+ export interface ITreeInterface < T > {
18
+ count : number ;
19
+ obj : T ;
20
+ indexes : IIndexs < T > ;
21
+ childNodeName : string ;
22
+ }
23
+
24
+ export class TreeViewUtil < T = any > implements ITreeInterface < T > {
25
+ count : number ;
26
+ obj : T ;
27
+ indexes : IIndexs < T > ;
28
+ childNodeName : string ;
29
+
30
+ /**
31
+ *
32
+ * @param obj // tree object
33
+ * @param childNodeName // loop properties
34
+ * @example indexes data structure example:
35
+ * {
36
+ [2]: {
37
+ id: 2,
38
+ node: {},
39
+ parent: 1,
40
+ prev: null,
41
+ next: 3
42
+ },
43
+ ...
44
+ }
45
+ */
46
+ constructor ( obj , childNodeName = 'children' ) {
47
+ this . count = 1 ; // nodes count
48
+ this . obj = obj || { [ childNodeName ] : [ ] } ;
49
+ this . indexes = { } ;
50
+ this . childNodeName = childNodeName ;
51
+ this . generate ( this . obj ) ;
52
+ }
53
+
54
+ generate ( obj ) {
55
+ const indexes = this . indexes ;
56
+ const startId = obj . id ;
57
+ const self = this ;
58
+
59
+ const index : IIndex < T > = { id : startId , node : obj } ;
60
+ indexes [ startId + '' ] = index ;
61
+ this . count ++ ;
62
+
63
+ if ( obj [ this . childNodeName ] ?. length ) {
64
+ walk ( obj [ this . childNodeName ] , index ) ;
65
+ }
66
+
67
+ function walk ( objs , parent ) {
68
+ const children : number [ ] = [ ] ; // current children ids
69
+ objs . forEach ( function ( obj : any , i ) {
70
+ const index : IIndex < T > = { } ;
71
+ index . id = obj . id ;
72
+ index . node = obj ;
73
+
74
+ if ( parent ) index . parent = parent . id ;
75
+
76
+ indexes [ obj . id + '' ] = index ;
77
+ children . push ( obj . id as number ) ;
78
+ self . count ++ ;
79
+
80
+ if ( obj [ self . childNodeName ] ?. length ) {
81
+ walk ( obj [ self . childNodeName ] , index ) ;
82
+ }
83
+ } ) ;
84
+ parent [ self . childNodeName ] = children ;
85
+
86
+ children . forEach ( function ( id , i ) {
87
+ const index = indexes [ id + '' ] ;
88
+ if ( i > 0 ) index . prev = children [ i - 1 ] ;
89
+ if ( i < children . length - 1 ) index . next = children [ i + 1 ] ;
90
+ } ) ;
91
+ }
92
+
93
+ return index ;
94
+ }
95
+
96
+ getIndex ( id : number ) {
97
+ const index = this . indexes [ id + '' ] ;
98
+ if ( index ) return index ;
99
+ }
100
+
101
+ removeIndex ( index : number ) {
102
+ const self = this ;
103
+ del ( index ) ;
104
+
105
+ function del ( index ) {
106
+ delete self . indexes [ index . id + '' ] ;
107
+ if ( index [ self . childNodeName ] ?. length ) {
108
+ index [ self . childNodeName ] . forEach ( function ( child ) {
109
+ del ( self . getIndex ( child ) ) ;
110
+ } ) ;
111
+ }
112
+ }
113
+ }
114
+
115
+ get ( id : number ) {
116
+ const index = this . getIndex ( id ) ;
117
+ if ( index ?. node ) return index . node ;
118
+ return null ;
119
+ }
120
+
121
+ remove ( id : number ) {
122
+ const index = this . getIndex ( id ) ;
123
+ const node = this . get ( id ) ;
124
+ const parentIndex = this . getIndex ( index . parent ) ;
125
+ const parentNode = this . get ( index . parent ) ;
126
+
127
+ parentNode [ this . childNodeName ] . splice (
128
+ parentNode [ this . childNodeName ] . indexOf ( node ) ,
129
+ 1
130
+ ) ;
131
+ parentIndex [ this . childNodeName ] . splice (
132
+ parentIndex [ this . childNodeName ] . indexOf ( id ) ,
133
+ 1
134
+ ) ;
135
+ this . removeIndex ( index ) ;
136
+ this . updateChildren ( parentIndex [ this . childNodeName ] ) ;
137
+
138
+ return node ;
139
+ }
140
+
141
+ update ( id : number , extra = { } ) {
142
+ const index = this . getIndex ( id ) ;
143
+ const node = this . get ( id ) ;
144
+ const parentIndex = this . getIndex ( index . parent ) ;
145
+ const parentNode = this . get ( index . parent ) ;
146
+ parentNode [ this . childNodeName ] . splice (
147
+ parentNode [ this . childNodeName ] . indexOf ( node ) ,
148
+ 1 ,
149
+ {
150
+ ...node ,
151
+ ...extra ,
152
+ }
153
+ ) ;
154
+ this . updateChildren ( parentIndex [ this . childNodeName ] ) ;
155
+
156
+ return node ;
157
+ }
158
+
159
+ updateChildren ( children : IIndex < T > ) {
160
+ const self = this ;
161
+ children . forEach ( function ( id , i ) {
162
+ const index = self . getIndex ( id ) ;
163
+ index . prev = index . next = null ;
164
+ if ( i > 0 ) index . prev = children [ i - 1 ] ;
165
+ if ( i < children . length - 1 ) index . next = children [ i + 1 ] ;
166
+ } ) ;
167
+ }
168
+
169
+ insert ( obj : T , parentId : number , i : number ) {
170
+ const parentIndex = this . getIndex ( parentId ) ;
171
+ const parentNode = this . get ( parentId ) ;
172
+
173
+ const index = this . generate ( obj ) ;
174
+ index . parent = parentId ;
175
+
176
+ parentNode [ this . childNodeName ] = parentNode [ this . childNodeName ] || [ ] ;
177
+ parentIndex [ this . childNodeName ] = parentIndex [ this . childNodeName ] || [ ] ;
178
+
179
+ parentNode [ this . childNodeName ] . splice ( i , 0 , obj ) ;
180
+ parentIndex [ this . childNodeName ] . splice ( i , 0 , index . id ) ;
181
+
182
+ this . updateChildren ( parentIndex [ this . childNodeName ] ) ;
183
+ if ( parentIndex . parent ) {
184
+ this . updateChildren (
185
+ this . getIndex ( parentIndex . parent ) [ this . childNodeName ]
186
+ ) ;
187
+ }
188
+
189
+ return index ;
190
+ }
191
+
192
+ insertBefore ( obj : T , destId : number ) {
193
+ const destIndex = this . getIndex ( destId ) ;
194
+ const parentId = destIndex . parent ;
195
+ const i = this . getIndex ( parentId ) [ this . childNodeName ] . indexOf ( destId ) ;
196
+ return this . insert ( obj , parentId , i ) ;
197
+ }
198
+
199
+ insertAfter ( obj : T , destId : number ) {
200
+ const destIndex = this . getIndex ( destId ) ;
201
+ const parentId = destIndex . parent ;
202
+ const i = this . getIndex ( parentId ) [ this . childNodeName ] . indexOf ( destId ) ;
203
+ return this . insert ( obj , parentId , i + 1 ) ;
204
+ }
205
+
206
+ prepend ( obj : T , destId : number ) {
207
+ return this . insert ( obj , destId , 0 ) ;
208
+ }
209
+
210
+ append ( obj : T , destId : number ) {
211
+ const destIndex = this . getIndex ( destId ) ;
212
+ destIndex [ this . childNodeName ] = destIndex [ this . childNodeName ] || [ ] ;
213
+ return this . insert ( obj , destId , destIndex [ this . childNodeName ] . length ) ;
214
+ }
215
+ }
0 commit comments