Commit 13efb6b3 authored by Benni Mack's avatar Benni Mack Committed by Georg Ringer
Browse files

[TASK] Remove jQuery from Tree components

This change aims to reduce the overhead by using
jQuery in favor of Vanilla JS in various Tree-related
JS files in preparation for a TypeScript migration.

* SvgTree.js
* SelectTree.js
* PageTree.js
* PageTreeToolbar.ts
* PageTreeElement.ts
* TreeToolbar.ts

Resolves: #93427
Releases: master
Change-Id: I57fc8e66415ea4ab6eaf690d925fbf7670d74284
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/67583

Tested-by: Benjamin Franzke's avatarBenjamin Franzke <bfr@qbus.de>
Tested-by: Georg Ringer's avatarGeorg Ringer <georg.ringer@gmail.com>
Reviewed-by: Benjamin Franzke's avatarBenjamin Franzke <bfr@qbus.de>
Reviewed-by: Georg Ringer's avatarGeorg Ringer <georg.ringer@gmail.com>
parent a6bfd190
......@@ -11,7 +11,6 @@
* The TYPO3 project - inspiring people to share!
*/
import $ from 'jquery';
import {Tooltip} from 'bootstrap';
import {render} from 'lit-html';
import {html, TemplateResult} from 'lit-element';
......@@ -30,7 +29,6 @@ export class TreeToolbar
toggleHideUnchecked: 'hide-unchecked-btn'
};
private $treeWrapper: JQuery;
private treeContainer: HTMLElement;
private tree: any;
......@@ -47,15 +45,15 @@ export class TreeToolbar
public initialize(treeContainer: HTMLElement): void {
this.treeContainer = treeContainer;
this.$treeWrapper = $(treeContainer);
if (!this.$treeWrapper.data('svgtree-initialized')
|| typeof this.$treeWrapper.data('svgtree') !== 'object'
if (!this.treeContainer.dataset.svgTreeInitialized
|| typeof (this.treeContainer as any).svgtree !== 'object'
) {
//both toolbar and tree are loaded independently through require js,
//so we don't know which is loaded first
//in case of toolbar being loaded first, we wait for an event from svgTree
this.$treeWrapper.on('svgTree.initialized', () => this.render());
this.treeContainer.addEventListener('svg-tree:initialized', this.render.bind(this));
return;
}
......@@ -137,7 +135,8 @@ export class TreeToolbar
}
private render(): void {
this.tree = this.$treeWrapper.data('svgtree');
this.tree = (this.treeContainer as any).svgtree;
// @todo Better use initialize() settings, drop this assignment here
Object.assign(this.settings, this.tree.settings);
......
......@@ -11,7 +11,6 @@
* The TYPO3 project - inspiring people to share!
*/
import $ from 'jquery';
import {render} from 'lit-html';
import {html, TemplateResult} from 'lit-element';
import {icon} from 'TYPO3/CMS/Core/lit-helper';
......@@ -29,19 +28,13 @@ export class PageTreeElement {
const targetEl = document.querySelector(selector);
// let SvgTree know it shall be visible
// @todo Replace jQuery event with CustomEvent
if (targetEl && targetEl.childNodes.length > 0) {
$('.svg-tree', targetEl).trigger('isVisible');
targetEl.querySelector('.svg-tree').dispatchEvent(new Event('svg-tree:visible'));
return;
}
render(PageTreeElement.renderTemplate(), targetEl);
const treeEl = targetEl.querySelector('.svg-tree-wrapper');
// Ensure tooltips don't stay when scrolling the pagetree
$(treeEl).on('scroll', () => {
$(treeEl).find('[data-bs-toggle=tooltip]').tooltip('hide');
});
const treeEl = <HTMLElement>targetEl.querySelector('.svg-tree-wrapper');
const tree = new PageTree();
const configurationUrl = top.TYPO3.settings.ajaxUrls.page_tree_configuration;
......@@ -61,7 +54,7 @@ export class PageTreeElement {
const toolbar = <HTMLElement>targetEl.querySelector('.svg-toolbar');
if (!toolbar.dataset.treeShowToolbar) {
const pageTreeToolbar = new PageTreeToolbar();
pageTreeToolbar.initialize('#typo3-pagetree-tree', toolbar);
pageTreeToolbar.initialize(treeEl, toolbar);
toolbar.dataset.treeShowToolbar = 'true';
}
});
......
......@@ -13,7 +13,6 @@
/** @ts-ignore */
import {select as d3select} from 'd3-selection';
import $ from 'jquery';
import {render} from 'lit-html';
import {html, TemplateResult} from 'lit-element';
import {icon, lll} from 'TYPO3/CMS/Core/lit-helper';
......@@ -31,28 +30,27 @@ export class PageTreeToolbar
filterTimeout: 450
};
private $treeWrapper: JQuery;
private treeContainer: any;
private targetEl: HTMLElement;
private tree: any;
private dragDrop: any;
private hideUncheckedState = false;
public constructor() {
this.dragDrop = pageTreeDragDrop;
}
public initialize(treeSelector: string, toolbar: HTMLElement, settings: any = {}): void {
this.$treeWrapper = $(treeSelector);
public initialize(treeContainer: HTMLElement, toolbar: HTMLElement, settings: any = {}): void {
this.treeContainer = treeContainer;
this.targetEl = toolbar;
if (!this.$treeWrapper.data('svgtree-initialized')
|| typeof this.$treeWrapper.data('svgtree') !== 'object'
if (!this.treeContainer.dataset.svgTreeInitialized
|| typeof this.treeContainer.svgtree !== 'object'
) {
//both toolbar and tree are loaded independently through require js,
//so we don't know which is loaded first
//in case of toolbar being loaded first, we wait for an event from svgTree
this.$treeWrapper.on('svgTree.initialized', () => this.render());
this.treeContainer.addEventListener('svg-tree:initialized', () => this.render());
return;
}
......@@ -65,52 +63,12 @@ export class PageTreeToolbar
}
private search(inputEl: HTMLInputElement): void {
this.tree.searchQuery = inputEl.value.trim()
this.tree.searchQuery = inputEl.value.trim()
this.tree.refreshOrFilterTree();
this.tree.prepareDataForVisibleNodes();
this.tree.update();
}
/**
* Show only checked items
* @todo Not sure, whether this is actually used
*/
private toggleHideUnchecked(inputEl: HTMLElement): void {
this.hideUncheckedState = !this.hideUncheckedState;
if (this.hideUncheckedState) {
this.tree.nodes.forEach((node: any) => {
if (node.checked) {
this.showParents(node);
node.expanded = true;
node.hidden = false;
} else {
node.hidden = true;
node.expanded = false;
}
});
} else {
this.tree.nodes.forEach((node: any) => {
node.hidden = false;
});
}
this.tree.prepareDataForVisibleNodes();
this.tree.update();
}
/**
* Finds and show all parents of node
*/
private showParents(node: any): void {
if (node.parents.length === 0) {
return;
}
const parent = this.tree.nodes[node.parents[0]];
parent.hidden = false;
//expand parent node
parent.expanded = true;
this.showParents(parent);
}
private showSubmenu(name: string): void {
// @todo Replace those states with real data-binding in lit-element
this.targetEl.querySelectorAll('[data-tree-show-submenu]')
......@@ -145,14 +103,14 @@ export class PageTreeToolbar
private render(): void
{
this.tree = this.$treeWrapper.data('svgtree');
this.tree = this.treeContainer.svgtree;
// @todo Better use initialize() settings, drop this assignment here
Object.assign(this.settings, this.tree.settings);
render(this.renderTemplate(), this.targetEl);
const d3Toolbar = d3select('.svg-toolbar');
$.each(this.tree.settings.doktypes, (id: number, item: any) => {
this.tree.settings.doktypes.forEach((item: any, id: number) => {
if (item.icon) {
d3Toolbar
.selectAll('[data-tree-icon=' + item.icon + ']')
......@@ -167,8 +125,6 @@ export class PageTreeToolbar
}, this.settings.filterTimeout)
.bindTo(this.targetEl.querySelector(this.settings.searchInput));
$(this.targetEl).find('[data-bs-toggle="tooltip"]').tooltip();
// @todo That always was a hack, to be replace with proper internal state handling
const newPageSubmenu = this.targetEl.querySelector('[data-tree-show-submenu="page-new"]') as HTMLButtonElement;
const firstToolbarButton = this.targetEl.querySelector('.svg-toolbar__menu :first-child:not(.js-svg-refresh)') as HTMLButtonElement;
......
......@@ -33,25 +33,25 @@ class Tooltip {
}
/**
* Show tooltip on $element
* Show tooltip on element(s)
*
* @param {Object} $element
* @param {Object} elements
* @param {String} title
*/
public show($element: JQuery, title: string): void {
$element
public show(elements: JQuery | NodeList | HTMLElement, title: string): void {
$(elements)
.attr('data-bs-placement', 'auto')
.attr('data-title', title)
.tooltip('show');
}
/**
* Hide tooltip on $element
* Hide tooltip on element(s)
*
* @param {Object} $element
* @param {Object} elements
*/
public hide($element: JQuery): void {
$element.tooltip('hide');
public hide(elements: JQuery | NodeList | HTMLElement): void {
$(elements).tooltip('hide');
}
}
......
......@@ -10,21 +10,21 @@
*
* The TYPO3 project - inspiring people to share!
*/
var __importDefault=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};define(["require","exports","jquery","bootstrap","lit-html","lit-element","TYPO3/CMS/Core/lit-helper"],(function(e,t,s,l,i,n,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.TreeToolbar=void 0,s=__importDefault(s);t.TreeToolbar=class{constructor(e={}){this.settings={toolbarSelector:"tree-toolbar btn-toolbar",collapseAllBtn:"collapse-all-btn",expandAllBtn:"expand-all-btn",searchInput:"search-input",toggleHideUnchecked:"hide-unchecked-btn"},this.hideUncheckedState=!1,Object.assign(this.settings,e)}initialize(e){this.treeContainer=e,this.$treeWrapper=s.default(e),this.$treeWrapper.data("svgtree-initialized")&&"object"==typeof this.$treeWrapper.data("svgtree")?this.render():this.$treeWrapper.on("svgTree.initialized",()=>this.render())}collapseAll(){this.tree.collapseAll()}expandAll(){this.tree.expandAll()}search(e){const t=e.target;this.tree.nodes.length&&(this.tree.nodes[0].open=!1);const s=t.value.trim(),l=new RegExp(s,"i");this.tree.nodes.forEach(e=>{l.test(e.name)?(this.showParents(e),e.open=!0,e.hidden=!1):(e.hidden=!0,e.open=!1)}),this.tree.prepareDataForVisibleNodes(),this.tree.update()}toggleHideUnchecked(){this.hideUncheckedState=!this.hideUncheckedState,this.hideUncheckedState?this.tree.nodes.forEach(e=>{e.checked?(this.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()}showParents(e){if(0===e.parents.length)return;const t=this.tree.nodes[e.parents[0]];t.hidden=!1,t.expanded=!0,this.showParents(t)}render(){this.tree=this.$treeWrapper.data("svgtree"),Object.assign(this.settings,this.tree.settings);const e=document.createElement("div");this.treeContainer.prepend(e),i.render(this.renderTemplate(),e);const t=this.treeContainer.querySelector("."+this.settings.toolbarSelector);t&&t.querySelectorAll('[data-bs-toggle="tooltip"]').forEach(e=>new l.Tooltip(e))}renderTemplate(){return n.html`
define(["require","exports","bootstrap","lit-html","lit-element","TYPO3/CMS/Core/lit-helper"],(function(e,t,s,n,i,l){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.TreeToolbar=void 0;t.TreeToolbar=class{constructor(e={}){this.settings={toolbarSelector:"tree-toolbar btn-toolbar",collapseAllBtn:"collapse-all-btn",expandAllBtn:"expand-all-btn",searchInput:"search-input",toggleHideUnchecked:"hide-unchecked-btn"},this.hideUncheckedState=!1,Object.assign(this.settings,e)}initialize(e){this.treeContainer=e,this.treeContainer.dataset.svgTreeInitialized&&"object"==typeof this.treeContainer.svgtree?this.render():this.treeContainer.addEventListener("svg-tree:initialized",this.render.bind(this))}collapseAll(){this.tree.collapseAll()}expandAll(){this.tree.expandAll()}search(e){const t=e.target;this.tree.nodes.length&&(this.tree.nodes[0].open=!1);const s=t.value.trim(),n=new RegExp(s,"i");this.tree.nodes.forEach(e=>{n.test(e.name)?(this.showParents(e),e.open=!0,e.hidden=!1):(e.hidden=!0,e.open=!1)}),this.tree.prepareDataForVisibleNodes(),this.tree.update()}toggleHideUnchecked(){this.hideUncheckedState=!this.hideUncheckedState,this.hideUncheckedState?this.tree.nodes.forEach(e=>{e.checked?(this.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()}showParents(e){if(0===e.parents.length)return;const t=this.tree.nodes[e.parents[0]];t.hidden=!1,t.expanded=!0,this.showParents(t)}render(){this.tree=this.treeContainer.svgtree,Object.assign(this.settings,this.tree.settings);const e=document.createElement("div");this.treeContainer.prepend(e),n.render(this.renderTemplate(),e);const t=this.treeContainer.querySelector("."+this.settings.toolbarSelector);t&&t.querySelectorAll('[data-bs-toggle="tooltip"]').forEach(e=>new s.Tooltip(e))}renderTemplate(){return i.html`
<div class="${this.settings.toolbarSelector}">
<div class="input-group">
<span class="input-group-addon input-group-icon filter">${r.icon("actions-filter","small")}</span>
<input type="text" class="form-control ${this.settings.searchInput}" placeholder="${r.lll("tcatree.findItem")}" @input="${e=>this.search(e)}">
<span class="input-group-addon input-group-icon filter">${l.icon("actions-filter","small")}</span>
<input type="text" class="form-control ${this.settings.searchInput}" placeholder="${l.lll("tcatree.findItem")}" @input="${e=>this.search(e)}">
</div>
<div class="btn-group">
<button type="button" data-bs-toggle="tooltip" class="btn btn-default ${this.settings.expandAllBtn}" title="${r.lll("tcatree.expandAll")}" @click="${()=>this.expandAll()}">
${r.icon("apps-pagetree-category-expand-all","small")}
<button type="button" data-bs-toggle="tooltip" class="btn btn-default ${this.settings.expandAllBtn}" title="${l.lll("tcatree.expandAll")}" @click="${()=>this.expandAll()}">
${l.icon("apps-pagetree-category-expand-all","small")}
</button>
<button type="button" data-bs-toggle="tooltip" class="btn btn-default ${this.settings.collapseAllBtn}" title="${r.lll("tcatree.collapseAll")}" @click="${()=>this.collapseAll()}">
${r.icon("apps-pagetree-category-collapse-all","small")}
<button type="button" data-bs-toggle="tooltip" class="btn btn-default ${this.settings.collapseAllBtn}" title="${l.lll("tcatree.collapseAll")}" @click="${()=>this.collapseAll()}">
${l.icon("apps-pagetree-category-collapse-all","small")}
</button>
<button type="button" data-bs-toggle="tooltip" class="btn btn-default ${this.settings.toggleHideUnchecked}" title="${r.lll("tcatree.toggleHideUnchecked")}" @click="${()=>this.toggleHideUnchecked()}">
${r.icon("apps-pagetree-category-toggle-hide-checked","small")}
<button type="button" data-bs-toggle="tooltip" class="btn btn-default ${this.settings.toggleHideUnchecked}" title="${l.lll("tcatree.toggleHideUnchecked")}" @click="${()=>this.toggleHideUnchecked()}">
${l.icon("apps-pagetree-category-toggle-hide-checked","small")}
</button>
</div>
</div>
......
......@@ -14,7 +14,7 @@
/**
* Module: TYPO3/CMS/Backend/PageTree/PageTree
*/
define(['jquery',
define([
'd3-selection',
'TYPO3/CMS/Core/Ajax/AjaxRequest',
'TYPO3/CMS/Backend/Icons',
......@@ -24,7 +24,7 @@ define(['jquery',
'TYPO3/CMS/Backend/Storage/Persistent',
'TYPO3/CMS/Backend/Notification'
],
function($, d3selection, AjaxRequest, Icons, PageTreeDragDrop, SvgTree, ContextMenu, Persistent, Notification) {
function(d3selection, AjaxRequest, Icons, PageTreeDragDrop, SvgTree, ContextMenu, Persistent, Notification) {
'use strict';
/**
......@@ -93,11 +93,12 @@ define(['jquery',
PageTree.prototype.addMountPoint = function(breadcrumb) {
var _this = this;
if (_this.wrapper.parent().find('.node-mount-point').length) {
_this.wrapper.parent().find('.node-mount-point').remove();
var existingMountPointInfo = _this.wrapper.parentNode.querySelector('.node-mount-point');
if (existingMountPointInfo) {
existingMountPointInfo.parentNode.removeChild(existingMountPointInfo);
}
_this.mountPoint = _this.wrapper.before(
_this.wrapper.insertAdjacentHTML('beforebegin',
'<div class="node-mount-point">' +
'<div class="node-mount-point__icon" data-tree-icon="actions-document-info"></div>' +
'<div class="node-mount-point__text"><div>' + breadcrumb + '</div></div>' +
......@@ -105,19 +106,17 @@ define(['jquery',
'</div>'
);
_this.wrapper.parent()
.find('[data-tree-icon=actions-close]')
.on('click', function() {
_this.wrapper.parentNode
.querySelector('[data-tree-icon=actions-close]')
.addEventListener('click', function() {
top.TYPO3.Backend.NavigationContainer.PageTree.unsetTemporaryMountPoint();
_this.wrapper.parent().find('.node-mount-point').remove();
_this.wrapper.parentNode.querySelector('.node-mount-point').remove();
});
//get icons
_this.wrapper.parent().find('.node-mount-point [data-tree-icon]').each(function() {
var $this = $(this);
Icons.getIcon($this.attr('data-tree-icon'), Icons.sizes.small, null, null, 'inline').then(function(icon) {
$this.append(icon);
// get icons
_this.wrapper.parentNode.querySelectorAll('.node-mount-point [data-tree-icon]').forEach(function(iconElement) {
Icons.getIcon(iconElement.dataset.treeIcon, Icons.sizes.small, null, null, 'inline').then(function(icon) {
iconElement.insertAdjacentHTML('beforeend', icon);
});
});
};
......@@ -180,7 +179,7 @@ define(['jquery',
.then(function(response) {
if (response && response.hasErrors) {
if (response.messages) {
$.each(response.messages, function(id, message) {
response.messages.forEach(function(message) {
Notification.error(
message.title,
message.message
......@@ -240,31 +239,31 @@ define(['jquery',
);
};
PageTree.prototype.nodeRightClick = function(node) {
var $node = $(node).closest('svg').find('.nodes .node[data-state-id=' + this.stateIdentifier + ']');
PageTree.prototype.nodeRightClick = function(selection) {
var node = selection.closest('svg').querySelector('.nodes .node[data-state-id="' + this.stateIdentifier + '"]');
if ($node.length) {
if (node) {
ContextMenu.show(
$node.data('table'),
node.dataset.table,
this.identifier,
$node.data('context'),
$node.data('iteminfo'),
$node.data('parameters'),
node.dataset.context,
node.dataset.iteminfo,
node.dataset.parameters,
node
);
}
};
PageTree.prototype.contextmenu = function(node) {
var $node = $(node).closest('svg').find('.nodes .node[data-state-id=' + this.stateIdentifier + ']');
PageTree.prototype.contextmenu = function(selection) {
var node = selection.closest('svg').querySelector('.nodes .node[data-state-id="' + this.stateIdentifier + '"]');
if ($node.length) {
if (node) {
ContextMenu.show(
$node.data('table'),
node.dataset.table,
this.identifier,
$node.data('context'),
$node.data('iteminfo'),
$node.data('parameters'),
node.dataset.context,
node.dataset.iteminfo,
node.dataset.parameters,
node
);
}
......@@ -368,9 +367,10 @@ define(['jquery',
.call(this.dragDrop.drag())
.attr('data-table', 'pages')
.attr('data-context', 'tree')
.on('contextmenu', function(event, node) {
.on('contextmenu', function(event, element) {
event.preventDefault();
_this.dispatch.call('nodeRightClick', node, this);
var selection = this;
_this.dispatch.call('nodeRightClick', element, selection);
});
var nodeStop = nodes
......@@ -541,7 +541,7 @@ define(['jquery',
.then(function(response) {
if (response && response.hasErrors) {
if (response.messages) {
$.each(response.messages, function(id, message) {
response.messages.forEach(function(message) {
Notification.error(
message.title,
message.message
......@@ -587,7 +587,7 @@ define(['jquery',
.then(function(response) {
if (response && response.hasErrors) {
if (response.messages) {
$.each(response.messages, function(id, message) {
response.messages.forEach(function(message) {
Notification.error(
message.title,
message.message
......
......@@ -10,20 +10,20 @@
*
* The TYPO3 project - inspiring people to share!
*/
var __importDefault=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};define(["require","exports","jquery","lit-html","lit-element","TYPO3/CMS/Core/lit-helper","TYPO3/CMS/Backend/PageTree/PageTree","../Viewport","./PageTreeToolbar","TYPO3/CMS/Core/Ajax/AjaxRequest"],(function(e,t,r,a,i,o,l,s,n,d){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.PageTreeElement=void 0,r=__importDefault(r),s=__importDefault(s),d=__importDefault(d);class c{static initialize(e){const t=document.querySelector(e);if(t&&t.childNodes.length>0)return void r.default(".svg-tree",t).trigger("isVisible");a.render(c.renderTemplate(),t);const i=t.querySelector(".svg-tree-wrapper");r.default(i).on("scroll",()=>{r.default(i).find("[data-bs-toggle=tooltip]").tooltip("hide")});const o=new l,g=top.TYPO3.settings.ajaxUrls.page_tree_configuration;new d.default(g).get().then(async e=>{const r=await e.resolve("json"),a=top.TYPO3.settings.ajaxUrls.page_tree_data,l=top.TYPO3.settings.ajaxUrls.page_tree_filter;Object.assign(r,{dataUrl:a,filterUrl:l,showIcons:!0}),o.initialize(i,r),s.default.NavigationContainer.setComponentInstance(o);const d=t.querySelector(".svg-toolbar");if(!d.dataset.treeShowToolbar){(new n.PageTreeToolbar).initialize("#typo3-pagetree-tree",d),d.dataset.treeShowToolbar="true"}})}static renderTemplate(){return i.html`
var __importDefault=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};define(["require","exports","lit-html","lit-element","TYPO3/CMS/Core/lit-helper","TYPO3/CMS/Backend/PageTree/PageTree","../Viewport","./PageTreeToolbar","TYPO3/CMS/Core/Ajax/AjaxRequest"],(function(e,t,r,a,i,o,l,s,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.PageTreeElement=void 0,l=__importDefault(l),n=__importDefault(n);class d{static initialize(e){const t=document.querySelector(e);if(t&&t.childNodes.length>0)return void t.querySelector(".svg-tree").dispatchEvent(new Event("svg-tree:visible"));r.render(d.renderTemplate(),t);const a=t.querySelector(".svg-tree-wrapper"),i=new o,c=top.TYPO3.settings.ajaxUrls.page_tree_configuration;new n.default(c).get().then(async e=>{const r=await e.resolve("json"),o=top.TYPO3.settings.ajaxUrls.page_tree_data,n=top.TYPO3.settings.ajaxUrls.page_tree_filter;Object.assign(r,{dataUrl:o,filterUrl:n,showIcons:!0}),i.initialize(a,r),l.default.NavigationContainer.setComponentInstance(i);const d=t.querySelector(".svg-toolbar");if(!d.dataset.treeShowToolbar){(new s.PageTreeToolbar).initialize(a,d),d.dataset.treeShowToolbar="true"}})}static renderTemplate(){return a.html`
<div id="typo3-pagetree" class="svg-tree">
<div>
<div id="typo3-pagetree-toolbar" class="svg-toolbar"></div>
<div id="typo3-pagetree-treeContainer" class="navigation-tree-container">
<div id="typo3-pagetree-tree" class="svg-tree-wrapper">
<div class="node-loader">
${o.icon("spinner-circle-light","small")}
${i.icon("spinner-circle-light","small")}
</div>
</div>
</div>
</div>
<div class="svg-tree-loader">
${o.icon("spinner-circle-light","large")}
${i.icon("spinner-circle-light","large")}
</div>
</div>
`}}t.PageTreeElement=c}));
\ No newline at end of file
`}}t.PageTreeElement=d}));
\ No newline at end of file
......@@ -10,38 +10,38 @@
*
* The TYPO3 project - inspiring people to share!
*/
var __importDefault=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};define(["require","exports","d3-selection","jquery","lit-html","lit-element","TYPO3/CMS/Core/lit-helper","TYPO3/CMS/Backend/PageTree/PageTreeDragDrop","TYPO3/CMS/Core/Event/DebounceEvent"],(function(e,t,s,r,i,a,n,o,l){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.PageTreeToolbar=void 0,r=__importDefault(r),l=__importDefault(l);t.PageTreeToolbar=class{constructor(){this.settings={toolbarSelector:"tree-toolbar",searchInput:".search-input",filterTimeout:450},this.hideUncheckedState=!1,this.dragDrop=o}initialize(e,t,s={}){this.$treeWrapper=r.default(e),this.targetEl=t,this.$treeWrapper.data("svgtree-initialized")&&"object"==typeof this.$treeWrapper.data("svgtree")?(Object.assign(this.settings,s),this.render()):this.$treeWrapper.on("svgTree.initialized",()=>this.render())}refreshTree(){this.tree.refreshOrFilterTree()}search(e){this.tree.searchQuery=e.value.trim(),this.tree.refreshOrFilterTree(),this.tree.prepareDataForVisibleNodes(),this.tree.update()}toggleHideUnchecked(e){this.hideUncheckedState=!this.hideUncheckedState,this.hideUncheckedState?this.tree.nodes.forEach(e=>{e.checked?(this.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()}showParents(e){if(0===e.parents.length)return;const t=this.tree.nodes[e.parents[0]];t.hidden=!1,t.expanded=!0,this.showParents(t)}showSubmenu(e){this.targetEl.querySelectorAll("[data-tree-show-submenu]").forEach(t=>{t.dataset.treeShowSubmenu===e?t.classList.add("active"):t.classList.remove("active")}),this.targetEl.querySelectorAll("[data-tree-submenu]").forEach(t=>{t.dataset.treeSubmenu===e?t.classList.add("active"):t.classList.remove("active")});const t=this.targetEl.querySelector('[data-tree-submenu="'+e+'"]').querySelector("input");t&&(t.focus(),t.clearable({onClear:()=>{this.tree.resetFilter(),this.tree.prepareDataForVisibleNodes(),this.tree.update()}}))}render(){this.tree=this.$treeWrapper.data("svgtree"),Object.assign(this.settings,this.tree.settings),i.render(this.renderTemplate(),this.targetEl);const e=s.select(".svg-toolbar");r.default.each(this.tree.settings.doktypes,(t,s)=>{s.icon?e.selectAll("[data-tree-icon="+s.icon+"]").call(this.dragDrop.dragToolbar()):console.warn("Missing icon definition for doktype: "+s.nodeType)}),new l.default("input",e=>{this.search(e.target)},this.settings.filterTimeout).bindTo(this.targetEl.querySelector(this.settings.searchInput)),r.default(this.targetEl).find('[data-bs-toggle="tooltip"]').tooltip();const t=this.targetEl.querySelector('[data-tree-show-submenu="page-new"]'),a=this.targetEl.querySelector(".svg-toolbar__menu :first-child:not(.js-svg-refresh)");(t||a).click()}renderTemplate(){return a.html`
var __importDefault=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};define(["require","exports","d3-selection","lit-html","lit-element","TYPO3/CMS/Core/lit-helper","TYPO3/CMS/Backend/PageTree/PageTreeDragDrop","TYPO3/CMS/Core/Event/DebounceEvent"],(function(e,t,s,r,i,a,n,o){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.PageTreeToolbar=void 0,o=__importDefault(o);t.PageTreeToolbar=class{constructor(){this.settings={toolbarSelector:"tree-toolbar",searchInput:".search-input",filterTimeout:450},this.dragDrop=n}initialize(e,t,s={}){this.treeContainer=e,this.targetEl=t,this.treeContainer.dataset.svgTreeInitialized&&"object"==typeof this.treeContainer.svgtree?(Object.assign(this.settings,s),this.render()):this.treeContainer.addEventListener("svg-tree:initialized",()=>this.render())}refreshTree(){this.tree.refreshOrFilterTree()}search(e){this.tree.searchQuery=e.value.trim(),this.tree.refreshOrFilterTree(),this.tree.prepareDataForVisibleNodes(),this.tree.update()}showSubmenu(e){this.targetEl.querySelectorAll("[data-tree-show-submenu]").forEach(t=>{t.dataset.treeShowSubmenu===e?t.classList.add("active"):t.classList.remove("active")}),this.targetEl.querySelectorAll("[data-tree-submenu]").forEach(t=>{t.dataset.treeSubmenu===e?t.classList.add("active"):t.classList.remove("active")});const t=this.targetEl.querySelector('[data-tree-submenu="'+e+'"]').querySelector("input");t&&(t.focus(),t.clearable({onClear:()=>{this.tree.resetFilter(),this.tree.prepareDataForVisibleNodes(),this.tree.update()}}))}render(){this.tree=this.treeContainer.svgtree,Object.assign(this.settings,this.tree.settings),r.render(this.renderTemplate(),this.targetEl);const e=s.select(".svg-toolbar");this.tree.settings.doktypes.forEach((t,s)=>{t.icon?e.selectAll("[data-tree-icon="+t.icon+"]").call(this.dragDrop.dragToolbar()):console.warn("Missing icon definition for doktype: "+t.nodeType)}),new o.default("input",e=>{this.search(e.target)},this.settings.filterTimeout).bindTo(this.targetEl.querySelector(this.settings.searchInput));const t=this.targetEl.querySelector('[data-tree-show-submenu="page-new"]'),i=this.targetEl.querySelector(".svg-toolbar__menu :first-child:not(.js-svg-refresh)");(t||i).click()}renderTemplate(){return i.html`
<div class="${this.settings.toolbarSelector}">
<div class="svg-toolbar__menu">
<div class="btn-group">
${this.tree.settings.doktypes&&this.tree.settings.doktypes.length>0?a.html`
${this.tree.settings.doktypes&&this.tree.settings.doktypes.length>0?i.html`
<div class="x-btn btn btn-default btn-sm x-btn-noicon" data-tree-show-submenu="page-new" @click="${()=>this.showSubmenu("page-new")}">
<button class="svg-toolbar__btn" data-tree-icon="actions-page-new" title="${n.lll("tree.buttonNewNode")}">
${n.icon("actions-page-new","small")}
<button class="svg-toolbar__btn" data-tree-icon="actions-page-new" title="${a.lll("tree.buttonNewNode")}">
${a.icon("actions-page-new","small")}
</button>
</div>
`:""}
<div class="x-btn btn btn-default btn-sm x-btn-noicon" data-tree-show-submenu="filter" @click="${()=>this.showSubmenu("filter")}">
<button class="svg-toolbar__btn" data-tree-icon="actions-filter" title="${n.lll("tree.buttonFilter")}">
${n.icon("actions-filter","small")}
<button class="svg-toolbar__btn" data-tree-icon="actions-filter" title="${a.lll("tree.buttonFilter")}">
${a.icon("actions-filter","small")}
</button>
</div>
</div>
<div class="x-btn btn btn-default btn-sm x-btn-noicon js-svg-refresh" @click="${()=>this.refreshTree()}">
<button class="svg-toolbar__btn" data-tree-icon="actions-refresh" title="${n.lll("labels.refresh")}">
${n.icon("actions-refresh","small")}
<button class="svg-toolbar__btn" data-tree-icon="actions-refresh" title="${a.lll("labels.refresh")}">
${a.icon("actions-refresh","small")}
</button>
</div>
</div>
<div class="svg-toolbar__submenu">
<div class="svg-toolbar__submenu-item" data-tree-submenu="filter">
<input type="text" class="form-control search-input" placeholder="${n.lll("tree.searchTermInfo")}">
<input type="text" class="form-control search-input" placeholder="${a.lll("tree.searchTermInfo")}">
</div>
<div class="svg-toolbar__submenu-item" data-tree-submenu="page-new">
${this.tree.settings.doktypes&&this.tree.settings.doktypes.length?this.tree.settings.doktypes.map(e=>(this.tree.fetchIcon(e.icon,!1),a.html`