[BUGFIX] Workspace selector in top toolbar cannot scroll 53/22653/2
authorGeorg Ringer <georg.ringer@gmail.com>
Sun, 28 Jul 2013 22:00:39 +0000 (00:00 +0200)
committerStefan Neufeind <typo3.neufeind@speedpartner.de>
Sun, 28 Jul 2013 22:08:08 +0000 (00:08 +0200)
If there are too many workspaces defined, some of them cannot
be accessed using the workspace selector in in the top toolbar
due to a missing scrolling behaviour of that component.

Fixes: #11014
Releases: 6.2, 6.1, 6.0
Change-Id: Iaae51ebb2524116b8673a9cc81d612fd845b2d29
Reviewed-on: https://review.typo3.org/22653
Reviewed-by: Stefan Neufeind
Tested-by: Stefan Neufeind
typo3/sysext/t3skin/stylesheets/structure/toolbar.css
typo3/sysext/t3skin/stylesheets/visual/toolbar_workspace.css
typo3/sysext/workspaces/Classes/ExtDirect/WorkspaceSelectorToolbarItem.php
typo3/sysext/workspaces/Resources/Public/JavaScript/workspacemenu.js

index 92547b9..e84d57f 100644 (file)
@@ -55,18 +55,16 @@ Toolbar inside the Topbar
        top: 28px;
        z-index: 100;
        right: 0;
+       margin: 0;
+       padding: 2px 0 0;
+       position: absolute;
+       width: 180px;
 }
 
 .separator .toolbar-item-menu {
        right: 12px;
 }
 
-ul.toolbar-item-menu {
-       margin: 0;
-       padding: 2px 0 0;
-       position: absolute;
-       width: 180px;
-}
 
 #typo3-toolbar .toolbar-item-menu li {
        padding-top: 0;
index eefed2d..3575726 100644 (file)
@@ -4,10 +4,14 @@ Workspace Selector
 - - - - - - - - - - - - - - - - - - - - - */
 
 #workspace-selector-menu ul {
+       position: static;
+}
+
+#workspace-selector-menu .items {
        list-style: none;
        background-color: #f9f9f9;
-       border: 1px solid #abb2bc;
-       border-top: none;
+       overflow-y: auto;
+       max-height: 300px;
 }
 
 #workspace-selector-menu li {
@@ -16,15 +20,19 @@ Workspace Selector
 
 #workspace-selector-menu li a {
        font-size: 11px;
-       line-height: 12px;
+       line-height: 19px;
        text-decoration: none;
 }
 
 #workspace-selector-menu li.divider {
-       border-right: 1px solid #a5a5a5;
-       border-top: 1px solid #a5a5a5;
+       border: 0;
        background-image: url('../../icons/gfx/shortcutgroups-bg.png');
        background-repeat: repeat-x;
+       min-height: 10px;
+       padding-right: 0;
+}
+#workspace-selector-menu li.divider:hover {
+       background-color: transparent;
 }
 
 body.typo3-in-workspace #typo3-top-container {
@@ -45,4 +53,4 @@ body.typo3-in-workspace #typo3-topbar {
 
 body.typo3-in-workspace #typo3-topbar #username {
        text-shadow: 0 0 5px #000000;
-}
\ No newline at end of file
+}
index 46dcd01..9714489 100644 (file)
@@ -95,32 +95,50 @@ class WorkspaceSelectorToolbarItem implements \TYPO3\CMS\Backend\Toolbar\Toolbar
        public function render() {
                $title = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xml:toolbarItems.workspace', TRUE);
                $this->addJavascriptToBackend();
+
+               $index = 0;
                $availableWorkspaces = \Tx_Workspaces_Service_Workspaces::getAvailableWorkspaces();
-               $workspaceMenu = array();
+               $activeWorkspace = (int) $GLOBALS['BE_USER']->workspace;
                $stateCheckedIcon = \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('status-status-checked');
                $stateUncheckedIcon = \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('empty-empty', array(
                        'title' => $GLOBALS['LANG']->getLL('bookmark_inactive')
                ));
-               $workspaceMenu[] = '<a href="#" class="toolbar-item">' . \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('apps-toolbar-menu-workspace', array('title' => $title)) . '</a>';
-               $workspaceMenu[] = '<ul class="toolbar-item-menu" style="display: none;">';
-               if (count($availableWorkspaces)) {
-                       foreach ($availableWorkspaces as $workspaceId => $label) {
-                               $selected = '';
-                               $icon = $stateUncheckedIcon;
-                               if ((int) $GLOBALS['BE_USER']->workspace === $workspaceId) {
-                                       $selected = ' class="selected"';
-                                       $icon = $stateCheckedIcon;
-                               }
-                               $workspaceMenu[] = '<li' . $selected . '>' . '<a href="backend.php?changeWorkspace=' . intval($workspaceId) . '" id="ws-' . intval($workspaceId) . '" class="ws">' . $icon . ' ' . htmlspecialchars($label) . '</a></li>';
+
+               $workspaceSections = array(
+                       'top' => array(),
+                       'items' => array(),
+               );
+
+               foreach ($availableWorkspaces as $workspaceId => $label) {
+                       $iconState = ($workspaceId === $activeWorkspace ? $stateCheckedIcon : $stateUncheckedIcon);
+                       $classValue = ($workspaceId === $activeWorkspace ? ' class="selected"' : '');
+                       $sectionName = ($index++ === 0 ? 'top' : 'items');
+                       $workspaceSections[$sectionName][] = '<li' . $classValue . '>' . '<a href="backend.php?changeWorkspace=' . intval($workspaceId) . '" id="ws-' . intval($workspaceId) . '" class="ws">' . $iconState . ' ' . htmlspecialchars($label) . '</a></li>';
+               }
+
+               if (count($workspaceSections['top']) > 0) {
+                       // Go to workspace module link
+                       if ($GLOBALS['BE_USER']->check('modules', 'web_WorkspacesWorkspaces')) {
+                               $workspaceSections['top'][] = '<li>' . '<a href="javascript:top.goToModule(\'web_WorkspacesWorkspaces\');" target="content" id="goToWsModule">' . $stateUncheckedIcon . ' ' . $GLOBALS['LANG']->getLL('bookmark_workspace', TRUE) . '</a></li>';
                        }
+                       $workspaceSections['top'][] = '<li class="divider"></li>';
                } else {
-                       $workspaceMenu[] = '<li>' . $stateUncheckedIcon . ' ' . $GLOBALS['LANG']->getLL('bookmark_noWSfound', TRUE) . '</li>';
-               }
-               if ($GLOBALS['BE_USER']->check('modules', 'web_WorkspacesWorkspaces')) {
-                       // go to workspace module link
-                       $workspaceMenu[] = '<li class="divider">' . $stateUncheckedIcon . ' ' . '<a href="javascript:top.goToModule(\'web_WorkspacesWorkspaces\');" target="content" id="goToWsModule">' . ' ' . $GLOBALS['LANG']->getLL('bookmark_workspace', TRUE) . '</a></li>';
+                       $workspaceSections['top'][] = '<li>' . $stateUncheckedIcon . ' ' . $GLOBALS['LANG']->getLL('bookmark_noWSfound', TRUE) . '</li>';
                }
-               $workspaceMenu[] = '</ul>';
+
+
+               $workspaceMenu = array(
+                       '<a href="#" class="toolbar-item">' . \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('apps-toolbar-menu-workspace', array('title' => $title)) . '</a>',
+                       '<div class="toolbar-item-menu" style="display: none">' ,
+                               '<ul class="top">',
+                                       implode(LF, $workspaceSections['top']),
+                               '</ul>',
+                               '<ul class="items">',
+                                       implode(LF, $workspaceSections['items']),
+                               '</ul>',
+                       '</div>'
+               );
+
                return implode(LF, $workspaceMenu);
        }
 
@@ -148,4 +166,4 @@ class WorkspaceSelectorToolbarItem implements \TYPO3\CMS\Backend\Toolbar\Toolbar
 if (!(TYPO3_REQUESTTYPE & TYPO3_REQUESTTYPE_AJAX)) {
        $GLOBALS['TYPO3backend']->addToolbarItem('workSpaceSelector', 'TYPO3\\CMS\\Workspaces\\ExtDirect\\WorkspaceSelectorToolbarItem');
 }
-?>
\ No newline at end of file
+?>
index bf239a4..57e86a8 100644 (file)
@@ -39,10 +39,7 @@ var WorkspaceMenu = Class.create({
        initialize: function() {
 
                Ext.onReady(function() {
-                       Event.observe(
-                               window, 'resize',
-                               function() { TYPO3BackendToolbarManager.positionMenu('workspace-selector-menu'); }
-                       );
+                       Event.observe(window, 'resize', TYPO3BackendWorkspaceMenu.updateDimension);
                        if (top.TYPO3.configuration.inWorkspace == 1) {
                                Ext.getBody().addClass('typo3-in-workspace');
                                this.updateTopBar(top.TYPO3.Workspaces.workspaceTitle);
@@ -73,6 +70,7 @@ var WorkspaceMenu = Class.create({
 
                if (!toolbarItem.hasClassName('toolbar-item-active')) {
                        toolbarItem.addClassName('toolbar-item-active');
+                       TYPO3BackendWorkspaceMenu.updateDimension();
                        Effect.Appear(menu, {duration: 0.2});
                        TYPO3BackendToolbarManager.hideOthers(toolbarItem);
                } else {
@@ -164,6 +162,29 @@ var WorkspaceMenu = Class.create({
                        }
                        userItem.insertHtml('beforeEnd', '<span id="typo3-topbar-workspaces-title">@' + Ext.util.Format.htmlEncode(workspaceTitle) + '</span>')
                }
+       },
+
+       updateDimension: function() {
+               var toolbarItem = Ext.get('workspace-selector-menu');
+               var container = toolbarItem.select('.toolbar-item-menu').first();
+               var menuTop = toolbarItem.select('.top').first();
+               var menuItems = toolbarItem.select('.items').first();
+               var fixDisplay = container.isStyle('display', 'none');
+
+               TYPO3BackendToolbarManager.positionMenu('workspace-selector-menu');
+
+               if (fixDisplay) {
+                       container.setStyle({visibility: 'hidden', display: 'block'});
+               }
+
+               menuItems.setStyle(
+                       'max-height',
+                       (top.TYPO3.Backend.getHeight() - menuTop.getY() - menuTop.getHeight() - 20) + 'px'
+               );
+
+               if (fixDisplay) {
+                       container.setStyle({display: 'none', visibility: 'visible'});
+               }
        }
 
 });