* @param int $tabBehaviour If set to '1' empty tabs will be remove, If set to '2' empty tabs will be disabled
* @return string JavaScript section for the HTML header.
*/
- public function getDynTabMenu($menuItems, $identString, $toggle = 0, $foldout = FALSE, $noWrap = TRUE, $fullWidth = FALSE, $defaultTabIndex = 1, $tabBehaviour = 2) {
- // Load the static code, if not already done with the function below
- $this->loadJavascriptLib('sysext/backend/Resources/Public/JavaScript/tabmenu.js');
+ public function getDynTabMenu($menuItems, $identString, $toggle = 0, $foldout = FALSE, $noWrap = TRUE, $fullWidth = FALSE, $defaultTabIndex = 1, $tabBehaviour = 1) {
$content = '';
if (is_array($menuItems)) {
- // Init:
$options = array(array());
$divs = array();
- $JSinit = array();
- $id = $this->getDynTabMenuId($identString);
+
+ // include JS for TabMenu
+ $this->pageRenderer->loadJquery();
+ $this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/TabMenuSetup');
+
+ // unique identifier on this page
+ $menuId = $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;
+ foreach ($menuItems as $index => $menuItemData) {
+
+ $menuItemId = $menuId . '-' . $index;
+
// Switch to next tab row if needed
- if (!$foldout && ($def['newline'] === TRUE && $titleLenCount > 0)) {
+ if (!$foldout && ($menuItemData['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']) === '';
+
+ $isEmpty = trim($menuItemData['content']) === '' && trim($menuItemData['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="" />';
+
+ // set the classes for the container
+ $containerClasses = ($isEmpty ? 'disabled' : 'tab');
+ if ($noWrap) {
+ $containerClasses .= ' nowrap';
+ }
+
+ $requiredIcon = '<img name="' . $menuItemId . '-REQ" src="' . $GLOBALS['BACK_PATH'] . 'gfx/clear.gif" class="t3-TCEforms-reqTabImg" alt="" />';
+
+ $tabHeader = $menuItemData['icon'] . ($menuItemData['label'] ? htmlspecialchars($menuItemData['label']) : ' ') . $requiredIcon;
+
+ // wrap it in a link if it is not empty
+ if (!$isEmpty) {
+ $tabHeader = '<a href="#' . $menuItemId . '" data-toggle="TabMenu" ' . ($menuItemData['linkTitle'] ? ' title="' . htmlspecialchars($menuItemData['linkTitle']) . '"' : '') . '>' . $tabHeader . '</a>';
+ }
+
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']);
+ $tabHeader .= $this->icons($menuItemData['stateIcon'], 'margin-left: 10px;');
+ // Create TAB cell
+ $options[$tabRows][] = '<li class="' . $containerClasses . '" id="' . $menuItemId . '-MENU">' . $tabHeader . '</li>';
+ $titleLenCount += strlen($menuItemData['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>';
+ $divs[] = '<div class="' . $containerClasses . '" id="' . $menuItemId . '-MENU">' . $tabHeader . '</div>';
}
+
// Create DIV layer for content:
- $divs[] = '
- <div style="display: none;" id="' . $id . '-' . $index . '-DIV" class="c-tablayer">' . ($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++;
+ $divs[] = '<div style="display: none;" id="' . $menuItemId . '" class="c-tablayer">' . ($menuItemData['description'] ? '<p class="c-descr">' . nl2br(htmlspecialchars($menuItemData['description'])) . '</p>' : '') . $menuItemData['content'] . '</div>';
}
- // Render menu:
+
+ // Render menu
if (count($options)) {
- // Tab menu is compiled:
+ // Tab menu is compiled
if (!$foldout) {
$tabContent = '';
for ($a = 0; $a <= $tabRows; $a++) {
$tabContent .= '
-
- <!-- Tab menu -->
- <ul class="nav nav-tabs" role="tablist">
+ <ul class="nav nav-tabs t3-dyntabnav" role="tablist">
' . implode('', $options[$a]) . '
</ul>';
}
- $content .= '<div class="typo3-dyntabmenu-tabs">' . $tabContent . '</div>';
+ $content .= '<div class="typo3-dyntabmenu-tabs" id="' . $menuId . '-menucontainer">' . $tabContent . '</div>';
}
- // Div layers are added:
+ // Div layers are added
$content .= '
<!-- Div layers for tab menu: -->
- <div class="typo3-dyntabmenu-divs' . ($foldout ? '-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>
-
- ';
+ <div class="typo3-dyntabmenu-divs' . ($foldout ? '-foldout' : '') . '">' . implode('', $divs) . '</div>';
}
}
return $content;
* Creates the id for dynTabMenus.
*
* @param string $identString Identification string. This should be unique for every instance of a dynamic menu!
- * @return string The id with a short MD5 of $identString and prefixed "DTM-", like "DTM-2e8791854a
+ * @return string The id with a short MD5 of $identString and prefixed "DTM-", like "DTM-2e8791854a"
*/
public function getDynTabMenuId($identString) {
- $id = 'DTM-' . GeneralUtility::shortMD5($identString);
- return $id;
+ return 'DTM-' . GeneralUtility::shortMD5($identString);
}
/**
--- /dev/null
+/**
+ * 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!
+ */
+
+/**
+ * provides a jQuery plugin called "tabMenu" that is hooked on to each
+ * item of the element of the menu
+ */
+define('TYPO3/CMS/Backend/Plugins/TabMenuPlugin', ['jquery'], function($) {
+
+ // constructor method
+ // element can be a tab (not the tab content)
+ var TabMenuPlugin = function(element, options) {
+ me = this;
+ me.$element = $(element);
+
+ // if no options given, check if one of the parents (menuElement) has the TabMenuPlugin
+ if (undefined === options) {
+ var $parent = me.$element;
+ do {
+ if ($parent.data('TabMenuPlugin')) {
+ options = $parent.data('TabMenuPlugin').options;
+ break;
+ }
+ $parent = $parent.parent();
+ }
+ while ($parent.length > 0);
+ }
+ // merging options
+ me.options = $.extend({}, TabMenuPlugin.defaults, options);
+ me.detectContainerElement();
+ };
+
+ // methods applied to each TabMenu item
+ TabMenuPlugin.prototype = {
+ // used for each menu container item, so that it initializes the events
+ // for its tabs
+ initialize: function() {
+ var $activeItem;
+
+ // show first tab of this menu, or the last active stored in the local storage
+ if (localStorage && localStorage.getItem('TabMenuPlugin-ActiveItem-' + me.containerId)) {
+ $activeItem = $(localStorage.getItem('TabMenuPlugin-ActiveItem-' + me.containerId));
+ $activeItem = $activeItem.find(me.options.tabSelector).first();
+ }
+ if (!$activeItem || $activeItem.length == 0) {
+ $activeItem = me.$containerElement.find(me.options.tabSelector).first();
+ }
+ if ($activeItem.length > 0) {
+ $activeItem.tabMenu('toggle');
+ }
+ me._initEvents();
+ },
+
+ // detect the menu element (if the plugin is called on a tab label, find the menu item)
+ detectContainerElement: function() {
+ me.$containerElement = me.$element.closest(me.options.tabMenuContainerSelector);
+ me.containerId = me.$containerElement.prop('id');
+ },
+
+ // initialize events
+ _initEvents: function() {
+ // events binding to toggle the tab menu on clicking the head
+ $(me.options.tabSelector, me.$containerElement).on('click', function(evt) {
+ evt.preventDefault();
+ $(this).tabMenu('toggle');
+ });
+ },
+
+ // called on a tab item, that shows the container target
+ // and disables the other container targets on the same level
+ toggle: function() {
+ var
+ $activeItem = this.$element,
+ $parent = $activeItem.closest('li'),
+ // get DOM id of the target tab container
+ $target = $($activeItem.attr('href'));
+
+ // trigger jQuery hook: "show"
+ $activeItem.trigger({
+ type: 'show',
+ relatedTarget: $target
+ });
+
+ // update tab label class, and the siblings
+ me.$containerElement.find('li').not($parent).removeClass(me.options.activeClass);
+ $parent.addClass(me.options.activeClass);
+
+ // save the change in the local storage
+ if (localStorage && $parent.prop('id')) {
+ localStorage.setItem('TabMenuPlugin-ActiveItem-' + me.containerId, '#' + $parent.prop('id'));
+ }
+
+ // display target tab content
+ $target.show().siblings().hide();
+
+ // trigger jQuery hook "shown"
+ $activeItem.trigger({
+ type: 'shown',
+ relatedTarget: $target
+ });
+ }
+ };
+
+ // default options
+ TabMenuPlugin.defaults = {
+ // the selector for the tab label, should contain the content tab as href=""
+ tabSelector: '[data-toggle="TabMenu"]',
+ // the container selector, contains all information about the tabs
+ tabMenuContainerSelector: '.typo3-dyntabmenu-tabs',
+ // the class that the tab selector gets
+ activeClass: 'active'
+ };
+
+ // register the jQuery plugin "as $('myContainer').tabMenu()"
+ $.fn.tabMenu = function(action, options) {
+ return this.each(function() {
+ var $this = $(this),
+ data = $this.data('TabMenuPlugin');
+
+ // only apply the tabmenu to an item that does not have the tabmenu initialized yet
+ if (!data) {
+ $this.data('TabMenuPlugin', (data = new TabMenuPlugin(this, options)));
+ }
+
+ // option is an action to call sth directly
+ if (typeof action == 'string') {
+ data[action]();
+ }
+ });
+ };
+
+ return TabMenuPlugin;
+});
--- /dev/null
+/**
+ * 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!
+ */
+/**
+ * JavaScript RequireJS module called "TYPO3/CMS/Backend/TabMenuSetup"
+ *
+ * requires the tab menu jQuery plugin that does the logic
+ * and calls the plugin for each menu (.typo3-dyntabmenu items).
+ *
+ * After that, does the usual RequireJS logic and returns the object
+ */
+define('TYPO3/CMS/Backend/TabMenuSetup', ['jquery', 'TYPO3/CMS/Backend/Plugins/TabMenuPlugin'], function($) {
+
+ /**
+ * part 1: The main module of this file
+ * initialize the TabMenu by applying the jQuery plugin
+ */
+ var TabMenu = {
+ options: {
+ tabSelector: '[data-toggle="TabMenu"]',
+ tabMenuContainerSelector : '.typo3-dyntabmenu-tabs'
+ },
+ initialize: function() {
+ var me = this;
+
+ // initialize all tabMenus that are available on dom ready
+ $(document).ready(function() {
+ $(me.options.tabMenuContainerSelector).tabMenu('initialize', me.options);
+ });
+ }
+ };
+
+ /**
+ * part 2: initialize the RequireJS module, require possible post-initialize hooks,
+ * and return the main object
+ */
+ var initialize = function(options) {
+ TabMenu.initialize();
+
+ // load required modules to hook in the post initialize function
+ if (undefined !== TYPO3.settings && undefined !== TYPO3.settings.RequireJS && undefined !== TYPO3.settings.RequireJS.PostInitializationModules && undefined !== TYPO3.settings.RequireJS.PostInitializationModules['TYPO3/CMS/Backend/TabMenuSetup']) {
+ $.each(TYPO3.settings.RequireJS.PostInitializationModules['TYPO3/CMS/Backend/TabMenuSetup'], function(pos, moduleName) {
+ require([moduleName]);
+ });
+ }
+
+ // return the object in the global space
+ return TabMenu;
+ };
+
+ // call the main initialize function and execute the hooks
+ return initialize();
+});
/**
* javascript functions regarding the "dyntabmenu" used throughout the TYPO3 backend
+ * @deprecated with TYPO3 CMS 7, will be removed with CMS 8
*/
var DTM_array = DTM_array || [];