Merged new PageTree (version for TYPO3 4.5 Beta 3) - new files added
authorSteffen Kamper <info@sk-typo3.de>
Wed, 22 Dec 2010 01:23:08 +0000 (01:23 +0000)
committerSteffen Kamper <info@sk-typo3.de>
Wed, 22 Dec 2010 01:23:08 +0000 (01:23 +0000)
git-svn-id: https://svn.typo3.org/TYPO3v4/Core/trunk@9875 709f56b5-9817-0410-a4d7-c38de5d9e867

16 files changed:
typo3/sysext/pagetree/components/pagetree/icons/gfx/ol/join.gif [new file with mode: 0644]
typo3/sysext/pagetree/components/pagetree/icons/gfx/ol/joinbottom.gif [new file with mode: 0644]
typo3/sysext/pagetree/components/pagetree/icons/gfx/ol/line.gif [new file with mode: 0644]
typo3/sysext/pagetree/components/pagetree/icons/gfx/ol/minus.gif [new file with mode: 0644]
typo3/sysext/pagetree/components/pagetree/icons/gfx/ol/minusbottom.gif [new file with mode: 0644]
typo3/sysext/pagetree/components/pagetree/icons/gfx/ol/plus.gif [new file with mode: 0644]
typo3/sysext/pagetree/components/pagetree/icons/gfx/ol/plusbottom.gif [new file with mode: 0644]
typo3/sysext/pagetree/components/pagetree/icons/gfx/toolbar_item_active_bg.png [new file with mode: 0644]
typo3/sysext/pagetree/components/pagetree/javascript/Ext.ux.state.TreePanel.js [new file with mode: 0644]
typo3/sysext/pagetree/components/pagetree/javascript/app.js [new file with mode: 0644]
typo3/sysext/pagetree/components/pagetree/javascript/filteringtree.js [new file with mode: 0644]
typo3/sysext/pagetree/components/pagetree/javascript/loadorder.txt [new file with mode: 0644]
typo3/sysext/pagetree/components/pagetree/javascript/nodeui.js [new file with mode: 0644]
typo3/sysext/pagetree/components/pagetree/javascript/toppanel.js [new file with mode: 0644]
typo3/sysext/pagetree/components/pagetree/javascript/treeeditor.js [new file with mode: 0644]
typo3/sysext/pagetree/pagetree_ie6.css [new file with mode: 0644]

diff --git a/typo3/sysext/pagetree/components/pagetree/icons/gfx/ol/join.gif b/typo3/sysext/pagetree/components/pagetree/icons/gfx/ol/join.gif
new file mode 100644 (file)
index 0000000..45c0b9a
Binary files /dev/null and b/typo3/sysext/pagetree/components/pagetree/icons/gfx/ol/join.gif differ
diff --git a/typo3/sysext/pagetree/components/pagetree/icons/gfx/ol/joinbottom.gif b/typo3/sysext/pagetree/components/pagetree/icons/gfx/ol/joinbottom.gif
new file mode 100644 (file)
index 0000000..a0ddcdf
Binary files /dev/null and b/typo3/sysext/pagetree/components/pagetree/icons/gfx/ol/joinbottom.gif differ
diff --git a/typo3/sysext/pagetree/components/pagetree/icons/gfx/ol/line.gif b/typo3/sysext/pagetree/components/pagetree/icons/gfx/ol/line.gif
new file mode 100644 (file)
index 0000000..c08adb8
Binary files /dev/null and b/typo3/sysext/pagetree/components/pagetree/icons/gfx/ol/line.gif differ
diff --git a/typo3/sysext/pagetree/components/pagetree/icons/gfx/ol/minus.gif b/typo3/sysext/pagetree/components/pagetree/icons/gfx/ol/minus.gif
new file mode 100644 (file)
index 0000000..a0a83da
Binary files /dev/null and b/typo3/sysext/pagetree/components/pagetree/icons/gfx/ol/minus.gif differ
diff --git a/typo3/sysext/pagetree/components/pagetree/icons/gfx/ol/minusbottom.gif b/typo3/sysext/pagetree/components/pagetree/icons/gfx/ol/minusbottom.gif
new file mode 100644 (file)
index 0000000..7331c81
Binary files /dev/null and b/typo3/sysext/pagetree/components/pagetree/icons/gfx/ol/minusbottom.gif differ
diff --git a/typo3/sysext/pagetree/components/pagetree/icons/gfx/ol/plus.gif b/typo3/sysext/pagetree/components/pagetree/icons/gfx/ol/plus.gif
new file mode 100644 (file)
index 0000000..b0df901
Binary files /dev/null and b/typo3/sysext/pagetree/components/pagetree/icons/gfx/ol/plus.gif differ
diff --git a/typo3/sysext/pagetree/components/pagetree/icons/gfx/ol/plusbottom.gif b/typo3/sysext/pagetree/components/pagetree/icons/gfx/ol/plusbottom.gif
new file mode 100644 (file)
index 0000000..ce6e684
Binary files /dev/null and b/typo3/sysext/pagetree/components/pagetree/icons/gfx/ol/plusbottom.gif differ
diff --git a/typo3/sysext/pagetree/components/pagetree/icons/gfx/toolbar_item_active_bg.png b/typo3/sysext/pagetree/components/pagetree/icons/gfx/toolbar_item_active_bg.png
new file mode 100644 (file)
index 0000000..9d44c71
Binary files /dev/null and b/typo3/sysext/pagetree/components/pagetree/icons/gfx/toolbar_item_active_bg.png differ
diff --git a/typo3/sysext/pagetree/components/pagetree/javascript/Ext.ux.state.TreePanel.js b/typo3/sysext/pagetree/components/pagetree/javascript/Ext.ux.state.TreePanel.js
new file mode 100644 (file)
index 0000000..4d08c6c
--- /dev/null
@@ -0,0 +1,136 @@
+/***************************************************************
+*  Copyright notice
+*
+*  (c) 2010 TYPO3 Tree Team <http://forge.typo3.org/projects/typo3v4-extjstrees>
+*  All rights reserved
+*
+*  This script is part of the TYPO3 project. The TYPO3 project is
+*  free software; you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation; either version 2 of the License, or
+*  (at your option) any later version.
+*
+*  The GNU General Public License can be found at
+*  http://www.gnu.org/copyleft/gpl.html.
+*  A copy is found in the textfile GPL.txt and important notices to the license
+*  from the author is found in LICENSE.txt distributed with these scripts.
+*
+*
+*  This script is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  This copyright notice MUST APPEAR in all copies of the script!
+***************************************************************/
+Ext.ns('Ext.ux.state');
+
+// dummy constructor
+Ext.ux.state.TreePanel = function() {};
+
+/**
+ * State Provider for a tree panel
+ */
+Ext.override(Ext.ux.state.TreePanel, {
+       /**
+        * Initializes the plugin
+        * @param {Ext.tree.TreePanel} tree
+        * @private
+        */
+       init:function(tree) {
+               tree.lastSelectedNode = null;
+               tree.isRestoringState = false;
+               tree.stateHash = {};
+
+               // install event handlers on TreePanel
+               tree.on({
+                       // add path of expanded node to stateHash
+                        beforeexpandnode:function(n) {
+                               if (this.isRestoringState) {
+                                       return;
+                               }
+
+                               this.stateHash[n.id] = n.getPath();
+                       },
+
+                       // delete path and all subpaths of collapsed node from stateHash
+                       beforecollapsenode:function(n) {
+                               if (this.isRestoringState) {
+                                       return;
+                               }
+
+                               delete this.stateHash[n.id];
+                               var cPath = n.getPath();
+                               for(var p in this.stateHash) {
+                                       if(this.stateHash.hasOwnProperty(p)) {
+                                               if(this.stateHash[p].indexOf(cPath) !== -1) {
+                                                       delete this.stateHash[p];
+                                               }
+                                       }
+                               }
+                       },
+
+                       beforeclick: function(node) {
+                               if (this.isRestoringState) {
+                                       return;
+                               }
+                               this.stateHash['lastSelectedNode'] = node.id;
+                       }
+               });
+
+                       // update state on node expand or collapse
+               tree.stateEvents = tree.stateEvents || [];
+               tree.stateEvents.push('expandnode', 'collapsenode', 'click');
+
+               // add state related props to the tree
+               Ext.apply(tree, {
+                       // keeps expanded nodes paths keyed by node.ids
+                        stateHash:{},
+
+                       restoreState: function() {
+                               this.isRestoringState = true;
+                               for(var p in this.stateHash) {
+                                       if(this.stateHash.hasOwnProperty(p)) {
+                                               this.expandPath(this.stateHash[p]);
+                                       }
+                               }
+                                       // get last selected node
+                               if (this.stateHash['lastSelectedNode']) {
+                                       var node = this.getNodeById(this.stateHash['lastSelectedNode']);
+                                       if (node) {
+                                               this.selectPath(node.getPath());
+                                               if (node.attributes.nodeData.id !== TYPO3.Backend.ContentContainer.getIdFromUrl()
+                                                       && this.commandProvider && this.commandProvider.singleClick
+                                               ) {
+                                                               this.commandProvider.singleClick(node, this);
+                                               }
+                                       }
+                               }
+
+                               this.isRestoringState = false;
+                       },
+
+                       // apply state on tree initialization
+                       applyState:function(state) {
+                               if(state) {
+                                       Ext.apply(this, state);
+
+                                       // it is too early to expand paths here
+                                       // so do it once on root load
+                                       this.root.on({
+                                               load: {
+                                                       single:true,
+                                                       scope:this,
+                                                       fn: this.restoreState
+                                               }
+                                       });
+                               }
+                       },
+
+                       // returns stateHash for save by state manager
+                       getState:function() {
+                               return {stateHash:this.stateHash};
+                       }
+               });
+       }
+});
diff --git a/typo3/sysext/pagetree/components/pagetree/javascript/app.js b/typo3/sysext/pagetree/components/pagetree/javascript/app.js
new file mode 100644 (file)
index 0000000..8c8a913
--- /dev/null
@@ -0,0 +1,324 @@
+/***************************************************************
+*  Copyright notice
+*
+*  (c) 2010 TYPO3 Tree Team <http://forge.typo3.org/projects/typo3v4-extjstrees>
+*  All rights reserved
+*
+*  This script is part of the TYPO3 project. The TYPO3 project is
+*  free software; you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation; either version 2 of the License, or
+*  (at your option) any later version.
+*
+*  The GNU General Public License can be found at
+*  http://www.gnu.org/copyleft/gpl.html.
+*  A copy is found in the textfile GPL.txt and important notices to the license
+*  from the author is found in LICENSE.txt distributed with these scripts.
+*
+*
+*  This script is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  This copyright notice MUST APPEAR in all copies of the script!
+***************************************************************/
+Ext.namespace('TYPO3.Components.PageTree');
+
+/**
+ * @class TYPO3.Components.PageTree.App
+ *
+ * Page tree main application that controls setups the components
+ *
+ * @namespace TYPO3.Components.PageTree
+ * @extends Ext.Panel
+ * @author Stefan Galinski <stefan.galinski@gmail.com>
+ */
+TYPO3.Components.PageTree.App = Ext.extend(Ext.Panel, {
+       /**
+        * Panel id
+        *
+        * @type {String}
+        */
+       id: 'typo3-pagetree',
+
+       /**
+        * Border
+        *
+        * @type {Boolean}
+        */
+       border: false,
+
+       /**
+        * Layout Type
+        *
+        * @type {String}
+        */
+       layout: 'anchor',
+
+       /**
+        * Listeners
+        *
+        * The afterlayout wizard relayoutes the navigation container to fix some nasty
+        * scrollbar issues.
+        *
+        * @type {Object}
+        */
+       listeners: {
+               afterlayout: {
+                       fn: function() {
+                               this.ownerCt.doLayout();
+                       },
+                       buffer: 250
+               }
+       },
+
+       /**
+        * Initializes the application
+        *
+        * Set's the necessary language labels, configuration options and sprite icons by an
+        * external call and initializes the needed components.
+        *
+        * @return {void}
+        */
+       initComponent: function() {
+               TYPO3.Components.PageTree.DataProvider.loadResources(function(response) {
+                       TYPO3.Components.PageTree.LLL = response['LLL'];
+                       TYPO3.Components.PageTree.Configuration = response['Configuration'];
+                       TYPO3.Components.PageTree.Sprites = response['Sprites'];
+
+                       var tree = new TYPO3.Components.PageTree.Tree({
+                               id: this.id + '-tree',
+                               ddGroup: this.id,
+                               stateful: true,
+                               stateId: 'Pagetree' + TYPO3.Components.PageTree.Configuration.temporaryMountPoint,
+                               stateEvents: [],
+                               autoScroll: true,
+                               plugins: new Ext.ux.state.TreePanel(),
+                               commandProvider: TYPO3.Components.PageTree.Actions,
+                               contextMenuProvider: TYPO3.Components.PageTree.ContextMenuDataProvider,
+                               treeDataProvider: TYPO3.Components.PageTree.DataProvider
+                       });
+
+                       var filteringTree = new TYPO3.Components.PageTree.FilteringTree({
+                               id: this.id + '-filteringTree',
+                               ddGroup: this.id,
+                               autoScroll: true,
+                               commandProvider: TYPO3.Components.PageTree.Actions,
+                               contextMenuProvider: TYPO3.Components.PageTree.ContextMenuDataProvider,
+                               treeDataProvider: TYPO3.Components.PageTree.DataProvider
+                       });
+
+                       var topPanel = new TYPO3.Components.PageTree.TopPanel({
+                               dataProvider: TYPO3.Components.PageTree.DataProvider,
+                               filteringTree: filteringTree,
+                               ddGroup: this.id,
+                               tree: tree
+                       });
+
+                       var deletionDropZone = new TYPO3.Components.PageTree.DeletionDropZone({
+                               commandProvider: TYPO3.Components.PageTree.Actions,
+                               ddGroup: this.id,
+                               tree: tree
+                       });
+
+                       this.add(
+                               topPanel, {
+                                       border: false,
+                                       id: this.id + '-indicatorBar'
+                               }, {
+                                       border: false,
+                                       id: this.id + '-treeContainer',
+                                       items: [tree, filteringTree]
+                               },
+                               deletionDropZone
+                       );
+
+                       if (TYPO3.Components.PageTree.Configuration.temporaryMountPoint) {
+                               this.addTemporaryMountPointIndicator();
+                       }
+
+                       if (TYPO3.Components.PageTree.Configuration.indicator !== '') {
+                               this.addIndicatorItems();
+                       }
+               }, this);
+
+               TYPO3.Components.PageTree.App.superclass.initComponent.apply(this, arguments);
+       },
+
+       /**
+        * Adds the default indicator items
+        *
+        * @return {void}
+        */
+       addIndicatorItems: function() {
+               this.addIndicator({
+                       border: false,
+                       id: this.id + '-indicatorBar-indicatorTitle',
+                       cls: this.id + '-indicatorBar-item',
+                       html: TYPO3.Components.PageTree.Configuration.indicator
+               });
+       },
+
+       /**
+        * Adds the temporary mount point indicator item
+        *
+        * @return {void}
+        */
+       addTemporaryMountPointIndicator: function() {
+               this.temporaryMountPointInfoIndicator = this.addIndicator({
+                       border: false,
+                       id: this.id + '-indicatorBar-temporaryMountPoint',
+                       cls: this.id + '-indicatorBar-item',
+                       html: '<p>' +
+                                       '<span id="' + this.id + '-indicatorBar-temporaryMountPoint-info' + '" ' +
+                                               'class="' + this.id + '-indicatorBar-item-leftIcon ' +
+                                                       TYPO3.Components.PageTree.Sprites.Info + '">' + '&nbsp;' +
+                                       '</span>' +
+                                       '<span id="' + this.id + '-indicatorBar-temporaryMountPoint-clear' + '" ' +
+                                               'class="' + this.id + '-indicatorBar-item-rightIcon ' +
+                                                       TYPO3.Components.PageTree.Sprites.InputClear + '">' + '&nbsp;' +
+                                       '</span>' +
+                                       TYPO3.Components.PageTree.LLL.temporaryMountPointIndicatorInfo + '<br />' +
+                                               TYPO3.Components.PageTree.Configuration.temporaryMountPoint +
+                               '</p>'
+               });
+
+               this.temporaryMountPointInfoIndicator.on('afterrender', function() {
+                       var element = Ext.fly(this.id + '-indicatorBar-temporaryMountPoint-clear');
+                       element.on('click', function() {
+                               TYPO3.BackendUserSettings.ExtDirect.unsetKey(
+                                       'pageTree_temporaryMountPoint',
+                                       function() {
+                                               this.removeIndicator(this.temporaryMountPointInfoIndicator);
+                                               this.getTree().refreshTree();
+                                               this.getTree().stateId = 'Pagetree';
+                                       },
+                                       this
+                               );
+                       }, this);
+               }, this);
+       },
+
+       /**
+        * Adds an indicator item
+        *
+        * @param {Ext.Component} component
+        * @return {void}
+        */
+       addIndicator: function(component) {
+               return Ext.getCmp(this.id + '-indicatorBar').add(component);
+       },
+
+       /**
+        * Removes an indicator item from the indicator bar
+        *
+        * @param {Ext.Component} component
+        * @return {void}
+        */
+       removeIndicator: function(component) {
+               Ext.getCmp(this.id + '-indicatorBar').remove(component);
+       },
+
+       /**
+        * Compatibility method that calls refreshTree()
+        *
+        * @return {void}
+        */
+       refresh: function() {
+               this.refreshTree();
+       },
+
+       /**
+        * Another compatibility method that calls refreshTree()
+        *
+        * @return {void}
+        */
+       refresh_nav: function() {
+               this.refreshTree();
+       },
+
+       /**
+        * Refreshes the tree and selects the node defined by fsMod.recentIds['web']
+        *
+        * @return {void}
+        */
+       refreshTree: function() {
+               if (!isNaN(fsMod.recentIds['web']) && fsMod.recentIds['web'] !== '') {
+                       this.select(fsMod.recentIds['web'], true);
+               }
+
+               TYPO3.Components.PageTree.DataProvider.getIndicators(function(response) {
+                       this.removeIndicator(Ext.getCmp(this.id + '-indicatorBar-indicatorTitle'));
+                       TYPO3.Components.PageTree.Configuration.indicator = response;
+                       this.addIndicatorItems();
+               }, this);
+
+               this.items.items[0].activeTree.refreshTree();
+       },
+
+       /**
+        * Returns the current active tree
+        *
+        * @return {TYPO3.Components.PageTree.Tree}
+        */
+       getTree: function() {
+               return this.items.items[0].activeTree;
+       },
+
+       /**
+        * Selects a node defined by the page id. If the second parameter is set, we
+        * store the new location into the state hash.
+        *
+        * @param {int} pageId
+        * @param {Boolean} saveState
+        * @return {Boolean}
+        */
+       select: function(pageId, saveState) {
+               if (saveState !== false) {
+                       saveState = true;
+               }
+
+               var tree = this.getTree();
+               var succeeded = false;
+               var node = tree.getRootNode().findChild('realId', pageId, true);
+               if (node) {
+                       succeeded = true;
+                       tree.selectPath(node.getPath());
+                       if (!!saveState) {
+                               tree.stateHash['lastSelectedNode'] = node.id;
+                       }
+               }
+
+               return succeeded;
+       },
+
+       /**
+        * Returns the currently selected node
+        *
+        * @return {Ext.tree.TreeNode}
+        */
+       getSelected: function() {
+               var node = this.getTree().getSelectionModel().getSelectedNode();
+               return node ? node : null;
+       }
+});
+
+/**
+ * Callback method for the module menu
+ *
+ * @return {TYPO3.Components.PageTree.App}
+ */
+TYPO3.ModuleMenu.App.registerNavigationComponent('typo3-pagetree', function() {
+       TYPO3.Backend.NavigationContainer.PageTree = new TYPO3.Components.PageTree.App();
+
+               // compatibility code
+    top.nav = TYPO3.Backend.NavigationContainer.PageTree;
+    top.nav_frame = TYPO3.Backend.NavigationContainer.PageTree;
+    top.content.nav_frame = TYPO3.Backend.NavigationContainer.PageTree;
+
+       return TYPO3.Backend.NavigationContainer.PageTree;
+});
+
+// XTYPE Registration
+Ext.reg('TYPO3.Components.PageTree.App', TYPO3.Components.PageTree.App);
diff --git a/typo3/sysext/pagetree/components/pagetree/javascript/filteringtree.js b/typo3/sysext/pagetree/components/pagetree/javascript/filteringtree.js
new file mode 100644 (file)
index 0000000..71d5d00
--- /dev/null
@@ -0,0 +1,68 @@
+/***************************************************************
+*  Copyright notice
+*
+*  (c) 2010 TYPO3 Tree Team <http://forge.typo3.org/projects/typo3v4-extjstrees>
+*  All rights reserved
+*
+*  This script is part of the TYPO3 project. The TYPO3 project is
+*  free software; you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation; either version 2 of the License, or
+*  (at your option) any later version.
+*
+*  The GNU General Public License can be found at
+*  http://www.gnu.org/copyleft/gpl.html.
+*  A copy is found in the textfile GPL.txt and important notices to the license
+*  from the author is found in LICENSE.txt distributed with these scripts.
+*
+*
+*  This script is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  This copyright notice MUST APPEAR in all copies of the script!
+***************************************************************/
+Ext.namespace('TYPO3.Components.PageTree');
+
+/**
+ * @class TYPO3.Components.PageTree.FilteringTree
+ *
+ * Filtering Tree
+ *
+ * @namespace TYPO3.Components.PageTree
+ * @extends TYPO3.Components.PageTree.Tree
+ * @author Stefan Galinski <stefan.galinski@gmail.com>
+ */
+TYPO3.Components.PageTree.FilteringTree = Ext.extend(TYPO3.Components.PageTree.Tree, {
+       /**
+        * Search word
+        *
+        * @type {String}
+        */
+       searchWord: '',
+
+       /**
+        * Tree loader implementation for the filtering tree
+        *
+        * @return {void}
+        */
+       addTreeLoader: function() {
+               this.loader = new Ext.tree.TreeLoader({
+                       directFn: this.treeDataProvider.getFilteredTree,
+                       paramOrder: 'searchWord',
+                       baseAttrs: {
+                               uiProvider: this.uiProvider
+                       },
+
+                       listeners: {
+                               beforeload: function(treeLoader, node) {
+                                       treeLoader.baseParams.searchWord = node.ownerTree.searchWord;
+                               }
+                       }
+               });
+       }
+});
+
+// XTYPE Registration
+Ext.reg('TYPO3.Components.PageTree.FilteringTree', TYPO3.Components.PageTree.FilteringTree);
\ No newline at end of file
diff --git a/typo3/sysext/pagetree/components/pagetree/javascript/loadorder.txt b/typo3/sysext/pagetree/components/pagetree/javascript/loadorder.txt
new file mode 100644 (file)
index 0000000..679453f
--- /dev/null
@@ -0,0 +1,10 @@
+treeeditor.js
+tree.js
+filteringtree.js
+nodeui.js
+deletiondropzone.js
+toppanel.js
+contextmenu.js
+actions.js
+Ext.ux.state.TreePanel.js
+app.js
\ No newline at end of file
diff --git a/typo3/sysext/pagetree/components/pagetree/javascript/nodeui.js b/typo3/sysext/pagetree/components/pagetree/javascript/nodeui.js
new file mode 100644 (file)
index 0000000..7eed67f
--- /dev/null
@@ -0,0 +1,145 @@
+/***************************************************************
+*  Copyright notice
+*
+*  (c) 2010 TYPO3 Tree Team <http://forge.typo3.org/projects/typo3v4-extjstrees>
+*  All rights reserved
+*
+*  This script is part of the TYPO3 project. The TYPO3 project is
+*  free software; you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation; either version 2 of the License, or
+*  (at your option) any later version.
+*
+*  The GNU General Public License can be found at
+*  http://www.gnu.org/copyleft/gpl.html.
+*  A copy is found in the textfile GPL.txt and important notices to the license
+*  from the author is found in LICENSE.txt distributed with these scripts.
+*
+*
+*  This script is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  This copyright notice MUST APPEAR in all copies of the script!
+***************************************************************/
+Ext.namespace('TYPO3.Components.PageTree');
+
+/**
+ * @class TYPO3.Components.PageTree.DeletionDropZone
+ *
+ * Tree Node User Interface that can handle sprite icons and more
+ *
+ * @namespace TYPO3.Components.PageTree
+ * @extends Ext.tree.TreeNodeUI
+ * @author Stefan Galinski <stefan.galinski@gmail.com>
+ */
+TYPO3.Components.PageTree.PageTreeNodeUI = Ext.extend(Ext.tree.TreeNodeUI, {
+       /**
+        * Adds the sprite icon and adds an event to open the context menu on a single click at the icon node
+        *
+        * @param {Ext.tree.TreeNode} n
+        * @param {Object} a
+        * @param {Ext.tree.TreeNode} targetNode
+        * @param {Boolean} bulkRender
+        * @return {void}
+        */
+       renderElements : function(n, a, targetNode, bulkRender) {
+               // add some indent caching, this helps performance when rendering a large tree
+        this.indentMarkup = n.parentNode ? n.parentNode.ui.getChildIndent() : '';
+
+        var cb = Ext.isBoolean(a.checked),
+            nel,
+            href = this.getHref(a.href),
+            buf = ['<li class="x-tree-node"><div ext:tree-node-id="',n.id,'" class="x-tree-node-el x-tree-node-leaf x-unselectable ', a.cls,'" unselectable="on">',
+            '<span class="x-tree-node-indent">',this.indentMarkup,"</span>",
+            '<img alt="" src="', this.emptyIcon, '" class="x-tree-ec-icon x-tree-elbow" />',
+//            '<img alt="" src="', a.icon || this.emptyIcon, '" class="x-tree-node-icon',(a.icon ? " x-tree-node-inline-icon" : ""),(a.iconCls ? " "+a.iconCls : ""),'" unselectable="on" />',
+                       a.spriteIconCode, // TYPO3: add sprite icon code
+            cb ? ('<input class="x-tree-node-cb" type="checkbox" ' + (a.checked ? 'checked="checked" />' : '/>')) : '',
+            '<a hidefocus="on" class="x-tree-node-anchor" href="',href,'" tabIndex="1" ',
+             a.hrefTarget ? ' target="'+a.hrefTarget+'"' : "", '><span unselectable="on">',n.text,"</span></a></div>",
+            '<ul class="x-tree-node-ct" style="display:none;"></ul>',
+            "</li>"].join('');
+
+        if(bulkRender !== true && n.nextSibling && (nel = n.nextSibling.ui.getEl())){
+            this.wrap = Ext.DomHelper.insertHtml("beforeBegin", nel, buf);
+        }else{
+            this.wrap = Ext.DomHelper.insertHtml("beforeEnd", targetNode, buf);
+        }
+
+        this.elNode = this.wrap.childNodes[0];
+        this.ctNode = this.wrap.childNodes[1];
+        var cs = this.elNode.childNodes;
+        this.indentNode = cs[0];
+        this.ecNode = cs[1];
+//        this.iconNode = cs[2];
+               this.iconNode = (cs[2].firstChild.tagName === 'SPAN' ? cs[2].firstChild : cs[2]); // TYPO3: get possible overlay icon
+        var index = 3; // TYPO3: index 4?
+        if(cb){
+            this.checkbox = cs[3];
+            // fix for IE6
+            this.checkbox.defaultChecked = this.checkbox.checked;
+            index++;
+        }
+        this.anchor = cs[index];
+        this.textNode = cs[index].firstChild;
+
+                       // TYPO3: call the context menu on a single click (Beware of drag&drop!)
+               if (!TYPO3.Components.PageTree.Configuration.disableIconLinkToContextmenu
+                       || TYPO3.Components.PageTree.Configuration.disableIconLinkToContextmenu === '0'
+               ) {
+                       Ext.fly(this.iconNode).on('click', function(event) {
+                               this.getOwnerTree().fireEvent('contextmenu', this, event);
+                               event.stopEvent();
+                       }, n);
+               }
+       },
+
+       /**
+        * Adds a quick tip to the sprite icon
+        *
+        * @param {Ext.tree.TreeNode} node
+        * @param {Object} tip
+        * @param {String} title
+        * @return {void}
+        */
+    onTipChange : function(node, tip, title) {
+               TYPO3.Components.PageTree.PageTreeNodeUI.superclass.onTipChange.apply(this, arguments);
+
+        if(this.rendered){
+            var hasTitle = Ext.isDefined(title);
+            if(this.iconNode.setAttributeNS){
+                this.iconNode.setAttributeNS("ext", "qtip", tip);
+                if(hasTitle){
+                    this.iconNode.setAttributeNS("ext", "qtitle", title);
+                }
+            }else{
+                this.iconNode.setAttribute("ext:qtip", tip);
+                if(hasTitle){
+                    this.iconNode.setAttribute("ext:qtitle", title);
+                }
+            }
+        }
+    },
+
+       /**
+        * Returns the drag and drop handles
+        *
+        * @return {Object}
+        */
+       getDDHandles: function() {
+               var ddHandles = [this.iconNode, this.textNode, this.elNode];
+               var textNode = Ext.get(this.textNode);
+               for (var i = 0; i < textNode.dom.childNodes.length; ++i) {
+                       if (textNode.dom.childNodes[i].nodeName === 'SPAN') {
+                               ddHandles[3] = textNode.dom.childNodes[i];
+                       }
+               }
+
+               return ddHandles;
+    }
+});
+
+// XTYPE Registration
+Ext.reg('TYPO3.Components.PageTree.PageTreeNodeUI', TYPO3.Components.PageTree.PageTreeNodeUI);
\ No newline at end of file
diff --git a/typo3/sysext/pagetree/components/pagetree/javascript/toppanel.js b/typo3/sysext/pagetree/components/pagetree/javascript/toppanel.js
new file mode 100644 (file)
index 0000000..dce45e1
--- /dev/null
@@ -0,0 +1,438 @@
+/***************************************************************
+*  Copyright notice
+*
+*  (c) 2010 TYPO3 Tree Team <http://forge.typo3.org/projects/typo3v4-extjstrees>
+*  All rights reserved
+*
+*  This script is part of the TYPO3 project. The TYPO3 project is
+*  free software; you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation; either version 2 of the License, or
+*  (at your option) any later version.
+*
+*  The GNU General Public License can be found at
+*  http://www.gnu.org/copyleft/gpl.html.
+*  A copy is found in the textfile GPL.txt and important notices to the license
+*  from the author is found in LICENSE.txt distributed with these scripts.
+*
+*
+*  This script is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  This copyright notice MUST APPEAR in all copies of the script!
+***************************************************************/
+Ext.namespace('TYPO3.Components.PageTree');
+
+/**
+ * @class TYPO3.Components.PageTree.TopPanel
+ *
+ * Top Panel
+ *
+ * @namespace TYPO3.Components.PageTree
+ * @extends Ext.Panel
+ * @author Stefan Galinski <stefan.galinski@gmail.com>
+ */
+TYPO3.Components.PageTree.TopPanel = Ext.extend(Ext.Panel, {
+       /**
+        * Component Id
+        *
+        * @type {String}
+        */
+       id: 'typo3-pagetree-topPanel',
+
+       /**
+        * Border
+        *
+        * @type {Boolean}
+        */
+       border: false,
+
+       /**
+        * Toolbar Object
+        *
+        * @type {Ext.Toolbar}
+        */
+       tbar: new Ext.Toolbar(),
+
+       /**
+        * Currently Clicked Toolbar Button
+        *
+        * @type {Ext.Button}
+        */
+       currentlyClickedButton: null,
+
+       /**
+        * Currently Shown Panel
+        *
+        * @type {Ext.Component}
+        */
+       currentlyShownPanel: null,
+
+       /**
+        * Active tree (often used from outside, too)
+        *
+        * @type {TYPO3.Components.PageTree.Tree}
+        */
+       activeTree: null,
+
+       /**
+        * Filtering Indicator Item
+        *
+        * @type {Ext.Panel}
+        */
+       filteringIndicator: null,
+
+       /**
+        * Drag and Drop Group
+        *
+        * @cfg {String}
+        */
+       ddGroup: '',
+
+       /**
+        * Data Provider
+        *
+        * @cfg {Object}
+        */
+       dataProvider: null,
+
+       /**
+        * Filtering Tree
+        *
+        * @cfg {TYPO3.Components.PageTree.FilteringTree}
+        */
+       filteringTree: null,
+
+       /**
+        * Page Tree
+        *
+        * @cfg {TYPO3.Components.PageTree.Tree}
+        */
+       tree: null,
+
+       /**
+        * Initializes the component
+        *
+        * @return {void}
+        */
+       initComponent: function() {
+               this.activeTree = this.tree;
+
+               this.currentlyShownPanel = new Ext.Panel({
+                       id: this.id + '-defaultPanel',
+                       cls: this.id + '-item',
+                       html: TYPO3.Components.PageTree.LLL.treeStructure
+               });
+               this.items = [this.currentlyShownPanel];
+
+               TYPO3.Components.PageTree.TopPanel.superclass.initComponent.apply(this, arguments);
+
+               this.addDragDropNodeInsertionFeature();
+               
+               if (!TYPO3.Components.PageTree.Configuration.hideFilter
+                       || TYPO3.Components.PageTree.Configuration.hideFilter === '0'
+               ) {
+                       this.addFilterFeature();
+               }
+
+               this.getTopToolbar().addItem({xtype: 'tbfill'});
+               this.addRefreshTreeFeature();
+       },
+
+       /**
+        * Returns a custom button template to fix some nasty webkit issues
+        * by removing some useless wrapping html code
+        *
+        * @return {void}
+        */
+       getButtonTemplate: function() {
+               return new Ext.Template(
+                       '<div id="{4}" class="x-btn {3}"><button type="{0}"">&nbsp;</button></div>'
+               );
+       },
+
+       /**
+        * Adds a button to the components toolbar with a related component
+        *
+        * @param {Object} button
+        * @param {Object} connectedWidget
+        * @return {void}
+        */
+       addButton: function(button, connectedWidget) {
+               button.template = this.getButtonTemplate();
+               if (!button.hasListener('click')) {
+                       button.on('click', this.topbarButtonCallback);
+               }
+
+               if (connectedWidget) {
+                       connectedWidget.hidden = true;
+                       button.connectedWidget = connectedWidget;
+                       this.add(connectedWidget);
+               }
+
+               this.getTopToolbar().addItem(button);
+               this.doLayout();
+       },
+
+       /**
+        * Usual button callback method that triggers the assigned component of the
+        * clicked toolbar button
+        *
+        * @return {void}
+        */
+       topbarButtonCallback: function() {
+               var topPanel = this.ownerCt.ownerCt;
+
+               topPanel.currentlyShownPanel.hide();
+               if (topPanel.currentlyClickedButton) {
+                       topPanel.currentlyClickedButton.toggle(false);
+               }
+
+               if (topPanel.currentlyClickedButton === this) {
+                       topPanel.currentlyClickedButton = null;
+                       topPanel.currentlyShownPanel = topPanel.get(topPanel.id + '-defaultPanel');
+               } else {
+                       this.toggle(true);
+                       topPanel.currentlyClickedButton = this;
+                       topPanel.currentlyShownPanel = this.connectedWidget;
+               }
+
+               topPanel.currentlyShownPanel.show();
+       },
+
+       /**
+        * Loads the filtering tree nodes with the given search word
+        *
+        * @param {Ext.form.TextField} textField
+        * @return {void}
+        */
+       createFilterTree: function(textField) {
+               var searchWord = textField.getValue();
+               if ((searchWord.length <= 2 && searchWord.length > 0) || searchWord === this.filteringTree.searchWord) {
+                       return;
+               }
+
+               this.filteringTree.searchWord = searchWord;
+               if (this.filteringTree.searchWord === '') {
+                       this.activeTree = this.tree;
+
+                       this.filteringTree.hide();
+                       this.tree.show().refreshTree(function() {
+                               textField.focus();
+                       }, this);
+
+                       if (this.filteringIndicator) {
+                               this.ownerCt.removeIndicator(this.filteringIndicator);
+                               this.filteringIndicator = null;
+                       }
+               } else {
+                       var selectedNode = this.ownerCt.getSelected();
+                       this.activeTree = this.filteringTree;
+
+                       if (!this.filteringIndicator) {
+                               this.filteringIndicator = this.ownerCt.addIndicator(
+                                       this.createIndicatorItem(textField)
+                               );
+                       }
+
+                       this.tree.hide();
+                       this.ownerCt.ownerCt.getEl().mask('', 'x-mask-loading-message');
+                       this.ownerCt.ownerCt.getEl().addClass('t3-mask-loading');
+                       this.filteringTree.show().refreshTree(function() {
+                               if (selectedNode) {
+                                       this.ownerCt.select(selectedNode.attributes.nodeData.id, false);
+                               }
+                               textField.focus();
+                               this.ownerCt.ownerCt.getEl().unmask();
+                       }, this);
+               }
+
+               this.doLayout();
+       },
+
+       /**
+        * Adds an indicator item to the page tree application for the filtering feature
+        *
+        * @param {Ext.form.TextField} textField
+        * @return {void}
+        */
+       createIndicatorItem: function(textField) {
+               return {
+                       border: false,
+                       id: this.ownerCt.id + '-indicatorBar-filter',
+                       cls: this.ownerCt.id + '-indicatorBar-item',
+                       html: '<p>' +
+                                       '<span id="' + this.ownerCt.id + '-indicatorBar-filter-info' + '" ' +
+                                               'class="' + this.ownerCt.id + '-indicatorBar-item-leftIcon ' +
+                                                       TYPO3.Components.PageTree.Sprites.Info + '">' + '&nbsp;' +
+                                       '</span>' +
+                                       '<span id="' + this.ownerCt.id + '-indicatorBar-filter-clear' + '" ' +
+                                               'class="' + this.ownerCt.id + '-indicatorBar-item-rightIcon ' +
+                                                       TYPO3.Components.PageTree.Sprites.InputClear + '">' + '&nbsp;' +
+                                       '</span>' +
+                                       TYPO3.Components.PageTree.LLL.activeFilterMode +
+                               '</p>',
+                       filteringTree: this.filteringTree,
+
+                       listeners: {
+                               afterrender: {
+                                       scope: this,
+                                       fn: function() {
+                                               var element = Ext.fly(this.ownerCt.id + '-indicatorBar-filter-clear');
+                                               element.on('click', function() {
+                                                       textField.setValue('');
+                                                       this.createFilterTree(textField);
+                                               }, this);
+                                       }
+                               }
+                       }
+               };
+       },
+
+       /**
+        * Adds the necessary functionality and components for the filtering feature
+        *
+        * @return {void}
+        */
+       addFilterFeature: function() {
+               var topPanelButton = new Ext.Button({
+                       id: this.id + '-button-filter',
+                       cls: this.id + '-button',
+                       iconCls: TYPO3.Components.PageTree.Sprites.Filter
+               });
+
+               var textField = new Ext.form.TriggerField({
+                       id: this.id + '-filter',
+                       enableKeyEvents: true,
+                       triggerClass: TYPO3.Components.PageTree.Sprites.InputClear,
+
+                       listeners: {
+                               keydown: {
+                                       fn: this.createFilterTree,
+                                       scope: this,
+                                       buffer: 1000
+                               }
+                       }
+               });
+
+               textField.onTriggerClick = function() {
+                       textField.setValue('');
+                       this.createFilterTree(textField);
+               }.createDelegate(this);
+
+               var topPanelWidget = new Ext.Panel({
+                       border: false,
+                       id: this.id + '-filterWrap',
+                       cls: this.id + '-item',
+                       items: [textField],
+
+                       listeners: {
+                               show: {
+                                       scope: this,
+                                       fn: function(panel) {
+                                               panel.get(this.id + '-filter').focus();
+                                       }
+                               }
+                       }
+               });
+
+               this.addButton(topPanelButton, topPanelWidget);
+       },
+
+       /**
+        * Creates the entries for the new node drag zone toolbar
+        *
+        * @return {void}
+        */
+       createNewNodeToolbar: function() {
+               (new Ext.dd.DragZone(this.getEl(), {
+                       ddGroup: this.ownerCt.ddGroup,
+
+                       getDragData: function(event) {
+                               this.proxyElement = document.createElement('div');
+
+                               var node = Ext.getCmp(event.getTarget('.x-btn').id);
+                               node.shouldCreateNewNode = true;
+
+                               return {
+                                       ddel: this.proxyElement,
+                                       item: node
+                               }
+                       },
+
+                       onInitDrag: function() {
+                               var clickedButton = this.dragData.item;
+                               var cls = clickedButton.initialConfig.iconCls;
+
+                               this.proxyElement.style.width = '150px';
+                               this.proxyElement.innerHTML = '<span class="' + cls + '"></span>'  + clickedButton.title;
+
+                               this.proxy.update(this.proxyElement);
+                       }
+               }));
+       },
+
+       /**
+        * Creates the necessary components for new node drag and drop feature
+        *
+        * @return {void}
+        */
+       addDragDropNodeInsertionFeature: function() {
+               var newNodeToolbar = new Ext.Toolbar({
+                       border: false,
+                       id: this.id + '-item-newNode',
+                       cls: this.id + '-item',
+
+                       listeners: {
+                               render: {
+                                       fn: this.createNewNodeToolbar
+                               }
+                       }
+               });
+
+               this.dataProvider.getNodeTypes(function(response) {
+                       for (var i = 0; i < response.length; ++i) {
+                               response[i].template = this.getButtonTemplate();
+                               newNodeToolbar.addItem(response[i]);
+                       }
+                       newNodeToolbar.doLayout();
+               }, this);
+
+               var topPanelButton = new Ext.Button({
+                       id: this.id + '-button-newNode',
+                       cls: this.id + '-button',
+                       iconCls: TYPO3.Components.PageTree.Sprites.NewNode
+               });
+
+               this.addButton(topPanelButton, newNodeToolbar);
+       },
+
+       /**
+        * Adds a button to the toolbar for the refreshing feature
+        *
+        * @return {void}
+        */
+       addRefreshTreeFeature: function() {
+               var topPanelButton = new Ext.Button({
+                       id: this.id + '-button-refresh',
+                       cls: this.id + '-button',
+                       iconCls: TYPO3.Components.PageTree.Sprites.Refresh,
+
+                       listeners: {
+                               click: {
+                                       scope: this,
+                                       fn: function() {
+                                               this.activeTree.refreshTree();
+                                       }
+                               }
+                       }
+               });
+
+               this.addButton(topPanelButton);
+       }
+});
+
+// XTYPE Registration
+Ext.reg('TYPO3.Components.PageTree.TopPanel', TYPO3.Components.PageTree.TopPanel);
\ No newline at end of file
diff --git a/typo3/sysext/pagetree/components/pagetree/javascript/treeeditor.js b/typo3/sysext/pagetree/components/pagetree/javascript/treeeditor.js
new file mode 100644 (file)
index 0000000..8ab42b1
--- /dev/null
@@ -0,0 +1,109 @@
+/***************************************************************
+*  Copyright notice
+*
+*  (c) 2010 TYPO3 Tree Team <http://forge.typo3.org/projects/typo3v4-extjstrees>
+*  All rights reserved
+*
+*  This script is part of the TYPO3 project. The TYPO3 project is
+*  free software; you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation; either version 2 of the License, or
+*  (at your option) any later version.
+*
+*  The GNU General Public License can be found at
+*  http://www.gnu.org/copyleft/gpl.html.
+*  A copy is found in the textfile GPL.txt and important notices to the license
+*  from the author is found in LICENSE.txt distributed with these scripts.
+*
+*
+*  This script is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  This copyright notice MUST APPEAR in all copies of the script!
+***************************************************************/
+Ext.namespace('TYPO3.Components.PageTree');
+
+/**
+ * @class TYPO3.Components.PageTree.TreeEditor
+ *
+ * Custom Tree Editor implementation to enable different source fields for the
+ * editable label.
+ *
+ * @namespace TYPO3.Components.PageTree
+ * @extends Ext.tree.TreeEditor
+ * @author Stefan Galinski <stefan.galinski@gmail.com>
+ */
+TYPO3.Components.PageTree.TreeEditor = Ext.extend(Ext.tree.TreeEditor, {
+       /**
+        * Don't send any save events if the value wasn't changed
+        *
+        * @type {Boolean}
+        */
+       ignoreNoChange: false,
+
+       /**
+        * Edit delay
+        *
+        * @type {int}
+        */
+       editDelay: 250,
+
+       /**
+        * Indicates if an underlying shadow should be shown
+        *
+        * @type {Boolean}
+        */
+       shadow: false,
+
+       /**
+        * Listeners
+        *
+        * Handles the synchronization between the edited label and the shown label.
+        */
+       listeners: {
+               beforecomplete: function(node) {
+                       this.updatedValue = this.getValue();
+                       node.editNode.attributes.editableText = this.updatedValue;
+                       this.setValue(node.editNode.attributes.prefix + this.updatedValue + node.editNode.attributes.suffix);
+                       this.editNode.attributes.editableText = this.updatedValue;
+               },
+
+               complete: {
+                       fn: function(node, newValue, oldValue) {
+                               this.editNode.ownerTree.commandProvider.saveTitle(node, this.updatedValue, oldValue);
+                       }
+               }
+       },
+
+       /**
+        * Overriden method to set another editable text than the node text attribute
+        *
+        * @param {Ext.tree.TreeNode} node
+        * @return {Boolean}
+        */
+       triggerEdit : function(node) {
+               this.completeEdit();
+               if (node.attributes.editable !== false) {
+                       this.editNode = node;
+                       if (this.tree.autoScroll) {
+                               Ext.fly(node.ui.getEl()).scrollIntoView(this.tree.body);
+                       }
+
+                       var value = node.text || '';
+                       if (!Ext.isGecko && Ext.isEmpty(node.text)) {
+                               node.setText(' ');
+                       }
+
+                               // TYPO3 MODIFICATION to use another attribute
+                       value = node.attributes.editableText;
+
+                       this.autoEditTimer = this.startEdit.defer(this.editDelay, this, [node.ui.textNode, value]);
+                       return false;
+               }
+       }
+});
+
+// XTYPE Registration
+Ext.reg('TYPO3.Components.PageTree.TreeEditor', TYPO3.Components.PageTree.TreeEditor);
\ No newline at end of file
diff --git a/typo3/sysext/pagetree/pagetree_ie6.css b/typo3/sysext/pagetree/pagetree_ie6.css
new file mode 100644 (file)
index 0000000..3b8f91e
--- /dev/null
@@ -0,0 +1,30 @@
+/**
+ * this has to be added to the t3skin ie6 folder
+ *
+ */
+#typo3-pagetree .typo3-pagetree-topPanel-button {
+       margin: 0;
+       padding: 0 2px;
+}
+
+#typo3-pagetree .typo3-pagetree-topPanel-button button {
+       margin: 0;
+       padding: 0;
+       width: 16px;
+       height: 16px;
+       overflow: hidden;
+}
+
+#typo3-pagetree #typo3-pagetree-indicatorBar {
+       padding: 0;
+       line-height: normal;
+}
+
+#typo3-pagetree #typo3-pagetree-topPanel {
+       height: 53px;
+}
+
+#typo3-pagetree .x-tree-node .x-tree-node-el {
+       border-top: 1px solid #F0F0F0;
+       border-bottom: 1px solid #F0F0F0;
+}
\ No newline at end of file