2 * This file is part of the TYPO3 CMS project.
4 * It is free software; you can redistribute it and/or modify it under
5 * the terms of the GNU General Public License, either version 2
6 * of the License, or any later version.
8 * For the full copyright and license information, please read the
9 * LICENSE.txt file that was distributed with this source code.
11 * The TYPO3 project - inspiring people to share!
15 * Module: TYPO3/CMS/Backend/FormEngine/Element/TreeToolbar
18 'TYPO3/CMS/Backend/Icons',
20 'TYPO3/CMS/Backend/PageTree/PageTreeDragDrop',
21 'TYPO3/CMS/Backend/Tooltip',
22 'TYPO3/CMS/Backend/SvgTree'
24 function($, Icons
, d3
, PageTreeDragDrop
) {
31 * @exports TYPO3/CMS/Backend/FormEngine/Element/TreeToolbar
33 var TreeToolbar
= function() {
35 toolbarSelector
: 'tree-toolbar',
36 searchInput
: '.search-input',
37 target
: '.svg-toolbar'
41 * jQuery object wrapping the SvgTree
45 this.$treeWrapper
= null;
55 * State of the hide unchecked toggle button
60 this._hideUncheckedState
= false;
71 * Toolbar initialization
73 * @param {String} treeSelector
74 * @param {Object} settings
76 TreeToolbar
.prototype.initialize
= function(treeSelector
, settings
) {
78 _this
.$treeWrapper
= $(treeSelector
);
80 this.dragDrop
= PageTreeDragDrop
;
81 this.dragDrop
.init(this);
82 if (!_this
.$treeWrapper
.data('svgtree-initialized') || typeof _this
.$treeWrapper
.data('svgtree') !== 'object') {
83 //both toolbar and tree are loaded independently through require js,
84 //so we don't know which is loaded first
85 //in case of toolbar being loaded first, we wait for an event from svgTree
86 _this
.$treeWrapper
.on('svgTree.initialized', _this
.render
.bind(_this
));
90 $.extend(this.settings
, settings
);
95 * Create toolbar template
97 TreeToolbar
.prototype.createTemplate
= function() {
101 '<div class="' + _this
.settings
.toolbarSelector
+ '">' +
102 '<div class="svg-toolbar__menu">' +
103 '<div class="x-btn btn btn-default btn-sm x-btn-noicon" data-tree-show-submenu="filter">' +
104 '<button class="svg-toolbar__btn" data-tree-icon="actions-filter" title="' + TYPO3
.lang
['tree.buttonFilter'] + '"></button>' +
106 '<div class="x-btn btn btn-default btn-sm x-btn-noicon js-svg-refresh">' +
107 '<button class="svg-toolbar__btn" data-tree-icon="actions-refresh" title="' + TYPO3
.lang
['labels.refresh'] + '"></button>' +
110 '<div class="svg-toolbar__submenu">' +
111 '<div class="svg-toolbar__submenu-item" data-tree-submenu="filter">' +
112 '<input type="text" class="form-control search-input" placeholder="' + TYPO3
.lang
['tree.searchTermInfo'] + '">' +
114 '<div class="svg-toolbar__submenu-item" data-tree-submenu="page-new">' +
120 if (this.tree
.settings
.doktypes
&& this.tree
.settings
.doktypes
.length
) {
121 var $buttons
= $template
.find('[data-tree-submenu=page-new]');
122 $template
.find('.svg-toolbar__menu').prepend('<div class="x-btn btn btn-default btn-sm x-btn-noicon" data-tree-show-submenu="page-new">' +
123 '<button class="svg-toolbar__btn" data-tree-icon="actions-page-new" title="' + TYPO3
.lang
['tree.buttonNewNode'] + '"></button>' +
127 $.each(this.tree
.settings
.doktypes
, function(id
, e
) {
128 _this
.tree
.fetchIcon(e
.icon
, false);
129 $buttons
.append('<div class="svg-toolbar__drag-node" data-tree-icon="' + e
.icon
+ '" data-node-type="' + e
.nodeType
+ '" title="' + e
.title
+ '" tooltip="' + e
.tooltip
+ '"></div>');
133 _this
.template
= $template
;
139 TreeToolbar
.prototype.render
= function() {
141 this.tree
= this.$treeWrapper
.data('svgtree');
143 $.extend(this.settings
, this.tree
.settings
);
144 this.createTemplate();
146 var $toolbar
= $(this.settings
.target
).append(this.template
);
149 $toolbar
.find('[data-tree-icon]').each(function() {
152 Icons
.getIcon($this.attr('data-tree-icon'), Icons
.sizes
.small
).done(function(icon
) {
157 //toggle toolbar submenu
158 $toolbar
.find('[data-tree-show-submenu]').each(function() {
159 $(this).click(function() {
161 var name
= $this.attr('data-tree-show-submenu');
162 var $submenu
= $toolbar
.find('[data-tree-submenu=' + name
+ ']');
164 $toolbar
.find('[data-tree-show-submenu]').not(this).removeClass('active');
165 $this.addClass('active');
167 $toolbar
.find('[data-tree-submenu]').not($submenu
).removeClass('active');
168 $submenu
.addClass('active');
169 $submenu
.find('input').focus();
173 $toolbar
.find('.js-svg-refresh').on('click', this.refreshTree
.bind(this));
175 var d3Toolbar
= d3
.select('.svg-toolbar');
177 $.each(this.tree
.settings
.doktypes
, function(id
, e
) {
180 .selectAll('[data-tree-icon=' + e
.icon
+ ']')
181 .call(_this
.dragDrop
.dragToolbar());
183 console
.warn('Missing icon definition for doktype: ' + e
.nodeType
);
187 $toolbar
.find(this.settings
.searchInput
).on('input', function() {
188 _this
.search
.call(_this
, this);
191 $toolbar
.find('[data-toggle="tooltip"]').tooltip();
193 if ($('[data-tree-show-submenu="page-new"]').length
) {
194 $('[data-tree-show-submenu="page-new"]').trigger('click');
196 $('.svg-toolbar__menu :first-child:not(.js-svg-refresh)').trigger('click');
203 TreeToolbar
.prototype.refreshTree
= function() {
204 this.tree
.refreshTree();
210 * @param {HTMLElement} input
212 TreeToolbar
.prototype.search
= function(input
) {
214 var name
= $(input
).val().trim();
216 this.tree
.nodes
[0].expanded
= false;
217 this.tree
.nodes
.forEach(function(node
) {
218 var regex
= new RegExp(name
, 'i');
219 if (node
.identifier
.toString() === name
|| regex
.test(node
.name
) || regex
.test(node
.alias
)) {
220 _this
.showParents(node
);
221 node
.expanded
= true;
223 } else if (node
.depth
!== 0) {
225 node
.expanded
= false;
229 this.tree
.prepareDataForVisibleNodes();
234 * Show only checked items
236 * @param {HTMLElement} input
238 TreeToolbar
.prototype.toggleHideUnchecked
= function(input
) {
241 this._hideUncheckedState
= !this._hideUncheckedState
;
243 if (this._hideUncheckedState
) {
244 this.tree
.nodes
.forEach(function(node
) {
246 _this
.showParents(node
);
247 node
.expanded
= true;
251 node
.expanded
= false;
255 this.tree
.nodes
.forEach(function(node
) {
260 this.tree
.prepareDataForVisibleNodes();
265 * Finds and show all parents of node
270 TreeToolbar
.prototype.showParents
= function(node
) {
271 if (node
.parents
.length
=== 0) {
275 var parent
= this.tree
.nodes
[node
.parents
[0]];
276 parent
.hidden
= false;
279 parent
.expanded
= true;
280 this.showParents(parent
);