diff --git a/typo3/sysext/backend/Classes/Controller/ContentElement/NewContentElementController.php b/typo3/sysext/backend/Classes/Controller/ContentElement/NewContentElementController.php index 54078b3ae6c451309ebe33891b20dec0b261928d..ca2ce510bd798d3d5b3ef30ba4a6cd17e98d9820 100644 --- a/typo3/sysext/backend/Classes/Controller/ContentElement/NewContentElementController.php +++ b/typo3/sysext/backend/Classes/Controller/ContentElement/NewContentElementController.php @@ -160,7 +160,7 @@ class NewContentElementController { $code = ''; $wizardItems = $this->getWizardItems(); // Wrapper for wizards - $this->elementWrapper['section'] = array('<div class="contentelement-wizard panel panel-tab"><div class="panel-body">', '</div></div>'); + $this->elementWrapper['section'] = array('', ''); // Copy wrapper for tabs $this->elementWrapperForTabs = $this->elementWrapper; // Hook for manipulating wizardItems, wrapper, onClickEvent etc. @@ -237,7 +237,7 @@ class NewContentElementController { } // Add the wizard table to the content, wrapped in tabs: if ($this->config['renderMode'] == 'tabs') { - $code = '<p>' . $GLOBALS['LANG']->getLL('sel1', 1) . '</p>' . $this->doc->getDynTabMenu($menuItems, 'new-content-element-wizard', FALSE, FALSE); + $code = '<p>' . $GLOBALS['LANG']->getLL('sel1', 1) . '</p>' . $this->doc->getDynamicTabMenu($menuItems, 'new-content-element-wizard'); } else { $code = '<p>' . $GLOBALS['LANG']->getLL('sel1', 1) . '</p>'; foreach ($menuItems as $section) { diff --git a/typo3/sysext/backend/Classes/Form/FormEngine.php b/typo3/sysext/backend/Classes/Form/FormEngine.php index 21febee6b208872e26f4021fc3c154f4db588732..90d6858af353a285f5c74815c50e259602dd06ff 100644 --- a/typo3/sysext/backend/Classes/Form/FormEngine.php +++ b/typo3/sysext/backend/Classes/Form/FormEngine.php @@ -1592,12 +1592,12 @@ class FormEngine { /** * Create dynamic tab menu * - * @param array $parts Parts for the tab menu, fed to template::getDynTabMenu() - * @param string $idString ID string for the tab menu + * @param array $menuItems Items for the tab menu, fed to template::getDynTabMenu() + * @param string $identString ID string for the tab menu * @param int $dividersToTabsBehaviour If set to '1' empty tabs will be removed, If set to '2' empty tabs will be disabled, deprecated, and not in use anymore since TYPO3 CMS 7 * @return string HTML for the menu */ - public function getDynTabMenu($parts, $idString, $dividersToTabsBehaviour = -1) { + public function getDynTabMenu($menuItems, $identString, $dividersToTabsBehaviour = -1) { // if the third (obsolete) parameter is used, throw a deprecation warning if ($dividersToTabsBehaviour !== -1) { GeneralUtility::deprecationLog('The parameter $dividersToTabsBehaviour in FormEngine::getDynTabMenu is deprecated. Please remove this option from your code'); @@ -1605,16 +1605,18 @@ class FormEngine { $docTemplate = $this->getDocumentTemplate(); if (is_object($docTemplate)) { $docTemplate->backPath = ''; - return $docTemplate->getDynTabMenu($parts, $idString, 0, FALSE, 1, FALSE, 1); + return $docTemplate->getDynamicTabMenu($menuItems, $identString, 1, FALSE, FALSE); } else { $output = ''; - foreach ($parts as $singlePad) { - $output .= ' - <h3>' . htmlspecialchars($singlePad['label']) . '</h3> - ' . ($singlePad['description'] ? '<p class="c-descr">' . nl2br(htmlspecialchars($singlePad['description'])) . '</p>' : '') . ' - ' . $singlePad['content']; + foreach ($menuItems as $menuItem) { + if (!empty($menuItem['content'])) { + $output .= ' + <h3>' . htmlspecialchars($menuItem['label']) . '</h3> + ' . ($menuItem['description'] ? '<p>' . nl2br(htmlspecialchars($menuItem['description'])) . '</p>' : '') . ' + ' . $menuItem['content']; + } } - return '<div class="tab-content">' . $output . '</div>'; + return $output; } } diff --git a/typo3/sysext/backend/Classes/Template/DocumentTemplate.php b/typo3/sysext/backend/Classes/Template/DocumentTemplate.php index 71d5957d4f05327491c2ca0360c4d3b004c3d57b..a739f341ff5444684f4d3129a09f9cd6802e97c5 100644 --- a/typo3/sysext/backend/Classes/Template/DocumentTemplate.php +++ b/typo3/sysext/backend/Classes/Template/DocumentTemplate.php @@ -20,6 +20,7 @@ use TYPO3\CMS\Core\Html\HtmlParser; use TYPO3\CMS\Core\Page\PageRenderer; use TYPO3\CMS\Core\Utility\ExtensionManagementUtility; use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Fluid\View\StandaloneView; /** * TYPO3 Backend Template Class @@ -1581,6 +1582,33 @@ function jumpToUrl(URL) { } + /** + * Creates a DYNAMIC tab-menu where the tabs or collapseable are rendered with bootstrap markup + * + * @param array $menuItems Numeric array where each entry is an array in itself with associative keys: "label" contains the label for the TAB, "content" contains the HTML content that goes into the div-layer of the tabs content. "description" contains description text to be shown in the layer. "linkTitle" is short text for the title attribute of the tab-menu link (mouse-over text of tab). "stateIcon" indicates a standard status icon (see ->icon(), values: -1, 1, 2, 3). "icon" is an image tag placed before the text. + * @param string $identString Identification string. This should be unique for every instance of a dynamic menu! + * @param int $defaultTabIndex Default tab to open (for toggle <=0). Value corresponds to integer-array index + 1 (index zero is "1", index "1" is 2 etc.). A value of zero (or something non-existing) will result in no default tab open. + * @param bool $collapseable If set, the tabs are rendered as headers instead over each sheet. Effectively this means there is no tab menu, but rather a foldout/foldin menu. + * @param bool $wrapContent If set, the content is wrapped in div structure which provides a padding and border style. Set this FALSE to get unstyled content pane with fullsize content area. + * @param bool $storeLastActiveTab If set, the last open tab is stored in local storage and will be re-open again. If you don't need this feature, e.g. for wizards like import/export you can disable this behaviour. + * @return string + */ + public function getDynamicTabMenu(array $menuItems, $identString, $defaultTabIndex = 1, $collapseable = FALSE, $wrapContent = TRUE, $storeLastActiveTab = TRUE) { + $this->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/Tabs'); + $templatePathAndFileName = 'EXT:backend/Resources/Private/Templates/DocumentTemplate/' . ($collapseable ? 'Collapse.html' : 'Tabs.html'); + $view = GeneralUtility::makeInstance(StandaloneView::class); + $view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName($templatePathAndFileName)); + $view->assignMultiple(array( + 'id' => $this->getDynTabMenuId($identString), + 'items' => $menuItems, + 'defaultTabIndex' => $defaultTabIndex, + 'wrapContent' => $wrapContent, + 'storeLastActiveTab' => $storeLastActiveTab, + 'BACK_PATH' => $GLOBALS['BACK_PATH'] + )); + return $view->render(); + } + /** * Creates a DYNAMIC tab-menu where the tabs are switched between with DHTML. * Should work in MSIE, Mozilla, Opera and Konqueror. On Konqueror I did find a serious problem: <textarea> fields loose their content when you switch tabs! @@ -1594,104 +1622,11 @@ function jumpToUrl(URL) { * @param int $defaultTabIndex Default tab to open (for toggle <=0). Value corresponds to integer-array index + 1 (index zero is "1", index "1" is 2 etc.). A value of zero (or something non-existing) will result in no default tab open. * @param int $tabBehaviour If set to '1' empty tabs will be remove, If set to '2' empty tabs will be disabled. setting this option to '2' is deprecated since TYPO3 CMS 7, and will be removed iwth CMS 8 * @return string JavaScript section for the HTML header. + * @deprecated since TYPO3 CMS 7, will be removed in TYPO3 CMS 8 */ public function getDynTabMenu($menuItems, $identString, $toggle = 0, $foldout = FALSE, $noWrap = TRUE, $fullWidth = FALSE, $defaultTabIndex = 1, $tabBehaviour = 1) { - if ($tabBehaviour === 2) { - GeneralUtility::deprecationLog('DocumentTemplate::getDynTabMenu parameter $tabBehavior (=2) with showing empty disabled since TYPO3 CMS 7, and will not be supported anymore with CMS 8'); - } - // Load the static code, if not already done with the function below - $this->loadJavascriptLib('sysext/backend/Resources/Public/JavaScript/tabmenu.js'); - $content = ''; - if (is_array($menuItems)) { - // Init: - $options = array(array()); - $divs = array(); - $JSinit = array(); - $id = $this->getDynTabMenuId($identString); - - // Traverse menu items - $c = 0; - $tabRows = 0; - $titleLenCount = 0; - foreach ($menuItems as $index => $def) { - // Need to add one so checking for first index in JavaScript - // is different than if it is not set at all. - $index += 1; - // Switch to next tab row if needed - if (!$foldout && ($def['newline'] === TRUE && $titleLenCount > 0)) { - $titleLenCount = 0; - $tabRows++; - $options[$tabRows] = array(); - } - if ($toggle == 1) { - $onclick = 'DTM_toggle("' . $id . '","' . $index . '"); return false;'; - } else { - $onclick = 'DTM_activate("' . $id . '","' . $index . '", ' . ($toggle < 0 ? 1 : 0) . '); return false;'; - } - $isEmpty = trim($def['content']) === '' && trim($def['icon']) === ''; - // "Removes" empty tabs - if ($isEmpty && $tabBehaviour == 1) { - continue; - } - $requiredIcon = '<img name="' . $id . '-' . $index . '-REQ" src="' . $GLOBALS['BACK_PATH'] . 'gfx/clear.gif" class="t3-TCEforms-reqTabImg" alt="" />'; - if (!$foldout) { - // Create TAB cell: - $options[$tabRows][] = ' - <li class="' . ($isEmpty ? 'disabled' : '') . '" id="' . $id . '-' . $index . '-MENU">' . ($isEmpty ? '' : '<a href="#" onclick="' . htmlspecialchars($onclick) . '"' . ($def['linkTitle'] ? ' title="' . htmlspecialchars($def['linkTitle']) . '"' : '') . '>') . $def['icon'] . ($def['label'] ? htmlspecialchars($def['label']) : ' ') . $requiredIcon . $this->icons($def['stateIcon'], 'margin-left: 10px;') . ($isEmpty ? '' : '</a>') . '</li>'; - $titleLenCount += strlen($def['label']); - } else { - // Create DIV layer for content: - $divs[] = ' - <div class="' . ($isEmpty ? 'disabled' : '') . '" id="' . $id . '-' . $index . '-MENU">' . ($isEmpty ? '' : '<a href="#" onclick="' . htmlspecialchars($onclick) . '"' . ($def['linkTitle'] ? ' title="' . htmlspecialchars($def['linkTitle']) . '"' : '') . '>') . $def['icon'] . ($def['label'] ? htmlspecialchars($def['label']) : ' ') . $requiredIcon . ($isEmpty ? '' : '</a>') . '</div>'; - } - // Create DIV layer for content: - $divs[] = ' - <div id="' . $id . '-' . $index . '-DIV" class="tab-pane">' . ($def['description'] ? '<p class="c-descr">' . nl2br(htmlspecialchars($def['description'])) . '</p>' : '') . $def['content'] . '</div>'; - // Create initialization string: - $JSinit[] = ' - DTM_array["' . $id . '"][' . $c . '] = "' . $id . '-' . $index . '"; - '; - // If not empty and we have the toggle option on, check if the tab needs to be expanded - if ($toggle == 1 && !$isEmpty) { - $JSinit[] = ' - if (top.DTM_currentTabs["' . $id . '-' . $index . '"]) { DTM_toggle("' . $id . '","' . $index . '",1); } - '; - } - $c++; - } - // Render menu: - if (count($options)) { - // Tab menu is compiled: - if (!$foldout) { - $tabContent = ''; - for ($a = 0; $a <= $tabRows; $a++) { - $tabContent .= ' - - <!-- Tab menu --> - <ul class="nav nav-tabs" role="tablist"> - ' . implode('', $options[$a]) . ' - </ul>'; - } - $content .= $tabContent; - } - // Div layers are added: - $content .= ' - <!-- Div layers for tab menu: --> - <div class="tab-content' . ($foldout ? ' tab-content-foldout' : '') . '"> - ' . implode('', $divs) . '</div>'; - // Java Script section added: - $content .= ' - <!-- Initialization JavaScript for the menu --> - <script type="text/javascript"> - DTM_array["' . $id . '"] = new Array(); - ' . implode('', $JSinit) . ' - ' . ($toggle <= 0 ? 'DTM_activate("' . $id . '", top.DTM_currentTabs["' . $id . '"]?top.DTM_currentTabs["' . $id . '"]:' . (int)$defaultTabIndex . ', 0);' : '') . ' - </script> - - '; - } - } - return $content; + GeneralUtility::logDeprecatedFunction(); + return $this->getDynamicTabMenu($menuItems, $identString, $defaultTabIndex, $foldout, $noWrap); } /** diff --git a/typo3/sysext/backend/Classes/ViewHelpers/SpriteManagerIconViewHelper.php b/typo3/sysext/backend/Classes/ViewHelpers/SpriteManagerIconViewHelper.php new file mode 100644 index 0000000000000000000000000000000000000000..e421f52a0a0cc2161bf9b71822ecf6750e49c69b --- /dev/null +++ b/typo3/sysext/backend/Classes/ViewHelpers/SpriteManagerIconViewHelper.php @@ -0,0 +1,55 @@ +<?php +namespace TYPO3\CMS\Backend\ViewHelpers; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Backend\Utility\IconUtility; +use TYPO3\CMS\Fluid\Core\Rendering\RenderingContextInterface; +use TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper; +use TYPO3\CMS\Fluid\Core\ViewHelper\Facets\CompilableInterface; + +/** + * Displays sprite icon identified by iconName key + * + * @author Felix Kopp <felix-source@phorax.com> + * @internal + */ +class SpriteManagerIconViewHelper extends AbstractViewHelper implements CompilableInterface { + + /** + * Prints sprite icon html for $iconName key + * + * @param string $iconName + * @param array $options + * @return string + */ + public function render($iconName, $options = array()) { + return self::renderStatic(array('iconName' => $iconName, 'options' => $options), $this->buildRenderChildrenClosure(), $this->renderingContext); + } + + /** + * Print sprite icon html for $iconName key + * + * @param array $arguments + * @param \Closure $renderChildrenClosure + * @param RenderingContextInterface $renderingContext + * @return string + */ + static public function renderStatic(array $arguments, \Closure $renderChildrenClosure, RenderingContextInterface $renderingContext) { + $iconName = $arguments['iconName']; + $options = $arguments['options']; + return IconUtility::getSpriteIcon($iconName, $options); + } + +} diff --git a/typo3/sysext/backend/Resources/Private/Templates/DocumentTemplate/Collapse.html b/typo3/sysext/backend/Resources/Private/Templates/DocumentTemplate/Collapse.html new file mode 100644 index 0000000000000000000000000000000000000000..3d63bfc2a4c08266297b714ae592110660cecc99 --- /dev/null +++ b/typo3/sysext/backend/Resources/Private/Templates/DocumentTemplate/Collapse.html @@ -0,0 +1,40 @@ +<div class="panel-group" id="{id}" role="tablist" aria-multiselectable="true"> + <f:for each="{items}" as="item" iteration="iteration"> + <f:if condition="{item.content}"> + <div class="panel panel-default"> + <div class="panel-heading" role="tab" id="{id}-{iteration.cycle}-heading"> + <a data-toggle="collapse" title="{item.linkTitle}" data-parent="#{id}" href="#{id}-{iteration.cycle}" aria-expanded="true" aria-controls="{id}-{iteration.cycle}"> + <f:if condition="{item.icon}"> + <f:format.raw>{item.icon}</f:format.raw> + </f:if> + {item.label} + <img name="{id}-{iteration.cycle}-REQ" src="{BACK_PATH}gfx/clear.gif" class="t3-TCEforms-reqTabImg" alt="" /> + <f:if condition="{item.requiredIcon}"> + <f:format.raw>{item.requiredIcon}</f:format.raw> + </f:if> + <f:if condition="{item.stateIcon}"> + <f:render partial="StateIcon" arguments="{item: item}" /> + </f:if> + </a> + </div> + <div id="{id}-{iteration.cycle}" class="panel-collapse collapse{f:if(condition: '{iteration.cycle} == {defaultTabIndex}', then: ' in')}" role="tabpanel" aria-labelledby="{id}-{iteration.cycle}-heading"> + <f:if condition="{item.description}"> + <div class="panel-body"> + <p><f:format.nl2br>{item.description}</f:format.nl2br></p> + </div> + </f:if> + <f:if condition="{wrapContent}"> + <f:then> + <div class="panel-body"> + <f:format.raw>{item.content}</f:format.raw> + </div> + </f:then> + <f:else> + <f:format.raw>{item.content}</f:format.raw> + </f:else> + </f:if> + </div> + </div> + </f:if> + </f:for> +</div> diff --git a/typo3/sysext/backend/Resources/Private/Templates/DocumentTemplate/Partials/StateIcon.html b/typo3/sysext/backend/Resources/Private/Templates/DocumentTemplate/Partials/StateIcon.html new file mode 100644 index 0000000000000000000000000000000000000000..beedc5cc3540c67f8667b590f44b66482a6a7cbc --- /dev/null +++ b/typo3/sysext/backend/Resources/Private/Templates/DocumentTemplate/Partials/StateIcon.html @@ -0,0 +1,7 @@ +{namespace be = TYPO3\CMS\Backend\ViewHelpers} +<f:switch expression="{item.stateIcon}"> + <f:case value="-1"><be:spriteManagerIcon iconName="status-dialog-ok" /></f:case> + <f:case value="1"><be:spriteManagerIcon iconName="status-dialog-notification" /></f:case> + <f:case value="2"><be:spriteManagerIcon iconName="status-dialog-warning" /></f:case> + <f:case value="3"><be:spriteManagerIcon iconName="status-dialog-error" /></f:case> +</f:switch> diff --git a/typo3/sysext/backend/Resources/Private/Templates/DocumentTemplate/Tabs.html b/typo3/sysext/backend/Resources/Private/Templates/DocumentTemplate/Tabs.html new file mode 100644 index 0000000000000000000000000000000000000000..d88297b73533961bf37b3df80e05ceb89dd02812 --- /dev/null +++ b/typo3/sysext/backend/Resources/Private/Templates/DocumentTemplate/Tabs.html @@ -0,0 +1,50 @@ +<div role="tabpanel"> + <ul class="nav nav-tabs t3js-tabs" role="tablist" id="tabs-{id}" data-store-last-tab="{storeLastActiveTab}"> + <f:for each="{items}" as="item" iteration="iteration"> + <f:if condition="{item.content}"> + <li role="presentation"{f:if(condition: '{iteration.cycle} == {defaultTabIndex}', then: ' class="active"')}> + <a href="#{id}-{iteration.cycle}" title="{item.linkTitle}" aria-controls="{id}-{iteration.cycle}" role="tab" data-toggle="tab"> + <f:if condition="{item.icon}"> + <f:format.raw>{item.icon}</f:format.raw> + </f:if> + {item.label} + <img name="{id}-{iteration.cycle}-REQ" src="{BACK_PATH}gfx/clear.gif" class="t3-TCEforms-reqTabImg" alt="" /> + <f:if condition="{item.requiredIcon}"> + <f:format.raw>{item.requiredIcon}</f:format.raw> + </f:if> + <f:if condition="{item.stateIcon}"> + <f:render partial="StateIcon" arguments="{item: item}" /> + </f:if> + </a> + </li> + </f:if> + </f:for> + </ul> + <div class="tab-content"> + <f:for each="{items}" as="item" iteration="iteration"> + <f:if condition="{item.content}"> + <div role="tabpanel" class="tab-pane{f:if(condition: '{iteration.cycle} == {defaultTabIndex}', then: ' active')}" id="{id}-{iteration.cycle}"> + <f:if condition="{item.description}"> + <div class="panel panel-tab"> + <div class="panel-body"> + <p><f:format.nl2br>{item.description}</f:format.nl2br></p> + </div> + </div> + </f:if> + <f:if condition="{wrapContent}"> + <f:then> + <div class="panel panel-tab"> + <div class="panel-body"> + <f:format.raw>{item.content}</f:format.raw> + </div> + </div> + </f:then> + <f:else> + <f:format.raw>{item.content}</f:format.raw> + </f:else> + </f:if> + </div> + </f:if> + </f:for> + </div> +</div> diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/Tabs.js b/typo3/sysext/backend/Resources/Public/JavaScript/Tabs.js new file mode 100644 index 0000000000000000000000000000000000000000..f21f366cf1b55371ac8e2d7c065229c7493bb931 --- /dev/null +++ b/typo3/sysext/backend/Resources/Public/JavaScript/Tabs.js @@ -0,0 +1,92 @@ +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +/** + * This class handle the tabs in the TYPO3 backend. + * It stores the last active tab and open it again after a reload, + */ +define('TYPO3/CMS/Backend/Tabs', ['jquery', 'TYPO3/CMS/Backend/Storage'], function ($) { + + /** + * Tabs helper + * + * @type {{storage: (Storage.Client|*), cacheTimeInSeconds: number, storeLastActiveTab: number}} + */ + var Tabs = { + storage: top.TYPO3.Storage.Client, + // cache liftime in seconds + cacheTimeInSeconds: 1800, + storeLastActiveTab: 1 + }; + + /** + * initialize Tabs Helper + */ + Tabs.initialize = function() { + $('.t3js-tabs').each(function() { + var $tabContainer = $(this); + Tabs.storeLastActiveTab = $tabContainer.data('store-last-tab') == '1' ? 1 : 0; + $tabContainer.find('a[href="' + Tabs.receiveActiveTab($tabContainer.attr('id')) + '"]').tab('show'); + $tabContainer.on('show.bs.tab', function(e) { + if (Tabs.storeLastActiveTab == 1) { + var id = e.currentTarget.id; + var target = e.target.hash; + Tabs.storeActiveTab(id, target); + } + }); + }); + }; + + /** + * receive active tab from storage + * + * @param id + * @returns {string} + */ + Tabs.receiveActiveTab = function(id) { + var target = Tabs.storage.get(id) || ''; + var expire = Tabs.storage.get(id + '.expire') || 0; + if (expire > Tabs.getTimestamp()) { + return target; + } + return ''; + }; + + /** + * store active tab in storage + * + * @param id + * @param target + */ + Tabs.storeActiveTab = function(id, target) { + Tabs.storage.set(id, target); + Tabs.storage.set(id + '.expire', Tabs.getTimestamp() + Tabs.cacheTimeInSeconds); + }; + + /** + * get unixtimestamp + * + * @returns {number} + */ + Tabs.getTimestamp = function() { + return Math.round((new Date()).getTime() / 1000); + }; + + /** + * return the Tabs object + */ + return function() { + Tabs.initialize(); + return Tabs; + }(); +}); diff --git a/typo3/sysext/core/Documentation/Changelog/master/Deprecation-65111-getDynTabMenu.rst b/typo3/sysext/core/Documentation/Changelog/master/Deprecation-65111-getDynTabMenu.rst new file mode 100644 index 0000000000000000000000000000000000000000..b20a1c6de7bccc633e5f372a7672fc7f7eb41ccf --- /dev/null +++ b/typo3/sysext/core/Documentation/Changelog/master/Deprecation-65111-getDynTabMenu.rst @@ -0,0 +1,27 @@ +=================================== +Deprecation: #65111 - getDynTabMenu +=================================== + +Description +=========== + +The DocumentTemplate method ``getDynTabMenu()`` is deprecated. + + +Impact +====== + +The method was refactored and renamed. The new method ``getDynamicTabMenu()`` should be used. +The method ``getDynTabMenu()`` is now deprecated. + + +Affected installations +====================== + +All installations which make use of ``DocumentTemplate::getDynTabMenu()`` + + +Migration +========= + +Use ``DocumentTemplate::getDynamicTabMenu()`` instead of ``DocumentTemplate::getDynTabMenu()`` diff --git a/typo3/sysext/impexp/Classes/Controller/ImportExportController.php b/typo3/sysext/impexp/Classes/Controller/ImportExportController.php index f213487e68c815416dfa465d3c717b838add7c0c..e086a1410c8edc83b9006de31f97e56ba773be1f 100644 --- a/typo3/sysext/impexp/Classes/Controller/ImportExportController.php +++ b/typo3/sysext/impexp/Classes/Controller/ImportExportController.php @@ -440,7 +440,8 @@ class ImportExportController extends \TYPO3\CMS\Backend\Module\BaseScriptClass { 'stateIcon' => $errors ? 2 : 0 ); // Add hidden fields and create tabs: - $content = $this->doc->getDynTabMenu($menuItems, 'tx_impexp_export', -1); + + $content = $this->doc->getDynamicTabMenu($menuItems, 'tx_impexp_export', 1, FALSE, TRUE, FALSE); $content .= '<input type="hidden" name="tx_impexp[action]" value="export" />'; $this->content .= $this->doc->section('', $content, 0, 1); // Output Overview: @@ -1149,7 +1150,7 @@ class ImportExportController extends \TYPO3\CMS\Backend\Module\BaseScriptClass { 'stateIcon' => $errors ? 2 : 0 ); // Output tabs: - $content = $this->doc->getDynTabMenu($menuItems, 'tx_impexp_import', -1); + $content = $this->doc->getDynamicTabMenu($menuItems, 'tx_impexp_import', 1, FALSE, TRUE, FALSE); if ($extensionInstallationMessage) { $content = '<div style="border: 1px black solid; margin: 10px 10px 10px 10px; padding: 10px 10px 10px 10px;">' . $this->doc->icons(1) . htmlspecialchars($extensionInstallationMessage) . '</div>' . $content; diff --git a/typo3/sysext/linkvalidator/Classes/Report/LinkValidatorReport.php b/typo3/sysext/linkvalidator/Classes/Report/LinkValidatorReport.php index e07ffc145d70c56945a369e061d2e0034cd39cb2..c770e1bf0c505feff83981c8280c61b759edb804 100644 --- a/typo3/sysext/linkvalidator/Classes/Report/LinkValidatorReport.php +++ b/typo3/sysext/linkvalidator/Classes/Report/LinkValidatorReport.php @@ -213,7 +213,7 @@ class LinkValidatorReport extends \TYPO3\CMS\Backend\Module\AbstractFunctionModu ); } - return $this->doc->getDynTabMenu($menuItems, 'ident'); + return $this->doc->getDynamicTabMenu($menuItems, 'report-linkvalidator'); } /** diff --git a/typo3/sysext/setup/Classes/Controller/SetupModuleController.php b/typo3/sysext/setup/Classes/Controller/SetupModuleController.php index ee36e4ca56d99bcff37087e0aedf76f538c70cfc..2f2729826c8784a4e2cc9bbfb973a13687a2037c 100644 --- a/typo3/sysext/setup/Classes/Controller/SetupModuleController.php +++ b/typo3/sysext/setup/Classes/Controller/SetupModuleController.php @@ -404,7 +404,7 @@ class SetupModuleController { // Render the menu items $menuItems = $this->renderUserSetup(); - $this->content .= $this->doc->getDynTabMenu($menuItems, 'user-setup', FALSE, FALSE, 1, FALSE, 1, 1); + $this->content .= $this->doc->getDynamicTabMenu($menuItems, 'user-setup', 1, FALSE, FALSE); $formToken = $this->formProtection->generateToken('BE user setup', 'edit'); $this->content .= $this->doc->section('', '<input type="hidden" name="simUser" value="' . $this->simUser . '" /> <input type="hidden" name="formToken" value="' . $formToken . '" /> diff --git a/typo3/sysext/t3skin/Resources/Private/Styles/TYPO3/_element_animation.less b/typo3/sysext/t3skin/Resources/Private/Styles/TYPO3/_element_animation.less index 0492f2805d7c56255bbdcb0297abcc42b6ad4ffe..2d16ec89ff789117765f1f8837d73baeeb742bc6 100644 --- a/typo3/sysext/t3skin/Resources/Private/Styles/TYPO3/_element_animation.less +++ b/typo3/sysext/t3skin/Resources/Private/Styles/TYPO3/_element_animation.less @@ -16,3 +16,15 @@ .transition-property(~"width, visibility"); } } + +// +// Hotfix display collapse always to prevent RTE initialisation problems +// +.collapse { + display: block; + height: 0; + overflow: hidden; + &.in { + height: auto; + } +} diff --git a/typo3/sysext/t3skin/Resources/Private/Styles/TYPO3/_element_panel.less b/typo3/sysext/t3skin/Resources/Private/Styles/TYPO3/_element_panel.less index fa80a8efcc1d454a320ba31b26b4d30f572a5053..6152040290074a48a3fc4040153aa90314d3c466 100644 --- a/typo3/sysext/t3skin/Resources/Private/Styles/TYPO3/_element_panel.less +++ b/typo3/sysext/t3skin/Resources/Private/Styles/TYPO3/_element_panel.less @@ -103,8 +103,9 @@ border: 1px solid @nav-tabs-active-link-hover-border-color; background-color: @nav-tabs-active-link-bg; } -.panel-tab + .panel-tab { - margin-top: -19px; +.panel-tab + .panel-tab, +.panel-tab + .form-section { + margin-top: -(@line-height-computed+1); } .tab-pane { > .panel-tab:first-child { diff --git a/typo3/sysext/t3skin/Resources/Private/Styles/TYPO3/_element_tab.less b/typo3/sysext/t3skin/Resources/Private/Styles/TYPO3/_element_tab.less index 47a2e4863a0d2abac592a98d1ebf02094cd20b14..3ab849b4e5c77b4486bb5cb0a99fb1e766972848 100644 --- a/typo3/sysext/t3skin/Resources/Private/Styles/TYPO3/_element_tab.less +++ b/typo3/sysext/t3skin/Resources/Private/Styles/TYPO3/_element_tab.less @@ -5,6 +5,12 @@ background-color: darken(@nav-tabs-active-link-bg, 5%); > li { > a { + // Hotfix to prevent prototype / scriptaculous hiding the links + // this can be removed after prototype / scriptaculous removed completely. + // at the moment prototype / scriptaculous hide each tab after clicking on it. + // at the moment this seems to be the only way to fix the wrong behavior. + display: block!important; + margin-right: 3px; &:hover { background: @nav-tabs-link-hover-bg; @@ -79,4 +85,4 @@ div.typo3-dyntabmenu-divs-foldout div.disabled { div.typo3-dyntabmenu-divs-foldout div.disabled:hover { background: #f6eab7; color: #999; -} \ No newline at end of file +} diff --git a/typo3/sysext/t3skin/Resources/Public/Css/visual/t3skin.css b/typo3/sysext/t3skin/Resources/Public/Css/visual/t3skin.css index 34ba9897a41e2a57d30693cba1dc93dd7704be5d..0640fac3c580f75b794ab36402e81174597c03f5 100644 --- a/typo3/sysext/t3skin/Resources/Public/Css/visual/t3skin.css +++ b/typo3/sysext/t3skin/Resources/Public/Css/visual/t3skin.css @@ -7514,6 +7514,14 @@ button.close { -webkit-transition-property: width, visibility; transition-property: width, visibility; } +.collapse { + display: block; + height: 0; + overflow: hidden; +} +.collapse.in { + height: auto; +} table#typo3-clipboard { background-color: #efeff4; border: 1px solid #a2aab8; @@ -8542,6 +8550,7 @@ span.spinner { background-color: #ededed; } .nav-tabs > li > a { + display: block!important; margin-right: 3px; } .nav-tabs > li > a:hover { @@ -8887,7 +8896,8 @@ fieldset[disabled] .table .btn-default.active { border: 1px solid #cccccc; background-color: #fafafa; } -.panel-tab + .panel-tab { +.panel-tab + .panel-tab, +.panel-tab + .form-section { margin-top: -19px; } .tab-pane > .panel-tab:first-child {