228018dacf7e0d82a9ee3c6f29f36d7c554cf972
[Packages/TYPO3.CMS.git] / t3lib / js / extjs / tree / tree.js
1 /***************************************************************
2 * Copyright notice
3 *
4 * (c) 2010 Steffen Kamper <steffen@typo3.org>
5 * All rights reserved
6 *
7 * This script is part of the TYPO3 project. The TYPO3 project is
8 * free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * The GNU General Public License can be found at
14 * http://www.gnu.org/copyleft/gpl.html.
15 * A copy is found in the textfile GPL.txt and important notices to the license
16 * from the author is found in LICENSE.txt distributed with these scripts.
17 *
18 *
19 * This script is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * This copyright notice MUST APPEAR in all copies of the script!
25 ***************************************************************/
26
27 Ext.ns('TYPO3.Components', 'TYPO3.Components.Tree');
28
29 /**
30 * TYPO3window - General TYPO3 tree component
31 */
32
33 TYPO3.Components.Tree = {};
34 TYPO3.Components.Tree.StandardTreeItemData = [];
35
36 TYPO3.Components.Tree.StandardTree = function(config) {
37 var conf = Ext.apply({
38 header: false,
39 width: 280,
40 rootVisible: false,
41 useArrows: false,
42 lines: true,
43 autoScroll: true,
44 containerScroll: true,
45 exclusiveSelectedKey: null,
46 stateful: true,
47 filterOptionStartsWith: true,
48 countSelectedNodes: 0,
49 loader: new Ext.tree.TreeLoader({
50 preloadChildren: true,
51 clearOnLoad: false
52 }),
53 root: new Ext.tree.AsyncTreeNode({
54 text: 'TYPO3 StandardTree',
55 id: 'root',
56 expanded: true,
57 children: TYPO3.Components.Tree.StandardTreeItemData[config.id]
58 }),
59 collapseFirst: false,
60 listeners: {
61 'checkchange': function(checkedNode, checked) {
62 if (Ext.isFunction(this.checkChangeHandler)) {
63 this.checkChangeHandler.call(this, checkedNode, checked);
64 }
65 },
66 scope: this
67 }
68 }, config);
69 TYPO3.Components.Tree.StandardTree.superclass.constructor.call(this, conf);
70 };
71
72
73 Ext.extend(TYPO3.Components.Tree.StandardTree, Ext.tree.TreePanel, {
74
75 initComponent: function() {
76 Ext.apply(this, {
77 tbar: this.initialConfig.showHeader ? TYPO3.Components.Tree.Toolbar([], this) : null
78 });
79 TYPO3.Components.Tree.StandardTree.superclass.initComponent.call(this);
80 },
81 filterTree: function(filterText) {
82 var text = filterText.getValue();
83 Ext.each(this.hiddenNodes, function(node) {
84 node.ui.show();
85 node.ui.removeClass('bgColor6');
86 });
87 if (!text) {
88 this.filter.clear();
89 return;
90 }
91 this.expandAll();
92 var regText = (this.filterOptionStartsWith ? '^' : '') + Ext.escapeRe(text);
93 var re = new RegExp(regText, 'i');
94
95 // hide empty nodes that weren't filtered
96 this.hiddenNodes = [];
97 var me = this;
98 this.root.cascade(function(node) {
99 if (node.ui.ctNode.offsetHeight < 3) {
100 if (!re.test(node.text)) {
101 node.ui.hide();
102 me.hiddenNodes.push(node);
103 } else {
104 node.ui.addClass('bgColor6');
105 }
106 }
107 }, this);
108 }
109 });
110
111 TYPO3.Components.Tree.Toolbar = function(items, scope) {
112 items = items || [];
113 items.push([
114 ' ',
115 {
116 iconCls: 't3-icon t3-icon-actions t3-icon-actions-system t3-icon-system-tree-search-open',
117 menu: {
118 items: [
119 {
120 text: 'starts with',
121 checked: true,
122 group: 'searchStartsWith',
123 handler: function(item) {
124 scope.filterOptionStartsWith = true;
125 scope.filterTree(scope.getTopToolbar().getComponent('filterText'));
126 },
127 scope: scope
128 },
129 {
130 text: 'contains',
131 checked: false,
132 group: 'searchStartsWith',
133 handler: function(item) {
134 scope.filterOptionStartsWith = false;
135 scope.filterTree(scope.getTopToolbar().getComponent('filterText'));
136 },
137 scope: scope
138 }
139 ]
140 }
141 },
142 new Ext.form.TextField({
143 width: 150,
144 emptyText:'Find item',
145 enableKeyEvents: true,
146 itemId: 'filterText',
147 listeners:{
148 render: function(f) {
149 this.filter = new Ext.tree.TreeFilter(this, {
150 clearBlank: true,
151 autoClear: true
152 });
153 },
154 keydown: {
155 fn: scope.filterTree,
156 buffer: 350,
157 scope: scope
158 },
159 scope: scope
160 }
161 }),
162 '->',
163 {
164 iconCls: 'icon-expand-all',
165 tooltip: 'Expand All',
166 handler: function() {
167 this.root.expand(true);
168 },
169 scope: scope
170 }, {
171 iconCls: 'icon-collapse-all',
172 tooltip: 'Collapse All',
173 handler: function() {
174 this.root.collapse(true);
175 },
176 scope: scope
177 }
178 ]);
179 return items;
180 };
181
182 TYPO3.Components.Tree.EmptySelectionModel = new Ext.tree.DefaultSelectionModel({
183 select: Ext.emptyFn
184 })
185
186 TYPO3.Components.Tree.TcaCheckChangeHandler = function(checkedNode, checked) {
187 var exclusiveKeys = this.tcaExclusiveKeys.split(','),
188 uid = '' + checkedNode.attributes.uid;
189
190 this.suspendEvents();
191
192 if (this.tcaExclusiveKeys.length) {
193 if (checked = true && exclusiveKeys.indexOf(uid) > -1) {
194 // this key is exclusive, so uncheck all others
195 this.root.cascade(function(node) {
196 if (node !== checkedNode && node.attributes.checked) {
197 node.attributes.checked = false;
198 node.ui.toggleCheck(false);
199 }
200 });
201 this.exclusiveSelectedKey = uid;
202 } else if (checked = true && exclusiveKeys.indexOf(uid) === -1 && !Ext.isEmpty(this.exclusiveSelectedKey)) {
203 // this key is exclusive, so uncheck all others
204 this.root.cascade(function(node) {
205 if (exclusiveKeys.indexOf('' + node.attributes.uid) > -1) {
206 node.attributes.checked = false;
207 node.ui.toggleCheck(false);
208 }
209 });
210 this.exclusiveSelectedKey = null;
211 }
212 }
213
214 if (this.countSelectedNodes >= this.tcaMaxItems) {
215 checkedNode.attributes.checked = false;
216 checkedNode.getUI().toggleCheck(false);
217 return false;
218 }
219 if (checked) {
220 checkedNode.getUI().addClass('complete');
221 } else {
222 checkedNode.getUI().removeClass('complete');
223 }
224 var selected = [];
225 this.root.cascade(function(node) {
226 if (node.ui.isChecked()) {
227 selected.push(node.attributes.uid);
228 }
229 });
230 this.countSelectedNodes = selected.length;
231 Ext.fly('treeinput' + this.id).dom.value = selected.join(',');
232 eval(this.onChange);
233
234 this.resumeEvents();
235 };