f0fb429ec4dd32715bb3f44cc0d4bc129aa2ea8b
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Resources / Public / JavaScript / modulemenu.js
1 /*
2 * This file is part of the TYPO3 CMS project.
3 *
4 * It is free software; you can redistribute it and/or modify it under
5 * the terms of the GNU General Public License, either version 2
6 * of the License, or any later version.
7 *
8 * For the full copyright and license information, please read the
9 * LICENSE.txt file that was distributed with this source code.
10 *
11 * The TYPO3 project - inspiring people to share!
12 */
13
14
15 /**
16 * Class to render the module menu and handle the BE navigation
17 */
18 require(
19 [
20 'jquery',
21 'TYPO3/CMS/Backend/Icons',
22 'TYPO3/CMS/Backend/Viewport'
23 ],
24 function ($, Icons) {
25 if (typeof TYPO3.ModuleMenu !== 'undefined') {
26 return TYPO3.ModuleMenu.App;
27 }
28 TYPO3.ModuleMenu = {};
29 TYPO3.ModuleMenu.App = {
30 loadedModule: null,
31 loadedNavigationComponentId: '',
32 availableNavigationComponents: {},
33
34 initialize: function () {
35 var me = this;
36
37 // load the start module
38 if (top.startInModule && top.startInModule[0] && $('#' + top.startInModule[0]).length > 0) {
39 me.showModule(top.startInModule[0], top.startInModule[1]);
40 } else {
41 // fetch first module
42 me.showModule($('.t3js-mainmodule:first').attr('id'));
43 }
44
45 // check if module menu should be collapsed or not
46 var state = Ext.state.Manager.getProvider().get('typo3-module-menu');
47 if (state && state.collapsed) {
48 TYPO3.ModuleMenu.App.toggleMenu(state.collapsed);
49 }
50
51 // check if there are collapsed items in the users' configuration
52 require(['TYPO3/CMS/Backend/Storage'], function () {
53 var collapsedMainMenuItems = me.getCollapsedMainMenuItems();
54 $.each(collapsedMainMenuItems, function (key, itm) {
55 if (itm !== true) {
56 return;
57 }
58 var $group = $('#' + key);
59 if ($group.length > 0) {
60 var $groupContainer = $group.find('.modulemenu-group-container');
61 $group.addClass('collapsed').removeClass('expanded');
62 TYPO3.Backend.NavigationContainer.cleanup();
63 $groupContainer.hide().promise().done(function () {
64 TYPO3.Backend.doLayout();
65 });
66 }
67 });
68 me.initializeEvents();
69 });
70 },
71
72 initializeEvents: function () {
73 var me = this;
74 $(document).on('click', '.modulemenu-group .modulemenu-group-header', function () {
75 var $group = $(this).parent('.modulemenu-group');
76 var $groupContainer = $group.find('.modulemenu-group-container');
77
78 TYPO3.Backend.NavigationContainer.cleanup();
79 if ($group.hasClass('expanded')) {
80 me.addCollapsedMainMenuItem($group.attr('id'));
81 $group.addClass('collapsed').removeClass('expanded');
82 $groupContainer.stop().slideUp().promise().done(function () {
83 TYPO3.Backend.doLayout();
84 });
85 } else {
86 me.removeCollapseMainMenuItem($group.attr('id'));
87 $group.addClass('expanded').removeClass('collapsed');
88 $groupContainer.stop().slideDown().promise().done(function () {
89 TYPO3.Backend.doLayout();
90 });
91 }
92
93 });
94 // register clicking on sub modules
95 $(document).on('click', '.modulemenu-item,.t3-menuitem-submodule', function (evt) {
96 evt.preventDefault();
97 me.showModule($(this).attr('id'));
98 TYPO3.Backend.doLayout();
99 });
100 $(document).on('click', '.t3js-topbar-button-modulemenu',
101 function (evt) {
102 evt.preventDefault();
103 TYPO3.ModuleMenu.App.toggleMenu();
104 }
105 );
106 $(document).on('click', '.t3js-scaffold-content-overlay',
107 function (evt) {
108 evt.preventDefault();
109 TYPO3.ModuleMenu.App.toggleMenu(true);
110 }
111 );
112 $(document).on('click', '.t3js-topbar-button-navigationcomponent',
113 function (evt) {
114 evt.preventDefault();
115 TYPO3.Backend.NavigationContainer.toggle();
116 }
117 );
118
119 },
120 toggleMenu: function (collapse) {
121 TYPO3.Backend.NavigationContainer.cleanup();
122
123 var $mainContainer = $('.t3js-scaffold');
124 var expandedClass = 'scaffold-modulemenu-expanded';
125
126 if (typeof collapse === 'undefined') {
127 collapse = $mainContainer.hasClass(expandedClass);
128 }
129 if (collapse) {
130 $mainContainer.removeClass(expandedClass);
131 } else {
132 $mainContainer.addClass(expandedClass);
133 $('.scaffold').removeClass('scaffold-search-expanded');
134 $('.scaffold').removeClass('scaffold-toolbar-expanded');
135 }
136
137 // @todo remove once we have a new state manager
138 Ext.state.Manager.set(
139 'typo3-module-menu',
140 {
141 collapsed: collapse
142 }
143 );
144
145 TYPO3.Backend.doLayout();
146 },
147
148 /* fetch the data for a submodule */
149 getRecordFromName: function (name) {
150 var $subModuleElement = $('#' + name);
151 return {
152 name: name,
153 navigationComponentId: $subModuleElement.data('navigationcomponentid'),
154 navigationFrameScript: $subModuleElement.data('navigationframescript'),
155 navigationFrameScriptParam: $subModuleElement.data('navigationframescriptparameters'),
156 link: $subModuleElement.find('a').attr('href')
157 };
158 },
159
160 showModule: function (mod, params) {
161 params = params || '';
162 params = this.includeId(mod, params);
163 var record = this.getRecordFromName(mod);
164 this.loadModuleComponents(record, params);
165 },
166
167 loadModuleComponents: function (record, params) {
168 var mod = record.name;
169 if (record.navigationComponentId) {
170 this.loadNavigationComponent(record.navigationComponentId);
171 } else if (record.navigationFrameScript) {
172 TYPO3.Backend.NavigationContainer.show('typo3-navigationIframe');
173 this.openInNavFrame(record.navigationFrameScript, record.navigationFrameScriptParam);
174 } else {
175 TYPO3.Backend.NavigationContainer.hide();
176 }
177
178 this.highlightModuleMenuItem(mod);
179 this.loadedModule = mod;
180 this.openInContentFrame(record.link, params);
181
182 // compatibility
183 top.currentSubScript = record.link;
184 top.currentModuleLoaded = mod;
185
186 TYPO3.Backend.doLayout();
187 },
188
189 includeId: function (mod, params) {
190 if (typeof mod === 'undefined') {
191 return params;
192 }
193 //get id
194 var section = mod.split('_')[0];
195 if (top.fsMod.recentIds[section]) {
196 params = 'id=' + top.fsMod.recentIds[section] + '&' + params;
197 }
198
199 return params;
200 },
201
202 loadNavigationComponent: function (navigationComponentId) {
203 TYPO3.Backend.NavigationContainer.show(navigationComponentId);
204 if (navigationComponentId === this.loadedNavigationComponentId) {
205 return;
206 }
207 if (this.loadedNavigationComponentId !== '') {
208 Ext.getCmp(this.loadedNavigationComponentId).hide();
209 }
210 if ($('.t3js-scaffold-content-navigation [data-component="' + navigationComponentId + '"]').length < 1) {
211 $('.t3js-scaffold-content-navigation')
212 .append('<div class="scaffold-content-navigation-component" data-component="' + navigationComponentId + '" id="navigationComponent-' + navigationComponentId + '"></div>');
213 }
214 var component = Ext.getCmp(navigationComponentId);
215 if (typeof component === 'undefined') {
216 /** @todo fix hard coded pagetree **/
217 component = new TYPO3.Components.PageTree.App();
218 component.render('navigationComponent-' + navigationComponentId);
219 }
220 TYPO3.Backend.NavigationContainer.show(navigationComponentId);
221 this.loadedNavigationComponentId = navigationComponentId;
222 },
223
224 registerNavigationComponent: function (componentId, initCallback) {
225 this.availableNavigationComponents[componentId] = initCallback;
226 },
227
228 openInNavFrame: function (url, params) {
229 var navUrl = url + (params ? (url.indexOf('?') !== -1 ? '&' : '?') + params : '');
230 var currentUrl = this.relativeUrl(TYPO3.Backend.NavigationContainer.getUrl());
231 if (currentUrl !== navUrl) {
232 TYPO3.Backend.NavigationContainer.refresh();
233 }
234 TYPO3.Backend.NavigationContainer.setUrl(url);
235 },
236
237 openInContentFrame: function (url, params) {
238 if (top.nextLoadModuleUrl) {
239 TYPO3.Backend.ContentContainer.setUrl(top.nextLoadModuleUrl);
240 top.nextLoadModuleUrl = '';
241 } else {
242 var urlToLoad = url + (params ? (url.indexOf('?') !== -1 ? '&' : '?') + params : '');
243 TYPO3.Backend.ContentContainer.setUrl(urlToLoad);
244 }
245 },
246
247 highlightModuleMenuItem: function (module, mainModule) {
248 $('.modulemenu-item.active').removeClass('active');
249 $('#' + module).addClass('active');
250 },
251
252 relativeUrl: function (url) {
253 if (url) {
254 return url.replace(TYPO3.configuration.siteUrl + 'typo3/', '');
255 } else {
256 return '';
257 }
258 },
259
260 // refresh the HTML by fetching the menu again
261 refreshMenu: function () {
262 $.ajax(TYPO3.settings.ajaxUrls['modulemenu']).done(function (result) {
263 $('#menu').replaceWith(result.menu);
264 if (top.currentModuleLoaded) {
265 TYPO3.ModuleMenu.App.highlightModuleMenuItem(top.currentModuleLoaded);
266 }
267 TYPO3.Backend.doLayout();
268 });
269 },
270
271 reloadFrames: function () {
272 TYPO3.Backend.NavigationContainer.refresh();
273 TYPO3.Backend.ContentContainer.refresh();
274 },
275
276 /**
277 * fetches all module menu elements in the local storage that should be collapsed
278 * @returns {*}
279 */
280 getCollapsedMainMenuItems: function () {
281 if (TYPO3.Storage.Persistent.isset('modulemenu')) {
282 return JSON.parse(TYPO3.Storage.Persistent.get('modulemenu'));
283 } else {
284 return {};
285 }
286 },
287
288 /**
289 * adds a module menu item to the local storage
290 * @param item
291 */
292 addCollapsedMainMenuItem: function (item) {
293 var existingItems = this.getCollapsedMainMenuItems();
294 existingItems[item] = true;
295 TYPO3.Storage.Persistent.set('modulemenu', JSON.stringify(existingItems));
296 },
297
298 /**
299 * removes a module menu item from the local storage
300 * @param item
301 */
302 removeCollapseMainMenuItem: function (item) {
303 var existingItems = this.getCollapsedMainMenuItems();
304 delete existingItems[item];
305 TYPO3.Storage.Persistent.set('modulemenu', JSON.stringify(existingItems));
306 }
307
308 };
309 // start the module menu app
310 TYPO3.ModuleMenu.App.initialize();
311 return TYPO3.ModuleMenu;
312 }
313 );