Commit 27881b60 authored by Benjamin Franzke's avatar Benjamin Franzke Committed by Benni Mack
Browse files

[TASK] Update bootstrap javascript to 5.0.0-beta1

Bootstrap v5 – introduced in #92616 – was added with CCS from beta1 but
JavaScript from alpha2. bootstrap.bundle.js was manually wrapped
into a AMD closure, and because bootstrap 5.0.0-beta1 contains alot of
changes regarding data tags, it couldn't be updated in the initial
patch.

Bootstrap is now bundled using rollup using the ES6 sources in order
to allow for automatic updates through `grunt build`.

popperjs – previously bundled into bootstrap distributed files –
is now added as dependency. The bootstap ES6 sources, that we now use
through rollup, do not bundle this external dependency (for good reasons).

Dependency added with:

   yarn add @popperjs/core

Further adaptions contained in this change to ensure beta1 compatibility:

a) Carousel "item" to "carousel-item" class migration
b) $.fn.modal(options) does no longer imply $.fn.modal('show')
c) Fix panels, both JS and CSS (card-group can't be used here)
d) All bootstrap data- tags are migrated to data-bs-.
   (see https://github.com/twbs/bootstrap/pull/31827)
   Migrated with

   # renderes a sed substition with the help of a nested sed from all the
   # data-bs attributes that where changed in the twbs/bootstrap commit
   git grep -l data- | xargs sed -i $( \
        curl -s \
        https://patch-diff.githubusercontent.com/raw/twbs/bootstrap/pull/31827.patch | \
        sed 's/data-bs-[a-z-]*/\n&\n/g' | grep "data-bs-[a-z-]" | \
        sort | uniq | \
        sed 's/data-bs-\(.*\)\([^a-z-]\|$\)/ -e s\/data-\1\\\([^a-z-]\\\)\/data-bs-\1\\1\/g -e s\/data('"'"'\1'"'"')\/data('"'"'bs-\1'"'"')\/g/g' \
   )

   # Revert false positives from the above auto-replacement
   git checkout -- typo3/sysext/core/Documentation/Changelog/ \
        typo3/sysext/backend/Classes/Form/Container/FlexFormContainerContainer.php \
        Build/Sources/TypeScript/backend/Resources/Public/TypeScript/LiveSearch.ts \
        Build/Sources/TypeScript/backend/Resources/Public/TypeScript/FormEngineFlexForm.ts \
        Build/Sources/TypeScript/install/Resources/Public/TypeScript/Module/Settings/ExtensionConfiguration.ts \
        Build/Sources/Sass/typo3/_element_panel.scss

   (cd Build && grunt build)

Resolves: #93126
Resolves: #93123
Resolves: #93132
Related: #92616
Releases: master
Change-Id: Ie194d0f87d2c60df7b9e8a6de4893cfaaea55356
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/67215

Tested-by: default avatarTYPO3com <noreply@typo3.com>
Tested-by: default avatarMartin Kutschker <mkutschker-typo3@yahoo.com>
Tested-by: Christian Kuhn's avatarChristian Kuhn <lolli@schwarzbu.ch>
Tested-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
Reviewed-by: default avatarMartin Kutschker <mkutschker-typo3@yahoo.com>
Reviewed-by: Christian Kuhn's avatarChristian Kuhn <lolli@schwarzbu.ch>
Reviewed-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
parent 89f2e9f8
...@@ -127,7 +127,7 @@ class Wizard { ...@@ -127,7 +127,7 @@ class Wizard {
this.initializeEvents(); this.initializeEvents();
this.getComponent().on('wizard-visible', (): void => { this.getComponent().on('wizard-visible', (): void => {
this.runSlideCallback(firstSlide, this.setup.$carousel.find('.item').first()); this.runSlideCallback(firstSlide, this.setup.$carousel.find('.carousel-item').first());
}).on('wizard-dismissed', (): void => { }).on('wizard-dismissed', (): void => {
this.setup = $.extend(true, {}, this.originalSetup); this.setup = $.extend(true, {}, this.originalSetup);
}); });
...@@ -229,7 +229,7 @@ class Wizard { ...@@ -229,7 +229,7 @@ class Wizard {
} }
private addProgressBar(): void { private addProgressBar(): void {
let realSlideCount = this.setup.$carousel.find('.item').length; let realSlideCount = this.setup.$carousel.find('.carousel-item').length;
let slideCount = Math.max(1, realSlideCount); let slideCount = Math.max(1, realSlideCount);
let initialStep; let initialStep;
let $modal = this.setup.$carousel.closest('.modal'); let $modal = this.setup.$carousel.closest('.modal');
...@@ -270,7 +270,7 @@ class Wizard { ...@@ -270,7 +270,7 @@ class Wizard {
return this.setup.$carousel; return this.setup.$carousel;
} }
let slides = '<div class="carousel slide" data-ride="carousel" data-interval="false">' let slides = '<div class="carousel slide" data-bs-ride="carousel" data-bs-interval="false">'
+ '<div class="carousel-inner" role="listbox">'; + '<div class="carousel-inner" role="listbox">';
for (let currentSlide of Object.values(this.setup.slides)) { for (let currentSlide of Object.values(this.setup.slides)) {
...@@ -279,13 +279,13 @@ class Wizard { ...@@ -279,13 +279,13 @@ class Wizard {
if (typeof slideContent === 'object') { if (typeof slideContent === 'object') {
slideContent = slideContent.html(); slideContent = slideContent.html();
} }
slides += '<div class="item" data-slide="' + currentSlide.identifier + '">' + slideContent + '</div>'; slides += '<div class="carousel-item" data-bs-slide="' + currentSlide.identifier + '">' + slideContent + '</div>';
} }
slides += '</div></div>'; slides += '</div></div>';
this.setup.$carousel = $(slides); this.setup.$carousel = $(slides);
this.setup.$carousel.find('.item').first().addClass('active'); this.setup.$carousel.find('.carousel-item').first().addClass('active');
return this.setup.$carousel; return this.setup.$carousel;
} }
......
...@@ -101,7 +101,7 @@ class LanguagePacks extends AbstractInteractableModule { ...@@ -101,7 +101,7 @@ class LanguagePacks extends AbstractInteractableModule {
contentContainer.empty(); contentContainer.empty();
contentContainer.append(this.languageMatrixHtml(data)); contentContainer.append(this.languageMatrixHtml(data));
contentContainer.append(this.extensionMatrixHtml(data)); contentContainer.append(this.extensionMatrixHtml(data));
$('[data-toggle="tooltip"]').tooltip(<any>({container: contentContainer})); $('[data-bs-toggle="tooltip"]').tooltip(<any>({container: contentContainer}));
} else { } else {
const message = InfoBox.render(Severity.error, 'Something went wrong', ''); const message = InfoBox.render(Severity.error, 'Something went wrong', '');
this.addNotification(message); this.addNotification(message);
...@@ -337,13 +337,13 @@ class LanguagePacks extends AbstractInteractableModule { ...@@ -337,13 +337,13 @@ class LanguagePacks extends AbstractInteractableModule {
$('<a>', { $('<a>', {
'class': 'btn btn-default t3js-languagePacks-deactivateLanguage', 'class': 'btn btn-default t3js-languagePacks-deactivateLanguage',
'data-iso': language.iso, 'data-iso': language.iso,
'data-toggle': 'tooltip', 'data-bs-toggle': 'tooltip',
'title': 'Deactivate', 'title': 'Deactivate',
}).append(deactivateIcon), }).append(deactivateIcon),
$('<a>', { $('<a>', {
'class': 'btn btn-default t3js-languagePacks-update', 'class': 'btn btn-default t3js-languagePacks-update',
'data-iso': language.iso, 'data-iso': language.iso,
'data-toggle': 'tooltip', 'data-bs-toggle': 'tooltip',
'title': 'Download language packs', 'title': 'Download language packs',
}).append(updateIcon), }).append(updateIcon),
), ),
...@@ -358,7 +358,7 @@ class LanguagePacks extends AbstractInteractableModule { ...@@ -358,7 +358,7 @@ class LanguagePacks extends AbstractInteractableModule {
$('<a>', { $('<a>', {
'class': 'btn btn-default t3js-languagePacks-activateLanguage', 'class': 'btn btn-default t3js-languagePacks-activateLanguage',
'data-iso': language.iso, 'data-iso': language.iso,
'data-toggle': 'tooltip', 'data-bs-toggle': 'tooltip',
'title': 'Activate', 'title': 'Activate',
}).append(activateIcon), }).append(activateIcon),
), ),
...@@ -428,7 +428,7 @@ class LanguagePacks extends AbstractInteractableModule { ...@@ -428,7 +428,7 @@ class LanguagePacks extends AbstractInteractableModule {
$('<a>', { $('<a>', {
'class': 'btn btn-default t3js-languagePacks-update', 'class': 'btn btn-default t3js-languagePacks-update',
'data-iso': language, 'data-iso': language,
'data-toggle': 'tooltip', 'data-bs-toggle': 'tooltip',
'title': 'Download and update all language packs', 'title': 'Download and update all language packs',
}).append( }).append(
$('<span>').append(updateIcon), $('<span>').append(updateIcon),
...@@ -479,7 +479,7 @@ class LanguagePacks extends AbstractInteractableModule { ...@@ -479,7 +479,7 @@ class LanguagePacks extends AbstractInteractableModule {
'class': 'btn btn-default t3js-languagePacks-update', 'class': 'btn btn-default t3js-languagePacks-update',
'data-extension': extension.key, 'data-extension': extension.key,
'data-iso': pack.iso, 'data-iso': pack.iso,
'data-toggle': 'tooltip', 'data-bs-toggle': 'tooltip',
'title': securityUtility.encodeHtml(tooltip), 'title': securityUtility.encodeHtml(tooltip),
}).append(updateIcon), }).append(updateIcon),
); );
......
...@@ -241,7 +241,7 @@ class Router { ...@@ -241,7 +241,7 @@ class Router {
+ '<div class="panel panel-default panel-flat searchhit">' + '<div class="panel panel-default panel-flat searchhit">'
+ '<div class="panel-heading" role="tab" id="heading-error">' + '<div class="panel-heading" role="tab" id="heading-error">'
+ '<h3 class="panel-title">' + '<h3 class="panel-title">'
+ '<a role="button" data-toggle="collapse" data-parent="#accordion" href="#collapse-error" aria-expanded="true" ' + '<a role="button" data-bs-toggle="collapse" data-bs-parent="#accordion" href="#collapse-error" aria-expanded="true" '
+ 'aria-controls="collapse-error" class="collapsed">' + 'aria-controls="collapse-error" class="collapsed">'
+ '<span class="caret"></span>' + '<span class="caret"></span>'
+ '<strong>Ajax error</strong>' + '<strong>Ajax error</strong>'
......
...@@ -68,7 +68,7 @@ class Recordlist { ...@@ -68,7 +68,7 @@ class Recordlist {
const $me = $(e.currentTarget); const $me = $(e.currentTarget);
const table = $me.data('table'); const table = $me.data('table');
const $target = $($me.data('target')); const $target = $($me.data('bs-target'));
const isExpanded = $target.data('state') === 'expanded'; const isExpanded = $target.data('state') === 'expanded';
const $collapseIcon = $me.find('.collapseIcon'); const $collapseIcon = $me.find('.collapseIcon');
const toggleIcon = isExpanded ? this.identifier.icons.expand : this.identifier.icons.collapse; const toggleIcon = isExpanded ? this.identifier.icons.expand : this.identifier.icons.collapse;
......
...@@ -293,7 +293,7 @@ class Backend extends Workspaces { ...@@ -293,7 +293,7 @@ class Backend extends Workspaces {
}).on('click', '[data-action="remove"]', this.confirmDeleteRecordFromWorkspace) }).on('click', '[data-action="remove"]', this.confirmDeleteRecordFromWorkspace)
.on('click', '[data-action="expand"]', (e: JQueryEventObject): void => { .on('click', '[data-action="expand"]', (e: JQueryEventObject): void => {
const $me = $(e.currentTarget); const $me = $(e.currentTarget);
const $target = this.elements.$tableBody.find($me.data('target')); const $target = this.elements.$tableBody.find($me.data('bs-target'));
let iconIdentifier; let iconIdentifier;
if ($target.first().attr('aria-expanded') === 'true') { if ($target.first().attr('aria-expanded') === 'true') {
...@@ -578,12 +578,12 @@ class Backend extends Workspaces { ...@@ -578,12 +578,12 @@ class Backend extends Workspaces {
'expand', 'expand',
'apps-pagetree-collapse', 'apps-pagetree-collapse',
).attr('title', TYPO3.lang['tooltip.expand']) ).attr('title', TYPO3.lang['tooltip.expand'])
.attr('data-target', '[data-collection="' + item.Workspaces_CollectionCurrent + '"]') .attr('data-bs-target', '[data-collection="' + item.Workspaces_CollectionCurrent + '"]')
.attr('data-toggle', 'collapse'), .attr('data-bs-toggle', 'collapse'),
$('<button />', { $('<button />', {
class: 'btn btn-default', class: 'btn btn-default',
'data-action': 'changes', 'data-action': 'changes',
'data-toggle': 'tooltip', 'data-bs-toggle': 'tooltip',
title: TYPO3.lang['tooltip.showChanges'], title: TYPO3.lang['tooltip.showChanges'],
}).append(this.getPreRenderedIcon('actions-document-info')), }).append(this.getPreRenderedIcon('actions-document-info')),
this.getAction( this.getAction(
...@@ -616,9 +616,9 @@ class Backend extends Workspaces { ...@@ -616,9 +616,9 @@ class Backend extends Workspaces {
if (item.integrity.messages !== '') { if (item.integrity.messages !== '') {
$integrityIcon = $(TYPO3.settings.Workspaces.icons[item.integrity.status]); $integrityIcon = $(TYPO3.settings.Workspaces.icons[item.integrity.status]);
$integrityIcon $integrityIcon
.attr('data-toggle', 'tooltip') .attr('data-bs-toggle', 'tooltip')
.attr('data-placement', 'top') .attr('data-bs-placement', 'top')
.attr('data-html', 'true') .attr('data-bs-html', 'true')
.attr('title', item.integrity.messages); .attr('title', item.integrity.messages);
} }
...@@ -680,7 +680,7 @@ class Backend extends Workspaces { ...@@ -680,7 +680,7 @@ class Backend extends Workspaces {
), ),
); );
Tooltip.initialize('[data-toggle="tooltip"]', { Tooltip.initialize('[data-bs-toggle="tooltip"]', {
delay: { delay: {
show: 500, show: 500,
hide: 100, hide: 100,
...@@ -786,7 +786,7 @@ class Backend extends Workspaces { ...@@ -786,7 +786,7 @@ class Backend extends Workspaces {
href: '#workspace-changes', href: '#workspace-changes',
'aria-controls': 'workspace-changes', 'aria-controls': 'workspace-changes',
role: 'tab', role: 'tab',
'data-toggle': 'tab', 'data-bs-toggle': 'tab',
}).text(TYPO3.lang['window.recordChanges.tabs.changeSummary']), }).text(TYPO3.lang['window.recordChanges.tabs.changeSummary']),
), ),
); );
...@@ -807,7 +807,7 @@ class Backend extends Workspaces { ...@@ -807,7 +807,7 @@ class Backend extends Workspaces {
href: '#workspace-comments', href: '#workspace-comments',
'aria-controls': 'workspace-comments', 'aria-controls': 'workspace-comments',
role: 'tab', role: 'tab',
'data-toggle': 'tab', 'data-bs-toggle': 'tab',
}).html(TYPO3.lang['window.recordChanges.tabs.comments'] + '&nbsp;').append( }).html(TYPO3.lang['window.recordChanges.tabs.comments'] + '&nbsp;').append(
$('<span />', {class: 'badge'}).text(item.comments.length), $('<span />', {class: 'badge'}).text(item.comments.length),
), ),
...@@ -830,7 +830,7 @@ class Backend extends Workspaces { ...@@ -830,7 +830,7 @@ class Backend extends Workspaces {
href: '#workspace-history', href: '#workspace-history',
'aria-controls': 'workspace-history', 'aria-controls': 'workspace-history',
role: 'tab', role: 'tab',
'data-toggle': 'tab', 'data-bs-toggle': 'tab',
}).text(TYPO3.lang['window.recordChanges.tabs.history']), }).text(TYPO3.lang['window.recordChanges.tabs.history']),
), ),
); );
...@@ -1203,7 +1203,7 @@ class Backend extends Workspaces { ...@@ -1203,7 +1203,7 @@ class Backend extends Workspaces {
return $('<button />', { return $('<button />', {
class: 'btn btn-default', class: 'btn btn-default',
'data-action': action, 'data-action': action,
'data-toggle': 'tooltip', 'data-bs-toggle': 'tooltip',
}).append(this.getPreRenderedIcon(iconIdentifier)); }).append(this.getPreRenderedIcon(iconIdentifier));
} }
return $('<span />', {class: 'btn btn-default disabled'}).append(this.getPreRenderedIcon('empty-empty')); return $('<span />', {class: 'btn btn-default disabled'}).append(this.getPreRenderedIcon('empty-empty'));
......
...@@ -71,6 +71,7 @@ ...@@ -71,6 +71,7 @@
}, },
"dependencies": { "dependencies": {
"@claviska/jquery-minicolors": "^2.3.5", "@claviska/jquery-minicolors": "^2.3.5",
"@popperjs/core": "^2.6.0",
"@typo3/icons": "^2.0.4", "@typo3/icons": "^2.0.4",
"autosize": "^4.0.2", "autosize": "^4.0.2",
"bootstrap": "^5.0.0-beta1", "bootstrap": "^5.0.0-beta1",
......
...@@ -245,6 +245,11 @@ ...@@ -245,6 +245,11 @@
"@nodelib/fs.scandir" "2.1.3" "@nodelib/fs.scandir" "2.1.3"
fastq "^1.6.0" fastq "^1.6.0"
"@popperjs/core@^2.6.0":
version "2.6.0"
resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.6.0.tgz#f022195afdfc942e088ee2101285a1d31c7d727f"
integrity sha512-cPqjjzuFWNK3BSKLm0abspP0sp/IGOli4p5I5fKFAzdS8fvjdOwDCfZqAaIiXd9lPkOWi3SUUfZof3hEb7J/uw==
"@sindresorhus/is@^0.7.0": "@sindresorhus/is@^0.7.0":
version "0.7.0" version "0.7.0"
resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.7.0.tgz#9a06f4f137ee84d7df0460c1fdb1135ffa6c50fd" resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.7.0.tgz#9a06f4f137ee84d7df0460c1fdb1135ffa6c50fd"
......
...@@ -6,8 +6,8 @@ ...@@ -6,8 +6,8 @@
<f:translate key="{label}" default="{label}" extensionName="adminpanel"/> <f:translate key="{label}" default="{label}" extensionName="adminpanel"/>
</label> </label>
<div class="typo3-adminPanel-form-datetime-input-group"> <div class="typo3-adminPanel-form-datetime-input-group">
<input type="date" id="{name}-date-hr" class="typo3-adminPanel-form-datetime-input" data-target="{name}"/> <input type="date" id="{name}-date-hr" class="typo3-adminPanel-form-datetime-input" data-bs-target="{name}"/>
<input type="time" id="{name}-time-hr" class="typo3-adminPanel-form-datetime-input" data-target="{name}"/> <input type="time" id="{name}-time-hr" class="typo3-adminPanel-form-datetime-input" data-bs-target="{name}"/>
</div> </div>
<input type="hidden" name="TSFE_ADMIN_PANEL[{name}]" id="{name}" value="{value}" /> <input type="hidden" name="TSFE_ADMIN_PANEL[{name}]" id="{name}" value="{value}" />
</div> </div>
......
...@@ -323,7 +323,7 @@ class BackendController ...@@ -323,7 +323,7 @@ class BackendController
$toolbar[] = '<li ' . GeneralUtility::implodeAttributes($liAttributes, true) . '>'; $toolbar[] = '<li ' . GeneralUtility::implodeAttributes($liAttributes, true) . '>';
if ($hasDropDown) { if ($hasDropDown) {
$toolbar[] = '<a href="#" class="toolbar-item-link dropdown-toggle" data-toggle="dropdown">'; $toolbar[] = '<a href="#" class="toolbar-item-link dropdown-toggle" data-bs-toggle="dropdown">';
$toolbar[] = $toolbarItem->getItem(); $toolbar[] = $toolbarItem->getItem();
$toolbar[] = '</a>'; $toolbar[] = '</a>';
$toolbar[] = '<div class="dropdown-menu" role="menu">'; $toolbar[] = '<div class="dropdown-menu" role="menu">';
......
...@@ -221,7 +221,7 @@ class InlineRecordContainer extends AbstractContainer ...@@ -221,7 +221,7 @@ class InlineRecordContainer extends AbstractContainer
$ariaAttributesString = 'aria-expanded="' . $ariaExpanded . '" aria-controls="' . $ariaControls . '"'; $ariaAttributesString = 'aria-expanded="' . $ariaExpanded . '" aria-controls="' . $ariaControls . '"';
$html = ' $html = '
<div ' . GeneralUtility::implodeAttributes($containerAttributes, true) . '> <div ' . GeneralUtility::implodeAttributes($containerAttributes, true) . '>
<div class="panel-heading" data-toggle="formengine-inline" id="' . htmlspecialchars($hashedObjectId, ENT_QUOTES | ENT_HTML5) . '_header" data-expandSingle="' . ($inlineConfig['appearance']['expandSingle'] ? 1 : 0) . '"> <div class="panel-heading" data-bs-toggle="formengine-inline" id="' . htmlspecialchars($hashedObjectId, ENT_QUOTES | ENT_HTML5) . '_header" data-expandSingle="' . ($inlineConfig['appearance']['expandSingle'] ? 1 : 0) . '">
<div class="form-irre-header"> <div class="form-irre-header">
<div class="form-irre-header-cell form-irre-header-icon"> <div class="form-irre-header-cell form-irre-header-icon">
<span class="caret"></span> <span class="caret"></span>
...@@ -614,7 +614,7 @@ class InlineRecordContainer extends AbstractContainer ...@@ -614,7 +614,7 @@ class InlineRecordContainer extends AbstractContainer
// If the record is edit-locked by another user, we will show a little warning sign: // If the record is edit-locked by another user, we will show a little warning sign:
if ($lockInfo = BackendUtility::isRecordLocked($foreignTable, $rec['uid'])) { if ($lockInfo = BackendUtility::isRecordLocked($foreignTable, $rec['uid'])) {
$cells['locked'] = ' $cells['locked'] = '
<button type="button" class="btn btn-default" data-toggle="tooltip" data-title="' . htmlspecialchars($lockInfo['msg']) . '"> <button type="button" class="btn btn-default" data-bs-toggle="tooltip" data-title="' . htmlspecialchars($lockInfo['msg']) . '">
<span title="' . htmlspecialchars($lockInfo['msg']) . '">' . $this->iconFactory->getIcon('warning-in-use', Icon::SIZE_SMALL)->render() . '</span> <span title="' . htmlspecialchars($lockInfo['msg']) . '">' . $this->iconFactory->getIcon('warning-in-use', Icon::SIZE_SMALL)->render() . '</span>
</button>'; </button>';
} }
......
...@@ -223,7 +223,7 @@ class InputLinkElement extends AbstractFormElement ...@@ -223,7 +223,7 @@ class InputLinkElement extends AbstractFormElement
$expansionHtml[] = '<div class="form-wizards-element">'; $expansionHtml[] = '<div class="form-wizards-element">';
$expansionHtml[] = '<div class="input-group t3js-form-field-inputlink">'; $expansionHtml[] = '<div class="input-group t3js-form-field-inputlink">';
$expansionHtml[] = '<span class="t3js-form-field-inputlink-icon input-group-addon">' . $linkExplanation['icon'] . '</span>'; $expansionHtml[] = '<span class="t3js-form-field-inputlink-icon input-group-addon">' . $linkExplanation['icon'] . '</span>';
$expansionHtml[] = '<input class="form-control t3js-form-field-inputlink-explanation" data-toggle="tooltip" data-title="' . $explanation . '" value="' . $explanation . '" readonly>'; $expansionHtml[] = '<input class="form-control t3js-form-field-inputlink-explanation" data-bs-toggle="tooltip" data-title="' . $explanation . '" value="' . $explanation . '" readonly>';
$expansionHtml[] = '<input type="text" ' . GeneralUtility::implodeAttributes($attributes, true) . ' />'; $expansionHtml[] = '<input type="text" ' . GeneralUtility::implodeAttributes($attributes, true) . ' />';
$expansionHtml[] = '<span class="input-group-btn">'; $expansionHtml[] = '<span class="input-group-btn">';
$expansionHtml[] = '<button class="btn btn-default t3js-form-field-inputlink-explanation-toggle" type="button" title="' . htmlspecialchars($toggleButtonTitle) . '">'; $expansionHtml[] = '<button class="btn btn-default t3js-form-field-inputlink-explanation-toggle" type="button" title="' . htmlspecialchars($toggleButtonTitle) . '">';
......
...@@ -122,7 +122,7 @@ class InputSlugElement extends AbstractFormElement ...@@ -122,7 +122,7 @@ class InputSlugElement extends AbstractFormElement
// field to manipulate the value, and the final hidden field used to send the value // field to manipulate the value, and the final hidden field used to send the value
$mainFieldHtml[] = '<input'; $mainFieldHtml[] = '<input';
$mainFieldHtml[] = ' class="form-control t3js-form-field-slug-readonly"'; $mainFieldHtml[] = ' class="form-control t3js-form-field-slug-readonly"';
$mainFieldHtml[] = ' data-toggle="tooltip"'; $mainFieldHtml[] = ' data-bs-toggle="tooltip"';
$mainFieldHtml[] = ' data-title="' . htmlspecialchars($itemValue) . '"'; $mainFieldHtml[] = ' data-title="' . htmlspecialchars($itemValue) . '"';
$mainFieldHtml[] = ' value="' . htmlspecialchars($itemValue) . '"'; $mainFieldHtml[] = ' value="' . htmlspecialchars($itemValue) . '"';
$mainFieldHtml[] = ' readonly'; $mainFieldHtml[] = ' readonly';
......
...@@ -177,7 +177,7 @@ class SelectCheckBoxElement extends AbstractFormElement ...@@ -177,7 +177,7 @@ class SelectCheckBoxElement extends AbstractFormElement
$html[] = '<div id="' . $groupId . '" class="panel panel-default">'; $html[] = '<div id="' . $groupId . '" class="panel panel-default">';
if (is_array($group['header'])) { if (is_array($group['header'])) {
$html[] = '<div class="panel-heading">'; $html[] = '<div class="panel-heading">';
$html[] = '<a data-toggle="collapse" href="#' . $groupIdCollapsible . '" aria-expanded="false" aria-controls="' . $groupIdCollapsible . '">'; $html[] = '<a data-bs-toggle="collapse" href="#' . $groupIdCollapsible . '" aria-expanded="false" aria-controls="' . $groupIdCollapsible . '">';
$html[] = $group['header']['icon']; $html[] = $group['header']['icon'];
$html[] = htmlspecialchars($group['header']['title']); $html[] = htmlspecialchars($group['header']['title']);
$html[] = '</a>'; $html[] = '</a>';
...@@ -231,7 +231,7 @@ class SelectCheckBoxElement extends AbstractFormElement ...@@ -231,7 +231,7 @@ class SelectCheckBoxElement extends AbstractFormElement
$html[] = '<thead>'; $html[] = '<thead>';
$html[] = '<tr>'; $html[] = '<tr>';
$html[] = '<th class="col-checkbox">'; $html[] = '<th class="col-checkbox">';
$html[] = '<input type="checkbox" id="' . $checkboxId . '" class="t3js-toggle-checkboxes" data-trigger="hover" data-placement="right" data-title="' . $title . '" data-toggle="tooltip" />'; $html[] = '<input type="checkbox" id="' . $checkboxId . '" class="t3js-toggle-checkboxes" data-bs-trigger="hover" data-bs-placement="right" data-title="' . $title . '" data-bs-toggle="tooltip" />';
$html[] = '</th>'; $html[] = '</th>';
$html[] = '<th class="col-title" colspan="2"><label for="' . $checkboxId . '">' . $title . '</label></th>'; $html[] = '<th class="col-title" colspan="2"><label for="' . $checkboxId . '">' . $title . '</label></th>';
$html[] = '<th class="text-right">' . $resetGroupBtn . '</th>'; $html[] = '<th class="text-right">' . $resetGroupBtn . '</th>';
......
...@@ -47,7 +47,7 @@ class InlineStackProcessor ...@@ -47,7 +47,7 @@ class InlineStackProcessor
/** /**
* Convert the DOM object-id of an inline container to an array. * Convert the DOM object-id of an inline container to an array.
* The object-id could look like 'data-parentPageId-tx_mmftest_company-1-employees'. * The object-id could look like 'data-bs-parentPageId-tx_mmftest_company-1-employees'.
* This initializes $this->inlineStructure - used by AJAX entry points * This initializes $this->inlineStructure - used by AJAX entry points
* There are two keys: * There are two keys:
* - 'stable': Containing full qualified identifiers (table, uid and field) * - 'stable': Containing full qualified identifiers (table, uid and field)
......
...@@ -159,8 +159,7 @@ class SplitButton extends AbstractButton ...@@ -159,8 +159,7 @@ class SplitButton extends AbstractButton
' . $items['primary']->getIcon()->render('inline') . ' ' . $items['primary']->getIcon()->render('inline') . '
' . htmlspecialchars($items['primary']->getTitle()) . ' ' . htmlspecialchars($items['primary']->getTitle()) . '
</button> </button>
<button type="button" class="btn btn-sm btn-default dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> <button type="button" class="btn btn-sm btn-default dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
<span class="caret"></span>
<span class="sr-only">Toggle Dropdown</span> <span class="sr-only">Toggle Dropdown</span>
</button> </button>
<ul class="dropdown-menu">'; <ul class="dropdown-menu">';
...@@ -182,6 +181,7 @@ class SplitButton extends AbstractButton ...@@ -182,6 +181,7 @@ class SplitButton extends AbstractButton
if (!empty($option->getOnClick())) { if (!empty($option->getOnClick())) {
$optionAttributes['onclick'] = $option->getOnClick(); $optionAttributes['onclick'] = $option->getOnClick();
} }
$optionAttributes['class'] = $optionAttributes['class'] ? $optionAttributes['class'] . ' dropdown-item' : 'dropdown-item';
$optionAttributesString = ''; $optionAttributesString = '';
foreach ($optionAttributes as $key => $value) { foreach ($optionAttributes as $key => $value) {
$optionAttributesString .= ' ' . htmlspecialchars($key) . '="' . htmlspecialchars($value) . '"'; $optionAttributesString .= ' ' . htmlspecialchars($key) . '="' . htmlspecialchars($value) . '"';
......
...@@ -530,7 +530,7 @@ class PagePositionMap ...@@ -530,7 +530,7 @@ class PagePositionMap
$uid = ''; $uid = '';
} }
$cc = hexdec(substr(md5($uid . '-' . $vv . '-' . $kk), 0, 4)); $cc = hexdec(substr(md5($uid . '-' . $vv . '-' . $kk), 0, 4));
return '<a href="#" onclick="' . htmlspecialchars($this->onClickInsertRecord($row, $vv, $moveUid, $pid, $this->cur_sys_language)) . '" data-dismiss="modal"><i class="t3-icon fa fa-long-arrow-left" name="mImgEnd' . $cc . '" title="' . htmlspecialchars($this->getLanguageService()->getLL($this->l_insertNewRecordHere)) . '"></i></a>'; return '<a href="#" onclick="' . htmlspecialchars($this->onClickInsertRecord($row, $vv, $moveUid, $pid, $this->cur_sys_language)) . '" data-bs-dismiss="modal"><i class="t3-icon fa fa-long-arrow-left" name="mImgEnd' . $cc . '" title="' . htmlspecialchars($this->getLanguageService()->getLL($this->l_insertNewRecordHere)) . '"></i></a>';
} }
/** /**
......
...@@ -1200,9 +1200,9 @@ class BackendUtility ...@@ -1200,9 +1200,9 @@ class BackendUtility
public static function getRecordToolTip(array $row, $table = 'pages') public static function getRecordToolTip(array $row, $table = 'pages')
{ {
$toolTipText = self::getRecordIconAltText($row, $table); $toolTipText = self::getRecordIconAltText($row, $table);
$toolTipCode = 'data-toggle="tooltip" data-title=" ' $toolTipCode = 'data-bs-toggle="tooltip" data-title=" '
. str_replace(' - ', '<br>', $toolTipText) . str_replace(' - ', '<br>', $toolTipText)
. '" data-html="true" data-placement="right"'; . '" data-bs-html="true" data-bs-placement="right"';
return $toolTipCode; return $toolTipCode;
} }
......
...@@ -173,7 +173,7 @@ class GridColumnItem extends AbstractGridObject ...@@ -173,7 +173,7 @@ class GridColumnItem extends AbstractGridObject
} }
if ($lockInfo = BackendUtility::isRecordLocked('tt_content', $row['uid'])) { if ($lockInfo = BackendUtility::isRecordLocked('tt_content', $row['uid'])) {
$icons[] = '<a href="#" data-toggle="tooltip" data-title="' . htmlspecialchars($lockInfo['msg']) . '">' $icons[] = '<a href="#" data-bs-toggle="tooltip" data-title="' . htmlspecialchars($lockInfo['msg']) . '">'
. $this->iconFactory->getIcon('warning-in-use', Icon::SIZE_SMALL)->render() . '</a>'; . $this->iconFactory->getIcon('warning-in-use', Icon::SIZE_SMALL)->render() . '</a>';
} }
......
...@@ -332,7 +332,7 @@ class BackendLayoutRenderer ...@@ -332,7 +332,7 @@ class BackendLayoutRenderer
{ {