1 |
|
2 |
|
3 | import React from 'react';
|
4 |
|
5 | export function browser(navigator) {
|
6 | let tem;
|
7 | const ua = navigator.userAgent;
|
8 | let M = ua.match(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i) || [];
|
9 | if (/trident/i.test(M[1])) {
|
10 | tem = /\brv[ :]+(\d+)/g.exec(ua) || [];
|
11 | return `IE ${tem[1] || ''}`;
|
12 | }
|
13 | if (M[1] === 'Chrome') {
|
14 | tem = ua.match(/\b(OPR|Edge)\/(\d+)/);
|
15 | if (tem) return tem.slice(1).join(' ').replace('OPR', 'Opera');
|
16 | }
|
17 | M = M[2] ? [M[1], M[2]] : [navigator.appName, navigator.appVersion, '-?'];
|
18 | tem = ua.match(/version\/(\d+)/i);
|
19 | if (tem) {
|
20 | M.splice(1, 1, tem[1]);
|
21 | }
|
22 | return M.join(' ');
|
23 | }
|
24 |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 |
|
31 |
|
32 |
|
33 |
|
34 |
|
35 |
|
36 |
|
37 |
|
38 |
|
39 |
|
40 |
|
41 |
|
42 |
|
43 |
|
44 |
|
45 |
|
46 |
|
47 |
|
48 |
|
49 |
|
50 |
|
51 |
|
52 |
|
53 |
|
54 | export function getOffset(ele) {
|
55 | let doc, win, docElem, rect;
|
56 |
|
57 | if (!ele.getClientRects().length) {
|
58 | return { top: 0, left: 0 };
|
59 | }
|
60 |
|
61 | rect = ele.getBoundingClientRect();
|
62 |
|
63 | if (rect.width || rect.height) {
|
64 | doc = ele.ownerDocument;
|
65 | win = doc.defaultView;
|
66 | docElem = doc.documentElement;
|
67 |
|
68 | return {
|
69 | top: rect.top + win.pageYOffset - docElem.clientTop,
|
70 | left: rect.left + win.pageXOffset - docElem.clientLeft
|
71 | };
|
72 | }
|
73 |
|
74 | return rect;
|
75 | }
|
76 |
|
77 |
|
78 | function getChildrenlength(children) {
|
79 | let len = 1;
|
80 | if (Array.isArray(children)) {
|
81 | len = children.length;
|
82 | }
|
83 | return len;
|
84 | }
|
85 |
|
86 | function getSiblingPosition(index, len, siblingPosition) {
|
87 | if (len === 1) {
|
88 | siblingPosition.first = true;
|
89 | siblingPosition.last = true;
|
90 | } else {
|
91 | siblingPosition.first = index === 0;
|
92 | siblingPosition.last = index === len - 1;
|
93 | }
|
94 | return siblingPosition;
|
95 | }
|
96 |
|
97 | export function loopAllChildren(childs, callback, parent) {
|
98 | const loop = (children, level, _parent) => {
|
99 | const len = getChildrenlength(children);
|
100 | React.Children.forEach(children, (item, index) => {
|
101 | const pos = `${level}-${index}`;
|
102 | if (item.props.children && item.type && item.type.isTreeNode) {
|
103 | loop(item.props.children, pos, { node: item, pos });
|
104 | }
|
105 | callback(item, index, pos, item.key || pos, getSiblingPosition(index, len, {}), _parent);
|
106 | });
|
107 | };
|
108 | loop(childs, 0, parent);
|
109 | }
|
110 |
|
111 | export function isInclude(smallArray, bigArray) {
|
112 | return smallArray.every((ii, i) => {
|
113 | return ii === bigArray[i];
|
114 | });
|
115 | }
|
116 |
|
117 |
|
118 |
|
119 |
|
120 | export function filterParentPosition(arr) {
|
121 | const levelObj = {};
|
122 | arr.forEach((item) => {
|
123 | const posLen = item.split('-').length;
|
124 | if (!levelObj[posLen]) {
|
125 | levelObj[posLen] = [];
|
126 | }
|
127 | levelObj[posLen].push(item);
|
128 | });
|
129 | const levelArr = Object.keys(levelObj).sort();
|
130 | for (let i = 0; i < levelArr.length; i++) {
|
131 | if (levelArr[i + 1]) {
|
132 | levelObj[levelArr[i]].forEach(ii => {
|
133 | for (let j = i + 1; j < levelArr.length; j++) {
|
134 | levelObj[levelArr[j]].forEach((_i, index) => {
|
135 | if (isInclude(ii.split('-'), _i.split('-'))) {
|
136 | levelObj[levelArr[j]][index] = null;
|
137 | }
|
138 | });
|
139 | levelObj[levelArr[j]] = levelObj[levelArr[j]].filter(p => p);
|
140 | }
|
141 | });
|
142 | }
|
143 | }
|
144 | let nArr = [];
|
145 | levelArr.forEach(i => {
|
146 | nArr = nArr.concat(levelObj[i]);
|
147 | });
|
148 | return nArr;
|
149 | }
|
150 |
|
151 |
|
152 |
|
153 |
|
154 |
|
155 | function stripTail(str) {
|
156 | const arr = str.match(/(.+)(-[^-]+)$/);
|
157 | let st = '';
|
158 | if (arr && arr.length === 3) {
|
159 | st = arr[1];
|
160 | }
|
161 | return st;
|
162 | }
|
163 | function splitPosition(pos) {
|
164 | return pos.split('-');
|
165 | }
|
166 |
|
167 | export function handleCheckState(obj, checkedPositionArr, checkIt) {
|
168 |
|
169 | let objKeys = Object.keys(obj);
|
170 |
|
171 | objKeys.forEach((i, index) => {
|
172 | const iArr = splitPosition(i);
|
173 | let saved = false;
|
174 | checkedPositionArr.forEach((_pos) => {
|
175 |
|
176 | const _posArr = splitPosition(_pos);
|
177 | if (iArr.length > _posArr.length && isInclude(_posArr, iArr)) {
|
178 | obj[i].halfChecked = false;
|
179 | obj[i].checked = checkIt;
|
180 | objKeys[index] = null;
|
181 | }
|
182 | if (iArr[0] === _posArr[0] && iArr[1] === _posArr[1]) {
|
183 |
|
184 | saved = true;
|
185 | }
|
186 | });
|
187 | if (!saved) {
|
188 | objKeys[index] = null;
|
189 | }
|
190 | });
|
191 |
|
192 |
|
193 | objKeys = objKeys.filter(i => i);
|
194 |
|
195 | for (let pIndex = 0; pIndex < checkedPositionArr.length; pIndex++) {
|
196 |
|
197 | const loop = (__pos) => {
|
198 | const _posLen = splitPosition(__pos).length;
|
199 | if (_posLen <= 2) {
|
200 | return;
|
201 | }
|
202 | let sibling = 0;
|
203 | let siblingChecked = 0;
|
204 | const parentPosition = stripTail(__pos);
|
205 | objKeys.forEach((i /* , index*/) => {
|
206 | const iArr = splitPosition(i);
|
207 | if (iArr.length === _posLen && isInclude(splitPosition(parentPosition), iArr)) {
|
208 | sibling++;
|
209 | if (obj[i].checked) {
|
210 | siblingChecked++;
|
211 | const _i = checkedPositionArr.indexOf(i);
|
212 | if (_i > -1) {
|
213 | checkedPositionArr.splice(_i, 1);
|
214 | if (_i <= pIndex) {
|
215 | pIndex--;
|
216 | }
|
217 | }
|
218 | } else if (obj[i].halfChecked) {
|
219 | siblingChecked += 0.5;
|
220 | }
|
221 |
|
222 | }
|
223 | });
|
224 |
|
225 | const parent = obj[parentPosition];
|
226 |
|
227 |
|
228 | if (siblingChecked === 0) {
|
229 | parent.checked = false;
|
230 | parent.halfChecked = false;
|
231 | } else if (siblingChecked === sibling) {
|
232 | parent.checked = true;
|
233 | parent.halfChecked = false;
|
234 | } else {
|
235 | parent.halfChecked = true;
|
236 | parent.checked = false;
|
237 | }
|
238 | loop(parentPosition);
|
239 | };
|
240 | loop(checkedPositionArr[pIndex], pIndex);
|
241 | }
|
242 |
|
243 | }
|
244 |
|
245 | export function getCheck(treeNodesStates) {
|
246 | const halfCheckedKeys = [];
|
247 | const checkedKeys = [];
|
248 | const checkedNodes = [];
|
249 | const checkedNodesPositions = [];
|
250 | Object.keys(treeNodesStates).forEach((item) => {
|
251 | const itemObj = treeNodesStates[item];
|
252 | if (itemObj.checked) {
|
253 | checkedKeys.push(itemObj.key);
|
254 | checkedNodes.push(itemObj.node);
|
255 | checkedNodesPositions.push({ node: itemObj.node, pos: item });
|
256 | } else if (itemObj.halfChecked) {
|
257 | halfCheckedKeys.push(itemObj.key);
|
258 | }
|
259 | });
|
260 | return {
|
261 | halfCheckedKeys, checkedKeys, checkedNodes, checkedNodesPositions, treeNodesStates,
|
262 | };
|
263 | }
|
264 |
|
265 | export function getStrictlyValue(checkedKeys, halfChecked) {
|
266 | if (halfChecked) {
|
267 | return { checked: checkedKeys, halfChecked };
|
268 | }
|
269 | return checkedKeys;
|
270 | }
|
271 |
|
272 | export function arraysEqual(a, b) {
|
273 | if (a === b) return true;
|
274 | if (a === null || typeof a === 'undefined' || b === null || typeof b === 'undefined') {
|
275 | return false;
|
276 | }
|
277 | if (a.length !== b.length) return false;
|
278 |
|
279 |
|
280 |
|
281 |
|
282 | for (let i = 0; i < a.length; ++i) {
|
283 | if (a[i] !== b[i]) return false;
|
284 | }
|
285 | return true;
|
286 | }
|
287 |
|
288 |
|
289 | export function closest(el, selector) {
|
290 | const matchesSelector = el.matches || el.webkitMatchesSelector || el.mozMatchesSelector || el.msMatchesSelector;
|
291 |
|
292 | while (el) {
|
293 | if (matchesSelector.call(el, selector)) {
|
294 | return el;
|
295 | } else {
|
296 | el = el.parentElement;
|
297 | }
|
298 | }
|
299 | return null;
|
300 | }
|
301 |
|
302 | export function isTreeNode(node) {
|
303 | return node && node.type && node.type.isTreeNode;
|
304 | }
|
305 |
|
306 | export function toArray(children) {
|
307 | const ret = [];
|
308 | React.Children.forEach(children, (c) => {
|
309 | ret.push(c);
|
310 | });
|
311 | return ret;
|
312 | }
|
313 |
|
314 | export function getNodeChildren(children) {
|
315 | return toArray(children).filter(isTreeNode);
|
316 | }
|
317 |
|
318 | let onlyTreeNodeWarned = false;
|
319 |
|
320 | export function warnOnlyTreeNode() {
|
321 | if (onlyTreeNodeWarned) return;
|
322 | onlyTreeNodeWarned = true;
|
323 | console.warn('Tree only accept TreeNode as children.');
|
324 | }
|
325 |
|
326 |
|
327 |
|
328 |
|
329 |
|
330 |
|
331 |
|
332 | export function convertListToTree(treeData, attr, flatTreeKeysMap) {
|
333 | let tree = [];
|
334 | let resData = treeData,
|
335 | resKeysMap = {},
|
336 | treeKeysMap = {};
|
337 | resData.map((element) => {
|
338 | let key = attr.id;
|
339 | resKeysMap[element[key]] = element;
|
340 | });
|
341 |
|
342 | let findParentNode = (node) => {
|
343 | let parentKey = node[attr.parendId];
|
344 | if(parentKey !== attr.rootId) {
|
345 | let item = flatTreeKeysMap[parentKey];
|
346 |
|
347 | if(resKeysMap.hasOwnProperty(item[attr.id])) return;
|
348 | resData.unshift(item);
|
349 | resKeysMap[item[attr.id]] = item;
|
350 | findParentNode(item);
|
351 | }else{
|
352 |
|
353 | if (!treeKeysMap.hasOwnProperty(node[attr.id]) ) {
|
354 | let { key, title, children, isLeaf, ...otherProps } = node;
|
355 | let obj = {
|
356 | key,
|
357 | title,
|
358 | isLeaf,
|
359 | children: []
|
360 | }
|
361 | tree.push(Object.assign(obj, {...otherProps}));
|
362 | treeKeysMap[key] = node;
|
363 | }
|
364 | }
|
365 | }
|
366 |
|
367 | for (let i = 0; i < resData.length; i++) {
|
368 | let item = resData[i];
|
369 | if (item[attr.parendId] === attr.rootId && !treeKeysMap.hasOwnProperty(item[attr.id])) {
|
370 | let { key, title, children, ...otherProps } = item;
|
371 | let obj = {
|
372 | key: item[attr.id],
|
373 | title: item[attr.name],
|
374 | isLeaf: item[attr.isLeaf],
|
375 | children: []
|
376 | };
|
377 | tree.push(Object.assign(obj, {...otherProps}));
|
378 | treeKeysMap[key] = item;
|
379 | resData.splice(i, 1);
|
380 | i--;
|
381 | }else {
|
382 | findParentNode(item);
|
383 | }
|
384 | }
|
385 |
|
386 | var run = function(treeArrs) {
|
387 | if (resData.length > 0) {
|
388 | for (let i = 0; i < treeArrs.length; i++) {
|
389 | for (let j = 0; j < resData.length; j++) {
|
390 | let item = resData[j];
|
391 | if (treeArrs[i].key === item[attr.parendId]) {
|
392 | let { key, title, children, ...otherProps } = item;
|
393 | let obj = {
|
394 | key: item[attr.id],
|
395 | title: item[attr.name],
|
396 | isLeaf: item[attr.isLeaf],
|
397 | children: []
|
398 | };
|
399 | treeArrs[i].children.push(Object.assign(obj, {...otherProps}));
|
400 | resData.splice(j, 1);
|
401 | j--;
|
402 | }
|
403 | }
|
404 | run(treeArrs[i].children);
|
405 | }
|
406 | }
|
407 | };
|
408 | run(tree);
|
409 | return tree;
|
410 | }
|
411 |
|
412 | function isObject(value) {
|
413 | const type = typeof value
|
414 | return value != null && (type == 'object' || type == 'function')
|
415 | }
|
416 |
|
417 |
|
418 |
|
419 |
|
420 |
|
421 |
|
422 |
|
423 | export function debounce(func, wait, immediate) {
|
424 | let timeout;
|
425 | return function debounceFunc() {
|
426 | const context = this;
|
427 | const args = arguments;
|
428 |
|
429 | if (args[0] && args[0].persist) {
|
430 | args[0].persist();
|
431 | }
|
432 | const later = () => {
|
433 | timeout = null;
|
434 | if (!immediate) {
|
435 | func.apply(context, args);
|
436 | }
|
437 | };
|
438 | const callNow = immediate && !timeout;
|
439 | clearTimeout(timeout);
|
440 | timeout = setTimeout(later, wait);
|
441 | if (callNow) {
|
442 | func.apply(context, args);
|
443 | }
|
444 | };
|
445 | }
|
446 |
|
447 |
|
448 |
|
449 |
|
450 |
|
451 |
|
452 |
|
453 |
|
454 | export function throttle(func, wait, options) {
|
455 | let leading = true
|
456 | let trailing = true
|
457 |
|
458 | if (typeof func !== 'function') {
|
459 | throw new TypeError('Expected a function')
|
460 | }
|
461 | if (isObject(options)) {
|
462 | leading = 'leading' in options ? !!options.leading : leading
|
463 | trailing = 'trailing' in options ? !!options.trailing : trailing
|
464 | }
|
465 | return debounce(func, wait, {
|
466 | leading,
|
467 | trailing,
|
468 | 'maxWait': wait,
|
469 | })
|
470 | } |
\ | No newline at end of file |