From 258645ae7a1a5de15e1ea3551f03724da5816c15 Mon Sep 17 00:00:00 2001
From: Andreas Fernandez <a.fernandez@scripting-base.de>
Date: Fri, 26 Aug 2022 12:35:45 +0200
Subject: [PATCH] [TASK] Remove jQuery from EXT:impexp and EXT:info

Some small JavaScripts used in EXT:impexp and EXT:info are migrated to
remove the dependency on jQuery.

Resolves: #98211
Releases: main
Change-Id: If0c80465f8dc6770e529ac986266c14256aa79cb
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/75553
Tested-by: Susanne Moog <look@susi.dev>
Tested-by: core-ci <typo3@b13.com>
Tested-by: Benni Mack <benni@typo3.org>
Tested-by: Andreas Fernandez <a.fernandez@scripting-base.de>
Reviewed-by: Susanne Moog <look@susi.dev>
Reviewed-by: Benni Mack <benni@typo3.org>
Reviewed-by: Andreas Fernandez <a.fernandez@scripting-base.de>
---
 .../TypeScript/impexp/import-export.ts        | 54 +++++++++++--------
 .../TypeScript/info/translation-status.ts     | 28 ++++------
 .../Public/JavaScript/import-export.js        |  2 +-
 .../TranslationStatusController.php           |  2 +-
 .../Public/JavaScript/translation-status.js   |  2 +-
 5 files changed, 47 insertions(+), 41 deletions(-)

diff --git a/Build/Sources/TypeScript/impexp/import-export.ts b/Build/Sources/TypeScript/impexp/import-export.ts
index 7885064b26db..9fa69a0f94e4 100644
--- a/Build/Sources/TypeScript/impexp/import-export.ts
+++ b/Build/Sources/TypeScript/impexp/import-export.ts
@@ -11,8 +11,9 @@
  * The TYPO3 project - inspiring people to share!
  */
 
-import $ from 'jquery';
 import Modal from '@typo3/backend/modal';
+import RegularEvent from '@typo3/core/event/regular-event';
+import DocumentService from '@typo3/core/document-service';
 
 /**
  * Module: @typo3/impexp/import-export
@@ -21,29 +22,40 @@ import Modal from '@typo3/backend/modal';
  */
 class ImportExport {
   constructor() {
-    $((): void => {
-      $(document).on('click', '.t3js-confirm-trigger', (e: JQueryEventObject): void => {
-        const $button = $(e.currentTarget);
-        Modal.confirm($button.data('title'), $button.data('message'))
-          .on('confirm.button.ok', (): void => {
-            $('#t3js-submit-field')
-              .attr('name', $button.attr('name'))
-              .closest('form').trigger('submit');
-            Modal.currentModal.trigger('modal-dismiss');
-          })
-          .on('confirm.button.cancel', (): void => {
-            Modal.currentModal.trigger('modal-dismiss');
-          });
+    DocumentService.ready().then((): void => this.registerEvents());
+  }
+
+  private registerEvents(): void {
+    new RegularEvent('click', this.triggerConfirmation).delegateTo(document, '.t3js-confirm-trigger');
+
+    const toggleDisabledControl = document.querySelector('.t3js-impexp-toggledisabled');
+    if (toggleDisabledControl !== null) {
+      new RegularEvent('click', this.toggleDisabled).bindTo(toggleDisabledControl);
+    }
+  }
+
+  private triggerConfirmation(this: HTMLButtonElement): void {
+    Modal.confirm(this.dataset.title, this.dataset.message)
+      .on('confirm.button.ok', (): void => {
+        const submitTrigger: HTMLInputElement = document.getElementById('t3js-submit-field') as HTMLInputElement;
+        submitTrigger.name = this.name;
+        submitTrigger.closest('form').submit();
+
+        Modal.currentModal.trigger('modal-dismiss');
+      })
+      .on('confirm.button.cancel', (): void => {
+        Modal.currentModal.trigger('modal-dismiss');
       });
+  }
 
-      $('.t3js-impexp-toggledisabled').on('click', (): void => {
-        const $checkboxes = $('table.t3js-impexp-preview tr[data-active="hidden"] input.t3js-exclude-checkbox');
-        if ($checkboxes.length) {
-          const $firstCheckbox = $checkboxes.get(0) as HTMLInputElement;
-          $checkboxes.prop('checked', !$firstCheckbox.checked);
-        }
+  private toggleDisabled() {
+    const checkboxes: NodeListOf<HTMLInputElement> = document.querySelectorAll('table.t3js-impexp-preview tr[data-active="hidden"] input.t3js-exclude-checkbox');
+    if (checkboxes.length > 0) {
+      const firstCheckbox = checkboxes.item(0);
+      checkboxes.forEach((element: HTMLInputElement): void => {
+        element.checked = !firstCheckbox.checked;
       });
-    });
+    }
   }
 }
 
diff --git a/Build/Sources/TypeScript/info/translation-status.ts b/Build/Sources/TypeScript/info/translation-status.ts
index b4adc414b404..aa8ba39ab101 100644
--- a/Build/Sources/TypeScript/info/translation-status.ts
+++ b/Build/Sources/TypeScript/info/translation-status.ts
@@ -11,7 +11,7 @@
  * The TYPO3 project - inspiring people to share!
  */
 
-import $ from 'jquery';
+import RegularEvent from '@typo3/core/event/regular-event';
 
 /**
  * Module: @typo3/info/translation-status
@@ -22,25 +22,19 @@ class TranslationStatus {
   }
 
   private registerEvents(): void {
-    $('input[type="checkbox"][data-lang]').on('change', this.toggleNewButton);
+    new RegularEvent('click', this.toggleNewButton).delegateTo(document, 'input[type="checkbox"][data-lang]');
   }
 
-  /**
-   * @param {JQueryEventObject} e
-   */
-  private toggleNewButton(e: JQueryEventObject): void {
-    const $me = $(e.currentTarget);
-    const languageId = parseInt($me.data('lang'), 10);
-    const $newButton = $('.t3js-language-new-' + languageId);
-    const $selected = $('input[type="checkbox"][data-lang="' + languageId + '"]:checked');
-
-    const additionalArguments: string[] = [];
-    $selected.each((index: number, element: Element): void => {
-      additionalArguments.push('cmd[pages][' + (<HTMLInputElement>element).dataset.uid + '][localize]=' + languageId);
+  private toggleNewButton(this: HTMLInputElement): void {
+    const relatedCreationButton = document.querySelector(`.t3js-language-new[data-lang="${this.dataset.lang}"]`) as HTMLAnchorElement;
+    const selectedButtons = document.querySelectorAll(`input[type="checkbox"][data-lang="${this.dataset.lang}"]:checked`);
+    const actionUrl = new URL(location.origin + relatedCreationButton.dataset.editUrl);
+    selectedButtons.forEach((element: HTMLInputElement): void => {
+      actionUrl.searchParams.set(`cmd[pages][${element.dataset.uid}][localize]`, this.dataset.lang);
     });
-    const updatedHref = $newButton.data('editUrl') + '&' + additionalArguments.join('&');
-    $newButton.attr('href', updatedHref);
-    $newButton.toggleClass('disabled', $selected.length === 0);
+
+    relatedCreationButton.href = actionUrl.toString();
+    relatedCreationButton.classList.toggle('disabled', selectedButtons.length === 0);
   }
 }
 
diff --git a/typo3/sysext/impexp/Resources/Public/JavaScript/import-export.js b/typo3/sysext/impexp/Resources/Public/JavaScript/import-export.js
index b69d36d98ca4..1e308510078b 100644
--- a/typo3/sysext/impexp/Resources/Public/JavaScript/import-export.js
+++ b/typo3/sysext/impexp/Resources/Public/JavaScript/import-export.js
@@ -10,4 +10,4 @@
  *
  * The TYPO3 project - inspiring people to share!
  */
-import $ from"jquery";import Modal from"@typo3/backend/modal.js";class ImportExport{constructor(){$((()=>{$(document).on("click",".t3js-confirm-trigger",(t=>{const o=$(t.currentTarget);Modal.confirm(o.data("title"),o.data("message")).on("confirm.button.ok",(()=>{$("#t3js-submit-field").attr("name",o.attr("name")).closest("form").trigger("submit"),Modal.currentModal.trigger("modal-dismiss")})).on("confirm.button.cancel",(()=>{Modal.currentModal.trigger("modal-dismiss")}))})),$(".t3js-impexp-toggledisabled").on("click",(()=>{const t=$('table.t3js-impexp-preview tr[data-active="hidden"] input.t3js-exclude-checkbox');if(t.length){const o=t.get(0);t.prop("checked",!o.checked)}}))}))}}export default new ImportExport;
\ No newline at end of file
+import Modal from"@typo3/backend/modal.js";import RegularEvent from"@typo3/core/event/regular-event.js";import DocumentService from"@typo3/core/document-service.js";class ImportExport{constructor(){DocumentService.ready().then((()=>this.registerEvents()))}registerEvents(){new RegularEvent("click",this.triggerConfirmation).delegateTo(document,".t3js-confirm-trigger");const e=document.querySelector(".t3js-impexp-toggledisabled");null!==e&&new RegularEvent("click",this.toggleDisabled).bindTo(e)}triggerConfirmation(){Modal.confirm(this.dataset.title,this.dataset.message).on("confirm.button.ok",(()=>{const e=document.getElementById("t3js-submit-field");e.name=this.name,e.closest("form").submit(),Modal.currentModal.trigger("modal-dismiss")})).on("confirm.button.cancel",(()=>{Modal.currentModal.trigger("modal-dismiss")}))}toggleDisabled(){const e=document.querySelectorAll('table.t3js-impexp-preview tr[data-active="hidden"] input.t3js-exclude-checkbox');if(e.length>0){const t=e.item(0);e.forEach((e=>{e.checked=!t.checked}))}}}export default new ImportExport;
\ No newline at end of file
diff --git a/typo3/sysext/info/Classes/Controller/TranslationStatusController.php b/typo3/sysext/info/Classes/Controller/TranslationStatusController.php
index 8f524b1932aa..3392a0aa33cc 100644
--- a/typo3/sysext/info/Classes/Controller/TranslationStatusController.php
+++ b/typo3/sysext/info/Classes/Controller/TranslationStatusController.php
@@ -326,7 +326,7 @@ class TranslationStatusController extends InfoModuleController
                 $createLink = (string)$this->uriBuilder->buildUriFromRoute('tce_db', [
                     'redirect' => $request->getAttribute('normalizedParams')->getRequestUri(),
                 ]);
-                $newButton = '<a href="' . htmlspecialchars($createLink) . '" data-edit-url="' . htmlspecialchars($createLink) . '" class="btn btn-default disabled t3js-language-new-' . $languageId . '" title="' . $lang->sL(
+                $newButton = '<a href="' . htmlspecialchars($createLink) . '" data-edit-url="' . htmlspecialchars($createLink) . '" class="btn btn-default disabled t3js-language-new" data-lang="' . $languageId . '" title="' . $lang->sL(
                     'LLL:EXT:info/Resources/Private/Language/locallang_webinfo.xlf:lang_getlangsta_createNewTranslationHeaders'
                 ) . '">' . $this->iconFactory->getIcon('actions-document-new', Icon::SIZE_SMALL)->render() . '</a>';
 
diff --git a/typo3/sysext/info/Resources/Public/JavaScript/translation-status.js b/typo3/sysext/info/Resources/Public/JavaScript/translation-status.js
index 0cae51d18991..10c4762da609 100644
--- a/typo3/sysext/info/Resources/Public/JavaScript/translation-status.js
+++ b/typo3/sysext/info/Resources/Public/JavaScript/translation-status.js
@@ -10,4 +10,4 @@
  *
  * The TYPO3 project - inspiring people to share!
  */
-import $ from"jquery";class TranslationStatus{constructor(){this.registerEvents()}registerEvents(){$('input[type="checkbox"][data-lang]').on("change",this.toggleNewButton)}toggleNewButton(t){const e=$(t.currentTarget),a=parseInt(e.data("lang"),10),n=$(".t3js-language-new-"+a),s=$('input[type="checkbox"][data-lang="'+a+'"]:checked'),o=[];s.each(((t,e)=>{o.push("cmd[pages]["+e.dataset.uid+"][localize]="+a)}));const r=n.data("editUrl")+"&"+o.join("&");n.attr("href",r),n.toggleClass("disabled",0===s.length)}}export default new TranslationStatus;
\ No newline at end of file
+import RegularEvent from"@typo3/core/event/regular-event.js";class TranslationStatus{constructor(){this.registerEvents()}registerEvents(){new RegularEvent("click",this.toggleNewButton).delegateTo(document,'input[type="checkbox"][data-lang]')}toggleNewButton(){const t=document.querySelector(`.t3js-language-new[data-lang="${this.dataset.lang}"]`),e=document.querySelectorAll(`input[type="checkbox"][data-lang="${this.dataset.lang}"]:checked`),a=new URL(location.origin+t.dataset.editUrl);e.forEach((t=>{a.searchParams.set(`cmd[pages][${t.dataset.uid}][localize]`,this.dataset.lang)})),t.href=a.toString(),t.classList.toggle("disabled",0===e.length)}}export default new TranslationStatus;
\ No newline at end of file
-- 
GitLab