From a8861f19b7d0a34bd05a09290e19283ba8afe7c5 Mon Sep 17 00:00:00 2001 From: Andreas Fernandez <a.fernandez@scripting-base.de> Date: Tue, 8 Aug 2023 15:01:30 +0200 Subject: [PATCH] [TASK] Migrate from jQuery in `@typo3/backend/layout-module/paste` This patch removes jQuery from the `@typo3/backend/layout-module/paste` module in favor of native APIs. Resolves: #101617 Releases: main Change-Id: I201eaf575a328bc805dc0fb90a364a918686900a Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/80460 Reviewed-by: Andreas Nedbal <andy@pixelde.su> Tested-by: Nikita Hovratov <nikita.h@live.de> Tested-by: Andreas Fernandez <a.fernandez@scripting-base.de> Tested-by: Andreas Nedbal <andy@pixelde.su> Reviewed-by: Nikita Hovratov <nikita.h@live.de> Tested-by: core-ci <typo3@b13.com> Reviewed-by: Andreas Fernandez <a.fernandez@scripting-base.de> --- .../TypeScript/backend/layout-module/paste.ts | 48 ++++++++----------- .../Public/JavaScript/layout-module/paste.js | 2 +- 2 files changed, 20 insertions(+), 30 deletions(-) diff --git a/Build/Sources/TypeScript/backend/layout-module/paste.ts b/Build/Sources/TypeScript/backend/layout-module/paste.ts index 0f6b1f96e9fc..e96b161f77f5 100644 --- a/Build/Sources/TypeScript/backend/layout-module/paste.ts +++ b/Build/Sources/TypeScript/backend/layout-module/paste.ts @@ -18,13 +18,13 @@ import DocumentService from '@typo3/core/document-service'; * and triggers a modal window. which then calls the AjaxDataHandler * to execute the action to paste the current clipboard contents. */ -import $ from 'jquery'; import ResponseInterface from '../ajax-data-handler/response-interface'; import DataHandler from '../ajax-data-handler'; import { default as Modal, ModalElement, Button } from '@typo3/backend/modal'; import Severity from '../severity'; import '@typo3/backend/element/icon-element'; import { SeverityEnum } from '../enum/severity'; +import RegularEvent from '@typo3/core/event/regular-event'; type PasteOptions = { itemOnClipboardUid: number; @@ -49,7 +49,7 @@ class Paste { this.copyMode = args.copyMode; DocumentService.ready().then((): void => { - if ($('.t3js-page-columns').length) { + if (document.querySelectorAll('.t3js-page-columns').length > 0) { this.generateButtonTemplates(); this.activatePasteIcons(); this.initializeEvents(); @@ -57,29 +57,21 @@ class Paste { }); } - /** - * @param {JQuery} $element - * @return number - */ - private static determineColumn($element: JQuery): number { - const $columnContainer = $element.closest('[data-colpos]'); - if ($columnContainer.length && $columnContainer.data('colpos') !== 'undefined') { - return $columnContainer.data('colpos'); - } - - return 0; + private static determineColumn(element: HTMLElement): number { + const columnContainer = element.closest('[data-colpos]') as HTMLElement|null; + return parseInt(columnContainer?.dataset?.colpos ?? '0', 10); } private initializeEvents(): void { - $(document).on('click', '.t3js-paste', (evt: Event): void => { + new RegularEvent('click', (evt: Event, target: HTMLElement): void => { evt.preventDefault(); - this.activatePasteModal($(evt.currentTarget)); - }); + + this.activatePasteModal(target); + }).delegateTo(document, '.t3js-paste'); } - private generateButtonTemplates(): void - { + private generateButtonTemplates(): void { if (!this.itemOnClipboardUid) { return; } @@ -98,7 +90,7 @@ class Paste { } /** - * activates the paste into / paste after icons outside of the context menus + * activates the paste into / paste after icons outside the context menus */ private activatePasteIcons(): void { if (this.pasteAfterLinkTemplate && this.pasteIntoLinkTemplate) { @@ -112,7 +104,7 @@ class Paste { /** * generates the paste into / paste after modal */ - private activatePasteModal($element: JQuery): void { + private activatePasteModal(element: HTMLElement): void { const title = (TYPO3.lang['paste.modal.title.paste'] || 'Paste record') + ': "' + this.itemOnClipboardTitle + '"'; const content = TYPO3.lang['paste.modal.paste'] || 'Do you want to paste the record to this position?'; @@ -129,7 +121,7 @@ class Paste { btnClass: 'btn-' + Severity.getCssClass(SeverityEnum.warning), trigger: (e: Event, modal: ModalElement): void => { modal.hideModal(); - this.execute($element); + this.execute(element); }, }, ]; @@ -139,20 +131,18 @@ class Paste { /** * Send an AJAX request via the AjaxDataHandler - * - * @param {JQuery} $element */ - private execute($element: JQuery): void { - const colPos = Paste.determineColumn($element); - const closestElement = $element.closest(this.elementIdentifier); - const targetFound = closestElement.data('uid'); + private execute(element: HTMLElement): void { + const colPos = Paste.determineColumn(element); + const closestElement = element.closest(this.elementIdentifier) as HTMLElement; + const targetFound = closestElement.dataset.uid; let targetPid; if (typeof targetFound === 'undefined') { - targetPid = parseInt(closestElement.data('page'), 10); + targetPid = parseInt(closestElement.dataset.page, 10); } else { targetPid = 0 - parseInt(targetFound, 10); } - const language = parseInt($element.closest('[data-language-uid]').data('language-uid'), 10); + const language = parseInt((element.closest('[data-language-uid]') as HTMLElement).dataset.languageUid, 10); const parameters = { CB: { paste: 'tt_content|' + targetPid, diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/layout-module/paste.js b/typo3/sysext/backend/Resources/Public/JavaScript/layout-module/paste.js index 3da07f16b6bd..8e2132dc367a 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/layout-module/paste.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/layout-module/paste.js @@ -10,4 +10,4 @@ * * The TYPO3 project - inspiring people to share! */ -import DocumentService from"@typo3/core/document-service.js";import $ from"jquery";import DataHandler from"@typo3/backend/ajax-data-handler.js";import{default as Modal}from"@typo3/backend/modal.js";import Severity from"@typo3/backend/severity.js";import"@typo3/backend/element/icon-element.js";import{SeverityEnum}from"@typo3/backend/enum/severity.js";class Paste{constructor(t){this.itemOnClipboardUid=0,this.itemOnClipboardTitle="",this.copyMode="",this.elementIdentifier=".t3js-page-ce",this.pasteAfterLinkTemplate="",this.pasteIntoLinkTemplate="",this.itemOnClipboardUid=t.itemOnClipboardUid,this.itemOnClipboardTitle=t.itemOnClipboardTitle,this.copyMode=t.copyMode,DocumentService.ready().then((()=>{$(".t3js-page-columns").length&&(this.generateButtonTemplates(),this.activatePasteIcons(),this.initializeEvents())}))}static determineColumn(t){const e=t.closest("[data-colpos]");return e.length&&"undefined"!==e.data("colpos")?e.data("colpos"):0}initializeEvents(){$(document).on("click",".t3js-paste",(t=>{t.preventDefault(),this.activatePasteModal($(t.currentTarget))}))}generateButtonTemplates(){this.itemOnClipboardUid&&(this.pasteAfterLinkTemplate='<button type="button" class="t3js-paste t3js-paste'+(this.copyMode?"-"+this.copyMode:"")+' t3js-paste-after btn btn-default btn-sm" title="'+TYPO3.lang?.pasteAfterRecord+'"><typo3-backend-icon identifier="actions-document-paste-into" size="small"></typo3-backend-icon></button>',this.pasteIntoLinkTemplate='<button type="button" class="t3js-paste t3js-paste'+(this.copyMode?"-"+this.copyMode:"")+' t3js-paste-into btn btn-default btn-sm" title="'+TYPO3.lang?.pasteIntoColumn+'"><typo3-backend-icon identifier="actions-document-paste-into" size="small"></typo3-backend-icon></button>')}activatePasteIcons(){this.pasteAfterLinkTemplate&&this.pasteIntoLinkTemplate&&document.querySelectorAll(".t3js-page-new-ce").forEach((t=>{const e=t.parentElement.dataset.page?this.pasteIntoLinkTemplate:this.pasteAfterLinkTemplate;t.append(document.createRange().createContextualFragment(e))}))}activatePasteModal(t){const e=(TYPO3.lang["paste.modal.title.paste"]||"Paste record")+': "'+this.itemOnClipboardTitle+'"',a=TYPO3.lang["paste.modal.paste"]||"Do you want to paste the record to this position?";let n=[];n=[{text:TYPO3.lang["paste.modal.button.cancel"]||"Cancel",active:!0,btnClass:"btn-default",trigger:(t,e)=>e.hideModal()},{text:TYPO3.lang["paste.modal.button.paste"]||"Paste",btnClass:"btn-"+Severity.getCssClass(SeverityEnum.warning),trigger:(e,a)=>{a.hideModal(),this.execute(t)}}],Modal.show(e,a,SeverityEnum.warning,n)}execute(t){const e=Paste.determineColumn(t),a=t.closest(this.elementIdentifier),n=a.data("uid");let s;s=void 0===n?parseInt(a.data("page"),10):0-parseInt(n,10);const i={CB:{paste:"tt_content|"+s,pad:"normal",update:{colPos:e,sys_language_uid:parseInt(t.closest("[data-language-uid]").data("language-uid"),10)}}};DataHandler.process(i).then((t=>{t.hasErrors||window.location.reload()}))}}export default Paste; \ No newline at end of file +import DocumentService from"@typo3/core/document-service.js";import DataHandler from"@typo3/backend/ajax-data-handler.js";import{default as Modal}from"@typo3/backend/modal.js";import Severity from"@typo3/backend/severity.js";import"@typo3/backend/element/icon-element.js";import{SeverityEnum}from"@typo3/backend/enum/severity.js";import RegularEvent from"@typo3/core/event/regular-event.js";class Paste{constructor(t){this.itemOnClipboardUid=0,this.itemOnClipboardTitle="",this.copyMode="",this.elementIdentifier=".t3js-page-ce",this.pasteAfterLinkTemplate="",this.pasteIntoLinkTemplate="",this.itemOnClipboardUid=t.itemOnClipboardUid,this.itemOnClipboardTitle=t.itemOnClipboardTitle,this.copyMode=t.copyMode,DocumentService.ready().then((()=>{document.querySelectorAll(".t3js-page-columns").length>0&&(this.generateButtonTemplates(),this.activatePasteIcons(),this.initializeEvents())}))}static determineColumn(t){const e=t.closest("[data-colpos]");return parseInt(e?.dataset?.colpos??"0",10)}initializeEvents(){new RegularEvent("click",((t,e)=>{t.preventDefault(),this.activatePasteModal(e)})).delegateTo(document,".t3js-paste")}generateButtonTemplates(){this.itemOnClipboardUid&&(this.pasteAfterLinkTemplate='<button type="button" class="t3js-paste t3js-paste'+(this.copyMode?"-"+this.copyMode:"")+' t3js-paste-after btn btn-default btn-sm" title="'+TYPO3.lang?.pasteAfterRecord+'"><typo3-backend-icon identifier="actions-document-paste-into" size="small"></typo3-backend-icon></button>',this.pasteIntoLinkTemplate='<button type="button" class="t3js-paste t3js-paste'+(this.copyMode?"-"+this.copyMode:"")+' t3js-paste-into btn btn-default btn-sm" title="'+TYPO3.lang?.pasteIntoColumn+'"><typo3-backend-icon identifier="actions-document-paste-into" size="small"></typo3-backend-icon></button>')}activatePasteIcons(){this.pasteAfterLinkTemplate&&this.pasteIntoLinkTemplate&&document.querySelectorAll(".t3js-page-new-ce").forEach((t=>{const e=t.parentElement.dataset.page?this.pasteIntoLinkTemplate:this.pasteAfterLinkTemplate;t.append(document.createRange().createContextualFragment(e))}))}activatePasteModal(t){const e=(TYPO3.lang["paste.modal.title.paste"]||"Paste record")+': "'+this.itemOnClipboardTitle+'"',a=TYPO3.lang["paste.modal.paste"]||"Do you want to paste the record to this position?";let n=[];n=[{text:TYPO3.lang["paste.modal.button.cancel"]||"Cancel",active:!0,btnClass:"btn-default",trigger:(t,e)=>e.hideModal()},{text:TYPO3.lang["paste.modal.button.paste"]||"Paste",btnClass:"btn-"+Severity.getCssClass(SeverityEnum.warning),trigger:(e,a)=>{a.hideModal(),this.execute(t)}}],Modal.show(e,a,SeverityEnum.warning,n)}execute(t){const e=Paste.determineColumn(t),a=t.closest(this.elementIdentifier),n=a.dataset.uid;let s;s=void 0===n?parseInt(a.dataset.page,10):0-parseInt(n,10);const o={CB:{paste:"tt_content|"+s,pad:"normal",update:{colPos:e,sys_language_uid:parseInt(t.closest("[data-language-uid]").dataset.languageUid,10)}}};DataHandler.process(o).then((t=>{t.hasErrors||window.location.reload()}))}}export default Paste; \ No newline at end of file -- GitLab