ng-zorro-antd-core-tree.mjs 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006
  1. import * as i0 from '@angular/core';
  2. import { Injectable, InjectionToken } from '@angular/core';
  3. import { BehaviorSubject } from 'rxjs';
  4. /**
  5. * Use of this source code is governed by an MIT-style license that can be
  6. * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE
  7. */
  8. class NzTreeNode {
  9. _title = '';
  10. key;
  11. level = 0;
  12. origin;
  13. // Parent Node
  14. parentNode = null;
  15. _icon = '';
  16. _children = [];
  17. _isLeaf = false;
  18. _isChecked = false;
  19. _isSelectable = false;
  20. _isDisabled = false;
  21. _isDisableCheckbox = false;
  22. _isExpanded = false;
  23. _isHalfChecked = false;
  24. _isSelected = false;
  25. _isLoading = false;
  26. canHide = false;
  27. isMatched = false;
  28. service = null;
  29. component;
  30. /** New added in Tree for easy data access */
  31. isStart;
  32. isEnd;
  33. get treeService() {
  34. return this.service || (this.parentNode && this.parentNode.treeService);
  35. }
  36. /**
  37. * Init nzTreeNode
  38. *
  39. * @param option option user's input
  40. * @param parent parent node
  41. * @param service base nzTreeService
  42. */
  43. constructor(option, parent = null, service = null) {
  44. if (option instanceof NzTreeNode) {
  45. return option;
  46. }
  47. this.service = service || null;
  48. this.origin = option;
  49. this.key = option.key;
  50. this.parentNode = parent;
  51. this._title = option.title || '---';
  52. this._icon = option.icon || '';
  53. this._isLeaf = option.isLeaf || false;
  54. this._children = [];
  55. // option params
  56. this._isChecked = option.checked || false;
  57. this._isSelectable = option.disabled || option.selectable !== false;
  58. this._isDisabled = option.disabled || false;
  59. this._isDisableCheckbox = option.disableCheckbox || false;
  60. this._isExpanded = option.isLeaf ? false : option.expanded || false;
  61. this._isHalfChecked = false;
  62. this._isSelected = (!option.disabled && option.selected) || false;
  63. this._isLoading = false;
  64. this.isMatched = false;
  65. /**
  66. * parent's checked status will affect children while initializing
  67. */
  68. if (parent) {
  69. this.level = parent.level + 1;
  70. }
  71. else {
  72. this.level = 0;
  73. }
  74. const s = this.treeService;
  75. /**
  76. * post process of current treeNode
  77. */
  78. s?.treeNodePostProcessor?.(this);
  79. /**
  80. * instantiate children tree nodes
  81. */
  82. if (typeof option.children !== 'undefined' && option.children !== null) {
  83. option.children.forEach(nodeOptions => {
  84. if (s &&
  85. !s.isCheckStrictly &&
  86. option.checked &&
  87. !option.disabled &&
  88. !nodeOptions.disabled &&
  89. !nodeOptions.disableCheckbox) {
  90. nodeOptions.checked = option.checked;
  91. }
  92. this._children.push(new NzTreeNode(nodeOptions, this));
  93. });
  94. }
  95. }
  96. /**
  97. * auto generate
  98. * get
  99. * set
  100. */
  101. get title() {
  102. return this._title;
  103. }
  104. set title(value) {
  105. this._title = value;
  106. this.update();
  107. }
  108. get icon() {
  109. return this._icon;
  110. }
  111. set icon(value) {
  112. this._icon = value;
  113. this.update();
  114. }
  115. get children() {
  116. return this._children;
  117. }
  118. set children(value) {
  119. this._children = value;
  120. this.update();
  121. }
  122. get isLeaf() {
  123. return this._isLeaf;
  124. }
  125. set isLeaf(value) {
  126. this._isLeaf = value;
  127. this.update();
  128. }
  129. get isChecked() {
  130. return this._isChecked;
  131. }
  132. set isChecked(value) {
  133. this._isChecked = value;
  134. this.origin.checked = value;
  135. this.afterValueChange('isChecked');
  136. }
  137. get isHalfChecked() {
  138. return this._isHalfChecked;
  139. }
  140. set isHalfChecked(value) {
  141. this._isHalfChecked = value;
  142. this.afterValueChange('isHalfChecked');
  143. }
  144. get isSelectable() {
  145. return this._isSelectable;
  146. }
  147. set isSelectable(value) {
  148. this._isSelectable = value;
  149. this.update();
  150. }
  151. get isDisabled() {
  152. return this._isDisabled;
  153. }
  154. set isDisabled(value) {
  155. this._isDisabled = value;
  156. this.update();
  157. }
  158. get isDisableCheckbox() {
  159. return this._isDisableCheckbox;
  160. }
  161. set isDisableCheckbox(value) {
  162. this._isDisableCheckbox = value;
  163. this.update();
  164. }
  165. get isExpanded() {
  166. return this._isExpanded;
  167. }
  168. set isExpanded(value) {
  169. this._isExpanded = value;
  170. this.origin.expanded = value;
  171. this.afterValueChange('isExpanded');
  172. this.afterValueChange('reRender');
  173. }
  174. get isSelected() {
  175. return this._isSelected;
  176. }
  177. set isSelected(value) {
  178. this._isSelected = value;
  179. this.origin.selected = value;
  180. this.afterValueChange('isSelected');
  181. }
  182. get isLoading() {
  183. return this._isLoading;
  184. }
  185. set isLoading(value) {
  186. this._isLoading = value;
  187. this.update();
  188. }
  189. setSyncChecked(checked = false, halfChecked = false) {
  190. this.setChecked(checked, halfChecked);
  191. if (this.treeService && !this.treeService.isCheckStrictly) {
  192. this.treeService.conduct(this);
  193. }
  194. }
  195. setChecked(checked = false, halfChecked = false) {
  196. this.origin.checked = checked;
  197. this.isChecked = checked;
  198. this.isHalfChecked = halfChecked;
  199. }
  200. setExpanded(value) {
  201. this._isExpanded = value;
  202. this.origin.expanded = value;
  203. this.afterValueChange('isExpanded');
  204. }
  205. getParentNode() {
  206. return this.parentNode;
  207. }
  208. getChildren() {
  209. return this.children;
  210. }
  211. /**
  212. * Support appending child nodes by position. Leaf node cannot be appended.
  213. */
  214. addChildren(children, childPos = -1) {
  215. if (!this.isLeaf) {
  216. children.forEach(node => {
  217. const refreshLevel = (n) => {
  218. n.getChildren().forEach(c => {
  219. c.level = c.getParentNode().level + 1;
  220. // flush origin
  221. c.origin.level = c.level;
  222. refreshLevel(c);
  223. });
  224. };
  225. let child = node;
  226. if (child instanceof NzTreeNode) {
  227. child.parentNode = this;
  228. }
  229. else {
  230. child = new NzTreeNode(node, this);
  231. }
  232. child.level = this.level + 1;
  233. child.origin.level = child.level;
  234. refreshLevel(child);
  235. try {
  236. childPos === -1 ? this.children.push(child) : this.children.splice(childPos, 0, child);
  237. // flush origin
  238. }
  239. catch {
  240. // noop
  241. }
  242. });
  243. this.origin.children = this.getChildren().map(v => v.origin);
  244. // remove loading state
  245. this.isLoading = false;
  246. }
  247. this.afterValueChange('addChildren');
  248. this.afterValueChange('reRender');
  249. }
  250. clearChildren() {
  251. // refresh checked state
  252. this.afterValueChange('clearChildren');
  253. this.children = [];
  254. this.origin.children = [];
  255. this.afterValueChange('reRender');
  256. }
  257. remove() {
  258. const parentNode = this.getParentNode();
  259. if (parentNode) {
  260. parentNode.children = parentNode.getChildren().filter(v => v.key !== this.key);
  261. parentNode.origin.children = parentNode.origin.children.filter(v => v.key !== this.key);
  262. this.afterValueChange('remove');
  263. this.afterValueChange('reRender');
  264. }
  265. }
  266. afterValueChange(key) {
  267. if (this.treeService) {
  268. switch (key) {
  269. case 'isChecked':
  270. this.treeService.setCheckedNodeList(this);
  271. break;
  272. case 'isHalfChecked':
  273. this.treeService.setHalfCheckedNodeList(this);
  274. break;
  275. case 'isExpanded':
  276. this.treeService.setExpandedNodeList(this);
  277. break;
  278. case 'isSelected':
  279. this.treeService.setNodeActive(this);
  280. break;
  281. case 'clearChildren':
  282. this.treeService.afterRemove(this.getChildren());
  283. break;
  284. case 'remove':
  285. this.treeService.afterRemove([this]);
  286. break;
  287. case 'reRender':
  288. this.treeService.flattenTreeData(this.treeService.rootNodes, this.treeService.getExpandedNodeList().map(v => v.key));
  289. break;
  290. }
  291. }
  292. this.update();
  293. }
  294. update() {
  295. if (this.component) {
  296. this.component.markForCheck();
  297. }
  298. }
  299. }
  300. /**
  301. * Use of this source code is governed by an MIT-style license that can be
  302. * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE
  303. */
  304. /**
  305. * Use of this source code is governed by an MIT-style license that can be
  306. * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE
  307. */
  308. function isCheckDisabled(node) {
  309. const { isDisabled, isDisableCheckbox } = node;
  310. return !!(isDisabled || isDisableCheckbox);
  311. }
  312. function isInArray(needle, haystack) {
  313. return haystack.length > 0 && haystack.indexOf(needle) > -1;
  314. }
  315. function getPosition(level, index) {
  316. return `${level}-${index}`;
  317. }
  318. function getKey(key, pos) {
  319. if (key !== null && key !== undefined) {
  320. return key;
  321. }
  322. return pos;
  323. }
  324. /**
  325. * Flat nest tree data into flatten list. This is used for virtual list render.
  326. *
  327. * @param treeNodeList Origin data node list
  328. * @param expandedKeys
  329. * need expanded keys, provides `true` means all expanded (used in `rc-tree-select`).
  330. */
  331. function flattenTreeData(treeNodeList = [], expandedKeys = []) {
  332. const expandedKeySet = new Set(expandedKeys === true ? [] : expandedKeys);
  333. const flattenList = [];
  334. function dig(list, parent = null) {
  335. return list.map((treeNode, index) => {
  336. const pos = getPosition(parent ? parent.pos : '0', index);
  337. const mergedKey = getKey(treeNode.key, pos);
  338. treeNode.isStart = [...(parent ? parent.isStart : []), index === 0];
  339. treeNode.isEnd = [...(parent ? parent.isEnd : []), index === list.length - 1];
  340. // Add FlattenDataNode into list
  341. // TODO: only need data here.
  342. const flattenNode = {
  343. parent,
  344. pos,
  345. children: [],
  346. data: treeNode,
  347. isStart: [...(parent ? parent.isStart : []), index === 0],
  348. isEnd: [...(parent ? parent.isEnd : []), index === list.length - 1]
  349. };
  350. flattenList.push(flattenNode);
  351. // Loop treeNode children
  352. if (expandedKeys === true || expandedKeySet.has(mergedKey) || treeNode.isExpanded) {
  353. flattenNode.children = dig(treeNode.children || [], flattenNode);
  354. }
  355. else {
  356. flattenNode.children = [];
  357. }
  358. return flattenNode;
  359. });
  360. }
  361. dig(treeNodeList);
  362. return flattenList;
  363. }
  364. /**
  365. * Use of this source code is governed by an MIT-style license that can be
  366. * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE
  367. */
  368. class NzTreeBaseService {
  369. DRAG_SIDE_RANGE = 0.25;
  370. DRAG_MIN_GAP = 2;
  371. isCheckStrictly = false;
  372. isMultiple = false;
  373. selectedNode;
  374. rootNodes = [];
  375. flattenNodes$ = new BehaviorSubject([]);
  376. selectedNodeList = [];
  377. expandedNodeList = [];
  378. checkedNodeList = [];
  379. halfCheckedNodeList = [];
  380. matchedNodeList = [];
  381. /**
  382. * handle to post process a tree node when it's instantiating, note that its children haven't been initiated yet
  383. */
  384. treeNodePostProcessor;
  385. /**
  386. * reset tree nodes will clear default node list
  387. */
  388. initTree(nzNodes) {
  389. this.rootNodes = nzNodes;
  390. this.expandedNodeList = [];
  391. this.selectedNodeList = [];
  392. this.halfCheckedNodeList = [];
  393. this.checkedNodeList = [];
  394. this.matchedNodeList = [];
  395. }
  396. flattenTreeData(nzNodes, expandedKeys = []) {
  397. this.flattenNodes$.next(flattenTreeData(nzNodes, expandedKeys).map(item => item.data));
  398. }
  399. getSelectedNode() {
  400. return this.selectedNode;
  401. }
  402. /**
  403. * get some list
  404. */
  405. getSelectedNodeList() {
  406. return this.conductNodeState('select');
  407. }
  408. /**
  409. * get checked node keys
  410. */
  411. getCheckedNodeKeys() {
  412. const keys = [];
  413. const checkedNodes = this.getCheckedNodeList();
  414. const calc = (nodes) => {
  415. nodes.forEach(node => {
  416. keys.push(node.key);
  417. if (node.children.length < 1)
  418. return;
  419. calc(node.children);
  420. });
  421. };
  422. calc(checkedNodes);
  423. return keys;
  424. }
  425. /**
  426. * return checked nodes
  427. */
  428. getCheckedNodeList() {
  429. return this.conductNodeState('check');
  430. }
  431. getHalfCheckedNodeList() {
  432. return this.conductNodeState('halfCheck');
  433. }
  434. /**
  435. * return expanded nodes
  436. */
  437. getExpandedNodeList() {
  438. return this.conductNodeState('expand');
  439. }
  440. /**
  441. * return search matched nodes
  442. */
  443. getMatchedNodeList() {
  444. return this.conductNodeState('match');
  445. }
  446. isArrayOfNzTreeNode(value) {
  447. return value.every(item => item instanceof NzTreeNode);
  448. }
  449. /**
  450. * set drag node
  451. */
  452. setSelectedNode(node) {
  453. this.selectedNode = node;
  454. }
  455. /**
  456. * set node selected status
  457. */
  458. setNodeActive(node) {
  459. if (!this.isMultiple && node.isSelected) {
  460. this.selectedNodeList.forEach(n => {
  461. if (node.key !== n.key) {
  462. // reset other nodes
  463. n.isSelected = false;
  464. }
  465. });
  466. // single mode: remove pre node
  467. this.selectedNodeList = [];
  468. }
  469. this.setSelectedNodeList(node, this.isMultiple);
  470. }
  471. /**
  472. * add or remove node to selectedNodeList
  473. */
  474. setSelectedNodeList(node, isMultiple = false) {
  475. const index = this.getIndexOfArray(this.selectedNodeList, node.key);
  476. if (isMultiple) {
  477. if (node.isSelected && index === -1) {
  478. this.selectedNodeList.push(node);
  479. }
  480. }
  481. else {
  482. if (node.isSelected && index === -1) {
  483. this.selectedNodeList = [node];
  484. }
  485. }
  486. if (!node.isSelected) {
  487. this.selectedNodeList = this.selectedNodeList.filter(n => n.key !== node.key);
  488. }
  489. }
  490. /**
  491. * merge checked nodes
  492. */
  493. setHalfCheckedNodeList(node) {
  494. const index = this.getIndexOfArray(this.halfCheckedNodeList, node.key);
  495. if (node.isHalfChecked && index === -1) {
  496. this.halfCheckedNodeList.push(node);
  497. }
  498. else if (!node.isHalfChecked && index > -1) {
  499. this.halfCheckedNodeList = this.halfCheckedNodeList.filter(n => node.key !== n.key);
  500. }
  501. }
  502. setCheckedNodeList(node) {
  503. const index = this.getIndexOfArray(this.checkedNodeList, node.key);
  504. if (node.isChecked && index === -1) {
  505. this.checkedNodeList.push(node);
  506. }
  507. else if (!node.isChecked && index > -1) {
  508. this.checkedNodeList = this.checkedNodeList.filter(n => node.key !== n.key);
  509. }
  510. }
  511. /**
  512. * conduct checked/selected/expanded keys
  513. */
  514. conductNodeState(type = 'check') {
  515. let resultNodesList = [];
  516. switch (type) {
  517. case 'select':
  518. resultNodesList = this.selectedNodeList;
  519. break;
  520. case 'expand':
  521. resultNodesList = this.expandedNodeList;
  522. break;
  523. case 'match':
  524. resultNodesList = this.matchedNodeList;
  525. break;
  526. case 'check': {
  527. resultNodesList = this.checkedNodeList;
  528. const isIgnore = (node) => {
  529. const parentNode = node.getParentNode();
  530. if (parentNode) {
  531. if (this.checkedNodeList.findIndex(n => n.key === parentNode.key) > -1) {
  532. return true;
  533. }
  534. else {
  535. return isIgnore(parentNode);
  536. }
  537. }
  538. return false;
  539. };
  540. // merge checked
  541. if (!this.isCheckStrictly) {
  542. resultNodesList = this.checkedNodeList.filter(n => !isIgnore(n));
  543. }
  544. break;
  545. }
  546. case 'halfCheck':
  547. if (!this.isCheckStrictly) {
  548. resultNodesList = this.halfCheckedNodeList;
  549. }
  550. break;
  551. }
  552. return resultNodesList;
  553. }
  554. /**
  555. * set expanded nodes
  556. */
  557. setExpandedNodeList(node) {
  558. if (node.isLeaf) {
  559. return;
  560. }
  561. const index = this.getIndexOfArray(this.expandedNodeList, node.key);
  562. if (node.isExpanded && index === -1) {
  563. this.expandedNodeList.push(node);
  564. }
  565. else if (!node.isExpanded && index > -1) {
  566. this.expandedNodeList.splice(index, 1);
  567. }
  568. }
  569. setMatchedNodeList(node) {
  570. const index = this.getIndexOfArray(this.matchedNodeList, node.key);
  571. if (node.isMatched && index === -1) {
  572. this.matchedNodeList.push(node);
  573. }
  574. else if (!node.isMatched && index > -1) {
  575. this.matchedNodeList.splice(index, 1);
  576. }
  577. }
  578. /**
  579. * check state
  580. *
  581. * @param isCheckStrictly
  582. */
  583. refreshCheckState(isCheckStrictly = false) {
  584. if (isCheckStrictly) {
  585. return;
  586. }
  587. this.checkedNodeList.forEach(node => {
  588. this.conduct(node, isCheckStrictly);
  589. });
  590. }
  591. // reset other node checked state based current node
  592. conduct(node, isCheckStrictly = false) {
  593. const isChecked = node.isChecked;
  594. if (node && !isCheckStrictly) {
  595. this.conductUp(node);
  596. this.conductDown(node, isChecked);
  597. }
  598. }
  599. /**
  600. * 1、children half checked
  601. * 2、children all checked, parent checked
  602. * 3、no children checked
  603. */
  604. conductUp(node) {
  605. const parentNode = node.getParentNode();
  606. if (parentNode) {
  607. if (!isCheckDisabled(parentNode)) {
  608. if (parentNode.children.every(child => isCheckDisabled(child) || (!child.isHalfChecked && child.isChecked))) {
  609. parentNode.isChecked = true;
  610. parentNode.isHalfChecked = false;
  611. }
  612. else if (parentNode.children.some(child => child.isHalfChecked || child.isChecked)) {
  613. parentNode.isChecked = false;
  614. parentNode.isHalfChecked = true;
  615. }
  616. else {
  617. parentNode.isChecked = false;
  618. parentNode.isHalfChecked = false;
  619. }
  620. }
  621. this.setCheckedNodeList(parentNode);
  622. this.setHalfCheckedNodeList(parentNode);
  623. this.conductUp(parentNode);
  624. }
  625. }
  626. /**
  627. * reset child check state
  628. */
  629. conductDown(node, value) {
  630. if (!isCheckDisabled(node)) {
  631. node.isChecked = value;
  632. node.isHalfChecked = false;
  633. this.setCheckedNodeList(node);
  634. this.setHalfCheckedNodeList(node);
  635. node.children.forEach(n => {
  636. this.conductDown(n, value);
  637. });
  638. }
  639. }
  640. /**
  641. * flush after delete node
  642. */
  643. afterRemove(nodes) {
  644. // to reset selectedNodeList & expandedNodeList
  645. const loopNode = (node) => {
  646. // remove selected node
  647. this.selectedNodeList = this.selectedNodeList.filter(n => n.key !== node.key);
  648. // remove expanded node
  649. this.expandedNodeList = this.expandedNodeList.filter(n => n.key !== node.key);
  650. // remove checked node
  651. this.checkedNodeList = this.checkedNodeList.filter(n => n.key !== node.key);
  652. if (node.children) {
  653. node.children.forEach(child => {
  654. loopNode(child);
  655. });
  656. }
  657. };
  658. nodes.forEach(n => {
  659. loopNode(n);
  660. });
  661. this.refreshCheckState(this.isCheckStrictly);
  662. }
  663. /**
  664. * drag event
  665. */
  666. refreshDragNode(node) {
  667. if (node.children.length === 0) {
  668. // until root
  669. this.conductUp(node);
  670. }
  671. else {
  672. node.children.forEach(child => {
  673. this.refreshDragNode(child);
  674. });
  675. }
  676. }
  677. // reset node level
  678. resetNodeLevel(node) {
  679. const parentNode = node.getParentNode();
  680. if (parentNode) {
  681. node.level = parentNode.level + 1;
  682. }
  683. else {
  684. node.level = 0;
  685. }
  686. for (const child of node.children) {
  687. this.resetNodeLevel(child);
  688. }
  689. }
  690. calcDropPosition(event) {
  691. const { clientY } = event;
  692. // to fix firefox undefined
  693. const { top, bottom, height } = event.target.getBoundingClientRect();
  694. const des = Math.max(height * this.DRAG_SIDE_RANGE, this.DRAG_MIN_GAP);
  695. if (clientY <= top + des) {
  696. return -1;
  697. }
  698. else if (clientY >= bottom - des) {
  699. return 1;
  700. }
  701. return 0;
  702. }
  703. /**
  704. * drop
  705. * 0: inner -1: pre 1: next
  706. */
  707. dropAndApply(targetNode, dragPos = -1) {
  708. if (!targetNode || dragPos > 1) {
  709. return;
  710. }
  711. const treeService = targetNode.treeService;
  712. const targetParent = targetNode.getParentNode();
  713. const isSelectedRootNode = this.selectedNode.getParentNode();
  714. // remove the dragNode
  715. if (isSelectedRootNode) {
  716. isSelectedRootNode.children = isSelectedRootNode.children.filter(n => n.key !== this.selectedNode.key);
  717. }
  718. else {
  719. this.rootNodes = this.rootNodes.filter(n => n.key !== this.selectedNode.key);
  720. }
  721. switch (dragPos) {
  722. case 0:
  723. targetNode.addChildren([this.selectedNode]);
  724. this.resetNodeLevel(targetNode);
  725. break;
  726. case -1:
  727. case 1: {
  728. const tIndex = dragPos === 1 ? 1 : 0;
  729. if (targetParent) {
  730. targetParent.addChildren([this.selectedNode], targetParent.children.indexOf(targetNode) + tIndex);
  731. const parentNode = this.selectedNode.getParentNode();
  732. if (parentNode) {
  733. this.resetNodeLevel(parentNode);
  734. }
  735. }
  736. else {
  737. const targetIndex = this.rootNodes.indexOf(targetNode) + tIndex;
  738. // Insert root node.
  739. this.rootNodes.splice(targetIndex, 0, this.selectedNode);
  740. this.rootNodes[targetIndex].parentNode = null;
  741. this.resetNodeLevel(this.rootNodes[targetIndex]);
  742. }
  743. break;
  744. }
  745. }
  746. // flush all nodes
  747. this.rootNodes.forEach(child => {
  748. if (!child.treeService) {
  749. child.service = treeService;
  750. }
  751. this.refreshDragNode(child);
  752. });
  753. }
  754. /**
  755. * emit Structure
  756. * eventName
  757. * node
  758. * event: MouseEvent / DragEvent
  759. * dragNode
  760. */
  761. formatEvent(eventName, node, event) {
  762. const emitStructure = {
  763. eventName,
  764. node,
  765. event
  766. };
  767. switch (eventName) {
  768. case 'dragstart':
  769. case 'dragenter':
  770. case 'dragover':
  771. case 'dragleave':
  772. case 'drop':
  773. case 'dragend':
  774. Object.assign(emitStructure, { dragNode: this.getSelectedNode() });
  775. break;
  776. case 'click':
  777. case 'dblclick':
  778. Object.assign(emitStructure, { selectedKeys: this.selectedNodeList });
  779. Object.assign(emitStructure, { nodes: this.selectedNodeList });
  780. Object.assign(emitStructure, { keys: this.selectedNodeList.map(n => n.key) });
  781. break;
  782. case 'check': {
  783. const checkedNodeList = this.getCheckedNodeList();
  784. Object.assign(emitStructure, { checkedKeys: checkedNodeList });
  785. Object.assign(emitStructure, { nodes: checkedNodeList });
  786. Object.assign(emitStructure, { keys: checkedNodeList.map(n => n.key) });
  787. break;
  788. }
  789. case 'search':
  790. Object.assign(emitStructure, { matchedKeys: this.getMatchedNodeList() });
  791. Object.assign(emitStructure, { nodes: this.getMatchedNodeList() });
  792. Object.assign(emitStructure, { keys: this.getMatchedNodeList().map(n => n.key) });
  793. break;
  794. case 'expand':
  795. Object.assign(emitStructure, { nodes: this.expandedNodeList });
  796. Object.assign(emitStructure, { keys: this.expandedNodeList.map(n => n.key) });
  797. break;
  798. }
  799. return emitStructure;
  800. }
  801. /**
  802. * New functions for flatten nodes
  803. */
  804. getIndexOfArray(list, key) {
  805. return list.findIndex(v => v.key === key);
  806. }
  807. /**
  808. * Render by nzCheckedKeys
  809. * When keys equals null, just render with checkStrictly
  810. *
  811. * @param keys
  812. * @param checkStrictly
  813. */
  814. conductCheck(keys, checkStrictly) {
  815. this.checkedNodeList = [];
  816. this.halfCheckedNodeList = [];
  817. const calc = (nodes) => {
  818. nodes.forEach(node => {
  819. if (keys === null) {
  820. // render tree if no default checked keys found
  821. node.isChecked = !!node.origin.checked;
  822. }
  823. else {
  824. if (isInArray(node.key, keys || [])) {
  825. node.isChecked = true;
  826. node.isHalfChecked = false;
  827. }
  828. else {
  829. node.isChecked = false;
  830. node.isHalfChecked = false;
  831. }
  832. }
  833. if (node.children.length > 0) {
  834. calc(node.children);
  835. }
  836. });
  837. };
  838. calc(this.rootNodes);
  839. this.refreshCheckState(checkStrictly);
  840. }
  841. conductExpandedKeys(keys = []) {
  842. const expandedKeySet = new Set(keys === true ? [] : keys);
  843. this.expandedNodeList = [];
  844. const calc = (nodes) => {
  845. nodes.forEach(node => {
  846. node.setExpanded(keys === true || expandedKeySet.has(node.key) || node.isExpanded === true);
  847. if (node.isExpanded) {
  848. this.setExpandedNodeList(node);
  849. }
  850. if (node.children.length > 0) {
  851. calc(node.children);
  852. }
  853. });
  854. };
  855. calc(this.rootNodes);
  856. }
  857. conductSelectedKeys(keys, isMulti) {
  858. this.selectedNodeList.forEach(node => (node.isSelected = false));
  859. this.selectedNodeList = [];
  860. const calc = (nodes) => nodes.every(node => {
  861. if (isInArray(node.key, keys)) {
  862. node.isSelected = true;
  863. this.setSelectedNodeList(node);
  864. if (!isMulti) {
  865. // if not support multi select
  866. return false;
  867. }
  868. }
  869. else {
  870. node.isSelected = false;
  871. }
  872. if (node.children.length > 0) {
  873. // Recursion
  874. return calc(node.children);
  875. }
  876. return true;
  877. });
  878. calc(this.rootNodes);
  879. }
  880. /**
  881. * Expand parent nodes by child node
  882. *
  883. * @param node
  884. */
  885. expandNodeAllParentBySearch(node) {
  886. const calc = (n) => {
  887. if (n) {
  888. n.canHide = false;
  889. n.setExpanded(true);
  890. this.setExpandedNodeList(n);
  891. if (n.getParentNode()) {
  892. return calc(n.getParentNode());
  893. }
  894. }
  895. };
  896. calc(node.getParentNode());
  897. }
  898. static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: NzTreeBaseService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
  899. static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: NzTreeBaseService });
  900. }
  901. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: NzTreeBaseService, decorators: [{
  902. type: Injectable
  903. }] });
  904. /**
  905. * Use of this source code is governed by an MIT-style license that can be
  906. * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE
  907. */
  908. const NzTreeHigherOrderServiceToken = new InjectionToken('NzTreeHigherOrder');
  909. /**
  910. * Use of this source code is governed by an MIT-style license that can be
  911. * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE
  912. */
  913. class NzTreeBase {
  914. nzTreeService;
  915. constructor(nzTreeService) {
  916. this.nzTreeService = nzTreeService;
  917. }
  918. /**
  919. * Coerces a value({@link any[]}) to a TreeNodes({@link NzTreeNode[]})
  920. */
  921. coerceTreeNodes(value) {
  922. let nodes = [];
  923. if (!this.nzTreeService.isArrayOfNzTreeNode(value)) {
  924. // has not been new NzTreeNode
  925. nodes = value.map(item => new NzTreeNode(item, null, this.nzTreeService));
  926. }
  927. else {
  928. nodes = value.map((item) => {
  929. item.service = this.nzTreeService;
  930. return item;
  931. });
  932. }
  933. return nodes;
  934. }
  935. /**
  936. * Get all nodes({@link NzTreeNode})
  937. */
  938. getTreeNodes() {
  939. return this.nzTreeService.rootNodes;
  940. }
  941. /**
  942. * Get {@link NzTreeNode} with key
  943. */
  944. getTreeNodeByKey(key) {
  945. // flat tree nodes
  946. const nodes = [];
  947. const getNode = (node) => {
  948. nodes.push(node);
  949. node.getChildren().forEach(n => {
  950. getNode(n);
  951. });
  952. };
  953. this.getTreeNodes().forEach(n => {
  954. getNode(n);
  955. });
  956. return nodes.find(n => n.key === key) || null;
  957. }
  958. /**
  959. * Get checked nodes(merged)
  960. */
  961. getCheckedNodeList() {
  962. return this.nzTreeService.getCheckedNodeList();
  963. }
  964. /**
  965. * Get selected nodes
  966. */
  967. getSelectedNodeList() {
  968. return this.nzTreeService.getSelectedNodeList();
  969. }
  970. /**
  971. * Get half checked nodes
  972. */
  973. getHalfCheckedNodeList() {
  974. return this.nzTreeService.getHalfCheckedNodeList();
  975. }
  976. /**
  977. * Get expanded nodes
  978. */
  979. getExpandedNodeList() {
  980. return this.nzTreeService.getExpandedNodeList();
  981. }
  982. /**
  983. * Get matched nodes(if nzSearchValue is not null)
  984. */
  985. getMatchedNodeList() {
  986. return this.nzTreeService.getMatchedNodeList();
  987. }
  988. }
  989. /**
  990. * Use of this source code is governed by an MIT-style license that can be
  991. * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE
  992. */
  993. /**
  994. * Generated bundle index. Do not edit.
  995. */
  996. export { NzTreeBase, NzTreeBaseService, NzTreeHigherOrderServiceToken, NzTreeNode, flattenTreeData, getKey, getPosition, isCheckDisabled, isInArray };
  997. //# sourceMappingURL=ng-zorro-antd-core-tree.mjs.map