/* * Copyright (C) 2022 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import '../icon/LitIcon'; import { BaseElement, element } from '../BaseElement'; import { type LitIcon } from '../icon/LitIcon'; import { type TreeItemData } from './LitTree'; import {LitTreeNodeHtmlStyle} from "./LitTreeNode.html"; @element('lit-tree-node') export class LitTreeNode extends BaseElement { private arrowElement: HTMLSpanElement | null | undefined; private itemElement: HTMLDivElement | null | undefined; private checkboxElement: HTMLInputElement | null | undefined; private iconElement: LitIcon | null | undefined; private _data: TreeItemData | null | undefined; static get observedAttributes(): string[] { return [ 'icon-name', 'icon-size', 'color', 'path', 'title', 'arrow', 'checkable', 'selected', 'checked', 'missing', 'multiple', 'top-depth', ]; } get checkable(): string { return this.getAttribute('checkable') || 'false'; } set data(value: TreeItemData | null | undefined) { this._data = value; } get data(): TreeItemData | null | undefined { return this._data; } set checkable(value) { if (value === 'true') { this.setAttribute('checkable', 'true'); } else { this.setAttribute('checkable', 'false'); } } set multiple(value: boolean) { if (value) { this.setAttribute('multiple', ''); } else { this.removeAttribute('multiple'); } } get multiple(): boolean { return this.hasAttribute('multiple'); } get iconName(): string { return this.getAttribute('icon-name') || ''; } set iconName(value) { this.setAttribute('icon-name', value); } get topDepth(): boolean { return this.hasAttribute('top-depth'); } set topDepth(value) { if (value) { this.setAttribute('top-depth', ''); } else { this.removeAttribute('top-depth'); } } get arrow(): boolean { return this.hasAttribute('arrow'); } set arrow(value) { if (value) { this.setAttribute('arrow', 'true'); } else { this.removeAttribute('arrow'); } } get open(): string { return this.getAttribute('open') || 'true'; } set open(value) { this.setAttribute('open', value); } get selected(): boolean { return this.hasAttribute('selected'); } set selected(value) { if (value) { this.setAttribute('selected', ''); } else { this.removeAttribute('selected'); } } get checked(): boolean { return this.hasAttribute('checked'); } set checked(value) { if (value === null || !value) { this.removeAttribute('checked'); } else { this.setAttribute('checked', ''); } } initElements(): void { this.arrowElement = this.shadowRoot!.querySelector('#arrow'); this.iconElement = this.shadowRoot!.querySelector('#icon'); this.itemElement = this.shadowRoot!.querySelector('#item'); this.checkboxElement = this.shadowRoot!.querySelector('#checkbox'); this.arrowElement!.onclick = (e): void => { e.stopPropagation(); this.autoExpand(); }; this.itemElement!.onclick = (e): void => { e.stopPropagation(); if (this._data && this._data.disable === true) { return; } this.onChange(!this.data?.checked); }; } onChange(checked: boolean): void { this.checked = checked; this.data!.checked = checked; this.checkHandler(); this.dispatchEvent(new CustomEvent('change', { detail: checked })); } initHtml(): string { return ` ${LitTreeNodeHtmlStyle}
${this.title}
`; } //当 custom element首次被插入文档DOM时,被调用。 connectedCallback(): void { if (this.hasAttribute('checked')) { this.checkboxElement!.checked = true; } this.checkHandler(); } checkHandler(): void { if (this.checked) { this.removeAttribute('missing'); } if (this.hasAttribute('multiple')) { if (this.nextElementSibling) { if (this.checked) { this.nextElementSibling.querySelectorAll('lit-tree-node').forEach((a: any) => { a.checked = true; a.removeAttribute('missing'); }); } else { this.nextElementSibling.querySelectorAll('lit-tree-node').forEach((a: any) => (a.checked = false)); } } let setCheckStatus = (element: any): void => { if ( element.parentElement.parentElement.previousElementSibling && element.parentElement.parentElement.previousElementSibling.tagName === 'LIT-TREE-NODE' ) { let allChecked = Array.from(element.parentElement.parentElement.querySelectorAll('lit-tree-node')).every( (item: any) => item.checked ); let someChecked = Array.from(element.parentElement.parentElement.querySelectorAll('lit-tree-node')).some( (item: any, index, array) => item.checked ); if (allChecked === true) { element.parentElement.parentElement.previousElementSibling.checked = true; element.parentElement.parentElement.previousElementSibling.removeAttribute('missing'); } else if (someChecked) { element.parentElement.parentElement.previousElementSibling.setAttribute('missing', ''); element.parentElement.parentElement.previousElementSibling.removeAttribute('checked'); } else { element.parentElement.parentElement.previousElementSibling.removeAttribute('missing'); element.parentElement.parentElement.previousElementSibling.removeAttribute('checked'); } setCheckStatus(element.parentElement.parentElement.previousElementSibling); } }; setCheckStatus(this); } } expand(): void { if (this.open === 'true') { return; } let uul = this.parentElement!.querySelector('ul'); this.expandSection(uul); this.arrowElement!.style.transform = 'translateX(-50%) rotateZ(0deg)'; } collapse(): void { if (this.open === 'false') { return; } let uul = this.parentElement!.querySelector('ul'); this.collapseSection(uul); this.arrowElement!.style.transform = 'translateX(-50%) rotateZ(-90deg)'; } autoExpand(): void { let uul = this.parentElement!.querySelector('ul'); if (this.open === 'true') { this.collapseSection(uul); this.arrowElement!.style.transform = 'translateX(-50%) rotateZ(-90deg)'; } else { this.expandSection(uul); this.arrowElement!.style.transform = 'translateX(-50%) rotateZ(0deg)'; } } //收起 collapseSection(element: any): void { if (!element) { return; } let sectionHeight = element.scrollHeight; let elementTransition = element.style.transition; element.style.transition = ''; requestAnimationFrame(function () { element.style.height = sectionHeight + 'px'; element.style.transition = elementTransition; requestAnimationFrame(function () { element.style.height = 0 + 'px'; }); }); this.open = 'false'; } //展开 expandSection(element: any): void { if (!element) { return; } let sectionHeight = element.scrollHeight; element.style.height = sectionHeight + 'px'; element.ontransitionend = (e: any): void => { element.ontransitionend = null; element.style.height = null; this.open = 'true'; }; } //当 custom element从文档DOM中删除时,被调用。 disconnectedCallback(): void {} //当 custom element被移动到新的文档时,被调用。 adoptedCallback(): void {} //当 custom element增加、删除、修改自身属性时,被调用。 attributeChangedCallback(name: string, oldValue: any, newValue: any): void { if (name === 'title') { this.shadowRoot!.querySelector('#title')!.textContent = newValue; } else if (name === 'icon-name') { if (this.iconElement) { if (newValue !== null && newValue !== '' && newValue !== 'null') { this.iconElement!.setAttribute('name', newValue); this.iconElement!.style.display = 'flex'; } else { this.iconElement!.style.display = 'none'; } } } else if (name === 'checkable') { if (this.checkboxElement) { if (newValue === 'true' && this._data!.disable !== true) { this.checkboxElement!.style.display = 'inline-block'; } else { this.checkboxElement!.style.display = 'none'; } } } else if (name === 'checked') { if (this.checkboxElement) { this.checkboxElement.checked = this.hasAttribute('checked'); } } } //在node top top-right bottom bottom-right 画线条 drawLine(direction: string /*string[top|bottom|top-right|bottom-right]*/): void { let item = this.shadowRoot!.querySelector('#item'); if (!item) { return; } item.removeAttribute('line-top'); item.removeAttribute('line-top-right'); item.removeAttribute('line-bottom'); item.removeAttribute('line-bottom-right'); switch (direction) { case 'top': item.setAttribute('line-top', ''); break; case 'bottom': item.setAttribute('line-bottom', ''); break; case 'top-right': item.setAttribute('line-top-right', ''); break; case 'bottom-right': item.setAttribute('line-bottom-right', ''); break; } } } if (!customElements.get('lit-tree-node')) { customElements.define('lit-tree-node', LitTreeNode); }