Commit bdc9b55f authored by Andreas Fernandez's avatar Andreas Fernandez Committed by Daniel Goerz
Browse files

[TASK] Move clipboard inline JavaScript into separate modules

This patch moves the inline JavaScript for clipboard handling into a
separate module that is re-used in record list and in file list.

Additionally, the function `editList` only used in record list context
has been moved into the according module.

Resolves: #89476
Releases: master
Change-Id: I43c972aadd8cd097850139813a01c3560a9b202c
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/62041

Tested-by: default avatarTYPO3com <noreply@typo3.com>
Tested-by: Susanne Moog's avatarSusanne Moog <look@susi.dev>
Tested-by: Daniel Goerz's avatarDaniel Goerz <daniel.goerz@posteo.de>
Reviewed-by: Susanne Moog's avatarSusanne Moog <look@susi.dev>
Reviewed-by: Daniel Goerz's avatarDaniel Goerz <daniel.goerz@posteo.de>
parent 3f2d98c4
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
class ClipboardComponent {
private static setCheckboxValue(checkboxName: string, check: boolean): void {
const fullName = 'CBC[' + checkboxName + ']';
const checkboxElement: HTMLInputElement = document.querySelector('form[name="dblistForm"] [name="' + fullName + '"]');
if (checkboxElement !== null) {
checkboxElement.checked = check;
}
}
constructor() {
this.registerCheckboxTogglers();
}
private registerCheckboxTogglers(): void {
const selector = 'a.t3js-toggle-all-checkboxes';
document.addEventListener('click', (e: Event): void => {
let target = <HTMLElement>e.target;
if (!target.matches(selector)) {
let closest: HTMLElement = target.closest(selector);
if (closest !== null) {
target = closest;
} else {
return;
}
}
e.preventDefault();
let flagAll: boolean;
if (target.getAttribute('rel') === '') {
target.setAttribute('rel', 'allChecked');
flagAll = true;
} else {
target.setAttribute('rel', '');
flagAll = false;
}
const listOfCheckboxNames: Array<string> = target.dataset.checkboxesNames.split(',');
for (let checkboxName of listOfCheckboxNames) {
ClipboardComponent.setCheckboxValue(checkboxName, flagAll);
}
});
}
}
export = new ClipboardComponent();
......@@ -17,7 +17,6 @@ import Icons = require('TYPO3/CMS/Backend/Icons');
declare global {
const T3_THIS_LOCATION: string;
const editList: Function;
}
interface IconIdentifier {
......@@ -131,7 +130,7 @@ class Recordlist {
$.each(pipes, (pipeIndex: string, pipe: string): void => {
if (pipe === 'editList') {
value = editList(tableName, value);
value = this.editList(tableName, value);
}
});
......@@ -141,11 +140,37 @@ class Recordlist {
window.location.href = uri;
}
private editList(table: string, idList: string): string {
const list: Array<string> = [];
let pointer = 0;
let pos = idList.indexOf(',');
while (pos !== -1) {
if (this.getCheckboxState(table + '|' + idList.substr(pointer, pos - pointer))) {
list.push(idList.substr(pointer, pos - pointer));
}
pointer = pos + 1;
pos = idList.indexOf(',', pointer);
}
if (this.getCheckboxState(table + '|' + idList.substr(pointer))) {
list.push(idList.substr(pointer));
}
return list.length > 0 ? list.join(',') : idList;
}
private disableButton = (event: JQueryEventObject): void => {
const $me = $(event.currentTarget);
$me.prop('disable', true).addClass('disabled');
}
private getCheckboxState(CBname: string): boolean {
const fullName = 'CBC[' + CBname + ']';
const checkbox: HTMLInputElement = document.querySelector('form[name="dblistForm"] [name="' + fullName + '"]');
return checkbox.checked;
}
}
export = new Recordlist();
......@@ -4010,45 +4010,6 @@ class PageLayoutView implements LoggerAwareInterface
return strpos($this->thisScript, '?') === false ? $this->thisScript . '?' : $this->thisScript . '&';
}
/**
* Returning JavaScript for ClipBoard functionality.
*
* @return string
*/
public function CBfunctions()
{
return '
// checkOffCB()
function checkOffCB(listOfCBnames, link) { //
var checkBoxes, flag, i;
var checkBoxes = listOfCBnames.split(",");
if (link.rel === "") {
link.rel = "allChecked";
flag = true;
} else {
link.rel = "";
flag = false;
}
for (i = 0; i < checkBoxes.length; i++) {
setcbValue(checkBoxes[i], flag);
}
}
// cbValue()
function cbValue(CBname) { //
var CBfullName = "CBC["+CBname+"]";
return (document.dblistForm[CBfullName] && document.dblistForm[CBfullName].checked ? 1 : 0);
}
// setcbValue()
function setcbValue(CBname,flag) { //
CBfullName = "CBC["+CBname+"]";
if(document.dblistForm[CBfullName]) {
document.dblistForm[CBfullName].checked = flag ? "on" : 0;
}
}
';
}
/**
* Initializes page languages
*/
......
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
define(["require","exports"],function(e,t){"use strict";class r{static setCheckboxValue(e,t){const r="CBC["+e+"]",s=document.querySelector('form[name="dblistForm"] [name="'+r+'"]');null!==s&&(s.checked=t)}constructor(){this.registerCheckboxTogglers()}registerCheckboxTogglers(){const e="a.t3js-toggle-all-checkboxes";document.addEventListener("click",t=>{let s,c=t.target;if(!c.matches(e)){let t=c.closest(e);if(null===t)return;c=t}t.preventDefault(),""===c.getAttribute("rel")?(c.setAttribute("rel","allChecked"),s=!0):(c.setAttribute("rel",""),s=!1);const l=c.dataset.checkboxesNames.split(",");for(let e of l)r.setCheckboxValue(e,s)})}}return new r});
\ No newline at end of file
......@@ -389,9 +389,10 @@ class FileListController extends ActionController implements LoggerAwareInterfac
// Set top JavaScript:
$this->view->getModuleTemplate()->addJavaScriptCode(
'FileListIndex',
'if (top.fsMod) top.fsMod.recentIds["file"] = "' . rawurlencode($this->id) . '";' . $this->filelist->CBfunctions() . '
'if (top.fsMod) top.fsMod.recentIds["file"] = "' . rawurlencode($this->id) . '";
'
);
$pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/ClipboardComponent');
$pageRenderer->loadRequireJsModule('TYPO3/CMS/Filelist/FileDelete');
$pageRenderer->addInlineLanguageLabelFile('EXT:backend/Resources/Private/Language/locallang_alt_doc.xlf', 'buttons');
......
......@@ -506,8 +506,7 @@ class FileList
if ($this->folderObject->checkActionPermission('delete')) {
$cells[] = $this->linkClipboardHeaderIcon('<span title="' . htmlspecialchars($this->getLanguageService()->getLL('clip_deleteMarked')) . '">' . $this->iconFactory->getIcon('actions-edit-delete', Icon::SIZE_SMALL)->render(), $table, 'delete', $this->getLanguageService()->getLL('clip_deleteMarkedWarning'));
}
$onClick = 'checkOffCB(' . GeneralUtility::quoteJSvalue(implode(',', $this->CBnames)) . ', this); return false;';
$cells[] = '<a class="btn btn-default" rel="" href="#" onclick="' . htmlspecialchars($onClick) . '" title="' . htmlspecialchars($this->getLanguageService()->getLL('clip_markRecords')) . '">' . $this->iconFactory->getIcon('actions-document-select', Icon::SIZE_SMALL)->render() . '</a>';
$cells[] = '<a class="btn btn-default t3js-toggle-all-checkboxes" data-checkboxes-names="' . htmlspecialchars(implode(',', $this->CBnames)) . '" rel="" href="#" title="' . htmlspecialchars($this->getLanguageService()->getLL('clip_markRecords')) . '">' . $this->iconFactory->getIcon('actions-document-select', Icon::SIZE_SMALL)->render() . '</a>';
}
$theData[$v] = implode('', $cells);
} elseif ($v === '_REF_') {
......@@ -708,45 +707,6 @@ class FileList
return $content;
}
/**
* Returning JavaScript for ClipBoard functionality.
*
* @return string
*/
public function CBfunctions()
{
return '
// checkOffCB()
function checkOffCB(listOfCBnames, link) { //
var checkBoxes, flag, i;
var checkBoxes = listOfCBnames.split(",");
if (link.rel === "") {
link.rel = "allChecked";
flag = true;
} else {
link.rel = "";
flag = false;
}
for (i = 0; i < checkBoxes.length; i++) {
setcbValue(checkBoxes[i], flag);
}
}
// cbValue()
function cbValue(CBname) { //
var CBfullName = "CBC["+CBname+"]";
return (document.dblistForm[CBfullName] && document.dblistForm[CBfullName].checked ? 1 : 0);
}
// setcbValue()
function setcbValue(CBname,flag) { //
CBfullName = "CBC["+CBname+"]";
if(document.dblistForm[CBfullName]) {
document.dblistForm[CBfullName].checked = flag ? "on" : 0;
}
}
';
}
/**
* Initializes page languages and icons
*/
......
......@@ -366,7 +366,9 @@ class RecordListController
// Render the list of tables:
$dblist->generateList();
$listUrl = $dblist->listURL();
// Add JavaScript functions to the page:
$this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/ClipboardComponent');
$this->moduleTemplate->addJavaScriptCode(
'RecordListInlineJS',
......@@ -392,29 +394,9 @@ class RecordListController
}
}
' . $this->moduleTemplate->redirectUrls($listUrl) . '
' . $dblist->CBfunctions() . '
function editRecords(table,idList,addParams,CBflag) {
window.location.href="' . (string)$uriBuilder->buildUriFromRoute('record_edit', ['returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI')]) . '&edit["+table+"]["+idList+"]=edit"+addParams;
}
function editList(table,idList) {
var list="";
// Checking how many is checked, how many is not
var pointer=0;
var pos = idList.indexOf(",");
while (pos!=-1) {
if (cbValue(table+"|"+idList.substr(pointer,pos-pointer))) {
list+=idList.substr(pointer,pos-pointer)+",";
}
pointer=pos+1;
pos = idList.indexOf(",",pointer);
}
if (cbValue(table+"|"+idList.substr(pointer))) {
list+=idList.substr(pointer)+",";
}
return list ? list : idList;
}
if (top.fsMod) top.fsMod.recentIds["web"] = ' . (int)$this->id . ';
'
......
......@@ -1488,8 +1488,7 @@ class DatabaseRecordList
$lang->getLL('clip_deleteMarked')
);
// The "Select all" link:
$onClick = htmlspecialchars('checkOffCB(' . GeneralUtility::quoteJSvalue(implode(',', $this->CBnames)) . ', this); return false;');
$cells['markAll'] = '<a class="btn btn-default" rel="" href="#" onclick="' . $onClick . '" title="'
$cells['markAll'] = '<a class="btn btn-default t3js-toggle-all-checkboxes" data-checkboxes-names="' . htmlspecialchars(implode(',', $this->CBnames)) . '" rel="" href="#" title="'
. htmlspecialchars($lang->getLL('clip_markRecords')) . '">'
. $this->iconFactory->getIcon('actions-document-select', Icon::SIZE_SMALL)->render() . '</a>';
} else {
......@@ -3898,45 +3897,6 @@ class DatabaseRecordList
return $out;
}
/**
* Returning JavaScript for ClipBoard functionality.
*
* @return string
*/
public function CBfunctions()
{
return '
// checkOffCB()
function checkOffCB(listOfCBnames, link) { //
var checkBoxes, flag, i;
var checkBoxes = listOfCBnames.split(",");
if (link.rel === "") {
link.rel = "allChecked";
flag = true;
} else {
link.rel = "";
flag = false;
}
for (i = 0; i < checkBoxes.length; i++) {
setcbValue(checkBoxes[i], flag);
}
}
// cbValue()
function cbValue(CBname) { //
var CBfullName = "CBC["+CBname+"]";
return (document.dblistForm[CBfullName] && document.dblistForm[CBfullName].checked ? 1 : 0);
}
// setcbValue()
function setcbValue(CBname,flag) { //
CBfullName = "CBC["+CBname+"]";
if(document.dblistForm[CBfullName]) {
document.dblistForm[CBfullName].checked = flag ? "on" : 0;
}
}
';
}
/**
* Initializes page languages and icons
*/
......
......@@ -10,4 +10,4 @@
*
* The TYPO3 project - inspiring people to share!
*/
define(["require","exports","jquery","TYPO3/CMS/Backend/Storage/Persistent","TYPO3/CMS/Backend/Icons"],function(t,e,i,a,s){"use strict";return new class{constructor(){this.identifier={entity:".t3js-entity",toggle:".t3js-toggle-recordlist",localize:".t3js-action-localize",icons:{collapse:"actions-view-list-collapse",expand:"actions-view-list-expand",editMultiple:".t3js-record-edit-multiple"}},this.toggleClick=(t=>{t.preventDefault();const e=i(t.currentTarget),l=e.data("table"),n=i(e.data("target")),d="expanded"===n.data("state"),o=e.find(".collapseIcon"),c=d?this.identifier.icons.expand:this.identifier.icons.collapse;s.getIcon(c,s.sizes.small).done(t=>{o.html(t)});let r={};a.isset("moduleData.list")&&(r=a.get("moduleData.list"));const u={};u[l]=d?1:0,i.extend(!0,r,u),a.set("moduleData.list",r).done(()=>{n.data("state",d?"collapsed":"expanded")})}),this.onEditMultiple=(t=>{let e,a,s,l,n;t.preventDefault(),0!==(e=i(t.currentTarget).closest("[data-table]")).length&&(l=i(t.currentTarget).data("uri"),a=e.data("table"),s=e.find(this.identifier.entity+'[data-uid][data-table="'+a+'"]').map((t,e)=>i(e).data("uid")).toArray().join(","),n=l.match(/{[^}]+}/g),i.each(n,(t,e)=>{const n=e.substr(1,e.length-2).split(":");let d;switch(n.shift()){case"entityIdentifiers":d=s;break;case"T3_THIS_LOCATION":d=T3_THIS_LOCATION;break;default:return}i.each(n,(t,e)=>{"editList"===e&&(d=editList(a,d))}),l=l.replace(e,d)}),window.location.href=l)}),this.disableButton=(t=>{i(t.currentTarget).prop("disable",!0).addClass("disabled")}),i(document).on("click",this.identifier.toggle,this.toggleClick),i(document).on("click",this.identifier.icons.editMultiple,this.onEditMultiple),i(document).on("click",this.identifier.localize,this.disableButton)}}});
\ No newline at end of file
define(["require","exports","jquery","TYPO3/CMS/Backend/Storage/Persistent","TYPO3/CMS/Backend/Icons"],function(t,e,i,s,a){"use strict";return new class{constructor(){this.identifier={entity:".t3js-entity",toggle:".t3js-toggle-recordlist",localize:".t3js-action-localize",icons:{collapse:"actions-view-list-collapse",expand:"actions-view-list-expand",editMultiple:".t3js-record-edit-multiple"}},this.toggleClick=(t=>{t.preventDefault();const e=i(t.currentTarget),n=e.data("table"),l=i(e.data("target")),d="expanded"===l.data("state"),o=e.find(".collapseIcon"),c=d?this.identifier.icons.expand:this.identifier.icons.collapse;a.getIcon(c,a.sizes.small).done(t=>{o.html(t)});let r={};s.isset("moduleData.list")&&(r=s.get("moduleData.list"));const u={};u[n]=d?1:0,i.extend(!0,r,u),s.set("moduleData.list",r).done(()=>{l.data("state",d?"collapsed":"expanded")})}),this.onEditMultiple=(t=>{let e,s,a,n,l;t.preventDefault(),0!==(e=i(t.currentTarget).closest("[data-table]")).length&&(n=i(t.currentTarget).data("uri"),s=e.data("table"),a=e.find(this.identifier.entity+'[data-uid][data-table="'+s+'"]').map((t,e)=>i(e).data("uid")).toArray().join(","),l=n.match(/{[^}]+}/g),i.each(l,(t,e)=>{const l=e.substr(1,e.length-2).split(":");let d;switch(l.shift()){case"entityIdentifiers":d=a;break;case"T3_THIS_LOCATION":d=T3_THIS_LOCATION;break;default:return}i.each(l,(t,e)=>{"editList"===e&&(d=this.editList(s,d))}),n=n.replace(e,d)}),window.location.href=n)}),this.disableButton=(t=>{i(t.currentTarget).prop("disable",!0).addClass("disabled")}),i(document).on("click",this.identifier.toggle,this.toggleClick),i(document).on("click",this.identifier.icons.editMultiple,this.onEditMultiple),i(document).on("click",this.identifier.localize,this.disableButton)}editList(t,e){const i=[];let s=0,a=e.indexOf(",");for(;-1!==a;)this.getCheckboxState(t+"|"+e.substr(s,a-s))&&i.push(e.substr(s,a-s)),s=a+1,a=e.indexOf(",",s);return this.getCheckboxState(t+"|"+e.substr(s))&&i.push(e.substr(s)),i.length>0?i.join(","):e}getCheckboxState(t){const e="CBC["+t+"]";return document.querySelector('form[name="dblistForm"] [name="'+e+'"]').checked}}});
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment