Added feature #16408: Support for Custom Navigation Components (Thanks to Stefan...
authorSteffen Kamper <info@sk-typo3.de>
Tue, 16 Nov 2010 12:06:22 +0000 (12:06 +0000)
committerSteffen Kamper <info@sk-typo3.de>
Tue, 16 Nov 2010 12:06:22 +0000 (12:06 +0000)
git-svn-id: https://svn.typo3.org/TYPO3v4/Core/trunk@9395 709f56b5-9817-0410-a4d7-c38de5d9e867

ChangeLog
t3lib/class.t3lib_befunc.php
t3lib/class.t3lib_extmgm.php
t3lib/class.t3lib_loadmodules.php
typo3/backend.php
typo3/classes/class.modulemenu.php
typo3/js/backend.js
typo3/js/extjs/viewport.js
typo3/js/extjs/viewportConfiguration.js
typo3/js/modulemenu.js

index 0b803fe..97bb6a0 100755 (executable)
--- a/ChangeLog
+++ b/ChangeLog
@@ -4,6 +4,7 @@
 
 2010-11-16  Steffen Kamper  <steffen@typo3.org>
 
+       * Added feature #16408: Support for Custom Navigation Components (Thanks to Stefan Galinski)
        * Added feature #16396: Implement a Grid View + wizard to enable the backend layout to be adapted to the frontend look and feel (Thanks to Joey Hasenau, Martin Ficzel and Thomas Hempel)
 
 2010-11-15  Steffen Kamper  <steffen@typo3.org>
index a0780d2..32cebab 100644 (file)
@@ -3010,8 +3010,8 @@ final class t3lib_BEfunc {
                                $signals[] = $params['JScode'];
                        } else if ($set == 'updatePageTree' || $set == 'updateFolderTree') {
                                $signals[] = '
-                                       if (top && top.TYPO3.Backend.NavigationContainer) {
-                                               top.TYPO3.Backend.NavigationContainer.refresh();
+                                       if (top && top.TYPO3.Backend.NavigationIframe) {
+                                               top.TYPO3.Backend.NavigationIframe.refresh();
                                        }';
                        }
                }
index 53f40e6..b945a6b 100644 (file)
@@ -797,6 +797,21 @@ final class t3lib_extMgm {
                }
        }
 
+       /**
+        * Registers a navigation component
+        *
+        * @param string $module
+        * @param string $componentId
+        * @param array $extDirectNamespaces
+        * @return void
+        */
+       public static function addNavigationComponent($module, $componentId, $extDirectNamespaces = array()) {
+               $GLOBALS['TBE_MODULES']['_navigationComponents'][$module] = array(
+                       'componentId' => $componentId,
+                       'extKey' => $GLOBALS['_EXTKEY'],
+                       'extDirectNamespaces' => $extDirectNamespaces
+               );
+       }
 
 
 
index c3888f7..820330d 100644 (file)
@@ -91,6 +91,12 @@ class t3lib_loadModules {
        var $BE_USER;
        var $observeWorkspaces = FALSE;         // If set true, workspace "permissions" will be observed so non-allowed modules will not be included in the array of modules.
 
+       /**
+        * Contains the registered navigation components
+        *
+        * @var array
+        */
+       protected $navigationComponents = array();
 
        /**
         * Init.
@@ -138,6 +144,9 @@ class t3lib_loadModules {
                        // unset the array for calling backend modules based on external backend module dispatchers in typo3/mod.php
                unset($modulesArray['_configuration']);
 
+               $this->navigationComponents = $modulesArray['_navigationComponents'];
+               unset($modulesArray['_navigationComponents']);
+
                $theMods = $this->parseModulesArray($modulesArray);
 
                        /*
@@ -327,6 +336,10 @@ class t3lib_loadModules {
                                if ($MCONF['navFrameScriptParam']) {
                                        $modconf['navFrameScriptParam'] = $MCONF['navFrameScriptParam'];
                                }
+
+                               if (is_array($this->navigationComponents[$name])) {
+                                       $modconf['navigationComponentId'] = $this->navigationComponents[$name]['componentId'];
+                               }
                        } else return false;
                } else $modconf = 'notFound';
                return $modconf;
index f480215..ced28e9 100644 (file)
@@ -256,6 +256,7 @@ class TYPO3backend {
                $this->generateJavascript();
                $this->pageRenderer->addJsInlineCode('BackendInlineJavascript', $this->js);
 
+               $this->loadResourcesForRegisteredNavigationComponents();
 
                        // set document title:
                $title = ($GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename']
@@ -277,6 +278,46 @@ class TYPO3backend {
        }
 
        /**
+        * Loads the css and javascript files of all registered navigation widgets
+        * 
+        * @return void
+        */
+       protected function loadResourcesForRegisteredNavigationComponents() {
+               $loadedComponents = array();
+               foreach ($GLOBALS['TBE_MODULES']['_navigationComponents'] as $module => $info) {
+                       if (in_array($info['componentId'], $loadedComponents)) {
+                               continue;
+                       }
+                       $loadedComponents[] = $info['componentId'];
+
+                       $component = strtolower(substr($info['componentId'], strrpos($info['componentId'], '-') + 1));
+                       $componentDirectory = 'components/' . $component . '/';
+                       $absoluteComponentPath = t3lib_extMgm::extPath($info['extKey']) . $componentDirectory;
+                       $relativeComponentPath = t3lib_extMgm::extRelPath($info['extKey']) . $componentDirectory;
+
+                       $cssFiles = t3lib_div::getFilesInDir($absoluteComponentPath . 'css/');
+                       foreach ($cssFiles as $cssFile) {
+                               $this->pageRenderer->addCssFile($relativeComponentPath . 'css/' . $cssFile);
+                       }
+
+                       $jsFiles = t3lib_div::getFilesInDir($absoluteComponentPath . 'javascript/');
+                       foreach ($jsFiles as $jsFile) {
+                               $this->pageRenderer->addJsFile($relativeComponentPath . 'javascript/' . $jsFile);
+                       }
+
+                       if (is_array($info['extDirectNamespaces']) && count($info['extDirectNamespaces'])) {
+                               foreach ($info['extDirectNamespaces'] as $namespace) {
+                                       $this->pageRenderer->addJsFile(
+                                               'ajax.php?ajaxID=ExtDirect::getAPI&namespace=' . $namespace,
+                                               NULL,
+                                               FALSE
+                                       );
+                               }
+                       }
+               }
+       }
+
+       /**
         * renders the items in the top toolbar
         *
         * @return      string  top toolbar elements as HTML
index e673d44..2debacb 100644 (file)
@@ -136,6 +136,7 @@ class ModuleMenu {
                                                        'index' => $index++,
                                                        'navigationFrameScript' => $subData['navFrameScript'],
                                                        'navigationFrameScriptParam' => $subData['navFrameScriptParam'],
+                                                       'navigationComponentId' => $subData['navigationComponentId'],
                                                );
                                        }
                                }
@@ -219,6 +220,7 @@ class ModuleMenu {
                                        'description' => $GLOBALS['LANG']->moduleLabels['labels'][$moduleKey . 'label'],
                                        'navigationFrameScript' => NULL,
                                        'navigationFrameScriptParam' => NULL,
+                                       'navigationComponentId' => NULL,
                                );
                        } else {
                                foreach($moduleData['sub'] as $submoduleName => $submoduleData) {
@@ -239,7 +241,8 @@ class ModuleMenu {
                                                'originalLink' => $originalLink,
                                                'description'  => $submoduleDescription,
                                                'navigationFrameScript' => $submoduleData['navFrameScript'],
-                                               'navigationFrameScriptParam' => $submoduleData['navFrameScriptParam']
+                                               'navigationFrameScriptParam' => $submoduleData['navFrameScriptParam'],
+                                               'navigationComponentId' => $submoduleData['navigationComponentId'],
                                        );
 
                                        if($moduleData['navFrameScript']) {
index 2ee7bb6..8c391c1 100644 (file)
@@ -37,8 +37,8 @@ function jump(url, modName, mainModName) {
                // clear information about which entry in nav. tree that might have been highlighted.
        top.fsMod.navFrameHighlightedID = [];
 
-       if (top.TYPO3.Backend.NavigationContainer.isVisible()) {
-               top.TYPO3.Backend.NavigationContainer.refresh();
+       if (top.TYPO3.Backend.NavigationIframe.isVisible()) {
+               top.TYPO3.Backend.NavigationIframe.refresh();
        }
 
        top.nextLoadModuleUrl = url;
index 71430a8..3c226f3 100644 (file)
@@ -70,6 +70,13 @@ TYPO3.Viewport = Ext.extend(Ext.Viewport, {
        NavigationContainer: null,
 
        /**
+        * The iframe navigation component
+        *
+        * @var TYPO3.iframePanel
+        */
+       NavigationIframe: null,
+
+       /**
         * The module menu area
         *
         * @var Ext.Panel
@@ -100,6 +107,7 @@ TYPO3.Viewport = Ext.extend(Ext.Viewport, {
 
                this.ContentContainer = Ext.getCmp('typo3-contentContainer');
                this.NavigationContainer = Ext.getCmp('typo3-navigationContainer');
+               this.NavigationIframe = Ext.getCmp('typo3-navigationIframe');
                this.Topbar = Ext.getCmp('typo3-topbar');
                this.ModuleMenuContainer = Ext.getCmp('typo3-module-menu');
                this.DebugConsole = Ext.getCmp('typo3-debug-console');
@@ -125,74 +133,6 @@ TYPO3.Viewport = Ext.extend(Ext.Viewport, {
                        }
                );
        },
-
-       /**
-        * Loads a module into the content container
-        *
-        * @param mainModuleName string name of the main module (e.g. web)
-        * @param subModuleName string name of the sub module (e.g. page)
-        * @param contentScript string the content provider (path to a php script)
-        * @return void
-        */
-       loadModule: function(mainModuleName, subModuleName, contentScript) {
-               var navigationWidgetActive = false;
-               var widgetMainModule = '';
-               var widgetSubModule = '';
-               var widget = null;
-               for (var widgetId in this.navigationWidgetMetaData) {
-                       widgetMainModule = this.navigationWidgetMetaData[widgetId].mainModule;
-                       widgetSubModule = this.navigationWidgetMetaData[widgetId].subModule;
-                       widget = this.navigationWidgetMetaData[widgetId].widget;
-
-                       if ((widgetMainModule === mainModuleName || widgetMainModule === '*') &&
-                               (widgetSubModule === subModuleName || widgetSubModule === '*')
-                       ) {
-                               widget.show();
-                               navigationWidgetActive = true;
-                       } else {
-                               widget.hide();
-                       }
-               }
-
-               if (navigationWidgetActive) {
-                       this.NavigationContainer.show();
-               } else {
-                       this.NavigationContainer.hide();
-               }
-
-               // append the typo3 path if it wasn't already applied
-               // this is important for backwards compatibility (e.g. shortcuts)
-               if (contentScript.indexOf(top.TS.PATH_typo3) !== 0) {
-                       contentScript = top.TS.PATH_typo3 + contentScript;
-               }
-               this.ContentContainer.setUrl(contentScript);
-               
-               this.NavigationContainer.ownerCt.doLayout();
-       },
-
-       /**
-        * Adds the given widget to the navigation container. The key will be the id attribute
-        * of the given widget.
-        *
-        * @param mainModule string main module or wildcard (*) for all
-        * @param subModule string sub module or wildcard (*) for all
-        * @param widget object ExtJS widget (e.g. an Ext.Panel); must contain an id attribute!
-        * @return void
-        */
-       registerNavigationWidget: function(mainModule, subModule, widget) {
-                       // only one instance of specific widget may be exists!
-               if (this.navigationWidgetMetaData[widget.id] === undefined) {
-                       this.navigationWidgetMetaData[widget.id] = {
-                               mainModule: mainModule,
-                               subModule: subModule,
-                               widget: widget
-                       };
-
-                               // always take the full width and height
-                       widget.anchor = '100% 100%';
-                       this.NavigationContainer.add(widget);
-               }
-       }
 });
 
 Ext.reg('typo3Viewport', TYPO3.Viewport);
index 8b217ae..77ab793 100644 (file)
@@ -70,11 +70,16 @@ TYPO3.Viewport.configuration = {
                        collapsible: true,
                        collapseMode: 'mini',
                        hideCollapseTool: true,
-                       autoScroll: true,
                        hidden: true,
                        border: false,
-                       xtype: 'iframePanel',
-                       name: 'navigation'
+                       name: 'navigation',
+                       autoScroll: true,
+                       items: [{
+                               id: 'typo3-navigationIframe',
+                               border: false,
+                               hidden: true,
+                               xtype: 'iframePanel'
+                       }]
                }, {
                        region: 'center',
                        layout: 'fit',
index dd4f86a..5fe1b4d 100644 (file)
@@ -92,6 +92,8 @@ TYPO3.ModuleMenu.Template = new Ext.XTemplate(
 
 TYPO3.ModuleMenu.App = {
        loadedModule: null,
+       loadedNavigationComponentId: '',
+       availableNavigationComponents: {},
 
        init: function() {
                TYPO3.ModuleMenu.Store.load({
@@ -204,8 +206,13 @@ TYPO3.ModuleMenu.App = {
                                params = 'id=' + top.fsMod.recentIds[section] + params;
                        }
 
-                       if (record.navframe) {
+                       if (record.navigationComponentId) {
+                               this.loadNavigationComponent(record.navigationComponentId);
+                               TYPO3.Backend.NavigationIframe.getEl().parent().setStyle('overflow', 'auto');
+                       } else if (record.navframe) {
+                               this.loadNavigationComponent('typo3-navigationIframe');
                                this.openInNavFrame(record.navframe);
+                               TYPO3.Backend.NavigationIframe.getEl().parent().setStyle('overflow', 'hidden');
                        } else {
                                TYPO3.Backend.NavigationContainer.hide();
                        }
@@ -223,12 +230,44 @@ TYPO3.ModuleMenu.App = {
                }
        },
 
+       loadNavigationComponent: function(navigationComponentId) {
+               if (navigationComponentId === this.loadedNavigationComponentId) {
+                       if (TYPO3.Backend.NavigationContainer.hidden) {
+                               TYPO3.Backend.NavigationContainer.show();
+                       }
+
+                       return;
+               }
+
+               if (this.loadedNavigationComponentId !== '') {
+                       Ext.getCmp(this.loadedNavigationComponentId).hide();
+               }
+               
+               var component = Ext.getCmp(navigationComponentId);
+               if (typeof component !== 'object') {
+                       if (typeof this.availableNavigationComponents[navigationComponentId] !== 'function') {
+                               throw 'The navigation component "' + navigationComponentId + '" is not available ' +
+                                       'or has no valid callback function';
+                       }
+
+                       component = this.availableNavigationComponents[navigationComponentId]();
+                       TYPO3.Backend.NavigationContainer.add(component);
+               }
+
+               component.show()
+               TYPO3.Backend.NavigationContainer.show();
+               this.loadedNavigationComponentId = navigationComponentId;
+       },
+
+       registerNavigationComponent: function(componentId, initCallback) {
+               this.availableNavigationComponents[componentId] = initCallback;
+       },
+
        openInNavFrame: function(url, params) {
                var navUrl = url + (params ? (url.indexOf('?') !== -1 ? '&' : '?') + params : '');
-               var currentUrl = this.relativeUrl(TYPO3.Backend.NavigationContainer.getUrl());
-               TYPO3.Backend.NavigationContainer.show();
+               var currentUrl = this.relativeUrl(TYPO3.Backend.NavigationIframe.getUrl());
                if (currentUrl !== navUrl) {
-                       TYPO3.Backend.NavigationContainer.setUrl(navUrl);
+                       TYPO3.Backend.NavigationIframe.setUrl(navUrl);
                }
        },
 
@@ -262,7 +301,7 @@ TYPO3.ModuleMenu.App = {
        },
 
        reloadFrames: function() {
-               TYPO3.Backend.NavigationContainer.refresh();
+               TYPO3.Backend.NavigationIframe.refresh();
                TYPO3.Backend.ContentContainer.refresh();
        }
 
@@ -275,13 +314,13 @@ Ext.onReady(function() {
 
                // keep backward compatibility
        top.list = TYPO3.Backend.ContentContainer;
-       top.nav = TYPO3.Backend.NavigationContainer;
+       top.nav = TYPO3.Backend.NavigationIframe;
        top.list_frame = top.list.getIframe();
-       top.nav_frame = top.nav.getIframe();
+       top.nav_frame = TYPO3.Backend.NavigationIframe.getIframe();
 
        top.TYPO3ModuleMenu = TYPO3.ModuleMenu.App;
        top.content = {
-               nav_frame: TYPO3.Backend.NavigationContainer.getIframe(),
+               nav_frame: TYPO3.Backend.NavigationIframe.getIframe(),
                list_frame: TYPO3.Backend.ContentContainer.getIframe(),
                location: TYPO3.Backend.ContentContainer.getIframe().location,
                document: TYPO3.Backend.ContentContainer.getIframe()