diff --git a/t3lib/core_autoload.php b/t3lib/core_autoload.php index 4b4488744681175b7a3a264365418ad11f2aba7b..883285c15a2fac7cd1d5c1bb700c6b46c6cd8c7c 100644 --- a/t3lib/core_autoload.php +++ b/t3lib/core_autoload.php @@ -196,16 +196,15 @@ $t3libClasses = array( 't3lib_tree_abstractdataprovider' => PATH_t3lib . 'tree/class.t3lib_tree_abstractdataprovider.php', 't3lib_tree_abstractstateprovider' => PATH_t3lib . 'tree/class.t3lib_tree_abstractstateprovider.php', 't3lib_tree_node' => PATH_t3lib . 'tree/class.t3lib_tree_node.php', - 't3lib_tree_representationnode' => PATH_t3lib . 'tree/class.t3lib_tree_representationnode.php', 't3lib_tree_nodecollection' => PATH_t3lib . 'tree/class.t3lib_tree_nodecollection.php', 't3lib_tree_sortednodecollection' => PATH_t3lib . 'tree/class.t3lib_tree_sortednodecollection.php', - 't3lib_tree_extdirect_abstractextjstree' => PATH_t3lib . 'tree/extdirect/class.t3lib_tree_extdirect_abstractextjstree.php', - 't3lib_tree_comparablenode' => PATH_t3lib . 'interfaces/tree/interface.t3lib_tree_comparablenode.php', - 't3lib_tree_draggableanddropable' => PATH_t3lib . 'interfaces/tree/interface.t3lib_tree_draggableanddropable.php', - 't3lib_tree_labeleditable' => PATH_t3lib . 'interfaces/tree/interface.t3lib_tree_labeleditable.php', - 't3lib_tree_renderer_abstract' => PATH_t3lib . 'tree/renderer/class.t3lib_tree_renderer_abstract.php', - 't3lib_tree_renderer_unorderedlist' => PATH_t3lib . 'tree/renderer/class.t3lib_tree_renderer_unorderedlist.php', - 't3lib_tree_renderer_extjsjson' => PATH_t3lib . 'tree/renderer/class.t3lib_tree_renderer_extjsjson.php', + 't3lib_tree_extjs_abstractextjstree' => PATH_t3lib . 'tree/extjs/class.t3lib_tree_extjs_abstractextjstree.php', + 't3lib_tree_extjs_abstractstatefulextjstree' => PATH_t3lib . 'tree/extjs/class.t3lib_tree_extjs_abstractstatefulextjstree.php', + 't3lib_tree_comparablenode' => PATH_t3lib . 'tree/interfaces/interface.t3lib_tree_comparablenode.php', + 't3lib_tree_renderablenode' => PATH_t3lib . 'tree/interfaces/interface.t3lib_tree_renderablenode.php', + 't3lib_tree_draggableanddropable' => PATH_t3lib . 'tree/interfaces/interface.t3lib_tree_draggableanddropable.php', + 't3lib_tree_labeleditable' => PATH_t3lib . 'tree/interfaces/interface.t3lib_tree_labeleditable.php', + 't3lib_tree_recordbasednode' => PATH_t3lib . 'tree/interfaces/interface.t3lib_tree_recordbasednode.php', 't3lib_contextmenu_abstractcontextmenu' => PATH_t3lib . 'contextmenu/class.t3lib_contextmenu_abstractcontextmenu.php', 't3lib_contextmenu_abstractdataprovider' => PATH_t3lib . 'contextmenu/class.t3lib_contextmenu_abstractdataprovider.php', 't3lib_contextmenu_action' => PATH_t3lib . 'contextmenu/class.t3lib_contextmenu_action.php', @@ -225,7 +224,8 @@ $t3libClasses = array( 't3lib_contextmenu_pagetree_extdirect_contextmenu' => PATH_t3lib . 'contextmenu/pagetree/extdirect/class.t3lib_contextmenu_pagetree_extdirect_contextmenu.php', 't3lib_tree_pagetree_dataprovider' => PATH_t3lib . 'tree/pagetree/class.t3lib_tree_pagetree_dataprovider.php', 't3lib_tree_pagetree_node' => PATH_t3lib . 'tree/pagetree/class.t3lib_tree_pagetree_node.php', - 't3lib_tree_extdirect_node' => PATH_t3lib . 'tree/extdirect/class.t3lib_tree_extdirect_node.php', + 't3lib_tree_extjs_node' => PATH_t3lib . 'tree/extjs/class.t3lib_tree_extjs_node.php', + 't3lib_tree_navigationtree_node' => PATH_t3lib . 'tree/navigationtree/class.t3lib_tree_navigationtree_node.php', 't3lib_tree_pagetree_nodecollection' => PATH_t3lib . 'tree/pagetree/class.t3lib_tree_pagetree_nodecollection.php', 't3lib_tree_pagetree_commands' => PATH_t3lib . 'tree/pagetree/class.t3lib_tree_pagetree_commands.php', 't3lib_contextmenu_pagetree_dataprovider' => PATH_t3lib . 'contextmenu/pagetree/class.t3lib_contextmenu_pagetree_dataprovider.php', @@ -238,4 +238,4 @@ $t3libClasses = array( $tslibClasses = require(PATH_typo3 . 'sysext/cms/ext_autoload.php'); return array_merge($t3libClasses, $tslibClasses); -?> \ No newline at end of file +?> diff --git a/t3lib/js/extjs/components/pagetree/javascript/Ext.ux.state.TreePanel.js b/t3lib/js/extjs/components/pagetree/javascript/Ext.ux.state.TreePanel.js index 348d94cb900ae39cf8189e959c2ffba88c761b13..a781831f2d4b3b2ba5b26e5e98e7d9a70a0eb4c9 100644 --- a/t3lib/js/extjs/components/pagetree/javascript/Ext.ux.state.TreePanel.js +++ b/t3lib/js/extjs/components/pagetree/javascript/Ext.ux.state.TreePanel.js @@ -23,126 +23,117 @@ * * 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, { +Ext.define('Ext.ux.state.TreePanel', { + extend: 'Ext.state.Stateful', + /** - * Initializes the plugin - * @param {Ext.tree.TreePanel} tree - * @private + * Mixin constructor + * @param {Object} config + * */ - 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; - } - var saveID = n.id; - this.stateHash[saveID.substr(1)] = 1; - }, - - // delete path and all subpaths of collapsed node from stateHash - beforecollapsenode:function(n) { - if (this.isRestoringState) { - return; - } - - var deleteID = n.id; - delete this.stateHash[deleteID.substr(1)]; - }, - - 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; - // get last selected node - for (var pageID in this.stateHash) { - var pageNode = this.getNodeById('p' + pageID); - if (pageNode) { - pageNode.on({ - expand: { - single:true, - scope:this, - fn: this.restoreState + constructor: function (config) { + if (config.stateful) { + // Install event handlers on TreePanel + this.on({ + // Add path of expanded node to stateHash + beforeitemexpand: function (node) { + if (this.isRestoringState) { + return; + } + this.stateHash[String(node.getNodeData('id'))] = node.getId(); + }, + // Delete collapsed node from stateHash + beforeitemcollapse: function (node) { + if (this.isRestoringState) { + return; + } + delete this.stateHash[String(node.getNodeData('id'))]; + }, + // Update last selected node in stateHash + selectionchange: function (view, node) { + this.onStateChange(); + if (this.isRestoringState) { + return; + } + if (this.getSelectionModel().getLastSelected()) { + this.stateHash['lastSelectedNode'] = this.getSelectionModel().getLastSelected().getId(); + } + }, + scope: this + }); + // Add/override state properties + Ext.apply(this, { + // Update state on node expand, collapse or selection change + stateEvents: ['itemexpand', 'itemcollapse', 'selectionchange'], + // Avoid updating state while restoring + isRestoringState: false, + // State object + stateHash: {}, + /** + * Restore tree state into the saved state + * + */ + restoreState: function() { + if (this.stateful) { + this.isRestoringState = true; + // Expand paths according to stateHash + for (var pageID in this.stateHash) { + var pageNode = this.getStore().getNodeById(this.stateHash[pageID]); + if (pageNode && !pageNode.isLeaf() && !pageNode.isExpanded()) { + pageNode.on({ + expand: { + single: true, + scope: this, + fn: this.restoreState + } + }); + pageNode.set('expanded', true); + pageNode.commit(); + this.refreshNode(pageNode); + pageNode.fireEvent('expand', pageNode); } - }); - if (pageNode.expanded === false && pageNode.rendered == true) { - pageNode.expand(); } - } - } - if (this.stateHash['lastSelectedNode']) { - var node = this.getNodeById(this.stateHash['lastSelectedNode']); - if (node) { - this.selectPath(node.getPath()); - - var contentId = TYPO3.Backend.ContentContainer.getIdFromUrl() || - String(fsMod.recentIds['web']) || '-1'; - - var isCurrentSelectedNode = ( - String(node.attributes.nodeData.id) === contentId || - contentId.indexOf('pages' + String(node.attributes.nodeData.id)) !== -1 - ); - - if (contentId !== '-1' && !isCurrentSelectedNode && this.app.isVisible() && - this.commandProvider && this.commandProvider.singleClick - ) { - this.commandProvider.singleClick(node, this); + // Get last selected node + if (this.stateHash['lastSelectedNode']) { + var node = this.getStore().getNodeById(this.stateHash['lastSelectedNode']); + if (node) { + this.selectPath(node.getPath()); + + var contentId = TYPO3.Backend.ContentContainer.getIdFromUrl() || + String(fsMod.recentIds['web']) || '-1'; + + var isCurrentSelectedNode = ( + String(node.getNodeData('id')) === contentId || + contentId.indexOf('pages' + node.getNodeData('id')) !== -1 + ); + + if (contentId !== '-1' + && !isCurrentSelectedNode + && this == this.app.getTree() + && this.commandProvider + && this.commandProvider.singleClick + ) { + this.commandProvider.singleClick(node, this); + } + } } + this.isRestoringState = false; } + }, + /** + * Return stateHash for save by state manager + * + */ + getState: function() { + return { + stateHash: this.stateHash + }; } - - 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}; - } - }); + }); + this.callParent(arguments); + } } }); diff --git a/t3lib/js/extjs/components/pagetree/javascript/actions.js b/t3lib/js/extjs/components/pagetree/javascript/actions.js index 1dbb5b03ea961297f5a5429a5781da9b40952087..3b4947450931cc03383d79b235882c1ed85e7069 100644 --- a/t3lib/js/extjs/components/pagetree/javascript/actions.js +++ b/t3lib/js/extjs/components/pagetree/javascript/actions.js @@ -61,8 +61,8 @@ TYPO3.Components.PageTree.Actions = { tree.t3ContextInfo.inCopyMode = false; if (tree.t3ContextNode) { - tree.t3ContextNode.attributes.nodeData.t3InCutMode = false; - tree.t3ContextNode.attributes.nodeData.t3InCopyMode = false; + tree.t3ContextNode.setNodeData('t3InCutMode', false); + tree.t3ContextNode.setNodeData('t3InCopyMode', false); tree.t3ContextNode = null; } }, @@ -71,51 +71,55 @@ TYPO3.Components.PageTree.Actions = { * Updates an existing node with the given alternative. The new tree node * is returned afterwards. * - * @param {Ext.tree.TreeNode} node + * @param {TYPO3.Components.PageTree.Tree} tree + * @param {TYPO3.Components.PageTree.Model} node * @param {Boolean} isExpanded * @param {Object} updatedNode * @param {Function} callback - * @return {Ext.tree.TreeNode} + * @return {Ext.data.NodeInterface} */ - updateNode: function(node, isExpanded, updatedNode, callback) { + updateNode: function(tree, node, isExpanded, updatedNode, callback) { if (!updatedNode) { return null; } - updatedNode.uiProvider = node.ownerTree.uiProvider; - var newTreeNode = new Ext.tree.TreeNode(updatedNode); + var newTreeNode = Ext.create('TYPO3.Components.PageTree.Model', updatedNode); var refreshCallback = this.restoreNodeStateAfterRefresh; if (callback) { - refreshCallback = refreshCallback.createSequence(callback); + refreshCallback = Ext.Function.createSequence(refreshCallback, callback); } node.parentNode.replaceChild(newTreeNode, node); - newTreeNode.ownerTree.refreshNode(newTreeNode, refreshCallback); - + newTreeNode.set('expanded', isExpanded); + tree.refreshNode(newTreeNode, refreshCallback, tree); return newTreeNode; }, /** * Restores the node state * - * @param {Ext.tree.TreeNode} node + * @param {TYPO3.Components.PageTree.Tree} tree + * @param {TYPO3.Components.PageTree.Model} node * @param {Boolean} isExpanded * @return {void} */ - restoreNodeStateAfterRefresh: function(node, isExpanded) { - node.parentNode.expand(false, false); - if (isExpanded) { - node.expand(false, false); - } else { - node.collapse(false, false); + restoreNodeStateAfterRefresh: function (records, operation, successful) { + if (successful && operation.node) { + var node = operation.node; + node.parentNode.expand(false); + if (node.isExpanded()) { + node.expand(false); + } else { + node.collapse(false); + } } }, /** * Shows deletion confirmation window * - * @param {Ext.tree.TreeNode} node + * @param {TYPO3.Components.PageTree.Model} node * @param {TYPO3.Components.PageTree.Tree} tree * @param {Function} callback * @param {Boolean} recursiveDelete @@ -130,10 +134,10 @@ TYPO3.Components.PageTree.Actions = { message = TYPO3.Components.PageTree.LLL.recursiveDeleteDialogMessage; } - Ext.Msg.show({ + Ext.MessageBox.show({ title: title, msg: message, - buttons: Ext.Msg.YESNO, + buttons: Ext.MessageBox.YESNO, fn: function (answer) { if (answer === 'yes') { TYPO3.Components.PageTree.Actions.deleteNode(node, tree, callback); @@ -141,21 +145,21 @@ TYPO3.Components.PageTree.Actions = { } return false; }, - animEl: 'elId' + animateTarget: tree.getView().getNode(node).id }); }, /** * Deletes a node directly * - * @param {Ext.tree.TreeNode} node + * @param {TYPO3.Components.PageTree.Model} node * @param {TYPO3.Components.PageTree.Tree} tree * @param {Function} callback * @return {void} */ deleteNode: function(node, tree, callback) { TYPO3.Components.PageTree.Commands.deleteNode( - node.attributes.nodeData, + node.get('nodeData'), function(response) { var succeeded = this.evaluateResponse(response); if (Ext.isFunction(callback)) { @@ -165,7 +169,7 @@ TYPO3.Components.PageTree.Actions = { if (succeeded) { // the node may not be removed in workspace mode if (top.TYPO3.configuration.inWorkspace && response.id) { - this.updateNode(node, node.isExpanded(), response); + this.updateNode(tree, node, node.isExpanded(), response); } else { node.remove(); } @@ -178,13 +182,13 @@ TYPO3.Components.PageTree.Actions = { /** * Removes a node either directly or first shows deletion popup * - * @param {Ext.tree.TreeNode} node + * @param {TYPO3.Components.PageTree.Model} node * @param {TYPO3.Components.PageTree.Tree} tree * @return {void} */ removeNode: function(node, tree) { if (TYPO3.Components.PageTree.Configuration.displayDeleteConfirmation) { - this.confirmDelete(node); + this.confirmDelete(node, tree); } else { this.deleteNode(node, tree); } @@ -194,19 +198,19 @@ TYPO3.Components.PageTree.Actions = { * Restores a given node and moves it to the given destination inside the tree. Use this * method if you want to add it as the first child of the destination. * - * @param {Ext.tree.TreeNode} node + * @param {Ext.data.NodeInterface} node * @param {TYPO3.Components.PageTree.Tree} tree - * @param {Ext.tree.TreeNode} destination + * @param {Ext.data.NodeInterface} destination * @return {void} */ restoreNodeToFirstChildOfDestination: function(node, tree, destination) { TYPO3.Components.PageTree.Commands.restoreNode( - node.attributes.nodeData, - destination.attributes.nodeData.id, - function(updatedNode) { + node.get('nodeData'), + destination.get('nodeData').id, + function (updatedNode) { if (this.evaluateResponse(updatedNode)) { - var newTreeNode = new Ext.tree.TreeNode( - Ext.apply(node.attributes, updatedNode) + var newTreeNode = Ext.create('TYPO3.Components.PageTree.Model', + Ext.apply(node.fields, updatedNode) ); destination.insertBefore(newTreeNode, destination.firstChild); } @@ -219,19 +223,19 @@ TYPO3.Components.PageTree.Actions = { * Restores a given node and moves it to the given destination inside the tree. Use this * method if you want to add the node after the destination node. * - * @param {Ext.tree.TreeNode} node + * @param {TYPO3.Components.PageTree.Model} node * @param {TYPO3.Components.PageTree.Tree} tree - * @param {Ext.tree.TreeNode} destination + * @param {TYPO3.Components.PageTree.Model} destination * @return {void} */ restoreNodeAfterDestination: function(node, tree, destination) { TYPO3.Components.PageTree.Commands.restoreNode( - node.attributes.nodeData, - -destination.attributes.nodeData.id, - function(updatedNode) { + node.get('nodeData'), + -destination.get('nodeData').id, + function (updatedNode) { if (this.evaluateResponse(updatedNode)) { - var newTreeNode = new Ext.tree.TreeNode( - Ext.apply(node.attributes, updatedNode) + var newTreeNode = Ext.create('TYPO3.Components.PageTree.Model', + Ext.apply(node.fields, updatedNode) ); destination.parentNode.insertBefore(newTreeNode, destination.nextSibling); } @@ -243,7 +247,7 @@ TYPO3.Components.PageTree.Actions = { /** * Collapses a whole tree branch * - * @param {Ext.tree.TreeNode} node + * @param {TYPO3.Components.PageTree.Model} node * @return {void} */ collapseBranch: function(node) { @@ -253,7 +257,7 @@ TYPO3.Components.PageTree.Actions = { /** * Expands a whole tree branch * - * @param {Ext.tree.TreeNode} node + * @param {TYPO3.Components.PageTree.Model} node * @return {void} */ expandBranch: function(node) { @@ -263,13 +267,13 @@ TYPO3.Components.PageTree.Actions = { /** * Opens a popup windows for previewing the given node/page * - * @param {Ext.tree.TreeNode} node + * @param {TYPO3.Components.PageTree.Model} node * @return {void} */ viewPage: function(node) { var frontendWindow = window.open('', 'newTYPO3frontendWindow'); TYPO3.Components.PageTree.Commands.getViewLink( - node.attributes.nodeData, + node.get('nodeData'), function(result) { frontendWindow.location = result; frontendWindow.focus(); @@ -280,13 +284,13 @@ TYPO3.Components.PageTree.Actions = { /** * Creates a temporary tree mount point * - * @param {Ext.tree.TreeNode} node + * @param {TYPO3.Components.PageTree.Model} node * @param {TYPO3.Components.PageTree.Tree} tree * @return {void} */ mountAsTreeRoot: function(node, tree) { TYPO3.Components.PageTree.Commands.setTemporaryMountPoint( - node.attributes.nodeData, + node.get('nodeData'), function(response) { if (TYPO3.Components.PageTree.Configuration.temporaryMountPoint) { TYPO3.Backend.NavigationContainer.PageTree.removeIndicator( @@ -297,19 +301,18 @@ TYPO3.Components.PageTree.Actions = { TYPO3.Components.PageTree.Configuration.temporaryMountPoint = response; TYPO3.Backend.NavigationContainer.PageTree.addTemporaryMountPointIndicator(); - var selectedNode = TYPO3.Backend.NavigationContainer.PageTree.getSelected(); + var selectedNode = tree.getSelectionModel().getLastSelected(); tree.stateId = 'Pagetree' + TYPO3.Components.PageTree.Configuration.temporaryMountPoint; - tree.refreshTree(function() { - var nodeIsSelected = false; + // Refresh tree and restore last selection if under the temporary mount + tree.refreshTree(function () { + var selectionModel = tree.getSelectionModel(); if (selectedNode) { - nodeIsSelected = TYPO3.Backend.NavigationContainer.PageTree.select( - selectedNode.attributes.nodeData.id - ); + selectionModel.deselect(selectedNode); + selectionModel.select(selectedNode); } - - var node = (nodeIsSelected ? TYPO3.Backend.NavigationContainer.PageTree.getSelected() : null); - if (node) { - this.singleClick(node, tree); + selectedNode = selectionModel.getLastSelected(); + if (selectedNode) { + this.singleClick(selectedNode, tree); } else { this.singleClick(tree.getRootNode().firstChild, tree); } @@ -322,63 +325,67 @@ TYPO3.Components.PageTree.Actions = { /** * Opens the edit page properties dialog * - * @param {Ext.tree.TreeNode} node + * @param {TYPO3.Components.PageTree.Model} node + * @param {TYPO3.Components.PageTree.Tree} tree * @return {void} */ - editPageProperties: function(node) { - node.select(); + editPageProperties: function(node, tree) { + tree.getSelectionModel().select(node); TYPO3.Backend.ContentContainer.setUrl( - 'alt_doc.php?edit[pages][' + node.attributes.nodeData.id + ']=edit' + 'alt_doc.php?edit[pages][' + node.getNodeData('id') + ']=edit' ); }, /** * Opens the new page wizard * - * @param {Ext.tree.TreeNode} node + * @param {TYPO3.Components.PageTree.Model} node + * @param {TYPO3.Components.PageTree.Tree} tree * @return {void} */ - newPageWizard: function(node) { - node.select(); + newPageWizard: function(node, tree) { + tree.getSelectionModel().select(node); TYPO3.Backend.ContentContainer.setUrl( - 'db_new.php?id=' + node.attributes.nodeData.id + '&pagesOnly=1' + 'db_new.php?id=' + node.getNodeData('id') + '&pagesOnly=1' ); }, /** * Opens the info popup * - * @param {Ext.tree.TreeNode} node + * @param {TYPO3.Components.PageTree.Model} node * @return {void} */ openInfoPopUp: function(node) { - launchView('pages', node.attributes.nodeData.id); + launchView('pages', node.getNodeData('id')); }, /** * Opens the history popup * - * @param {Ext.tree.TreeNode} node + * @param {TYPO3.Components.PageTree.Model} node + * @param {TYPO3.Components.PageTree.Tree} tree * @return {void} */ - openHistoryPopUp: function(node) { - node.select(); + openHistoryPopUp: function(node, tree) { + tree.getSelectionModel().select(node); TYPO3.Backend.ContentContainer.setUrl( - 'show_rechis.php?element=pages:' + node.attributes.nodeData.id + 'show_rechis.php?element=pages:' + node.getNodeData('id') ); }, /** * Opens the export .t3d file dialog * - * @param {Ext.tree.TreeNode} node + * @param {TYPO3.Components.PageTree.Model} node + * @param {TYPO3.Components.PageTree.Tree} tree * @return {void} */ - exportT3d: function(node) { - node.select(); + exportT3d: function(node, tree) { + tree.getSelectionModel().select(node); TYPO3.Backend.ContentContainer.setUrl( 'sysext/impexp/app/index.php?tx_impexp[action]=export&' + - 'id=0&tx_impexp[pagetree][id]=' + node.attributes.nodeData.id + + 'id=0&tx_impexp[pagetree][id]=' + node.getNodeData('id') + '&tx_impexp[pagetree][levels]=0' + '&tx_impexp[pagetree][tables][]=_ALL' ); @@ -387,13 +394,14 @@ TYPO3.Components.PageTree.Actions = { /** * Opens the import .t3d file dialog * - * @param {Ext.tree.TreeNode} node + * @param {TYPO3.Components.PageTree.Model} node + * @param {TYPO3.Components.PageTree.Tree} tree * @return {void} */ - importT3d: function(node) { - node.select(); + importT3d: function(node, tree) { + tree.getSelectionModel().select(node); TYPO3.Backend.ContentContainer.setUrl( - 'sysext/impexp/app/index.php?id=' + node.attributes.nodeData.id + + 'sysext/impexp/app/index.php?id=' + node.getNodeData('id') + '&table=pages&tx_impexp[action]=import' ); }, @@ -401,13 +409,13 @@ TYPO3.Components.PageTree.Actions = { /** * Enables the cut mode of a node * - * @param {Ext.tree.TreeNode} node + * @param {TYPO3.Components.PageTree.Model} node * @param {TYPO3.Components.PageTree.Tree} tree * @return {void} */ enableCutMode: function(node, tree) { this.disableCopyMode(node, tree); - node.attributes.nodeData.t3InCutMode = true; + node.setNodeData('t3InCutMode', true); tree.t3ContextInfo.inCutMode = true; tree.t3ContextNode = node; }, @@ -415,25 +423,25 @@ TYPO3.Components.PageTree.Actions = { /** * Disables the cut mode of a node * - * @param {Ext.tree.TreeNode} node + * @param {TYPO3.Components.PageTree.Model} node * @param {TYPO3.Components.PageTree.Tree} tree * @return {void} */ disableCutMode: function(node, tree) { this.releaseCutAndCopyModes(tree); - node.attributes.nodeData.t3InCutMode = false; + node.setNodeData('t3InCutMode', false); }, /** * Enables the copy mode of a node * - * @param {Ext.tree.TreeNode} node + * @param {TYPO3.Components.PageTree.Model} node * @param {TYPO3.Components.PageTree.Tree} tree * @return {void} */ enableCopyMode: function(node, tree) { this.disableCutMode(node, tree); - node.attributes.nodeData.t3InCopyMode = true; + node.setNodeData('t3InCopyMode', true); tree.t3ContextInfo.inCopyMode = true; tree.t3ContextNode = node; }, @@ -441,19 +449,19 @@ TYPO3.Components.PageTree.Actions = { /** * Disables the copy mode of a node * - * @param {Ext.tree.TreeNode} node + * @param {TYPO3.Components.PageTree.Model} node * @param {TYPO3.Components.PageTree.Tree} tree * @return {void} */ disableCopyMode: function(node, tree) { this.releaseCutAndCopyModes(tree); - node.attributes.nodeData.t3InCopyMode = false; + node.setNodeData('t3InCopyMode', false); }, /** * Pastes the cut/copy context node into the given node * - * @param {Ext.tree.TreeNode} node + * @param {TYPO3.Components.PageTree.Model} node * @param {TYPO3.Components.PageTree.Tree} tree * @return {void} */ @@ -463,10 +471,10 @@ TYPO3.Components.PageTree.Actions = { } if (tree.t3ContextInfo.inCopyMode) { - var newNode = tree.t3ContextNode = new Ext.tree.TreeNode(tree.t3ContextNode.attributes); + var newNode = tree.t3ContextNode = Ext.create('TYPO3.Components.PageTree.Model', tree.t3ContextNode.fields); newNode.id = 'fakeNode'; node.insertBefore(newNode, node.childNodes[0]); - node.attributes.nodeData.t3InCopyMode = false; + node.setNodeData('t3InCopyMode', false); this.copyNodeToFirstChildOfDestination(newNode, tree); } else if (tree.t3ContextInfo.inCutMode) { @@ -475,7 +483,7 @@ TYPO3.Components.PageTree.Actions = { } node.appendChild(tree.t3ContextNode); - node.attributes.nodeData.t3InCutMode = false; + node.setNodeData('t3InCutMode', false); this.moveNodeToFirstChildOfDestination(node, tree); } }, @@ -483,7 +491,7 @@ TYPO3.Components.PageTree.Actions = { /** * Pastes a cut/copy context node after the given node * - * @param {Ext.tree.TreeNode} node + * @param {TYPO3.Components.PageTree.Model} node * @param {TYPO3.Components.PageTree.Tree} tree * @return {void} */ @@ -493,19 +501,18 @@ TYPO3.Components.PageTree.Actions = { } if (tree.t3ContextInfo.inCopyMode) { - var newNode = tree.t3ContextNode = new Ext.tree.TreeNode(tree.t3ContextNode.attributes); + var newNode = tree.t3ContextNode = Ext.create('TYPO3.Components.PageTree.Model', tree.t3ContextNode.fields); newNode.id = 'fakeNode'; node.parentNode.insertBefore(newNode, node.nextSibling); - node.attributes.nodeData.t3InCopyMode = false; + node.setNodeData('t3InCopyMode', false); this.copyNodeAfterDestination(newNode, tree); } else if (tree.t3ContextInfo.inCutMode) { if (node.getPath().indexOf(tree.t3ContextNode.id) !== -1) { return; } - node.parentNode.insertBefore(tree.t3ContextNode, node.nextSibling); - node.attributes.nodeData.t3InCutMode = false; + node.setNodeData('t3InCutMode', false); this.moveNodeAfterDestination(node, tree); } }, @@ -513,17 +520,17 @@ TYPO3.Components.PageTree.Actions = { /** * Moves the current tree context node after the given node * - * @param {Ext.tree.TreeNode} node + * @param {TYPO3.Components.PageTree.Model} node * @param {TYPO3.Components.PageTree.Tree} tree * @return {void} */ moveNodeAfterDestination: function(node, tree) { TYPO3.Components.PageTree.Commands.moveNodeAfterDestination( - tree.t3ContextNode.attributes.nodeData, - node.attributes.nodeData.id, - function(response) { + tree.t3ContextNode.get('nodeData'), + node.getNodeData('id'), + function (response) { if (this.evaluateResponse(response) && tree.t3ContextNode) { - this.updateNode(tree.t3ContextNode, tree.t3ContextNode.isExpanded(), response); + this.updateNode(tree, tree.t3ContextNode, tree.t3ContextNode.isExpanded(), response); } this.releaseCutAndCopyModes(tree); }, @@ -534,17 +541,17 @@ TYPO3.Components.PageTree.Actions = { /** * Moves the current tree context node as the first child of the given node * - * @param {Ext.tree.TreeNode} node + * @param {TYPO3.Components.PageTree.Model} node * @param {TYPO3.Components.PageTree.Tree} tree * @return {void} */ moveNodeToFirstChildOfDestination: function(node, tree) { TYPO3.Components.PageTree.Commands.moveNodeToFirstChildOfDestination( - tree.t3ContextNode.attributes.nodeData, - node.attributes.nodeData.id, - function(response) { + tree.t3ContextNode.get('nodeData'), + node.getNodeData('id'), + function (response) { if (this.evaluateResponse(response) && tree.t3ContextNode) { - this.updateNode(tree.t3ContextNode, tree.t3ContextNode.isExpanded(), response); + this.updateNode(tree, tree.t3ContextNode, tree.t3ContextNode.isExpanded(), response); } this.releaseCutAndCopyModes(tree); }, @@ -555,19 +562,21 @@ TYPO3.Components.PageTree.Actions = { /** * Inserts a new node after the given node * - * @param {Ext.tree.TreeNode} node + * @param {TYPO3.Components.PageTree.Model} node * @param {TYPO3.Components.PageTree.Tree} tree * @return {void} */ - insertNodeAfterDestination: function(node, tree) { + insertNodeAfterDestination: function (node, tree) { TYPO3.Components.PageTree.Commands.insertNodeAfterDestination( - tree.t3ContextNode.attributes.nodeData, - node.previousSibling.attributes.nodeData.id, + tree.t3ContextNode.get('nodeData'), + node.previousSibling.getNodeData('id'), tree.t3ContextInfo.serverNodeType, - function(response) { + function (response) { if (this.evaluateResponse(response)) { - this.updateNode(node, node.isExpanded(), response, function(node) { - tree.triggerEdit(node); + this.updateNode(tree, node, node.isExpanded(), response, function (records, operation, successful) { + if (successful && operation.node) { + tree.getPlugin('treeEditor').startEdit(operation.node, tree.getView().getHeaderAtIndex(0)); + } }); } this.releaseCutAndCopyModes(tree); @@ -579,18 +588,20 @@ TYPO3.Components.PageTree.Actions = { /** * Inserts a new node as the first child of the given node * - * @param {Ext.tree.TreeNode} node + * @param {TYPO3.Components.PageTree.Model} node * @param {TYPO3.Components.PageTree.Tree} tree * @return {void} */ insertNodeToFirstChildOfDestination: function(node, tree) { TYPO3.Components.PageTree.Commands.insertNodeToFirstChildOfDestination( - tree.t3ContextNode.attributes.nodeData, + tree.t3ContextNode.get('nodeData'), tree.t3ContextInfo.serverNodeType, - function(response) { + function (response) { if (this.evaluateResponse(response)) { - this.updateNode(node, true, response, function(node) { - tree.triggerEdit(node); + this.updateNode(tree, node, true, response, function (records, operation, successful) { + if (successful && operation.node) { + tree.getPlugin('treeEditor').startEdit(operation.node, tree.getView().getHeaderAtIndex(0)); + } }); } this.releaseCutAndCopyModes(tree); @@ -602,18 +613,20 @@ TYPO3.Components.PageTree.Actions = { /** * Copies the current tree context node after the given node * - * @param {Ext.tree.TreeNode} node + * @param {TYPO3.Components.PageTree.Model} node * @param {TYPO3.Components.PageTree.Tree} tree * @return {void} */ copyNodeAfterDestination: function(node, tree) { TYPO3.Components.PageTree.Commands.copyNodeAfterDestination( - tree.t3ContextNode.attributes.nodeData, - node.previousSibling.attributes.nodeData.id, - function(response) { + tree.t3ContextNode.get('nodeData'), + node.previousSibling.getNodeData('id'), + function (response) { if (this.evaluateResponse(response)) { - this.updateNode(node, true, response, function(node) { - tree.triggerEdit(node); + this.updateNode(tree, node, true, response, function (records, operation, successful) { + if (successful && operation.node) { + tree.getPlugin('treeEditor').startEdit(operation.node, tree.getView().getHeaderAtIndex(0)); + } }); } this.releaseCutAndCopyModes(tree); @@ -625,18 +638,20 @@ TYPO3.Components.PageTree.Actions = { /** * Copies the current tree context node as the first child of the given node * - * @param {Ext.tree.TreeNode} node + * @param {TYPO3.Components.PageTree.Model} node * @param {TYPO3.Components.PageTree.Tree} tree * @return {void} */ copyNodeToFirstChildOfDestination: function(node, tree) { TYPO3.Components.PageTree.Commands.copyNodeToFirstChildOfDestination( - tree.t3ContextNode.attributes.nodeData, - node.parentNode.attributes.nodeData.id, - function(response) { + tree.t3ContextNode.get('nodeData'), + node.parentNode.getNodeData('id'), + function (response) { if (this.evaluateResponse(response)) { - this.updateNode(node, true, response, function(node) { - tree.triggerEdit(node); + this.updateNode(tree, node, true, response, function (records, operation, successful) { + if (successful && operation.node) { + tree.getPlugin('treeEditor').startEdit(operation.node, tree.getView().getHeaderAtIndex(0)); + } }); } this.releaseCutAndCopyModes(tree); @@ -648,15 +663,16 @@ TYPO3.Components.PageTree.Actions = { /** * Visibilizes a page * - * @param {Ext.tree.TreeNode} node + * @param {Ext.data.NodeInterface} node + * @param {TYPO3.Components.PageTree.Tree} tree * @return {void} */ - enablePage: function(node) { + enablePage: function(node, tree) { TYPO3.Components.PageTree.Commands.visiblyNode( - node.attributes.nodeData, + node.get('nodeData'), function(response) { if (this.evaluateResponse(response)) { - this.updateNode(node, node.isExpanded(), response); + this.updateNode(tree, node, node.isExpanded(), response); } }, this @@ -666,15 +682,16 @@ TYPO3.Components.PageTree.Actions = { /** * Disables a page * - * @param {Ext.tree.TreeNode} node + * @param {Ext.data.NodeInterface} node + * @param {TYPO3.Components.PageTree.Tree} tree * @return {void} */ - disablePage: function(node) { + disablePage: function(node, tree) { TYPO3.Components.PageTree.Commands.disableNode( - node.attributes.nodeData, - function(response) { + node.get('nodeData'), + function (response) { if (this.evaluateResponse(response)) { - this.updateNode(node, node.isExpanded(), response); + this.updateNode(tree, node, node.isExpanded(), response); } }, this @@ -684,11 +701,11 @@ TYPO3.Components.PageTree.Actions = { /** * Reloads the content frame with the current module and node id * - * @param {Ext.tree.TreeNode} node + * @param {TYPO3.Components.PageTree.Model} node * @param {TYPO3.Components.PageTree.Tree} tree * @return {void} */ - singleClick: function(node, tree) { + singleClick: function (node, tree) { tree.currentSelectedNode = node; var separator = '?'; @@ -696,68 +713,77 @@ TYPO3.Components.PageTree.Actions = { separator = '&'; } - node.select(); - if (tree.stateHash) { - tree.stateHash.lastSelectedNode = node.id; - } + tree.getSelectionModel().select(node); - fsMod.recentIds['web'] = node.attributes.nodeData.id; + fsMod.recentIds['web'] = node.getNodeData('id'); TYPO3.Backend.ContentContainer.setUrl( - TS.PATH_typo3 + currentSubScript + separator + 'id=' + node.attributes.nodeData.id + TS.PATH_typo3 + currentSubScript + separator + 'id=' + node.getNodeData('id') ); }, /** * Opens a configured url inside the content frame * - * @param {Ext.tree.TreeNode} node + * @param {TYPO3.Components.PageTree.Model} node * @param {TYPO3.Components.PageTree.Tree} tree * @param {Object} contextItem * @return {void} */ - openCustomUrlInContentFrame: function(node, tree, contextItem) { + openCustomUrlInContentFrame: function (node, tree, contextItem) { if (!contextItem.customAttributes || !contextItem.customAttributes.contentUrl) { return; } - node.select(); + tree.getSelectionModel().select(node); TYPO3.Backend.ContentContainer.setUrl( - contextItem.customAttributes.contentUrl.replace('###ID###', node.attributes.nodeData.id) + contextItem.customAttributes.contentUrl.replace('###ID###', node.getNodeData('id')) ); }, /** * Updates the title of a node * - * @param {Ext.tree.TreeNode} node + * @param {TYPO3.Components.PageTree.Model} node * @param {String} newText * @param {String} oldText * @param {TYPO3.Components.PageTree.TreeEditor} treeEditor + * @param {TYPO3.Components.PageTree.Tree} tree + * @param {String} dataIndex * @return {void} */ - saveTitle: function(node, newText, oldText, treeEditor) { - this.singleClick(node.editNode, node.editNode.ownerTree); + saveTitle: function (node, newText, oldText, treeEditor, tree, dataIndex) { + this.singleClick(node, tree); if (newText === oldText || newText == '') { treeEditor.updateNodeText( node, - node.editNode.attributes.nodeData.editableText, - Ext.util.Format.htmlEncode(oldText) + node.getNodeData('editableText'), + Ext.util.Format.htmlEncode(oldText), + dataIndex, + tree ); return; } TYPO3.Components.PageTree.Commands.updateLabel( - node.editNode.attributes.nodeData, + node.get('nodeData'), newText, function(response) { if (this.evaluateResponse(response)) { - treeEditor.updateNodeText(node, response.editableText, response.updatedText); + treeEditor.updateNodeText( + node, + response.editableText, + response.updatedText, + dataIndex, + tree + ); } else { treeEditor.updateNodeText( node, - node.editNode.attributes.nodeData.editableText, - Ext.util.Format.htmlEncode(oldText) + node.getNodeData('editableText'), + Ext.util.Format.htmlEncode(oldText), + dataIndex, + tree ); } }, diff --git a/t3lib/js/extjs/components/pagetree/javascript/app.js b/t3lib/js/extjs/components/pagetree/javascript/app.js index 6a178f5921a17fdeef4d826158e41a9b98d92f71..2701f93c47a6ed39f31b13bb1ed24f410f2684aa 100644 --- a/t3lib/js/extjs/components/pagetree/javascript/app.js +++ b/t3lib/js/extjs/components/pagetree/javascript/app.js @@ -23,18 +23,18 @@ * * 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 + * @extends Ext.panel.Panel * @author Stefan Galinski <stefan.galinski@gmail.com> */ -TYPO3.Components.PageTree.App = Ext.extend(Ext.Panel, { +Ext.define('TYPO3.Components.PageTree.App', { + extend: 'Ext.panel.Panel', + /** * Panel id * @@ -45,7 +45,7 @@ TYPO3.Components.PageTree.App = Ext.extend(Ext.Panel, { /** * Border * - * @type {Boolean} + * @type {String} */ border: false, @@ -54,14 +54,38 @@ TYPO3.Components.PageTree.App = Ext.extend(Ext.Panel, { * * @type {String} */ - layout:'fit', + layout: 'border', /** - * Active tree + * Components defaults * - * @type {TYPO3.Components.PageTree.Tree} + * @type {Object} */ - activeTree: null, + defaults: { + border: false, + }, + + /** + * Tree containe + * + * @type {String} + */ + items: [{ + itemId: 'topPanelItems', + height: 49, + region: 'north', + cls: 'typo3-pageTree-topPanelItems' + },{ + itemId: 'treeContainer', + autoScroll: false, + layout: 'card', + region: 'center' + },{ + xtype: 'container', + itemId: 'deletionDropZoneContainer', + cls: 'typo3-pageTree-deletionDropZoneContainer', + region: 'south' + }], /** * Initializes the application @@ -72,112 +96,89 @@ TYPO3.Components.PageTree.App = Ext.extend(Ext.Panel, { * @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 = this.activeTree = new TYPO3.Components.PageTree.Tree({ - id: this.id + '-tree', - deletionDropZoneId: this.id + '-deletionDropZone', - ddGroup: this.id, - stateful: true, - stateId: 'Pagetree' + TYPO3.Components.PageTree.Configuration.temporaryMountPoint, - stateEvents: [], - autoScroll: true, - autoHeight: false, - plugins: new Ext.ux.state.TreePanel(), - commandProvider: TYPO3.Components.PageTree.Actions, - contextMenuProvider: TYPO3.Components.PageTree.ContextMenuDataProvider, - treeDataProvider: TYPO3.Components.PageTree.DataProvider, - app: this, - listeners: { - resize: { - fn: function() { - var treeContainer = Ext.getCmp(this.id + '-treeContainer'); - Ext.getCmp(this.id + '-filteringTree').setSize(treeContainer.getSize()); - treeContainer.doLayout(); - }, - scope: this, - buffer: 250 - } - } - }); - - var filteringTree = new TYPO3.Components.PageTree.FilteringTree({ - id: this.id + '-filteringTree', - deletionDropZoneId: this.id + '-deletionDropZone', - ddGroup: this.id, - autoScroll: true, - autoHeight: false, - commandProvider: TYPO3.Components.PageTree.Actions, - contextMenuProvider: TYPO3.Components.PageTree.ContextMenuDataProvider, - treeDataProvider: TYPO3.Components.PageTree.DataProvider, - app: this - }).hide(); - - var topPanel = new TYPO3.Components.PageTree.TopPanel({ - dataProvider: TYPO3.Components.PageTree.DataProvider, - filteringTree: filteringTree, - ddGroup: this.id, - tree: tree, - app: this - }); - - var deletionDropZone = new TYPO3.Components.PageTree.DeletionDropZone({ - id: this.id + '-deletionDropZone', - commandProvider: TYPO3.Components.PageTree.Actions, - ddGroup: this.id, - app: this, - region: 'south', - height: 35 - }); - - var topPanelItems = new Ext.Panel({ - id: this.id + '-topPanelItems', - border: false, - region: 'north', - height: 49, - items: [ - topPanel, { - border: false, - id: this.id + '-indicatorBar' - } - ] - }); - - this.add({ - layout: 'border', - items: [ - topPanelItems, - { - border: false, - id: this.id + '-treeContainer', - region: 'center', - layout: 'fit', - items: [tree, filteringTree] - }, - deletionDropZone - ] - }); - - if (TYPO3.Components.PageTree.Configuration.temporaryMountPoint) { - topPanelItems.on('afterrender', function() { + this.addListener('render', 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 = Ext.create('TYPO3.Components.PageTree.Tree', { + id: this.getId() + '-tree', + deletionDropZoneId: this.getId() + '-deletionDropZone', + ddGroup: this.getId(), + stateful: true, + stateId: 'Pagetree' + TYPO3.Components.PageTree.Configuration.temporaryMountPoint, + commandProvider: TYPO3.Components.PageTree.Actions, + contextMenuProvider: TYPO3.Components.PageTree.ContextMenuDataProvider, + treeDataProvider: TYPO3.Components.PageTree.DataProvider, + app: this + }); + + var filteringTree = Ext.create('TYPO3.Components.PageTree.FilteringTree', { + id: this.getId() + '-filteringTree', + deletionDropZoneId: this.getId() + '-deletionDropZone', + ddGroup: this.getId(), + commandProvider: TYPO3.Components.PageTree.Actions, + contextMenuProvider: TYPO3.Components.PageTree.ContextMenuDataProvider, + stateful: false, + treeDataProvider: TYPO3.Components.PageTree.DataProvider, + app: this + }); + + var topPanelItems = this.getComponent('topPanelItems'); + topPanelItems.add([ + Ext.create('TYPO3.Components.PageTree.TopPanel', { + border: false, + dataProvider: TYPO3.Components.PageTree.DataProvider, + filteringTree: filteringTree, + ddGroup: this.getId(), + height: 49, + itemId: 'topPanel', + tree: tree, + app: this + }), + { + xtype: 'container', + border: false, + defaultType: 'component', + id: this.getId() + '-indicatorBar', + itemId: 'indicatorBar' + } + ]); + + var treeContainer = this.getComponent('treeContainer'); + treeContainer.add([tree, filteringTree]); + treeContainer.addListener( + 'render', + function (panel) { panel.getLayout().setActiveItem(0); } + ); + + var deletionDropZoneContainer = this.getComponent('deletionDropZoneContainer'); + deletionDropZoneContainer.add({ + xtype: 'typo3deletiondropzone', + height: 35, + id: this.getId() + '-deletionDropZone', + commandProvider: TYPO3.Components.PageTree.Actions, + ddGroup: this.getId(), + layout: 'anchor', + app: this + }); + + if (TYPO3.Components.PageTree.Configuration.temporaryMountPoint) { this.addTemporaryMountPointIndicator(); - }, this); - } - - if (TYPO3.Components.PageTree.Configuration.indicator !== '') { - this.addIndicatorItems(); - } - this.doLayout(); - - this.ownerCt.on('resize', function() { + } + + if (TYPO3.Components.PageTree.Configuration.indicator !== '') { + this.addIndicatorItems(); + } this.doLayout(); - }); + + this.ownerCt.on('resize', function() { + this.doLayout(); + }, this); + }, this); }, this); - - TYPO3.Components.PageTree.App.superclass.initComponent.apply(this, arguments); + this.callParent(); }, /** @@ -187,9 +188,8 @@ TYPO3.Components.PageTree.App = Ext.extend(Ext.Panel, { */ addIndicatorItems: function() { this.addIndicator({ - border: false, - id: this.id + '-indicatorBar-indicatorTitle', - cls: this.id + '-indicatorBar-item', + id: this.getId() + '-indicatorBar-indicatorTitle', + cls: this.getId() + '-indicatorBar-item', html: TYPO3.Components.PageTree.Configuration.indicator }); }, @@ -201,14 +201,13 @@ TYPO3.Components.PageTree.App = Ext.extend(Ext.Panel, { */ addTemporaryMountPointIndicator: function() { this.temporaryMountPointInfoIndicator = this.addIndicator({ - border: false, - id: this.id + '-indicatorBar-temporaryMountPoint', - cls: this.id + '-indicatorBar-item', + id: this.getId() + '-indicatorBar-temporaryMountPoint', + cls: this.getId() + '-indicatorBar-item', listeners: { afterrender: { fn: function() { - var element = Ext.fly(this.id + '-indicatorBar-temporaryMountPoint-clear'); + var element = Ext.get(this.getId() + '-indicatorBar-temporaryMountPoint-clear'); element.on('click', function() { TYPO3.BackendUserSettings.ExtDirect.unsetKey( 'pageTree_temporaryMountPoint', @@ -225,18 +224,21 @@ TYPO3.Components.PageTree.App = Ext.extend(Ext.Panel, { scope: this } }, - - html: '<p>' + - '<span id="' + this.id + '-indicatorBar-temporaryMountPoint-info' + '" ' + - 'class="' + this.id + '-indicatorBar-item-leftIcon ' + - TYPO3.Components.PageTree.Sprites.Info + '"> ' + - '</span>' + - '<span id="' + this.id + '-indicatorBar-temporaryMountPoint-clear' + '" ' + - 'class="' + this.id + '-indicatorBar-item-rightIcon ' + '">X' + - '</span>' + - TYPO3.Components.PageTree.LLL.temporaryMountPointIndicatorInfo + '<br />' + - TYPO3.Components.PageTree.Configuration.temporaryMountPoint + + renderData: { + appId: this.getId(), + spriteIconCls: TYPO3.Components.PageTree.Sprites.Info, + label: TYPO3.Components.PageTree.LLL.temporaryMountPointIndicatorInfo, + mountPoint: TYPO3.Components.PageTree.Configuration.temporaryMountPoint + }, + renderTpl: Ext.create('Ext.XTemplate', + '<p>', + '<span id="{appId}-indicatorBar-temporaryMountPoint-info" class="{appId}-indicatorBar-item-leftIcon {spriteIconCls}"> </span>', + '{label}', + '<span id="{appId}-indicatorBar-temporaryMountPoint-clear" class="{appId}-indicatorBar-item-rightIcon t3-icon t3-icon-actions t3-icon-actions-input t3-icon-input-clear t3-tceforms-input-clearer"> </span>', + '</p>', + '<p>{mountPoint}', '</p>' + ) }); }, @@ -248,23 +250,18 @@ TYPO3.Components.PageTree.App = Ext.extend(Ext.Panel, { */ addIndicator: function(component) { if (component.listeners && component.listeners.afterrender) { - component.listeners.afterrender.fn = component.listeners.afterrender.fn.createSequence( - this.afterTopPanelItemAdded, this - ); + component.listeners.afterrender.fn = Ext.Function.createSequence(component.listeners.afterrender.fn, this.afterTopPanelItemAdded, this); } else { - if (component.listeners) { - component.listeners = {} + if (!component.listeners) { + component.listeners = {}; } - component.listeners.afterrender = { scope: this, fn: this.afterTopPanelItemAdded } } - - var indicator = Ext.getCmp(this.id + '-indicatorBar').add(component); - this.doLayout(); - + var indicatorBar = this.down('component[itemId=indicatorBar]'); + var indicator = indicatorBar.add(component); return indicator; }, @@ -275,8 +272,15 @@ TYPO3.Components.PageTree.App = Ext.extend(Ext.Panel, { * @return {void} */ afterTopPanelItemAdded: function(component) { - var topPanelItems = Ext.getCmp(this.id + '-topPanelItems'); - topPanelItems.setHeight(topPanelItems.getHeight() + component.getHeight() + 3); + var topPanel = this.down('component[itemId=topPanel]'); + var indicatorBar = this.down('component[itemId=indicatorBar]'); + var height = 0; + indicatorBar.items.each(function (item) { + height += item.getHeight() + 3; + }); + indicatorBar.setHeight(height); + topPanelItems = this.down('component[itemId=topPanelItems]'); + topPanelItems.setHeight(topPanel.getHeight() + indicatorBar.getHeight()); this.doLayout(); }, @@ -287,9 +291,9 @@ TYPO3.Components.PageTree.App = Ext.extend(Ext.Panel, { * @return {void} */ removeIndicator: function(component) { - var topPanelItems = Ext.getCmp(this.id + '-topPanelItems'); + var topPanelItems = this.down('component[itemId=topPanelItems]'); topPanelItems.setHeight(topPanelItems.getHeight() - component.getHeight() - 3); - Ext.getCmp(this.id + '-indicatorBar').remove(component); + Ext.getCmp(this.getId() + '-indicatorBar').remove(component); this.doLayout(); }, @@ -318,11 +322,11 @@ TYPO3.Components.PageTree.App = Ext.extend(Ext.Panel, { */ refreshTree: function() { if (!isNaN(fsMod.recentIds['web']) && fsMod.recentIds['web'] !== '') { - this.select(fsMod.recentIds['web'], true); + this.select(fsMod.recentIds['web']); } TYPO3.Components.PageTree.DataProvider.getIndicators(function(response) { - var indicators = Ext.getCmp(this.id + '-indicatorBar-indicatorTitle'); + var indicators = Ext.getCmp(this.getId() + '-indicatorBar-indicatorTitle'); if (indicators) { this.removeIndicator(indicators); } @@ -333,7 +337,7 @@ TYPO3.Components.PageTree.App = Ext.extend(Ext.Panel, { } }, this); - this.activeTree.refreshTree(); + this.getTree().refreshTree(); }, /** @@ -342,43 +346,44 @@ TYPO3.Components.PageTree.App = Ext.extend(Ext.Panel, { * @return {TYPO3.Components.PageTree.Tree} */ getTree: function() { - return this.activeTree; + return this.down('component[itemId=treeContainer]').getLayout().getActiveItem(); }, /** - * Selects a node defined by the page id. If the second parameter is set, we - * store the new location into the state hash. + * Sets the current active tree + * @param {TYPO3.Components.PageTree.Tree} tree + * @return {TYPO3.Components.PageTree.Tree} + */ + setTree: function(tree) { + var layout = this.down('component[itemId=treeContainer]').getLayout(); + layout.setActiveItem(tree); + return layout.getActiveItem(tree); + }, + + /** + * Selects a node defined by the page id. * * @param {int} pageId - * @param {Boolean} saveState * @return {Boolean} */ - select: function(pageId, saveState) { - if (saveState !== false) { - saveState = true; - } - + select: function(pageId) { 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) { - tree.stateHash.lastSelectedNode = node.id; - } } - return succeeded; }, /** * Returns the currently selected node * - * @return {Ext.tree.TreeNode} + * @return {Ext.data.NodeInterface} */ getSelected: function() { - var node = this.getTree().getSelectionModel().getSelectedNode(); + var node = this.getTree().getSelectionModel().getLastSelected(); return node ? node : null; } }); @@ -389,15 +394,12 @@ TYPO3.Components.PageTree.App = Ext.extend(Ext.Panel, { * @return {TYPO3.Components.PageTree.App} */ TYPO3.ModuleMenu.App.registerNavigationComponent('typo3-pagetree', function() { - TYPO3.Backend.NavigationContainer.PageTree = new TYPO3.Components.PageTree.App(); + TYPO3.Backend.NavigationContainer.PageTree = Ext.create('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; + 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/t3lib/js/extjs/components/pagetree/javascript/contextmenu.js b/t3lib/js/extjs/components/pagetree/javascript/contextmenu.js index 32501b69f334eb1d66e489b917a9bb938ce10d1a..5c6ed687aa82b4189688e60b6cd0ac1c8e7b9269 100644 --- a/t3lib/js/extjs/components/pagetree/javascript/contextmenu.js +++ b/t3lib/js/extjs/components/pagetree/javascript/contextmenu.js @@ -23,8 +23,6 @@ * * This copyright notice MUST APPEAR in all copies of the script! ***************************************************************/ -Ext.namespace('TYPO3.Components.PageTree'); - /** * @class TYPO3.Components.PageTree.ContextMenu * @@ -34,11 +32,12 @@ Ext.namespace('TYPO3.Components.PageTree'); * @extends Ext.menu.Menu * @author Stefan Galinski <stefan.galinski@gmail.com> */ -TYPO3.Components.PageTree.ContextMenu = Ext.extend(Ext.menu.Menu, { +Ext.define('TYPO3.Components.PageTree.ContextMenu', { + extend: 'Ext.menu.Menu', /** * Context menu node * - * @cfg {Ext.tree.TreeNode} + * @cfg {TYPO3.Components.PageTree.Model} */ node: null, @@ -66,15 +65,15 @@ TYPO3.Components.PageTree.ContextMenu = Ext.extend(Ext.menu.Menu, { /** * Listeners * - * The itemclick event triggers the configured single click action + * The click event triggers the configured single click action */ listeners: { - itemclick: { - fn: function (item) { - if (this.pageTree.commandProvider[item.callbackAction]) { + click: { + fn: function (menu, item) { + if (item && this.pageTree.commandProvider[item.callbackAction]) { if (item.parentMenu.pageTree.stateHash) { - fsMod.recentIds['web'] = item.parentMenu.node.attributes.nodeData.id; - item.parentMenu.pageTree.stateHash['lastSelectedNode'] = item.parentMenu.node.id; + fsMod.recentIds['web'] = item.parentMenu.node.getNodeData('id'); + item.parentMenu.pageTree.stateHash['lastSelectedNode'] = item.parentMenu.node.getId(); } this.pageTree.commandProvider[item.callbackAction]( @@ -90,12 +89,12 @@ TYPO3.Components.PageTree.ContextMenu = Ext.extend(Ext.menu.Menu, { /** * Fills the menu with the actions * - * @param {Ext.tree.TreeNode} node + * @param {TYPO3.Components.PageTree.Model} node * @param {TYPO3.Components.PageTree.Tree} pageTree * @param {Object} contextMenuConfiguration * @return {void} */ - fill: function(node, pageTree, contextMenuConfiguration) { + fill: function (node, pageTree, contextMenuConfiguration) { this.node = node; this.pageTree = pageTree; @@ -103,9 +102,11 @@ TYPO3.Components.PageTree.ContextMenu = Ext.extend(Ext.menu.Menu, { if (components.length) { for (var component in components) { if (components[component] === '-') { - this.addSeparator(); + this.add({ + xtype: 'menuseparator' + }); } else if (typeof components[component] === 'object') { - this.addItem(components[component]); + this.add(components[component]); } } } @@ -119,7 +120,7 @@ TYPO3.Components.PageTree.ContextMenu = Ext.extend(Ext.menu.Menu, { * @param {int} level * @return {Object} */ - preProcessContextMenuConfiguration: function(contextMenuConfiguration, level) { + preProcessContextMenuConfiguration: function (contextMenuConfiguration, level) { level = level || 0; if (level > 5) { return []; @@ -138,7 +139,7 @@ TYPO3.Components.PageTree.ContextMenu = Ext.extend(Ext.menu.Menu, { ); if (subMenuComponents.length) { - var subMenu = new TYPO3.Components.PageTree.ContextMenu({ + var subMenu = Ext.create('TYPO3.Components.PageTree.ContextMenu', { id: this.id + '-sub' + ++subMenus, items: subMenuComponents, node: this.node, @@ -150,7 +151,8 @@ TYPO3.Components.PageTree.ContextMenu = Ext.extend(Ext.menu.Menu, { cls: 'contextMenu-subMenu', menu: subMenu, icon: contextMenuConfiguration[singleAction]['icon'], - iconCls: contextMenuConfiguration[singleAction]['class'] + iconCls: contextMenuConfiguration[singleAction]['class'], + xtype: 'menuitem' }; } } else if (contextMenuConfiguration[singleAction]['type'] === 'divider') { @@ -163,22 +165,14 @@ TYPO3.Components.PageTree.ContextMenu = Ext.extend(Ext.menu.Menu, { if (typeof contextMenuConfiguration[singleAction] === 'object') { var component = { - 'text': contextMenuConfiguration[singleAction]['label'], - 'icon': contextMenuConfiguration[singleAction]['icon'], - 'iconCls': contextMenuConfiguration[singleAction]['class'], - 'callbackAction': contextMenuConfiguration[singleAction]['callbackAction'], - 'customAttributes': contextMenuConfiguration[singleAction]['customAttributes'] + text: contextMenuConfiguration[singleAction]['label'], + icon: contextMenuConfiguration[singleAction]['icon'], + iconCls: contextMenuConfiguration[singleAction]['class'], + callbackAction: contextMenuConfiguration[singleAction]['callbackAction'], + customAttributes: contextMenuConfiguration[singleAction]['customAttributes'], + xtype: 'menuitem' }; - component.itemTpl = Ext.menu.Item.prototype.itemTpl = new Ext.XTemplate( - '<a id="{id}" class="{cls}" hidefocus="true" unselectable="on" href="{href}">', - '<span class="{hrefTarget}">', - '<img src="{icon}" class="x-menu-item-icon {iconCls}" unselectable="on" />', - '</span>', - '<span class="x-menu-item-text">{text}</span>', - '</a>' - ); - components[index++] = component; } } @@ -192,6 +186,3 @@ TYPO3.Components.PageTree.ContextMenu = Ext.extend(Ext.menu.Menu, { return components; } }); - -// XTYPE Registration -Ext.reg('TYPO3.Components.PageTree.ContextMenu', TYPO3.Components.PageTree.ContextMenu); diff --git a/t3lib/js/extjs/components/pagetree/javascript/deletiondropzone.js b/t3lib/js/extjs/components/pagetree/javascript/deletiondropzone.js index 443f96fa65880019049a6dbed5ef246c31e75262..a89afdbff79411f48580e4edf3519f14cf3410e1 100644 --- a/t3lib/js/extjs/components/pagetree/javascript/deletiondropzone.js +++ b/t3lib/js/extjs/components/pagetree/javascript/deletiondropzone.js @@ -23,18 +23,19 @@ * * This copyright notice MUST APPEAR in all copies of the script! ***************************************************************/ -Ext.namespace('TYPO3.Components.PageTree'); - /** * @class TYPO3.Components.PageTree.DeletionDropZone * * Deletion Drop Zone * * @namespace TYPO3.Components.PageTree - * @extends Ext.Panel + * @extends Ext.panel.Panel * @author Stefan Galinski <stefan.galinski@gmail.com> */ -TYPO3.Components.PageTree.DeletionDropZone = Ext.extend(Ext.Panel, { +Ext.define('TYPO3.Components.PageTree.DeletionDropZone', { + extend: 'Ext.panel.Panel', + alias: 'widget.typo3deletiondropzone', + /** * Border * @@ -110,10 +111,7 @@ TYPO3.Components.PageTree.DeletionDropZone = Ext.extend(Ext.Panel, { this.getEl().on('mouseout', function(e) { if (!e.within(this.getEl(), true)) { - this.removeClass(this.id + '-activateProxyOver'); - if (!this.app.activeTree.shouldCopyNode) { - this.app.activeTree.copyHint.show(); - } + this.removeCls(this.id + '-activateProxyOver'); } }, this); } @@ -139,7 +137,7 @@ TYPO3.Components.PageTree.DeletionDropZone = Ext.extend(Ext.Panel, { '"> </span><span id="' + this.id + '-text">' + TYPO3.Components.PageTree.LLL.dropToRemove + '</span></p>'; - TYPO3.Components.PageTree.DeletionDropZone.superclass.initComponent.apply(this, arguments); + this.callParent(arguments); }, @@ -149,44 +147,49 @@ TYPO3.Components.PageTree.DeletionDropZone = Ext.extend(Ext.Panel, { * @return {void} */ createDropZone: function() { - (new Ext.dd.DropZone(this.getEl(), { + Ext.create('Ext.dd.DropZone', this.getEl(), { ddGroup: this.ddGroup, - notifyOver: function(ddProxy, e) { - ddProxy.setDragElPos(e.xy[0], e.xy[1] - 60); - return this.id + '-proxyOver'; - }.createDelegate(this), - - notifyEnter: function() { - this.addClass(this.id + '-activateProxyOver'); - if (!this.app.activeTree.shouldCopyNode) { - this.app.activeTree.copyHint.hide(); - } - - return this.id + '-proxyOver'; - }.createDelegate(this), - - notifyDrop: function(ddProxy, e, n) { - var node = n.node; - if (!node) { - return; - } - - var tree = node.ownerTree; - var nodeHasChildNodes = (node.hasChildNodes() || node.isExpandable()); - - var callback = null; - if (!top.TYPO3.configuration.inWorkspace && !nodeHasChildNodes) { - callback = this.setRecoverState.createDelegate(this); - } - - if (nodeHasChildNodes) { - node.ownerTree.commandProvider.confirmDelete(node, tree, callback, true); - } else { - node.ownerTree.commandProvider.deleteNode(node, tree, callback); - } - }.createDelegate(this) - })); + notifyOver: Ext.Function.bind( + function(ddProxy, e) { + ddProxy.setDragElPos(e.xy[0], e.xy[1] - 60); + return this.id + '-proxyOver'; + }, + this + ), + + notifyEnter: Ext.Function.bind( + function() { + this.addCls(this.id + '-activateProxyOver'); + return this.id + '-proxyOver'; + }, + this + ), + + notifyDrop: Ext.Function.bind( + function (ddProxy, e, dragData) { + var view = dragData.view, + tree = view.panel, + node = view.getRecord(dragData.item); + if (!node) { + return; + } + var nodeHasChildNodes = (node.hasChildNodes() || node.isExpandable()); + + var callback = null; + if (!top.TYPO3.configuration.inWorkspace && !nodeHasChildNodes) { + callback = Ext.Function.bind(this.setRecoverState, this); + } + + if (nodeHasChildNodes) { + tree.commandProvider.confirmDelete(node, tree, callback, true); + } else { + tree.commandProvider.deleteNode(node, tree, callback); + } + }, + this + ) + }); }, /** @@ -207,7 +210,7 @@ TYPO3.Components.PageTree.DeletionDropZone = Ext.extend(Ext.Panel, { this.setHeight(50); this.updateIcon(TYPO3.Components.PageTree.Sprites.TrashCanRestore); this.updateText( - node.text + '<br />' + + node.get('text') + '<br />' + '<span class="' + this.id + '-restore">' + '<span class="' + this.id + '-restoreText">' + TYPO3.Components.PageTree.LLL.dropZoneElementRemoved + @@ -218,13 +221,17 @@ TYPO3.Components.PageTree.DeletionDropZone = Ext.extend(Ext.Panel, { this.app.doLayout(); ++this.amountOfDrops; - (function() { - if (!--this.amountOfDrops) { - this.toOriginState(); - } - }).defer(10000, this); + Ext.Function.defer( + function() { + if (!--this.amountOfDrops) { + this.toOriginState(); + } + }, + 10000, + this + ); - this.textClickHandler = this.restoreNode.createDelegate(this, [node, tree]); + this.textClickHandler = Ext.Function.bind(this.restoreNode, this, [node, tree]); Ext.get(this.id + '-text').on('click', this.textClickHandler); this.isPreviousSibling = false; @@ -283,7 +290,7 @@ TYPO3.Components.PageTree.DeletionDropZone = Ext.extend(Ext.Panel, { this.previousNode = this.textClickHandler = null; this.isPreviousSibling = false; - if (hide && !this.app.activeTree.dragZone.dragging) { + if (hide && !this.app.getTree().getView().getPlugin('treeViewDragDrop').dragZone.dragging) { this.hide(); } @@ -310,13 +317,14 @@ TYPO3.Components.PageTree.DeletionDropZone = Ext.extend(Ext.Panel, { this.updateText(TYPO3.Components.PageTree.LLL.dropZoneElementRestored); this.app.doLayout(); - (function() { - if (this.textClickHandler) { - this.toOriginState(); - } - }).defer(3000, this); + Ext.Function.defer( + function() { + if (this.textClickHandler) { + this.toOriginState(); + } + }, + 3000, + this + ); } }); - -// XTYPE Registration -Ext.reg('TYPO3.Components.PageTree.DeletionDropZone', TYPO3.Components.PageTree.DeletionDropZone); diff --git a/t3lib/js/extjs/components/pagetree/javascript/filteringtree.js b/t3lib/js/extjs/components/pagetree/javascript/filteringtree.js index 7ee0d88d312de0316141e51525b4f52b217fcf51..5b24822d19bed59cf4281169e3883c513e9f8afa 100644 --- a/t3lib/js/extjs/components/pagetree/javascript/filteringtree.js +++ b/t3lib/js/extjs/components/pagetree/javascript/filteringtree.js @@ -23,8 +23,6 @@ * * This copyright notice MUST APPEAR in all copies of the script! ***************************************************************/ -Ext.namespace('TYPO3.Components.PageTree'); - /** * @class TYPO3.Components.PageTree.FilteringTree * @@ -34,7 +32,9 @@ Ext.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, { +Ext.define('TYPO3.Components.PageTree.FilteringTree', { + extend: 'TYPO3.Components.PageTree.Tree', + /** * Search word * @@ -47,29 +47,45 @@ TYPO3.Components.PageTree.FilteringTree = Ext.extend(TYPO3.Components.PageTree.T * * @return {void} */ - addTreeLoader: function() { - this.loader = new Ext.tree.TreeLoader({ - directFn: this.treeDataProvider.getFilteredTree, - paramOrder: 'nodeId,attributes,searchWord', - nodeParameter: 'nodeId', - baseAttrs: { - uiProvider: this.uiProvider - }, - - listeners: { - beforeload: function(treeLoader, node) { - if (!node.ownerTree.searchWord || node.ownerTree.searchWord === '') { - return false; + addStore: function (store) { + this.store = Ext.data.StoreManager.lookup(this.getId() + 'FilteredPageTreeStore'); + if (!this.store) { + this.store = Ext.create('Ext.data.TreeStore', { + clearOnLoad: false, + listeners: { + beforeload: { + fn: function (store, operation) { + if (!this.searchWord || this.searchWord === '') { + return false; + } + if (operation.node) { + var node = operation.node; + node.removeAll(); + node.commit(); + operation.params = { + nodeId: node.getNodeData('id'), + nodeData: node.get('nodeData'), + searchWord: this.searchWord + + }; + } + }, + scope: this } - - treeLoader.baseParams.nodeId = node.id; - treeLoader.baseParams.searchWord = node.ownerTree.searchWord; - treeLoader.baseParams.attributes = node.attributes.nodeData; - } - } - }); + }, + model: 'TYPO3.Components.PageTree.Model', + nodeParam: 'nodeId', + proxy: { + type: 'direct', + paramOrder: ['nodeId', 'nodeData', 'searchWord'], + directFn: this.treeDataProvider.getFilteredTree, + reader: { + type: 'json' + } + }, + root: this.rootNodeConfig, + storeId: this.getId() + 'FilteredPageTreeStore' + }); + } } }); - -// XTYPE Registration -Ext.reg('TYPO3.Components.PageTree.FilteringTree', TYPO3.Components.PageTree.FilteringTree); diff --git a/t3lib/js/extjs/components/pagetree/javascript/loadorder.txt b/t3lib/js/extjs/components/pagetree/javascript/loadorder.txt index a649b22150ae39b41101fde397cc2c58bcdbd83b..84566aec2fd71794cf8fc9d2331d9d27d8aefb66 100644 --- a/t3lib/js/extjs/components/pagetree/javascript/loadorder.txt +++ b/t3lib/js/extjs/components/pagetree/javascript/loadorder.txt @@ -1,10 +1,12 @@ treeeditor.js +pagetreecolumn.js +contextmenu.js +Ext.ux.state.TreePanel.js +treedropzone.js +treeviewdragdrop.js tree.js filteringtree.js -nodeui.js -deletiondropzone.js toppanel.js -contextmenu.js +deletiondropzone.js actions.js -Ext.ux.state.TreePanel.js app.js diff --git a/t3lib/js/extjs/components/pagetree/javascript/nodeui.js b/t3lib/js/extjs/components/pagetree/javascript/nodeui.js deleted file mode 100644 index 1a1066063bcecd47c5a5add71a3c12506068feb4..0000000000000000000000000000000000000000 --- a/t3lib/js/extjs/components/pagetree/javascript/nodeui.js +++ /dev/null @@ -1,169 +0,0 @@ -/*************************************************************** -* Copyright notice -* -* (c) 2010-2011 Stefan Galinski <stefan.galinski@gmail.com> -* 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), - rootline = ''; - - // TYPO3 modification to show the readable rootline above the user mounts - if (a.readableRootline !== '') { - var rootline = '<li class="x-tree-node-readableRootline">' + a.readableRootline + '</li>'; - } - - var buf = [rootline,'<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 handlesIndex = ddHandles.length; - - var textNode = Ext.get(this.textNode); - for (var i = 0; i < textNode.dom.childNodes.length; ++i) { - if (textNode.dom.childNodes[i].nodeName === 'SPAN') { - ddHandles[handlesIndex++] = textNode.dom.childNodes[i]; - if (textNode.dom.childNodes[i].childNodes) { - ddHandles[handlesIndex++] = textNode.dom.childNodes[i].childNodes[0]; - } - } - } - - return ddHandles; - }, - - /** - * Only set the onOver class if we are not in dragging mode - * - * @return {void} - */ - onOver: function() { - if (!this.node.ownerTree.dontSetOverClass) { - TYPO3.Components.PageTree.PageTreeNodeUI.superclass.onOver.apply(this, arguments); - } - } -}); - -// XTYPE Registration -Ext.reg('TYPO3.Components.PageTree.PageTreeNodeUI', TYPO3.Components.PageTree.PageTreeNodeUI); diff --git a/t3lib/js/extjs/components/pagetree/javascript/pagetreecolumn.js b/t3lib/js/extjs/components/pagetree/javascript/pagetreecolumn.js new file mode 100644 index 0000000000000000000000000000000000000000..e4941d313a5c622f28928a6e83ed1896c461927c --- /dev/null +++ b/t3lib/js/extjs/components/pagetree/javascript/pagetreecolumn.js @@ -0,0 +1,166 @@ +/*************************************************************** +* Copyright notice +* +* (c) 2011 Stanislas Rolland <typo3@sjbr.ca> +* 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! +***************************************************************/ +/** + * @class TYPO3.Components.PageTree.Column + * + * Page tree column + * + * @namespace TYPO3.Components.PageTree + * @extends Ext.grid.column.Column + * @author Stanislas Rolland <typo3@sjbr.ca> + */ +Ext.define('TYPO3.Components.PageTree.Column', { + extend: 'Ext.grid.column.Column', + alias: 'widget.pagetreecolumn', + + /** + * Render a row of the page tree adding relevant icons depending on record depth and record type + * + */ + initComponent: function() { + var origRenderer = this.renderer || this.defaultRenderer, + origScope = this.scope || window; + + this.renderer = function(value, metaData, record, rowIdx, colIdx, store, view) { + var buf = [], + format = Ext.String.format, + depth = record.getDepth(), + treePrefix = Ext.baseCSSPrefix + 'tree-', + elbowPrefix = treePrefix + 'elbow-', + expanderCls = treePrefix + 'expander', + imgText = '<img src="{1}" class="{0}" />', + checkboxText = '<input type="button" role="checkbox" class="{0}" {1} />', + formattedValue = origRenderer.apply(origScope, arguments), + checked = null, + href = record.getNodeData('href'), + target = record.getNodeData('hrefTarget'), + cls = record.getNodeData('cls'), + readableRootline = record.getNodeData('readableRootline'); + + while (record) { + if (!record.isRoot() || (record.isRoot() && view.rootVisible)) { + if (record.getDepth() === depth) { + // Add TYPO3 sprite icon code + buf.unshift(record.getNodeData('spriteIconCode')); + // Check if nodeData['checked'] is boolean + checked = record.getNodeData('checked'); + if (Ext.isBoolean(checked)) { + buf.unshift(format( + checkboxText, + (treePrefix + 'checkbox') + (checked ? ' ' + treePrefix + 'checkbox-checked' : ''), + checked ? 'aria-checked="true"' : '' + )); + if (checked) { + metaData.tdCls += (' ' + treePrefix + 'checked'); + } + } + // Remove +/arrow from the TYPO3 root + if (record.getDepth() === 1) { + buf.unshift(format(imgText, (elbowPrefix + 'empty'), Ext.BLANK_IMAGE_URL)); + } else if (record.isLast()) { + if (record.isExpandable()) { + buf.unshift(format(imgText, (elbowPrefix + 'end-plus ' + expanderCls), Ext.BLANK_IMAGE_URL)); + } else { + buf.unshift(format(imgText, (elbowPrefix + 'end'), Ext.BLANK_IMAGE_URL)); + } + } else { + if (record.isExpandable()) { + buf.unshift(format(imgText, (elbowPrefix + 'plus ' + expanderCls), Ext.BLANK_IMAGE_URL)); + } else { + buf.unshift(format(imgText, (treePrefix + 'elbow'), Ext.BLANK_IMAGE_URL)); + } + } + } else { + // Remove elbow from the TYPO3 root + if (record.isLast() || record.getDepth() === 1) { + buf.unshift(format(imgText, (elbowPrefix + 'empty'), Ext.BLANK_IMAGE_URL)); + } else if (record.getDepth() !== 1) { + buf.unshift(format(imgText, (elbowPrefix + 'line'), Ext.BLANK_IMAGE_URL)); + } + } + } + record = record.parentNode; + } + if (href) { + buf.push('<a href="', href, '" target="', target, '">', formattedValue, '</a>'); + } else { + buf.push(formattedValue); + } + if (cls) { + metaData.tdCls += ' ' + cls; + } + // Show the readable rootline above the user mounts + if (readableRootline !== '') { + buf.unshift('<div class="x-tree-node-readableRootline">' + readableRootline + '</div>'); + } + return buf.join(''); + }; + this.callParent(arguments); + }, + + defaultRenderer: function (value) { + return value; + }, + /** + * Create editing field with correct margin left + * + */ + getEditor: function (record, defaultField) { + var depth = parseInt(record.getDepth()), + marginLeft = 51; + if (depth > 2) { + marginLeft += (depth-2)*16; + } + var field = this.field; + if (!field && this.editor) { + field = this.editor; + delete this.editor; + } + + if (!field && defaultField) { + field = defaultField; + } + + if (field) { + if (Ext.isString(field)) { + field = { xtype: field }; + } + if (field.isFormField) { + field.setFieldStyle({ + marginLeft: marginLeft + 'px' + }); + } + if (Ext.isObject(field) && !field.isFormField) { + field = Ext.ComponentManager.create(field, 'textfield'); + this.field = field; + } + Ext.apply(field, { + name: this.dataIndex + }); + return field; + } + } +}); diff --git a/t3lib/js/extjs/components/pagetree/javascript/toppanel.js b/t3lib/js/extjs/components/pagetree/javascript/toppanel.js index f80299d8e9a3ec0c7dede09757fb1b996b71d9b3..04d28f9749a4e34dc861e1f61198edfc21e0e74e 100644 --- a/t3lib/js/extjs/components/pagetree/javascript/toppanel.js +++ b/t3lib/js/extjs/components/pagetree/javascript/toppanel.js @@ -23,18 +23,18 @@ * * 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 + * @extends Ext.panel.Panel * @author Stefan Galinski <stefan.galinski@gmail.com> */ -TYPO3.Components.PageTree.TopPanel = Ext.extend(Ext.Panel, { +Ext.define('TYPO3.Components.PageTree.TopPanel', { + extend: 'Ext.panel.Panel', + /** * Component Id * @@ -43,37 +43,48 @@ TYPO3.Components.PageTree.TopPanel = Ext.extend(Ext.Panel, { id: 'typo3-pagetree-topPanel', /** - * Border + * Toolbar Object * - * @type {Boolean} + * @type {Ext.Toolbar} */ - border: false, + dockedItems: [{ + xtype: 'toolbar', + dock: 'top', + itemId: 'topToolbar' + }], /** - * Toolbar Object + * Panel CSS * - * @type {Ext.Toolbar} + * @type {String} */ - tbar: new Ext.Toolbar(), - + cls: 'typo3-pagetree-topPanel', + /** - * Currently Clicked Toolbar Button + * Body CSS * - * @type {Ext.Button} + * @type {String} */ - currentlyClickedButton: null, + bodyCls: 'typo3-pagetree-topPanel-item', + + /** + * Layout + * + * @type {String} + */ + layout: 'anchor', /** - * Currently Shown Panel + * Currently Clicked Toolbar Button * - * @type {Ext.Component} + * @type {Ext.Button} */ - currentlyShownPanel: null, + currentlyClickedButton: null, /** * Filtering Indicator Item * - * @type {Ext.Panel} + * @type {Ext.panel.Panel} */ filteringIndicator: null, @@ -118,38 +129,20 @@ TYPO3.Components.PageTree.TopPanel = Ext.extend(Ext.Panel, { * @return {void} */ initComponent: function() { - this.currentlyShownPanel = new Ext.Panel({ - id: this.id + '-defaultPanel', - cls: this.id + '-item' - }); - this.items = [this.currentlyShownPanel]; - - TYPO3.Components.PageTree.TopPanel.superclass.initComponent.apply(this, arguments); - + this.callParent(); + // Node insertion feature this.addDragDropNodeInsertionFeature(); - + // Filter feature if (!TYPO3.Components.PageTree.Configuration.hideFilter || TYPO3.Components.PageTree.Configuration.hideFilter === '0' ) { this.addFilterFeature(); } - - this.getTopToolbar().addItem({xtype: 'tbfill'}); + // Refresh feature + this.getDockedComponent('topToolbar').add({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}""> </button></div>' - ); - }, - /** * Adds a button to the components toolbar with a related component * @@ -158,7 +151,6 @@ TYPO3.Components.PageTree.TopPanel = Ext.extend(Ext.Panel, { * @return {void} */ addButton: function(button, connectedWidget) { - button.template = this.getButtonTemplate(); if (!button.hasListener('click')) { button.on('click', this.topbarButtonCallback); } @@ -169,7 +161,7 @@ TYPO3.Components.PageTree.TopPanel = Ext.extend(Ext.Panel, { this.add(connectedWidget); } - this.getTopToolbar().addItem(button); + this.getDockedComponent('topToolbar').add(button); this.doLayout(); }, @@ -182,44 +174,45 @@ TYPO3.Components.PageTree.TopPanel = Ext.extend(Ext.Panel, { topbarButtonCallback: function() { var topPanel = this.ownerCt.ownerCt; - topPanel.currentlyShownPanel.hide(); if (topPanel.currentlyClickedButton) { topPanel.currentlyClickedButton.toggle(false); + if (topPanel.currentlyClickedButton.connectedWidget) { + topPanel.currentlyClickedButton.connectedWidget.hide(); + } } if (topPanel.currentlyClickedButton === this) { topPanel.currentlyClickedButton = null; - topPanel.currentlyShownPanel = topPanel.get(topPanel.id + '-defaultPanel'); + if (this.connectedWidget) { + this.connectedWidget.hide(); + } } else { this.toggle(true); topPanel.currentlyClickedButton = this; - topPanel.currentlyShownPanel = this.connectedWidget; + if (this.connectedWidget) { + this.connectedWidget.show(); + } } - - topPanel.currentlyShownPanel.show(); }, /** * Loads the filtering tree nodes with the given search word * - * @param {Ext.form.TextField} textField + * @param {Ext.form.field.Trigger} textField * @return {void} */ - createFilterTree: function(textField) { + createFilterTree: function (textField) { var searchWord = textField.getValue(); var isNumber = TYPO3.Utility.isNumber(searchWord); var hasMinLength = (searchWord.length > 2 || searchWord.length <= 0); if ((!hasMinLength && !isNumber) || searchWord === this.filteringTree.searchWord) { return; } - this.filteringTree.searchWord = searchWord; if (this.filteringTree.searchWord === '') { - this.app.activeTree = this.tree; - textField.setHideTrigger(true); - this.filteringTree.hide(); - this.tree.show().refreshTree(function() { + this.app.setTree(this.tree); + this.tree.refreshTree(function() { textField.focus(false, 500); }, this); @@ -229,7 +222,6 @@ TYPO3.Components.PageTree.TopPanel = Ext.extend(Ext.Panel, { } } else { var selectedNode = this.app.getSelected(); - this.app.activeTree = this.filteringTree; if (!this.filteringIndicator) { this.filteringIndicator = this.app.addIndicator( @@ -237,20 +229,20 @@ TYPO3.Components.PageTree.TopPanel = Ext.extend(Ext.Panel, { ); } - textField.setHideTrigger(false); - this.tree.hide(); this.app.ownerCt.getEl().mask('', 'x-mask-loading-message'); - this.app.ownerCt.getEl().addClass('t3-mask-loading'); - this.filteringTree.show().refreshTree(function() { + this.app.ownerCt.getEl().addCls('t3-mask-loading'); + this.app.setTree(this.filteringTree); + this.filteringTree.refreshTree(function() { if (selectedNode) { - this.app.select(selectedNode.attributes.nodeData.id, false); + this.app.select(selectedNode.getNodeData('id')); } - textField.focus(); this.app.ownerCt.getEl().unmask(); + textField.setHideTrigger(false); + textField.triggerWrap.setWidth(0); + this.forceComponentLayout(); + textField.focus(); }, this); } - - this.doLayout(); }, /** @@ -261,26 +253,27 @@ TYPO3.Components.PageTree.TopPanel = Ext.extend(Ext.Panel, { */ createIndicatorItem: function(textField) { return { - border: false, - id: this.app.id + '-indicatorBar-filter', - cls: this.app.id + '-indicatorBar-item', - html: '<p>' + - '<span id="' + this.app.id + '-indicatorBar-filter-info' + '" ' + - 'class="' + this.app.id + '-indicatorBar-item-leftIcon ' + - TYPO3.Components.PageTree.Sprites.Info + '"> ' + - '</span>' + - '<span id="' + this.app.id + '-indicatorBar-filter-clear' + '" ' + - 'class="' + this.app.id + '-indicatorBar-item-rightIcon ' + '">X' + - '</span>' + - TYPO3.Components.PageTree.LLL.activeFilterMode + - '</p>', + id: this.app.getId() + '-indicatorBar-filter', + cls: this.app.getId() + '-indicatorBar-item', + renderData: { + appId: this.app.getId(), + spriteIconCls: TYPO3.Components.PageTree.Sprites.Info, + label: TYPO3.Components.PageTree.LLL.activeFilterMode + }, + renderTpl: Ext.create('Ext.XTemplate', + '<p>', + '<span id="{appId}-indicatorBar-filter-info" class="{appId}-indicatorBar-item-leftIcon {spriteIconCls}"> </span>', + ' {label} ', + '<span id="{appId}-indicatorBar-filter-clear" class="{appId}-indicatorBar-item-rightIcon">X</span>', + '</p>' + ), filteringTree: this.filteringTree, listeners: { afterrender: { scope: this, - fn: function() { - var element = Ext.fly(this.app.id + '-indicatorBar-filter-clear'); + fn: function(component) { + var element = Ext.get(this.app.getId() + '-indicatorBar-filter-clear'); element.on('click', function() { textField.setValue(''); this.createFilterTree(textField); @@ -297,71 +290,65 @@ TYPO3.Components.PageTree.TopPanel = Ext.extend(Ext.Panel, { * @return {void} */ addFilterFeature: function() { - var topPanelButton = new Ext.Button({ - id: this.id + '-button-filter', - cls: this.id + '-button', + var topPanelButton = Ext.create('Ext.button.Button', { + id: this.getId() + '-button-filter', + cls: this.getId() + '-button', iconCls: TYPO3.Components.PageTree.Sprites.Filter, tooltip: TYPO3.Components.PageTree.LLL.buttonFilter }); - var textField = new Ext.form.TriggerField({ - id: this.id + '-filter', + var textField = Ext.create('Ext.form.field.Trigger', { + id: this.getId() + '-filter', + border: false, enableKeyEvents: true, - triggerClass: TYPO3.Components.PageTree.Sprites.InputClear, + labelWidth: 0, + triggerCls: TYPO3.Components.PageTree.Sprites.InputClear, value: TYPO3.Components.PageTree.LLL.searchTermInfo, listeners: { blur: { - scope: this, - fn:function(textField) { + fn: function (textField) { if (textField.getValue() === '') { textField.setValue(TYPO3.Components.PageTree.LLL.searchTermInfo); - textField.addClass(this.id + '-filter-defaultText'); + textField.inputEl.addCls(this.getId() + '-filter-defaultText'); } - } + }, + scope: this }, focus: { - scope: this, - fn: function(textField) { + fn: function (textField) { if (textField.getValue() === TYPO3.Components.PageTree.LLL.searchTermInfo) { textField.setValue(''); - textField.removeClass(this.id + '-filter-defaultText'); + textField.inputEl.removeCls(this.getId() + '-filter-defaultText'); } - } + }, + scope: this }, keydown: { fn: this.createFilterTree, scope: this, buffer: 1000 - } - } - }); - - textField.setHideTrigger(true); - 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(); - } + fn: function () { this.focus(); } } } }); - this.addButton(topPanelButton, topPanelWidget); + textField.setHideTrigger(true); + textField.onTriggerClick = Ext.Function.bind( + function (textField) { + textField.setValue(''); + this.createFilterTree(textField); + }, + this, + [textField] + ); + + this.addButton(topPanelButton, textField); }, /** @@ -370,28 +357,32 @@ TYPO3.Components.PageTree.TopPanel = Ext.extend(Ext.Panel, { * @return {void} */ createNewNodeToolbar: function() { - this.dragZone = new Ext.dd.DragZone(this.getEl(), { + this.dragZone = Ext.create('Ext.dd.DragZone', this.getEl(), { ddGroup: this.ownerCt.ddGroup, topPanel: this.ownerCt, endDrag: function() { - this.topPanel.app.activeTree.dontSetOverClass = false; + this.topPanel.app.getTree().dontSetOverClass = false; }, - getDragData: function(event) { + getDragData: function (event) { this.proxyElement = document.createElement('div'); - - var node = Ext.getCmp(event.getTarget('.x-btn').id); - node.shouldCreateNewNode = true; - + var clickedButton = event.getTarget('.x-btn'); + if (clickedButton) { + var node = Ext.getCmp(clickedButton.id); + } + if (node) { + node.shouldCreateNewNode = true; + } return { ddel: this.proxyElement, - item: node + item: node, + records: [node] } }, onInitDrag: function() { - this.topPanel.app.activeTree.dontSetOverClass = true; + this.topPanel.app.getTree().dontSetOverClass = true; var clickedButton = this.dragData.item; var cls = clickedButton.initialConfig.iconCls; @@ -405,18 +396,18 @@ TYPO3.Components.PageTree.TopPanel = Ext.extend(Ext.Panel, { } }); - // listens on the escape key to stop the dragging - (new Ext.KeyMap(document, { + // Listens on the escape key to stop the dragging + Ext.create('Ext.util.KeyMap', document, { key: Ext.EventObject.ESC, scope: this, buffer: 250, fn: function(event) { if (this.dragZone.dragging) { - Ext.dd.DragDropMgr.stopDrag(event); + Ext.dd.DragDropManager.stopDrag(event); this.dragZone.onInvalidDrop(event); } } - }, 'keydown')); + }, 'keydown'); }, /** @@ -425,11 +416,16 @@ TYPO3.Components.PageTree.TopPanel = Ext.extend(Ext.Panel, { * @return {void} */ addDragDropNodeInsertionFeature: function() { - var newNodeToolbar = new Ext.Toolbar({ - border: false, - id: this.id + '-item-newNode', - cls: this.id + '-item', + var topPanelButton = Ext.create('Ext.button.Button', { + id: this.getId() + '-button-newNode', + cls: this.getId() + '-button', + iconCls: TYPO3.Components.PageTree.Sprites.NewNode, + tooltip: TYPO3.Components.PageTree.LLL.buttonNewNode + }); + var newNodeToolbar = Ext.create('Ext.toolbar.Toolbar', { + id: this.getId() + '-item-newNode', + cls: this.getId() + '-item', listeners: { render: { fn: this.createNewNodeToolbar @@ -438,20 +434,10 @@ TYPO3.Components.PageTree.TopPanel = Ext.extend(Ext.Panel, { }); this.dataProvider.getNodeTypes(function(response) { - for (var i = 0; i < response.length; ++i) { - response[i].template = this.getButtonTemplate(); - newNodeToolbar.addItem(response[i]); - } + newNodeToolbar.add(response); newNodeToolbar.doLayout(); }, this); - var topPanelButton = new Ext.Button({ - id: this.id + '-button-newNode', - cls: this.id + '-button', - iconCls: TYPO3.Components.PageTree.Sprites.NewNode, - tooltip: TYPO3.Components.PageTree.LLL.buttonNewNode - }); - this.addButton(topPanelButton, newNodeToolbar); }, @@ -461,9 +447,9 @@ TYPO3.Components.PageTree.TopPanel = Ext.extend(Ext.Panel, { * @return {void} */ addRefreshTreeFeature: function() { - var topPanelButton = new Ext.Button({ - id: this.id + '-button-refresh', - cls: this.id + '-button', + var topPanelButton = Ext.create('Ext.button.Button', { + id: this.getId() + '-button-refresh', + cls: this.getId() + '-button', iconCls: TYPO3.Components.PageTree.Sprites.Refresh, tooltip: TYPO3.Components.PageTree.LLL.buttonRefresh, @@ -471,7 +457,7 @@ TYPO3.Components.PageTree.TopPanel = Ext.extend(Ext.Panel, { click: { scope: this, fn: function() { - this.app.activeTree.refreshTree(); + this.app.getTree().refreshTree(); } } } @@ -480,6 +466,3 @@ TYPO3.Components.PageTree.TopPanel = Ext.extend(Ext.Panel, { this.addButton(topPanelButton); } }); - -// XTYPE Registration -Ext.reg('TYPO3.Components.PageTree.TopPanel', TYPO3.Components.PageTree.TopPanel); diff --git a/t3lib/js/extjs/components/pagetree/javascript/tree.js b/t3lib/js/extjs/components/pagetree/javascript/tree.js index 7319b02472c735c5b349395d1c92b273e4628d0b..fe61c6a8e946c05a169daaacea432fdec7604f6c 100644 --- a/t3lib/js/extjs/components/pagetree/javascript/tree.js +++ b/t3lib/js/extjs/components/pagetree/javascript/tree.js @@ -23,43 +23,145 @@ * * This copyright notice MUST APPEAR in all copies of the script! ***************************************************************/ -Ext.namespace('TYPO3.Components.PageTree'); - /** * @class TYPO3.Components.PageTree.Tree * * Generic Tree Panel * * @namespace TYPO3.Components.PageTree - * @extends Ext.tree.TreePanel + * @extends Ext.tree.Panel * @author Stefan Galinski <stefan.galinski@gmail.com> */ -TYPO3.Components.PageTree.Tree = Ext.extend(Ext.tree.TreePanel, { +Ext.define('TYPO3.Components.PageTree.Model', { + extend: 'Ext.data.Model', + fields: [{ + name: 'id', + type: 'string', + defaultValue: 'root' + },{ + name: 'realId', + type: 'string' + },{ + name: 'text', + type: 'string' + },{ + name: 'depth', + type: 'int' + },{ + name: 'root', + type: 'boolean' + },{ + name: 'leaf', + type: 'boolean' + },{ + name: 'parentId', + type: 'string' + },{ + name: 'isFirst', + type: 'boolean' + },{ + name: 'index', + type: 'int' + },{ + name: 'isLast', + type: 'boolean' + },{ + name: 'isExpandable', + type: 'boolean' + },{ + name: 'isInsertedNode', + type: 'boolean' + },{ + name: 'nodeData', + type: 'object' + }], + hasMany: { + name: 'children', + associationKey: 'children', + model: 'TYPO3.Components.PageTree.Model' + }, + // Set method for nodeData fields + setNodeData: function (field, value) { + var nodeData = this.get('nodeData'); + nodeData[field] = value; + this.set('nodeData', Ext.merge(this.get('nodeData'), nodeData)); + }, + // Get method for nodeData fields + getNodeData: function (field) { + return this.get('nodeData')[field]; + } +}); +Ext.define('TYPO3.Components.PageTree.Tree', { + extend: 'Ext.tree.Panel', + /** + * Use extended stateful mixin + * + * @type {Object} + */ + mixins: { + state: 'Ext.ux.state.TreePanel' + }, + + /** + * View configuration + * + * @type {Object} + */ + viewConfig: { + autoScroll: false, + border: false, + toggleOnDblClick: false + }, + + /** + * Columns + * + * @type {TYPO3.Components.PageTree.Column}[] + */ + columns: [{ + xtype: 'pagetreecolumn', + dataIndex: 'text', + flex: 1, + editor: { + xtype: 'textfield', + allowBlank: false + } + }], + + /** + * Header + * + * @type {Boolean} + */ + hideHeaders: true, + preventHeader: true, + /** * Border * * @type {Boolean} */ + autoScroll: false, border: false, /** - * Indicates if the root node is visible + * Body css * - * @type {Boolean} + * @type {String} */ - rootVisible: false, + bodyCls: 'typo3-pagetree', /** - * Tree Editor Instance (Inline Edit) + * Indicates if the root node is visible * - * @type {TYPO3.Components.PageTree.TreeEditor} + * @type {Boolean} */ - treeEditor: null, + rootVisible: false, /** * Currently Selected Node * - * @type {Ext.tree.TreeNode} + * @type {TYPO3.Components.PageTree.Model} */ currentSelectedNode: null, @@ -78,18 +180,18 @@ TYPO3.Components.PageTree.Tree = Ext.extend(Ext.tree.TreePanel, { ddGroup: '', /** - * Indicates if the label should be editable + * Id of deletionDropZone * - * @cfg {Boolean} + * @cfg {String} */ - labelEdit: true, + deletionDropZoneId: '', /** - * User Interface Provider + * Indicates if the label should be editable * - * @cfg {Ext.tree.TreeNodeUI} + * @cfg {Boolean} */ - uiProvider: null, + labelEdit: true, /** * Data Provider @@ -103,7 +205,7 @@ TYPO3.Components.PageTree.Tree = Ext.extend(Ext.tree.TreePanel, { * * @cfg {Object} */ - commandProvider : null, + commandProvider: null, /** * Context menu provider @@ -113,18 +215,18 @@ TYPO3.Components.PageTree.Tree = Ext.extend(Ext.tree.TreePanel, { contextMenuProvider: null, /** - * Id of the deletion drop zone if any + * Main applicaton * - * @cfg {String} + * @cfg {TYPO3.Components.PageTree.App} */ - deletionDropZoneId: '', + app: null, /** - * Main applicaton + * Page Tree Store * - * @cfg {TYPO3.Components.PageTree.App} + * @type {Object} */ - app: null, + store: null, /** * Root Node Configuration @@ -139,17 +241,10 @@ TYPO3.Components.PageTree.Tree = Ext.extend(Ext.tree.TreePanel, { } }, - /** - * Indicator if the control key is pressed - * - * @type {Boolean} - */ - isControlPressed: false, - /** * Context Node * - * @type {Ext.tree.TreeNode} + * @type {TYPO3.Components.PageTree.Model} */ t3ContextNode: null, @@ -158,68 +253,52 @@ TYPO3.Components.PageTree.Tree = Ext.extend(Ext.tree.TreePanel, { * * @type {Object} */ - t3ContextInfo: { + t3ContextInfo: { inCopyMode: false, inCutMode: false }, /** - * Registered clicks for the double click feature + * Number of clicks to ignore for the label edit on dblclick feature + * Will be set to 2 by the tree editor * * @type {int} */ - clicksRegistered: 0, + inhibitClicks: 0, /** - * Indicator if the control key was pressed + * Constructor + * Plugins are built by the parent constructor * - * @type {Boolean} - */ - controlKeyPressed: false, - - /** - * Listeners - * - * Event handlers that handle click events and synchronizes the label edit, - * double click and single click events in a useful way. + * @param {Object} config + * @return {void} */ - listeners: { - // single click handler that only triggers after a delay to let the double click event - // a possibility to be executed (needed for label edit) - click: { - fn: function(node, event) { - if (this.clicksRegistered === 2) { - this.clicksRegistered = 0; - event.stopEvent(); - return false; - } - - this.clicksRegistered = 0; - if (this.commandProvider.singleClick) { - this.commandProvider.singleClick(node, this); - } - }, - delay: 400 - }, - - // prevent the expanding / collapsing on double click - beforedblclick: { - fn: function() { - return false; - } - }, - - // prevents label edit on a selected node - beforeclick: { - fn: function(node, event) { - if (!this.clicksRegistered && this.getSelectionModel().isSelected(node)) { - node.fireEvent('click', node, event); - ++this.clicksRegistered; - return false; - } - ++this.clicksRegistered; - } + constructor: function (config) { + // Inline label editing feature + this.labelEdit = config.labelEdit || this.labelEdit; + if (this.labelEdit ) { + var plugins = config.plugins || []; + config.plugins = plugins.concat( + Ext.create('TYPO3.Components.PageTree.TreeEditor', { + clicksToEdit: 2, + pluginId: 'treeEditor' + }) + ); + } + // Drag & drop feature + if (this.enableDD) { + config.viewConfig = Ext.applyIf(config.viewConfig || {}, this.viewConfig); + var plugins = config.viewConfig.plugins || []; + config.viewConfig.plugins = plugins.concat( + Ext.create('TYPO3.Components.PageTree.plugin.TreeViewDragDrop', { + ddGroup: config.ddGroup, + pluginId: 'treeViewDragDrop' + }) + ); + config.viewConfig.allowCopy = true; } + // Call parent constructor + this.callParent([config]); }, /** @@ -227,28 +306,74 @@ TYPO3.Components.PageTree.Tree = Ext.extend(Ext.tree.TreePanel, { * * @return {void} */ - initComponent: function() { - if (!this.uiProvider) { - this.uiProvider = TYPO3.Components.PageTree.PageTreeNodeUI; - } - Ext.dd.DragDropMgr.useCache = false; - this.root = new Ext.tree.AsyncTreeNode(this.rootNodeConfig); - this.addTreeLoader(); - - if (this.labelEdit) { - this.enableInlineEditor(); - } - + initComponent: function () { + // Add the tree store + this.addStore(); + // Add single click handler that only triggers after a delay to let the double click event + // a possibility to be executed (needed for label edit) + this.addListener('itemclick', this.onItemSingleClick, null, { delay: 400 }); + // Init component + this.callParent(); + // Drag & drop feature if (this.enableDD) { - this.dragConfig = {ddGroup: this.ddGroup}; - this.enableDragAndDrop(); + this.getView().addListener('afterrender', this.enableDragAndDrop, this); } - + // Context menu feature if (this.contextMenuProvider) { this.enableContextMenu(); } - - TYPO3.Components.PageTree.Tree.superclass.initComponent.apply(this, arguments); + }, + + /** + * Adds the store to the tree + * + * @return {void} + */ + addStore: function () { + this.store = Ext.data.StoreManager.lookup(this.getId() + 'PageTreeStore'); + if (!this.store) { + this.store = Ext.create('Ext.data.TreeStore', { + clearOnLoad: false, + listeners: { + // Remove nodes and add params to read operation + beforeload: { + fn: function (store, operation, options) { + if (operation.node) { + var node = operation.node; + node.removeAll(); + node.commit(); + operation.params = { + nodeId: node.getNodeData('id'), + nodeData: node.get('nodeData') + + }; + } + } + }, + // Restore state on initial load + load: { + fn: function (store, node, records, successful) { + if (successful) { + this.restoreState(); + } + }, + scope: this + } + }, + model: 'TYPO3.Components.PageTree.Model', + nodeParam: 'nodeId', + proxy: { + type: 'direct', + directFn: this.treeDataProvider.getNextTreeLevel, + paramOrder: ['nodeId', 'nodeData'], + reader: { + type: 'json' + } + }, + root: this.rootNodeConfig, + storeId: this.getId() + 'PageTreeStore' + }); + } }, /** @@ -258,9 +383,9 @@ TYPO3.Components.PageTree.Tree = Ext.extend(Ext.tree.TreePanel, { * @param {Object} scope * return {void} */ - refreshTree: function(callback, scope) { - // remove readable rootline elements while refreshing - if (!this.inRefreshingMode) { + refreshTree: function (callback, scope) { + // Remove readable rootline elements while refreshing + if (!this.store.isLoading()) { var rootlineElements = Ext.select('.x-tree-node-readableRootline'); if (rootlineElements) { rootlineElements.each(function(element) { @@ -268,70 +393,54 @@ TYPO3.Components.PageTree.Tree = Ext.extend(Ext.tree.TreePanel, { }); } } - - this.refreshNode(this.root, callback, scope); + this.refreshNode(this.getRootNode(), callback, scope); }, /** * Refreshes a given node * - * @param {Ext.tree.TreeNode} node + * @param {TYPO3.Components.PageTree.Model} node * @param {Function} callback * @param {Object} scope * return {void} */ - refreshNode: function(node, callback, scope) { - if (this.inRefreshingMode) { - return; - } - - scope = scope || node; - this.inRefreshingMode = true; - var loadCallback = function(node) { - node.ownerTree.inRefreshingMode = false; - if (node.ownerTree.restoreState) { - node.ownerTree.restoreState(node.getPath()); - } - }; - - if (callback) { - loadCallback = callback.createSequence(loadCallback); - } - - this.getLoader().load(node, loadCallback, scope); + refreshNode: function (node, callback, scope) { + this.store.load({ + node: node, + callback: callback || Ext.emptyFn, + scope: scope || this + }); }, /** - * Adds a tree loader implementation that uses the directFn feature + * Handles singe click on tree item * - * return {void} + * return {Boolean} */ - addTreeLoader: function() { - this.loader = new Ext.tree.TreeLoader({ - directFn: this.treeDataProvider.getNextTreeLevel, - paramOrder: 'nodeId,attributes', - nodeParameter: 'nodeId', - baseAttrs: { - uiProvider: this.uiProvider - }, - - // an id can never be zero in ExtJS, but this is needed - // for the root line feature or it will never be working! - createNode: function(attr) { - if (attr.id == 0) { - attr.id = 'siteRootNode'; - } - - return Ext.tree.TreeLoader.prototype.createNode.call(this, attr); - }, + onItemSingleClick: function (view, node, item, index, event) { + var tree = view.panel; + // Check if the tree editor was triggered by dblclick + // If so, stop the next two clicks + if (tree.inhibitClicks) { + --tree.inhibitClicks; + event.stopEvent(); + return false; + } - listeners: { - beforeload: function(treeLoader, node) { - treeLoader.baseParams.nodeId = node.id; - treeLoader.baseParams.attributes = node.attributes.nodeData; - } + if (tree.commandProvider.singleClick) { + tree.commandProvider.singleClick(node, tree); + } + // Fire the context menu on a single click on the node icon (Beware of drag&drop!) + if (!TYPO3.Components.PageTree.Configuration.disableIconLinkToContextmenu + || TYPO3.Components.PageTree.Configuration.disableIconLinkToContextmenu === '0' + ) { + var target = event.getTarget('span.t3-icon-apps-pagetree'); + if (target) { + view.fireEvent('itemcontextmenu', view, node, item, index, event); + event.stopEvent(); } - }); + } + return true; }, /** @@ -340,58 +449,33 @@ TYPO3.Components.PageTree.Tree = Ext.extend(Ext.tree.TreePanel, { * return {void} */ enableContextMenu: function() { - this.contextMenu = new TYPO3.Components.PageTree.ContextMenu(); - - this.on('contextmenu', function(node, event) { - this.openContextMenu(node, event); + this.contextMenu = Ext.create('TYPO3.Components.PageTree.ContextMenu', { pageTree: this }); + this.getView().on('itemcontextmenu', function (view, node, item, index, event) { + view.panel.openContextMenu(view, node, item, index, event); }); }, /** * Open a context menu for the given node * - * @param {Ext.tree.TreeNode} node + * @param {TYPO3.Components.PageTree.Model} node * @param {Ext.EventObject} event * return {void} */ - openContextMenu: function(node, event) { - var attributes = Ext.apply(node.attributes.nodeData, { - t3ContextInfo: node.ownerTree.t3ContextInfo - }); - - this.contextMenuProvider.getActionsForNodeArray( - attributes, - function(configuration) { - this.contextMenu.removeAll(); - this.contextMenu.fill(node, this, configuration); - if (this.contextMenu.items.length) { - this.contextMenu.showAt(event.getXY()); - + openContextMenu: function(view, node, item, index, event) { + var tree = view.panel; + node.setNodeData('t3ContextInfo', tree.t3ContextInfo); + tree.contextMenuProvider.getActionsForNodeArray( + node.get('nodeData'), + function (configuration) { + tree.contextMenu.removeAll(); + tree.contextMenu.fill(node, tree, configuration); + if (tree.contextMenu.items.length) { + tree.contextMenu.showAt(event.getXY()); } - }, - this + } ); - }, - - /** - * Initialize the inline editor for the given tree. - * - * @return {void} - */ - enableInlineEditor: function() { - this.treeEditor = new TYPO3.Components.PageTree.TreeEditor(this); - }, - - /** - * Triggers the editing of the node if the tree editor is available - * - * @param {Ext.tree.TreeNode} node - * @return {void} - */ - triggerEdit: function(node) { - if (this.treeEditor) { - this.treeEditor.triggerEdit(node); - } + event.stopEvent(); }, /** @@ -400,208 +484,144 @@ TYPO3.Components.PageTree.Tree = Ext.extend(Ext.tree.TreePanel, { * return {void} */ enableDragAndDrop: function() { - // init proxy element - this.on('startdrag', this.initDd, this); - this.on('enddrag', this.stopDd, this); - - // node is moved - this.on('movenode', this.moveNode, this); - - // new node is created/copied - this.on('beforenodedrop', this.beforeDropNode, this); - this.on('nodedrop', this.dropNode, this); - - // listens on the ctrl key to toggle the copy mode - (new Ext.KeyMap(document, { - key: Ext.EventObject.CONTROL, - scope: this, - buffer: 250, - fn: function() { - if (!this.controlKeyPressed && this.dragZone.dragging && this.copyHint) { - if (this.shouldCopyNode) { - this.copyHint.show(); - } else { - this.copyHint.hide(); - } - - this.shouldCopyNode = !this.shouldCopyNode; - this.dragZone.proxy.el.toggleClass('typo3-pagetree-copy'); - } - this.controlKeyPressed = true; - } - }, 'keydown')); - - (new Ext.KeyMap(document, { - key: Ext.EventObject.CONTROL, - scope: this, - fn: function() { - this.controlKeyPressed = false; - } - }, 'keyup')); - - // listens on the escape key to stop the dragging - (new Ext.KeyMap(document, { - key: Ext.EventObject.ESC, - scope: this, - buffer: 250, - fn: function(event) { - if (this.dragZone.dragging) { - Ext.dd.DragDropMgr.stopDrag(event); - this.dragZone.onInvalidDrop(event); - } - } - }, 'keydown')); + var view = this.getView(); + var dragZone = view.getPlugin('treeViewDragDrop').dragZone; + + // Show drop zone before drag, otherwise the proxy is never notified + dragZone.onBeforeDrag = Ext.Function.bind(this.startDeletionDropZone, view); + // Hide the drop zone after the drag completes + dragZone.onMouseUp = Ext.Function.bind(this.stopDeletionDropZone, view); + dragZone.endDrag = Ext.Function.bind(this.stopDeletionDropZone, view); + dragZone.afterInvalidDrop = Ext.Function.bind(this.stopDeletionDropZone, view, [true]); + + // Node is moved + this.on('itemmove', this.moveNode, this); + + // New node is created/copied + view.on('beforedrop', this.beforeDropNode, this); + view.on('drop', this.dropNode, this); }, /** - * Disables the deletion drop zone if configured + * Enables the deletion drop zone if configured * * @return {void} */ - stopDd: function() { - if (this.deletionDropZoneId) { - Ext.getCmp(this.deletionDropZoneId).hide(); - this.app.doLayout(); - } - }, - - /** - * Enables the deletion drop zone if configured. Also it creates the - * shown dd proxy element. - * - * @param {TYPO3.Components.PageTree.Tree} treePanel - * @param {Ext.tree.TreeNode} node - * @return {void} - */ - initDd: function(treePanel, node) { - var nodeHasChildNodes = (node.hasChildNodes() || node.isExpandable()); - if (this.deletionDropZoneId && + startDeletionDropZone: function (dragData, event) { + var view = dragData.view, + tree = view.panel, + node = view.getRecord(dragData.item), + nodeHasChildNodes = (node.hasChildNodes() || node.isExpandable()); + var tree = this.panel; + if (tree.deletionDropZoneId && (!nodeHasChildNodes || (nodeHasChildNodes && TYPO3.Components.PageTree.Configuration.canDeleteRecursivly) )) { - Ext.getCmp(this.deletionDropZoneId).show(); - this.app.doLayout(); + Ext.getCmp(tree.deletionDropZoneId).show(); } - this.initDDProxyElement(); }, /** - * Adds the copy hint to the proxy element + * Disables the deletion drop zone if configured * * @return {void} */ - initDDProxyElement: function() { - this.shouldCopyNode = false; - this.copyHint = new Ext.Element(document.createElement('div')).addClass(this.id + '-copy'); - this.copyHint.dom.appendChild(document.createTextNode(TYPO3.Components.PageTree.LLL.copyHint)); - this.copyHint.setVisibilityMode(Ext.Element.DISPLAY); - this.dragZone.proxy.el.shadow = false; - this.dragZone.proxy.ghost.dom.appendChild(this.copyHint.dom); + stopDeletionDropZone: function (forceStop) { + var tree = this.panel; + if (tree.deletionDropZoneId && (!this.getPlugin('treeViewDragDrop').dragZone.dragging || forceStop)) { + Ext.getCmp(tree.deletionDropZoneId).hide(); + } }, /** - * Creates a Fake Node + * Creates a place holder node when a new node is about to be dropped * - * This must be done to prevent the calling of the moveNode event. - * - * @param {object} dragElement + * @param {HTMLElement node} node + * @param {object} dragData + * @param {TYPO3.Components.PageTree.Model} overNode + * @param {string} dropPosition + * @return {boolean} */ - beforeDropNode: function(dragElement) { - if (dragElement.data && dragElement.data.item && dragElement.data.item.shouldCreateNewNode) { - this.t3ContextInfo.serverNodeType = dragElement.data.item.nodeType; - dragElement.dropNode = new Ext.tree.TreeNode({ + beforeDropNode: function (node, dragData, overNode, dropPosition) { + if (dragData && dragData.item && dragData.item.shouldCreateNewNode) { + // Inserting a new node of the type that was selected in the top panel + this.t3ContextInfo.serverNodeType = dragData.item.nodeType; + dragData.dropNode = Ext.create('TYPO3.Components.PageTree.Model', { text: TYPO3.Components.PageTree.LLL.fakeNodeHint, leaf: true, isInsertedNode: true }); - - // fix incorrect cancel value - dragElement.cancel = false; - - } else if (this.shouldCopyNode) { - dragElement.dropNode.ui.onOut(); - var attributes = dragElement.dropNode.attributes; - attributes.isCopiedNode = true; - attributes.id = 'fakeNode'; - dragElement.dropNode = new Ext.tree.TreeNode(attributes); + dragData.records = [dragData.dropNode]; } - return true; }, /** - * Differentiate between the copy and insert event + * Handle the copy and insert events * - * @param {Ext.tree.TreeDropZone} dragElement + * @param {HTMLElement node} node + * @param {object} dragData + * @param {TYPO3.Components.PageTree.Model} overNode + * @param {string} dropPosition * return {void} */ - dropNode: function(dragElement) { - this.controlKeyPressed = false; - if (dragElement.dropNode.attributes.isInsertedNode) { - dragElement.dropNode.attributes.isInsertedNode = false; - this.insertNode(dragElement.dropNode); - } else if (dragElement.dropNode.attributes.isCopiedNode) { - dragElement.dropNode.attributes.isCopiedNode = false; - this.copyNode(dragElement.dropNode) + dropNode: function (node, dragData, overNode, dropPosition) { + if (dragData.dropNode) { + if (dragData.dropNode.get('isInsertedNode')) { + dragData.dropNode.set('isInsertedNode', false); + this.insertNode(dragData.dropNode); + } + } else if (dragData.copy) { + this.copyNode(dragData.records[0]); } }, /** * Moves a node * - * @param {TYPO3.Components.PageTree.Tree} tree - * @param {Ext.tree.TreeNode} movedNode - * @param {Ext.tree.TreeNode} oldParent - * @param {Ext.tree.TreeNode} newParent + * @param {TYPO3.Components.PageTree.Model} movedNode + * @param {TYPO3.Components.PageTree.Model} oldParent + * @param {TYPO3.Components.PageTree.Model} newParent * @param {int} position * return {void} */ - moveNode: function(tree, movedNode, oldParent, newParent, position) { - this.controlKeyPressed = false; - tree.t3ContextNode = movedNode; - + moveNode: function (movedNode, oldParent, newParent, position) { + this.t3ContextNode = movedNode; if (position === 0) { - this.commandProvider.moveNodeToFirstChildOfDestination(newParent, tree); + this.commandProvider.moveNodeToFirstChildOfDestination(newParent, this); } else { var previousSiblingNode = newParent.childNodes[position - 1]; - this.commandProvider.moveNodeAfterDestination(previousSiblingNode, tree); + this.commandProvider.moveNodeAfterDestination(previousSiblingNode, this); } }, /** * Inserts a node * - * @param {Ext.tree.TreeNode} movedNode + * @param {TYPO3.Components.PageTree.Model} node * return {void} */ - insertNode: function(movedNode) { - this.t3ContextNode = movedNode.parentNode; - - movedNode.disable(); - if (movedNode.previousSibling) { - this.commandProvider.insertNodeAfterDestination(movedNode, this); + insertNode: function (node) { + this.t3ContextNode = node.parentNode; + if (node.previousSibling) { + this.commandProvider.insertNodeAfterDestination(node, this); } else { - this.commandProvider.insertNodeToFirstChildOfDestination(movedNode, this); + this.commandProvider.insertNodeToFirstChildOfDestination(node, this); } }, /** * Copies a node * - * @param {Ext.tree.TreeNode} movedNode + * @param {TYPO3.Components.PageTree.Model} movedNode * return {void} */ - copyNode: function(movedNode) { - this.t3ContextNode = movedNode; - - movedNode.disable(); - if (movedNode.previousSibling) { - this.commandProvider.copyNodeAfterDestination(movedNode, this); + copyNode: function (node) { + this.t3ContextNode = node; + if (node.previousSibling) { + this.commandProvider.copyNodeAfterDestination(node, this); } else { - this.commandProvider.copyNodeToFirstChildOfDestination(movedNode, this); + this.commandProvider.copyNodeToFirstChildOfDestination(node, this); } } }); - -// XTYPE Registration -Ext.reg('TYPO3.Components.PageTree.Tree', TYPO3.Components.PageTree.Tree); diff --git a/t3lib/js/extjs/components/pagetree/javascript/treedropzone.js b/t3lib/js/extjs/components/pagetree/javascript/treedropzone.js new file mode 100644 index 0000000000000000000000000000000000000000..2f4888ca9ffc77976915ab8180120f1bd2ac925f --- /dev/null +++ b/t3lib/js/extjs/components/pagetree/javascript/treedropzone.js @@ -0,0 +1,112 @@ +/*************************************************************** +* Copyright notice +* +* (c) 2011 Stanislas Rolland <typo3@sjbr.ca> +* 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! +***************************************************************/ +/** + * @class TYPO3.Components.PageTree.ViewDropZone + * + * handleNodeDrop method is modified in order to process copied nodes + * + * Based on ExtJS 4.0.7. + * Should be reviewed on ExtJS upgrade + * + * @namespace TYPO3.Components.PageTree + * @extends Ext.tree.ViewDropZone + * @author Stanislas Rolland <typo3@sjbr.ca> + */ +Ext.define('TYPO3.Components.PageTree.ViewDropZone', { + extend: 'Ext.tree.ViewDropZone', + + handleNodeDrop: function(data, targetNode, position) { + var me = this, + view = me.view, + parentNode = targetNode.parentNode, + store = view.getStore(), + recordDomNodes = [], + records, i, len, + insertionMethod, argList, + needTargetExpand, + transferData, + processDrop; + + if (data.copy) { + records = data.records; + data.records = []; + for (i = 0, len = records.length; i < len; i++) { + data.records.push(Ext.apply({}, records[i].data)); + } + } + + me.cancelExpand(); + + if (position == 'before') { + insertionMethod = parentNode.insertBefore; + argList = [null, targetNode]; + targetNode = parentNode; + } else if (position == 'after') { + if (targetNode.nextSibling) { + insertionMethod = parentNode.insertBefore; + argList = [null, targetNode.nextSibling]; + } else { + insertionMethod = parentNode.appendChild; + argList = [null]; + } + targetNode = parentNode; + } else { + if (!targetNode.isExpanded()) { + needTargetExpand = true; + } + insertionMethod = targetNode.appendChild; + argList = [null]; + } + + transferData = function() { + var node; + for (i = 0, len = data.records.length; i < len; i++) { + argList[0] = data.records[i]; + node = insertionMethod.apply(targetNode, argList); + // We need to update the records array in order to process the copied nodes in the drop event handler + data.records[i] = node; + + if (Ext.enableFx && me.dropHighlight) { + recordDomNodes.push(view.getNode(node)); + } + } + + if (Ext.enableFx && me.dropHighlight) { + Ext.Array.forEach(recordDomNodes, function(n) { + if (n) { + Ext.fly(n.firstChild ? n.firstChild : n).highlight(me.dropHighlightColor); + } + }); + } + }; + + if (needTargetExpand) { + targetNode.expand(false, transferData); + } else { + transferData(); + } + } +}); \ No newline at end of file diff --git a/t3lib/js/extjs/components/pagetree/javascript/treeeditor.js b/t3lib/js/extjs/components/pagetree/javascript/treeeditor.js index 0d12e7d526678b227e3039e4a31f56e3f38e3910..5daa34e2d79ec015ad0316cc427fe8cce03d1b52 100644 --- a/t3lib/js/extjs/components/pagetree/javascript/treeeditor.js +++ b/t3lib/js/extjs/components/pagetree/javascript/treeeditor.js @@ -23,8 +23,6 @@ * * This copyright notice MUST APPEAR in all copies of the script! ***************************************************************/ -Ext.namespace('TYPO3.Components.PageTree'); - /** * @class TYPO3.Components.PageTree.TreeEditor * @@ -32,30 +30,46 @@ Ext.namespace('TYPO3.Components.PageTree'); * editable label. * * @namespace TYPO3.Components.PageTree - * @extends Ext.tree.TreeEditor + * @extends Ext.ux.tree.TreeEditing * @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, +Ext.define('TYPO3.Components.PageTree.TreeEditor', { + extend: 'Ext.grid.plugin.CellEditing', + alias: 'plugin.pagetreeeditor', /** - * Edit delay - * - * @type {int} + * @override + * @private Collects all information necessary for any subclasses to perform their editing functions. + * @param record + * @param columnHeader + * @returns {Object} The editing context based upon the passed record and column */ - editDelay: 250, + getEditingContext: function (record, columnHeader) { + var me = this, + grid = me.grid, + store = grid.store, + colIdx, + editor, + originalValue, + value; - /** - * Indicates if an underlying shadow should be shown - * - * @type {Boolean} - */ - shadow: false, + if (Ext.isNumber(columnHeader)) { + colIdx = columnHeader; + columnHeader = grid.headerCt.getHeaderAtIndex(colIdx); + } else { + colIdx = columnHeader.getIndex(); + } + + return { + column: columnHeader, + colIdx: colIdx, + field: columnHeader.dataIndex, + grid: grid, + originalValue: record.getNodeData('editableText'), + record: record, + tree: grid + }; + }, /** * Listeners @@ -63,80 +77,66 @@ TYPO3.Components.PageTree.TreeEditor = Ext.extend(Ext.tree.TreeEditor, { * Handles the synchronization between the edited label and the shown label. */ listeners: { - beforecomplete: function(node) { - this.updatedValue = this.getValue(); - if (this.updatedValue === '') { - this.cancelEdit(); - return false; - } - this.setValue(this.editNode.attributes.prefix + Ext.util.Format.htmlEncode(this.updatedValue) + this.editNode.attributes.suffix); - }, - - complete: { - fn: function(node, newValue, oldValue) { - if (newValue === oldValue) { - this.fireEvent('canceledit', this); + beforeedit: { + fn: function (editEvent) { + var tree = editEvent.tree; + // Prevent editing the currently selected node + // Prevent editing if the node is not editable + if (editEvent.record == tree.currentSelectedNode || !editEvent.record.getNodeData('editable')) { + if (tree.currentSelectedNode) { + tree.getView().select(tree.currentSelectedNode); + } return false; } - - this.editNode.getOwnerTree().commandProvider.saveTitle(node, this.updatedValue, oldValue, this); + // Inhibit clicks on the tree while editing + tree.inhibitClicks = 2; } }, - - startEdit: { - fn: function(element, value) { - this.field.selectText(); + validateedit: { + fn: function (treeEditor, editEvent) { + var editorField = treeEditor.getEditor(editEvent.record, editEvent.column); + this.newValue = editorField.getValue(); + if (this.newValue === '' || this.newValue === editEvent.originalValue) { + var tree = editEvent.tree; + if (tree.currentSelectedNode) { + tree.getView().select(tree.currentSelectedNode); + } + return false; + } else { + editorField.setValue(editEvent.record.getNodeData('prefix') + Ext.util.Format.htmlEncode(this.newValue) + editEvent.record.getNodeData('suffix')); + } + } }, - - canceledit: function() { - var tree = this.editNode.getOwnerTree(); - if (tree.currentSelectedNode) { - tree.currentSelectedNode.select(); + edit: { + fn: function (treeEditor, editEvent) { + var tree = editEvent.tree; + tree.commandProvider.saveTitle(editEvent.record, this.newValue, editEvent.originalValue, treeEditor, tree, editEvent.field); } } }, + cancelEdit: function () { + var tree = this.grid; + if (tree.currentSelectedNode) { + tree.getView().select(tree.currentSelectedNode); + } + this.callParent(arguments); + }, /** - * Updates the edit node + * Updates the text field * - * @param {Ext.tree.TreeNode} node + * @param {TYPO3.Components.PageTree.Model} node * @param {String} editableText - * @param {String} updatedNode + * @param {String} updatedText + * @param {String} dataIndex + * @param {TYPO3.Components.PageTree.Tree} tree * @return {void} */ - updateNodeText: function(node, editableText, updatedNode) { - this.editNode.setText(this.editNode.attributes.prefix + updatedNode + this.editNode.attributes.suffix); - this.editNode.attributes.editableText = editableText; - }, - - /** - * Overridden 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; - } + updateNodeText: function (record, editableText, updatedText, dataIndex, tree) { + record.set(dataIndex, record.getNodeData('prefix') + updatedText + record.getNodeData('suffix')); + record.setNodeData('editableText', editableText); + record.commit(); + tree.getView().refresh(record.getId()); } }); - -// XTYPE Registration -Ext.reg('TYPO3.Components.PageTree.TreeEditor', TYPO3.Components.PageTree.TreeEditor); diff --git a/t3lib/js/extjs/components/pagetree/javascript/treeviewdragdrop.js b/t3lib/js/extjs/components/pagetree/javascript/treeviewdragdrop.js new file mode 100644 index 0000000000000000000000000000000000000000..b0c5bee20c5fd2d65579c48756e0d8d9ca9e1987 --- /dev/null +++ b/t3lib/js/extjs/components/pagetree/javascript/treeviewdragdrop.js @@ -0,0 +1,65 @@ +/*************************************************************** +* Copyright notice +* +* (c) 2011 Stanislas Rolland <typo3@sjbr.ca> +* 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! +***************************************************************/ +/** + * @class TYPO3.Components.PageTree.plugin.TreeViewDragDrop + * + * onViewRender method is modified in order to use TYPO3.Components.PageTree.ViewDropZone + * + * @namespace TYPO3.Components.PageTree + * @extends Ext.tree.plugin.TreeViewDragDrop + * @author Stanislas Rolland <typo3@sjbr.ca> + */ +Ext.define('TYPO3.Components.PageTree.plugin.TreeViewDragDrop', { + extend: 'Ext.tree.plugin.TreeViewDragDrop', + alias: 'plugin.pagetreeviewdragdrop', + + onViewRender: function(view) { + var me = this; + + if (me.enableDrag) { + me.dragZone = Ext.create('Ext.tree.ViewDragZone', { + view: view, + ddGroup: me.dragGroup || me.ddGroup, + dragText: me.dragText, + repairHighlightColor: me.nodeHighlightColor, + repairHighlight: me.nodeHighlightOnRepair + }); + } + + if (me.enableDrop) { + me.dropZone = Ext.create('TYPO3.Components.PageTree.ViewDropZone', { + view: view, + ddGroup: me.dropGroup || me.ddGroup, + allowContainerDrops: me.allowContainerDrops, + appendOnly: me.appendOnly, + allowParentInserts: me.allowParentInserts, + expandDelay: me.expandDelay, + dropHighlightColor: me.nodeHighlightColor, + dropHighlight: me.nodeHighlightOnDrop + }); + } + } +}); \ No newline at end of file diff --git a/t3lib/js/extjs/tree/tree.js b/t3lib/js/extjs/tree/tree.js index f0cad3962071883b4f1ad80753c0d669723cca24..bbd262485b33cf8b8a1eb74c06bb3f87a23ecf1e 100644 --- a/t3lib/js/extjs/tree/tree.js +++ b/t3lib/js/extjs/tree/tree.js @@ -23,60 +23,64 @@ * * This copyright notice MUST APPEAR in all copies of the script! ***************************************************************/ - -Ext.ns('TYPO3.Components', 'TYPO3.Components.Tree'); - /** * TYPO3window - General TYPO3 tree component */ +Ext.ns('TYPO3.Components.Tree'); TYPO3.Components.Tree = {}; TYPO3.Components.Tree.StandardTreeItemData = []; -TYPO3.Components.Tree.StandardTree = function(config) { - var conf = Ext.apply({ - header: false, - width: 280, - rootVisible: false, - useArrows: false, - lines: true, - autoScroll: true, - containerScroll: true, - exclusiveSelectedKey: null, - stateful: true, - filterOptionStartsWith: true, - countSelectedNodes: 0, - loader: new Ext.tree.TreeLoader({ - preloadChildren: true, - clearOnLoad: false - }), - root: new Ext.tree.AsyncTreeNode({ - text: TYPO3.l10n.localize('tcatree'), - id: 'root', - expanded: true, - children: TYPO3.Components.Tree.StandardTreeItemData[config.id] - }), - collapseFirst: false, - listeners: { - 'checkchange': function(checkedNode, checked) { - if (Ext.isFunction(this.checkChangeHandler)) { - this.checkChangeHandler.call(this, checkedNode, checked); - } - }, - scope: this - } - }, config); - TYPO3.Components.Tree.StandardTree.superclass.constructor.call(this, conf); -}; - - -Ext.extend(TYPO3.Components.Tree.StandardTree, Ext.tree.TreePanel, { - +Ext.define('TYPO3.Components.Tree.StandardTree', { + extend: 'Ext.tree.Panel', + + constructor: function(config) { + var conf = Ext.apply({ + header: false, + width: 280, + rootVisible: false, + useArrows: false, + lines: true, + autoScroll: true, + containerScroll: true, + exclusiveSelectedKey: null, + stateful: true, + filterOptionStartsWith: true, + countSelectedNodes: 0, + // Needs to be migrated to ExtJS 4 + loader: new Ext.tree.TreeLoader({ + preloadChildren: true, + clearOnLoad: false + }), + root: new Ext.tree.AsyncTreeNode({ + text: TYPO3.l10n.localize('tcatree'), + id: 'root', + expanded: true, + children: TYPO3.Components.Tree.StandardTreeItemData[config.id] + }), + collapseFirst: false, + listeners: { + 'checkchange': function(checkedNode, checked) { + if (Ext.isFunction(this.checkChangeHandler)) { + this.checkChangeHandler.call(this, checkedNode, checked); + } + }, + scope: this + } + }, config); + this.callParent([conf]); + }, initComponent: function() { - Ext.apply(this, { - tbar: this.initialConfig.showHeader ? TYPO3.Components.Tree.Toolbar([], this) : null - }); - TYPO3.Components.Tree.StandardTree.superclass.initComponent.call(this); + if (this.initialConfig.showHeader) { + Ext.apply(this, { + dockedItems: [{ + xtype: 'toolbar', + dock: 'top', + items: TYPO3.Components.Tree.Toolbar([], this) + }] + }); + } + this.callParent(arguments); }, filterTree: function(filterText) { var text = filterText.getValue(); @@ -139,7 +143,7 @@ TYPO3.Components.Tree.Toolbar = function(items, scope) { ] } }, - new Ext.form.TextField({ + Ext.create('Ext.form.field.Text', { width: 150, emptyText: TYPO3.l10n.localize('tcatree.findItem'), enableKeyEvents: true, diff --git a/t3lib/tree/class.t3lib_tree_abstracttree.php b/t3lib/tree/class.t3lib_tree_abstracttree.php index cda092584e1993f431ccdf0eb20bccfde018190e..5ba1ae315e535bf86c182c76f46b4cc768644d70 100644 --- a/t3lib/tree/class.t3lib_tree_abstracttree.php +++ b/t3lib/tree/class.t3lib_tree_abstracttree.php @@ -63,7 +63,7 @@ abstract class t3lib_tree_AbstractTree { } /** - * @param t3lib_tree_renderer_Abstract $dataProvider + * @param t3lib_tree_renderer_Abstract $nodeRenderer * @return void */ public function setNodeRenderer(t3lib_tree_renderer_Abstract $nodeRenderer) { @@ -83,6 +83,15 @@ abstract class t3lib_tree_AbstractTree { * @return t3lib_tree_Node */ abstract public function getRoot(); + + /** + * @param mixed $search + * @return t3lib_tree_Node + */ + public function find($search) { + return $this->getRoot()->find($search); + } + } ?> \ No newline at end of file diff --git a/t3lib/tree/class.t3lib_tree_node.php b/t3lib/tree/class.t3lib_tree_node.php index dd098882ecb3121dd4783326f2abe88349bc45d7..319307ccba22baec40ff4c221d11cc392f07e206 100644 --- a/t3lib/tree/class.t3lib_tree_node.php +++ b/t3lib/tree/class.t3lib_tree_node.php @@ -62,7 +62,6 @@ class t3lib_tree_Node implements t3lib_tree_ComparableNode, Serializable { * This is useful for the deserialization. * * @param array $data - * @return void */ public function __construct(array $data = array()) { if (count($data)) { @@ -107,7 +106,7 @@ class t3lib_tree_Node implements t3lib_tree_ComparableNode, Serializable { * @return boolean */ public function hasChildNodes() { - if ($this->childNodes !== NULL) { + if ($this->childNodes != NULL && $this->childNodes->count() > 0) { return TRUE; } @@ -214,7 +213,7 @@ class t3lib_tree_Node implements t3lib_tree_ComparableNode, Serializable { * @param array $data * @return void */ - public function dataFromArray($data) { + public function dataFromArray(array $data) { $this->setId($data['id']); if (isset($data['parentNode']) && $data['parentNode'] !== '') { @@ -255,6 +254,43 @@ class t3lib_tree_Node implements t3lib_tree_ComparableNode, Serializable { } $this->dataFromArray($arrayRepresentation); } + + /** + * searches the tree to find an node + * + * @param mixed $search + * @return t3lib_tree_Node + */ + public function find($search) { + $result = NULL; + + if($this->getId() == $search) { + $result = $this; + } elseif($this->hasChildNodes() && $this->getChildNodes() != NULL) { + foreach ($this->getChildNodes() AS $childNode) { + $result = $childNode->find($search); + if ($result != NULL) { + break; + } + } + } + + return $result; + } + + public function getLevel() { + if ($this->getParentNode() == NULL) { + return 0; + } else { + $i = 1; + $node = $this->getParentNode(); + while ($node != NULL) { + $node = $node->getParentNode(); + $i++; + } + return $i; + } + } } ?> \ No newline at end of file diff --git a/t3lib/tree/class.t3lib_tree_nodecollection.php b/t3lib/tree/class.t3lib_tree_nodecollection.php index 266f11ee98d30b19ac98933992077fe686390f04..e1a9293a452fa15d733f6777ccdfe3f57d0e7013 100644 --- a/t3lib/tree/class.t3lib_tree_nodecollection.php +++ b/t3lib/tree/class.t3lib_tree_nodecollection.php @@ -62,7 +62,9 @@ class t3lib_tree_NodeCollection extends ArrayObject { * * @noapi * @see t3lib_tree_Node::compareTo - * @return void + * @param t3lib_tree_Node $node + * @param t3lib_tree_Node $otherNode + * @return int */ public function nodeCompare(t3lib_tree_Node $node, t3lib_tree_Node $otherNode) { return $node->compareTo($otherNode); diff --git a/t3lib/tree/class.t3lib_tree_representationnode.php b/t3lib/tree/class.t3lib_tree_representationnode.php index 8a9482a393547d87ed54adfa248c535a64c815dd..4c64a733ad1ead5fd1439334e51aa08ba6c604ef 100644 --- a/t3lib/tree/class.t3lib_tree_representationnode.php +++ b/t3lib/tree/class.t3lib_tree_representationnode.php @@ -32,6 +32,7 @@ * @author Steffen Ritter <info@steffen-ritter.net> * @package TYPO3 * @subpackage t3lib + * @deprecated Not needed anymore as of 4.7, will be removed on 4.9 */ class t3lib_tree_RepresentationNode extends t3lib_tree_Node { /** @@ -69,6 +70,10 @@ class t3lib_tree_RepresentationNode extends t3lib_tree_Node { */ protected $callbackAction = ''; + public function __construct() { + t3lib_div::deprecationLog("The Class t3lib_tree_RepresentationNode is deprecated as of TYPO3 4.7, will be removed in 4.9"); + } + /** * @param string $class * @return void diff --git a/t3lib/tree/extjs/class.t3lib_tree_extjs_abstractextjstree.php b/t3lib/tree/extjs/class.t3lib_tree_extjs_abstractextjstree.php new file mode 100644 index 0000000000000000000000000000000000000000..b7762907bc2372b586ac38a30c6ad60ffdb5e6a0 --- /dev/null +++ b/t3lib/tree/extjs/class.t3lib_tree_extjs_abstractextjstree.php @@ -0,0 +1,48 @@ +<?php +/*************************************************************** + * Copyright notice + * + * (c) 2010-2011 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! + ***************************************************************/ + +/** + * Abstract ExtJS tree based on ExtDirect + * + * @author Stefan Galinski <stefan.galinski@gmail.com> + * @package TYPO3 + * @subpackage t3lib + */ +abstract class t3lib_tree_ExtJs_AbstractExtJsTree extends t3lib_tree_AbstractTree { + + /** + * Fetches the next tree level + * + * @abstract + * @param int $nodeId + * @param stdClass $nodeData + * @return array + */ + abstract public function getNextTreeLevel($nodeId, $nodeData); +} + +?> \ No newline at end of file diff --git a/t3lib/tree/extdirect/class.t3lib_tree_extdirect_abstractextjstree.php b/t3lib/tree/extjs/class.t3lib_tree_extjs_abstractstatefulextjstree.php similarity index 83% rename from t3lib/tree/extdirect/class.t3lib_tree_extdirect_abstractextjstree.php rename to t3lib/tree/extjs/class.t3lib_tree_extjs_abstractstatefulextjstree.php index 8dcfe320b41001893cf2089b6cbc5e67657f49e3..6ac45d21d8bb46daad4847abc2fcf459d3c22e9f 100644 --- a/t3lib/tree/extdirect/class.t3lib_tree_extdirect_abstractextjstree.php +++ b/t3lib/tree/extjs/class.t3lib_tree_extjs_abstractstatefulextjstree.php @@ -27,12 +27,13 @@ /** * Abstract ExtJS tree based on ExtDirect + * extends with StateProvider * - * @author Stefan Galinski <stefan.galinski@gmail.com> + * @author Steffen Ritter * @package TYPO3 * @subpackage t3lib */ -abstract class t3lib_tree_ExtDirect_AbstractExtJsTree extends t3lib_tree_AbstractTree { +abstract class t3lib_tree_ExtJs_AbstractStatefulExtJsTree extends t3lib_tree_ExtJs_AbstractExtJsTree { /** * State Provider @@ -56,15 +57,6 @@ abstract class t3lib_tree_ExtDirect_AbstractExtJsTree extends t3lib_tree_Abstrac return $this->stateProvider; } - /** - * Fetches the next tree level - * - * @abstract - * @param int $nodeId - * @param stdClass $nodeData - * @return array - */ - abstract public function getNextTreeLevel($nodeId, $nodeData); } ?> \ No newline at end of file diff --git a/t3lib/tree/extjs/class.t3lib_tree_extjs_node.php b/t3lib/tree/extjs/class.t3lib_tree_extjs_node.php new file mode 100644 index 0000000000000000000000000000000000000000..517f306611cb2164196bdfae0f07b59e0c608155 --- /dev/null +++ b/t3lib/tree/extjs/class.t3lib_tree_extjs_node.php @@ -0,0 +1,590 @@ +<?php +/*************************************************************** + * Copyright notice + * + * (c) 2010-2011 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! + ***************************************************************/ + +/** + * Node for the usage with ExtDirect and ExtJS + * + * @author Stefan Galinski <stefan.galinski@gmail.com> + * @package TYPO3 + * @subpackage t3lib + */ +class t3lib_tree_ExtJs_Node extends t3lib_tree_Node implements t3lib_tree_RenderableNode { + + /** + * Indicator if the node is allowDrag + * + * @var bool + */ + protected $allowDrag = TRUE; + + /** + * Indicator if the node is allowed as a drop target + * + * @var bool + */ + protected $allowDrop = TRUE; + + /** + * Indicator if the noded is checked + * three-state: TRUE|FALSE|NULL + * NULL won't show a checkbox + * + * @var boolean|NULL + */ + protected $checked = NULL; + + /** + * CSS Class + * + * @var string + */ + protected $cls = ''; + + /** + * The number of parents this node has. ... + * + * @var int + */ + protected $depth; + + /** + * Indicator if the node can be expanded + * + * @var bool + */ + protected $expandable = TRUE; + + /** + * Indicator if the node is expanded + * + * @var bool + */ + protected $expanded = FALSE; + + /** + * An URL for a link that's created when this config is specified. + * + * @var string|NULL + */ + protected $href = NULL; + + /** + * Target for link in $href + * + * @var string + */ + protected $hrefTarget = ''; + + /** + * URL for this node's icon file + * + * @var string + */ + protected $icon; + + /** + * URL for this node's icon css class + * + * @var string + */ + protected $iconCls; + + + /** + * The position of the node inside its parents + * starting from 0 + * + * @var int + */ + protected $index; + + + /** + * True if this is the first node. + * + * @var boolean + */ + protected $isFirst; + + /** + * True if this is the last node + */ + protected $isLast; + + /** + * Leaf Node Indicator + * + * @var bool + */ + protected $leaf = TRUE; + + /** + * Quick Tip + * + * @var string + */ + protected $qtip = ''; + + /** + * Quick Tip title + * + * @var string + */ + protected $qtitle = ''; + + /** + * is root node? + * + * @var boolean + */ + protected $root = FALSE; + + /** + * Label + * + * @var string + */ + protected $text = ''; + + /** + * Sets the leaf node indicator + * + * @param bool $isLeaf + * @return void + */ + public function setLeaf($isLeaf) { + $this->leaf = ($isLeaf == TRUE); + } + + /** + * Returns if the node is a leaf node + * + * @return bool + */ + public function isLeafNode() { + return $this->leaf; + } + + /** + * Sets the expandable indicator + * + * @param bool $expandable + * @return void + */ + public function setExpandable($expandable) { + $this->expandable = ($expandable == TRUE); + } + + /** + * Returns the expandable indicator + * + * @return bool + */ + public function isExpandable() { + return $this->expandable; + } + + /** + * Sets the expanded indicator + * + * @param bool $expanded + * @return void + */ + public function setExpanded($expanded) { + $this->expanded = ($expanded == TRUE); + } + + /** + * Returns the expanded indicator + * + * @return bool + */ + public function isExpanded() { + if ($this->isLeafNode()) { + return TRUE; + } + + return $this->expanded; + } + + /** + * Sets the allowDrag indicator + * + * @param bool $draggable + * @return void + */ + public function setAllowDrag($draggable) { + $this->allowDrag = ($draggable == TRUE); + } + + /** + * Returns the allowDrag indicator + * + * @return bool + */ + public function isDraggable() { + return $this->allowDrag; + } + + /** + * Sets the indicator if the node can be a drop target + * + * @param bool $isDropTarget + * @return void + */ + public function setAllowDrop($isDropTarget) { + $this->allowDrop = ($isDropTarget == TRUE); + } + + /** + * Returns the indicator if the node is a drop target + * + * @return bool + */ + public function allowDrop() { + return $this->allowDrop; + } + + /** + * Sets the label of the node with the source field and the prefix + * + * @param string $text + * @return void + */ + public function setText($text) { + $this->text = $text; + } + + /** + * Returns the label + * + * @return string + */ + public function getText() { + return $this->text; + } + + /** + * Sets the css class(es) + * + * @param string $class + * @return void + */ + public function setCls($class) { + $this->cls = $class; + } + + /** + * Returns the css class(es) + * + * @return string + */ + public function getCls() { + return $this->cls; + } + + /** + * Sets the quick tip + * + * @param string $qtip + * @return void + */ + public function setQTip($qtip) { + $this->qtip = $qtip; + } + + /** + * Returns the quick tip + * + * @return string + */ + public function getQTip() { + return $this->qtip; + } + + /** + * Sets the child nodes collection + * + * @param t3lib_tree_NodeCollection $childNodes + * @return void + */ + public function setChildNodes(t3lib_tree_NodeCollection $childNodes) { + parent::setChildNodes($childNodes); + + if ($childNodes->count()) { + $this->setLeaf(FALSE); + } + } + + /** + * Returns the node in an array representation that can be used for serialization + * + * @param bool $addChildNodes + * @return array + */ + public function toArray($addChildNodes = TRUE) { + $arrayRepresentation = array( + 'serializeClassName' => get_class($this), + 'allowDrag' => $this->isDraggable(), + 'allowDrop' => $this->allowDrop(), + 'checked' => $this->getChecked(), + 'cls' => $this->getCls(), + 'depth' => $this->getDepth(), + 'expandable' => $this->isExpandable(), + 'expanded' => $this->isExpanded(), + 'href' => $this->getHref(), + 'hrefTarget' => $this->getHrefTarget(), + 'id' => $this->getId(), + 'icon' => $this->getIcon(), + 'iconCls' => $this->getIconCls(), + 'index' => $this->getIndex(), + 'isFirst' => $this->getIsFirst(), + 'isLast' => $this->getIsLast(), + 'parentId' => (!$this->getRoot() && $this->getParentNode() ? $this->getParentNode()->getId() : ''), + 'qtip' => $this->getQTip(), + 'qtitle' => $this->getQtitle(), + 'root' => $this->getRoot(), + 'text' => $this->getText(), + ); + + // do not provide config if empty + if (trim($this->href) == '') { + unset($arrayRepresentation['href']); + unset($arrayRepresentation['hrefTarget']); + } + + // only added check option if checkbox should be shown + if($this->getChecked() == NULL) { + unset($arrayRepresentation['checked']); + } + // only set the leaf attribute if the node has children's, + // otherwise you cannot add child's to real leaf nodes + if (!$this->isLeafNode()) { + $arrayRepresentation['leaf'] = FALSE; + } + + // Suhosin(?) or some other strange environment thingy prevents + // the direct copy of an array into an index of the same array + $copy = $arrayRepresentation; + $arrayRepresentation['nodeData'] = $copy; + + if ($this->hasChildNodes() && $addChildNodes) { + $arrayRepresentation['children'] = $this->childNodes->toArray(); + } + + return $arrayRepresentation; + } + + /** + * Sets data of the node by a given data array + * + * @param array $data + * @return void + */ + public function dataFromArray($data) { + parent::dataFromArray($data); + + $this->setText($data['label']); + $this->setCls($data['cls']); + $this->setQTip($data['qtip']); + $this->setExpanded($data['expanded']); + $this->setExpandable($data['expandable']); + $this->setAllowDrag($data['allowDrag']); + $this->setAllowDrop($data['isTarget']); + $this->setChecked(isset($data['checked']) ? (bool)$data['checked'] : NULL); + + // only set the leaf attribute if it's applied + // otherwise you cannot insert nodes into this one + if (isset($data['leaf'])) { + $this->setLeaf(FALSE); + } + } + + /** + * @param bool|NULL $checked + */ + public function setChecked($checked) { + $this->checked = $checked; + } + + /** + * @return bool|NULL + */ + public function getChecked() { + return $this->checked; + } + + /** + * @param int $depth + */ + public function setDepth($depth) { + $this->depth = $depth; + } + + /** + * @return int + */ + public function getDepth() { + return $this->depth; + } + + /** + * @param NULL|string $href + */ + public function setHref($href) { + $this->href = $href; + } + + /** + * @return NULL|string + */ + public function getHref() { + return $this->href; + } + + /** + * @param string $hrefTarget + */ + public function setHrefTarget($hrefTarget) { + $this->hrefTarget = $hrefTarget; + } + + /** + * @return string + */ + public function getHrefTarget() { + return $this->hrefTarget; + } + + /** + * @param string $icon + */ + public function setIcon($icon) { + $this->icon = $icon; + } + + /** + * @return string + */ + public function getIcon() { + return $this->icon; + } + + /** + * @param string $iconCls + */ + public function setIconCls($iconCls) { + $this->iconCls = $iconCls; + } + + /** + * @return string + */ + public function getIconCls() { + return $this->iconCls; + } + + /** + * @param int $index + */ + public function setIndex($index) { + $this->index = $index; + } + + /** + * @return int + */ + public function getIndex() { + return $this->index; + } + + /** + * @param boolean $isFirst + */ + public function setIsFirst($isFirst) { + $this->isFirst = $isFirst; + } + + /** + * @return boolean + */ + public function getIsFirst() { + return $this->isFirst; + } + + public function setIsLast($isLast) { + $this->isLast = $isLast; + } + + public function getIsLast() { + return $this->isLast; + } + + + /** + * @param string $qtitle + */ + public function setQtitle($qtitle) { + $this->qtitle = $qtitle; + } + + /** + * @return string + */ + public function getQtitle() { + return $this->qtitle; + } + + /** + * @param boolean $root + */ + public function setRoot($root) { + $this->root = $root; + } + + /** + * @return boolean + */ + public function getRoot() { + return $this->root; + } + + /** + * returns a string representation + * + * @return string + */ + public function toString() { + return $this->getText(); + } +} + +if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/tree/extjs/class.t3lib_tree_extjs_node.php'])) { + include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/tree/extjs/class.t3lib_tree_extjs_node.php']); +} + +?> \ No newline at end of file diff --git a/t3lib/tree/interfaces/interface.t3lib_tree_comparablenode.php b/t3lib/tree/interfaces/interface.t3lib_tree_comparablenode.php new file mode 100644 index 0000000000000000000000000000000000000000..ed7c0932dc50dc3ccad4babc58fd7c1e15403a54 --- /dev/null +++ b/t3lib/tree/interfaces/interface.t3lib_tree_comparablenode.php @@ -0,0 +1,69 @@ +<?php +/*************************************************************** + * Copyright notice + * + * (c) 2010-2011 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! + ***************************************************************/ + +/** + * Interface that defines the comparison of nodes + * + * @author Stefan Galinski <stefan.galinski@gmail.com> + * @package TYPO3 + * @subpackage t3lib + */ +interface t3lib_tree_ComparableNode { + /** + * Compare Node against another one + * + * Returns: + * 1 if the current node is greater than the $other, + * -1 if $other is greater than the current node and + * 0 if the nodes are equal + * + * <strong>Example</strong> + * <pre> + * if ($this->sortValue > $other->sortValue) { + * return 1; + * } elseif ($this->sortValue < $other->sortValue) { + * return -1; + * } else { + * return 0; + * } + * </pre> + * + * @param t3lib_tree_Node $other + * @return integer see description + */ + public function compareTo($other); + + /** + * Compares a node if it's identical to another node by the id property. + * + * @param t3lib_tree_Node $other + * @return boolean + */ + public function equals(t3lib_tree_Node $other); + +} +?> \ No newline at end of file diff --git a/t3lib/tree/interfaces/interface.t3lib_tree_draggableanddropable.php b/t3lib/tree/interfaces/interface.t3lib_tree_draggableanddropable.php new file mode 100644 index 0000000000000000000000000000000000000000..2bdf9cdd4af88778e25059d519f0bf85b79ad4a7 --- /dev/null +++ b/t3lib/tree/interfaces/interface.t3lib_tree_draggableanddropable.php @@ -0,0 +1,75 @@ +<?php +/*************************************************************** + * Copyright notice + * + * (c) 2010-2011 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! + ***************************************************************/ + +/** + * Describes necessary methods if the nodes are allowDrag and dropable + * within the tree. + * + * @author Stefan Galinski <stefan.galinski@gmail.com> + * @author Steffen Ritter <info@steffen-ritter.net> + * @package TYPO3 + * @subpackage t3lib + */ +interface t3lib_tree_DraggableAndDropable { + /** + * Moves given node inside a destination node + * + * @param t3lib_tree_Node $node + * @param t3lib_tree_Node $destination + * @return void + */ + public function moveNodeInDestinationNode($node, $destination); + + /** + * Moves given node after a destination node + * + * @param t3lib_tree_Node $node + * @param t3lib_tree_Node $destination + * @return void + */ + public function moveNodeAfterDestinationNode($node, $destination); + + /** + * Copies given node inside a destination node + * + * @param t3lib_tree_Node $node + * @param t3lib_tree_Node $destination + * @return void + */ + public function copyNodeInDestinationNode($node, $destination); + + /** + * Copies given node after a destination node + * + * @param t3lib_tree_Node $node + * @param t3lib_tree_Node $destination + * @return void + */ + public function copyNodeAfterDestinationNode($node, $destination); + +} +?> \ No newline at end of file diff --git a/t3lib/tree/interfaces/interface.t3lib_tree_labeleditable.php b/t3lib/tree/interfaces/interface.t3lib_tree_labeleditable.php new file mode 100644 index 0000000000000000000000000000000000000000..52f7ce8382c15204ff0fcde1b773289fdfdd7d42 --- /dev/null +++ b/t3lib/tree/interfaces/interface.t3lib_tree_labeleditable.php @@ -0,0 +1,46 @@ +<?php +/*************************************************************** + * Copyright notice + * + * (c) 2010-2011 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! + ***************************************************************/ + +/** + * Describes necessary methods if the node label should be editable + * within the tree. + * + * @author Stefan Galinski <stefan.galinski@gmail.com> + * @author Steffen Ritter <info@steffen-ritter.net> + * @package TYPO3 + * @subpackage t3lib + */ +interface t3lib_tree_LabelEditable { + /** + * Sets the new label + * + * @param string $label + * @return void + */ + public function setLabel($label); +} +?> \ No newline at end of file diff --git a/t3lib/tree/interfaces/interface.t3lib_tree_recordbasednode.php b/t3lib/tree/interfaces/interface.t3lib_tree_recordbasednode.php new file mode 100644 index 0000000000000000000000000000000000000000..d4268b78598b9b88b96d9072a888248d403328d4 --- /dev/null +++ b/t3lib/tree/interfaces/interface.t3lib_tree_recordbasednode.php @@ -0,0 +1,83 @@ +<?php +/*************************************************************** + * Copyright notice + * + * (c) 2010-2011 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! + ***************************************************************/ + +/** + * Interface that defines the nodes based on records + * + * @author Steffen Ritter <info@steffen-ritter.net> + * @package TYPO3 + * @subpackage t3lib + */ +interface t3lib_tree_RecordBasedNode { + + /** + * Returns the source field of the label + * + * @return string + */ + public function getTextSourceField(); + + /** + * set the source field of the label + * + * @param string $field + * @return void + */ + public function setTextSourceField($field); + + /** + * Sets the database record array + * + * @param array $record + * @return void + */ + public function setRecord($record); + + /** + * Returns the database record array + * + * @return array + */ + public function getRecord(); + + /** + * Returns the table of the record data + * + * @return string + */ + public function getSourceTable(); + + /** + * sets the Table of record source data + * + * @param string $table + * @return void + */ + public function setSourceTable($table); + +} +?> diff --git a/t3lib/tree/interfaces/interface.t3lib_tree_renderablenode.php b/t3lib/tree/interfaces/interface.t3lib_tree_renderablenode.php new file mode 100644 index 0000000000000000000000000000000000000000..1c7ba3e166705371d277aea8ab2969d5fc9a3004 --- /dev/null +++ b/t3lib/tree/interfaces/interface.t3lib_tree_renderablenode.php @@ -0,0 +1,50 @@ +<?php +/*************************************************************** + * Copyright notice + * + * (c) 2010-2011 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! + ***************************************************************/ + +/** + * Interface that defines the to be rendered + * + * @author Steffen Ritter <info@steffen-ritter.net> + * @package TYPO3 + * @subpackage t3lib + */ +interface t3lib_tree_RenderableNode { + /** + * returns a string representation + * + * @return string + */ + public function toString(); + + /** + * returns an array representation of an node + * + * @return array + */ + public function toArray(); +} +?> diff --git a/t3lib/tree/extdirect/class.t3lib_tree_extdirect_node.php b/t3lib/tree/navigationtree/class.t3lib_tree_navigationtree_node.php similarity index 65% rename from t3lib/tree/extdirect/class.t3lib_tree_extdirect_node.php rename to t3lib/tree/navigationtree/class.t3lib_tree_navigationtree_node.php index 625ad0028aac54243f09c9bbc9c5f66cd012d169..678aaa62493c6bd7517d3971bba5c35f183b34f1 100644 --- a/t3lib/tree/extdirect/class.t3lib_tree_extdirect_node.php +++ b/t3lib/tree/navigationtree/class.t3lib_tree_navigationtree_node.php @@ -26,68 +26,37 @@ ***************************************************************/ /** - * Node for the usage with ExtDirect and ExtJS + * Extends the ExtJS-Tree Nodes with custom features implemented for the TYPO3 Navigation Panel * - * @author Stefan Galinski <stefan.galinski@gmail.com> + * @author Steffen Ritter <info@steffen-ritter.net> * @package TYPO3 * @subpackage t3lib */ -class t3lib_tree_extdirect_Node extends t3lib_tree_Node { - /** - * Node type - * - * @var string - */ - protected $type = ''; +class t3lib_tree_NavigationTree_Node extends t3lib_tree_ExtJs_Node { - /** - * Leaf Node Indicator - * - * @var bool - */ - protected $leaf = TRUE; /** - * Indicator if the node is expanded - * - * @var bool - */ - protected $expanded = FALSE; - - /** - * Indicator if the node can be expanded + * Database record (not serialized or merged into the result array!) * - * @var bool + * @var array */ - protected $expandable = FALSE; + protected $record = array(); - /** - * Indicator if the node is draggable - * - * @var bool - */ - protected $draggable = TRUE; /** - * Indicator if the node is allowed as a drop target + * Indicator if the node can have children's * * @var bool */ - protected $isDropTarget = TRUE; + protected $allowChildren = TRUE; /** - * Label + * Node type * * @var string */ - protected $text = ''; + protected $type = ''; - /** - * Editable Label text - * - * @var string - */ - protected $editableText = ''; /** * Prefix text of the label @@ -104,60 +73,19 @@ class t3lib_tree_extdirect_Node extends t3lib_tree_Node { protected $suffix = ''; /** - * CSS Class - * - * @var string - */ - protected $cls = ''; - - /** - * Quick Tip - * - * @var string - */ - protected $qtip = ''; - - /** - * Sprite Icon HTML + * Context Info * - * @var string + * @var array */ - protected $spriteIconCode = ''; + protected $contextInfo = array(); /** - * Text source field (title, nav_title, ...) + * Editable Label text * * @var string */ - protected $t3TextSourceField = ''; - - /** - * Indicator if the copy mode is activated - * - * @var bool - */ - protected $t3InCopyMode = FALSE; - - /** - * Indicator if the cut mode is activated - * - * @var bool - */ - protected $t3InCutMode = FALSE; - - /** - * Database record (not serialized or merged into the result array!) - * - * @var array - */ - protected $record = array(); + protected $editableText = ''; - /** - * Context Info - * - * @var array - */ - protected $contextInfo = array(); /** * Indicator if the label is editable @@ -166,173 +94,92 @@ class t3lib_tree_extdirect_Node extends t3lib_tree_Node { */ protected $labelIsEditable = TRUE; - /** - * Indicator if the node can have children's - * - * @var bool - */ - protected $allowChildren = TRUE; /** - * Set's the node type - * - * @param string $type - * @return void - */ - public function setType($type) { - $this->type = $type; - } - - /** - * Returns the node type - * - * @return string - */ - public function getType() { - return $this->type; - } - - /** - * Sets the leaf node indicator + * Sets the context info * - * @param bool $isLeaf + * @param array $contextInfo * @return void */ - public function setLeaf($isLeaf) { - $this->leaf = ($isLeaf == TRUE); - } - - /** - * Returns if the node is a leaf node - * - * @return bool - */ - public function isLeafNode() { - return $this->leaf; + public function setContextInfo($contextInfo) { + $this->contextInfo = (array) $contextInfo; } /** - * Sets the expandable indicator + * Returns the context info * - * @param bool $expandable - * @return void + * @return array */ - public function setExpandable($expandable) { - $this->expandable = ($expandable == TRUE); + public function getContextInfo() { + return (array) $this->contextInfo; } - /** - * Returns the expandable indicator - * - * @return bool - */ - public function isExpandable() { - return $this->expandable; - } /** - * Sets the expanded indicator + * Sets the indicator if the node can have child nodes * - * @param bool $expanded + * @param boolean $allowChildren * @return void */ - public function setExpanded($expanded) { - $this->expanded = ($expanded == TRUE); + public function setAllowChildren($allowChildren) { + $this->allowChildren = ($allowChildren == TRUE); } /** - * Returns the expanded indicator + * Checks if the node can have child nodes * * @return bool */ - public function isExpanded() { - if ($this->isLeafNode()) { - return TRUE; - } - - return $this->expanded; - } - - /** - * Sets the draggable indicator - * - * @param bool $draggable - * @return void - */ - public function setDraggable($draggable) { - $this->draggable = ($draggable == TRUE); + public function canHaveChildren() { + return $this->allowChildren; } - /** - * Returns the draggable indicator - * - * @return bool - */ - public function isDraggable() { - return $this->draggable; - } /** - * Sets the indicator if the node can be a drop target + * Sprite Icon HTML * - * @param bool $isDropTarget - * @return void + * @var string */ - public function setIsDropTarget($isDropTarget) { - $this->isDropTarget = ($isDropTarget == TRUE); - } + protected $spriteIconCode = ''; /** - * Returns the indicator if the node is a drop target + * Text source field (title, nav_title, ...) * - * @return bool + * @var string */ - public function isDropTarget() { - return $this->isDropTarget; - } + protected $t3TextSourceField = ''; /** - * Sets the label of the node with the source field and the prefix + * Indicator if the copy mode is activated * - * @param string $text - * @param string $textSourceField - * @param string $prefix - * @param string $suffix - * @return void + * @var bool */ - public function setText($text, $textSourceField = 'title', $prefix = '', $suffix = '') { - $this->text = $text; - $this->t3TextSourceField = $textSourceField; - $this->prefix = $prefix; - $this->suffix = $suffix; - } + protected $t3InCopyMode = FALSE; /** - * Returns the label + * Indicator if the cut mode is activated * - * @return string + * @var bool */ - public function getText() { - return $this->text; - } + protected $t3InCutMode = FALSE; - /** - * Sets the editable text + /** + * Sets the sprite icon code * - * @param string $editableText + * @param string $spriteIcon * @return void */ - public function setEditableText($editableText) { - $this->editableText = $editableText; + public function setSpriteIconCode($spriteIcon) { + $this->spriteIconCode = $spriteIcon; } /** - * Returns the editable text + * Returns the sprite icon code * * @return string */ - public function getEditableText() { - return $this->editableText; + public function getSpriteIconCode() { + return $this->spriteIconCode; } /** @@ -399,63 +246,45 @@ class t3lib_tree_extdirect_Node extends t3lib_tree_Node { public function getSuffix() { return $this->suffix; } - + /** - * Sets the css class(es) + * Set's the node type * - * @param string $class + * @param string $type * @return void */ - public function setCls($class) { - $this->cls = $class; + public function setType($type) { + $this->type = $type; } /** - * Returns the css class(es) + * Returns the node type * * @return string */ - public function getCls() { - return $this->cls; + public function getType() { + return $this->type; } /** - * Sets the quick tip + * Sets the editable text * - * @param string $qtip + * @param string $editableText * @return void */ - public function setQTip($qtip) { - $this->qtip = $qtip; + public function setEditableText($editableText) { + $this->editableText = $editableText; } /** - * Returns the quick tip + * Returns the editable text * * @return string */ - public function getQTip() { - return $this->qtip; - } - - /** - * Sets the sprite icon code - * - * @param string $spriteIcon - * @return void - */ - public function setSpriteIconCode($spriteIcon) { - $this->spriteIconCode = $spriteIcon; + public function getEditableText() { + return $this->editableText; } - /** - * Returns the sprite icon code - * - * @return string - */ - public function getSpriteIconCode() { - return $this->spriteIconCode; - } /** * Sets the indicator if the label is editable @@ -477,74 +306,39 @@ class t3lib_tree_extdirect_Node extends t3lib_tree_Node { } /** - * Sets the database record array - * - * @param array $record - * @return void - */ - public function setRecord($record) { - $this->record = (array) $record; - } - - /** - * Returns the database record array - * - * @return array - */ - public function getRecord() { - return $this->record; - } - - /** - * Sets the context info - * - * @param array $contextInfo - * @return void - */ - public function setContextInfo($contextInfo) { - $this->contextInfo = (array) $contextInfo; - } - - /** - * Returns the context info - * - * @return array - */ - public function getContextInfo() { - return (array) $this->contextInfo; - } - - /** - * Sets the child nodes collection + * Sets the label of the node with the source field and the prefix * - * @param t3lib_tree_NodeCollection $childNodes + * @param string $text + * @param string $textSourceField + * @param string $prefix + * @param string $suffix * @return void */ - public function setChildNodes(t3lib_tree_NodeCollection $childNodes) { - parent::setChildNodes($childNodes); - - if ($childNodes->count()) { - $this->setLeaf(FALSE); - } + public function setText($text, $textSourceField = 'title', $prefix = '', $suffix = '') { + $this->text = $text; + $this->t3TextSourceField = $textSourceField; + $this->prefix = $prefix; + $this->suffix = $suffix; } /** - * Sets the indicator if the node can have child nodes + * Sets data of the node by a given data array * - * @param boolean $allowChildren + * @param array $data * @return void */ - public function setAllowChildren($allowChildren) { - $this->allowChildren = ($allowChildren == TRUE); - } + public function dataFromArray($data) { + parent::dataFromArray($data); - /** - * Checks if the node can have child nodes - * - * @return bool - */ - public function canHaveChildren() { - return $this->allowChildren; + $this->setText($data['label'], $data['t3TextSourceField'], $data['prefix'], $data['suffix']); + $this->setType($data['type']); + $this->setEditableText($data['editableText']); + $this->setSpriteIconCode($data['spriteIconCode']); + $this->setInCopyMode($data['t3InCopyMode']); + $this->setInCutMode($data['t3InCutMode']); + $this->setContextInfo($data['t3ContextInfo']); + $this->setLabelIsEditable($data['editable']); + $this->setAllowChildren($data['allowChildren']); } /** @@ -554,20 +348,14 @@ class t3lib_tree_extdirect_Node extends t3lib_tree_Node { * @return array */ public function toArray($addChildNodes = TRUE) { - $arrayRepresentation = array( - 'serializeClassName' => get_class($this), - 'id' => $this->getId(), + $arrayRepresentation = parent::toArray($addChildNodes); + + $arrayRepresentation2 = array( 'type' => $this->getType(), 'editableText' => $this->getEditableText(), 'text' => $this->getPrefix() . $this->getText() . $this->getSuffix(), - 'cls' => $this->getCls(), 'prefix' => $this->getPrefix(), 'suffix' => $this->getSuffix(), - 'qtip' => $this->getQTip(), - 'expanded' => $this->isExpanded(), - 'expandable' => $this->isExpandable(), - 'draggable' => $this->isDraggable(), - 'isTarget' => $this->isDropTarget(), 'spriteIconCode' => $this->getSpriteIconCode(), 't3TextSourceField' => $this->getTextSourceField(), 't3InCopyMode' => $this->isInCopyMode(), @@ -580,56 +368,51 @@ class t3lib_tree_extdirect_Node extends t3lib_tree_Node { // only set the leaf attribute if the node has children's, // otherwise you cannot add child's to real leaf nodes if (!$this->isLeafNode()) { - $arrayRepresentation['leaf'] = FALSE; + $arrayRepresentation2['leaf'] = FALSE; } + // Do not nest nodeData and children arrays + unset($arrayRepresentation['nodeData']); + unset($arrayRepresentation['children']); + $arrayRepresentation = array_merge($arrayRepresentation, $arrayRepresentation2); + // Suhosin(?) or some other strange environment thingy prevents // the direct copy of an array into an index of the same array $copy = $arrayRepresentation; $arrayRepresentation['nodeData'] = $copy; - if ($this->hasChildNodes()) { + if ($this->hasChildNodes() && $addChildNodes) { $arrayRepresentation['children'] = $this->childNodes->toArray(); } return $arrayRepresentation; } + /** - * Sets data of the node by a given data array + * Sets the database record array * - * @param array $data + * @param array $record * @return void */ - public function dataFromArray($data) { - parent::dataFromArray($data); - - $this->setType($data['type']); - $this->setText($data['label'], $data['t3TextSourceField'], $data['prefix'], $data['suffix']); - $this->setEditableText($data['editableText']); - $this->setCls($data['cls']); - $this->setQTip($data['qtip']); - $this->setExpanded($data['expanded']); - $this->setExpandable($data['expandable']); - $this->setDraggable($data['draggable']); - $this->setIsDropTarget($data['isTarget']); - $this->setSpriteIconCode($data['spriteIconCode']); - $this->setInCopyMode($data['t3InCopyMode']); - $this->setInCutMode($data['t3InCutMode']); - $this->setContextInfo($data['t3ContextInfo']); - $this->setLabelIsEditable($data['editable']); - $this->setAllowChildren($data['allowChildren']); + public function setRecord($record) { + $this->record = (array) $record; + } - // only set the leaf attribute if it's applied - // otherwise you cannot insert nodes into this one - if (isset($data['leaf'])) { - $this->setLeaf(FALSE); - } + /** + * Returns the database record array + * + * @return array + */ + public function getRecord() { + return $this->record; } + + } -if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/tree/extdirect/class.t3lib_tree_extdirect_node.php'])) { - include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/tree/extdirect/class.t3lib_tree_extdirect_node.php']); +if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/tree/navigationtree/class.t3lib_tree_navigationtree_node.php'])) { + include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/tree/navigationtree/class.t3lib_tree_navigationtree_node.php']); } ?> \ No newline at end of file diff --git a/t3lib/tree/pagetree/class.t3lib_tree_pagetree_commands.php b/t3lib/tree/pagetree/class.t3lib_tree_pagetree_commands.php index 532761ede0fca3788b6455f6c8db3b23749af1f8..782c7b5609c51db8a8bf417f75213f2026b98774 100644 --- a/t3lib/tree/pagetree/class.t3lib_tree_pagetree_commands.php +++ b/t3lib/tree/pagetree/class.t3lib_tree_pagetree_commands.php @@ -36,7 +36,7 @@ final class t3lib_tree_pagetree_Commands { /** * Visibly the page * - * @param t3lib_tree_pagetree_Node $nodeData + * @param t3lib_tree_pagetree_Node $node * @return void */ public static function visiblyNode(t3lib_tree_pagetree_Node $node) { @@ -47,7 +47,7 @@ final class t3lib_tree_pagetree_Commands { /** * Hide the page * - * @param t3lib_tree_pagetree_Node $nodeData + * @param t3lib_tree_pagetree_Node $node * @return void */ public static function disableNode(t3lib_tree_pagetree_Node $node) { @@ -58,7 +58,7 @@ final class t3lib_tree_pagetree_Commands { /** * Delete the page * - * @param t3lib_tree_pagetree_Node $nodeData + * @param t3lib_tree_pagetree_Node $node * @return void */ public static function deleteNode(t3lib_tree_pagetree_Node $node) { @@ -69,7 +69,7 @@ final class t3lib_tree_pagetree_Commands { /** * Restore the page * - * @param t3lib_tree_pagetree_Node $nodeData + * @param t3lib_tree_pagetree_Node $node * @param int $targetId * @return void */ @@ -85,7 +85,7 @@ final class t3lib_tree_pagetree_Commands { /** * Updates the node label * - * @param t3lib_tree_pagetree_Node $nodeData + * @param t3lib_tree_pagetree_Node $node * @param string $updatedLabel * @return void */ @@ -276,6 +276,7 @@ final class t3lib_tree_pagetree_Commands { * Creates a node with the given record information's * * @param array $record + * @param int $mountPoint * @return t3lib_tree_pagetree_Node */ public static function getNewNode($record, $mountPoint = 0) { @@ -335,7 +336,7 @@ final class t3lib_tree_pagetree_Commands { if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['GLOBAL']['recStatInfoHooks'])) { $_params = array('pages', $record['uid']); foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['GLOBAL']['recStatInfoHooks'] as $_funcRef) { - $stat .= t3lib_div::callUserFunction($_funcRef, $_params, $this); + $stat .= t3lib_div::callUserFunction($_funcRef, $_params, NULL); } } @@ -358,11 +359,11 @@ final class t3lib_tree_pagetree_Commands { $subNode->setSpriteIconCode($spriteIconCode); if (!$subNode->canCreateNewPages() || intval($record['t3ver_state']) === 2) { - $subNode->setIsDropTarget(FALSE); + $subNode->setAllowDrop(FALSE); } if (!$subNode->canBeEdited() || !$subNode->canBeRemoved() || intval($record['t3ver_state']) === 2) { - $subNode->setDraggable(FALSE); + $subNode->setAllowDrag(FALSE); } return $subNode; diff --git a/t3lib/tree/pagetree/class.t3lib_tree_pagetree_dataprovider.php b/t3lib/tree/pagetree/class.t3lib_tree_pagetree_dataprovider.php index 4cd6f238992702ad32f5b53cf9b7d04c2394728c..78b010ddd7be109b1b721badd48da3e1663c7167 100644 --- a/t3lib/tree/pagetree/class.t3lib_tree_pagetree_dataprovider.php +++ b/t3lib/tree/pagetree/class.t3lib_tree_pagetree_dataprovider.php @@ -123,7 +123,7 @@ class t3lib_tree_pagetree_DataProvider extends t3lib_tree_AbstractDataProvider { if (!is_array($subpages) || !count($subpages)) { return $nodeCollection; } - + $index = -1; foreach ($subpages as $subpage) { if (in_array($subpage['uid'], $this->hiddenRecords)) { continue; @@ -135,14 +135,20 @@ class t3lib_tree_pagetree_DataProvider extends t3lib_tree_AbstractDataProvider { } $subNode = t3lib_tree_pagetree_Commands::getNewNode($subpage, $mountPoint); + $subNode->setParentNode($node); + $subNode->setDepth($node->getDepth() + 1); + $subNode->setIndex(++$index); + $subNode->setIsFirst($index === 0); + $subNode->setIsLast($index === (count($subpages)-1)); if ($this->nodeCounter < $this->nodeLimit) { $childNodes = $this->getNodes($subNode, $mountPoint, $level + 1); $subNode->setChildNodes($childNodes); + $subNode->setLeaf(!$subNode->hasChildNodes()); $this->nodeCounter += $childNodes->count(); } else { $subNode->setLeaf(!$this->hasNodeSubPages($subNode->getId())); } - + $subNode->setExpandable(!$subNode->isLeafNode()); $nodeCollection->append($subNode); } @@ -160,7 +166,7 @@ class t3lib_tree_pagetree_DataProvider extends t3lib_tree_AbstractDataProvider { * @param t3lib_tree_Node $node * @param string $searchFilter * @param int $mountPoint - * @return void + * @return t3lib_tree_pagetree_NodeCollection */ public function getFilteredNodes(t3lib_tree_Node $node, $searchFilter, $mountPoint = 0) { /** @var $nodeCollection t3lib_tree_pagetree_NodeCollection */ @@ -205,13 +211,10 @@ class t3lib_tree_pagetree_DataProvider extends t3lib_tree_AbstractDataProvider { if ($reference && $reference->offsetExists($ident)) { /** @var $refNode t3lib_tree_pagetree_Node */ $refNode = $reference->offsetGet($ident); - $refNode->setExpanded(TRUE); - $refNode->setLeaf(FALSE); - - $reference = $refNode->getChildNodes(); - if ($reference == NULL) { - $reference = t3lib_div::makeInstance('t3lib_tree_pagetree_NodeCollection'); - $refNode->setChildNodes($reference); + if ($refNode->hasChildNodes()) { + $refNode->setExpanded(TRUE); + $refNode->setLeaf(FALSE); + $reference = $refNode->getChildNodes(); } } else { $refNode = t3lib_tree_pagetree_Commands::getNewNode($rootlineElement, $mountPoint); @@ -287,6 +290,7 @@ class t3lib_tree_pagetree_DataProvider extends t3lib_tree_AbstractDataProvider { } $showRootlineAboveMounts = $GLOBALS['BE_USER']->getTSConfigVal('options.pageTree.showPathAboveMounts'); + $index = -1; foreach ($mountPoints as $mountPoint) { if ($mountPoint === 0) { $sitename = 'TYPO3'; @@ -322,10 +326,13 @@ class t3lib_tree_pagetree_DataProvider extends t3lib_tree_AbstractDataProvider { $subNode->setExpanded(TRUE); $subNode->setCls('typo3-pagetree-node-notExpandable'); } - + $subNode->setDepth(1); + $subNode->setIndex(++$index); + $subNode->setIsFirst($index === 0); + $subNode->setIsLast($index === (count($mountPoints)-1)); $subNode->setIsMountPoint(TRUE); - $subNode->setDraggable(FALSE); - $subNode->setIsDropTarget(FALSE); + $subNode->setAllowDrag(FALSE); + $subNode->setAllowDrop(FALSE); if ($searchFilter === '') { $childNodes = $this->getNodes($subNode, $mountPoint); @@ -363,21 +370,22 @@ class t3lib_tree_pagetree_DataProvider extends t3lib_tree_AbstractDataProvider { } if ($searchFilter !== '') { + $searchWhere = ''; if (is_numeric($searchFilter) && $searchFilter > 0) { - $seachWhere .= 'uid = ' . intval($searchFilter) . ' OR '; + $searchWhere .= 'uid = ' . intval($searchFilter) . ' OR '; } $searchFilter = $GLOBALS['TYPO3_DB']->fullQuoteStr('%' . $searchFilter . '%', 'pages'); $useNavTitle = $GLOBALS['BE_USER']->getTSConfigVal('options.pageTree.showNavTitle'); if ($useNavTitle) { - $seachWhere .= '(nav_title LIKE ' . $searchFilter . + $searchWhere .= '(nav_title LIKE ' . $searchFilter . ' OR (nav_title = "" && title LIKE ' . $searchFilter . '))'; } else { - $seachWhere .= 'title LIKE ' . $searchFilter; + $searchWhere .= 'title LIKE ' . $searchFilter; } - $where .= ' AND (' . $seachWhere . ')'; + $where .= ' AND (' . $searchWhere . ')'; } return $where; diff --git a/t3lib/tree/pagetree/class.t3lib_tree_pagetree_indicator.php b/t3lib/tree/pagetree/class.t3lib_tree_pagetree_indicator.php index a97f7ac826996a4b8ece8f81fbc4072c1b889e6a..619273a2b9185ef3e2473cfebceb54a245400db4 100644 --- a/t3lib/tree/pagetree/class.t3lib_tree_pagetree_indicator.php +++ b/t3lib/tree/pagetree/class.t3lib_tree_pagetree_indicator.php @@ -53,7 +53,7 @@ class t3lib_tree_pagetree_Indicator { */ protected function getIndicatorProviders() { $providers = $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['pagetree']['t3lib_tree_pagetree']['indicator']['providers']; - if (!is_array($providers)) { + if (!is_array($providers) || count($this->indicatorProviders) > 0) { return; } @@ -69,13 +69,13 @@ class t3lib_tree_pagetree_Indicator { /** * Runs through all indicator providers and returns all indicators collected. * - * @return array An array of + * @return array An array of indicator objects */ public function getAllIndicators() { $indicators = array(); foreach ($this->indicatorProviders as $indicatorProvider) { $indicator = $indicatorProvider->getIndicator(); - if($indicator) { + if ($indicator) { $indicators[] = $indicator; } } diff --git a/t3lib/tree/pagetree/class.t3lib_tree_pagetree_node.php b/t3lib/tree/pagetree/class.t3lib_tree_pagetree_node.php index 91af17c4d33001ee575bf57ad57be14f6554b160..4c5145933a583b76d453a47d2018ebe170a7eb4c 100644 --- a/t3lib/tree/pagetree/class.t3lib_tree_pagetree_node.php +++ b/t3lib/tree/pagetree/class.t3lib_tree_pagetree_node.php @@ -32,7 +32,7 @@ * @package TYPO3 * @subpackage t3lib */ -class t3lib_tree_pagetree_Node extends t3lib_tree_extdirect_Node { +class t3lib_tree_pagetree_Node extends t3lib_tree_NavigationTree_Node implements t3lib_tree_RecordBasedNode { /** * Cached access rights to save some performance * @@ -297,6 +297,19 @@ class t3lib_tree_pagetree_Node extends t3lib_tree_extdirect_Node { public function canBeTemporaryMountPoint() { return TRUE; } + + /** + * Returns a special id for a page tree node + * + * @return string + */ + public function getPageTreeNodeId() { + if ($this->getId() === 'root') { + return 'root'; + } else { + return 'p' . dechex($this->getId()) . ($this->getMountPoint() ? '-' . dechex($this->getMountPoint()) : ''); + } + } /** * Returns the node in an array representation that can be used for serialization @@ -307,17 +320,34 @@ class t3lib_tree_pagetree_Node extends t3lib_tree_extdirect_Node { public function toArray($addChildNodes = TRUE) { $arrayRepresentation = parent::toArray(); - $arrayRepresentation['id'] = 'p' . dechex($this->getId()) . ($this->getMountPoint() ? '-' . dechex($this->getMountPoint()) : ''); - $arrayRepresentation['realId'] = $this->getId(); - $arrayRepresentation['nodeData']['id'] = $this->getId(); - - $arrayRepresentation['readableRootline'] = $this->getReadableRootline(); - $arrayRepresentation['nodeData']['readableRootline'] = $this->getReadableRootline(); - - $arrayRepresentation['nodeData']['mountPoint'] = $this->getMountPoint(); - $arrayRepresentation['nodeData']['workspaceId'] = $this->getWorkspaceId(); - $arrayRepresentation['nodeData']['isMountPoint'] = $this->isMountPoint(); - $arrayRepresentation['nodeData']['serializeClassName'] = get_class($this); + $arrayRepresentation2['id'] = $this->getPageTreeNodeId(); + $arrayRepresentation2['realId'] = $this->getId(); + $arrayRepresentation2['serializeClassName'] = get_class($this); + $arrayRepresentation2['parentId'] = (!$this->getRoot() && $this->getParentNode()) ? $this->getParentNode()->getPageTreeNodeId() : 'root'; + $arrayRepresentation2['readableRootline'] = $this->getReadableRootline(); + $arrayRepresentation2['mountPoint'] = $this->getMountPoint(); + $arrayRepresentation2['workspaceId'] = $this->getWorkspaceId(); + $arrayRepresentation2['isMountPoint'] = $this->isMountPoint(); + + // only set the leaf attribute if the node has children's, + // otherwise you cannot add child's to real leaf nodes + if (!$this->isLeafNode()) { + $arrayRepresentation2['leaf'] = FALSE; + } + // Do not nest nodeData and children arrays + unset($arrayRepresentation['nodeData']); + unset($arrayRepresentation['children']); + $arrayRepresentation = array_merge($arrayRepresentation, $arrayRepresentation2); + + // Suhosin(?) or some other strange environment thingy prevents + // the direct copy of an array into an index of the same array + $copy = $arrayRepresentation; + $arrayRepresentation['nodeData'] = $copy; + $arrayRepresentation['nodeData']['id'] = $arrayRepresentation['realId']; + + if ($this->hasChildNodes() && $addChildNodes) { + $arrayRepresentation['children'] = $this->childNodes->toArray(); + } return $arrayRepresentation; } @@ -335,6 +365,35 @@ class t3lib_tree_pagetree_Node extends t3lib_tree_extdirect_Node { $this->setReadableRootline($data['readableRootline']); $this->setIsMountPoint($data['isMountPoint']); } + + /** + * set the source field of the label + * + * @param string $field + * @return void + */ + public function setTextSourceField($field) { + $this->t3TextSourceField = $field; + } + + /** + * Returns the table of the record data + * + * @return string + */ + public function getSourceTable() { + return 'pages'; + } + + /** + * sets the Table of record source data + * + * @param string $table + * @return void + */ + public function setSourceTable($table) { + // not needed, pagetree always is 'pages' + } } if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/tree/pagetree/class.t3lib_tree_pagetree_node.php'])) { diff --git a/t3lib/tree/pagetree/extdirect/class.t3lib_tree_pagetree_extdirect_commands.php b/t3lib/tree/pagetree/extdirect/class.t3lib_tree_pagetree_extdirect_commands.php index a3a33dac362ca8b8d76c4abedbb55fe3840f83cc..12ccaeb8ed014d648c3b63670e664ea81d20f6f4 100644 --- a/t3lib/tree/pagetree/extdirect/class.t3lib_tree_pagetree_extdirect_commands.php +++ b/t3lib/tree/pagetree/extdirect/class.t3lib_tree_pagetree_extdirect_commands.php @@ -225,7 +225,7 @@ class t3lib_tree_pagetree_extdirect_Commands { * * @param stdClass $nodeData * @param int $destination - * @return void + * @return array */ public function moveNodeAfterDestination($nodeData, $destination) { /** @var $node t3lib_tree_pagetree_Node */ diff --git a/t3lib/tree/pagetree/extdirect/class.t3lib_tree_pagetree_extdirect_tree.php b/t3lib/tree/pagetree/extdirect/class.t3lib_tree_pagetree_extdirect_tree.php index e8df3f8f2ab2711fd799603347925d0aa5cb6c9f..466195f9c6763f6794e0a5555c744b2fda98729f 100644 --- a/t3lib/tree/pagetree/extdirect/class.t3lib_tree_pagetree_extdirect_tree.php +++ b/t3lib/tree/pagetree/extdirect/class.t3lib_tree_pagetree_extdirect_tree.php @@ -32,7 +32,7 @@ * @package TYPO3 * @subpackage t3lib */ -class t3lib_tree_pagetree_extdirect_Tree extends t3lib_tree_ExtDirect_AbstractExtJsTree { +class t3lib_tree_pagetree_extdirect_Tree extends t3lib_tree_ExtJs_AbstractStatefulExtJsTree { /** * Data Provider * @@ -180,7 +180,7 @@ class t3lib_tree_pagetree_extdirect_Tree extends t3lib_tree_ExtDirect_AbstractEx /** * Returns the language labels, sprites and configuration options for the pagetree * - * @return void + * @return array */ public function loadResources() { $file = 'LLL:EXT:lang/locallang_core.xml:'; diff --git a/typo3/sysext/t3skin/stylesheets/structure/element_pagetree.css b/typo3/sysext/t3skin/stylesheets/structure/element_pagetree.css index 8ae4e364b21ce822b27a23892984d893099f3695..aed04b76ab3eca17b7f9cf0be8a42968c2c8e6fb 100644 --- a/typo3/sysext/t3skin/stylesheets/structure/element_pagetree.css +++ b/typo3/sysext/t3skin/stylesheets/structure/element_pagetree.css @@ -6,50 +6,32 @@ Pagetree #typo3-pagetree, #typo3-pagetree .x-panel-bwrap, #typo3-pagetree .x-panel-body { + border: none; height: 100%; } -#typo3-pagetree .x-panel-tbar { - padding: 0; - margin: 0; -} - -.x-tree-node .x-tree-node-el { - margin-right: 0; +.typo3-pagetree .x-grid-table { + padding-left: 5px; } .x-tree-node-readableRootline { padding: 10px 0 3px 10px; } -.x-tree-lines .typo3-pagetree-node-notExpandable .x-tree-ec-icon { - visibility: hidden; -} - -.x-tree-lines .typo3-pagetree-node-notExpandable ul .x-tree-ec-icon { - visibility: visible; -} - -#typo3-pagetree span.t3-icon { +.typo3-pagetree span.t3-icon { margin-bottom: 2px; } -#typo3-pagetree .x-toolbar, -.typo3-pagetree-topPanel-item .x-toolbar { - padding-bottom: 0; -} - -#typo3-pagetree ul.x-tree-root-ct { - padding-left: 5px; - padding-top: 15px; -} - -.x-tree-node a .typo3-pagetree-status, +.typo3-pagetree .x-grid-row .x-grid-cell a .typo3-pagetree-status, .x-dd-drag-ghost a .typo3-pagetree-status { padding: 0; margin: 0 3px 0 0; } +.typo3-pagetree .x-form-field { + height: 19px; +} + /** * * section drag and drop @@ -86,62 +68,62 @@ Pagetree * @section Top Panel * */ -#typo3-pagetree-topPanel .x-toolbar-left { - height: 20px; +#typo3-pagetree .x-docked-top { + padding: 0; } -.typo3-pagetree-topPanel-button { - margin: 0 5px 0 0; - padding: 1px 2px; - height: 18px; +.typo3-pagetree-topPanel { + height: 49px; } -.typo3-pagetree-topPanel-button button { - height: 16px; - width: 16px; +#typo3-pagetree-topPanel .x-docked-top .x-box-inner { + height: 22px; + margin: 0; } -.typo3-pagetree-topPanel-item { - padding: 5px 3px 0 3px; - height: 22px; +#typo3-pagetree .typo3-pagetree-topPanel-button { + height: 21px; + margin-right: 1px; + margin-top: 0px !important; + padding: 1px 3px 0 3px; } -#typo3-pagetree-topPanel-filterWrap { - padding-top: 3px; - height: 24px; +.typo3-pagetree-topPanel-item { + padding: 2px 0 0 0; + height: 22px; } -#typo3-pagetree-topPanel-filter { - height: 16px; - width: 98% !important; - padding: 1px 0 1px 2px; +#typo3-pagetree-topPanel-item-newNode { + padding: 0; } -#typo3-pagetree-topPanel-filterWrap .t3-icon-input-clear { - right: 2%; +.typo3-pagetree-topPanel-item .x-form-item { + border: none !important; + margin: 3px; + width: 100%; } -#typo3-pagetree .typo3-pagetree-topPanel-button { - margin-right: 1px; - margin-top: -2px; - padding: 2px 3px; +.typo3-pagetree-topPanel-item .x-form-field { + height: 18px; + line-height: 16px; } -#typo3-pagetree-topPanel-defaultPanel { - padding-left: 6px; +.typo3-pagetree-topPanel-filter .t3-icon-input-clear { } -#typo3-pagetree-topPanel-filterWrap .x-form-field-trigger-wrap { - width: 100% !important; - margin: 0 20px 0 0; +.typo3-pagetree-topPanel-item .x-form-trigger-wrap { + margin: 0; } .typo3-pagetree-topPanel-item .x-form-trigger { - margin: 4px 0 0; + background-image: none; + border-bottom: none !important; display: none; + margin-right: 0; + margin-top: 1px; } -.typo3-pagetree-topPanel-item .x-form-field-trigger-wrap:hover .x-form-trigger { +.typo3-pagetree-topPanel-item .x-form-trigger-wrap-focus:hover .x-form-trigger { display: block; } @@ -154,25 +136,31 @@ Pagetree * @section Indicator Bar * */ -.typo3-pagetree-indicatorBar-item p { - padding: 5px 10px; +#typo3-pagetree-indicatorBar { + width: 100%; +} + +#typo3-pagetree-indicatorBar-filter, +#typo3-pagetree-indicatorBar-temporaryMountPoint { + padding: 10px 20px; } #typo3-pagetree-indicatorBar-filter p, #typo3-pagetree-indicatorBar-temporaryMountPoint p { - padding: 10px 35px; + padding-left: 5px; + width: 100%; } .typo3-pagetree-indicatorBar-item .typo3-pagetree-indicatorBar-item-leftIcon { - left: 10px; - top: 9px; - position: absolute; + position: relative; + left: -10px; + top: 0px; } .typo3-pagetree-indicatorBar-item .typo3-pagetree-indicatorBar-item-rightIcon { - right: 10px; - top: 5px; - position: absolute; + position: relative; + right: -10px; + vertical-align: top; } #typo3-pagetree-indicatorBar-indicatorTitle span { diff --git a/typo3/sysext/t3skin/stylesheets/visual/element_pagetree.css b/typo3/sysext/t3skin/stylesheets/visual/element_pagetree.css index 67dd10fc473fcaff1b3a890a46bde53e7a8828ab..2337e495ae04da2a9b9fc2dc3391f5834dc192d1 100644 --- a/typo3/sysext/t3skin/stylesheets/visual/element_pagetree.css +++ b/typo3/sysext/t3skin/stylesheets/visual/element_pagetree.css @@ -3,28 +3,29 @@ Pagetree - - - - - - - - - - - - - - - - - - - - - */ #typo3-pagetree-treeContainer, -#typo3-pagetree-topPanelItems { +.typo3-pageTree-topPanelItems { background-color: #ebebeb; } -#typo3-pagetree .x-tree .x-panel-body { +.typo3-pagetree .x-panel-body { background: none; } -#typo3-pagetree .x-tree-node .x-tree-node-el { +.typo3-pagetree .x-grid-row .x-grid-cell { border-top: 1px solid transparent; border-bottom: 1px solid transparent; border-left: 1px solid transparent; + font-size: 12px; } -#typo3-pagetree .x-tree-node .x-tree-node-over, -#typo3-pagetree .x-tree-node .x-tree-selected { +.typo3-pagetree .x-grid-row.x-grid-row-over .x-grid-cell, +.typo3-pagetree .x-grid-row.x-grid-row-selected .x-grid-cell { border-bottom: 1px solid #d7d7d7; border-top: 1px solid #d7d7d7; border-left: 1px solid #d7d7d7; } -#typo3-pagetree .x-tree-node .x-tree-node-over { +.typo3-pagetree .x-grid-row.x-grid-row-over .x-grid-cell { background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAABCAYAAAAb4BS0AAAAGElEQVR42gENAPL/AMjIyEzIyMizyMjI/zhvCQelaHPPAAAAAElFTkSuQmCC"); /* star-hack targets IE7 */ *background-image: url("../../images/shadows/navigation-container.png"); @@ -39,20 +40,34 @@ Pagetree border-bottom-right-radius: 3px; } -#typo3-pagetree .x-tree-node .x-tree-selected { +.typo3-pagetree .x-grid-row-selected .x-grid-cell { background-color: #f8f8f8; } -#typo3-pagetree .x-tree-node .x-tree-selected.x-tree-node-over { +.typo3-pagetree .x-grid-row-selected.x-grid-row-over .x-grid-cell { background-image: none; -webkit-border-radius: 0; -moz-border-radius: 0; border-radius: 0; } -#typo3-pagetree .x-panel-tbar { - background-color: #585858; - border: none; +.typo3-pagetree .x-tree-elbow-plus, +.typo3-pagetree .x-tree-elbow-end-plus { + background-image:url('../../images/icons/apps/pagetree-collapse.png'); +} + +.typo3-pagetree .x-tree-elbow-minus, +.typo3-pagetree .x-tree-elbow-end-minus, +.typo3-pagetree .x-grid-tree-node-expanded .x-tree-elbow-plus, +.typo3-pagetree .x-grid-tree-node-expanded .x-tree-elbow-end-plus { + background-image:url('../../images/icons/apps/pagetree-expand.png'); +} + +.typo3-pagetree .x-form-field { + color: black; + font-family: Verdana,Arial,Helvetica,sans-serif; + font-size: 11px; + line-height: 14px; } /** @@ -62,6 +77,8 @@ Pagetree */ .typo3-pagetree-tree-copy { color: #666; + font-size: 11px; + text-align: center; } .x-dd-drag-ghost { @@ -149,7 +166,13 @@ Pagetree * @section Top Panel * */ -#typo3-pagetree .x-toolbar { +#typo3-pagetree-topPanel .x-docked-top, +#typo3-pagetree-topPanel .x-docked-top .x-box-inner { + background-color: #585858; + border: none; +} + +#typo3-pagetree .x-panel-body .x-toolbar { background: none; border: none; } @@ -159,6 +182,10 @@ Pagetree border: none; } +#typo3-pagetree-topPanel-body { + background-color: #dadada; +} + #typo3-pagetree-topPanel .x-btn-click, #typo3-pagetree-topPanel .x-btn-over { background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAWCAIAAACKUbHAAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAD9JREFUCB19wdERAUAARDEv23+FmsGZG38Sz0sfKoXEppDKyldyxBzzM1eObWYMM5Zr/ipEWRm9UXnr0OVxvQAaNAkk1SzJpgAAAABJRU5ErkJggg=="); @@ -193,19 +220,6 @@ Pagetree #typo3-pagetree .typo3-pagetree-topPanel-item { background-color: #dadada; - line-height: normal; -} - -#typo3-pagetree-topPanel-filter { - border: 1px solid #aeaeae; - -moz-box-shadow: inset 0 1px 1px #aeaeae; - -ms-box-shadow: inset 0 1px 1px #aeaeae; - -webkit-box-shadow: inset 0 1px 1px #aeaeae; - box-shadow: inset 0 2px 1px #aeaeae; -} - -.typo3-pagetree-topPanel-filter-defaultText { - color: gray; } #typo3-pagetree .typo3-pagetree-topPanel-button { @@ -219,7 +233,10 @@ Pagetree #typo3-pagetree-topPanel-defaultPanel { color: #a2aab8; - line-height: 18px; +} + +.typo3-pagetree-topPanel-filter-defaultText { + color: gray; } #typo3-pagetree-topPanel-item-newNode .x-btn-over { @@ -271,7 +288,8 @@ Pagetree * */ -#typo3-pagetree-indicatorBar-temporaryMountPoint p { +#typo3-pagetree-indicatorBar-temporaryMountPoint p, +#typo3-pagetree-indicatorBar-filter p { line-height: 13px; } @@ -296,8 +314,7 @@ Pagetree * @section Deletion Drop Zone * */ - -#typo3-pagetree-deletionDropZone { +#typo3-pagetree-deletionDropZone .x-panel-body { color: #FFF; background-color: #585858; -moz-box-shadow: inset 0 2px 5px #414141;