From e4dcc1e0e7aef87d70db2258ab81cf4bf8755632 Mon Sep 17 00:00:00 2001 From: Benni Mack <benni@typo3.org> Date: Fri, 12 Mar 2021 17:13:08 +0100 Subject: [PATCH] [TASK] Use Lit-based template for SVG tree wrapper The SVG tree is now building the SVG elements and needed containers ("<g>") via lit-helper. In addition, the update() method is renamed to this.updateVisibleNodes() to easier integrate this as Lit element, as update() is a reserved protected method in lit. The initialize() method is much cleaner, as the event listener registration is now separated in a custom method. Resolves: #93724 Releases: master Change-Id: I945cd620f9900c6ea535dfe5f0d44ee5ced46f89 Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/68367 Tested-by: Richard Haeser <richard@richardhaeser.com> Tested-by: TYPO3com <noreply@typo3.com> Tested-by: core-ci <typo3@b13.com> Tested-by: Daniel Gorges <daniel.gorges@b13.com> Tested-by: Benni Mack <benni@typo3.org> Reviewed-by: Richard Haeser <richard@richardhaeser.com> Reviewed-by: Daniel Gorges <daniel.gorges@b13.com> Reviewed-by: Benni Mack <benni@typo3.org> --- .../FormEngine/Element/SelectTree.ts | 66 ++++-- .../FormEngine/Element/SelectTreeElement.ts | 2 +- .../Public/TypeScript/PageTree/PageTree.ts | 6 +- .../TypeScript/PageTree/PageTreeDragDrop.ts | 4 +- .../TypeScript/PageTree/PageTreeElement.ts | 8 +- .../Resources/Public/TypeScript/SvgTree.ts | 213 ++++++++---------- .../Public/TypeScript/Tree/DragDrop.ts | 2 +- .../Public/TypeScript/Tree/FileStorageTree.ts | 16 +- .../TypeScript/Tree/FileStorageTreeActions.ts | 2 +- .../Tree/FileStorageTreeContainer.ts | 6 +- .../FormEngine/Element/SelectTree.js | 2 +- .../FormEngine/Element/SelectTreeElement.js | 2 +- .../Public/JavaScript/PageTree/PageTree.js | 2 +- .../JavaScript/PageTree/PageTreeDragDrop.js | 2 +- .../JavaScript/PageTree/PageTreeElement.js | 8 +- .../Resources/Public/JavaScript/SvgTree.js | 14 +- .../Public/JavaScript/Tree/DragDrop.js | 2 +- .../Public/JavaScript/Tree/FileStorageTree.js | 2 +- .../JavaScript/Tree/FileStorageTreeActions.js | 2 +- .../Tree/FileStorageTreeContainer.js | 6 +- 20 files changed, 175 insertions(+), 192 deletions(-) diff --git a/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/FormEngine/Element/SelectTree.ts b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/FormEngine/Element/SelectTree.ts index 4f82dacd682f..e8998b2a04da 100644 --- a/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/FormEngine/Element/SelectTree.ts +++ b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/FormEngine/Element/SelectTree.ts @@ -56,6 +56,24 @@ export class SelectTree extends SvgTree this.dispatch.on('prepareLoadedNode.selectTree', (node: TreeNode) => this.prepareLoadedNode(node)); } + /** + * Expand all nodes and refresh view + */ + public expandAll(): void { + this.nodes.forEach((node: TreeNode) => { this.showChildren(node); }); + this.prepareDataForVisibleNodes(); + this.updateVisibleNodes(); + } + + /** + * Collapse all nodes recursively and refresh view + */ + public collapseAll(): void { + this.nodes.forEach((node: TreeNode) => { this.hideChildren(node); }); + this.prepareDataForVisibleNodes(); + this.updateVisibleNodes(); + } + /** * Node selection logic (triggered by different events) */ @@ -76,30 +94,7 @@ export class SelectTree extends SvgTree node.checked = !checked; this.dispatch.call('nodeSelectedAfter', this, node); - this.update(); - } - - /** - * Function relays on node.indeterminate state being up to date - * - * @param {Selection} nodes - */ - public updateNodes(nodes: TreeNodeSelection): void { - nodes - .selectAll('.tree-check use') - .attr('visibility', function(this: SVGUseElement, node: TreeNode): string { - const checked = Boolean(node.checked); - const selection = d3selection.select(this); - if (selection.classed('icon-checked') && checked) { - return 'visible'; - } else if (selection.classed('icon-indeterminate') && node.indeterminate && !checked) { - return 'visible'; - } else if (selection.classed('icon-check') && !node.indeterminate && !checked) { - return 'visible'; - } else { - return 'hidden'; - } - }); + this.updateVisibleNodes(); } public filter(searchTerm?: string|null): void { @@ -121,7 +116,7 @@ export class SelectTree extends SvgTree }); this.prepareDataForVisibleNodes(); - this.update(); + this.updateVisibleNodes(); } /** @@ -147,6 +142,27 @@ export class SelectTree extends SvgTree return !this.settings.readOnlyMode && this.settings.unselectableElements.indexOf(node.identifier) === -1; } + /** + * Function relays on node.indeterminate state being up to date + */ + private updateNodes(nodes: TreeNodeSelection): void { + nodes + .selectAll('.tree-check use') + .attr('visibility', function(this: SVGUseElement, node: TreeNode): string { + const checked = Boolean(node.checked); + const selection = d3selection.select(this); + if (selection.classed('icon-checked') && checked) { + return 'visible'; + } else if (selection.classed('icon-indeterminate') && node.indeterminate && !checked) { + return 'visible'; + } else if (selection.classed('icon-check') && !node.indeterminate && !checked) { + return 'visible'; + } else { + return 'hidden'; + } + }); + } + /** * Check if a node has all information to be used. */ diff --git a/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/FormEngine/Element/SelectTreeElement.ts b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/FormEngine/Element/SelectTreeElement.ts index 6b367a8ee1b4..387b5f7efcdc 100644 --- a/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/FormEngine/Element/SelectTreeElement.ts +++ b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/FormEngine/Element/SelectTreeElement.ts @@ -171,6 +171,6 @@ class TreeToolbar extends LitElement { this.tree.nodes.forEach((node: any) => node.hidden = false); } this.tree.prepareDataForVisibleNodes(); - this.tree.update(); + this.tree.updateVisibleNodes(); } } diff --git a/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/PageTree/PageTree.ts b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/PageTree/PageTree.ts index fbdf484ec48d..87f67a5ebfa7 100644 --- a/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/PageTree/PageTree.ts +++ b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/PageTree/PageTree.ts @@ -104,7 +104,7 @@ export class PageTree extends SvgTree if (response && response.hasErrors) { this.errorNotification(response.messages, false); this.nodesContainer.selectAll('.node').remove(); - this.update(); + this.updateVisibleNodes(); this.nodesRemovePlaceholder(); } else { this.refreshOrFilterTree(); @@ -179,7 +179,7 @@ export class PageTree extends SvgTree this.disableSelectedNodes(); node.checked = true; this.dispatch.call('nodeSelectedAfter', this, node); - this.update(); + this.updateVisibleNodes(); } /** @@ -239,7 +239,7 @@ export class PageTree extends SvgTree parentNode.loaded = true; this.setParametersNode(); this.prepareDataForVisibleNodes(); - this.update(); + this.updateVisibleNodes(); this.nodesRemovePlaceholder(); this.switchFocusNode(parentNode); diff --git a/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/PageTree/PageTreeDragDrop.ts b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/PageTree/PageTreeDragDrop.ts index 5f9e8a2d1aef..7f029a797e1f 100644 --- a/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/PageTree/PageTreeDragDrop.ts +++ b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/PageTree/PageTreeDragDrop.ts @@ -238,7 +238,7 @@ export class ToolbarDragHandler implements DragDropHandler { this.tree.nodes.splice(index, 0, newNode); this.tree.setParametersNode(); this.tree.prepareDataForVisibleNodes(); - this.tree.update(); + this.tree.updateVisibleNodes(); this.tree.removeEditedText(); d3selection.select(this.tree.svg.node().parentNode as HTMLElement) @@ -295,7 +295,7 @@ export class ToolbarDragHandler implements DragDropHandler { this.tree.nodes.splice(index, 1); this.tree.setParametersNode(); this.tree.prepareDataForVisibleNodes(); - this.tree.update(); + this.tree.updateVisibleNodes(); this.tree.removeEditedText(); }; } diff --git a/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/PageTree/PageTreeElement.ts b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/PageTree/PageTreeElement.ts index 272779c19f48..395d060e77a7 100644 --- a/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/PageTree/PageTreeElement.ts +++ b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/PageTree/PageTreeElement.ts @@ -77,11 +77,7 @@ export class PageTreeNavigationComponent extends LitElement { </div> <div id="typo3-pagetree-treeContainer" class="navigation-tree-container"> ${this.renderMountPoint()} - <div id="typo3-pagetree-tree" class="svg-tree-wrapper"> - <div class="node-loader"> - <typo3-backend-icon identifier="spinner-circle-light" size="small"></typo3-backend-icon> - </div> - </div> + <div id="typo3-pagetree-tree" class="svg-tree-wrapper"></div> </div> </div> <div class="svg-tree-loader"> @@ -162,7 +158,7 @@ export class PageTreeNavigationComponent extends LitElement { .then((response) => { if (response && response.hasErrors) { this.tree.errorNotification(response.message, true); - this.tree.update(); + this.tree.updateVisibleNodes(); } else { this.mountPointPath = response.mountPointPath; this.tree.refreshOrFilterTree(); diff --git a/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/SvgTree.ts b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/SvgTree.ts index e77a618da1b8..33d0c5c7a756 100644 --- a/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/SvgTree.ts +++ b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/SvgTree.ts @@ -11,6 +11,8 @@ * The TYPO3 project - inspiring people to share! */ +import {html, TemplateResult} from 'lit-element'; +import {renderNodes} from 'TYPO3/CMS/Core/lit-helper'; import {TreeNode} from './Tree/TreeNode'; import * as d3selection from 'd3-selection'; import * as d3dispatch from 'd3-dispatch'; @@ -96,6 +98,7 @@ export class SvgTree { width: 300, duration: 400, dataUrl: '', + filterUrl: '', defaultProperties: {}, expandUpToLevel: null as any, }; @@ -117,8 +120,8 @@ export class SvgTree { protected linksContainer: TreeWrapperSelection<SVGGElement> = null; protected data: SvgTreeData = new class implements SvgTreeData { - links: SvgTreeDataLink[]; - nodes: TreeNode[]; + links: SvgTreeDataLink[] = []; + nodes: TreeNode[] = []; }; /** @@ -156,73 +159,21 @@ export class SvgTree { * @param {Object} settings */ public initialize(selector: HTMLElement, settings: any): void { - Object.assign(this.settings, settings); this.wrapper = selector; - /** - * Create element: - * - * <svg version="1.1" width="100%"> - * <g class="nodes-wrapper"> - * <g class="nodes-bg"><rect class="node-bg"></rect></g> - * <g class="links"><path class="link"></path></g> - * <g class="nodes"><g class="node"></g></g> - * </g> - * </svg> - */ - this.svg = d3selection.select(this.wrapper).append('svg') - .attr('version', '1.1') - .attr('width', '100%') - .on('mouseover', () => this.isOverSvg = true) - .on('mouseout', () => this.isOverSvg = false) - .on('keydown', (evt: KeyboardEvent) => this.handleKeyboardInteraction(evt)); + Object.assign(this.settings, settings); - this.container = this.svg - .append('g') - .attr('class', 'nodes-wrapper') - .attr('transform', 'translate(' + (this.settings.indentWidth / 2) + ',' + (this.settings.nodeHeight / 2) + ')'); - this.nodesBgContainer = this.container.append('g') - .attr('class', 'nodes-bg'); - this.linksContainer = this.container.append('g') - .attr('class', 'links'); - this.nodesContainer = this.container.append('g') - .attr('class', 'nodes') - .attr('role', 'tree'); - if (this.settings.showIcons) { - this.iconsContainer = this.svg.append('defs'); - } + this.wrapper.append(...renderNodes(this.getTemplate())); + this.svg = d3selection.select(this.wrapper).select('svg'); + this.container = this.svg.select('.nodes-wrapper') as TreeWrapperSelection<SVGGElement>; + this.nodesBgContainer = this.container.select('.nodes-bg') as TreeWrapperSelection<SVGGElement>; + this.linksContainer = this.container.select('.links') as TreeWrapperSelection<SVGGElement>; + this.nodesContainer = this.container.select('.nodes') as TreeWrapperSelection<SVGGElement>; + this.iconsContainer = this.svg.select('defs') as TreeWrapperSelection<SVGGElement>; this.updateScrollPosition(); this.loadData(); - - this.wrapper.addEventListener('resize', () => { - this.updateScrollPosition(); - this.update(); - }); - - this.wrapper.addEventListener('scroll', () => { - this.updateScrollPosition(); - this.update(); - }); - - this.wrapper.addEventListener('svg-tree:visible', () => { - this.updateScrollPosition(); - this.update(); - }); - + this.addEventListeners(); this.wrapper.dispatchEvent(new Event('svg-tree:initialized')); - this.resize(); - } - - /** - * Update svg tree after changed window height - */ - public resize() { - window.addEventListener('resize', () => { - if (this.wrapper.getClientRects().length > 0) { - this.updateScrollPosition(); - this.update(); - } - }); } /** @@ -245,7 +196,7 @@ export class SvgTree { /** * Make the DOM element of the node given as parameter focusable and focus it */ - public switchFocusNode(node: TreeNode) { + public switchFocusNode(node: TreeNode): void { this.switchFocus(this.getNodeElement(node)); } @@ -253,18 +204,7 @@ export class SvgTree { * Return the DOM element of a tree node */ public getNodeElement(node: TreeNode): HTMLElement|null { - return document.getElementById('identifier-' + this.getNodeStateIdentifier(node)); - } - - /** - * Updates variables used for visible nodes calculation - */ - public updateScrollPosition() { - this.viewportHeight = this.wrapper.getBoundingClientRect().height; - this.scrollTop = this.wrapper.scrollTop; - this.scrollBottom = this.scrollTop + this.viewportHeight + (this.viewportHeight / 2); - // disable tooltips when scrolling - Tooltip.hide(this.wrapper.querySelectorAll('[data-bs-toggle=tooltip]')); + return this.wrapper.querySelector('#identifier-' + this.getNodeStateIdentifier(node)); } /** @@ -272,7 +212,6 @@ export class SvgTree { */ public loadData() { this.nodesAddPlaceholder(); - (new AjaxRequest(this.settings.dataUrl)) .get({cache: 'no-cache'}) .then((response: AjaxResponse) => response.resolve()) @@ -282,7 +221,7 @@ export class SvgTree { this.nodesRemovePlaceholder(); // @todo: needed? this.updateScrollPosition(); - this.update(); + this.updateVisibleNodes(); }) .catch((error) => { this.errorNotification(error, false); @@ -301,7 +240,7 @@ export class SvgTree { this.nodesContainer.selectAll('.node').remove(); this.nodesBgContainer.selectAll('.node-bg').remove(); this.linksContainer.selectAll('.link').remove(); - this.update(); + this.updateVisibleNodes(); } /** @@ -350,11 +289,11 @@ export class SvgTree { } public nodesRemovePlaceholder() { - const componentWrapper = this.svg.node().closest('.svg-tree'); - const nodeLoader = componentWrapper?.querySelector('.node-loader') as HTMLElement; + const nodeLoader = this.wrapper.querySelector('.node-loader') as HTMLElement; if (nodeLoader) { nodeLoader.style.display = 'none'; } + const componentWrapper = this.wrapper.closest('.svg-tree'); const treeLoader = componentWrapper?.querySelector('.svg-tree-loader') as HTMLElement; if (treeLoader) { treeLoader.style.display = 'none'; @@ -362,14 +301,14 @@ export class SvgTree { } public nodesAddPlaceholder(node: TreeNode = null) { - const componentWrapper = this.svg.node().closest('.svg-tree'); if (node) { - const nodeLoader = componentWrapper?.querySelector('.node-loader') as HTMLElement; + const nodeLoader = this.wrapper.querySelector('.node-loader') as HTMLElement; if (nodeLoader) { nodeLoader.style.top = '' + (node.y + this.settings.marginTop); nodeLoader.style.display = 'block'; } } else { + const componentWrapper = this.wrapper.closest('.svg-tree'); const treeLoader = componentWrapper?.querySelector('.svg-tree-loader') as HTMLElement; if (treeLoader) { treeLoader.style.display = 'block'; @@ -430,30 +369,12 @@ export class SvgTree { } } - /** - * Expand all nodes and refresh view - */ - public expandAll(): void { - this.nodes.forEach(this.showChildren.bind(this)); - this.prepareDataForVisibleNodes(); - this.update(); - } - - /** - * Collapse all nodes recursively and refresh view - */ - public collapseAll(): void { - this.nodes.forEach(this.hideChildren.bind(this)); - this.prepareDataForVisibleNodes(); - this.update(); - } - /** * Filters out invisible nodes (collapsed) from the full dataset (this.rootNode) * and enriches dataset with additional properties * Visible dataset is stored in this.data */ - public prepareDataForVisibleNodes() { + public prepareDataForVisibleNodes(): void { const blacklist: {[keys: string]: boolean} = {}; this.nodes.forEach((node: TreeNode, index: number): void => { if (!node.expanded) { @@ -471,7 +392,6 @@ export class SvgTree { this.data.nodes.forEach((node: TreeNode, i: number) => { // delete n.children; node.x = node.depth * this.settings.indentWidth; - if (node.readableRootline) { pathAboveMounts += this.settings.nodeHeight; } @@ -516,7 +436,7 @@ export class SvgTree { this.icons[iconName].icon = result[0]; } if (update) { - this.update(); + this.updateVisibleNodes(); } }); } @@ -525,7 +445,7 @@ export class SvgTree { /** * Renders the subset of the tree nodes fitting the viewport (adding, modifying and removing SVG nodes) */ - public update() { + public updateVisibleNodes(): void { const visibleRows = Math.ceil(this.viewportHeight / this.settings.nodeHeight + 1); const position = Math.floor(Math.max(this.scrollTop - (this.settings.nodeHeight * 2), 0) / this.settings.nodeHeight); @@ -656,7 +576,7 @@ export class SvgTree { this.searchTerm = searchTerm; } this.nodesAddPlaceholder(); - if (this.searchTerm) { + if (this.searchTerm && this.settings.filterUrl) { (new AjaxRequest(this.settings.filterUrl + '&q=' + this.searchTerm)) .get({cache: 'no-cache'}) .then((response: AjaxResponse) => response.resolve()) @@ -703,7 +623,7 @@ export class SvgTree { this.refreshTree(); } this.prepareDataForVisibleNodes(); - this.update(); + this.updateVisibleNodes(); } /** @@ -727,6 +647,56 @@ export class SvgTree { } } + /** + * Create element: + * + * <svg version="1.1" width="100%"> + * <g class="nodes-wrapper"> + * <g class="nodes-bg"><rect class="node-bg"></rect></g> + * <g class="links"><path class="link"></path></g> + * <g class="nodes"><g class="node"></g></g> + * </g> + * </svg> + */ + protected getTemplate(): TemplateResult { + return html` + <div class="node-loader"> + <typo3-backend-icon identifier="spinner-circle-light" size="small"></typo3-backend-icon> + </div> + <svg version="1.1" width="100%"> + <g class="nodes-wrapper" transform="translate(${this.settings.indentWidth / 2},${this.settings.nodeHeight / 2})"> + <g class="nodes-bg"></g> + <g class="links"></g> + <g class="nodes" role="tree"></g> + </g> + <defs></defs> + </svg> + `; + } + + /** + * Add an event listener Update svg tree after changed window height + */ + protected addEventListeners() { + this.wrapper.addEventListener('resize', () => this.updateView()); + this.wrapper.addEventListener('scroll', () => this.updateView()); + this.wrapper.addEventListener('svg-tree:visible', () => this.updateView()); + window.addEventListener('resize', () => { + if (this.wrapper.getClientRects().length > 0) { + this.updateView(); + } + }); + const svgElement = this.wrapper.querySelector('svg') as SVGElement; + svgElement.addEventListener('mouseover', () => this.isOverSvg = true) + svgElement.addEventListener('mouseout', () => this.isOverSvg = false) + svgElement.addEventListener('keydown', (evt: KeyboardEvent) => this.handleKeyboardInteraction(evt)); + } + + protected updateView(): void { + this.updateScrollPosition(); + this.updateVisibleNodes(); + } + protected disableSelectedNodes(): void { // Disable already selected nodes this.getSelectedNodes().forEach((node: TreeNode) => { @@ -950,9 +920,19 @@ export class SvgTree { } else { this.showChildren(node); } - this.prepareDataForVisibleNodes(); - this.update(); + this.updateVisibleNodes(); + } + + /** + * Updates variables used for visible nodes calculation + */ + private updateScrollPosition(): void { + this.viewportHeight = this.wrapper.getBoundingClientRect().height; + this.scrollTop = this.wrapper.scrollTop; + this.scrollBottom = this.scrollTop + this.viewportHeight + (this.viewportHeight / 2); + // disable tooltips when scrolling + Tooltip.hide(this.wrapper.querySelectorAll('[data-bs-toggle=tooltip]')); } /** @@ -1013,14 +993,15 @@ export class SvgTree { // scroll to end, select last node this.scrollTop = this.wrapper.lastElementChild.getBoundingClientRect().height + this.settings.nodeHeight - this.viewportHeight; parentDomNode.scrollIntoView({behavior: 'smooth', block: 'end'}); - this.update(); + this.updateVisibleNodes(); this.switchFocus(parentDomNode.lastElementChild as SVGElement); break; case KeyTypes.HOME: // scroll to top, select first node this.scrollTop = this.nodes[0].y; this.wrapper.scrollTo({'top': this.scrollTop, 'behavior': 'smooth'}); - this.update(); + this.prepareDataForVisibleNodes(); + this.updateVisibleNodes(); this.switchFocus(parentDomNode.firstElementChild as SVGElement); break; case KeyTypes.LEFT: @@ -1029,7 +1010,7 @@ export class SvgTree { if (currentNode.hasChildren) { this.hideChildren(currentNode); this.prepareDataForVisibleNodes(); - this.update(); + this.updateVisibleNodes(); } } else if (currentNode.parents.length > 0) { // go to parent node @@ -1053,7 +1034,7 @@ export class SvgTree { // expand currentNode this.showChildren(currentNode); this.prepareDataForVisibleNodes(); - this.update(); + this.updateVisibleNodes(); this.switchFocus(evtTarget as SVGElement); } //do nothing if node has no children @@ -1086,7 +1067,7 @@ export class SvgTree { return; } this.wrapper.scrollTo({'top': this.scrollTop, 'behavior': 'smooth'}); - this.update(); + this.updateVisibleNodes(); } /** @@ -1103,9 +1084,7 @@ export class SvgTree { link.source.owns.push('identifier-' + link.target.stateIdentifier); return link; }); - const links = this.linksContainer - .selectAll('.link') - .data(visibleLinks); + const links = this.linksContainer.selectAll('.link').data(visibleLinks); // delete links.exit().remove(); // create diff --git a/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/Tree/DragDrop.ts b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/Tree/DragDrop.ts index 09a96f770f87..7a20a7419cac 100644 --- a/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/Tree/DragDrop.ts +++ b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/Tree/DragDrop.ts @@ -126,7 +126,7 @@ export class DragDrop { if (this.tree.hoveredNode) { this.tree.showChildren(this.tree.hoveredNode); this.tree.prepareDataForVisibleNodes(); - this.tree.update(); + this.tree.updateVisibleNodes(); } }, 1000); } diff --git a/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/Tree/FileStorageTree.ts b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/Tree/FileStorageTree.ts index 16270ef76b20..8923af879185 100644 --- a/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/Tree/FileStorageTree.ts +++ b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/Tree/FileStorageTree.ts @@ -80,18 +80,10 @@ export class FileStorageTree extends SvgTree { if (!this.isNodeSelectable(node)) { return; } - - // Disable already selected nodes - this.getSelectedNodes().forEach((node: TreeNode) => { - if (node.checked === true) { - node.checked = false; - this.dispatch.call('nodeSelectedAfter', this, node); - } - }); - + this.disableSelectedNodes(); node.checked = true; this.dispatch.call('nodeSelectedAfter', this, node); - this.update(); + this.updateVisibleNodes(); } public selectNodeByIdentifier(identifier: string): void { @@ -119,7 +111,7 @@ export class FileStorageTree extends SvgTree { private loadChildrenOfNode(parentNode: TreeNode): void { if (parentNode.loaded) { this.prepareDataForVisibleNodes(); - this.update(); + this.updateVisibleNodes(); return; } this.nodesAddPlaceholder(); @@ -137,7 +129,7 @@ export class FileStorageTree extends SvgTree { parentNode.loaded = true; this.setParametersNode(); this.prepareDataForVisibleNodes(); - this.update(); + this.updateVisibleNodes(); this.nodesRemovePlaceholder(); this.switchFocusNode(parentNode); }) diff --git a/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/Tree/FileStorageTreeActions.ts b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/Tree/FileStorageTreeActions.ts index 790b2134892d..d519dd725aae 100644 --- a/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/Tree/FileStorageTreeActions.ts +++ b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/Tree/FileStorageTreeActions.ts @@ -276,7 +276,7 @@ export class FileStorageTreeNodeDragHandler implements DragDropHandler { if (response && response.hasErrors) { this.tree.errorNotification(response.messages, false); this.tree.nodesContainer.selectAll('.node').remove(); - this.tree.update(); + this.tree.updateVisibleNodes(); this.tree.nodesRemovePlaceholder(); } else { if (response.messages) { diff --git a/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/Tree/FileStorageTreeContainer.ts b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/Tree/FileStorageTreeContainer.ts index 5c74a8d36d02..5c7ae44b5547 100644 --- a/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/Tree/FileStorageTreeContainer.ts +++ b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/Tree/FileStorageTreeContainer.ts @@ -62,11 +62,7 @@ export class FileStorageTreeNavigationComponent extends LitElement { <div> <typo3-backend-navigation-component-filestoragetree-toolbar .tree="${this.tree}" id="filestoragetree-toolbar" class="svg-toolbar"></typo3-backend-navigation-component-filestoragetree-toolbar> <div class="navigation-tree-container"> - <div id="typo3-filestoragetree-tree" class="svg-tree-wrapper"> - <div class="node-loader"> - <typo3-backend-icon identifier="spinner-circle-light" size="small"></typo3-backend-icon> - </div> - </div> + <div id="typo3-filestoragetree-tree" class="svg-tree-wrapper"></div> </div> </div> <div class="svg-tree-loader"> diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/SelectTree.js b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/SelectTree.js index 2c6c7132b6f1..4ee6c568d08c 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/SelectTree.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/SelectTree.js @@ -10,4 +10,4 @@ * * The TYPO3 project - inspiring people to share! */ -var __createBinding=this&&this.__createBinding||(Object.create?function(e,t,i,s){void 0===s&&(s=i),Object.defineProperty(e,s,{enumerable:!0,get:function(){return t[i]}})}:function(e,t,i,s){void 0===s&&(s=i),e[s]=t[i]}),__setModuleDefault=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),__importStar=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var i in e)"default"!==i&&Object.prototype.hasOwnProperty.call(e,i)&&__createBinding(t,e,i);return __setModuleDefault(t,e),t};define(["require","exports","d3-selection","../../SvgTree","TYPO3/CMS/Backend/FormEngineValidation"],(function(e,t,i,s,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.SelectTree=void 0,i=__importStar(i);class d extends s.SvgTree{constructor(){super(),this.settings={unselectableElements:[],exclusiveNodesIdentifiers:"",validation:{},readOnlyMode:!1,showIcons:!0,marginTop:15,nodeHeight:20,indentWidth:16,width:300,duration:400,dataUrl:"",defaultProperties:{},expandUpToLevel:null},this.exclusiveSelectedNode=null,this.addIcons(),this.dispatch.on("updateNodes.selectTree",e=>this.updateNodes(e)),this.dispatch.on("loadDataAfter.selectTree",()=>this.loadDataAfter()),this.dispatch.on("updateSvg.selectTree",e=>this.renderCheckbox(e)),this.dispatch.on("nodeSelectedAfter.selectTree",e=>this.nodeSelectedAfter(e)),this.dispatch.on("prepareLoadedNode.selectTree",e=>this.prepareLoadedNode(e))}selectNode(e){if(!this.isNodeSelectable(e))return;const t=e.checked;this.handleExclusiveNodeSelection(e),this.settings.validation&&this.settings.validation.maxItems&&!t&&this.getSelectedNodes().length>=this.settings.validation.maxItems||(e.checked=!t,this.dispatch.call("nodeSelectedAfter",this,e),this.update())}updateNodes(e){e.selectAll(".tree-check use").attr("visibility",(function(e){const t=Boolean(e.checked),s=i.select(this);return s.classed("icon-checked")&&t||s.classed("icon-indeterminate")&&e.indeterminate&&!t?"visible":!s.classed("icon-check")||e.indeterminate||t?"hidden":"visible"}))}filter(e){this.searchTerm=e,this.nodes.length&&(this.nodes[0].expanded=!1);const t=new RegExp(e,"i");this.nodes.forEach(e=>{t.test(e.name)?(this.showParents(e),e.expanded=!0,e.hidden=!1):(e.hidden=!0,e.expanded=!1)}),this.prepareDataForVisibleNodes(),this.update()}showParents(e){if(0===e.parents.length)return;const t=this.nodes[e.parents[0]];t.hidden=!1,t.expanded=!0,this.showParents(t)}isNodeSelectable(e){return!this.settings.readOnlyMode&&-1===this.settings.unselectableElements.indexOf(e.identifier)}prepareLoadedNode(e){if(!e.stateIdentifier){const t=e.parents.length?e.parents[e.parents.length-1]:e.identifier;e.stateIdentifier=t+"_"+e.identifier}!1===e.selectable&&this.settings.unselectableElements.push(e.identifier)}renderCheckbox(e){this.textPosition=50;const t=e.filter(e=>this.isNodeSelectable(e)||Boolean(e.checked)).append("g").attr("class","tree-check").on("click",(e,t)=>this.selectNode(t));t.append("use").attr("x",28).attr("y",-8).attr("visibility","hidden").attr("class","icon-check").attr("xlink:href","#icon-check"),t.append("use").attr("x",28).attr("y",-8).attr("visibility","hidden").attr("class","icon-checked").attr("xlink:href","#icon-checked"),t.append("use").attr("x",28).attr("y",-8).attr("visibility","hidden").attr("class","icon-indeterminate").attr("xlink:href","#icon-indeterminate")}updateAncestorsIndeterminateState(e){let t=!1;e.parents.forEach(e=>{const i=this.nodes[e];i.indeterminate=i.checked||i.indeterminate||t,t=i.checked||i.indeterminate||i.checked||i.indeterminate})}loadDataAfter(){this.nodes=this.nodes.map(e=>(e.indeterminate=!1,e)),this.calculateIndeterminate(this.nodes),this.saveCheckboxes(),n.validateField(this.settings.input)}calculateIndeterminate(e){e.forEach(t=>{(t.checked||t.indeterminate)&&t.parents&&t.parents.length>0&&t.parents.forEach(t=>{e[t].indeterminate=!0})})}nodeSelectedAfter(e){this.updateAncestorsIndeterminateState(e),this.calculateIndeterminate(this.nodes),this.saveCheckboxes()}saveCheckboxes(){void 0!==this.settings.input&&(this.settings.input.value=this.getSelectedNodes().map(e=>e.identifier))}handleExclusiveNodeSelection(e){const t=this.settings.exclusiveNodesIdentifiers.split(",");this.settings.exclusiveNodesIdentifiers.length&&!1===e.checked&&(t.indexOf(""+e.identifier)>-1?(this.disableSelectedNodes(),this.exclusiveSelectedNode=e):-1===t.indexOf(""+e.identifier)&&this.exclusiveSelectedNode&&(this.exclusiveSelectedNode.checked=!1,this.dispatch.call("nodeSelectedAfter",this,this.exclusiveSelectedNode),this.exclusiveSelectedNode=null))}addIcons(){this.icons={check:{identifier:"check",icon:'<g width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><rect height="16" width="16" fill="transparent"></rect><path transform="scale(0.01)" d="M1312 256h-832q-66 0-113 47t-47 113v832q0 66 47 113t113 47h832q66 0 113-47t47-113v-832q0-66-47-113t-113-47zm288 160v832q0 119-84.5 203.5t-203.5 84.5h-832q-119 0-203.5-84.5t-84.5-203.5v-832q0-119 84.5-203.5t203.5-84.5h832q119 0 203.5 84.5t84.5 203.5z"></path></g>'},checked:{identifier:"checked",icon:'<g width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><rect height="16" width="16" fill="transparent"></rect><path transform="scale(0.01)" d="M813 1299l614-614q19-19 19-45t-19-45l-102-102q-19-19-45-19t-45 19l-467 467-211-211q-19-19-45-19t-45 19l-102 102q-19 19-19 45t19 45l358 358q19 19 45 19t45-19zm851-883v960q0 119-84.5 203.5t-203.5 84.5h-960q-119 0-203.5-84.5t-84.5-203.5v-960q0-119 84.5-203.5t203.5-84.5h960q119 0 203.5 84.5t84.5 203.5z"></path></g>'},indeterminate:{identifier:"indeterminate",icon:'<g width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><rect height="16" width="16" fill="transparent"></rect><path transform="scale(0.01)" d="M1344 800v64q0 14-9 23t-23 9h-832q-14 0-23-9t-9-23v-64q0-14 9-23t23-9h832q14 0 23 9t9 23zm128 448v-832q0-66-47-113t-113-47h-832q-66 0-113 47t-47 113v832q0 66 47 113t113 47h832q66 0 113-47t47-113zm128-832v832q0 119-84.5 203.5t-203.5 84.5h-832q-119 0-203.5-84.5t-84.5-203.5v-832q0-119 84.5-203.5t203.5-84.5h832q119 0 203.5 84.5t84.5 203.5z"></path></g>'}}}}t.SelectTree=d})); \ No newline at end of file +var __createBinding=this&&this.__createBinding||(Object.create?function(e,t,i,s){void 0===s&&(s=i),Object.defineProperty(e,s,{enumerable:!0,get:function(){return t[i]}})}:function(e,t,i,s){void 0===s&&(s=i),e[s]=t[i]}),__setModuleDefault=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),__importStar=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var i in e)"default"!==i&&Object.prototype.hasOwnProperty.call(e,i)&&__createBinding(t,e,i);return __setModuleDefault(t,e),t};define(["require","exports","d3-selection","../../SvgTree","TYPO3/CMS/Backend/FormEngineValidation"],(function(e,t,i,s,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.SelectTree=void 0,i=__importStar(i);class d extends s.SvgTree{constructor(){super(),this.settings={unselectableElements:[],exclusiveNodesIdentifiers:"",validation:{},readOnlyMode:!1,showIcons:!0,marginTop:15,nodeHeight:20,indentWidth:16,width:300,duration:400,dataUrl:"",defaultProperties:{},expandUpToLevel:null},this.exclusiveSelectedNode=null,this.addIcons(),this.dispatch.on("updateNodes.selectTree",e=>this.updateNodes(e)),this.dispatch.on("loadDataAfter.selectTree",()=>this.loadDataAfter()),this.dispatch.on("updateSvg.selectTree",e=>this.renderCheckbox(e)),this.dispatch.on("nodeSelectedAfter.selectTree",e=>this.nodeSelectedAfter(e)),this.dispatch.on("prepareLoadedNode.selectTree",e=>this.prepareLoadedNode(e))}expandAll(){this.nodes.forEach(e=>{this.showChildren(e)}),this.prepareDataForVisibleNodes(),this.updateVisibleNodes()}collapseAll(){this.nodes.forEach(e=>{this.hideChildren(e)}),this.prepareDataForVisibleNodes(),this.updateVisibleNodes()}selectNode(e){if(!this.isNodeSelectable(e))return;const t=e.checked;this.handleExclusiveNodeSelection(e),this.settings.validation&&this.settings.validation.maxItems&&!t&&this.getSelectedNodes().length>=this.settings.validation.maxItems||(e.checked=!t,this.dispatch.call("nodeSelectedAfter",this,e),this.updateVisibleNodes())}filter(e){this.searchTerm=e,this.nodes.length&&(this.nodes[0].expanded=!1);const t=new RegExp(e,"i");this.nodes.forEach(e=>{t.test(e.name)?(this.showParents(e),e.expanded=!0,e.hidden=!1):(e.hidden=!0,e.expanded=!1)}),this.prepareDataForVisibleNodes(),this.updateVisibleNodes()}showParents(e){if(0===e.parents.length)return;const t=this.nodes[e.parents[0]];t.hidden=!1,t.expanded=!0,this.showParents(t)}isNodeSelectable(e){return!this.settings.readOnlyMode&&-1===this.settings.unselectableElements.indexOf(e.identifier)}updateNodes(e){e.selectAll(".tree-check use").attr("visibility",(function(e){const t=Boolean(e.checked),s=i.select(this);return s.classed("icon-checked")&&t||s.classed("icon-indeterminate")&&e.indeterminate&&!t?"visible":!s.classed("icon-check")||e.indeterminate||t?"hidden":"visible"}))}prepareLoadedNode(e){if(!e.stateIdentifier){const t=e.parents.length?e.parents[e.parents.length-1]:e.identifier;e.stateIdentifier=t+"_"+e.identifier}!1===e.selectable&&this.settings.unselectableElements.push(e.identifier)}renderCheckbox(e){this.textPosition=50;const t=e.filter(e=>this.isNodeSelectable(e)||Boolean(e.checked)).append("g").attr("class","tree-check").on("click",(e,t)=>this.selectNode(t));t.append("use").attr("x",28).attr("y",-8).attr("visibility","hidden").attr("class","icon-check").attr("xlink:href","#icon-check"),t.append("use").attr("x",28).attr("y",-8).attr("visibility","hidden").attr("class","icon-checked").attr("xlink:href","#icon-checked"),t.append("use").attr("x",28).attr("y",-8).attr("visibility","hidden").attr("class","icon-indeterminate").attr("xlink:href","#icon-indeterminate")}updateAncestorsIndeterminateState(e){let t=!1;e.parents.forEach(e=>{const i=this.nodes[e];i.indeterminate=i.checked||i.indeterminate||t,t=i.checked||i.indeterminate||i.checked||i.indeterminate})}loadDataAfter(){this.nodes=this.nodes.map(e=>(e.indeterminate=!1,e)),this.calculateIndeterminate(this.nodes),this.saveCheckboxes(),n.validateField(this.settings.input)}calculateIndeterminate(e){e.forEach(t=>{(t.checked||t.indeterminate)&&t.parents&&t.parents.length>0&&t.parents.forEach(t=>{e[t].indeterminate=!0})})}nodeSelectedAfter(e){this.updateAncestorsIndeterminateState(e),this.calculateIndeterminate(this.nodes),this.saveCheckboxes()}saveCheckboxes(){void 0!==this.settings.input&&(this.settings.input.value=this.getSelectedNodes().map(e=>e.identifier))}handleExclusiveNodeSelection(e){const t=this.settings.exclusiveNodesIdentifiers.split(",");this.settings.exclusiveNodesIdentifiers.length&&!1===e.checked&&(t.indexOf(""+e.identifier)>-1?(this.disableSelectedNodes(),this.exclusiveSelectedNode=e):-1===t.indexOf(""+e.identifier)&&this.exclusiveSelectedNode&&(this.exclusiveSelectedNode.checked=!1,this.dispatch.call("nodeSelectedAfter",this,this.exclusiveSelectedNode),this.exclusiveSelectedNode=null))}addIcons(){this.icons={check:{identifier:"check",icon:'<g width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><rect height="16" width="16" fill="transparent"></rect><path transform="scale(0.01)" d="M1312 256h-832q-66 0-113 47t-47 113v832q0 66 47 113t113 47h832q66 0 113-47t47-113v-832q0-66-47-113t-113-47zm288 160v832q0 119-84.5 203.5t-203.5 84.5h-832q-119 0-203.5-84.5t-84.5-203.5v-832q0-119 84.5-203.5t203.5-84.5h832q119 0 203.5 84.5t84.5 203.5z"></path></g>'},checked:{identifier:"checked",icon:'<g width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><rect height="16" width="16" fill="transparent"></rect><path transform="scale(0.01)" d="M813 1299l614-614q19-19 19-45t-19-45l-102-102q-19-19-45-19t-45 19l-467 467-211-211q-19-19-45-19t-45 19l-102 102q-19 19-19 45t19 45l358 358q19 19 45 19t45-19zm851-883v960q0 119-84.5 203.5t-203.5 84.5h-960q-119 0-203.5-84.5t-84.5-203.5v-960q0-119 84.5-203.5t203.5-84.5h960q119 0 203.5 84.5t84.5 203.5z"></path></g>'},indeterminate:{identifier:"indeterminate",icon:'<g width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><rect height="16" width="16" fill="transparent"></rect><path transform="scale(0.01)" d="M1344 800v64q0 14-9 23t-23 9h-832q-14 0-23-9t-9-23v-64q0-14 9-23t23-9h832q14 0 23 9t9 23zm128 448v-832q0-66-47-113t-113-47h-832q-66 0-113 47t-47 113v832q0 66 47 113t113 47h832q66 0 113-47t47-113zm128-832v832q0 119-84.5 203.5t-203.5 84.5h-832q-119 0-203.5-84.5t-84.5-203.5v-832q0-119 84.5-203.5t203.5-84.5h832q119 0 203.5 84.5t84.5 203.5z"></path></g>'}}}}t.SelectTree=d})); \ No newline at end of file diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/SelectTreeElement.js b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/SelectTreeElement.js index 0da2bdd9186a..a2e7d6c970c8 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/SelectTreeElement.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/SelectTreeElement.js @@ -30,4 +30,4 @@ var __decorate=this&&this.__decorate||function(e,t,r,i){var l,a=arguments.length </button> </div> </div> - `}collapseAll(){this.tree.collapseAll()}expandAll(){this.tree.expandAll()}filter(e){const t=e.target;this.tree.filter(t.value.trim())}toggleHideUnchecked(){this.hideUncheckedState=!this.hideUncheckedState,this.hideUncheckedState?this.tree.nodes.forEach(e=>{e.checked?(this.tree.showParents(e),e.expanded=!0,e.hidden=!1):(e.hidden=!0,e.expanded=!1)}):this.tree.nodes.forEach(e=>e.hidden=!1),this.tree.prepareDataForVisibleNodes(),this.tree.update()}};n=__decorate([l.customElement("typo3-backend-form-selecttree-toolbar")],n)})); \ No newline at end of file + `}collapseAll(){this.tree.collapseAll()}expandAll(){this.tree.expandAll()}filter(e){const t=e.target;this.tree.filter(t.value.trim())}toggleHideUnchecked(){this.hideUncheckedState=!this.hideUncheckedState,this.hideUncheckedState?this.tree.nodes.forEach(e=>{e.checked?(this.tree.showParents(e),e.expanded=!0,e.hidden=!1):(e.hidden=!0,e.expanded=!1)}):this.tree.nodes.forEach(e=>e.hidden=!1),this.tree.prepareDataForVisibleNodes(),this.tree.updateVisibleNodes()}};n=__decorate([l.customElement("typo3-backend-form-selecttree-toolbar")],n)})); \ No newline at end of file diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/PageTree/PageTree.js b/typo3/sysext/backend/Resources/Public/JavaScript/PageTree/PageTree.js index ca650dac3ec3..d9839d0b8b6a 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/PageTree/PageTree.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/PageTree/PageTree.js @@ -10,4 +10,4 @@ * * The TYPO3 project - inspiring people to share! */ -var __createBinding=this&&this.__createBinding||(Object.create?function(e,t,i,o){void 0===o&&(o=i),Object.defineProperty(e,o,{enumerable:!0,get:function(){return t[i]}})}:function(e,t,i,o){void 0===o&&(o=i),e[o]=t[i]}),__setModuleDefault=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),__importStar=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var i in e)"default"!==i&&Object.prototype.hasOwnProperty.call(e,i)&&__createBinding(t,e,i);return __setModuleDefault(t,e),t},__importDefault=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};define(["require","exports","d3-selection","TYPO3/CMS/Core/Ajax/AjaxRequest","../SvgTree","./PageTreeDragDrop","../ContextMenu","../Storage/Persistent","../Enum/KeyTypes"],(function(e,t,i,o,d,s,r,n,a){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.PageTree=void 0,i=__importStar(i),o=__importDefault(o),n=__importDefault(n);class l extends d.SvgTree{constructor(){super(),this.networkErrorTitle=TYPO3.lang.pagetree_networkErrorTitle,this.networkErrorMessage=TYPO3.lang.pagetree_networkErrorDesc,this.settings.defaultProperties={hasChildren:!1,nameSourceField:"title",itemType:"pages",prefix:"",suffix:"",locked:!1,loaded:!1,overlayIcon:"",selectable:!0,expanded:!1,checked:!1,backgroundColor:"",stopPageTree:!1,class:"",readableRootline:"",isMountPoint:!1},this.dispatch.on("nodeSelectedAfter.pageTree",e=>this.nodeSelectedAfter(e)),this.dispatch.on("nodeRightClick.pageTree",e=>this.nodeRightClick(e)),this.dispatch.on("prepareLoadedNode.pageTree",e=>this.prepareLoadedNode(e))}initialize(e,t,i){super.initialize(e,t),this.dragDrop=i}sendChangeCommand(e){let t="",i=0;e.target&&(i=e.target.identifier,"after"===e.position&&(i=-i)),"new"===e.command?t="&data[pages][NEW_1][pid]="+i+"&data[pages][NEW_1][title]="+encodeURIComponent(e.name)+"&data[pages][NEW_1][doktype]="+e.type:"edit"===e.command?t="&data[pages]["+e.uid+"]["+e.nameSourceField+"]="+encodeURIComponent(e.title):"delete"===e.command?(e.uid===window.fsMod.recentIds.web&&this.selectNode(this.nodes[0]),t="&cmd[pages]["+e.uid+"][delete]=1"):t="cmd[pages]["+e.uid+"]["+e.command+"]="+i,this.nodesAddPlaceholder(),new o.default(top.TYPO3.settings.ajaxUrls.record_process).post(t,{headers:{"Content-Type":"application/x-www-form-urlencoded","X-Requested-With":"XMLHttpRequest"}}).then(e=>e.resolve()).then(e=>{e&&e.hasErrors?(this.errorNotification(e.messages,!1),this.nodesContainer.selectAll(".node").remove(),this.update(),this.nodesRemovePlaceholder()):this.refreshOrFilterTree()}).catch(e=>{this.errorNotification(e)})}nodeRightClick(e){r.show(e.itemType,parseInt(e.identifier,10),"tree","","",this.getNodeElement(e))}prepareLoadedNode(e){e.stateIdentifier===top.window.fsMod.navFrameHighlightedID.web&&(e.checked=!0)}hideChildren(e){super.hideChildren(e),n.default.set("BackendComponents.States.Pagetree.stateHash."+e.stateIdentifier,"0")}showChildren(e){this.loadChildrenOfNode(e),super.showChildren(e),n.default.set("BackendComponents.States.Pagetree.stateHash."+e.stateIdentifier,"1")}updateNodeBgClass(e){return super.updateNodeBgClass.call(this,e).call(this.initializeDragForNode())}nodesUpdate(e){return(e=super.nodesUpdate.call(this,e).call(this.initializeDragForNode())).append("text").text("+").attr("class","node-stop").attr("dx",30).attr("dy",5).attr("visibility",e=>e.stopPageTree&&0!==e.depth?"visible":"hidden").on("click",(e,t)=>{document.dispatchEvent(new CustomEvent("typo3:pagetree:mountPoint",{detail:{pageId:parseInt(t.identifier,10)}}))}),e}selectNode(e){this.isNodeSelectable(e)&&(this.disableSelectedNodes(),e.checked=!0,this.dispatch.call("nodeSelectedAfter",this,e),this.update())}switchFocusNode(e){this.nodeIsEdit||this.switchFocus(this.getNodeElement(e))}initializeDragForNode(){return this.dragDrop.connectDragHandler(new s.PageTreeNodeDragHandler(this,this.dragDrop))}removeEditedText(){const e=i.selectAll(".node-edit");if(e.size())try{e.remove(),this.nodeIsEdit=!1}catch(e){}}loadChildrenOfNode(e){e.loaded||(this.nodesAddPlaceholder(),new o.default(this.settings.dataUrl+"&pid="+e.identifier+"&mount="+e.mountPoint+"&pidDepth="+e.depth).get({cache:"no-cache"}).then(e=>e.resolve()).then(t=>{let i=Array.isArray(t)?t:[];i.shift();const o=this.nodes.indexOf(e)+1;i.forEach((e,t)=>{this.nodes.splice(o+t,0,e)}),e.loaded=!0,this.setParametersNode(),this.prepareDataForVisibleNodes(),this.update(),this.nodesRemovePlaceholder(),this.switchFocusNode(e)}).catch(e=>{throw this.errorNotification(e,!1),this.nodesRemovePlaceholder(),e}))}nodeSelectedAfter(e){if(!e.checked)return;top.window.fsMod.recentIds.web=e.identifier,top.window.fsMod.currentBank=e.stateIdentifier.split("_")[0],top.window.fsMod.navFrameHighlightedID.web=e.stateIdentifier;let t="?";-1!==top.window.currentSubScript.indexOf("?")&&(t="&"),top.TYPO3.Backend.ContentContainer.setUrl(top.window.currentSubScript+t+"id="+e.identifier)}appendTextElement(e){let t=0;return super.appendTextElement(e).attr("dx",e=>{let t=this.textPosition;return e.stopPageTree&&0!==e.depth&&(t+=15),e.locked&&(t+=15),t}).on("click",(e,i)=>{"0"!==i.identifier?1==++t&&setTimeout(()=>{1===t?this.selectNode(i):this.editNodeLabel(i),t=0},300):this.selectNode(i)})}sendEditNodeLabelCommand(e){const t="&data[pages]["+e.identifier+"]["+e.nameSourceField+"]="+encodeURIComponent(e.newName);this.nodesAddPlaceholder(e),new o.default(top.TYPO3.settings.ajaxUrls.record_process).post(t,{headers:{"Content-Type":"application/x-www-form-urlencoded","X-Requested-With":"XMLHttpRequest"}}).then(e=>e.resolve()).then(t=>{t&&t.hasErrors?this.errorNotification(t.messages,!1):e.name=e.newName,this.refreshOrFilterTree()}).catch(e=>{this.errorNotification(e,!0)})}editNodeLabel(e){e.allowEdit&&(this.removeEditedText(),this.nodeIsEdit=!0,i.select(this.svg.node().parentNode).append("input").attr("class","node-edit").style("top",()=>e.y+this.settings.marginTop+"px").style("left",e.x+this.textPosition+5+"px").style("width",this.settings.width-(e.x+this.textPosition+20)+"px").style("height",this.settings.nodeHeight+"px").attr("type","text").attr("value",e.name).on("keydown",t=>{const i=t.keyCode;if(i===a.KeyTypesEnum.ENTER||i===a.KeyTypesEnum.TAB){const i=t.target.value.trim();this.nodeIsEdit=!1,this.removeEditedText(),i.length&&i!==e.name&&(e.nameSourceField=e.nameSourceField||"title",e.newName=i,this.sendEditNodeLabelCommand(e))}else i===a.KeyTypesEnum.ESCAPE&&(this.nodeIsEdit=!1,this.removeEditedText())}).on("blur",t=>{if(!this.nodeIsEdit)return;const i=t.target.value.trim();i.length&&i!==e.name&&(e.nameSourceField=e.nameSourceField||"title",e.newName=i,this.sendEditNodeLabelCommand(e)),this.removeEditedText()}).node().select())}}t.PageTree=l})); \ No newline at end of file +var __createBinding=this&&this.__createBinding||(Object.create?function(e,t,i,o){void 0===o&&(o=i),Object.defineProperty(e,o,{enumerable:!0,get:function(){return t[i]}})}:function(e,t,i,o){void 0===o&&(o=i),e[o]=t[i]}),__setModuleDefault=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),__importStar=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var i in e)"default"!==i&&Object.prototype.hasOwnProperty.call(e,i)&&__createBinding(t,e,i);return __setModuleDefault(t,e),t},__importDefault=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};define(["require","exports","d3-selection","TYPO3/CMS/Core/Ajax/AjaxRequest","../SvgTree","./PageTreeDragDrop","../ContextMenu","../Storage/Persistent","../Enum/KeyTypes"],(function(e,t,i,o,d,s,r,n,a){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.PageTree=void 0,i=__importStar(i),o=__importDefault(o),n=__importDefault(n);class l extends d.SvgTree{constructor(){super(),this.networkErrorTitle=TYPO3.lang.pagetree_networkErrorTitle,this.networkErrorMessage=TYPO3.lang.pagetree_networkErrorDesc,this.settings.defaultProperties={hasChildren:!1,nameSourceField:"title",itemType:"pages",prefix:"",suffix:"",locked:!1,loaded:!1,overlayIcon:"",selectable:!0,expanded:!1,checked:!1,backgroundColor:"",stopPageTree:!1,class:"",readableRootline:"",isMountPoint:!1},this.dispatch.on("nodeSelectedAfter.pageTree",e=>this.nodeSelectedAfter(e)),this.dispatch.on("nodeRightClick.pageTree",e=>this.nodeRightClick(e)),this.dispatch.on("prepareLoadedNode.pageTree",e=>this.prepareLoadedNode(e))}initialize(e,t,i){super.initialize(e,t),this.dragDrop=i}sendChangeCommand(e){let t="",i=0;e.target&&(i=e.target.identifier,"after"===e.position&&(i=-i)),"new"===e.command?t="&data[pages][NEW_1][pid]="+i+"&data[pages][NEW_1][title]="+encodeURIComponent(e.name)+"&data[pages][NEW_1][doktype]="+e.type:"edit"===e.command?t="&data[pages]["+e.uid+"]["+e.nameSourceField+"]="+encodeURIComponent(e.title):"delete"===e.command?(e.uid===window.fsMod.recentIds.web&&this.selectNode(this.nodes[0]),t="&cmd[pages]["+e.uid+"][delete]=1"):t="cmd[pages]["+e.uid+"]["+e.command+"]="+i,this.nodesAddPlaceholder(),new o.default(top.TYPO3.settings.ajaxUrls.record_process).post(t,{headers:{"Content-Type":"application/x-www-form-urlencoded","X-Requested-With":"XMLHttpRequest"}}).then(e=>e.resolve()).then(e=>{e&&e.hasErrors?(this.errorNotification(e.messages,!1),this.nodesContainer.selectAll(".node").remove(),this.updateVisibleNodes(),this.nodesRemovePlaceholder()):this.refreshOrFilterTree()}).catch(e=>{this.errorNotification(e)})}nodeRightClick(e){r.show(e.itemType,parseInt(e.identifier,10),"tree","","",this.getNodeElement(e))}prepareLoadedNode(e){e.stateIdentifier===top.window.fsMod.navFrameHighlightedID.web&&(e.checked=!0)}hideChildren(e){super.hideChildren(e),n.default.set("BackendComponents.States.Pagetree.stateHash."+e.stateIdentifier,"0")}showChildren(e){this.loadChildrenOfNode(e),super.showChildren(e),n.default.set("BackendComponents.States.Pagetree.stateHash."+e.stateIdentifier,"1")}updateNodeBgClass(e){return super.updateNodeBgClass.call(this,e).call(this.initializeDragForNode())}nodesUpdate(e){return(e=super.nodesUpdate.call(this,e).call(this.initializeDragForNode())).append("text").text("+").attr("class","node-stop").attr("dx",30).attr("dy",5).attr("visibility",e=>e.stopPageTree&&0!==e.depth?"visible":"hidden").on("click",(e,t)=>{document.dispatchEvent(new CustomEvent("typo3:pagetree:mountPoint",{detail:{pageId:parseInt(t.identifier,10)}}))}),e}selectNode(e){this.isNodeSelectable(e)&&(this.disableSelectedNodes(),e.checked=!0,this.dispatch.call("nodeSelectedAfter",this,e),this.updateVisibleNodes())}switchFocusNode(e){this.nodeIsEdit||this.switchFocus(this.getNodeElement(e))}initializeDragForNode(){return this.dragDrop.connectDragHandler(new s.PageTreeNodeDragHandler(this,this.dragDrop))}removeEditedText(){const e=i.selectAll(".node-edit");if(e.size())try{e.remove(),this.nodeIsEdit=!1}catch(e){}}loadChildrenOfNode(e){e.loaded||(this.nodesAddPlaceholder(),new o.default(this.settings.dataUrl+"&pid="+e.identifier+"&mount="+e.mountPoint+"&pidDepth="+e.depth).get({cache:"no-cache"}).then(e=>e.resolve()).then(t=>{let i=Array.isArray(t)?t:[];i.shift();const o=this.nodes.indexOf(e)+1;i.forEach((e,t)=>{this.nodes.splice(o+t,0,e)}),e.loaded=!0,this.setParametersNode(),this.prepareDataForVisibleNodes(),this.updateVisibleNodes(),this.nodesRemovePlaceholder(),this.switchFocusNode(e)}).catch(e=>{throw this.errorNotification(e,!1),this.nodesRemovePlaceholder(),e}))}nodeSelectedAfter(e){if(!e.checked)return;top.window.fsMod.recentIds.web=e.identifier,top.window.fsMod.currentBank=e.stateIdentifier.split("_")[0],top.window.fsMod.navFrameHighlightedID.web=e.stateIdentifier;let t="?";-1!==top.window.currentSubScript.indexOf("?")&&(t="&"),top.TYPO3.Backend.ContentContainer.setUrl(top.window.currentSubScript+t+"id="+e.identifier)}appendTextElement(e){let t=0;return super.appendTextElement(e).attr("dx",e=>{let t=this.textPosition;return e.stopPageTree&&0!==e.depth&&(t+=15),e.locked&&(t+=15),t}).on("click",(e,i)=>{"0"!==i.identifier?1==++t&&setTimeout(()=>{1===t?this.selectNode(i):this.editNodeLabel(i),t=0},300):this.selectNode(i)})}sendEditNodeLabelCommand(e){const t="&data[pages]["+e.identifier+"]["+e.nameSourceField+"]="+encodeURIComponent(e.newName);this.nodesAddPlaceholder(e),new o.default(top.TYPO3.settings.ajaxUrls.record_process).post(t,{headers:{"Content-Type":"application/x-www-form-urlencoded","X-Requested-With":"XMLHttpRequest"}}).then(e=>e.resolve()).then(t=>{t&&t.hasErrors?this.errorNotification(t.messages,!1):e.name=e.newName,this.refreshOrFilterTree()}).catch(e=>{this.errorNotification(e,!0)})}editNodeLabel(e){e.allowEdit&&(this.removeEditedText(),this.nodeIsEdit=!0,i.select(this.svg.node().parentNode).append("input").attr("class","node-edit").style("top",()=>e.y+this.settings.marginTop+"px").style("left",e.x+this.textPosition+5+"px").style("width",this.settings.width-(e.x+this.textPosition+20)+"px").style("height",this.settings.nodeHeight+"px").attr("type","text").attr("value",e.name).on("keydown",t=>{const i=t.keyCode;if(i===a.KeyTypesEnum.ENTER||i===a.KeyTypesEnum.TAB){const i=t.target.value.trim();this.nodeIsEdit=!1,this.removeEditedText(),i.length&&i!==e.name&&(e.nameSourceField=e.nameSourceField||"title",e.newName=i,this.sendEditNodeLabelCommand(e))}else i===a.KeyTypesEnum.ESCAPE&&(this.nodeIsEdit=!1,this.removeEditedText())}).on("blur",t=>{if(!this.nodeIsEdit)return;const i=t.target.value.trim();i.length&&i!==e.name&&(e.nameSourceField=e.nameSourceField||"title",e.newName=i,this.sendEditNodeLabelCommand(e)),this.removeEditedText()}).node().select())}}t.PageTree=l})); \ No newline at end of file diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/PageTree/PageTreeDragDrop.js b/typo3/sysext/backend/Resources/Public/JavaScript/PageTree/PageTreeDragDrop.js index facc6d532a2d..86cd3728d688 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/PageTree/PageTreeDragDrop.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/PageTree/PageTreeDragDrop.js @@ -10,4 +10,4 @@ * * The TYPO3 project - inspiring people to share! */ -var __createBinding=this&&this.__createBinding||(Object.create?function(e,t,s,r){void 0===r&&(r=s),Object.defineProperty(e,r,{enumerable:!0,get:function(){return t[s]}})}:function(e,t,s,r){void 0===r&&(r=s),e[r]=t[s]}),__setModuleDefault=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),__importStar=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var s in e)"default"!==s&&Object.prototype.hasOwnProperty.call(e,s)&&__createBinding(t,e,s);return __setModuleDefault(t,e),t};define(["require","exports","../Tree/DragDrop","d3-selection","../Modal","../Severity"],(function(e,t,s,r,i,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.PageTreeNodeDragHandler=t.ToolbarDragHandler=t.PageTreeDragDrop=void 0,r=__importStar(r);class o extends s.DragDrop{changeNodePosition(e,t=""){const r=this.tree.nodes,i=this.tree.settings.nodeDrag.identifier;let n=this.tree.settings.nodeDragPosition,o=e||this.tree.settings.nodeDrag;if(i===o.identifier&&"delete"!==t)return null;if(n===s.DraggablePositionEnum.BEFORE){const t=r.indexOf(e),s=this.setNodePositionAndTarget(t);if(null===s)return null;n=s.position,o=s.target}return{node:this.tree.settings.nodeDrag,uid:i,target:o,position:n,command:t}}setNodePositionAndTarget(e){const t=this.tree.nodes,r=t[e].depth;e>0&&e--;const i=t[e].depth,n=this.tree.nodes[e];if(i===r)return{position:s.DraggablePositionEnum.AFTER,target:n};if(i<r)return{position:s.DraggablePositionEnum.INSIDE,target:n};for(let i=e;i>=0;i--){if(t[i].depth===r)return{position:s.DraggablePositionEnum.AFTER,target:this.tree.nodes[i]};if(t[i].depth<r)return{position:s.DraggablePositionEnum.AFTER,target:t[i]}}return null}}t.PageTreeDragDrop=o;t.ToolbarDragHandler=class{constructor(e,t,s){this.startDrag=!1,this.startPageX=0,this.startPageY=0,this.id="",this.name="",this.tooltip="",this.icon="",this.isDragged=!1,this.id=e.nodeType,this.name=e.title,this.tooltip=e.tooltip,this.icon=e.icon,this.tree=t,this.dragDrop=s}dragStart(e){return this.isDragged=!1,this.startDrag=!1,this.startPageX=e.sourceEvent.pageX,this.startPageY=e.sourceEvent.pageY,!0}dragDragged(e){return!!this.dragDrop.isDragNodeDistanceMore(e,this)&&(this.startDrag=!0,!1===this.isDragged&&(this.isDragged=!0,this.dragDrop.createDraggable("#icon-"+this.icon,this.name)),this.dragDrop.openNodeTimeout(),this.dragDrop.updateDraggablePosition(e),this.dragDrop.changeNodeClasses(e),!0)}dragEnd(e){return!!this.startDrag&&(this.isDragged=!1,this.dragDrop.removeNodeDdClass(),!(!0!==this.tree.settings.allowDragMove||!this.tree.hoveredNode||!this.tree.isOverSvg)&&(this.tree.settings.canNodeDrag&&this.addNewNode({type:this.id,name:this.name,tooltip:this.tooltip,icon:this.icon,position:this.tree.settings.nodeDragPosition,target:this.tree.hoveredNode}),!0))}addNewNode(e){const t=e.target;let i=this.tree.nodes.indexOf(t);const n={command:"new"};if(n.type=e.type,n.identifier="-1",n.target=t,n.parents=t.parents,n.parentsStateIdentifier=t.parentsStateIdentifier,n.depth=t.depth,n.position=e.position,n.name=void 0!==e.title?e.title:TYPO3.lang["tree.defaultPageTitle"],n.y=n.y||n.target.y,n.x=n.x||n.target.x,this.tree.nodeIsEdit=!0,e.position===s.DraggablePositionEnum.INSIDE&&(n.depth++,n.parents.unshift(i),n.parentsStateIdentifier.unshift(this.tree.nodes[i].stateIdentifier),this.tree.nodes[i].hasChildren=!0,this.tree.showChildren(this.tree.nodes[i])),e.position!==s.DraggablePositionEnum.INSIDE&&e.position!==s.DraggablePositionEnum.AFTER||i++,e.icon&&(n.icon=e.icon),n.position===s.DraggablePositionEnum.AFTER){const e=this.dragDrop.setNodePositionAndTarget(i);null!==e&&(n.position=e.position,n.target=e.target)}this.tree.nodes.splice(i,0,n),this.tree.setParametersNode(),this.tree.prepareDataForVisibleNodes(),this.tree.update(),this.tree.removeEditedText(),r.select(this.tree.svg.node().parentNode).append("input").attr("class","node-edit").style("top",n.y+this.tree.settings.marginTop+"px").style("left",n.x+this.tree.textPosition+5+"px").style("width",this.tree.settings.width-(n.x+this.tree.textPosition+20)+"px").style("height",this.tree.settings.nodeHeight+"px").attr("text","text").attr("value",n.name).on("keydown",e=>{const t=e.target,s=e.keyCode;if(13===s||9===s){this.tree.nodeIsEdit=!1;const e=t.value.trim();e.length?(n.name=e,this.tree.removeEditedText(),this.tree.sendChangeCommand(n)):this.removeNode(n)}else 27===s&&(this.tree.nodeIsEdit=!1,this.removeNode(n))}).on("blur",e=>{if(this.tree.nodeIsEdit&&this.tree.nodes.indexOf(n)>-1){const t=e.target.value.trim();t.length?(n.name=t,this.tree.removeEditedText(),this.tree.sendChangeCommand(n)):this.removeNode(n)}}).node().select()}removeNode(e){let t=this.tree.nodes.indexOf(e);this.tree.nodes[t-1].depth==e.depth||this.tree.nodes[t+1]&&this.tree.nodes[t+1].depth==e.depth||(this.tree.nodes[t-1].hasChildren=!1),this.tree.nodes.splice(t,1),this.tree.setParametersNode(),this.tree.prepareDataForVisibleNodes(),this.tree.update(),this.tree.removeEditedText()}};t.PageTreeNodeDragHandler=class{constructor(e,t){this.startDrag=!1,this.startPageX=0,this.startPageY=0,this.isDragged=!1,this.nodeIsOverDelete=!1,this.tree=e,this.dragDrop=t}dragStart(e){const t=e.subject;return!0===this.tree.settings.allowDragMove&&0!==t.depth&&(this.dropZoneDelete=null,t.allowDelete&&(this.dropZoneDelete=this.tree.nodesContainer.select('.node[data-state-id="'+t.stateIdentifier+'"]').append("g").attr("class","nodes-drop-zone").attr("height",this.tree.settings.nodeHeight),this.nodeIsOverDelete=!1,this.dropZoneDelete.append("rect").attr("height",this.tree.settings.nodeHeight).attr("width","50px").attr("x",0).attr("y",0).on("mouseover",()=>{this.nodeIsOverDelete=!0}).on("mouseout",()=>{this.nodeIsOverDelete=!1}),this.dropZoneDelete.append("text").text(TYPO3.lang.deleteItem).attr("dx",5).attr("dy",15),this.dropZoneDelete.node().dataset.open="false",this.dropZoneDelete.node().style.transform=this.getDropZoneCloseTransform(t)),this.startPageX=e.sourceEvent.pageX,this.startPageY=e.sourceEvent.pageY,this.startDrag=!1,!0)}dragDragged(e){const t=e.subject;if(!this.dragDrop.isDragNodeDistanceMore(e,this))return!1;if(this.startDrag=!0,!0!==this.tree.settings.allowDragMove||0===t.depth)return!1;this.tree.settings.nodeDrag=t;const s=this.tree.svg.node().querySelector('.node-bg[data-state-id="'+t.stateIdentifier+'"]'),r=this.tree.svg.node().parentNode.querySelector(".node-dd");return this.isDragged||(this.isDragged=!0,this.dragDrop.createDraggable(this.tree.getIconId(t),t.name),s.classList.add("node-bg--dragging")),this.tree.settings.nodeDragPosition=!1,this.dragDrop.openNodeTimeout(),this.dragDrop.updateDraggablePosition(e),t.isOver||this.tree.hoveredNode&&-1!==this.tree.hoveredNode.parentsStateIdentifier.indexOf(t.stateIdentifier)||!this.tree.isOverSvg?(this.dragDrop.addNodeDdClass(r,"nodrop"),this.tree.isOverSvg||this.tree.nodesBgContainer.selectAll(".node-bg__border").style("display","none"),this.dropZoneDelete&&"true"!==this.dropZoneDelete.node().dataset.open&&this.tree.isOverSvg&&this.animateDropZone("show",this.dropZoneDelete.node(),t)):this.tree.hoveredNode?this.dropZoneDelete&&"false"!==this.dropZoneDelete.node().dataset.open&&this.animateDropZone("hide",this.dropZoneDelete.node(),t):(this.dragDrop.addNodeDdClass(r,"nodrop"),this.tree.nodesBgContainer.selectAll(".node-bg__border").style("display","none")),this.dragDrop.changeNodeClasses(e),!0}dragEnd(e){const t=e.subject;if(this.dropZoneDelete&&"true"===this.dropZoneDelete.node().dataset.open){const e=this.dropZoneDelete;this.animateDropZone("hide",this.dropZoneDelete.node(),t,()=>{e.remove(),this.dropZoneDelete=null})}else this.dropZoneDelete=null;if(!this.startDrag||!0!==this.tree.settings.allowDragMove||0===t.depth)return!1;const r=this.tree.hoveredNode;if(this.isDragged=!1,this.dragDrop.removeNodeDdClass(),t.isOver||r&&-1!==r.parentsStateIdentifier.indexOf(t.stateIdentifier)||!this.tree.settings.canNodeDrag||!this.tree.isOverSvg){if(this.nodeIsOverDelete){const e=this.dragDrop.changeNodePosition(r,"delete");if(null===e)return!1;if(this.tree.settings.displayDeleteConfirmation){i.confirm(TYPO3.lang.deleteItem,TYPO3.lang["mess.delete"].replace("%s",e.node.name),n.warning,[{text:TYPO3.lang["labels.cancel"]||"Cancel",active:!0,btnClass:"btn-default",name:"cancel"},{text:TYPO3.lang["cm.delete"]||"Delete",btnClass:"btn-warning",name:"delete"}]).on("button.clicked",t=>{"delete"===t.target.name&&this.tree.sendChangeCommand(e),i.dismiss()})}else this.tree.sendChangeCommand(e)}}else{const e=this.dragDrop.changeNodePosition(r,"");if(null===e)return!1;let t=e.position===s.DraggablePositionEnum.INSIDE?TYPO3.lang["mess.move_into"]:TYPO3.lang["mess.move_after"];t=t.replace("%s",e.node.name).replace("%s",e.target.name),i.confirm(TYPO3.lang.move_page,t,n.warning,[{text:TYPO3.lang["labels.cancel"]||"Cancel",active:!0,btnClass:"btn-default",name:"cancel"},{text:TYPO3.lang["cm.copy"]||"Copy",btnClass:"btn-warning",name:"copy"},{text:TYPO3.lang["labels.move"]||"Move",btnClass:"btn-warning",name:"move"}]).on("button.clicked",t=>{const s=t.target;"move"===s.name?(e.command="move",this.tree.sendChangeCommand(e)):"copy"===s.name&&(e.command="copy",this.tree.sendChangeCommand(e)),i.dismiss()})}return!0}getDropZoneOpenTransform(e){return"translate("+((parseFloat(this.tree.svg.style("width"))||300)-58-e.x)+"px, -10px)"}getDropZoneCloseTransform(e){return"translate("+((parseFloat(this.tree.svg.style("width"))||300)-e.x)+"px, -10px)"}animateDropZone(e,t,s,r=null){t.classList.add("animating"),t.dataset.open="show"===e?"true":"false";let i=[{transform:this.getDropZoneCloseTransform(s)},{transform:this.getDropZoneOpenTransform(s)}];"show"!==e&&(i=i.reverse());const n=function(){t.style.transform=i[1].transform,t.classList.remove("animating"),r&&r()};"animate"in t?t.animate(i,{duration:300,easing:"cubic-bezier(.02, .01, .47, 1)"}).onfinish=n:n()}}})); \ No newline at end of file +var __createBinding=this&&this.__createBinding||(Object.create?function(e,t,s,i){void 0===i&&(i=s),Object.defineProperty(e,i,{enumerable:!0,get:function(){return t[s]}})}:function(e,t,s,i){void 0===i&&(i=s),e[i]=t[s]}),__setModuleDefault=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),__importStar=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var s in e)"default"!==s&&Object.prototype.hasOwnProperty.call(e,s)&&__createBinding(t,e,s);return __setModuleDefault(t,e),t};define(["require","exports","../Tree/DragDrop","d3-selection","../Modal","../Severity"],(function(e,t,s,i,r,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.PageTreeNodeDragHandler=t.ToolbarDragHandler=t.PageTreeDragDrop=void 0,i=__importStar(i);class o extends s.DragDrop{changeNodePosition(e,t=""){const i=this.tree.nodes,r=this.tree.settings.nodeDrag.identifier;let n=this.tree.settings.nodeDragPosition,o=e||this.tree.settings.nodeDrag;if(r===o.identifier&&"delete"!==t)return null;if(n===s.DraggablePositionEnum.BEFORE){const t=i.indexOf(e),s=this.setNodePositionAndTarget(t);if(null===s)return null;n=s.position,o=s.target}return{node:this.tree.settings.nodeDrag,uid:r,target:o,position:n,command:t}}setNodePositionAndTarget(e){const t=this.tree.nodes,i=t[e].depth;e>0&&e--;const r=t[e].depth,n=this.tree.nodes[e];if(r===i)return{position:s.DraggablePositionEnum.AFTER,target:n};if(r<i)return{position:s.DraggablePositionEnum.INSIDE,target:n};for(let r=e;r>=0;r--){if(t[r].depth===i)return{position:s.DraggablePositionEnum.AFTER,target:this.tree.nodes[r]};if(t[r].depth<i)return{position:s.DraggablePositionEnum.AFTER,target:t[r]}}return null}}t.PageTreeDragDrop=o;t.ToolbarDragHandler=class{constructor(e,t,s){this.startDrag=!1,this.startPageX=0,this.startPageY=0,this.id="",this.name="",this.tooltip="",this.icon="",this.isDragged=!1,this.id=e.nodeType,this.name=e.title,this.tooltip=e.tooltip,this.icon=e.icon,this.tree=t,this.dragDrop=s}dragStart(e){return this.isDragged=!1,this.startDrag=!1,this.startPageX=e.sourceEvent.pageX,this.startPageY=e.sourceEvent.pageY,!0}dragDragged(e){return!!this.dragDrop.isDragNodeDistanceMore(e,this)&&(this.startDrag=!0,!1===this.isDragged&&(this.isDragged=!0,this.dragDrop.createDraggable("#icon-"+this.icon,this.name)),this.dragDrop.openNodeTimeout(),this.dragDrop.updateDraggablePosition(e),this.dragDrop.changeNodeClasses(e),!0)}dragEnd(e){return!!this.startDrag&&(this.isDragged=!1,this.dragDrop.removeNodeDdClass(),!(!0!==this.tree.settings.allowDragMove||!this.tree.hoveredNode||!this.tree.isOverSvg)&&(this.tree.settings.canNodeDrag&&this.addNewNode({type:this.id,name:this.name,tooltip:this.tooltip,icon:this.icon,position:this.tree.settings.nodeDragPosition,target:this.tree.hoveredNode}),!0))}addNewNode(e){const t=e.target;let r=this.tree.nodes.indexOf(t);const n={command:"new"};if(n.type=e.type,n.identifier="-1",n.target=t,n.parents=t.parents,n.parentsStateIdentifier=t.parentsStateIdentifier,n.depth=t.depth,n.position=e.position,n.name=void 0!==e.title?e.title:TYPO3.lang["tree.defaultPageTitle"],n.y=n.y||n.target.y,n.x=n.x||n.target.x,this.tree.nodeIsEdit=!0,e.position===s.DraggablePositionEnum.INSIDE&&(n.depth++,n.parents.unshift(r),n.parentsStateIdentifier.unshift(this.tree.nodes[r].stateIdentifier),this.tree.nodes[r].hasChildren=!0,this.tree.showChildren(this.tree.nodes[r])),e.position!==s.DraggablePositionEnum.INSIDE&&e.position!==s.DraggablePositionEnum.AFTER||r++,e.icon&&(n.icon=e.icon),n.position===s.DraggablePositionEnum.AFTER){const e=this.dragDrop.setNodePositionAndTarget(r);null!==e&&(n.position=e.position,n.target=e.target)}this.tree.nodes.splice(r,0,n),this.tree.setParametersNode(),this.tree.prepareDataForVisibleNodes(),this.tree.updateVisibleNodes(),this.tree.removeEditedText(),i.select(this.tree.svg.node().parentNode).append("input").attr("class","node-edit").style("top",n.y+this.tree.settings.marginTop+"px").style("left",n.x+this.tree.textPosition+5+"px").style("width",this.tree.settings.width-(n.x+this.tree.textPosition+20)+"px").style("height",this.tree.settings.nodeHeight+"px").attr("text","text").attr("value",n.name).on("keydown",e=>{const t=e.target,s=e.keyCode;if(13===s||9===s){this.tree.nodeIsEdit=!1;const e=t.value.trim();e.length?(n.name=e,this.tree.removeEditedText(),this.tree.sendChangeCommand(n)):this.removeNode(n)}else 27===s&&(this.tree.nodeIsEdit=!1,this.removeNode(n))}).on("blur",e=>{if(this.tree.nodeIsEdit&&this.tree.nodes.indexOf(n)>-1){const t=e.target.value.trim();t.length?(n.name=t,this.tree.removeEditedText(),this.tree.sendChangeCommand(n)):this.removeNode(n)}}).node().select()}removeNode(e){let t=this.tree.nodes.indexOf(e);this.tree.nodes[t-1].depth==e.depth||this.tree.nodes[t+1]&&this.tree.nodes[t+1].depth==e.depth||(this.tree.nodes[t-1].hasChildren=!1),this.tree.nodes.splice(t,1),this.tree.setParametersNode(),this.tree.prepareDataForVisibleNodes(),this.tree.updateVisibleNodes(),this.tree.removeEditedText()}};t.PageTreeNodeDragHandler=class{constructor(e,t){this.startDrag=!1,this.startPageX=0,this.startPageY=0,this.isDragged=!1,this.nodeIsOverDelete=!1,this.tree=e,this.dragDrop=t}dragStart(e){const t=e.subject;return!0===this.tree.settings.allowDragMove&&0!==t.depth&&(this.dropZoneDelete=null,t.allowDelete&&(this.dropZoneDelete=this.tree.nodesContainer.select('.node[data-state-id="'+t.stateIdentifier+'"]').append("g").attr("class","nodes-drop-zone").attr("height",this.tree.settings.nodeHeight),this.nodeIsOverDelete=!1,this.dropZoneDelete.append("rect").attr("height",this.tree.settings.nodeHeight).attr("width","50px").attr("x",0).attr("y",0).on("mouseover",()=>{this.nodeIsOverDelete=!0}).on("mouseout",()=>{this.nodeIsOverDelete=!1}),this.dropZoneDelete.append("text").text(TYPO3.lang.deleteItem).attr("dx",5).attr("dy",15),this.dropZoneDelete.node().dataset.open="false",this.dropZoneDelete.node().style.transform=this.getDropZoneCloseTransform(t)),this.startPageX=e.sourceEvent.pageX,this.startPageY=e.sourceEvent.pageY,this.startDrag=!1,!0)}dragDragged(e){const t=e.subject;if(!this.dragDrop.isDragNodeDistanceMore(e,this))return!1;if(this.startDrag=!0,!0!==this.tree.settings.allowDragMove||0===t.depth)return!1;this.tree.settings.nodeDrag=t;const s=this.tree.svg.node().querySelector('.node-bg[data-state-id="'+t.stateIdentifier+'"]'),i=this.tree.svg.node().parentNode.querySelector(".node-dd");return this.isDragged||(this.isDragged=!0,this.dragDrop.createDraggable(this.tree.getIconId(t),t.name),s.classList.add("node-bg--dragging")),this.tree.settings.nodeDragPosition=!1,this.dragDrop.openNodeTimeout(),this.dragDrop.updateDraggablePosition(e),t.isOver||this.tree.hoveredNode&&-1!==this.tree.hoveredNode.parentsStateIdentifier.indexOf(t.stateIdentifier)||!this.tree.isOverSvg?(this.dragDrop.addNodeDdClass(i,"nodrop"),this.tree.isOverSvg||this.tree.nodesBgContainer.selectAll(".node-bg__border").style("display","none"),this.dropZoneDelete&&"true"!==this.dropZoneDelete.node().dataset.open&&this.tree.isOverSvg&&this.animateDropZone("show",this.dropZoneDelete.node(),t)):this.tree.hoveredNode?this.dropZoneDelete&&"false"!==this.dropZoneDelete.node().dataset.open&&this.animateDropZone("hide",this.dropZoneDelete.node(),t):(this.dragDrop.addNodeDdClass(i,"nodrop"),this.tree.nodesBgContainer.selectAll(".node-bg__border").style("display","none")),this.dragDrop.changeNodeClasses(e),!0}dragEnd(e){const t=e.subject;if(this.dropZoneDelete&&"true"===this.dropZoneDelete.node().dataset.open){const e=this.dropZoneDelete;this.animateDropZone("hide",this.dropZoneDelete.node(),t,()=>{e.remove(),this.dropZoneDelete=null})}else this.dropZoneDelete=null;if(!this.startDrag||!0!==this.tree.settings.allowDragMove||0===t.depth)return!1;const i=this.tree.hoveredNode;if(this.isDragged=!1,this.dragDrop.removeNodeDdClass(),t.isOver||i&&-1!==i.parentsStateIdentifier.indexOf(t.stateIdentifier)||!this.tree.settings.canNodeDrag||!this.tree.isOverSvg){if(this.nodeIsOverDelete){const e=this.dragDrop.changeNodePosition(i,"delete");if(null===e)return!1;if(this.tree.settings.displayDeleteConfirmation){r.confirm(TYPO3.lang.deleteItem,TYPO3.lang["mess.delete"].replace("%s",e.node.name),n.warning,[{text:TYPO3.lang["labels.cancel"]||"Cancel",active:!0,btnClass:"btn-default",name:"cancel"},{text:TYPO3.lang["cm.delete"]||"Delete",btnClass:"btn-warning",name:"delete"}]).on("button.clicked",t=>{"delete"===t.target.name&&this.tree.sendChangeCommand(e),r.dismiss()})}else this.tree.sendChangeCommand(e)}}else{const e=this.dragDrop.changeNodePosition(i,"");if(null===e)return!1;let t=e.position===s.DraggablePositionEnum.INSIDE?TYPO3.lang["mess.move_into"]:TYPO3.lang["mess.move_after"];t=t.replace("%s",e.node.name).replace("%s",e.target.name),r.confirm(TYPO3.lang.move_page,t,n.warning,[{text:TYPO3.lang["labels.cancel"]||"Cancel",active:!0,btnClass:"btn-default",name:"cancel"},{text:TYPO3.lang["cm.copy"]||"Copy",btnClass:"btn-warning",name:"copy"},{text:TYPO3.lang["labels.move"]||"Move",btnClass:"btn-warning",name:"move"}]).on("button.clicked",t=>{const s=t.target;"move"===s.name?(e.command="move",this.tree.sendChangeCommand(e)):"copy"===s.name&&(e.command="copy",this.tree.sendChangeCommand(e)),r.dismiss()})}return!0}getDropZoneOpenTransform(e){return"translate("+((parseFloat(this.tree.svg.style("width"))||300)-58-e.x)+"px, -10px)"}getDropZoneCloseTransform(e){return"translate("+((parseFloat(this.tree.svg.style("width"))||300)-e.x)+"px, -10px)"}animateDropZone(e,t,s,i=null){t.classList.add("animating"),t.dataset.open="show"===e?"true":"false";let r=[{transform:this.getDropZoneCloseTransform(s)},{transform:this.getDropZoneOpenTransform(s)}];"show"!==e&&(r=r.reverse());const n=function(){t.style.transform=r[1].transform,t.classList.remove("animating"),i&&i()};"animate"in t?t.animate(r,{duration:300,easing:"cubic-bezier(.02, .01, .47, 1)"}).onfinish=n:n()}}})); \ No newline at end of file diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/PageTree/PageTreeElement.js b/typo3/sysext/backend/Resources/Public/JavaScript/PageTree/PageTreeElement.js index 2c5e86b6e093..b071d4fb2302 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/PageTree/PageTreeElement.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/PageTree/PageTreeElement.js @@ -18,11 +18,7 @@ var __decorate=this&&this.__decorate||function(e,t,o,r){var n,i=arguments.length </div> <div id="typo3-pagetree-treeContainer" class="navigation-tree-container"> ${this.renderMountPoint()} - <div id="typo3-pagetree-tree" class="svg-tree-wrapper"> - <div class="node-loader"> - <typo3-backend-icon identifier="spinner-circle-light" size="small"></typo3-backend-icon> - </div> - </div> + <div id="typo3-pagetree-tree" class="svg-tree-wrapper"></div> </div> </div> <div class="svg-tree-loader"> @@ -37,7 +33,7 @@ var __decorate=this&&this.__decorate||function(e,t,o,r){var n,i=arguments.length <typo3-backend-icon identifier="actions-close" size="small"></typo3-backend-icon> </div> </div> - `}setTemporaryMountPoint(e){new s.default(top.TYPO3.settings.ajaxUrls.page_tree_set_temporary_mount_point).post("pid="+e,{headers:{"Content-Type":"application/x-www-form-urlencoded","X-Requested-With":"XMLHttpRequest"}}).then(e=>e.resolve()).then(e=>{e&&e.hasErrors?(this.tree.errorNotification(e.message,!0),this.tree.update()):(this.mountPointPath=e.mountPointPath,this.tree.refreshOrFilterTree())}).catch(e=>{this.tree.errorNotification(e,!0)})}};__decorate([o.property({type:String})],d.prototype,"mountPointPath",void 0),__decorate([o.query(".svg-tree-wrapper")],d.prototype,"treeWrapper",void 0),d=__decorate([o.customElement(t.navigationComponentName)],d),t.PageTreeNavigationComponent=d;let p=class extends o.LitElement{constructor(){super(...arguments),this.tree=null,this.settings={searchInput:".search-input",filterTimeout:450}}initializeDragDrop(e){var t,o;(null===(o=null===(t=this.tree.settings)||void 0===t?void 0:t.doktypes)||void 0===o?void 0:o.length)&&this.tree.settings.doktypes.forEach(t=>{if(t.icon){const o=this.querySelector('[data-tree-icon="'+t.icon+'"]');a.select(o).call(this.dragToolbar(t,e))}else console.warn("Missing icon definition for doktype: "+t.nodeType)})}createRenderRoot(){return this}firstUpdated(){const e=this.querySelector(this.settings.searchInput);e&&(new l.default("input",e=>{const t=e.target;this.tree.filter(t.value.trim())},this.settings.filterTimeout).bindTo(e),e.focus(),e.clearable({onClear:()=>{this.tree.resetFilter()}}))}render(){var e,t;return o.html` + `}setTemporaryMountPoint(e){new s.default(top.TYPO3.settings.ajaxUrls.page_tree_set_temporary_mount_point).post("pid="+e,{headers:{"Content-Type":"application/x-www-form-urlencoded","X-Requested-With":"XMLHttpRequest"}}).then(e=>e.resolve()).then(e=>{e&&e.hasErrors?(this.tree.errorNotification(e.message,!0),this.tree.updateVisibleNodes()):(this.mountPointPath=e.mountPointPath,this.tree.refreshOrFilterTree())}).catch(e=>{this.tree.errorNotification(e,!0)})}};__decorate([o.property({type:String})],d.prototype,"mountPointPath",void 0),__decorate([o.query(".svg-tree-wrapper")],d.prototype,"treeWrapper",void 0),d=__decorate([o.customElement(t.navigationComponentName)],d),t.PageTreeNavigationComponent=d;let p=class extends o.LitElement{constructor(){super(...arguments),this.tree=null,this.settings={searchInput:".search-input",filterTimeout:450}}initializeDragDrop(e){var t,o;(null===(o=null===(t=this.tree.settings)||void 0===t?void 0:t.doktypes)||void 0===o?void 0:o.length)&&this.tree.settings.doktypes.forEach(t=>{if(t.icon){const o=this.querySelector('[data-tree-icon="'+t.icon+'"]');a.select(o).call(this.dragToolbar(t,e))}else console.warn("Missing icon definition for doktype: "+t.nodeType)})}createRenderRoot(){return this}firstUpdated(){const e=this.querySelector(this.settings.searchInput);e&&(new l.default("input",e=>{const t=e.target;this.tree.filter(t.value.trim())},this.settings.filterTimeout).bindTo(e),e.focus(),e.clearable({onClear:()=>{this.tree.resetFilter()}}))}render(){var e,t;return o.html` <div class="tree-toolbar"> <div class="svg-toolbar__menu"> <div class="svg-toolbar__search"> diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/SvgTree.js b/typo3/sysext/backend/Resources/Public/JavaScript/SvgTree.js index 696d20ad34e0..a5dc4cf2c0a5 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/SvgTree.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/SvgTree.js @@ -10,4 +10,16 @@ * * The TYPO3 project - inspiring people to share! */ -var __createBinding=this&&this.__createBinding||(Object.create?function(e,t,s,i){void 0===i&&(i=s),Object.defineProperty(e,i,{enumerable:!0,get:function(){return t[s]}})}:function(e,t,s,i){void 0===i&&(i=s),e[i]=t[s]}),__setModuleDefault=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),__importStar=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var s in e)"default"!==s&&Object.prototype.hasOwnProperty.call(e,s)&&__createBinding(t,e,s);return __setModuleDefault(t,e),t},__importDefault=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};define(["require","exports","d3-selection","d3-dispatch","TYPO3/CMS/Core/Ajax/AjaxRequest","./Notification","./Enum/KeyTypes","./Icons","./Tooltip","./Enum/IconTypes"],(function(e,t,s,i,r,n,o,a,d,l){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.SvgTree=void 0,s=__importStar(s),i=__importStar(i),r=__importDefault(r);t.SvgTree=class{constructor(){this.dispatch=null,this.isOverSvg=!1,this.svg=null,this.container=null,this.nodesContainer=null,this.nodesBgContainer=null,this.hoveredNode=null,this.nodes=[],this.settings={showIcons:!1,marginTop:15,nodeHeight:20,indentWidth:16,width:300,duration:400,dataUrl:"",defaultProperties:{},expandUpToLevel:null},this.textPosition=0,this.iconsContainer=null,this.linksContainer=null,this.data=new class{},this.wrapper=null,this.viewportHeight=0,this.scrollTop=0,this.scrollBottom=0,this.searchTerm=null,this.unfilteredNodes="",this.networkErrorTitle=TYPO3.lang.pagetree_networkErrorTitle,this.networkErrorMessage=TYPO3.lang.pagetree_networkErrorDesc,this.dispatch=i.dispatch("updateNodes","updateSvg","loadDataAfter","prepareLoadedNode","nodeSelectedAfter","nodeRightClick")}initialize(e,t){Object.assign(this.settings,t),this.wrapper=e,this.svg=s.select(this.wrapper).append("svg").attr("version","1.1").attr("width","100%").on("mouseover",()=>this.isOverSvg=!0).on("mouseout",()=>this.isOverSvg=!1).on("keydown",e=>this.handleKeyboardInteraction(e)),this.container=this.svg.append("g").attr("class","nodes-wrapper").attr("transform","translate("+this.settings.indentWidth/2+","+this.settings.nodeHeight/2+")"),this.nodesBgContainer=this.container.append("g").attr("class","nodes-bg"),this.linksContainer=this.container.append("g").attr("class","links"),this.nodesContainer=this.container.append("g").attr("class","nodes").attr("role","tree"),this.settings.showIcons&&(this.iconsContainer=this.svg.append("defs")),this.updateScrollPosition(),this.loadData(),this.wrapper.addEventListener("resize",()=>{this.updateScrollPosition(),this.update()}),this.wrapper.addEventListener("scroll",()=>{this.updateScrollPosition(),this.update()}),this.wrapper.addEventListener("svg-tree:visible",()=>{this.updateScrollPosition(),this.update()}),this.wrapper.dispatchEvent(new Event("svg-tree:initialized")),this.resize()}resize(){window.addEventListener("resize",()=>{this.wrapper.getClientRects().length>0&&(this.updateScrollPosition(),this.update())})}switchFocus(e){if(null===e)return;e.parentNode.querySelectorAll("[tabindex]").forEach(e=>{e.setAttribute("tabindex","-1")}),e.setAttribute("tabindex","0"),e.focus()}switchFocusNode(e){this.switchFocus(this.getNodeElement(e))}getNodeElement(e){return document.getElementById("identifier-"+this.getNodeStateIdentifier(e))}updateScrollPosition(){this.viewportHeight=this.wrapper.getBoundingClientRect().height,this.scrollTop=this.wrapper.scrollTop,this.scrollBottom=this.scrollTop+this.viewportHeight+this.viewportHeight/2,d.hide(this.wrapper.querySelectorAll("[data-bs-toggle=tooltip]"))}loadData(){this.nodesAddPlaceholder(),new r.default(this.settings.dataUrl).get({cache:"no-cache"}).then(e=>e.resolve()).then(e=>{const t=Array.isArray(e)?e:[];this.replaceData(t),this.nodesRemovePlaceholder(),this.updateScrollPosition(),this.update()}).catch(e=>{throw this.errorNotification(e,!1),this.nodesRemovePlaceholder(),e})}replaceData(e){this.setParametersNode(e),this.dispatch.call("loadDataAfter",this),this.prepareDataForVisibleNodes(),this.nodesContainer.selectAll(".node").remove(),this.nodesBgContainer.selectAll(".node-bg").remove(),this.linksContainer.selectAll(".link").remove(),this.update()}setParametersNode(e=null){1===(e=(e=e||this.nodes).map((t,s)=>{if(void 0===t.command&&(t=Object.assign({},this.settings.defaultProperties,t)),t.expanded=null!==this.settings.expandUpToLevel?t.depth<this.settings.expandUpToLevel:Boolean(t.expanded),t.parents=[],t.parentsStateIdentifier=[],t.depth>0){let i=t.depth;for(let r=s;r>=0;r--){let s=e[r];s.depth<i&&(t.parents.push(r),t.parentsStateIdentifier.push(e[r].stateIdentifier),i=s.depth)}}return void 0===t.checked&&(t.checked=!1),this.dispatch.call("prepareLoadedNode",this,t),t})).filter(e=>0===e.depth).length&&(e[0].expanded=!0),this.nodes=e}nodesRemovePlaceholder(){const e=this.svg.node().closest(".svg-tree"),t=null==e?void 0:e.querySelector(".node-loader");t&&(t.style.display="none");const s=null==e?void 0:e.querySelector(".svg-tree-loader");s&&(s.style.display="none")}nodesAddPlaceholder(e=null){const t=this.svg.node().closest(".svg-tree");if(e){const s=null==t?void 0:t.querySelector(".node-loader");s&&(s.style.top=""+(e.y+this.settings.marginTop),s.style.display="block")}else{const e=null==t?void 0:t.querySelector(".svg-tree-loader");e&&(e.style.display="block")}}hideChildren(e){e.expanded=!1,this.setExpandedState(e)}showChildren(e){e.expanded=!0,this.setExpandedState(e)}setExpandedState(e){const t=this.getNodeElement(e);t&&(e.hasChildren?t.setAttribute("aria-expanded",e.expanded?"true":"false"):t.removeAttribute("aria-expanded"))}refreshTree(){this.loadData()}refreshOrFilterTree(){""!==this.searchTerm?this.filter(this.searchTerm):this.refreshTree()}expandAll(){this.nodes.forEach(this.showChildren.bind(this)),this.prepareDataForVisibleNodes(),this.update()}collapseAll(){this.nodes.forEach(this.hideChildren.bind(this)),this.prepareDataForVisibleNodes(),this.update()}prepareDataForVisibleNodes(){const e={};this.nodes.forEach((t,s)=>{t.expanded||(e[s]=!0)}),this.data.nodes=this.nodes.filter(t=>!0!==t.hidden&&!t.parents.some(t=>Boolean(e[t]))),this.data.links=[];let t=0;this.data.nodes.forEach((e,s)=>{e.x=e.depth*this.settings.indentWidth,e.readableRootline&&(t+=this.settings.nodeHeight),e.y=s*this.settings.nodeHeight+t,void 0!==e.parents[0]&&this.data.links.push({source:this.nodes[e.parents[0]],target:e}),this.settings.showIcons&&(this.fetchIcon(e.icon),this.fetchIcon(e.overlayIcon),e.locked&&this.fetchIcon("warning-in-use"))}),this.svg.attr("height",this.data.nodes.length*this.settings.nodeHeight+this.settings.nodeHeight/2+t)}fetchIcon(e,t=!0){e&&(this.icons=this.icons||{},e in this.icons||(this.icons[e]={identifier:e,icon:""},a.getIcon(e,a.sizes.small,null,null,l.MarkupIdentifiers.inline).then(s=>{let i=s.match(/<svg[\s\S]*<\/svg>/i);i&&(this.icons[e].icon=i[0]),t&&this.update()})))}update(){const e=Math.ceil(this.viewportHeight/this.settings.nodeHeight+1),t=Math.floor(Math.max(this.scrollTop-2*this.settings.nodeHeight,0)/this.settings.nodeHeight),i=this.data.nodes.slice(t,t+e),r=this.wrapper.querySelector('[tabindex="0"]'),n=i.find(e=>e.checked);let o=this.nodesContainer.selectAll(".node").data(i,e=>e.stateIdentifier);const a=this.nodesBgContainer.selectAll(".node-bg").data(i,e=>e.stateIdentifier);o.exit().remove(),a.exit().remove();const d=this.updateNodeBgClass(a);d.attr("class",(e,t)=>this.getNodeBgClass(e,t,d)).attr("style",e=>e.backgroundColor?"fill: "+e.backgroundColor+";":""),this.updateLinks(),o=this.enterSvgElements(o),o.attr("tabindex",(e,t)=>{if(void 0!==n){if(n===e)return"0"}else if(null===r){if(0===t)return"0"}else if(s.select(r).datum()===e)return"0";return"-1"}).attr("transform",this.getNodeTransform).select(".node-name").text(this.getNodeLabel),o.select(".chevron").attr("transform",this.getChevronTransform).style("fill",this.getChevronColor).attr("class",this.getChevronClass),o.select(".toggle").attr("visibility",this.getToggleVisibility),this.settings.showIcons&&(o.select("use.node-icon").attr("xlink:href",this.getIconId),o.select("use.node-icon-overlay").attr("xlink:href",this.getIconOverlayId),o.select("use.node-icon-locked").attr("xlink:href",e=>"#icon-"+(e.locked?"warning-in-use":""))),this.dispatch.call("updateNodes",this,o)}updateNodeBgClass(e){return e.enter().append("rect").merge(e).attr("width","100%").attr("height",this.settings.nodeHeight).attr("data-state-id",this.getNodeStateIdentifier).attr("transform",this.getNodeBgTransform).on("mouseover",(e,t)=>this.onMouseOverNode(t)).on("mouseout",(e,t)=>this.onMouseOutOfNode(t)).on("click",(e,t)=>{this.selectNode(t),this.switchFocusNode(t)}).on("contextmenu",(e,t)=>{this.dispatch.call("nodeRightClick",this,t)})}getIconId(e){return"#icon-"+e.icon}getIconOverlayId(e){return"#icon-"+e.overlayIcon}selectNode(e){this.isNodeSelectable(e)&&this.dispatch.call("nodeSelectedAfter",this,e)}filter(e){"string"==typeof e&&(this.searchTerm=e),this.nodesAddPlaceholder(),this.searchTerm?new r.default(this.settings.filterUrl+"&q="+this.searchTerm).get({cache:"no-cache"}).then(e=>e.resolve()).then(e=>{let t=Array.isArray(e)?e:[];t.length>0&&(""===this.unfilteredNodes&&(this.unfilteredNodes=JSON.stringify(this.nodes)),this.replaceData(t)),this.nodesRemovePlaceholder()}).catch(e=>{throw this.errorNotification(e,!1),this.nodesRemovePlaceholder(),e}):this.resetFilter()}resetFilter(){if(this.searchTerm="",this.unfilteredNodes.length>0){let e=this.getSelectedNodes()[0];if(void 0===e)return void this.refreshTree();this.nodes=JSON.parse(this.unfilteredNodes),this.unfilteredNodes="";const t=this.getNodeByIdentifier(e.stateIdentifier);t?this.selectNode(t):this.refreshTree()}else this.refreshTree();this.prepareDataForVisibleNodes(),this.update()}errorNotification(e=null,t=!1){if(Array.isArray(e))e.forEach(e=>{n.error(e.title,e.message)});else{let t=this.networkErrorTitle;e&&e.target&&(e.target.status||e.target.statusText)&&(t+=" - "+(e.target.status||"")+" "+(e.target.statusText||"")),n.error(t,this.networkErrorMessage)}t&&this.loadData()}disableSelectedNodes(){this.getSelectedNodes().forEach(e=>{!0===e.checked&&(e.checked=!1,this.dispatch.call("nodeSelectedAfter",this,e))})}isNodeSelectable(e){return!0}getSelectedNodes(){return this.nodes.filter(e=>e.checked)}appendTextElement(e){return e.append("text").attr("dx",e=>this.textPosition+(e.locked?15:0)).attr("dy",5).attr("class","node-name").on("click",(e,t)=>this.selectNode(t))}nodesUpdate(e){return(e=e.enter().append("g").attr("class",this.getNodeClass).attr("id",e=>"identifier-"+e.stateIdentifier).attr("role","treeitem").attr("aria-owns",e=>e.hasChildren?"group-identifier-"+e.stateIdentifier:null).attr("aria-level",this.getNodeDepth).attr("aria-setsize",this.getNodeSetsize).attr("aria-posinset",this.getNodePositionInSet).attr("aria-expanded",e=>e.hasChildren?e.expanded:null).attr("transform",this.getNodeTransform).attr("data-state-id",this.getNodeStateIdentifier).attr("title",this.getNodeTitle).on("mouseover",(e,t)=>this.onMouseOverNode(t)).on("mouseout",(e,t)=>this.onMouseOutOfNode(t)).on("contextmenu",(e,t)=>{e.preventDefault(),this.dispatch.call("nodeRightClick",this,t)})).append("text").text(e=>e.readableRootline).attr("class","node-rootline").attr("dx",0).attr("dy",-15).attr("visibility",e=>e.readableRootline?"visible":"hidden"),e}getNodeIdentifier(e){return e.identifier}getNodeDepth(e){return e.depth}getNodeSetsize(e){return e.siblingsCount}getNodePositionInSet(e){return e.siblingsPosition}getNodeStateIdentifier(e){return e.stateIdentifier}getNodeLabel(e){return(e.prefix||"")+e.name+(e.suffix||"")}getNodeClass(e){return"node identifier-"+e.stateIdentifier}getNodeByIdentifier(e){return this.nodes.find(t=>t.stateIdentifier===e)}getNodeBgClass(e,t,s){let i="node-bg",r=null,n=null;return"object"==typeof s&&(r=s.data()[t-1],n=s.data()[t+1]),e.checked&&(i+=" node-selected"),(r&&e.depth>r.depth||!r)&&(e.firstChild=!0,i+=" node-first-child"),(n&&e.depth>n.depth||!n)&&(e.lastChild=!0,i+=" node-last-child"),e.class&&(i+=" "+e.class),i}getNodeTitle(e){return e.tip?e.tip:"uid="+e.identifier}getChevronTransform(e){return e.expanded?"translate(16,0) rotate(90)":" rotate(0)"}getChevronColor(e){return e.expanded?"#000":"#8e8e8e"}getToggleVisibility(e){return e.hasChildren?"visible":"hidden"}getChevronClass(e){return"chevron "+(e.expanded?"expanded":"collapsed")}getLinkPath(e){const t=e.target.x,s=e.target.y,i=[];return i.push("M"+e.source.x+" "+e.source.y),i.push("V"+s),e.target.hasChildren?i.push("H"+(t-2)):i.push("H"+(t+this.settings.indentWidth/4-2)),i.join(" ")}getNodeTransform(e){return"translate("+(e.x||0)+","+(e.y||0)+")"}getNodeBgTransform(e){return"translate(-8, "+((e.y||0)-10)+")"}clickOnIcon(e){this.dispatch.call("nodeRightClick",this,e)}chevronClick(e){e.expanded?this.hideChildren(e):this.showChildren(e),this.prepareDataForVisibleNodes(),this.update()}onMouseOverNode(e){e.isOver=!0,this.hoveredNode=e;let t=this.svg.select('.nodes-bg .node-bg[data-state-id="'+e.stateIdentifier+'"]');t.size()&&t.classed("node-over",!0).attr("rx","3").attr("ry","3")}onMouseOutOfNode(e){e.isOver=!1,this.hoveredNode=null;let t=this.svg.select('.nodes-bg .node-bg[data-state-id="'+e.stateIdentifier+'"]');t.size()&&t.classed("node-over node-alert",!1).attr("rx","0").attr("ry","0")}handleKeyboardInteraction(e){const t=e.target;let i=s.select(t).datum();if(-1===[o.KeyTypesEnum.ENTER,o.KeyTypesEnum.SPACE,o.KeyTypesEnum.END,o.KeyTypesEnum.HOME,o.KeyTypesEnum.LEFT,o.KeyTypesEnum.UP,o.KeyTypesEnum.RIGHT,o.KeyTypesEnum.DOWN].indexOf(e.keyCode))return;e.preventDefault();const r=t.parentNode;switch(e.keyCode){case o.KeyTypesEnum.END:this.scrollTop=this.wrapper.lastElementChild.getBoundingClientRect().height+this.settings.nodeHeight-this.viewportHeight,r.scrollIntoView({behavior:"smooth",block:"end"}),this.update(),this.switchFocus(r.lastElementChild);break;case o.KeyTypesEnum.HOME:this.scrollTop=this.nodes[0].y,this.wrapper.scrollTo({top:this.scrollTop,behavior:"smooth"}),this.update(),this.switchFocus(r.firstElementChild);break;case o.KeyTypesEnum.LEFT:if(i.expanded)i.hasChildren&&(this.hideChildren(i),this.prepareDataForVisibleNodes(),this.update());else if(i.parents.length>0){let e=this.nodes[i.parents[0]];this.scrollNodeIntoVisibleArea(e,"up"),this.switchFocusNode(e)}break;case o.KeyTypesEnum.UP:this.scrollNodeIntoVisibleArea(i,"up"),this.switchFocus(t.previousSibling);break;case o.KeyTypesEnum.RIGHT:i.expanded?(this.scrollNodeIntoVisibleArea(i,"down"),this.switchFocus(t.nextSibling)):i.hasChildren&&(this.showChildren(i),this.prepareDataForVisibleNodes(),this.update(),this.switchFocus(t));break;case o.KeyTypesEnum.DOWN:this.scrollNodeIntoVisibleArea(i,"down"),this.switchFocus(t.nextSibling);break;case o.KeyTypesEnum.ENTER:case o.KeyTypesEnum.SPACE:this.selectNode(i)}}scrollNodeIntoVisibleArea(e,t="up"){if("up"===t&&this.scrollTop>e.y-this.settings.nodeHeight)this.scrollTop=e.y-this.settings.nodeHeight;else{if(!("down"===t&&this.scrollTop+this.viewportHeight<=e.y+3*this.settings.nodeHeight))return;this.scrollTop=this.scrollTop+this.settings.nodeHeight}this.wrapper.scrollTo({top:this.scrollTop,behavior:"smooth"}),this.update()}updateLinks(){const e=this.data.links.filter(e=>e.source.y<=this.scrollBottom&&e.target.y>=this.scrollTop-this.settings.nodeHeight).map(e=>(e.source.owns=e.source.owns||[],e.source.owns.push("identifier-"+e.target.stateIdentifier),e)),t=this.linksContainer.selectAll(".link").data(e);t.exit().remove(),t.enter().append("path").attr("class","link").attr("id",this.getGroupIdentifier).attr("role",e=>1===e.target.siblingsPosition&&e.source.owns.length>0?"group":null).attr("aria-owns",e=>1===e.target.siblingsPosition&&e.source.owns.length>0?e.source.owns.join(" "):null).merge(t).attr("d",e=>this.getLinkPath(e))}getGroupIdentifier(e){return 1===e.target.siblingsPosition?"group-identifier-"+e.source.stateIdentifier:null}enterSvgElements(e){if(this.textPosition=10,this.settings.showIcons){const e=Object.values(this.icons).filter(e=>""!==e.icon),t=this.iconsContainer.selectAll(".icon-def").data(e,e=>e.identifier);t.exit().remove(),t.enter().append("g").attr("class","icon-def").attr("id",e=>"icon-"+e.identifier).append(e=>{const t=new DOMParser,s='<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">'+e.icon.replace("<svg","<g").replace("/svg>","/g>")+"</svg>";return t.parseFromString(s,"image/svg+xml").documentElement.firstChild})}const t=this.nodesUpdate(e);let s=t.append("g").attr("class","toggle").attr("visibility",this.getToggleVisibility).attr("transform","translate(-8, -8)").on("click",(e,t)=>this.chevronClick(t));if(s.append("path").style("opacity",0).attr("d","M 0 0 L 16 0 L 16 16 L 0 16 Z"),s.append("path").attr("class","chevron").attr("d","M 4 3 L 13 8 L 4 13 Z"),this.settings.showIcons){this.textPosition=30;const e=t.append("g").attr("class","node-icon-container").attr("title",this.getNodeTitle).attr("data-bs-toggle","tooltip").on("click",(e,t)=>{this.clickOnIcon(t)});e.append("use").attr("class","node-icon").attr("data-uid",this.getNodeIdentifier).attr("transform","translate(8, -8)"),e.append("use").attr("transform","translate(8, -3)").attr("class","node-icon-overlay"),e.append("use").attr("x",27).attr("y",-7).attr("class","node-icon-locked")}return d.initialize('[data-bs-toggle="tooltip"]',{delay:{show:50,hide:50},trigger:"hover",placement:"right"}),this.dispatch.call("updateSvg",this,t),this.appendTextElement(t),e.merge(t)}}})); \ No newline at end of file +var __createBinding=this&&this.__createBinding||(Object.create?function(e,t,s,i){void 0===i&&(i=s),Object.defineProperty(e,i,{enumerable:!0,get:function(){return t[s]}})}:function(e,t,s,i){void 0===i&&(i=s),e[i]=t[s]}),__setModuleDefault=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),__importStar=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var s in e)"default"!==s&&Object.prototype.hasOwnProperty.call(e,s)&&__createBinding(t,e,s);return __setModuleDefault(t,e),t},__importDefault=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};define(["require","exports","lit-element","TYPO3/CMS/Core/lit-helper","d3-selection","d3-dispatch","TYPO3/CMS/Core/Ajax/AjaxRequest","./Notification","./Enum/KeyTypes","./Icons","./Tooltip","./Enum/IconTypes"],(function(e,t,s,i,r,n,o,a,d,l,h,c){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.SvgTree=void 0,r=__importStar(r),n=__importStar(n),o=__importDefault(o);t.SvgTree=class{constructor(){this.dispatch=null,this.isOverSvg=!1,this.svg=null,this.container=null,this.nodesContainer=null,this.nodesBgContainer=null,this.hoveredNode=null,this.nodes=[],this.settings={showIcons:!1,marginTop:15,nodeHeight:20,indentWidth:16,width:300,duration:400,dataUrl:"",filterUrl:"",defaultProperties:{},expandUpToLevel:null},this.textPosition=0,this.iconsContainer=null,this.linksContainer=null,this.data=new class{constructor(){this.links=[],this.nodes=[]}},this.wrapper=null,this.viewportHeight=0,this.scrollTop=0,this.scrollBottom=0,this.searchTerm=null,this.unfilteredNodes="",this.networkErrorTitle=TYPO3.lang.pagetree_networkErrorTitle,this.networkErrorMessage=TYPO3.lang.pagetree_networkErrorDesc,this.dispatch=n.dispatch("updateNodes","updateSvg","loadDataAfter","prepareLoadedNode","nodeSelectedAfter","nodeRightClick")}initialize(e,t){this.wrapper=e,Object.assign(this.settings,t),this.wrapper.append(...i.renderNodes(this.getTemplate())),this.svg=r.select(this.wrapper).select("svg"),this.container=this.svg.select(".nodes-wrapper"),this.nodesBgContainer=this.container.select(".nodes-bg"),this.linksContainer=this.container.select(".links"),this.nodesContainer=this.container.select(".nodes"),this.iconsContainer=this.svg.select("defs"),this.updateScrollPosition(),this.loadData(),this.addEventListeners(),this.wrapper.dispatchEvent(new Event("svg-tree:initialized"))}switchFocus(e){if(null===e)return;e.parentNode.querySelectorAll("[tabindex]").forEach(e=>{e.setAttribute("tabindex","-1")}),e.setAttribute("tabindex","0"),e.focus()}switchFocusNode(e){this.switchFocus(this.getNodeElement(e))}getNodeElement(e){return this.wrapper.querySelector("#identifier-"+this.getNodeStateIdentifier(e))}loadData(){this.nodesAddPlaceholder(),new o.default(this.settings.dataUrl).get({cache:"no-cache"}).then(e=>e.resolve()).then(e=>{const t=Array.isArray(e)?e:[];this.replaceData(t),this.nodesRemovePlaceholder(),this.updateScrollPosition(),this.updateVisibleNodes()}).catch(e=>{throw this.errorNotification(e,!1),this.nodesRemovePlaceholder(),e})}replaceData(e){this.setParametersNode(e),this.dispatch.call("loadDataAfter",this),this.prepareDataForVisibleNodes(),this.nodesContainer.selectAll(".node").remove(),this.nodesBgContainer.selectAll(".node-bg").remove(),this.linksContainer.selectAll(".link").remove(),this.updateVisibleNodes()}setParametersNode(e=null){1===(e=(e=e||this.nodes).map((t,s)=>{if(void 0===t.command&&(t=Object.assign({},this.settings.defaultProperties,t)),t.expanded=null!==this.settings.expandUpToLevel?t.depth<this.settings.expandUpToLevel:Boolean(t.expanded),t.parents=[],t.parentsStateIdentifier=[],t.depth>0){let i=t.depth;for(let r=s;r>=0;r--){let s=e[r];s.depth<i&&(t.parents.push(r),t.parentsStateIdentifier.push(e[r].stateIdentifier),i=s.depth)}}return void 0===t.checked&&(t.checked=!1),this.dispatch.call("prepareLoadedNode",this,t),t})).filter(e=>0===e.depth).length&&(e[0].expanded=!0),this.nodes=e}nodesRemovePlaceholder(){const e=this.wrapper.querySelector(".node-loader");e&&(e.style.display="none");const t=this.wrapper.closest(".svg-tree"),s=null==t?void 0:t.querySelector(".svg-tree-loader");s&&(s.style.display="none")}nodesAddPlaceholder(e=null){if(e){const t=this.wrapper.querySelector(".node-loader");t&&(t.style.top=""+(e.y+this.settings.marginTop),t.style.display="block")}else{const e=this.wrapper.closest(".svg-tree"),t=null==e?void 0:e.querySelector(".svg-tree-loader");t&&(t.style.display="block")}}hideChildren(e){e.expanded=!1,this.setExpandedState(e)}showChildren(e){e.expanded=!0,this.setExpandedState(e)}setExpandedState(e){const t=this.getNodeElement(e);t&&(e.hasChildren?t.setAttribute("aria-expanded",e.expanded?"true":"false"):t.removeAttribute("aria-expanded"))}refreshTree(){this.loadData()}refreshOrFilterTree(){""!==this.searchTerm?this.filter(this.searchTerm):this.refreshTree()}prepareDataForVisibleNodes(){const e={};this.nodes.forEach((t,s)=>{t.expanded||(e[s]=!0)}),this.data.nodes=this.nodes.filter(t=>!0!==t.hidden&&!t.parents.some(t=>Boolean(e[t]))),this.data.links=[];let t=0;this.data.nodes.forEach((e,s)=>{e.x=e.depth*this.settings.indentWidth,e.readableRootline&&(t+=this.settings.nodeHeight),e.y=s*this.settings.nodeHeight+t,void 0!==e.parents[0]&&this.data.links.push({source:this.nodes[e.parents[0]],target:e}),this.settings.showIcons&&(this.fetchIcon(e.icon),this.fetchIcon(e.overlayIcon),e.locked&&this.fetchIcon("warning-in-use"))}),this.svg.attr("height",this.data.nodes.length*this.settings.nodeHeight+this.settings.nodeHeight/2+t)}fetchIcon(e,t=!0){e&&(this.icons=this.icons||{},e in this.icons||(this.icons[e]={identifier:e,icon:""},l.getIcon(e,l.sizes.small,null,null,c.MarkupIdentifiers.inline).then(s=>{let i=s.match(/<svg[\s\S]*<\/svg>/i);i&&(this.icons[e].icon=i[0]),t&&this.updateVisibleNodes()})))}updateVisibleNodes(){const e=Math.ceil(this.viewportHeight/this.settings.nodeHeight+1),t=Math.floor(Math.max(this.scrollTop-2*this.settings.nodeHeight,0)/this.settings.nodeHeight),s=this.data.nodes.slice(t,t+e),i=this.wrapper.querySelector('[tabindex="0"]'),n=s.find(e=>e.checked);let o=this.nodesContainer.selectAll(".node").data(s,e=>e.stateIdentifier);const a=this.nodesBgContainer.selectAll(".node-bg").data(s,e=>e.stateIdentifier);o.exit().remove(),a.exit().remove();const d=this.updateNodeBgClass(a);d.attr("class",(e,t)=>this.getNodeBgClass(e,t,d)).attr("style",e=>e.backgroundColor?"fill: "+e.backgroundColor+";":""),this.updateLinks(),o=this.enterSvgElements(o),o.attr("tabindex",(e,t)=>{if(void 0!==n){if(n===e)return"0"}else if(null===i){if(0===t)return"0"}else if(r.select(i).datum()===e)return"0";return"-1"}).attr("transform",this.getNodeTransform).select(".node-name").text(this.getNodeLabel),o.select(".chevron").attr("transform",this.getChevronTransform).style("fill",this.getChevronColor).attr("class",this.getChevronClass),o.select(".toggle").attr("visibility",this.getToggleVisibility),this.settings.showIcons&&(o.select("use.node-icon").attr("xlink:href",this.getIconId),o.select("use.node-icon-overlay").attr("xlink:href",this.getIconOverlayId),o.select("use.node-icon-locked").attr("xlink:href",e=>"#icon-"+(e.locked?"warning-in-use":""))),this.dispatch.call("updateNodes",this,o)}updateNodeBgClass(e){return e.enter().append("rect").merge(e).attr("width","100%").attr("height",this.settings.nodeHeight).attr("data-state-id",this.getNodeStateIdentifier).attr("transform",this.getNodeBgTransform).on("mouseover",(e,t)=>this.onMouseOverNode(t)).on("mouseout",(e,t)=>this.onMouseOutOfNode(t)).on("click",(e,t)=>{this.selectNode(t),this.switchFocusNode(t)}).on("contextmenu",(e,t)=>{this.dispatch.call("nodeRightClick",this,t)})}getIconId(e){return"#icon-"+e.icon}getIconOverlayId(e){return"#icon-"+e.overlayIcon}selectNode(e){this.isNodeSelectable(e)&&this.dispatch.call("nodeSelectedAfter",this,e)}filter(e){"string"==typeof e&&(this.searchTerm=e),this.nodesAddPlaceholder(),this.searchTerm&&this.settings.filterUrl?new o.default(this.settings.filterUrl+"&q="+this.searchTerm).get({cache:"no-cache"}).then(e=>e.resolve()).then(e=>{let t=Array.isArray(e)?e:[];t.length>0&&(""===this.unfilteredNodes&&(this.unfilteredNodes=JSON.stringify(this.nodes)),this.replaceData(t)),this.nodesRemovePlaceholder()}).catch(e=>{throw this.errorNotification(e,!1),this.nodesRemovePlaceholder(),e}):this.resetFilter()}resetFilter(){if(this.searchTerm="",this.unfilteredNodes.length>0){let e=this.getSelectedNodes()[0];if(void 0===e)return void this.refreshTree();this.nodes=JSON.parse(this.unfilteredNodes),this.unfilteredNodes="";const t=this.getNodeByIdentifier(e.stateIdentifier);t?this.selectNode(t):this.refreshTree()}else this.refreshTree();this.prepareDataForVisibleNodes(),this.updateVisibleNodes()}errorNotification(e=null,t=!1){if(Array.isArray(e))e.forEach(e=>{a.error(e.title,e.message)});else{let t=this.networkErrorTitle;e&&e.target&&(e.target.status||e.target.statusText)&&(t+=" - "+(e.target.status||"")+" "+(e.target.statusText||"")),a.error(t,this.networkErrorMessage)}t&&this.loadData()}getTemplate(){return s.html` + <div class="node-loader"> + <typo3-backend-icon identifier="spinner-circle-light" size="small"></typo3-backend-icon> + </div> + <svg version="1.1" width="100%"> + <g class="nodes-wrapper" transform="translate(${this.settings.indentWidth/2},${this.settings.nodeHeight/2})"> + <g class="nodes-bg"></g> + <g class="links"></g> + <g class="nodes" role="tree"></g> + </g> + <defs></defs> + </svg> + `}addEventListeners(){this.wrapper.addEventListener("resize",()=>this.updateView()),this.wrapper.addEventListener("scroll",()=>this.updateView()),this.wrapper.addEventListener("svg-tree:visible",()=>this.updateView()),window.addEventListener("resize",()=>{this.wrapper.getClientRects().length>0&&this.updateView()});const e=this.wrapper.querySelector("svg");e.addEventListener("mouseover",()=>this.isOverSvg=!0),e.addEventListener("mouseout",()=>this.isOverSvg=!1),e.addEventListener("keydown",e=>this.handleKeyboardInteraction(e))}updateView(){this.updateScrollPosition(),this.updateVisibleNodes()}disableSelectedNodes(){this.getSelectedNodes().forEach(e=>{!0===e.checked&&(e.checked=!1,this.dispatch.call("nodeSelectedAfter",this,e))})}isNodeSelectable(e){return!0}getSelectedNodes(){return this.nodes.filter(e=>e.checked)}appendTextElement(e){return e.append("text").attr("dx",e=>this.textPosition+(e.locked?15:0)).attr("dy",5).attr("class","node-name").on("click",(e,t)=>this.selectNode(t))}nodesUpdate(e){return(e=e.enter().append("g").attr("class",this.getNodeClass).attr("id",e=>"identifier-"+e.stateIdentifier).attr("role","treeitem").attr("aria-owns",e=>e.hasChildren?"group-identifier-"+e.stateIdentifier:null).attr("aria-level",this.getNodeDepth).attr("aria-setsize",this.getNodeSetsize).attr("aria-posinset",this.getNodePositionInSet).attr("aria-expanded",e=>e.hasChildren?e.expanded:null).attr("transform",this.getNodeTransform).attr("data-state-id",this.getNodeStateIdentifier).attr("title",this.getNodeTitle).on("mouseover",(e,t)=>this.onMouseOverNode(t)).on("mouseout",(e,t)=>this.onMouseOutOfNode(t)).on("contextmenu",(e,t)=>{e.preventDefault(),this.dispatch.call("nodeRightClick",this,t)})).append("text").text(e=>e.readableRootline).attr("class","node-rootline").attr("dx",0).attr("dy",-15).attr("visibility",e=>e.readableRootline?"visible":"hidden"),e}getNodeIdentifier(e){return e.identifier}getNodeDepth(e){return e.depth}getNodeSetsize(e){return e.siblingsCount}getNodePositionInSet(e){return e.siblingsPosition}getNodeStateIdentifier(e){return e.stateIdentifier}getNodeLabel(e){return(e.prefix||"")+e.name+(e.suffix||"")}getNodeClass(e){return"node identifier-"+e.stateIdentifier}getNodeByIdentifier(e){return this.nodes.find(t=>t.stateIdentifier===e)}getNodeBgClass(e,t,s){let i="node-bg",r=null,n=null;return"object"==typeof s&&(r=s.data()[t-1],n=s.data()[t+1]),e.checked&&(i+=" node-selected"),(r&&e.depth>r.depth||!r)&&(e.firstChild=!0,i+=" node-first-child"),(n&&e.depth>n.depth||!n)&&(e.lastChild=!0,i+=" node-last-child"),e.class&&(i+=" "+e.class),i}getNodeTitle(e){return e.tip?e.tip:"uid="+e.identifier}getChevronTransform(e){return e.expanded?"translate(16,0) rotate(90)":" rotate(0)"}getChevronColor(e){return e.expanded?"#000":"#8e8e8e"}getToggleVisibility(e){return e.hasChildren?"visible":"hidden"}getChevronClass(e){return"chevron "+(e.expanded?"expanded":"collapsed")}getLinkPath(e){const t=e.target.x,s=e.target.y,i=[];return i.push("M"+e.source.x+" "+e.source.y),i.push("V"+s),e.target.hasChildren?i.push("H"+(t-2)):i.push("H"+(t+this.settings.indentWidth/4-2)),i.join(" ")}getNodeTransform(e){return"translate("+(e.x||0)+","+(e.y||0)+")"}getNodeBgTransform(e){return"translate(-8, "+((e.y||0)-10)+")"}clickOnIcon(e){this.dispatch.call("nodeRightClick",this,e)}chevronClick(e){e.expanded?this.hideChildren(e):this.showChildren(e),this.prepareDataForVisibleNodes(),this.updateVisibleNodes()}updateScrollPosition(){this.viewportHeight=this.wrapper.getBoundingClientRect().height,this.scrollTop=this.wrapper.scrollTop,this.scrollBottom=this.scrollTop+this.viewportHeight+this.viewportHeight/2,h.hide(this.wrapper.querySelectorAll("[data-bs-toggle=tooltip]"))}onMouseOverNode(e){e.isOver=!0,this.hoveredNode=e;let t=this.svg.select('.nodes-bg .node-bg[data-state-id="'+e.stateIdentifier+'"]');t.size()&&t.classed("node-over",!0).attr("rx","3").attr("ry","3")}onMouseOutOfNode(e){e.isOver=!1,this.hoveredNode=null;let t=this.svg.select('.nodes-bg .node-bg[data-state-id="'+e.stateIdentifier+'"]');t.size()&&t.classed("node-over node-alert",!1).attr("rx","0").attr("ry","0")}handleKeyboardInteraction(e){const t=e.target;let s=r.select(t).datum();if(-1===[d.KeyTypesEnum.ENTER,d.KeyTypesEnum.SPACE,d.KeyTypesEnum.END,d.KeyTypesEnum.HOME,d.KeyTypesEnum.LEFT,d.KeyTypesEnum.UP,d.KeyTypesEnum.RIGHT,d.KeyTypesEnum.DOWN].indexOf(e.keyCode))return;e.preventDefault();const i=t.parentNode;switch(e.keyCode){case d.KeyTypesEnum.END:this.scrollTop=this.wrapper.lastElementChild.getBoundingClientRect().height+this.settings.nodeHeight-this.viewportHeight,i.scrollIntoView({behavior:"smooth",block:"end"}),this.updateVisibleNodes(),this.switchFocus(i.lastElementChild);break;case d.KeyTypesEnum.HOME:this.scrollTop=this.nodes[0].y,this.wrapper.scrollTo({top:this.scrollTop,behavior:"smooth"}),this.prepareDataForVisibleNodes(),this.updateVisibleNodes(),this.switchFocus(i.firstElementChild);break;case d.KeyTypesEnum.LEFT:if(s.expanded)s.hasChildren&&(this.hideChildren(s),this.prepareDataForVisibleNodes(),this.updateVisibleNodes());else if(s.parents.length>0){let e=this.nodes[s.parents[0]];this.scrollNodeIntoVisibleArea(e,"up"),this.switchFocusNode(e)}break;case d.KeyTypesEnum.UP:this.scrollNodeIntoVisibleArea(s,"up"),this.switchFocus(t.previousSibling);break;case d.KeyTypesEnum.RIGHT:s.expanded?(this.scrollNodeIntoVisibleArea(s,"down"),this.switchFocus(t.nextSibling)):s.hasChildren&&(this.showChildren(s),this.prepareDataForVisibleNodes(),this.updateVisibleNodes(),this.switchFocus(t));break;case d.KeyTypesEnum.DOWN:this.scrollNodeIntoVisibleArea(s,"down"),this.switchFocus(t.nextSibling);break;case d.KeyTypesEnum.ENTER:case d.KeyTypesEnum.SPACE:this.selectNode(s)}}scrollNodeIntoVisibleArea(e,t="up"){if("up"===t&&this.scrollTop>e.y-this.settings.nodeHeight)this.scrollTop=e.y-this.settings.nodeHeight;else{if(!("down"===t&&this.scrollTop+this.viewportHeight<=e.y+3*this.settings.nodeHeight))return;this.scrollTop=this.scrollTop+this.settings.nodeHeight}this.wrapper.scrollTo({top:this.scrollTop,behavior:"smooth"}),this.updateVisibleNodes()}updateLinks(){const e=this.data.links.filter(e=>e.source.y<=this.scrollBottom&&e.target.y>=this.scrollTop-this.settings.nodeHeight).map(e=>(e.source.owns=e.source.owns||[],e.source.owns.push("identifier-"+e.target.stateIdentifier),e)),t=this.linksContainer.selectAll(".link").data(e);t.exit().remove(),t.enter().append("path").attr("class","link").attr("id",this.getGroupIdentifier).attr("role",e=>1===e.target.siblingsPosition&&e.source.owns.length>0?"group":null).attr("aria-owns",e=>1===e.target.siblingsPosition&&e.source.owns.length>0?e.source.owns.join(" "):null).merge(t).attr("d",e=>this.getLinkPath(e))}getGroupIdentifier(e){return 1===e.target.siblingsPosition?"group-identifier-"+e.source.stateIdentifier:null}enterSvgElements(e){if(this.textPosition=10,this.settings.showIcons){const e=Object.values(this.icons).filter(e=>""!==e.icon),t=this.iconsContainer.selectAll(".icon-def").data(e,e=>e.identifier);t.exit().remove(),t.enter().append("g").attr("class","icon-def").attr("id",e=>"icon-"+e.identifier).append(e=>{const t=new DOMParser,s='<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">'+e.icon.replace("<svg","<g").replace("/svg>","/g>")+"</svg>";return t.parseFromString(s,"image/svg+xml").documentElement.firstChild})}const t=this.nodesUpdate(e);let s=t.append("g").attr("class","toggle").attr("visibility",this.getToggleVisibility).attr("transform","translate(-8, -8)").on("click",(e,t)=>this.chevronClick(t));if(s.append("path").style("opacity",0).attr("d","M 0 0 L 16 0 L 16 16 L 0 16 Z"),s.append("path").attr("class","chevron").attr("d","M 4 3 L 13 8 L 4 13 Z"),this.settings.showIcons){this.textPosition=30;const e=t.append("g").attr("class","node-icon-container").attr("title",this.getNodeTitle).attr("data-bs-toggle","tooltip").on("click",(e,t)=>{this.clickOnIcon(t)});e.append("use").attr("class","node-icon").attr("data-uid",this.getNodeIdentifier).attr("transform","translate(8, -8)"),e.append("use").attr("transform","translate(8, -3)").attr("class","node-icon-overlay"),e.append("use").attr("x",27).attr("y",-7).attr("class","node-icon-locked")}return h.initialize('[data-bs-toggle="tooltip"]',{delay:{show:50,hide:50},trigger:"hover",placement:"right"}),this.dispatch.call("updateSvg",this,t),this.appendTextElement(t),e.merge(t)}}})); \ No newline at end of file diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/Tree/DragDrop.js b/typo3/sysext/backend/Resources/Public/JavaScript/Tree/DragDrop.js index e3c5424eaf3f..f45a9ec5edb3 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/Tree/DragDrop.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/Tree/DragDrop.js @@ -20,4 +20,4 @@ var __createBinding=this&&this.__createBinding||(Object.create?function(e,t,s,o) </span> <span class="node-dd__name">${t}</span> </div> - </div>`}}.get(e,t));d.after(...n),null===(r=this.tree.svg.node().querySelector(".nodes-wrapper"))||void 0===r||r.classList.add("nodes-wrapper--dragging")}updateDraggablePosition(e){let t=18,s=15;e.sourceEvent&&e.sourceEvent.pageX&&(t+=e.sourceEvent.pageX),e.sourceEvent&&e.sourceEvent.pageY&&(s+=e.sourceEvent.pageY),document.querySelectorAll(".node-dd").forEach(e=>{e.style.top=s+"px",e.style.left=t+"px",e.style.display="block"})}openNodeTimeout(){null!==this.tree.hoveredNode&&this.tree.hoveredNode.hasChildren&&!this.tree.hoveredNode.expanded?this.timeout.node!=this.tree.hoveredNode&&(this.timeout.node=this.tree.hoveredNode,clearTimeout(this.timeout.time),this.timeout.time=setTimeout(()=>{this.tree.hoveredNode&&(this.tree.showChildren(this.tree.hoveredNode),this.tree.prepareDataForVisibleNodes(),this.tree.update())},1e3)):clearTimeout(this.timeout.time)}changeNodeClasses(e){const t=this.tree.svg.select(".node-over"),s=this.tree.svg.node().parentNode.querySelector(".node-dd");let o=this.tree.nodesBgContainer.selectAll(".node-bg__border");if(t.size()&&this.tree.isOverSvg){o.empty()&&(o=this.tree.nodesBgContainer.append("rect").attr("class","node-bg__border").attr("height","1px").attr("width","100%"));let r=d.pointer(e,t.node())[1];if(r<3){o.attr("transform","translate(-8, "+(this.tree.hoveredNode.y-10)+")").style("display","block"),0===this.tree.hoveredNode.depth?this.addNodeDdClass(s,"nodrop"):this.tree.hoveredNode.firstChild?this.addNodeDdClass(s,"ok-above"):this.addNodeDdClass(s,"ok-between"),this.tree.settings.nodeDragPosition=n.BEFORE}else if(r>17)if(o.style("display","none"),this.tree.hoveredNode.expanded&&this.tree.hoveredNode.hasChildren)this.addNodeDdClass(s,"ok-append"),this.tree.settings.nodeDragPosition=n.INSIDE;else{o.attr("transform","translate(-8, "+(this.tree.hoveredNode.y+10)+")").style("display","block"),this.tree.hoveredNode.lastChild?this.addNodeDdClass(s,"ok-below"):this.addNodeDdClass(s,"ok-between"),this.tree.settings.nodeDragPosition=n.AFTER}else o.style("display","none"),this.addNodeDdClass(s,"ok-append"),this.tree.settings.nodeDragPosition=n.INSIDE}else this.tree.nodesBgContainer.selectAll(".node-bg__border").style("display","none"),this.addNodeDdClass(s,"nodrop")}addNodeDdClass(e,t){const s=this.tree.svg.node().querySelector(".nodes-wrapper");e&&this.applyNodeClassNames(e,"node-dd--",t),s&&this.applyNodeClassNames(s,"nodes-wrapper--",t),this.tree.settings.canNodeDrag="nodrop"!==t}removeNodeDdClass(){var e;const t=this.tree.svg.node().querySelector(".nodes-wrapper");["nodes-wrapper--nodrop","nodes-wrapper--ok-append","nodes-wrapper--ok-below","nodes-wrapper--ok-between","nodes-wrapper--ok-above","nodes-wrapper--dragging"].forEach(e=>t.classList.remove(e)),null===(e=this.tree.nodesBgContainer.node().querySelector(".node-bg.node-bg--dragging"))||void 0===e||e.classList.remove("node-bg--dragging"),this.tree.nodesBgContainer.selectAll(".node-bg__border").style("display","none"),this.tree.svg.node().parentNode.querySelector(".node-dd").remove()}isDragNodeDistanceMore(e,t){return t.startDrag||t.startPageX-this.minimalDistance>e.sourceEvent.pageX||t.startPageX+this.minimalDistance<e.sourceEvent.pageX||t.startPageY-this.minimalDistance>e.sourceEvent.pageY||t.startPageY+this.minimalDistance<e.sourceEvent.pageY}applyNodeClassNames(e,t,s){["nodrop","ok-append","ok-below","ok-between","ok-above","dragging"].forEach(s=>e.classList.remove(t+s)),e.classList.add(t+s)}}t.DragDrop=a})); \ No newline at end of file + </div>`}}.get(e,t));d.after(...n),null===(r=this.tree.svg.node().querySelector(".nodes-wrapper"))||void 0===r||r.classList.add("nodes-wrapper--dragging")}updateDraggablePosition(e){let t=18,s=15;e.sourceEvent&&e.sourceEvent.pageX&&(t+=e.sourceEvent.pageX),e.sourceEvent&&e.sourceEvent.pageY&&(s+=e.sourceEvent.pageY),document.querySelectorAll(".node-dd").forEach(e=>{e.style.top=s+"px",e.style.left=t+"px",e.style.display="block"})}openNodeTimeout(){null!==this.tree.hoveredNode&&this.tree.hoveredNode.hasChildren&&!this.tree.hoveredNode.expanded?this.timeout.node!=this.tree.hoveredNode&&(this.timeout.node=this.tree.hoveredNode,clearTimeout(this.timeout.time),this.timeout.time=setTimeout(()=>{this.tree.hoveredNode&&(this.tree.showChildren(this.tree.hoveredNode),this.tree.prepareDataForVisibleNodes(),this.tree.updateVisibleNodes())},1e3)):clearTimeout(this.timeout.time)}changeNodeClasses(e){const t=this.tree.svg.select(".node-over"),s=this.tree.svg.node().parentNode.querySelector(".node-dd");let o=this.tree.nodesBgContainer.selectAll(".node-bg__border");if(t.size()&&this.tree.isOverSvg){o.empty()&&(o=this.tree.nodesBgContainer.append("rect").attr("class","node-bg__border").attr("height","1px").attr("width","100%"));let r=d.pointer(e,t.node())[1];if(r<3){o.attr("transform","translate(-8, "+(this.tree.hoveredNode.y-10)+")").style("display","block"),0===this.tree.hoveredNode.depth?this.addNodeDdClass(s,"nodrop"):this.tree.hoveredNode.firstChild?this.addNodeDdClass(s,"ok-above"):this.addNodeDdClass(s,"ok-between"),this.tree.settings.nodeDragPosition=n.BEFORE}else if(r>17)if(o.style("display","none"),this.tree.hoveredNode.expanded&&this.tree.hoveredNode.hasChildren)this.addNodeDdClass(s,"ok-append"),this.tree.settings.nodeDragPosition=n.INSIDE;else{o.attr("transform","translate(-8, "+(this.tree.hoveredNode.y+10)+")").style("display","block"),this.tree.hoveredNode.lastChild?this.addNodeDdClass(s,"ok-below"):this.addNodeDdClass(s,"ok-between"),this.tree.settings.nodeDragPosition=n.AFTER}else o.style("display","none"),this.addNodeDdClass(s,"ok-append"),this.tree.settings.nodeDragPosition=n.INSIDE}else this.tree.nodesBgContainer.selectAll(".node-bg__border").style("display","none"),this.addNodeDdClass(s,"nodrop")}addNodeDdClass(e,t){const s=this.tree.svg.node().querySelector(".nodes-wrapper");e&&this.applyNodeClassNames(e,"node-dd--",t),s&&this.applyNodeClassNames(s,"nodes-wrapper--",t),this.tree.settings.canNodeDrag="nodrop"!==t}removeNodeDdClass(){var e;const t=this.tree.svg.node().querySelector(".nodes-wrapper");["nodes-wrapper--nodrop","nodes-wrapper--ok-append","nodes-wrapper--ok-below","nodes-wrapper--ok-between","nodes-wrapper--ok-above","nodes-wrapper--dragging"].forEach(e=>t.classList.remove(e)),null===(e=this.tree.nodesBgContainer.node().querySelector(".node-bg.node-bg--dragging"))||void 0===e||e.classList.remove("node-bg--dragging"),this.tree.nodesBgContainer.selectAll(".node-bg__border").style("display","none"),this.tree.svg.node().parentNode.querySelector(".node-dd").remove()}isDragNodeDistanceMore(e,t){return t.startDrag||t.startPageX-this.minimalDistance>e.sourceEvent.pageX||t.startPageX+this.minimalDistance<e.sourceEvent.pageX||t.startPageY-this.minimalDistance>e.sourceEvent.pageY||t.startPageY+this.minimalDistance<e.sourceEvent.pageY}applyNodeClassNames(e,t,s){["nodrop","ok-append","ok-below","ok-between","ok-above","dragging"].forEach(s=>e.classList.remove(t+s)),e.classList.add(t+s)}}t.DragDrop=a})); \ No newline at end of file diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/Tree/FileStorageTree.js b/typo3/sysext/backend/Resources/Public/JavaScript/Tree/FileStorageTree.js index 734559732e69..02ec9393622a 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/Tree/FileStorageTree.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/Tree/FileStorageTree.js @@ -10,4 +10,4 @@ * * The TYPO3 project - inspiring people to share! */ -var __importDefault=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};define(["require","exports","TYPO3/CMS/Core/Ajax/AjaxRequest","../SvgTree","../ContextMenu","../Storage/Persistent","./FileStorageTreeActions"],(function(e,t,i,r,d,o,s){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.FileStorageTree=void 0,i=__importDefault(i),o=__importDefault(o);class n extends r.SvgTree{constructor(){super(),this.networkErrorTitle=TYPO3.lang.tree_networkError,this.networkErrorMessage=TYPO3.lang.tree_networkErrorDescription,this.settings.defaultProperties={hasChildren:!1,nameSourceField:"title",itemType:"sys_file",prefix:"",suffix:"",locked:!1,loaded:!1,overlayIcon:"",selectable:!0,expanded:!1,checked:!1,backgroundColor:"",class:"",readableRootline:""},this.dispatch.on("nodeSelectedAfter.fileStorageTree",e=>this.nodeSelectedAfter(e)),this.dispatch.on("nodeRightClick.fileStorageTree",e=>this.nodeRightClick(e)),this.dispatch.on("prepareLoadedNode.fileStorageTree",e=>this.prepareLoadedNode(e))}initialize(e,t,i){super.initialize(e,t),this.actionHandler=i}hideChildren(e){super.hideChildren(e),o.default.set("BackendComponents.States.FileStorageTree.stateHash."+e.stateIdentifier,"0")}showChildren(e){this.loadChildrenOfNode(e),super.showChildren(e),o.default.set("BackendComponents.States.FileStorageTree.stateHash."+e.stateIdentifier,"1")}updateNodeBgClass(e){return super.updateNodeBgClass.call(this,e).call(this.initializeDragForNode())}nodesUpdate(e){return super.nodesUpdate.call(this,e).call(this.initializeDragForNode())}selectNode(e){this.isNodeSelectable(e)&&(this.getSelectedNodes().forEach(e=>{!0===e.checked&&(e.checked=!1,this.dispatch.call("nodeSelectedAfter",this,e))}),e.checked=!0,this.dispatch.call("nodeSelectedAfter",this,e),this.update())}selectNodeByIdentifier(e){e=encodeURIComponent(e);let t=this.nodes.filter(t=>t.identifier===e)[0];t&&0===this.getSelectedNodes().filter(e=>e.identifier===t.identifier).length&&this.selectNode(t)}initializeDragForNode(){return this.actionHandler.connectDragHandler(new s.FileStorageTreeNodeDragHandler(this,this.actionHandler))}getNodeTitle(e){return decodeURIComponent(e.name)}loadChildrenOfNode(e){if(e.loaded)return this.prepareDataForVisibleNodes(),void this.update();this.nodesAddPlaceholder(),new i.default(this.settings.dataUrl+"&parent="+e.identifier+"¤tDepth="+e.depth).get({cache:"no-cache"}).then(e=>e.resolve()).then(t=>{let i=Array.isArray(t)?t:[];const r=this.nodes.indexOf(e)+1;i.forEach((e,t)=>{this.nodes.splice(r+t,0,e)}),e.loaded=!0,this.setParametersNode(),this.prepareDataForVisibleNodes(),this.update(),this.nodesRemovePlaceholder(),this.switchFocusNode(e)}).catch(e=>{throw this.errorNotification(e,!1),this.nodesRemovePlaceholder(),e})}nodeSelectedAfter(e){if(!e.checked)return;window.fsMod.recentIds.file=e.identifier,window.fsMod.navFrameHighlightedID.file=e.stateIdentifier;const t=-1!==window.currentSubScript.indexOf("?")?"&":"?";TYPO3.Backend.ContentContainer.setUrl(window.currentSubScript+t+"id="+e.identifier)}nodeRightClick(e){d.show(e.itemType,decodeURIComponent(e.identifier),"tree","","",this.getNodeElement(e))}prepareLoadedNode(e){e.stateIdentifier===window.fsMod.navFrameHighlightedID.file&&(e.checked=!0)}}t.FileStorageTree=n})); \ No newline at end of file +var __importDefault=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};define(["require","exports","TYPO3/CMS/Core/Ajax/AjaxRequest","../SvgTree","../ContextMenu","../Storage/Persistent","./FileStorageTreeActions"],(function(e,t,i,r,d,o,s){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.FileStorageTree=void 0,i=__importDefault(i),o=__importDefault(o);class n extends r.SvgTree{constructor(){super(),this.networkErrorTitle=TYPO3.lang.tree_networkError,this.networkErrorMessage=TYPO3.lang.tree_networkErrorDescription,this.settings.defaultProperties={hasChildren:!1,nameSourceField:"title",itemType:"sys_file",prefix:"",suffix:"",locked:!1,loaded:!1,overlayIcon:"",selectable:!0,expanded:!1,checked:!1,backgroundColor:"",class:"",readableRootline:""},this.dispatch.on("nodeSelectedAfter.fileStorageTree",e=>this.nodeSelectedAfter(e)),this.dispatch.on("nodeRightClick.fileStorageTree",e=>this.nodeRightClick(e)),this.dispatch.on("prepareLoadedNode.fileStorageTree",e=>this.prepareLoadedNode(e))}initialize(e,t,i){super.initialize(e,t),this.actionHandler=i}hideChildren(e){super.hideChildren(e),o.default.set("BackendComponents.States.FileStorageTree.stateHash."+e.stateIdentifier,"0")}showChildren(e){this.loadChildrenOfNode(e),super.showChildren(e),o.default.set("BackendComponents.States.FileStorageTree.stateHash."+e.stateIdentifier,"1")}updateNodeBgClass(e){return super.updateNodeBgClass.call(this,e).call(this.initializeDragForNode())}nodesUpdate(e){return super.nodesUpdate.call(this,e).call(this.initializeDragForNode())}selectNode(e){this.isNodeSelectable(e)&&(this.disableSelectedNodes(),e.checked=!0,this.dispatch.call("nodeSelectedAfter",this,e),this.updateVisibleNodes())}selectNodeByIdentifier(e){e=encodeURIComponent(e);let t=this.nodes.filter(t=>t.identifier===e)[0];t&&0===this.getSelectedNodes().filter(e=>e.identifier===t.identifier).length&&this.selectNode(t)}initializeDragForNode(){return this.actionHandler.connectDragHandler(new s.FileStorageTreeNodeDragHandler(this,this.actionHandler))}getNodeTitle(e){return decodeURIComponent(e.name)}loadChildrenOfNode(e){if(e.loaded)return this.prepareDataForVisibleNodes(),void this.updateVisibleNodes();this.nodesAddPlaceholder(),new i.default(this.settings.dataUrl+"&parent="+e.identifier+"¤tDepth="+e.depth).get({cache:"no-cache"}).then(e=>e.resolve()).then(t=>{let i=Array.isArray(t)?t:[];const r=this.nodes.indexOf(e)+1;i.forEach((e,t)=>{this.nodes.splice(r+t,0,e)}),e.loaded=!0,this.setParametersNode(),this.prepareDataForVisibleNodes(),this.updateVisibleNodes(),this.nodesRemovePlaceholder(),this.switchFocusNode(e)}).catch(e=>{throw this.errorNotification(e,!1),this.nodesRemovePlaceholder(),e})}nodeSelectedAfter(e){if(!e.checked)return;window.fsMod.recentIds.file=e.identifier,window.fsMod.navFrameHighlightedID.file=e.stateIdentifier;const t=-1!==window.currentSubScript.indexOf("?")?"&":"?";TYPO3.Backend.ContentContainer.setUrl(window.currentSubScript+t+"id="+e.identifier)}nodeRightClick(e){d.show(e.itemType,decodeURIComponent(e.identifier),"tree","","",this.getNodeElement(e))}prepareLoadedNode(e){e.stateIdentifier===window.fsMod.navFrameHighlightedID.file&&(e.checked=!0)}}t.FileStorageTree=n})); \ No newline at end of file diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/Tree/FileStorageTreeActions.js b/typo3/sysext/backend/Resources/Public/JavaScript/Tree/FileStorageTreeActions.js index 33e441355181..c7f6e5191b4b 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/Tree/FileStorageTreeActions.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/Tree/FileStorageTreeActions.js @@ -10,4 +10,4 @@ * * The TYPO3 project - inspiring people to share! */ -var __importDefault=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};define(["require","exports","./DragDrop","../Modal","../Severity","../Notification","TYPO3/CMS/Core/Ajax/AjaxRequest"],(function(e,t,s,r,i,n,o){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.FileStorageTreeNodeDragHandler=t.FileStorageTreeActions=void 0,o=__importDefault(o);class a extends s.DragDrop{changeNodePosition(e){const t=this.tree.nodes,r=this.tree.settings.nodeDrag.identifier;let i=this.tree.settings.nodeDragPosition,n=e||this.tree.settings.nodeDrag;if(r===n.identifier)return null;if(i===s.DraggablePositionEnum.BEFORE){const s=t.indexOf(e),r=this.setNodePositionAndTarget(s);if(null===r)return null;i=r.position,n=r.target}return{node:this.tree.settings.nodeDrag,identifier:r,target:n,position:i}}setNodePositionAndTarget(e){const t=this.tree.nodes,r=t[e].depth;e>0&&e--;const i=t[e].depth,n=this.tree.nodes[e];if(i===r)return{position:s.DraggablePositionEnum.AFTER,target:n};if(i<r)return{position:s.DraggablePositionEnum.INSIDE,target:n};for(let i=e;i>=0;i--){if(t[i].depth===r)return{position:s.DraggablePositionEnum.AFTER,target:this.tree.nodes[i]};if(t[i].depth<r)return{position:s.DraggablePositionEnum.AFTER,target:t[i]}}return null}changeNodeClasses(e){const t=this.tree.svg.select(".node-over"),r=this.tree.svg.node().parentNode.querySelector(".node-dd");t.size()&&this.tree.isOverSvg&&(this.tree.nodesBgContainer.selectAll(".node-bg__border").style("display","none"),this.addNodeDdClass(r,"ok-append"),this.tree.settings.nodeDragPosition=s.DraggablePositionEnum.INSIDE)}}t.FileStorageTreeActions=a;t.FileStorageTreeNodeDragHandler=class{constructor(e,t){this.startDrag=!1,this.startPageX=0,this.startPageY=0,this.isDragged=!1,this.tree=e,this.actionHandler=t}dragStart(e){return 0!==e.subject.depth&&(this.startPageX=e.sourceEvent.pageX,this.startPageY=e.sourceEvent.pageY,this.startDrag=!1,!0)}dragDragged(e){let t=e.subject;if(!this.actionHandler.isDragNodeDistanceMore(e,this))return!1;if(this.startDrag=!0,0===t.depth)return!1;this.tree.settings.nodeDrag=t;let s=this.tree.svg.node().querySelector('.node-bg[data-state-id="'+t.stateIdentifier+'"]'),r=this.tree.svg.node().parentNode.querySelector(".node-dd");return this.isDragged||(this.isDragged=!0,this.actionHandler.createDraggable(this.tree.getIconId(t),t.name),null==s||s.classList.add("node-bg--dragging")),this.tree.settings.nodeDragPosition=!1,this.actionHandler.openNodeTimeout(),this.actionHandler.updateDraggablePosition(e),(t.isOver||this.tree.hoveredNode&&-1!==this.tree.hoveredNode.parentsStateIdentifier.indexOf(t.stateIdentifier)||!this.tree.isOverSvg)&&(this.actionHandler.addNodeDdClass(r,"nodrop"),this.tree.isOverSvg||this.tree.nodesBgContainer.selectAll(".node-bg__border").style("display","none")),!this.tree.hoveredNode||this.isInSameParentNode(t,this.tree.hoveredNode)?(this.actionHandler.addNodeDdClass(r,"nodrop"),this.tree.nodesBgContainer.selectAll(".node-bg__border").style("display","none")):this.actionHandler.changeNodeClasses(e),!0}isInSameParentNode(e,t){return e.parentsStateIdentifier[0]==t.parentsStateIdentifier[0]||e.parentsStateIdentifier[0]==t.stateIdentifier}dragEnd(e){let t=e.subject;if(!this.startDrag||0===t.depth)return!1;let n=this.tree.hoveredNode;if(this.isDragged=!1,this.actionHandler.removeNodeDdClass(),!(t.isOver||n&&-1!==n.parentsStateIdentifier.indexOf(t.stateIdentifier))&&this.tree.settings.canNodeDrag&&this.tree.isOverSvg){let e=this.actionHandler.changeNodePosition(n),t=e.position===s.DraggablePositionEnum.INSIDE?TYPO3.lang["mess.move_into"]:TYPO3.lang["mess.move_after"];t=t.replace("%s",e.node.name).replace("%s",e.target.name),r.confirm(TYPO3.lang.move_folder,t,i.warning,[{text:TYPO3.lang["labels.cancel"]||"Cancel",active:!0,btnClass:"btn-default",name:"cancel"},{text:TYPO3.lang["cm.copy"]||"Copy",btnClass:"btn-warning",name:"copy"},{text:TYPO3.lang["labels.move"]||"Move",btnClass:"btn-warning",name:"move"}]).on("button.clicked",t=>{const s=t.target;"move"===s.name?this.sendChangeCommand("move",e):"copy"===s.name&&this.sendChangeCommand("copy",e),r.dismiss()})}return!0}sendChangeCommand(e,t){let s={data:{}};if("copy"===e)s.data.copy=[],s.copy.push({data:decodeURIComponent(t.identifier),target:decodeURIComponent(t.target.identifier)});else{if("move"!==e)return;s.data.move=[],s.data.move.push({data:decodeURIComponent(t.identifier),target:decodeURIComponent(t.target.identifier)})}this.tree.nodesAddPlaceholder(),new o.default(top.TYPO3.settings.ajaxUrls.file_process+"&includeMessages=1").post(s).then(e=>e.resolve()).then(e=>{e&&e.hasErrors?(this.tree.errorNotification(e.messages,!1),this.tree.nodesContainer.selectAll(".node").remove(),this.tree.update(),this.tree.nodesRemovePlaceholder()):(e.messages&&e.messages.forEach(e=>{n.showMessage(e.title||"",e.message||"",e.severity)}),this.tree.refreshOrFilterTree())}).catch(e=>{this.tree.errorNotification(e,!0)})}}})); \ No newline at end of file +var __importDefault=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};define(["require","exports","./DragDrop","../Modal","../Severity","../Notification","TYPO3/CMS/Core/Ajax/AjaxRequest"],(function(e,t,s,r,i,n,o){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.FileStorageTreeNodeDragHandler=t.FileStorageTreeActions=void 0,o=__importDefault(o);class a extends s.DragDrop{changeNodePosition(e){const t=this.tree.nodes,r=this.tree.settings.nodeDrag.identifier;let i=this.tree.settings.nodeDragPosition,n=e||this.tree.settings.nodeDrag;if(r===n.identifier)return null;if(i===s.DraggablePositionEnum.BEFORE){const s=t.indexOf(e),r=this.setNodePositionAndTarget(s);if(null===r)return null;i=r.position,n=r.target}return{node:this.tree.settings.nodeDrag,identifier:r,target:n,position:i}}setNodePositionAndTarget(e){const t=this.tree.nodes,r=t[e].depth;e>0&&e--;const i=t[e].depth,n=this.tree.nodes[e];if(i===r)return{position:s.DraggablePositionEnum.AFTER,target:n};if(i<r)return{position:s.DraggablePositionEnum.INSIDE,target:n};for(let i=e;i>=0;i--){if(t[i].depth===r)return{position:s.DraggablePositionEnum.AFTER,target:this.tree.nodes[i]};if(t[i].depth<r)return{position:s.DraggablePositionEnum.AFTER,target:t[i]}}return null}changeNodeClasses(e){const t=this.tree.svg.select(".node-over"),r=this.tree.svg.node().parentNode.querySelector(".node-dd");t.size()&&this.tree.isOverSvg&&(this.tree.nodesBgContainer.selectAll(".node-bg__border").style("display","none"),this.addNodeDdClass(r,"ok-append"),this.tree.settings.nodeDragPosition=s.DraggablePositionEnum.INSIDE)}}t.FileStorageTreeActions=a;t.FileStorageTreeNodeDragHandler=class{constructor(e,t){this.startDrag=!1,this.startPageX=0,this.startPageY=0,this.isDragged=!1,this.tree=e,this.actionHandler=t}dragStart(e){return 0!==e.subject.depth&&(this.startPageX=e.sourceEvent.pageX,this.startPageY=e.sourceEvent.pageY,this.startDrag=!1,!0)}dragDragged(e){let t=e.subject;if(!this.actionHandler.isDragNodeDistanceMore(e,this))return!1;if(this.startDrag=!0,0===t.depth)return!1;this.tree.settings.nodeDrag=t;let s=this.tree.svg.node().querySelector('.node-bg[data-state-id="'+t.stateIdentifier+'"]'),r=this.tree.svg.node().parentNode.querySelector(".node-dd");return this.isDragged||(this.isDragged=!0,this.actionHandler.createDraggable(this.tree.getIconId(t),t.name),null==s||s.classList.add("node-bg--dragging")),this.tree.settings.nodeDragPosition=!1,this.actionHandler.openNodeTimeout(),this.actionHandler.updateDraggablePosition(e),(t.isOver||this.tree.hoveredNode&&-1!==this.tree.hoveredNode.parentsStateIdentifier.indexOf(t.stateIdentifier)||!this.tree.isOverSvg)&&(this.actionHandler.addNodeDdClass(r,"nodrop"),this.tree.isOverSvg||this.tree.nodesBgContainer.selectAll(".node-bg__border").style("display","none")),!this.tree.hoveredNode||this.isInSameParentNode(t,this.tree.hoveredNode)?(this.actionHandler.addNodeDdClass(r,"nodrop"),this.tree.nodesBgContainer.selectAll(".node-bg__border").style("display","none")):this.actionHandler.changeNodeClasses(e),!0}isInSameParentNode(e,t){return e.parentsStateIdentifier[0]==t.parentsStateIdentifier[0]||e.parentsStateIdentifier[0]==t.stateIdentifier}dragEnd(e){let t=e.subject;if(!this.startDrag||0===t.depth)return!1;let n=this.tree.hoveredNode;if(this.isDragged=!1,this.actionHandler.removeNodeDdClass(),!(t.isOver||n&&-1!==n.parentsStateIdentifier.indexOf(t.stateIdentifier))&&this.tree.settings.canNodeDrag&&this.tree.isOverSvg){let e=this.actionHandler.changeNodePosition(n),t=e.position===s.DraggablePositionEnum.INSIDE?TYPO3.lang["mess.move_into"]:TYPO3.lang["mess.move_after"];t=t.replace("%s",e.node.name).replace("%s",e.target.name),r.confirm(TYPO3.lang.move_folder,t,i.warning,[{text:TYPO3.lang["labels.cancel"]||"Cancel",active:!0,btnClass:"btn-default",name:"cancel"},{text:TYPO3.lang["cm.copy"]||"Copy",btnClass:"btn-warning",name:"copy"},{text:TYPO3.lang["labels.move"]||"Move",btnClass:"btn-warning",name:"move"}]).on("button.clicked",t=>{const s=t.target;"move"===s.name?this.sendChangeCommand("move",e):"copy"===s.name&&this.sendChangeCommand("copy",e),r.dismiss()})}return!0}sendChangeCommand(e,t){let s={data:{}};if("copy"===e)s.data.copy=[],s.copy.push({data:decodeURIComponent(t.identifier),target:decodeURIComponent(t.target.identifier)});else{if("move"!==e)return;s.data.move=[],s.data.move.push({data:decodeURIComponent(t.identifier),target:decodeURIComponent(t.target.identifier)})}this.tree.nodesAddPlaceholder(),new o.default(top.TYPO3.settings.ajaxUrls.file_process+"&includeMessages=1").post(s).then(e=>e.resolve()).then(e=>{e&&e.hasErrors?(this.tree.errorNotification(e.messages,!1),this.tree.nodesContainer.selectAll(".node").remove(),this.tree.updateVisibleNodes(),this.tree.nodesRemovePlaceholder()):(e.messages&&e.messages.forEach(e=>{n.showMessage(e.title||"",e.message||"",e.severity)}),this.tree.refreshOrFilterTree())}).catch(e=>{this.tree.errorNotification(e,!0)})}}})); \ No newline at end of file diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/Tree/FileStorageTreeContainer.js b/typo3/sysext/backend/Resources/Public/JavaScript/Tree/FileStorageTreeContainer.js index 201779089170..176462bb1162 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/Tree/FileStorageTreeContainer.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/Tree/FileStorageTreeContainer.js @@ -15,11 +15,7 @@ var __decorate=this&&this.__decorate||function(e,t,r,i){var o,s=arguments.length <div> <typo3-backend-navigation-component-filestoragetree-toolbar .tree="${this.tree}" id="filestoragetree-toolbar" class="svg-toolbar"></typo3-backend-navigation-component-filestoragetree-toolbar> <div class="navigation-tree-container"> - <div id="typo3-filestoragetree-tree" class="svg-tree-wrapper"> - <div class="node-loader"> - <typo3-backend-icon identifier="spinner-circle-light" size="small"></typo3-backend-icon> - </div> - </div> + <div id="typo3-filestoragetree-tree" class="svg-tree-wrapper"></div> </div> </div> <div class="svg-tree-loader"> -- GitLab