From 7ef327081a503fc2e4e60b6d2cb413943f68469e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Uzna=C5=84ski?= <l.uznanski@macopedia.pl> Date: Wed, 29 Nov 2017 10:37:15 +0100 Subject: [PATCH] [FEATURE] Add button to select all records Add and handle button to select all records from all pages in recycler. Right now, there is pagination, which means that you can select 50 records max. Resolves: #81310 Releases: master Change-Id: Icfc0c93e5cff5cd9573a6a39b615ce0c6e1d273c Reviewed-on: https://review.typo3.org/54849 Tested-by: TYPO3com <no-reply@typo3.com> Reviewed-by: Tobi Kretschmann <tobi@tobishome.de> Tested-by: Tobi Kretschmann <tobi@tobishome.de> Reviewed-by: Joerg Boesche <typo3@joergboesche.de> Tested-by: Joerg Boesche <typo3@joergboesche.de> Reviewed-by: Steffen Frese <steffenf14@gmail.com> Reviewed-by: Jigal van Hemert <jigal.van.hemert@typo3.org> Tested-by: Jigal van Hemert <jigal.van.hemert@typo3.org> --- ...dButtonToSelectAllRecordsInEXTrecycler.rst | 20 + .../Controller/DeletedRecordsController.php | 29 +- .../Controller/RecyclerAjaxController.php | 11 +- .../Controller/RecyclerModuleController.php | 2 +- .../Resources/Private/Language/locallang.xlf | 12 + .../Templates/RecyclerModule/Index.html | 45 ++- .../Resources/Public/JavaScript/Recycler.js | 378 +++++++++++++++--- 7 files changed, 428 insertions(+), 69 deletions(-) create mode 100644 typo3/sysext/core/Documentation/Changelog/master/Feature-54849-AddButtonToSelectAllRecordsInEXTrecycler.rst diff --git a/typo3/sysext/core/Documentation/Changelog/master/Feature-54849-AddButtonToSelectAllRecordsInEXTrecycler.rst b/typo3/sysext/core/Documentation/Changelog/master/Feature-54849-AddButtonToSelectAllRecordsInEXTrecycler.rst new file mode 100644 index 000000000000..024f6071c220 --- /dev/null +++ b/typo3/sysext/core/Documentation/Changelog/master/Feature-54849-AddButtonToSelectAllRecordsInEXTrecycler.rst @@ -0,0 +1,20 @@ +.. include:: ../../Includes.txt + +================================================================== +Feature: #54849 - Add button to select all records in EXT:recycler +================================================================== + +See :issue:`54849` + +Description +=========== + +Add button to select all records from all pages in EXT:recycler. + + +Impact +====== + +All TYPO3 installations where EXT:recycler is enabled. + +.. index:: Backend, ext:recycler \ No newline at end of file diff --git a/typo3/sysext/recycler/Classes/Controller/DeletedRecordsController.php b/typo3/sysext/recycler/Classes/Controller/DeletedRecordsController.php index d6554d39b738..7dbfbc6824a1 100644 --- a/typo3/sysext/recycler/Classes/Controller/DeletedRecordsController.php +++ b/typo3/sysext/recycler/Classes/Controller/DeletedRecordsController.php @@ -50,12 +50,10 @@ class DeletedRecordsController * Transforms the rows for the deleted records * * @param array $deletedRowsArray Array with table as key and array with all deleted rows - * @param int $totalDeleted Number of deleted records in total * @return array JSON array */ - public function transform($deletedRowsArray, $totalDeleted) + public function transform($deletedRowsArray) { - $total = 0; $jsonArray = [ 'rows' => [] ]; @@ -65,7 +63,6 @@ class DeletedRecordsController $iconFactory = GeneralUtility::makeInstance(IconFactory::class); foreach ($deletedRowsArray as $table => $rows) { - $total += count($deletedRowsArray[$table]); foreach ($rows as $row) { $pageTitle = $this->getPageTitle((int)$row['pid']); $backendUserName = $this->getBackendUser((int)$row[$GLOBALS['TCA'][$table]['ctrl']['cruser_id']]); @@ -92,7 +89,29 @@ class DeletedRecordsController } } } - $jsonArray['total'] = $totalDeleted; + return $jsonArray; + } + + /** + * Transforms the rows for the deleted records + * + * @param array $deletedRowsArray Array with table as key and array with all deleted rows + * @return array JSON array + */ + public function transformSmallAddTotal(array $deletedRowsArray): array + { + $jsonArray = []; + $total = 0; + if (is_array($deletedRowsArray)) { + foreach ($deletedRowsArray as $table => $rows) { + foreach ($rows as $row) { + $key = $table . ':' . $row['uid']; + $jsonArray['rows'][$key] = 1; + $total++; + } + } + } + $jsonArray['total'] = $total; return $jsonArray; } diff --git a/typo3/sysext/recycler/Classes/Controller/RecyclerAjaxController.php b/typo3/sysext/recycler/Classes/Controller/RecyclerAjaxController.php index 7a2759c1593c..fac6a2f2251b 100644 --- a/typo3/sysext/recycler/Classes/Controller/RecyclerAjaxController.php +++ b/typo3/sysext/recycler/Classes/Controller/RecyclerAjaxController.php @@ -54,7 +54,7 @@ class RecyclerAjaxController $this->conf['filterTxt'] = GeneralUtility::_GP('filterTxt') ? GeneralUtility::_GP('filterTxt') : ''; $this->conf['startUid'] = GeneralUtility::_GP('startUid') ? (int)GeneralUtility::_GP('startUid') : 0; $this->conf['depth'] = GeneralUtility::_GP('depth') ? (int)GeneralUtility::_GP('depth') : 0; - $this->conf['records'] = GeneralUtility::_GP('records') ? GeneralUtility::_GP('records') : null; + $this->conf['records'] = json_decode(GeneralUtility::_GP('records') ? GeneralUtility::_GP('records') : '[]', true); $this->conf['recursive'] = GeneralUtility::_GP('recursive') ? (bool)GeneralUtility::_GP('recursive') : false; } @@ -94,11 +94,13 @@ class RecyclerAjaxController $deletedRowsArray = $model->getDeletedRows(); $model = GeneralUtility::makeInstance(DeletedRecords::class); - $totalDeleted = $model->getTotalCount($this->conf['startUid'], $this->conf['table'], $this->conf['depth'], $this->conf['filterTxt']); + $model->loadData($this->conf['startUid'], $this->conf['table'], $this->conf['depth'], null, $this->conf['filterTxt']); + $deletedRowsArrayAll = $model->getDeletedRows(); /* @var $controller DeletedRecordsController */ $controller = GeneralUtility::makeInstance(DeletedRecordsController::class); - $recordsArray = $controller->transform($deletedRowsArray, $totalDeleted); + $recordsArray = $controller->transform($deletedRowsArray); + $recordsArrayAll = $controller->transformSmallAddTotal($deletedRowsArrayAll); $modTS = $this->getBackendUser()->getTSConfig('mod.recycler'); $allowDelete = $this->getBackendUser()->isAdmin() ? true : (bool)$modTS['properties']['allowDelete']; @@ -109,7 +111,8 @@ class RecyclerAjaxController $view->assign('total', $recordsArray['total']); $content = [ 'rows' => $view->render(), - 'totalItems' => $recordsArray['total'] + 'totalItems' => $recordsArrayAll['total'], + 'allTheRows' => $recordsArrayAll['rows'] ]; break; case 'undoRecords': diff --git a/typo3/sysext/recycler/Classes/Controller/RecyclerModuleController.php b/typo3/sysext/recycler/Classes/Controller/RecyclerModuleController.php index edd952867a10..06a003e943e8 100644 --- a/typo3/sysext/recycler/Classes/Controller/RecyclerModuleController.php +++ b/typo3/sysext/recycler/Classes/Controller/RecyclerModuleController.php @@ -55,7 +55,7 @@ class RecyclerModuleController extends ActionController /** * @var int */ - protected $recordsPageLimit = 50; + protected $recordsPageLimit = 25; /** * @var int diff --git a/typo3/sysext/recycler/Resources/Private/Language/locallang.xlf b/typo3/sysext/recycler/Resources/Private/Language/locallang.xlf index e0812d710c31..abc493c5c6b2 100644 --- a/typo3/sysext/recycler/Resources/Private/Language/locallang.xlf +++ b/typo3/sysext/recycler/Resources/Private/Language/locallang.xlf @@ -18,6 +18,18 @@ <trans-unit id="button.delete"> <source>Delete</source> </trans-unit> + <trans-unit id="button.selectall"> + <source>Select all records from all pages</source> + </trans-unit> + <trans-unit id="button.deselectall"> + <source>Deselect all</source> + </trans-unit> + <trans-unit id="button.selectallamount"> + <source>Select all records ({0}) from all pages</source> + </trans-unit> + <trans-unit id="button.selectallamountrest"> + <source>Select the rest of the records ({0}) from all pages</source> + </trans-unit> <trans-unit id="button.deleteselected"> <source>Delete {0} records</source> </trans-unit> diff --git a/typo3/sysext/recycler/Resources/Private/Templates/RecyclerModule/Index.html b/typo3/sysext/recycler/Resources/Private/Templates/RecyclerModule/Index.html index 053e91cf4144..d916dfd25841 100644 --- a/typo3/sysext/recycler/Resources/Private/Templates/RecyclerModule/Index.html +++ b/typo3/sysext/recycler/Resources/Private/Templates/RecyclerModule/Index.html @@ -44,21 +44,44 @@ </tbody> </table> </div> + <div class="progress progress-bar-notice alert-loading" style="display: none"> + <div class="t3js-progressbar progress-bar progress-bar-striped active m-3" + role="progressbar" aria-valuenow="100" aria-valuemin="0" aria-valuemax="100" + style="width: 100%; height:25px; "> + <span class="sr-only">Loading...</span> + </div> + </div> <div> - <button class="btn btn-default disabled" data-action="massundo"> - <core:icon identifier="actions-edit-undo" /> - <span class="text"> - <f:translate key="button.undo" /> - </span> - </button> - <f:if condition="{allowDelete}"> - <button class="btn btn-default disabled" data-action="massdelete"> - <core:icon identifier="actions-edit-delete" /> + + <div> + <button class="btn btn-default disabled" data-action="selectall"> + <core:icon identifier="actions-document-select" /> + <span class="text"> + <f:translate key="LLL:EXT:recycler/Resources/Private/Language/locallang.xlf:button.selectall"/> + </span> + </button> + <button class="btn btn-default disabled" data-action="deselectall"> <span class="text"> - <f:translate key="button.delete" /> + <f:translate key="LLL:EXT:recycler/Resources/Private/Language/locallang.xlf:button.deselectall"/> </span> </button> - </f:if> + </div> + <div> + <button class="btn btn-default disabled" data-action="massundo"> + <core:icon identifier="actions-edit-undo" /> + <span class="text"> + <f:translate key="button.undo" /> + </span> + </button> + <f:if condition="{allowDelete}"> + <button class="btn btn-default disabled" data-action="massdelete"> + <core:icon identifier="actions-edit-delete" /> + <span class="text"> + <f:translate key="button.delete" /> + </span> + </button> + </f:if> + </div> </div> <nav> </nav> diff --git a/typo3/sysext/recycler/Resources/Public/JavaScript/Recycler.js b/typo3/sysext/recycler/Resources/Public/JavaScript/Recycler.js index 1128c58e5562..f2a34328439f 100644 --- a/typo3/sysext/recycler/Resources/Public/JavaScript/Recycler.js +++ b/typo3/sysext/recycler/Resources/Public/JavaScript/Recycler.js @@ -41,7 +41,10 @@ define(['jquery', reloadAction: 'a[data-action=reload]', massUndo: 'button[data-action=massundo]', massDelete: 'button[data-action=massdelete]', - toggleAll: '.t3js-toggle-all' + selectAll: 'button[data-action=selectall]', + deselectAll: 'button[data-action=deselectall]', + toggleAll: '.t3js-toggle-all', + progressBar: '#recycler-index .progress.progress-bar-notice.alert-loading' }, elements: {}, // filled in getElements() paging: { @@ -70,7 +73,10 @@ define(['jquery', $reloadAction: $(Recycler.identifiers.reloadAction), $massUndo: $(Recycler.identifiers.massUndo), $massDelete: $(Recycler.identifiers.massDelete), - $toggleAll: $(Recycler.identifiers.toggleAll) + $selectAll: $(Recycler.identifiers.selectAll), + $deselectAll: $(Recycler.identifiers.deselectAll), + $toggleAll: $(Recycler.identifiers.toggleAll), + $progressBar: $(Recycler.identifiers.progressBar) }; }; @@ -108,6 +114,7 @@ define(['jquery', // changing "depth" Recycler.elements.$depthSelector.on('change', function() { $.when(Recycler.loadAvailableTables()).done(function() { + Recycler.clearMarked(); Recycler.loadDeletedElements(); }); }); @@ -115,6 +122,7 @@ define(['jquery', // changing "table" Recycler.elements.$tableSelector.on('change', function() { Recycler.paging.currentPage = 1; + Recycler.clearMarked(); Recycler.loadDeletedElements(); }); @@ -159,6 +167,7 @@ define(['jquery', if (reload) { Recycler.loadDeletedElements(); + Recycler.loadMarked(); } }); @@ -189,14 +198,31 @@ define(['jquery', }); // checkboxes in the table - Recycler.elements.$toggleAll.on('click', function() { - Recycler.allToggled = !Recycler.allToggled; - $('input[type="checkbox"]').prop('checked', Recycler.allToggled).trigger('change'); - }); Recycler.elements.$recyclerTable.on('change', 'tr input[type=checkbox]', Recycler.handleCheckboxSelects); - Recycler.elements.$massUndo.on('click', Recycler.undoRecord); - Recycler.elements.$massDelete.on('click', Recycler.deleteRecord); + Recycler.elements.$toggleAll.on('click', Recycler.toggleAll); + + Recycler.elements.$massUndo.on('click', function() { + if (!$(this).hasClass('disabled')) { + Recycler.undoRecord(); + } + }); + Recycler.elements.$massDelete.on('click', function() { + if (!$(this).hasClass('disabled')) { + Recycler.deleteRecord(); + } + }); + Recycler.elements.$selectAll.on('click', function() { + if (!$(this).hasClass('disabled')) { + Recycler.selectAll(); + } + }); + Recycler.elements.$deselectAll.on('click', function() { + if (!$(this).hasClass('disabled')) { + Recycler.deselectAll(); + } + + }); }; /** @@ -226,46 +252,40 @@ define(['jquery', table = $tr.data('table'), uid = $tr.data('uid'), record = table + ':' + uid; - if ($checkbox.prop('checked')) { - Recycler.markedRecordsForMassAction.push(record); - $tr.addClass('warning'); - } else { - var index = Recycler.markedRecordsForMassAction.indexOf(record); - if (index > -1) { - Recycler.markedRecordsForMassAction.splice(index, 1); - } - $tr.removeClass('warning'); - } - - if (Recycler.markedRecordsForMassAction.length > 0) { - if (Recycler.elements.$massUndo.hasClass('disabled')) { - Recycler.elements.$massUndo.removeClass('disabled'); - } - if (Recycler.elements.$massDelete.hasClass('disabled')) { - Recycler.elements.$massDelete.removeClass('disabled'); + if (!Recycler.markedRecordsForMassAction[record]) { + Recycler.addRecord(record); + $tr.addClass('warning'); } - - var btnTextUndo = Recycler.createMessage(TYPO3.lang['button.undoselected'], [Recycler.markedRecordsForMassAction.length]), - btnTextDelete = Recycler.createMessage(TYPO3.lang['button.deleteselected'], [Recycler.markedRecordsForMassAction.length]); - - Recycler.elements.$massUndo.find('span.text').text(btnTextUndo); - Recycler.elements.$massDelete.find('span.text').text(btnTextDelete); - } else { - Recycler.resetMassActionButtons(); + if (!!Recycler.markedRecordsForMassAction[record]) { + Recycler.subtractRecord(record); + $tr.removeClass('warning'); + } } + Recycler.selectAllRefresh(); }; + /** * Resets the mass action state */ Recycler.resetMassActionButtons = function() { - Recycler.markedRecordsForMassAction = []; + if (!!Recycler.markedRecordsForMassAction) { + Recycler.persistMarked(Recycler.markedRecordsForMassAction); + } else { + Recycler.markedRecordsForMassAction = {}; + } + Recycler.elements.$massUndo.addClass('disabled'); Recycler.elements.$massUndo.find('span.text').text(TYPO3.lang['button.undo']); Recycler.elements.$massDelete.addClass('disabled'); Recycler.elements.$massDelete.find('span.text').text(TYPO3.lang['button.delete']); + + Recycler.elements.$selectAll.addClass('disabled'); + Recycler.elements.$selectAll.find('span.text').text(TYPO3.lang['button.selectall']); + Recycler.elements.$deselectAll.addClass('disabled'); + Recycler.elements.$deselectAll.find('span.text').text(TYPO3.lang['button.deselectall']); }; /** @@ -286,6 +306,7 @@ define(['jquery', NProgress.start(); Recycler.elements.$tableSelector.val(''); Recycler.paging.currentPage = 1; + Recycler.markedRecordsCounter = 0; }, success: function(data) { var tables = []; @@ -336,13 +357,24 @@ define(['jquery', beforeSend: function() { NProgress.start(); Recycler.resetMassActionButtons(); + Recycler.selectAllDataShort = []; + Recycler.currentDataCount = 0; + + /** if there are any checkboxes and corresponding buttons, hide them while new content arrives */ + Recycler.showLoading(); }, success: function(data) { + var totalItems = data.totalItems; + Recycler.elements.$tableBody.html(data.rows); - Recycler.buildPaginator(data.totalItems); + Recycler.buildPaginator(totalItems); + Recycler.currentDataCount = totalItems; + + Recycler.selectAllDataShort = data.allTheRows; }, complete: function() { NProgress.done(); + Recycler.selectAllRefresh(); } }); }; @@ -354,13 +386,12 @@ define(['jquery', if (TYPO3.settings.Recycler.deleteDisable) { return; } - var $tr = $(this).parents('tr'), isMassDelete = $tr.parent().prop('tagName') !== 'TBODY'; // deleteRecord() was invoked by the mass delete button var records, message; if (isMassDelete) { - records = Recycler.markedRecordsForMassAction; + records = Recycler.returnProperMarkedArray(); message = TYPO3.lang['modal.massdelete.text']; } else { var uid = $tr.data('uid'), @@ -382,7 +413,11 @@ define(['jquery', text: TYPO3.lang['button.delete'], btnClass: 'btn-danger', trigger: function() { - Recycler.callAjaxAction('delete', typeof records === 'object' ? records : [records], isMassDelete); + Recycler.callAjaxAction( + 'delete', + typeof records === 'object' ? records : [records], + isMassDelete + ) } } ]); @@ -397,7 +432,7 @@ define(['jquery', var records, messageText, recoverPages; if (isMassUndo) { - records = Recycler.markedRecordsForMassAction; + records = Recycler.returnProperMarkedArray(); messageText = TYPO3.lang['modal.massundo.text']; recoverPages = true; } else { @@ -427,7 +462,7 @@ define(['jquery', ) ); } else { - $message = messageText; + $message = $('<div />').text(messageText); } Modal.confirm(TYPO3.lang['modal.undo.header'], $message, Severity.ok, [ @@ -441,7 +476,13 @@ define(['jquery', text: TYPO3.lang['button.undo'], btnClass: 'btn-success', trigger: function() { - Recycler.callAjaxAction('undo', typeof records === 'object' ? records : [records], isMassUndo, $message.find('#undo-recursive').prop('checked') ? 1 : 0); + Recycler.callAjaxAction( + 'undo', + // typeof records === 'object' ? records : [records], + records, + isMassUndo, + $message.find('#undo-recursive').prop('checked') ? 1 : 0 + ); } } ]); @@ -456,10 +497,12 @@ define(['jquery', */ Recycler.callAjaxAction = function(action, records, isMassAction, recursive) { var data = { - records: records, + records: JSON.stringify(records), action: '' }, - reloadPageTree = false; + reloadPageTree = false, + oldCount = Recycler.markedRecordsCounter, + error = 0; if (action === 'undo') { data.action = 'undoRecords'; data.recursive = recursive ? 1 : 0; @@ -470,18 +513,23 @@ define(['jquery', return; } + $.ajax({ url: TYPO3.settings.ajaxUrls['recycler'], dataType: 'json', data: data, + method: 'POST', beforeSend: function() { NProgress.start(); + /** if there are any checkboxes and corresponding buttons, hide them while new content arrives */ + Recycler.showLoading(); }, success: function(data) { if (data.success) { Notification.success('', data.message); } else { Notification.error('', data.message); + error = 1; } // reload recycler data @@ -489,16 +537,22 @@ define(['jquery', $.when(Recycler.loadAvailableTables()).done(function() { Recycler.loadDeletedElements(); - if (isMassAction) { - Recycler.resetMassActionButtons(); + if (isMassAction && !error) { + Recycler.clearMarked(); + } else { + if (!error) { + if (!!Recycler.markedRecordsForMassAction[records]) { + Recycler.subtractRecord(records); + oldCount--; + } + Recycler.markedRecordsCounter = oldCount; + } } if (reloadPageTree) { Recycler.refreshPageTree(); } - // Reset toggle state - Recycler.allToggled = false; }); }, complete: function() { @@ -592,6 +646,235 @@ define(['jquery', Recycler.elements.$paginator.html($ul); }; + /** + * Select all records + */ + Recycler.selectAll = function() { + if (Recycler.currentDataCount > 0) { + Recycler.elements.$selectAll.addClass('disabled'); + + Recycler.markedRecordsForMassAction = {}; + + Recycler.markedRecordsCounter = Recycler.currentDataCount; + Recycler.markedRecordsForMassAction = $.extend(true, {}, Recycler.selectAllDataShort); + + Recycler.elements.$selectAll.removeClass('disabled'); + + Recycler.selectAllRefresh(); + } + }; + + /** + * Deselect all records and return everything to clean state + */ + Recycler.deselectAll = function() { + Recycler.elements.$deselectAll.addClass('disabled'); + + Recycler.clearMarked(); + Recycler.resetMassActionButtons(); + Recycler.selectAllRefresh(); + + Recycler.elements.$selectAll.removeClass('disabled'); + }; + + /** + * Adjusts mass action buttons to user's action + */ + Recycler.selectAllRefresh = function() { + var totalItems, btnTextSelectAll = '', + btnDisabledArr = ['$deselectAll', '$massUndo', '$massDelete']; + + Recycler.hideLoading(); + Recycler.persistMarked(Recycler.markedRecordsForMassAction); + Recycler.refreshCheckboxes(); + + /** if any checkboxes are checked change mass action buttons state */ + if (Recycler.markedRecordsCounter > 0) { + var recordsLength = Recycler.markedRecordsCounter, + btnTextDelete = Recycler.createMessage(TYPO3.lang['button.deleteselected'], [recordsLength]), + btnTextUndo = Recycler.createMessage(TYPO3.lang['button.undoselected'], [recordsLength]); + + /** if there are any records unselected show the amount */ + if (!!Recycler.currentDataCount && ( (Recycler.currentDataCount-Recycler.markedRecordsCounter) > 0 )) { + if (Recycler.markedRecordsCounter === 0) { + btnTextSelectAll = Recycler.createMessage(TYPO3.lang['button.selectallamount'], [Recycler.currentDataCount]); + + } else { + var rest = Recycler.currentDataCount - Recycler.markedRecordsCounter; + + btnTextSelectAll = Recycler.createMessage(TYPO3.lang['button.selectallamountrest'], [rest]); + } + } else { + btnTextSelectAll = Recycler.createMessage(TYPO3.lang['button.selectall']) + } + + /** if total amount of records from ajax is bigger than amount of currently selected records enable selectall */ + if (!!Recycler.currentDataCount && (Recycler.currentDataCount > Recycler.markedRecordsCounter)) { + if (Recycler.elements.$selectAll.hasClass('disabled')) { + Recycler.elements.$selectAll.removeClass('disabled'); + } + } else { + Recycler.elements.$selectAll.addClass('disabled'); + } + + /** enable mass action buttons (without selectall)*/ + $.each(btnDisabledArr, (function(index, value) { + if (Recycler.elements[value].hasClass('disabled')) { + Recycler.elements[value].removeClass('disabled'); + } + })); + + Recycler.elements.$selectAll.find('span.text').text(btnTextSelectAll); + Recycler.elements.$massDelete.find('span.text').text(btnTextDelete); + Recycler.elements.$massUndo.find('span.text').text(btnTextUndo); + + } else { + + /** default states of mass action buttons if none checkboxes are checked */ + if (!!Recycler.currentDataCount) { + totalItems = Recycler.currentDataCount; + btnTextSelectAll = Recycler.createMessage(TYPO3.lang['button.selectallamount'], [totalItems]) + } else { + btnTextSelectAll = Recycler.createMessage(TYPO3.lang['button.selectall']) + } + + /** disable all action buttons (without selectall) */ + $.each(btnDisabledArr, (function(index, value) { + if (!Recycler.elements[value].hasClass('disabled')) { + Recycler.elements[value].addClass('disabled'); + } + })); + + Recycler.elements.$massUndo.find('span.text').text(TYPO3.lang['button.undo']); + Recycler.elements.$massDelete.find('span.text').text(TYPO3.lang['button.delete']); + Recycler.elements.$selectAll.find('span.text').text(btnTextSelectAll); + Recycler.elements.$selectAll.removeClass('disabled'); + } + }; + + /** + * Show feedback while loading new content + */ + Recycler.showLoading = function() { + Recycler.elements.$recyclerTable.parent().hide(); + Recycler.elements.$progressBar.show(); + Recycler.resetMassActionButtons(); + }; + + Recycler.hideLoading = function() { + Recycler.elements.$recyclerTable.parent().show(); + Recycler.elements.$progressBar.hide(); + }; + + /** + * Check and uncheck checkboxes based on Recycler.markedRecordsForMassAction obj + */ + Recycler.refreshCheckboxes = function() { + var $checkboxes = Recycler.elements.$tableBody.find('input[type="checkbox"]'); + $.each($checkboxes, function(index, value) { + var $checkbox = $(value), + tableUid = Recycler.createTableUid($checkbox); + + if (!!Recycler.markedRecordsForMassAction[tableUid]) { + $checkbox.prop('checked', true).parents('tr').addClass('warning'); + } else { + $checkbox.prop('checked', false).parents('tr').removeClass('warning'); + } + }); + }; + + /** + * Toggles checkboxes of all records from current page + */ + Recycler.toggleAll = function() { + var $checkboxes = Recycler.elements.$tableBody.find('input[type="checkbox"]'), + markedRecordsOnThisPage = Recycler.countMarkedRecordsOnThisPage(), + allToggled = (markedRecordsOnThisPage === $checkboxes.length); + + $.each($checkboxes, function(index, value) { + var tableUid = Recycler.createTableUid($(value)); + if (!Recycler.markedRecordsForMassAction[tableUid]) { + if (!allToggled) { + Recycler.addRecord(tableUid); + } + } else { + if (allToggled) { + Recycler.subtractRecord(tableUid); + } + } + }); + Recycler.selectAllRefresh(); + }; + + Recycler.subtractRecord = function(tableUid) { + delete Recycler.markedRecordsForMassAction[tableUid]; + Recycler.markedRecordsCounter--; + }; + + Recycler.addRecord = function(tableUid) { + /** it should have truthy value */ + Recycler.markedRecordsForMassAction[tableUid] = 1; + Recycler.markedRecordsCounter++; + }; + + /** + * Function to store Recycler.markedRecordsForMassAction + * @param data + */ + Recycler.persistMarked = function(data) { + Recycler.persist = {}; + Recycler.persist = data; + }; + /** + * Function to load Recycler.markedRecordsForMassAction from Recycler.persist + */ + Recycler.loadMarked = function() { + Recycler.markedRecordsForMassAction = Recycler.persist; + Recycler.persist = {}; + }; + + /** + * clear everything about selecting records + */ + Recycler.clearMarked = function() { + Recycler.markedRecordsForMassAction = {}; + Recycler.persist = {}; + Recycler.markedRecordsCounter = 0; + }; + + /** + * Changing obj into proper array for ajax + * @returns {string[]} + */ + Recycler.returnProperMarkedArray = function() { + return Object.keys(Recycler.markedRecordsForMassAction); + }; + + /** + * Counts checkboxes which have corresponding entry in Recycler.markedRecordsForMassAction + * @returns {number} + */ + Recycler.countMarkedRecordsOnThisPage = function() { + var $checkboxes = Recycler.elements.$tableBody.find('input[type="checkbox"]'), + countOnPage = 0; + $.each($checkboxes, function(index,value) { + var tableUid = Recycler.createTableUid($(value)); + + if (!!Recycler.markedRecordsForMassAction[tableUid]) { + countOnPage++; + } + }); + return countOnPage; + }; + + Recycler.createTableUid = function($row) { + var $checkbox = $($row), + $tr = $checkbox.parents('tr'), + table = $tr.data('table'), + uid = $tr.data('uid'); + return table + ':' + uid; + }; + /** * Changes the markup of a pagination action being disabled */ @@ -600,6 +883,5 @@ define(['jquery', }; $(Recycler.initialize); - return Recycler; }); -- GitLab