From ca2a2567a10cd9536856baf6a4abdbf18b850647 Mon Sep 17 00:00:00 2001 From: Andreas Kienast <a.fernandez@scripting-base.de> Date: Thu, 21 Mar 2024 14:28:03 +0100 Subject: [PATCH] [TASK] linkvalidator: Calculate option toggle state on render time MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit changes how the "Toggle all" and option and action button states are determined. Previously, the state was determined via JavaScript, leading to an unexpected rendering change when the module has loaded. To avoid this, the state is now calculated in the controller as the necessary metrics are already known. In the same run, `optionByType.checked` is now a simple bool flag instead of holding arbitrary HTML attributes. Resolves: #103454 Releases: main Change-Id: I2da39063dbb9161873274dadddcc3b0384e36321 Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/83560 Tested-by: Benjamin Franzke <ben@bnf.dev> Tested-by: core-ci <typo3@b13.com> Reviewed-by: Benjamin Franzke <ben@bnf.dev> Reviewed-by: Benni Mack <benni@typo3.org> Tested-by: Andreas Kienast <a.fernandez@scripting-base.de> Reviewed-by: Jörg Bösche <typo3@joergboesche.de> Reviewed-by: Andreas Kienast <a.fernandez@scripting-base.de> Tested-by: Benni Mack <benni@typo3.org> --- Build/Sources/TypeScript/linkvalidator/linkvalidator.ts | 2 -- .../Classes/Controller/LinkValidatorController.php | 8 +++++++- .../Resources/Private/Partials/CheckOptions.html | 4 ++-- .../Resources/Private/Templates/Backend/CheckLinks.html | 2 +- .../Resources/Private/Templates/Backend/Report.html | 2 +- .../Resources/Public/JavaScript/linkvalidator.js | 2 +- 6 files changed, 12 insertions(+), 8 deletions(-) diff --git a/Build/Sources/TypeScript/linkvalidator/linkvalidator.ts b/Build/Sources/TypeScript/linkvalidator/linkvalidator.ts index c3ff0487de06..667589b7b848 100644 --- a/Build/Sources/TypeScript/linkvalidator/linkvalidator.ts +++ b/Build/Sources/TypeScript/linkvalidator/linkvalidator.ts @@ -29,8 +29,6 @@ enum Identifier { */ class Linkvalidator { constructor() { - this.toggleTriggerCheckBox(); - this.toggleActionButton(); this.initializeEvents(); } diff --git a/typo3/sysext/linkvalidator/Classes/Controller/LinkValidatorController.php b/typo3/sysext/linkvalidator/Classes/Controller/LinkValidatorController.php index e970df84ab62..62a555dc938c 100644 --- a/typo3/sysext/linkvalidator/Classes/Controller/LinkValidatorController.php +++ b/typo3/sysext/linkvalidator/Classes/Controller/LinkValidatorController.php @@ -427,6 +427,7 @@ class LinkValidatorController { $brokenLinksInformation = $this->linkAnalyzer->getLinkCounts(); $options = [ + 'anyOptionChecked' => false, 'totalCountLabel' => $this->getLanguageService()->sL('LLL:EXT:linkvalidator/Resources/Private/Language/Module/locallang.xlf:overviews.nbtotal'), 'totalCount' => $brokenLinksInformation['total'] ?: '0', 'optionsByType' => [], @@ -436,14 +437,19 @@ class LinkValidatorController if (!in_array($type, $linkTypes, true)) { continue; } + $isChecked = !empty($this->checkOpt[$prefix][$type]); + if ($isChecked) { + $options['anyOptionChecked'] = true; + } $options['optionsByType'][$type] = [ 'id' => $prefix . '_SET_' . $type, 'name' => $prefix . '_SET[' . $type . ']', 'label' => $this->getLanguageService()->sL('LLL:EXT:linkvalidator/Resources/Private/Language/Module/locallang.xlf:hooks.' . $type) ?: $type, - 'checked' => !empty($this->checkOpt[$prefix][$type]) ? ' checked="checked"' : '', + 'checked' => $isChecked, 'count' => (!empty($brokenLinksInformation[$type]) ? $brokenLinksInformation[$type] : '0'), ]; } + $options['allOptionsChecked'] = array_filter($options['optionsByType'], static fn(array $option): bool => !$option['checked']) === []; return $options; } diff --git a/typo3/sysext/linkvalidator/Resources/Private/Partials/CheckOptions.html b/typo3/sysext/linkvalidator/Resources/Private/Partials/CheckOptions.html index 5d84e8a3ebaa..6941ddd082ee 100644 --- a/typo3/sysext/linkvalidator/Resources/Private/Partials/CheckOptions.html +++ b/typo3/sysext/linkvalidator/Resources/Private/Partials/CheckOptions.html @@ -13,7 +13,7 @@ <tr> <th> <div class="form-check form-switch"> - <input id="options-by-type-toggle-all" class="options-by-type-toggle-all form-check-input" type="checkbox" title="{f:translate(key: 'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.toggleall')}"> + <input id="options-by-type-toggle-all" class="options-by-type-toggle-all form-check-input" type="checkbox" title="{f:translate(key: 'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.toggleall')}" {f:if(condition: '{options.allOptionsChecked}', then: 'checked')}> <label class="form-check-label" for="options-by-type-toggle-all"><f:translate key="LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.toggleall"/></label> </div> </th> @@ -25,7 +25,7 @@ <tr> <td> <div class="form-check form-switch"> - <input type="checkbox" class="form-check-input options-by-type" value="1" id="{optionByType.id}" name="{optionByType.name}" {optionByType.checked}/> + <input type="checkbox" class="form-check-input options-by-type" value="1" id="{optionByType.id}" name="{optionByType.name}" {f:if(condition: '{optionByType.checked}', then: 'checked')} /> <label class="form-check-label" for="{optionByType.id}">{optionByType.label}</label> </div> </td> diff --git a/typo3/sysext/linkvalidator/Resources/Private/Templates/Backend/CheckLinks.html b/typo3/sysext/linkvalidator/Resources/Private/Templates/Backend/CheckLinks.html index d7f8eff2c167..765a9e84e82e 100644 --- a/typo3/sysext/linkvalidator/Resources/Private/Templates/Backend/CheckLinks.html +++ b/typo3/sysext/linkvalidator/Resources/Private/Templates/Backend/CheckLinks.html @@ -32,7 +32,7 @@ type="submit" class="btn btn-default t3js-linkvalidator-action-button" name="updateLinkList" - disabled + {f:if(condition: '!{options.anyOptionChecked}', then: 'disabled')} value="{f:translate(key: 'LLL:EXT:linkvalidator/Resources/Private/Language/Module/locallang.xlf:label_update')}" data-notification-message="{f:translate(key: 'LLL:EXT:linkvalidator/Resources/Private/Language/Module/locallang.xlf:label_update-link-list')}" /> diff --git a/typo3/sysext/linkvalidator/Resources/Private/Templates/Backend/Report.html b/typo3/sysext/linkvalidator/Resources/Private/Templates/Backend/Report.html index fc1f7d767fc3..d6198e24ec00 100644 --- a/typo3/sysext/linkvalidator/Resources/Private/Templates/Backend/Report.html +++ b/typo3/sysext/linkvalidator/Resources/Private/Templates/Backend/Report.html @@ -32,7 +32,7 @@ type="submit" class="btn btn-default t3js-linkvalidator-action-button" name="refreshLinkList" - disabled + {f:if(condition: '!{options.anyOptionChecked}', then: 'disabled')} value="{f:translate(key: 'LLL:EXT:linkvalidator/Resources/Private/Language/Module/locallang.xlf:label_refresh')}" data-notification-message="{f:translate(key: 'LLL:EXT:linkvalidator/Resources/Private/Language/Module/locallang.xlf:label_refresh-link-list')}" /> diff --git a/typo3/sysext/linkvalidator/Resources/Public/JavaScript/linkvalidator.js b/typo3/sysext/linkvalidator/Resources/Public/JavaScript/linkvalidator.js index 352c73aea4f7..f2ee8f45f760 100644 --- a/typo3/sysext/linkvalidator/Resources/Public/JavaScript/linkvalidator.js +++ b/typo3/sysext/linkvalidator/Resources/Public/JavaScript/linkvalidator.js @@ -10,4 +10,4 @@ * * The TYPO3 project - inspiring people to share! */ -import Notification from"@typo3/backend/notification.js";import RegularEvent from"@typo3/core/event/regular-event.js";var Selectors,Identifier;!function(e){e.actionButtonSelector=".t3js-linkvalidator-action-button",e.toggleAllLinktypesSelector='.t3js-linkvalidator-settings input[type="checkbox"].options-by-type-toggle-all',e.linktypesSelector='.t3js-linkvalidator-settings input[type="checkbox"].options-by-type'}(Selectors||(Selectors={})),function(e){e.toggleAllLinktypesId="options-by-type-toggle-all"}(Identifier||(Identifier={}));class Linkvalidator{constructor(){this.toggleTriggerCheckBox(),this.toggleActionButton(),this.initializeEvents()}static allCheckBoxesAreChecked(e){const t=Array.from(e);return e.length===t.filter((e=>e.checked)).length}toggleActionButton(){document.querySelector(Selectors.actionButtonSelector)?.toggleAttribute("disabled",!document.querySelectorAll('input[type="checkbox"]:checked').length)}toggleTriggerCheckBox(){const e=document.querySelectorAll(Selectors.linktypesSelector);document.getElementById(Identifier.toggleAllLinktypesId).checked=Linkvalidator.allCheckBoxesAreChecked(e)}initializeEvents(){new RegularEvent("change",((e,t)=>{const o=document.querySelectorAll(Selectors.linktypesSelector),l=!Linkvalidator.allCheckBoxesAreChecked(o);o.forEach((e=>{e.checked=l})),t.checked=l,this.toggleActionButton()})).delegateTo(document,Selectors.toggleAllLinktypesSelector),new RegularEvent("change",(()=>{this.toggleTriggerCheckBox(),this.toggleActionButton()})).delegateTo(document,Selectors.linktypesSelector),new RegularEvent("click",((e,t)=>{Notification.success(t.dataset.notificationMessage||"Event triggered","",2)})).delegateTo(document,Selectors.actionButtonSelector)}}export default new Linkvalidator; \ No newline at end of file +import Notification from"@typo3/backend/notification.js";import RegularEvent from"@typo3/core/event/regular-event.js";var Selectors,Identifier;!function(e){e.actionButtonSelector=".t3js-linkvalidator-action-button",e.toggleAllLinktypesSelector='.t3js-linkvalidator-settings input[type="checkbox"].options-by-type-toggle-all',e.linktypesSelector='.t3js-linkvalidator-settings input[type="checkbox"].options-by-type'}(Selectors||(Selectors={})),function(e){e.toggleAllLinktypesId="options-by-type-toggle-all"}(Identifier||(Identifier={}));class Linkvalidator{constructor(){this.initializeEvents()}static allCheckBoxesAreChecked(e){const t=Array.from(e);return e.length===t.filter((e=>e.checked)).length}toggleActionButton(){document.querySelector(Selectors.actionButtonSelector)?.toggleAttribute("disabled",!document.querySelectorAll('input[type="checkbox"]:checked').length)}toggleTriggerCheckBox(){const e=document.querySelectorAll(Selectors.linktypesSelector);document.getElementById(Identifier.toggleAllLinktypesId).checked=Linkvalidator.allCheckBoxesAreChecked(e)}initializeEvents(){new RegularEvent("change",((e,t)=>{const o=document.querySelectorAll(Selectors.linktypesSelector),l=!Linkvalidator.allCheckBoxesAreChecked(o);o.forEach((e=>{e.checked=l})),t.checked=l,this.toggleActionButton()})).delegateTo(document,Selectors.toggleAllLinktypesSelector),new RegularEvent("change",(()=>{this.toggleTriggerCheckBox(),this.toggleActionButton()})).delegateTo(document,Selectors.linktypesSelector),new RegularEvent("click",((e,t)=>{Notification.success(t.dataset.notificationMessage||"Event triggered","",2)})).delegateTo(document,Selectors.actionButtonSelector)}}export default new Linkvalidator; \ No newline at end of file -- GitLab