UNPKG

6.13 kBPlain TextView Raw
1import { IEyzyNodeAPI } from '../types/Api'
2import { TreeComponent, TreeProps, TreeAPI } from '../types/Tree'
3import { TreeNode } from '../types/Node'
4import { State } from '../types/State'
5
6import { hasChild } from './utils'
7
8export default class EyzyNode implements IEyzyNodeAPI {
9 _tree: TreeComponent
10 _props: TreeProps
11 _state: State
12 _api: TreeAPI
13 _nodes: TreeNode[]
14
15 constructor(nodes: TreeNode[] | TreeNode | null, api: TreeAPI) {
16 this._api = api
17 this._state = api.state
18 this._tree = api.tree
19 this._props = api.tree.props
20 this._nodes = Array.isArray(nodes)
21 ? nodes
22 : (nodes ? [nodes] : [])
23 }
24
25 get length(): number {
26 return this._nodes.length
27 }
28
29 get result(): TreeNode[] | null {
30 return this._nodes.length ? this._nodes : null
31 }
32
33 private _operate(updateState: boolean, operator: (node: TreeNode, state: State) => any): boolean {
34 const result: boolean = this._nodes
35 .map((node: TreeNode) => operator(node, this._state))
36 .every(res => false !== res)
37
38 if (updateState) {
39 this._tree.updateState(this._state)
40 }
41
42 return this._nodes.length == 0 ? false : result
43 }
44
45 remove(): boolean {
46 return this._operate(false, (node: TreeNode, state: State): any => {
47 return this._api.remove(node.id)
48 })
49 }
50
51 empty(): boolean {
52 return this._operate(true, (node: TreeNode, state: State): any => {
53 if (!hasChild(node)) {
54 return false
55 }
56
57 this._api.core.clearKeys(node, true)
58
59 state.set(node.id, {
60 child: [],
61 indeterminate: false,
62 isBatch: false
63 })
64
65 if (node.parent) {
66 this._tree.refreshIndeterminateState(node.id, !!node.checked, false)
67 }
68 })
69 }
70
71 select(extendSelection?: boolean): boolean {
72 return this._operate(false, (node: TreeNode): any => {
73 if (node.selected) {
74 return false
75 }
76
77 if (this._props.multiple) {
78 this._tree.select(node, false, extendSelection)
79 } else {
80 this._tree.select(node)
81 }
82 })
83 }
84
85 unselect(): boolean {
86 return this._operate(false, (node: TreeNode): any => {
87 if (!node.selected) {
88 return false
89 }
90
91 this._tree.unselect(node)
92 })
93 }
94
95 check(): boolean {
96 if (!this._props.checkable) {
97 return false
98 }
99
100 return this._operate(false, (node: TreeNode): any => {
101 if (node.checked) {
102 return false
103 }
104
105 this._tree.check(node)
106 })
107 }
108
109 uncheck(): boolean {
110 if (!this._props.checkable) {
111 return false
112 }
113
114 return this._operate(false, (node: TreeNode, state: State): any => {
115 if (!node.checked) {
116 return false
117 }
118
119 this._tree.check(node)
120 })
121 }
122
123 disable(): boolean {
124 return this._operate(true, (node: TreeNode, state: State): any => {
125 if (node.disabled) {
126 return false
127 }
128
129 state.set(node.id, 'disabled', true)
130 })
131 }
132
133 enable(): boolean {
134 return this._operate(true, (node: TreeNode, state: State): any => {
135 if (!node.disabled) {
136 return false
137 }
138
139 state.set(node.id, 'disabled', false)
140 })
141 }
142
143 disableCheckbox(): boolean {
144 if (!this._props.checkable) {
145 return false
146 }
147
148 return this._operate(true, (node: TreeNode, state: State): any => {
149 if (node.disabledCheckbox) {
150 return false
151 }
152
153 state.set(node.id, 'disabledCheckbox', true)
154 })
155 }
156
157 enableCheckbox(): boolean {
158 if (!this._props.checkable) {
159 return false
160 }
161
162 return this._operate(true, (node: TreeNode, state: State): any => {
163 if (!node.disabledCheckbox) {
164 return false
165 }
166
167 state.set(node.id, 'disabledCheckbox', false)
168
169 if (hasChild(node) && this._props.useIndeterminateState) {
170 const iNode: TreeNode = node.checked
171 ? node
172 : node.child[0]
173
174 this._tree.refreshIndeterminateState(iNode.id, !!iNode.checked, false)
175 }
176 })
177 }
178
179 expand(): boolean {
180 return this._operate(false, (node: TreeNode): any => {
181 if (!hasChild(node) || node.expanded) {
182 return false
183 }
184
185 this._tree.expand(node)
186 })
187 }
188
189 collapse(): boolean {
190 return this._operate(false, (node: TreeNode): any => {
191 if (!hasChild(node) || !node.expanded) {
192 return false
193 }
194
195 this._tree.expand(node)
196 })
197 }
198
199 data(key: any, value?: any): any {
200 const nodes = this._nodes
201
202 if (1 === nodes.length) {
203 return this._api.core.data(nodes[0], key, value)
204 }
205
206 return nodes.map((node: TreeNode) => this._api.core.data(node, key, value))
207 }
208
209 hasClass(className: string): boolean {
210 return this._nodes.some((node: TreeNode) => this._api.core.hasClass(node, className))
211 }
212
213 addClass(...classNames: string[]): boolean {
214 this._nodes.forEach((node: TreeNode) => this._api.core.addClass(node, classNames))
215
216 return true
217 }
218
219 removeClass(...classNames: string[]): boolean {
220 return this._operate(false, (node: TreeNode) => {
221 if (!node.className) {
222 return
223 }
224
225 const oldClassNames = node.className
226 const updatedNode = this._api.core.removeClass(node, classNames)
227
228 return oldClassNames !== updatedNode.className
229 })
230 }
231
232 _find<T>(multiple: boolean, query: any): T | null {
233 const core = this._api.core
234 const nodes = core
235 .flatMap(this._nodes)
236 .nodes
237 .filter((node: TreeNode) => !~this._nodes.indexOf(node))
238
239 return core.find<T>(nodes, multiple, query)
240 }
241
242 find(...query: any): IEyzyNodeAPI {
243 const node: TreeNode | null = this._find<TreeNode>(false, query)
244 return new EyzyNode(node ? [node] : [], this._api)
245 }
246
247 findAll(...query: any): IEyzyNodeAPI {
248 const nodes: TreeNode[] | null = this._find<TreeNode[]>(true, query)
249 return new EyzyNode(nodes && nodes.length ? nodes : [], this._api)
250 }
251}
\No newline at end of file