Commit 290d9d2c authored by Benni Mack's avatar Benni Mack
Browse files

[TASK] Reduce inline JavaScript in Page Module Paste logic

When having a content element on the clipboard (normal mode)
the page module dynamically shows paste icons
everywhere.

This change centralizes the generation of the Paste icons
into JavaScript, so the inline javascript usage of "top.*"
functionality to park code somewhere has been removed,
and the actual items are generated in JavaScript.

In addition, as this code is only affecting the page module
when a tt_content element is on the clipboard, the Paste.js
JS module is only loaded when appropriate, thus reducing
the actual loading time for "regular" visits on the Page Module.

The icon in the paste button is now loaded via a native web component,
and only necessary logic is used in the Paste JS module.

The outer rendering for the Page Module has been simplified,
moving this functionality all into PageLayoutController,
reducing cross-dependencies between the PageLayout* classes.

Resolves: #94840
Releases: master
Change-Id: I380df9a56bfff74684616732166f25c68bbc6dec
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/70488

Tested-by: core-ci's avatarcore-ci <typo3@b13.com>
Tested-by: Jochen's avatarJochen <rothjochen@gmail.com>
Tested-by: Oliver Bartsch's avatarOliver Bartsch <bo@cedev.de>
Tested-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
Reviewed-by: Wouter Wolters's avatarWouter Wolters <typo3@wouterwolters.nl>
Reviewed-by: Jochen's avatarJochen <rothjochen@gmail.com>
Reviewed-by: Oliver Bartsch's avatarOliver Bartsch <bo@cedev.de>
Reviewed-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
parent 2b4713ca
......@@ -13,14 +13,17 @@
/**
* Module: TYPO3/CMS/Backend/LayoutModule/Paste
* this JS code does the paste logic for the Layout module (Web => Page)
* based on jQuery UI
* Dynamically adds "Paste" Icons in the Page Layout module (Web => Page)
* 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 '../AjaxDataHandler/ResponseInterface';
import DataHandler = require('../AjaxDataHandler');
import Modal = require('../Modal');
import Severity = require('../Severity');
import 'TYPO3/CMS/Backend/Element/IconElement';
import {SeverityEnum} from '../Enum/Severity';
interface Button {
text: string;
......@@ -30,7 +33,12 @@ interface Button {
}
class Paste {
public itemOnClipboardUid: number = 0;
public itemOnClipboardTitle: string = '';
public copyMode: string = '';
private elementIdentifier: string = '.t3js-page-ce';
private pasteAfterLinkTemplate: string = '';
private pasteIntoLinkTemplate: string = '';
/**
* @param {JQuery} $element
......@@ -51,33 +59,57 @@ class Paste {
constructor() {
$((): void => {
if ($('.t3js-page-columns').length) {
this.generateButtonTemplates();
this.activatePasteIcons();
this.initializeEvents();
}
});
}
private initializeEvents(): void
{
$(document).on('click', '.t3js-paste', (evt: Event): void => {
evt.preventDefault();
this.activatePasteModal($(evt.currentTarget));
});
}
private generateButtonTemplates(): void
{
if (!this.itemOnClipboardUid) {
return;
}
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>';
}
/**
* activates the paste into / paste after icons outside of the context menus
*/
private activatePasteIcons(): void {
const me = this;
$('.t3-page-ce-wrapper-new-ce').each((index: number, el: HTMLElement): void => {
if (!$(el).find('.t3js-toggle-new-content-element-wizard').length) {
return;
}
$('.t3js-page-lang-column .t3-page-ce > .t3-page-ce').removeClass('t3js-page-ce');
if (top.pasteAfterLinkTemplate && top.pasteIntoLinkTemplate) {
if (this.pasteAfterLinkTemplate && this.pasteIntoLinkTemplate) {
const parent = $(el).parent();
// append the buttons
if (parent.data('page')) {
$(el).append(top.pasteIntoLinkTemplate);
$(el).append(this.pasteIntoLinkTemplate);
} else {
$(el).append(top.pasteAfterLinkTemplate);
$(el).append(this.pasteAfterLinkTemplate);
}
$(el).find('.t3js-paste').on('click', (evt: Event): void => {
evt.preventDefault();
me.activatePasteModal($(evt.currentTarget));
});
}
});
}
......@@ -85,15 +117,9 @@ class Paste {
/**
* generates the paste into / paste after modal
*/
private activatePasteModal(element: JQuery): void {
const me = this;
const $element = $(element);
const url = $element.data('url') || null;
const title = (TYPO3.lang['paste.modal.title.paste'] || 'Paste record') + ': "' + $element.data('title') + '"';
private activatePasteModal($element: JQuery): 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?';
const severity = (typeof top.TYPO3.Severity[$element.data('severity')] !== 'undefined') ?
top.TYPO3.Severity[$element.data('severity')] :
top.TYPO3.Severity.info;
let buttons: Array<Button> = [];
buttons = [
......@@ -107,20 +133,15 @@ class Paste {
},
{
text: TYPO3.lang['paste.modal.button.paste'] || 'Paste',
btnClass: 'btn-' + Severity.getCssClass(severity),
btnClass: 'btn-' + Severity.getCssClass(SeverityEnum.warning),
trigger: (): void => {
Modal.currentModal.trigger('modal-dismiss');
me.execute($element);
this.execute($element);
},
},
];
if (url !== null) {
const separator = url.contains('?') ? '&' : '?';
const params = $.param({data: $element.data()});
Modal.loadUrl(title, severity, buttons, url + separator + params);
} else {
Modal.show(title, content, severity, buttons);
}
Modal.show(title, content, SeverityEnum.warning, buttons);
}
/**
......@@ -150,11 +171,9 @@ class Paste {
};
DataHandler.process(parameters).then((result: ResponseInterface): void => {
if (result.hasErrors) {
return;
if (!result.hasErrors) {
window.location.reload();
}
window.location.reload();
});
}
}
......
......@@ -19,6 +19,7 @@ namespace TYPO3\CMS\Backend\Controller;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use TYPO3\CMS\Backend\Clipboard\Clipboard;
use TYPO3\CMS\Backend\Domain\Model\Element\ImmediateActionElement;
use TYPO3\CMS\Backend\Module\ModuleLoader;
use TYPO3\CMS\Backend\Routing\PreviewUriBuilder;
......@@ -28,6 +29,7 @@ use TYPO3\CMS\Backend\Template\ModuleTemplate;
use TYPO3\CMS\Backend\Template\ModuleTemplateFactory;
use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Backend\View\BackendLayoutView;
use TYPO3\CMS\Backend\View\Drawing\BackendLayoutRenderer;
use TYPO3\CMS\Backend\View\PageLayoutContext;
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
use TYPO3\CMS\Core\Database\ConnectionPool;
......@@ -599,6 +601,7 @@ class PageLayoutController
$content .= '</form>';
// Setting up the buttons for the docheader
$this->makeButtons($request);
$this->initializeClipboard($request);
// Create LanguageMenu
$this->makeLanguageMenu();
......@@ -618,6 +621,30 @@ class PageLayoutController
$this->moduleTemplate->setContent($content);
}
/**
* Initializes the clipboard for generating paste links dynamically via JavaScript after each "+ Content" symbol
*/
protected function initializeClipboard(ServerRequestInterface $request): void
{
$clipboard = GeneralUtility::makeInstance(Clipboard::class);
$clipboard->initializeClipboard($request);
$clipboard->lockToNormal();
$clipboard->cleanCurrent();
$clipboard->endClipboard();
$elFromTable = $clipboard->elFromTable('tt_content');
if (!empty($elFromTable) && $this->isContentEditable($this->current_sys_language)) {
$pasteItem = (int)substr((string)key($elFromTable), 11);
$pasteRecord = BackendUtility::getRecordWSOL('tt_content', $pasteItem);
$pasteTitle = BackendUtility::getRecordTitle('tt_content', $pasteRecord, false, true);
$this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/LayoutModule/Paste', '
function(Paste) {
Paste.itemOnClipboardUid = ' . $pasteItem . ';
Paste.itemOnClipboardTitle = ' . GeneralUtility::quoteJSvalue($pasteTitle) . ';
Paste.copyMode = ' . GeneralUtility::quoteJSvalue($clipboard->clipData['normal']['mode']) . ';
}');
}
}
/**
* Rendering content
*
......@@ -630,7 +657,6 @@ class PageLayoutController
$this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/Localization');
$this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/LayoutModule/DragDrop');
$this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/Modal');
$this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/LayoutModule/Paste');
$this->pageRenderer->loadRequireJsModule(ImmediateActionElement::MODULE_NAME);
$this->pageRenderer->addInlineLanguageLabelFile('EXT:backend/Resources/Private/Language/locallang_layout.xlf');
......@@ -654,8 +680,6 @@ class PageLayoutController
$numberOfHiddenElements = $this->getNumberOfHiddenElements($configuration->getLanguageColumns());
$pageLayoutDrawer = $this->context->getBackendLayoutRenderer();
$pageActionsCallback = null;
if ($this->context->isPageEditable()) {
$languageOverlayId = 0;
......@@ -672,7 +696,7 @@ class PageLayoutController
}';
}
$this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/PageActions', $pageActionsCallback);
$tableOutput = $pageLayoutDrawer->drawContent();
$tableOutput = GeneralUtility::makeInstance(BackendLayoutRenderer::class, $this->context)->drawContent();
}
if ($this->getBackendUser()->check('tables_select', 'tt_content') && $numberOfHiddenElements > 0) {
......@@ -979,6 +1003,7 @@ class PageLayoutController
return !$this->pageinfo['editlock']
&& $this->getBackendUser()->doesUserHaveAccess($this->pageinfo, Permission::CONTENT_EDIT)
&& $this->getBackendUser()->check('tables_modify', 'tt_content')
&& $this->getBackendUser()->checkLanguageAccess($languageId);
}
......
......@@ -17,8 +17,6 @@ declare(strict_types=1);
namespace TYPO3\CMS\Backend\View\Drawing;
use Psr\Log\LoggerAwareTrait;
use TYPO3\CMS\Backend\Clipboard\Clipboard;
use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Backend\View\BackendLayout\ContentFetcher;
use TYPO3\CMS\Backend\View\BackendLayout\Grid\Grid;
......@@ -29,13 +27,9 @@ use TYPO3\CMS\Backend\View\BackendLayout\Grid\LanguageColumn;
use TYPO3\CMS\Backend\View\BackendLayout\RecordRememberer;
use TYPO3\CMS\Backend\View\PageLayoutContext;
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
use TYPO3\CMS\Core\Imaging\Icon;
use TYPO3\CMS\Core\Imaging\IconFactory;
use TYPO3\CMS\Core\Localization\LanguageService;
use TYPO3\CMS\Core\Messaging\FlashMessage;
use TYPO3\CMS\Core\Messaging\FlashMessageService;
use TYPO3\CMS\Core\Page\PageRenderer;
use TYPO3\CMS\Core\Type\Bitmask\Permission;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Mvc\Request;
use TYPO3\CMS\Fluid\View\TemplateView;
......@@ -47,46 +41,18 @@ use TYPO3\CMS\Fluid\View\TemplateView;
* which renders the Resources/Private/PageLayout/PageLayout template
* with necessary assigned template variables.
*
* - Initializes the clipboard used in the page layout
* - Inserts an encoded paste icon as JS which is made visible when clipboard elements are registered
*
* @internal this is experimental and subject to change in TYPO3 v10 / v11
*/
class BackendLayoutRenderer
{
use LoggerAwareTrait;
/**
* @var IconFactory
*/
protected $iconFactory;
/**
* @var PageLayoutContext
*/
protected $context;
/**
* @var ContentFetcher
*/
protected $contentFetcher;
/**
* @var Clipboard
*/
protected $clipboard;
/**
* @var TemplateView
*/
protected $view;
protected PageLayoutContext $context;
protected ContentFetcher $contentFetcher;
protected TemplateView $view;
public function __construct(PageLayoutContext $context)
{
$this->context = $context;
$this->contentFetcher = GeneralUtility::makeInstance(ContentFetcher::class, $context);
$this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
$this->initializeClipboard();
$this->view = GeneralUtility::makeInstance(TemplateView::class);
$this->view->getRenderingContext()->setRequest(GeneralUtility::makeInstance(Request::class));
$this->view->getRenderingContext()->getTemplatePaths()->fillDefaultsByPackageName('backend');
......@@ -125,7 +91,7 @@ class BackendLayoutRenderer
/**
* @return LanguageColumn[]
*/
public function getLanguageColumnsForPageLayoutContext(PageLayoutContext $context): iterable
protected function getLanguageColumnsForPageLayoutContext(PageLayoutContext $context): iterable
{
$languageColumns = [];
foreach ($context->getLanguagesToShow() as $siteLanguage) {
......@@ -279,79 +245,6 @@ class BackendLayoutRenderer
return $rendered;
}
/**
* Initializes the clipboard for generating paste links
*
* @see \TYPO3\CMS\Backend\Controller\ContextMenuController::clipboardAction()
* @see \TYPO3\CMS\Filelist\Controller\FileListController::indexAction()
*/
protected function initializeClipboard(): void
{
$this->clipboard = GeneralUtility::makeInstance(Clipboard::class);
$this->clipboard->initializeClipboard();
$this->clipboard->lockToNormal();
$this->clipboard->cleanCurrent();
$this->clipboard->endClipboard();
$elFromTable = $this->clipboard->elFromTable('tt_content');
if (!empty($elFromTable) && $this->isContentEditable()) {
$pasteItem = (int)substr((string)key($elFromTable), 11);
$pasteRecord = BackendUtility::getRecord('tt_content', (int)$pasteItem);
$pasteTitle = (string)($pasteRecord['header'] ?: $pasteItem);
$copyMode = $this->clipboard->clipData['normal']['mode'] ? '-' . $this->clipboard->clipData['normal']['mode'] : '';
$addExtOnReadyCode = '
top.pasteIntoLinkTemplate = '
. $this->drawPasteIcon($pasteItem, $pasteTitle, $copyMode, 't3js-paste-into', 'pasteIntoColumn')
. ';
top.pasteAfterLinkTemplate = '
. $this->drawPasteIcon($pasteItem, $pasteTitle, $copyMode, 't3js-paste-after', 'pasteAfterRecord')
. ';';
} else {
$addExtOnReadyCode = '
top.pasteIntoLinkTemplate = \'\';
top.pasteAfterLinkTemplate = \'\';';
}
GeneralUtility::makeInstance(PageRenderer::class)->addJsInlineCode('pasteLinkTemplates', $addExtOnReadyCode);
}
/**
* Draw a paste icon either for pasting into a column or for pasting after a record
*
* @param int $pasteItem ID of the item in the clipboard
* @param string $pasteTitle Title for the JS modal
* @param string $copyMode copy or cut
* @param string $cssClass CSS class to determine if pasting is done into column or after record
* @param string $title title attribute of the generated link
*
* @return string Generated HTML code with link and icon
*/
private function drawPasteIcon(int $pasteItem, string $pasteTitle, string $copyMode, string $cssClass, string $title): string
{
$pasteIcon = json_encode(
' <button type="button"'
. ' data-bs-content="' . htmlspecialchars((string)$pasteItem) . '"'
. ' data-title="' . htmlspecialchars($pasteTitle) . '"'
. ' data-severity="warning"'
. ' class="t3js-paste t3js-paste' . htmlspecialchars($copyMode) . ' ' . htmlspecialchars($cssClass) . ' btn btn-default btn-sm"'
. ' title="' . htmlspecialchars($this->getLanguageService()->getLL($title)) . '">'
. $this->iconFactory->getIcon('actions-document-paste-into', Icon::SIZE_SMALL)->render()
. '</button>'
);
return $pasteIcon;
}
protected function isContentEditable(): bool
{
if ($this->getBackendUser()->isAdmin()) {
return true;
}
$pageRecord = $this->context->getPageRecord();
return !$pageRecord['editlock']
&& $this->getBackendUser()->check('tables_modify', 'tt_content')
&& $this->getBackendUser()->doesUserHaveAccess($pageRecord, Permission::CONTENT_EDIT);
}
protected function getBackendUser(): BackendUserAuthentication
{
return $GLOBALS['BE_USER'];
......
......@@ -21,7 +21,6 @@ use TYPO3\CMS\Backend\Routing\UriBuilder;
use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Backend\View\BackendLayout\BackendLayout;
use TYPO3\CMS\Backend\View\BackendLayout\ContentFetcher;
use TYPO3\CMS\Backend\View\Drawing\BackendLayoutRenderer;
use TYPO3\CMS\Backend\View\Drawing\DrawingConfiguration;
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
use TYPO3\CMS\Core\Database\ConnectionPool;
......@@ -56,11 +55,6 @@ class PageLayoutContext
*/
protected $contentFetcher;
/**
* @var BackendLayoutRenderer
*/
protected $backendLayoutRenderer;
/**
* @var array
*/
......@@ -125,7 +119,6 @@ class PageLayoutContext
$this->backendLayout = $backendLayout;
$this->drawingConfiguration = GeneralUtility::makeInstance(DrawingConfiguration::class);
$this->contentFetcher = GeneralUtility::makeInstance(ContentFetcher::class, $this);
$this->backendLayoutRenderer = GeneralUtility::makeInstance(BackendLayoutRenderer::class, $this);
$this->siteLanguages = $this->site->getAvailableLanguages($this->getBackendUser(), true, $this->pageId);
$this->siteLanguage = $this->site->getDefaultLanguage();
}
......@@ -168,11 +161,6 @@ class PageLayoutContext
return $this->drawingConfiguration;
}
public function getBackendLayoutRenderer(): BackendLayoutRenderer
{
return $this->backendLayoutRenderer;
}
public function getBackendUser(): BackendUserAuthentication
{
return $GLOBALS['BE_USER'];
......
......@@ -20,7 +20,6 @@ use Doctrine\DBAL\Statement;
use Psr\EventDispatcher\EventDispatcherInterface;
use Psr\Log\LoggerAwareInterface;
use Psr\Log\LoggerAwareTrait;
use TYPO3\CMS\Backend\Clipboard\Clipboard;
use TYPO3\CMS\Backend\Controller\Page\LocalizationController;
use TYPO3\CMS\Backend\Routing\PreviewUriBuilder;
use TYPO3\CMS\Backend\Routing\UriBuilder;
......@@ -146,11 +145,6 @@ class PageLayoutView implements LoggerAwareInterface
*/
protected $siteLanguages = [];
/**
* @var Clipboard
*/
protected $clipboard;
/**
* Current ids page record
*
......@@ -243,7 +237,6 @@ class PageLayoutView implements LoggerAwareInterface
{
$this->resolveSiteLanguages($this->id);
$this->pageRecord = BackendUtility::getRecordWSOL('pages', $this->id);
$this->initializeClipboard();
$this->pageinfo = BackendUtility::readPageAccess($this->id, '') ?: [];
$pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
$pageActionsCallback = null;
......@@ -651,26 +644,6 @@ class PageLayoutView implements LoggerAwareInterface
$out .= $grid . '</table></div>';
}
}
$elFromTable = $this->clipboard->elFromTable('tt_content');
if (!empty($elFromTable) && $this->isContentEditable()) {
$pasteItem = (int)substr((string)key($elFromTable), 11);
$pasteRecord = BackendUtility::getRecord('tt_content', $pasteItem);
$pasteTitle = $pasteRecord['header'] ?: (string)$pasteItem;
$copyMode = $this->clipboard->clipData['normal']['mode'] ? '-' . $this->clipboard->clipData['normal']['mode'] : '';
$inlineJavaScript = '
top.pasteIntoLinkTemplate = '
. $this->tt_content_drawPasteIcon($pasteItem, $pasteTitle, $copyMode, 't3js-paste-into', 'pasteIntoColumn')
. ';
top.pasteAfterLinkTemplate = '
. $this->tt_content_drawPasteIcon($pasteItem, $pasteTitle, $copyMode, 't3js-paste-after', 'pasteAfterRecord')
. ';';
} else {
$inlineJavaScript = '
top.pasteIntoLinkTemplate = \'\';
top.pasteAfterLinkTemplate = \'\';';
}
$pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
$pageRenderer->addJsInlineCode('pasteLinkTemplates', $inlineJavaScript);
// If language mode, then make another presentation:
// Notice that THIS presentation will override the value of $out!
// But it needs the code above to execute since $languageColumn is filled with content we need!
......@@ -951,32 +924,6 @@ class PageLayoutView implements LoggerAwareInterface
</div>';
}
/**
* Draw a paste icon either for pasting into a column or for pasting after a record
*
* @param int $pasteItem ID of the item in the clipboard
* @param string $pasteTitle Title for the JS modal
* @param string $copyMode copy or cut
* @param string $cssClass CSS class to determine if pasting is done into column or after record
* @param string $title title attribute of the generated link
*
* @return string Generated HTML code with link and icon
*/
protected function tt_content_drawPasteIcon($pasteItem, $pasteTitle, $copyMode, $cssClass, $title)
{
$pasteIcon = json_encode(
' <button type="button"'
. ' data-bs-content="' . htmlspecialchars((string)$pasteItem) . '"'
. ' data-title="' . htmlspecialchars($pasteTitle) . '"'
. ' data-severity="warning"'
. ' class="t3js-paste t3js-paste' . htmlspecialchars($copyMode) . ' ' . htmlspecialchars($cssClass) . ' btn btn-default btn-sm"'
. ' title="' . htmlspecialchars($this->getLanguageService()->getLL($title)) . '">'
. $this->iconFactory->getIcon('actions-document-paste-into', Icon::SIZE_SMALL)->render()
. '</button>'
);
return $pasteIcon;
}
/**
* Draw the footer for a single tt_content element
*
......@@ -1645,31 +1592,6 @@ class PageLayoutView implements LoggerAwareInterface
*
********************************/
/**
* Initializes the clipboard for generating paste links
*
*
* @see \TYPO3\CMS\Backend\Controller\ContextMenuController::clipboardAction()
* @see \TYPO3\CMS\Filelist\Controller\FileListController::indexAction()
*/
protected function initializeClipboard()
{
// Start clipboard
$this->clipboard = GeneralUtility::makeInstance(Clipboard::class);
// Initialize - reads the clipboard content from the user session
$this->clipboard->initializeClipboard();
// This locks the clipboard to the Normal for this request.
$this->clipboard->lockToNormal();
// Clean up pad
$this->clipboard->cleanCurrent();
// Save the clipboard content
$this->clipboard->endClipboard();
}
/**
* Generates the data for previous and next elements which is needed for movements.
*
......
......@@ -10,4 +10,4 @@
*
* The TYPO3 project - inspiring people to share!
*/
var __importDefault=this&&this.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};define(["require","exports","jquery","../AjaxDataHandler","../Modal","../Severity"],(function(t,e,a,s,n,l){"use strict";a=__importDefault(a);class o{constructor(){this.elementIdentifier=".t3js-page-ce",a.default(()=>{a.default(".t3js-page-columns").length&&this.activatePasteIcons()})}static determineColumn(t){const e=t.closest("[data-colpos]");return e.length&&"undefined"!==e.data("colpos")?e.data("colpos"):0}activatePasteIcons(){const t=this;a.default(".t3-page-ce-wrapper-new-ce").each((e,s)=>{if(a.default(s).find(".t3js-toggle-new-content-element-wizard").length&&(a.default(".t3js-page-lang-column .t3-page-ce > .t3-page-ce").removeClass("t3js-page-ce"),top.pasteAfterLinkTemplate&&top.pasteIntoLinkTemplate)){a.default(s).parent().data("page")?a.default(s).append(top.pasteIntoLinkTemplate):a.default(s).append(top.pasteAfterLinkTemplate),a.default(s).find(".t3js-paste").on("click",e=>{e.preventDefault(),t.activatePasteModal(a.default(e.currentTarget))})}})}activatePasteModal(t){const e=this,s=a.default(t),o=s.data("url")||null,d=(TYPO3.lang["paste.modal.title.paste"]||"Paste record")+': "'+s.data("title")+'"',i=TYPO3.lang["paste.modal.paste"]||"Do you want to paste the record to this position?",r=void 0!==top.TYPO3.Severity[s.data("severity")]?top.TYPO3.Severity[s.data("severity")]:top.TYPO3.Severity.info;let p=[];if(p=[{text:TYPO3.lang["paste.modal.button.cancel"]||"Cancel",active:!0,btnClass:"btn-default",trigger:()=>{n.currentModal.trigger("modal-dismiss")}},{text:TYPO3.lang["paste.modal.button.paste"]||"Paste",btnClass:"btn-"+l.getCssClass(r),trigger:()=>{n.currentModal.trigger("modal-dismiss"),e.execute(s)}}],null!==o){const t=o.contains("?")?"&":"?",e=a.default.param({data:s.data()});n.loadUrl(d,r,p,o+t+e)}else n.show(d,i,r,p)}execute(t){const e=o.determineColumn(t),a=t.closest(this.elementIdentifier),n=a.data("uid");let l;l=void 0===n?parseInt(a.data("page"),10):0-parseInt(n,10);const d={CB:{paste:"tt_content|"+l,update:{colPos:e,sys_language_uid:parseInt(t.closest("[data-language-uid]").data("language-uid"),10)}}};s.process(d).then(t=>{t.hasErrors||window.location.reload()})}}return new o}));
\ No newline at end of file
var __importDefault=this&&this.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};define(["require","exports","jquery","../AjaxDataHandler","../Modal","../Severity","../Enum/Severity","TYPO3/CMS/Backend/Element/IconElement"],(function(t,e,a,n,s,i,o){"use strict";a=__importDefault(a);class l{constructor(){this.itemOnClipboardUid=0,this.itemOnClipboardTitle="",this.copyMode="",this.elementIdentifier=".t3js-page-ce",this.pasteAfterLinkTemplate="",this.pasteIntoLinkTemplate="",a.default(()=>{a.default(".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(){a.default(document).on("click",".t3js-paste",t=>{t.preventDefault(),this.activatePasteModal(a.default(t.currentTarget))})}generateButtonTemplates(){var t,e;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="'+(null===(t=TYPO3.lang)||void 0===t?void 0:t.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="'+(null===(e=TYPO3.lang)||void 0===e?void 0:e.pasteIntoColumn)+'"><typo3-backend-icon identifier="actions-document-paste-into" size="small"></typo3-backend-icon></button>')}activatePasteIcons(){a.default(".t3-page-ce-wrapper-new-ce").each((t,e)=>{if(a.default(e).find(".t3js-toggle-new-content-element-wizard").length&&(a.default(".t3js-page-lang-column .t3-page-ce > .t3-page-ce").removeClass("t3js-page-ce"),this.pasteAfterLinkTemplate&&this.pasteIntoLinkTemplate)){a.default(e).parent().data("page")?a.default(e).append(this.pasteIntoLinkTemplate):a.default(e).append(this.pasteAfterLinkTemplate)}})}activatePasteModal(t){const e=(TYPO3.lang["paste.modal.title.paste"]||"Paste record