diff --git a/typo3/sysext/recordlist/Classes/RecordList/DatabaseRecordList.php b/typo3/sysext/recordlist/Classes/RecordList/DatabaseRecordList.php index c4a8a641ce6acc4928b5846f6f8eeb1a7bd24a22..a6b98666536555413661bb93b4f27d09f9505b17 100644 --- a/typo3/sysext/recordlist/Classes/RecordList/DatabaseRecordList.php +++ b/typo3/sysext/recordlist/Classes/RecordList/DatabaseRecordList.php @@ -915,19 +915,23 @@ class DatabaseRecordList extends AbstractDatabaseRecordList $id_orig = $this->id; $this->id = $row['pid']; } + + $tagAttributes = [ + 'class' => ['t3js-entity'], + 'data-table' => $table, + ]; + // Add special classes for first and last row - $rowSpecial = ''; if ($cc == 1 && $indent == 0) { - $rowSpecial .= ' firstcol'; + $tagAttributes['class'][] = 'firstcol'; } if ($cc == $this->totalRowCount || $cc == $this->iLimit) { - $rowSpecial .= ' lastcol'; + $tagAttributes['class'][] = 'lastcol'; } - - $row_bgColor = ' class="' . $rowSpecial . '"'; - // Overriding with versions background color if any: - $row_bgColor = $row['_CSSCLASS'] ? ' class="' . $row['_CSSCLASS'] . '"' : $row_bgColor; + if (!empty($row['_CSSCLASS'])) { + $tagAttributes['class'] = [$row['_CSSCLASS']]; + } // Incr. counter. $this->counter++; // The icon with link @@ -1033,7 +1037,18 @@ class DatabaseRecordList extends AbstractDatabaseRecordList ) { $theData['_l10nparent_'] = $row[$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']]; } - $rowOutput .= $this->addElement(1, $theIcon, $theData, $row_bgColor); + + $tagAttributes = array_map( + function ($attributeValue) { + if (is_array($attributeValue)) { + return implode(' ', $attributeValue); + } + return $attributeValue; + }, + $tagAttributes + ); + + $rowOutput .= $this->addElement(1, $theIcon, $theData, GeneralUtility::implodeAttributes($tagAttributes, true)); // Finally, return table row element: return $rowOutput; } @@ -1129,16 +1144,12 @@ class DatabaseRecordList extends AbstractDatabaseRecordList $spriteIcon = $this->iconFactory->getIcon('actions-edit-copy', Icon::SIZE_SMALL)->render(); $cells['copyMarked'] = $this->linkClipboardHeaderIcon($spriteIcon, $table, 'setCB', '', $lang->getLL('clip_selectMarked')); // The "edit marked" link: - $editIdList = implode(',', $currentIdList); - $editIdList = '\'+editList(' . GeneralUtility::quoteJSvalue($table) . ',' . GeneralUtility::quoteJSvalue($editIdList) . ')+\''; - $params = 'edit[' . $table . '][' . $editIdList . ']=edit'; - $onClick = BackendUtility::editOnClick('', '', -1); - $onClickArray = explode('?', $onClick, 2); - $lastElement = array_pop($onClickArray); - $onClickArray[] = $params . '&' . $lastElement; - $onClick = implode('?', $onClickArray); - $cells['edit'] = '<a class="btn btn-default" href="#" onclick="' . htmlspecialchars($onClick) . '" title="' - . htmlspecialchars($lang->getLL('clip_editMarked')) . '">' + $editUri = BackendUtility::getModuleUrl('record_edit') + . '&edit[' . $table . '][{entityIdentifiers:editList}]=edit' + . '&returnUrl={T3_THIS_LOCATION}'; + $cells['edit'] = '<a class="btn btn-default t3js-record-edit-multiple" href="#"' + . ' data-uri="' . htmlspecialchars($editUri) . '"' + . ' title="' . htmlspecialchars($lang->getLL('clip_editMarked')) . '">' . $this->iconFactory->getIcon('actions-document-open', Icon::SIZE_SMALL)->render() . '</a>'; // The "Delete marked" link: $cells['delete'] = $this->linkClipboardHeaderIcon( @@ -1215,19 +1226,17 @@ class DatabaseRecordList extends AbstractDatabaseRecordList } // If the table can be edited, add link for editing ALL SHOWN fields for all listed records: if ($permsEdit && $this->table && is_array($currentIdList)) { - $editIdList = implode(',', $currentIdList); + $entityIdentifiers = 'entityIdentifiers'; if ($this->clipNumPane()) { - $editIdList = '\'+editList(' . GeneralUtility::quoteJSvalue($table) . ',' . GeneralUtility::quoteJSvalue($editIdList) . ')+\''; + $entityIdentifiers .= ':editList'; } - $params = 'edit[' . $table . '][' . $editIdList . ']=edit&columnsOnly=' . implode(',', $this->fieldArray); - // we need to build this uri differently, otherwise GeneralUtility::quoteJSvalue messes up the edit list function - $onClick = BackendUtility::editOnClick('', '', -1); - $onClickArray = explode('?', $onClick, 2); - $lastElement = array_pop($onClickArray); - $onClickArray[] = $params . '&' . $lastElement; - $onClick = implode('?', $onClickArray); - $icon .= '<a class="btn btn-default" href="#" onclick="' . htmlspecialchars($onClick) - . '" title="' . htmlspecialchars($lang->getLL('editShownColumns')) . '">' + $editUri = BackendUtility::getModuleUrl('record_edit') + . '&edit[' . $table . '][{' . $entityIdentifiers . '}]=edit' + . '&columnsOnly=' . implode(',', $this->fieldArray) + . '&returnUrl={T3_THIS_LOCATION}'; + $icon .= '<a class="btn btn-default t3js-record-edit-multiple" href="#"' + . ' data-uri="' . htmlspecialchars($editUri) . '"' + . ' title="' . htmlspecialchars($lang->getLL('editShownColumns')) . '">' . $this->iconFactory->getIcon('actions-document-open', Icon::SIZE_SMALL)->render() . '</a>'; $icon = '<div class="btn-group" role="group">' . $icon . '</div>'; } @@ -1261,20 +1270,18 @@ class DatabaseRecordList extends AbstractDatabaseRecordList // If the table can be edited, add link for editing THIS field for all // listed records: if ($this->isEditable($table) && $permsEdit && $GLOBALS['TCA'][$table]['columns'][$fCol]) { - $editIdList = implode(',', $currentIdList); + $entityIdentifiers = 'entityIdentifiers'; if ($this->clipNumPane()) { - $editIdList = '\'+editList(' . GeneralUtility::quoteJSvalue($table) . ',' . GeneralUtility::quoteJSvalue($editIdList) . ')+\''; + $entityIdentifiers .= ':editList'; } - $params = 'edit[' . $table . '][' . $editIdList . ']=edit&columnsOnly=' . $fCol; - // we need to build this uri differently, otherwise GeneralUtility::quoteJSvalue messes up the edit list function - $onClick = BackendUtility::editOnClick('', '', -1); - $onClickArray = explode('?', $onClick, 2); - $lastElement = array_pop($onClickArray); - $onClickArray[] = $params . '&' . $lastElement; - $onClick = implode('?', $onClickArray); + $editUri = BackendUtility::getModuleUrl('record_edit') + . '&edit[' . $table . '][{' . $entityIdentifiers . '}]=edit' + . '&columnsOnly=' . $fCol + . '&returnUrl={T3_THIS_LOCATION}'; $iTitle = sprintf($lang->getLL('editThisColumn'), $sortLabel); - $theData[$fCol] .= '<a class="btn btn-default" href="#" onclick="' . htmlspecialchars($onClick) - . '" title="' . htmlspecialchars($iTitle) . '">' + $theData[$fCol] .= '<a class="btn btn-default t3js-record-edit-multiple" href="#"' + . ' data-uri="' . htmlspecialchars($editUri) . '"' + . ' title="' . htmlspecialchars($iTitle) . '">' . $this->iconFactory->getIcon('actions-document-open', Icon::SIZE_SMALL)->render() . '</a>'; } if (strlen($theData[$fCol]) > 0) { diff --git a/typo3/sysext/recordlist/Resources/Public/JavaScript/Recordlist.js b/typo3/sysext/recordlist/Resources/Public/JavaScript/Recordlist.js index d1a5dc179de838bc8062cff1499674eef6393049..e421d1ad5b430a40763dd4f0a6205e72fc402f44 100644 --- a/typo3/sysext/recordlist/Resources/Public/JavaScript/Recordlist.js +++ b/typo3/sysext/recordlist/Resources/Public/JavaScript/Recordlist.js @@ -19,23 +19,23 @@ define(['jquery', 'TYPO3/CMS/Backend/Storage', 'TYPO3/CMS/Backend/Icons'], funct 'use strict'; /** - * - * @type {{identifier: {toggle: string, icons: {collapse: string, expand: string}}}} + * @type {Object} * @exports TYPO3/CMS/Recordlist/Recordlist */ var Recordlist = { identifier: { + entity: '.t3js-entity', toggle: '.t3js-toggle-recordlist', icons: { collapse: 'actions-view-list-collapse', - expand: 'actions-view-list-expand' + expand: 'actions-view-list-expand', + editMultiple: '.t3js-record-edit-multiple' } } }; /** - * - * @param {Event} e + * @param {MouseEvent} e */ Recordlist.toggleClick = function(e) { e.preventDefault(); @@ -67,9 +67,61 @@ define(['jquery', 'TYPO3/CMS/Backend/Storage', 'TYPO3/CMS/Backend/Icons'], funct }); }; - $(function() { - $(document).on('click', Recordlist.identifier.toggle, Recordlist.toggleClick); - }); + /** + * Handles editing multiple records. + * + * @param {MouseEvent} event + */ + Recordlist.onEditMultiple = function(event) { + event.preventDefault(); + + var $tableContainer, tableName, entityIdentifiers, uri, patterns; + + $tableContainer = $(this).closest('[data-table]'); + if ($tableContainer.length === 0) { + return; + } + + uri = $(this).data('uri'); + tableName = $tableContainer.data('table'); + entityIdentifiers = $tableContainer + .find(Recordlist.identifier.entity + '[data-uid][data-table="' + tableName + '"]') + .map(function(index, entity) { return $(entity).data('uid'); }) + .toArray() + .join(','); + + patterns = uri.match(/{[^}]+}/g); + $.each(patterns, function(patternIndex, pattern) { + var expression = pattern.substr(1, pattern.length - 2); + var pipes = expression.split(':'); + var name = pipes.shift(); + var value; + + switch (name) { + case 'entityIdentifiers': + value = entityIdentifiers; + break; + case 'T3_THIS_LOCATION': + value = T3_THIS_LOCATION; + break; + default: + return; + } + + $.each(pipes, function(pipeIndex, pipe) { + if (pipe === 'editList') { + value = editList(tableName, value); + } + }); + + uri = uri.replace(pattern, value); + }); + + window.location.href = uri; + }; + + $(document).on('click', Recordlist.identifier.toggle, Recordlist.toggleClick); + $(document).on('click', Recordlist.identifier.icons.editMultiple, Recordlist.onEditMultiple); return Recordlist; });