Commit f048ee3a authored by Oliver Hader's avatar Oliver Hader Committed by Benni Mack
Browse files

[TASK] Reduce inline JavaScript in ext:redirects and ext:scheduler

This change aims to reduce the amount of inline JavaScript by
moving these parts to dedicated static JavaScript modules or
using native HTML functionality instead of location.href.

Resolves: #91109
Releases: master
Change-Id: I1cd0f6bc1b69e600f62d00c614119c825ae02a36
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/64228


Tested-by: default avatarTYPO3com <noreply@typo3.com>
Tested-by: Andreas Fernandez's avatarAndreas Fernandez <a.fernandez@scripting-base.de>
Tested-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
Reviewed-by: Andreas Fernandez's avatarAndreas Fernandez <a.fernandez@scripting-base.de>
Reviewed-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
parent a86c3e2a
/*
* 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!
*/
import {AjaxResponse} from 'TYPO3/CMS/Core/Ajax/AjaxResponse';
import AjaxRequest = require('TYPO3/CMS/Core/Ajax/AjaxRequest');
import NotificationService = require('TYPO3/CMS/Backend/Notification');
import DeferredAction = require('TYPO3/CMS/Backend/ActionButton/DeferredAction');
/**
* Module: TYPO3/CMS/Redirects/EventHandler
* @exports TYPO3/CMS/Redirects/EventHandler
*/
class EventHandler {
public constructor() {
document.addEventListener(
......
/*
* 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!
*/
import RegularEvent = require('TYPO3/CMS/Core/Event/RegularEvent');
/**
* Module: TYPO3/CMS/Redirects/RedirectsModule
* @exports TYPO3/CMS/Redirects/RedirectsModule
*/
class RedirectsModule {
public constructor() {
const filterForm: HTMLFormElement = document.querySelector('form[data-on-submit="processNavigate"]');
if (filterForm !== null) {
new RegularEvent('change', this.executeSubmit.bind(this))
.delegateTo(document, '[data-on-change="submit"]');
new RegularEvent('submit', this.processNavigate.bind(this))
.bindTo(filterForm);
}
}
private executeSubmit(evt: Event, target: Element): void {
if (target instanceof HTMLSelectElement) {
target.form.submit();
}
}
private processNavigate(evt: Event, target: Element): void {
if (!(target instanceof HTMLFormElement)) {
return;
}
evt.preventDefault();
const formField = target.elements.namedItem('paginator-target-page') as HTMLInputElement;
const numberOfPages = parseInt(formField.dataset.numberOfPages, 10);
let url = formField.dataset.url;
let page = parseInt(formField.value, 10);
if (page > numberOfPages) {
page = numberOfPages;
} else if (page < 1) {
page = 1;
}
url = url.replace('987654322', page.toString());
self.location.href = url;
}
}
export = new RedirectsModule();
......@@ -163,6 +163,13 @@ class Scheduler {
this.actOnChangeSchedulerTableGarbageCollectionTable($(evt.currentTarget));
});
$('[data-update-task-frequency]').change((evt: JQueryEventObject): void => {
const $target = $(evt.currentTarget);
const $taskFrequency = $('#task_frequency');
$taskFrequency.val($target.val());
$target.val($target.attr('value')).blur();
});
const taskGroupTable = document.querySelector('table.taskGroup-table');
if (taskGroupTable !== null) {
new Tablesort(taskGroupTable);
......
......@@ -69,6 +69,7 @@ class ManagementController
{
$this->moduleTemplate = GeneralUtility::makeInstance(ModuleTemplate::class);
$this->moduleTemplate->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/Modal');
$this->moduleTemplate->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Redirects/RedirectsModule');
$this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
$this->getLanguageService()->includeLLFile('EXT:redirects/Resources/Private/Language/locallang_module_redirect.xlf');
}
......
......@@ -26,6 +26,7 @@ class SourceHost
{
/**
* JavaScript code for client side validation/evaluation
* (invoked by FormEngine when editing redirect entities)
*
* @return string JavaScript code for client side validation/evaluation
*/
......
<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
data-namespace-typo3-fluid="true">
<script>
function goToPage(formObject) {
var formField = formObject.elements['paginator-target-page'];
var url = formField.dataset.url;
var numberOfPages = parseInt(formField.dataset.numberOfPages);
var page = parseInt(formField.value);
if (page > numberOfPages) {
page = numberOfPages;
} else if (page < 1) {
page = 1;
}
url = url.replace('987654322', page);
self.location.href = url;
return false;
}
</script>
<nav class="pagination-wrap">
<ul class="pagination pagination-block">
<f:if condition="{pagination.hasLessPages}">
......@@ -58,7 +41,7 @@
<f:variable name="gotToPageUrl">
<f:be.uri route="site_redirects" parameters="{action: 'overview', demand: demand.parameters, page: 987654322}" />
</f:variable>
<form onsubmit="return goToPage(this);" style="display:inline;">
<form data-on-submit="processNavigate" style="display:inline;">
<f:form.textfield
additionalAttributes="{min: 1, max: pagination.numberOfPages}"
data="{number-of-pages: pagination.numberOfPages, url: gotToPageUrl}"
......
......@@ -9,7 +9,6 @@
</f:section>
<f:section name="content">
<f:if condition="{redirects -> f:count()}">
<f:then>
<f:render section="filter" arguments="{_all}" />
......@@ -160,7 +159,7 @@
<div class="form-group">
<label for="demand-source-host"><f:translate key="LLL:EXT:redirects/Resources/Private/Language/locallang_module_redirect.xlf:source_host"/></label>
<select id="demand-source-host" class="form-control input-sm" name="demand[source_host]" onchange="submit()">
<select id="demand-source-host" class="form-control input-sm" name="demand[source_host]" data-on-change="submit">
<option value=""><f:translate key="LLL:EXT:redirects/Resources/Private/Language/locallang_module_redirect.xlf:filter.source_host.showAll"/></option>
<f:for each="{hosts}" as="host">
<f:form.select.option value="{host.name}" selected="{host.name} === {demand.sourceHost}">{host.name}</f:form.select.option>
......@@ -177,7 +176,7 @@
</div>
<div class="form-group">
<label for="demand-target-status-code"><f:translate key="LLL:EXT:redirects/Resources/Private/Language/locallang_module_redirect.xlf:filter.targetStatusCode"/></label>
<select id="demand-target-status-code" class="form-control input-sm" name="demand[target_statuscode]" onchange="submit()">
<select id="demand-target-status-code" class="form-control input-sm" name="demand[target_statuscode]" data-on-change="submit">
<option value=""><f:translate key="LLL:EXT:redirects/Resources/Private/Language/locallang_module_redirect.xlf:filter.source_host.showAll"/></option>
<f:for each="{statusCodes}" as="statusCode">
<f:form.select.option value="{statusCode.code}" selected="{statusCode.code} === {demand.statusCode}">{statusCode.code}</f:form.select.option>
......
/*
* 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","TYPO3/CMS/Core/Event/RegularEvent"],(function(e,t,n){"use strict";return new class{constructor(){const e=document.querySelector('form[data-on-submit="processNavigate"]');null!==e&&(new n("change",this.executeSubmit.bind(this)).delegateTo(document,'[data-on-change="submit"]'),new n("submit",this.processNavigate.bind(this)).bindTo(e))}executeSubmit(e,t){t instanceof HTMLSelectElement&&t.form.submit()}processNavigate(e,t){if(!(t instanceof HTMLFormElement))return;e.preventDefault();const n=t.elements.namedItem("paginator-target-page"),a=parseInt(n.dataset.numberOfPages,10);let s=n.dataset.url,r=parseInt(n.value,10);r>a?r=a:r<1&&(r=1),s=s.replace("987654322",r.toString()),self.location.href=s}}}));
\ No newline at end of file
......@@ -1325,8 +1325,7 @@ class SchedulerModuleController
$closeButton = $buttonBar->makeLinkButton()
->setTitle($this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:cancel'))
->setIcon($this->moduleTemplate->getIconFactory()->getIcon('actions-close', Icon::SIZE_SMALL))
->setOnClick('document.location=' . GeneralUtility::quoteJSvalue($this->moduleUri))
->setHref('#');
->setHref($this->moduleUri);
$buttonBar->addButton($closeButton, ButtonBar::BUTTON_POSITION_LEFT, 2);
// Save, SaveAndClose, SaveAndNew
$saveButtonDropdown = $buttonBar->makeSplitButton();
......
......@@ -105,8 +105,8 @@
<div class="form-wizards-items-aside">
<div class="btn-group">
<select
class="form-control tceforms-select tceforms-wizardselect"
onchange="document.getElementById('task_frequency').value=this.options[this.selectedIndex].value;this.blur();this.selectedIndex=0;">
data-update-task-frequency
class="form-control tceforms-select tceforms-wizardselect">
<option></option>
<f:for each="{frequencyOptions}" as="label" key="command">
<option value="{command}">{f:translate(key:label,default:label)} ({command})</option>
......
......@@ -10,4 +10,4 @@
*
* The TYPO3 project - inspiring people to share!
*/
define(["require","exports","jquery","TYPO3/CMS/Backend/DocumentSaveActions","TYPO3/CMS/Backend/Modal","TYPO3/CMS/Backend/Utility/MessageUtility","tablesort"],(function(e,t,a,l,s,r){"use strict";class i{constructor(){this.allCheckedStatus=!1,this.actOnChangedTaskClass=e=>{let t=e.val();t=t.toLowerCase().replace(/\\/g,"-"),a(".extraFields").hide(),a(".extra_fields_"+t).show()},this.actOnChangedTaskType=e=>{this.toggleFieldsByTaskType(a(e.currentTarget).val())},this.actOnChangeSchedulerTableGarbageCollectionAllTables=e=>{let t=a("#task_tableGarbageCollection_numberOfDays"),l=a("#task_tableGarbageCollection_table");if(e.prop("checked"))l.prop("disabled",!0),t.prop("disabled",!0);else{let e=parseInt(t.val(),10);if(e<1){let t=l.val();void 0!==defaultNumberOfDays[t]&&(e=defaultNumberOfDays[t])}l.prop("disabled",!1),e>0&&t.prop("disabled",!1)}},this.actOnChangeSchedulerTableGarbageCollectionTable=e=>{let t=a("#task_tableGarbageCollection_numberOfDays");defaultNumberOfDays[e.val()]>0?(t.prop("disabled",!1),t.val(defaultNumberOfDays[e.val()])):(t.prop("disabled",!0),t.val(0))},this.checkOrUncheckAllCheckboxes=e=>(e.parents(".tx_scheduler_mod1_table").find(":checkbox").prop("checked",!this.allCheckedStatus),this.allCheckedStatus=!this.allCheckedStatus,!1),this.toggleFieldsByTaskType=e=>{e=parseInt(e+"",10),a("#task_end_col").toggle(2===e),a("#task_frequency_row").toggle(2===e)},this.toggleTaskGroups=e=>{let t=e.data("task-group-id");a("#recordlist-task-group-"+t).collapse("toggle")},this.initializeEvents=()=>{a(".checkall").on("click",e=>{this.checkOrUncheckAllCheckboxes(a(e.currentTarget))}),a("#task_class").change(e=>{this.actOnChangedTaskClass(a(e.currentTarget))}),a("#task_type").change(this.actOnChangedTaskType),a("#task_tableGarbageCollection_allTables").change(e=>{this.actOnChangeSchedulerTableGarbageCollectionAllTables(a(e.currentTarget))}),a("#task_tableGarbageCollection_table").change(e=>{this.actOnChangeSchedulerTableGarbageCollectionTable(a(e.currentTarget))});const e=document.querySelector("table.taskGroup-table");null!==e&&new Tablesort(e),a(document).on("click",".t3js-element-browser",e=>{e.preventDefault();const t=e.currentTarget;s.advanced({type:s.types.iframe,content:t.href+"&mode="+t.dataset.mode+"&bparams="+t.dataset.params,size:s.sizes.large})}),window.addEventListener("message",this.listenOnElementBrowser)},this.initializeDefaultStates=()=>{let e=a("#task_type");e.length&&this.toggleFieldsByTaskType(e.val());let t=a("#task_class");t.length&&(this.actOnChangedTaskClass(t),i.updateElementBrowserTriggers())},this.listenOnElementBrowser=e=>{if(!r.MessageUtility.verifyOrigin(e.origin))throw"Denied message sent by "+e.origin;if("typo3:elementBrowser:elementAdded"===e.data.actionName){if(void 0===e.data.fieldName)throw"fieldName not defined in message";if(void 0===e.data.value)throw"value not defined in message";const t=e.data.value.split("_");document.querySelector('input[name="'+e.data.fieldName+'"]').value=t[1]}},this.initializeEvents(),this.initializeDefaultStates(),l.getInstance().addPreSubmitCallback(()=>{let e=a("#task_class").val();e=e.toLowerCase().replace(/\\/g,"-"),a(".extraFields").appendTo(a("#extraFieldsHidden")),a(".extra_fields_"+e).appendTo(a("#extraFieldsSection"))})}static updateElementBrowserTriggers(){document.querySelectorAll(".t3js-element-browser").forEach(e=>{const t=document.getElementById(e.dataset.triggerFor);e.dataset.params=t.name+"|||pages"})}}return new i}));
\ No newline at end of file
define(["require","exports","jquery","TYPO3/CMS/Backend/DocumentSaveActions","TYPO3/CMS/Backend/Modal","TYPO3/CMS/Backend/Utility/MessageUtility","tablesort"],(function(e,a,t,l,s,r){"use strict";class n{constructor(){this.allCheckedStatus=!1,this.actOnChangedTaskClass=e=>{let a=e.val();a=a.toLowerCase().replace(/\\/g,"-"),t(".extraFields").hide(),t(".extra_fields_"+a).show()},this.actOnChangedTaskType=e=>{this.toggleFieldsByTaskType(t(e.currentTarget).val())},this.actOnChangeSchedulerTableGarbageCollectionAllTables=e=>{let a=t("#task_tableGarbageCollection_numberOfDays"),l=t("#task_tableGarbageCollection_table");if(e.prop("checked"))l.prop("disabled",!0),a.prop("disabled",!0);else{let e=parseInt(a.val(),10);if(e<1){let a=l.val();void 0!==defaultNumberOfDays[a]&&(e=defaultNumberOfDays[a])}l.prop("disabled",!1),e>0&&a.prop("disabled",!1)}},this.actOnChangeSchedulerTableGarbageCollectionTable=e=>{let a=t("#task_tableGarbageCollection_numberOfDays");defaultNumberOfDays[e.val()]>0?(a.prop("disabled",!1),a.val(defaultNumberOfDays[e.val()])):(a.prop("disabled",!0),a.val(0))},this.checkOrUncheckAllCheckboxes=e=>(e.parents(".tx_scheduler_mod1_table").find(":checkbox").prop("checked",!this.allCheckedStatus),this.allCheckedStatus=!this.allCheckedStatus,!1),this.toggleFieldsByTaskType=e=>{e=parseInt(e+"",10),t("#task_end_col").toggle(2===e),t("#task_frequency_row").toggle(2===e)},this.toggleTaskGroups=e=>{let a=e.data("task-group-id");t("#recordlist-task-group-"+a).collapse("toggle")},this.initializeEvents=()=>{t(".checkall").on("click",e=>{this.checkOrUncheckAllCheckboxes(t(e.currentTarget))}),t("#task_class").change(e=>{this.actOnChangedTaskClass(t(e.currentTarget))}),t("#task_type").change(this.actOnChangedTaskType),t("#task_tableGarbageCollection_allTables").change(e=>{this.actOnChangeSchedulerTableGarbageCollectionAllTables(t(e.currentTarget))}),t("#task_tableGarbageCollection_table").change(e=>{this.actOnChangeSchedulerTableGarbageCollectionTable(t(e.currentTarget))}),t("[data-update-task-frequency]").change(e=>{const a=t(e.currentTarget);t("#task_frequency").val(a.val()),a.val(a.attr("value")).blur()});const e=document.querySelector("table.taskGroup-table");null!==e&&new Tablesort(e),t(document).on("click",".t3js-element-browser",e=>{e.preventDefault();const a=e.currentTarget;s.advanced({type:s.types.iframe,content:a.href+"&mode="+a.dataset.mode+"&bparams="+a.dataset.params,size:s.sizes.large})}),window.addEventListener("message",this.listenOnElementBrowser)},this.initializeDefaultStates=()=>{let e=t("#task_type");e.length&&this.toggleFieldsByTaskType(e.val());let a=t("#task_class");a.length&&(this.actOnChangedTaskClass(a),n.updateElementBrowserTriggers())},this.listenOnElementBrowser=e=>{if(!r.MessageUtility.verifyOrigin(e.origin))throw"Denied message sent by "+e.origin;if("typo3:elementBrowser:elementAdded"===e.data.actionName){if(void 0===e.data.fieldName)throw"fieldName not defined in message";if(void 0===e.data.value)throw"value not defined in message";const a=e.data.value.split("_");document.querySelector('input[name="'+e.data.fieldName+'"]').value=a[1]}},this.initializeEvents(),this.initializeDefaultStates(),l.getInstance().addPreSubmitCallback(()=>{let e=t("#task_class").val();e=e.toLowerCase().replace(/\\/g,"-"),t(".extraFields").appendTo(t("#extraFieldsHidden")),t(".extra_fields_"+e).appendTo(t("#extraFieldsSection"))})}static updateElementBrowserTriggers(){document.querySelectorAll(".t3js-element-browser").forEach(e=>{const a=document.getElementById(e.dataset.triggerFor);e.dataset.params=a.name+"|||pages"})}}return new n}));
\ 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