1 | import { IEyzyNodeAPI } from '../types/Api'
|
2 | import { TreeComponent, TreeProps, TreeAPI } from '../types/Tree'
|
3 | import { TreeNode } from '../types/Node'
|
4 | import { State } from '../types/State'
|
5 |
|
6 | import { hasChild } from './utils'
|
7 |
|
8 | export 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 |