[BUGFIX] Fix broken ImageManipulation wizard
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Resources / Public / JavaScript / AjaxDataHandler.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 * Module: TYPO3/CMS/Backend/AjaxDataHandler
16 * AjaxDataHandler - Javascript functions to work with AJAX and interacting with tce_db.php
17 */
18 define(['jquery',
19 'TYPO3/CMS/Backend/Modal',
20 'TYPO3/CMS/Backend/Icons',
21 'TYPO3/CMS/Backend/Notification',
22 'TYPO3/CMS/Backend/Severity'
23 ], function ($, Modal, Icons, Notification, Severity) {
24 'use strict';
25
26 /**
27 *
28 * @type {{identifier: {hide: string, delete: string, icon: string}}}
29 * @exports TYPO3/CMS/Backend/AjaxDataHandler
30 */
31 var AjaxDataHandler = {
32 identifier: {
33 hide: '.t3js-record-hide',
34 delete: '.t3js-record-delete',
35 icon: '.t3js-icon'
36 }
37 };
38
39 /**
40 * generic function to call from the outside the script and validate directly showing errors
41 *
42 * @param {Object} parameters
43 * @return {Promise<Object>} a jQuery deferred object (promise)
44 */
45 AjaxDataHandler.process = function(parameters) {
46 return AjaxDataHandler._call(parameters).done(function(result) {
47 if (result.hasErrors) {
48 AjaxDataHandler.handleErrors(result);
49 }
50 });
51 };
52
53 /**
54 *
55 */
56 AjaxDataHandler.initialize = function() {
57
58 // HIDE/UNHIDE: click events for all action icons to hide/unhide
59 $(document).on('click', AjaxDataHandler.identifier.hide, function(evt) {
60 evt.preventDefault();
61 var $anchorElement = $(this);
62 var $iconElement = $anchorElement.find(AjaxDataHandler.identifier.icon);
63 var $rowElement = $anchorElement.closest('tr[data-uid]');
64 var params = $anchorElement.data('params');
65
66 // add a spinner
67 AjaxDataHandler._showSpinnerIcon($iconElement);
68
69 // make the AJAX call to toggle the visibility
70 AjaxDataHandler._call(params).done(function(result) {
71 // print messages on errors
72 if (result.hasErrors) {
73 AjaxDataHandler.handleErrors(result);
74 } else {
75 // adjust overlay icon
76 AjaxDataHandler.toggleRow($rowElement);
77 }
78 });
79 });
80
81 // DELETE: click events for all action icons to delete
82 $(document).on('click', AjaxDataHandler.identifier.delete, function(evt) {
83 evt.preventDefault();
84 var $anchorElement = $(this);
85 var $modal = Modal.confirm($anchorElement.data('title'), $anchorElement.data('message'), Severity.warning, [
86 {
87 text: $(this).data('button-close-text') || TYPO3.lang['button.cancel'] || 'Cancel',
88 active: true,
89 btnClass: 'btn-default',
90 name: 'cancel'
91 },
92 {
93 text: $(this).data('button-ok-text') || TYPO3.lang['button.delete'] || 'Delete',
94 btnClass: 'btn-warning',
95 name: 'delete'
96 }
97 ]);
98 $modal.on('button.clicked', function(e) {
99 if (e.target.name === 'cancel') {
100 Modal.dismiss();
101 } else if (e.target.name === 'delete') {
102 Modal.dismiss();
103 AjaxDataHandler.deleteRecord($anchorElement);
104 }
105 });
106 });
107 };
108
109 /**
110 * Toggle row visibility after record has been changed
111 *
112 * @param {Object} $rowElement
113 */
114 AjaxDataHandler.toggleRow = function($rowElement) {
115 var $anchorElement = $rowElement.find(AjaxDataHandler.identifier.hide);
116 var table = $anchorElement.closest('table[data-table]').data('table');
117 var params = $anchorElement.data('params');
118 var nextParams, nextState, iconName;
119
120 if ($anchorElement.data('state') === 'hidden') {
121 nextState = 'visible';
122 nextParams = params.replace('=0', '=1');
123 iconName = 'actions-edit-hide';
124 } else {
125 nextState = 'hidden';
126 nextParams = params.replace('=1', '=0');
127 iconName = 'actions-edit-unhide';
128 }
129 $anchorElement.data('state', nextState).data('params', nextParams);
130
131 // Update tooltip title
132 $anchorElement.tooltip('hide').one('hidden.bs.tooltip', function() {
133 var nextTitle = $anchorElement.data('toggleTitle');
134 // Bootstrap Tooltip internally uses only .attr('data-original-title')
135 $anchorElement
136 .data('toggleTitle', $anchorElement.attr('data-original-title'))
137 .attr('data-original-title', nextTitle)
138 .tooltip('show');
139 });
140
141 var $iconElement = $anchorElement.find(AjaxDataHandler.identifier.icon);
142 Icons.getIcon(iconName, Icons.sizes.small).done(function(icon) {
143 $iconElement.replaceWith(icon);
144 });
145
146 // Set overlay for the record icon
147 var $recordIcon = $rowElement.find('.col-icon ' + AjaxDataHandler.identifier.icon);
148 if (nextState === 'hidden') {
149 Icons.getIcon('miscellaneous-placeholder', Icons.sizes.small, 'overlay-hidden').done(function(icon) {
150 $recordIcon.append($(icon).find('.icon-overlay'));
151 });
152 } else {
153 $recordIcon.find('.icon-overlay').remove();
154 }
155
156 $rowElement.fadeTo('fast', 0.4, function() {
157 $rowElement.fadeTo('fast', 1);
158 });
159 if (table === 'pages') {
160 AjaxDataHandler.refreshPageTree();
161 }
162 };
163
164 /**
165 * delete record by given element (icon in table)
166 * don't call it directly!
167 *
168 * @param {HTMLElement} element
169 */
170 AjaxDataHandler.deleteRecord = function(element) {
171 var $anchorElement = $(element);
172 var params = $anchorElement.data('params');
173 var $iconElement = $anchorElement.find(AjaxDataHandler.identifier.icon);
174
175 // add a spinner
176 AjaxDataHandler._showSpinnerIcon($iconElement);
177
178 // make the AJAX call to toggle the visibility
179 AjaxDataHandler._call(params).done(function(result) {
180 // revert to the old class
181 Icons.getIcon('actions-edit-delete', Icons.sizes.small).done(function(icon) {
182 $iconElement.replaceWith(icon);
183 });
184 // print messages on errors
185 if (result.hasErrors) {
186 AjaxDataHandler.handleErrors(result);
187 } else {
188 var $table = $anchorElement.closest('table[data-table]');
189 var $panel = $anchorElement.closest('.panel');
190 var $panelHeading = $panel.find('.panel-heading');
191 var table = $table.data('table');
192 var $rowElements = $anchorElement.closest('tr[data-uid]');
193 var uid = $rowElements.data('uid');
194 var $translatedRowElements = $table.find('[data-l10nparent=' + uid + ']').closest('tr[data-uid]');
195 $rowElements = $rowElements.add($translatedRowElements);
196
197 $rowElements.fadeTo('slow', 0.4, function() {
198 $rowElements.slideUp('slow', 0, function() {
199 $rowElements.remove();
200 if ($table.find('tbody tr').length === 0) {
201 $panel.slideUp('slow');
202 }
203 });
204 });
205 if ($anchorElement.data('l10parent') === '0' || $anchorElement.data('l10parent') === '') {
206 var count = Number($panelHeading.find('.t3js-table-total-items').html());
207 $panelHeading.find('.t3js-table-total-items').html(count-1);
208 }
209
210 if (table === 'pages') {
211 AjaxDataHandler.refreshPageTree();
212 }
213 }
214 });
215 };
216
217 /**
218 * handle the errors from result object
219 *
220 * @param {Object} result
221 * @private
222 */
223 AjaxDataHandler.handleErrors = function(result) {
224 $.each(result.messages, function(position, message) {
225 Notification.error(message.title, message.message);
226 });
227 };
228
229 /**
230 * refresh the page tree
231 * @private
232 */
233 AjaxDataHandler.refreshPageTree = function() {
234 if (top.TYPO3 && top.TYPO3.Backend && top.TYPO3.Backend.NavigationContainer && top.TYPO3.Backend.NavigationContainer.PageTree) {
235 top.TYPO3.Backend.NavigationContainer.PageTree.refreshTree();
236 }
237 };
238
239 /**
240 * AJAX call to tce_db.php
241 * returns a jQuery Promise to work with
242 *
243 * @param {Object} params
244 * @returns {Object}
245 * @private
246 */
247 AjaxDataHandler._call = function(params) {
248 return $.getJSON(TYPO3.settings.ajaxUrls['record_process'], params);
249 };
250
251 /**
252 * Replace the given icon with a spinner icon
253 *
254 * @param {Object} $iconElement
255 * @private
256 */
257 AjaxDataHandler._showSpinnerIcon = function($iconElement) {
258 Icons.getIcon('spinner-circle-dark', Icons.sizes.small).done(function(icon) {
259 $iconElement.replaceWith(icon);
260 });
261 };
262
263 $(AjaxDataHandler.initialize);
264
265 return AjaxDataHandler;
266 });