diff --git a/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/DateTimePicker.ts b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/DateTimePicker.ts index 502f95ba4f2ec022b15a109c8ab9178992680464..349e52a9e2ac6acb7d759e5b7c31cf467b3c49a5 100644 --- a/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/DateTimePicker.ts +++ b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/DateTimePicker.ts @@ -103,7 +103,11 @@ class DateTimePicker { } $hiddenField.val(value); - $(document).trigger('formengine.dp.change', [$element]); + document.dispatchEvent(new CustomEvent('formengine.dp.change', { + detail: { + element: $element, + } + })); }); }); } diff --git a/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/FormEngine/Container/InlineControlContainer.ts b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/FormEngine/Container/InlineControlContainer.ts index 7363630d925e44ce8c7f25013975c4d3c81c17f1..d7ed3eb9b23283b63491bccbf134944fa56147c6 100644 --- a/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/FormEngine/Container/InlineControlContainer.ts +++ b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/FormEngine/Container/InlineControlContainer.ts @@ -11,11 +11,11 @@ * The TYPO3 project - inspiring people to share! */ -import $ from 'jquery'; import AjaxRequest = require('TYPO3/CMS/Core/Ajax/AjaxRequest'); import {MessageUtility} from '../../Utility/MessageUtility'; import {AjaxDispatcher} from './../InlineRelation/AjaxDispatcher'; import {InlineResponseInterface} from './../InlineRelation/InlineResponseInterface'; +import DocumentService = require('TYPO3/CMS/Core/DocumentService'); import NProgress = require('nprogress'); import Sortable = require('Sortable'); import FormEngine = require('TYPO3/CMS/Backend/FormEngine'); @@ -214,7 +214,7 @@ class InlineControlContainer { * @param {string} elementId */ constructor(elementId: string) { - $((): void => { + DocumentService.ready().then((document: Document): void => { this.container = <HTMLElement>document.getElementById(elementId); this.ajaxDispatcher = new AjaxDispatcher(this.container.dataset.objectGroup); @@ -406,7 +406,7 @@ class InlineControlContainer { const hiddenClass = 't3-form-field-container-inline-hidden'; const isHidden = recordContainer.classList.contains(hiddenClass); - let toggleIcon: string = ''; + let toggleIcon: string; if (isHidden) { toggleIcon = 'actions-edit-hide'; @@ -640,7 +640,7 @@ class InlineControlContainer { (<HTMLInputElement>formField).value = records.join(','); (<HTMLInputElement>formField).classList.add('has-change'); - $(document).trigger('change'); + document.dispatchEvent(new Event('change')); this.redrawSortingButtons(this.container.dataset.objectGroup, records); this.setUnique(newUid, selectedValue); @@ -669,7 +669,7 @@ class InlineControlContainer { (<HTMLInputElement>formField).value = records.join(','); (<HTMLInputElement>formField).classList.add('has-change'); - $(document).trigger('change'); + document.dispatchEvent(new Event('change')); this.redrawSortingButtons(this.container.dataset.objectGroup, records); } @@ -722,8 +722,8 @@ class InlineControlContainer { (<HTMLInputElement>formField).value = records.join(','); (<HTMLInputElement>formField).classList.add('has-change'); - $(document).trigger('inline:sorting-changed'); - $(document).trigger('change'); + document.dispatchEvent(new Event('inline:sorting-changed')); + document.dispatchEvent(new Event('change')); this.redrawSortingButtons(this.container.dataset.objectGroup, records); } diff --git a/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/FormEngine/Element/Extra/SelectBoxFilter.ts b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/FormEngine/Element/Extra/SelectBoxFilter.ts index af825f17cde622666afb5924175a3934a31950a6..4390d48041b81c92c73ace1471af3e53322162d8 100644 --- a/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/FormEngine/Element/Extra/SelectBoxFilter.ts +++ b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/FormEngine/Element/Extra/SelectBoxFilter.ts @@ -11,7 +11,7 @@ * The TYPO3 project - inspiring people to share! */ -import $ from 'jquery'; +import RegularEvent = require('TYPO3/CMS/Core/Event/RegularEvent'); enum Selectors { fieldContainerSelector = '.t3js-formengine-field-group', @@ -25,7 +25,7 @@ enum Selectors { class SelectBoxFilter { private selectElement: HTMLSelectElement = null; private filterText: string = ''; - private $availableOptions: JQuery = null; + private availableOptions: NodeListOf<HTMLOptionElement> = null; constructor(selectElement: HTMLSelectElement) { this.selectElement = selectElement; @@ -39,16 +39,13 @@ class SelectBoxFilter { return; } - wizardsElement.addEventListener('keyup', (e: Event): void => { - if ((<HTMLElement>e.target).matches(Selectors.filterTextFieldSelector)) { - this.filter((<HTMLInputElement>e.target).value); - } - }); - wizardsElement.addEventListener('change', (e: Event): void => { - if ((<HTMLElement>e.target).matches(Selectors.filterSelectFieldSelector)) { - this.filter((<HTMLInputElement>e.target).value); - } - }); + new RegularEvent('input', (e: Event): void => { + this.filter((<HTMLInputElement>e.target).value); + }).delegateTo(wizardsElement, Selectors.filterTextFieldSelector); + + new RegularEvent('change', (e: Event): void => { + this.filter((<HTMLInputElement>e.target).value); + }).delegateTo(wizardsElement, Selectors.filterSelectFieldSelector); } /** @@ -58,17 +55,13 @@ class SelectBoxFilter { */ private filter(filterText: string): void { this.filterText = filterText; - if (!this.$availableOptions) { - this.$availableOptions = $(this.selectElement).find('option').clone(); + if (this.availableOptions === null) { + this.availableOptions = this.selectElement.querySelectorAll('option'); } - this.selectElement.innerHTML = ''; const matchFilter = new RegExp(filterText, 'i'); - - this.$availableOptions.each((i: number, el: HTMLElement): void => { - if (filterText.length === 0 || el.textContent.match(matchFilter)) { - this.selectElement.appendChild(el); - } + this.availableOptions.forEach((option: HTMLOptionElement): void => { + option.hidden = filterText.length > 0 && option.textContent.match(matchFilter) === null; }); } } diff --git a/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/FormEngine/Element/InputDateTimeElement.ts b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/FormEngine/Element/InputDateTimeElement.ts index bb9b91ae1e7dd10310e078d607e1f0ca70061080..0fc4a673c80cc07c3f7b2a38b5ab991ed267b954 100644 --- a/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/FormEngine/Element/InputDateTimeElement.ts +++ b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/FormEngine/Element/InputDateTimeElement.ts @@ -11,12 +11,13 @@ * The TYPO3 project - inspiring people to share! */ -import $ from 'jquery'; +import DocumentService = require('TYPO3/CMS/Core/DocumentService'); import FormEngine = require('TYPO3/CMS/Backend/FormEngine'); +import RegularEvent = require('TYPO3/CMS/Core/Event/RegularEvent'); class InputDateTimeElement { constructor(elementId: string) { - $((): void => { + DocumentService.ready().then((): void => { this.registerEventHandler(); require(['../../DateTimePicker'], (DateTimePicker: any): void => { DateTimePicker.initialize('#' + elementId) @@ -25,11 +26,15 @@ class InputDateTimeElement { } private registerEventHandler(): void { - $(document).on('formengine.dp.change', (event: JQueryEventObject, $field: JQuery): void => { + new RegularEvent('formengine.dp.change', (e: CustomEvent): void => { FormEngine.Validation.validate(); - FormEngine.Validation.markFieldAsChanged($field); - $('.module-docheader-bar .btn').removeClass('disabled').prop('disabled', false); - }); + FormEngine.Validation.markFieldAsChanged(e.detail.element); + + document.querySelectorAll('.module-docheader-bar .btn').forEach((btn: HTMLButtonElement): void => { + btn.classList.remove('disabled'); + btn.disabled = false; + }); + }).bindTo(document); } } diff --git a/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/FormEngine/Element/InputLinkElement.ts b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/FormEngine/Element/InputLinkElement.ts index e04529a02e8c911fce854b6947059a6d4e7efaa4..8c049842e6845e7ab2553deff752201d3e515528 100644 --- a/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/FormEngine/Element/InputLinkElement.ts +++ b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/FormEngine/Element/InputLinkElement.ts @@ -11,7 +11,7 @@ * The TYPO3 project - inspiring people to share! */ -import $ from 'jquery'; +import DocumentService = require('TYPO3/CMS/Core/DocumentService'); enum Selectors { toggleSelector = '.t3js-form-field-inputlink-explanation-toggle', @@ -28,7 +28,7 @@ class InputLinkElement { private icon: HTMLSpanElement = null; constructor(elementId: string) { - $((): void => { + DocumentService.ready().then((document: Document): void => { this.element = <HTMLSelectElement>document.getElementById(elementId); this.container = <HTMLElement>this.element.closest('.t3js-form-field-inputlink'); this.toggleSelector = <HTMLButtonElement>this.container.querySelector(Selectors.toggleSelector); diff --git a/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/FormEngine/Element/SelectCheckBoxElement.ts b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/FormEngine/Element/SelectCheckBoxElement.ts index b186a0dadeca9abf28a77cdbaf226c2ee24c9fbd..2895edde168f1545e5d4031e450d32a9225fc1e5 100644 --- a/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/FormEngine/Element/SelectCheckBoxElement.ts +++ b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/FormEngine/Element/SelectCheckBoxElement.ts @@ -11,8 +11,8 @@ * The TYPO3 project - inspiring people to share! */ -import $ from 'jquery'; -import FormEngine = require('TYPO3/CMS/Backend/FormEngine'); +import DocumentService = require('TYPO3/CMS/Core/DocumentService'); +import RegularEvent = require('TYPO3/CMS/Core/Event/RegularEvent'); enum Identifier { toggleAll = '.t3js-toggle-checkboxes', @@ -22,17 +22,18 @@ enum Identifier { class SelectCheckBoxElement { private checkBoxId: string = ''; - private $table: JQuery = null; - private checkedBoxes: JQuery = null; + private table: HTMLTableElement = null; + private checkedBoxes: NodeListOf<HTMLInputElement> = null; /** * Determines whether all available checkboxes are checked * - * @param {JQuery} $checkBoxes + * @param {NodeListOf<HTMLInputElement>} checkBoxes * @return {boolean} */ - private static allCheckBoxesAreChecked($checkBoxes: JQuery): boolean { - return $checkBoxes.length === $checkBoxes.filter(':checked').length; + private static allCheckBoxesAreChecked(checkBoxes: NodeListOf<HTMLInputElement>): boolean { + const checkboxArray = Array.from(checkBoxes); + return checkBoxes.length === checkboxArray.filter((checkBox: HTMLInputElement) => checkBox.checked).length; } /** @@ -40,9 +41,9 @@ class SelectCheckBoxElement { */ constructor(checkBoxId: string) { this.checkBoxId = checkBoxId; - $((): void => { - this.$table = $('#' + checkBoxId).closest('table'); - this.checkedBoxes = this.$table.find(Identifier.singleItem + ':checked'); + DocumentService.ready().then((document: Document): void => { + this.table = document.getElementById(checkBoxId).closest('table'); + this.checkedBoxes = this.table.querySelectorAll(Identifier.singleItem + ':checked'); this.enableTriggerCheckBox(); this.registerEventHandler(); @@ -53,38 +54,39 @@ class SelectCheckBoxElement { * Registers the events for clicking the "Toggle all" and the single item checkboxes */ private registerEventHandler(): void { - this.$table.on('change', Identifier.toggleAll, (e: JQueryEventObject): void => { - const $me = $(e.currentTarget); - const $checkBoxes = this.$table.find(Identifier.singleItem); - const checkIt = !SelectCheckBoxElement.allCheckBoxesAreChecked($checkBoxes); + new RegularEvent('change', (e: Event, currentTarget: HTMLInputElement): void => { + const checkBoxes: NodeListOf<HTMLInputElement> = this.table.querySelectorAll(Identifier.singleItem); + const checkIt = !SelectCheckBoxElement.allCheckBoxesAreChecked(checkBoxes); - $checkBoxes.prop('checked', checkIt); - $me.prop('checked', checkIt); - FormEngine.Validation.markFieldAsChanged($me); - }).on('change', Identifier.singleItem, (): void => { - this.setToggleAllState(); - }).on('click', Identifier.revertSelection, (): void => { - this.$table.find(Identifier.singleItem).each((_: number, checkbox: HTMLInputElement): void => { - checkbox.checked = this.checkedBoxes.index(checkbox) > -1; + checkBoxes.forEach((checkBox: HTMLInputElement): void => { + checkBox.checked = checkIt; + }); + currentTarget.checked = checkIt; + }).delegateTo(this.table, Identifier.toggleAll); + + new RegularEvent('change', this.setToggleAllState.bind(this)).delegateTo(this.table, Identifier.singleItem); + + new RegularEvent('click', (): void => { + const checkBoxes = this.table.querySelectorAll(Identifier.singleItem); + const checkedCheckBoxesAsArray = Array.from(this.checkedBoxes); + checkBoxes.forEach((checkBox: HTMLInputElement): void => { + checkBox.checked = checkedCheckBoxesAsArray.includes(checkBox); }); this.setToggleAllState(); - }); + }).delegateTo(this.table, Identifier.revertSelection); } private setToggleAllState(): void { - const $checkBoxes = this.$table.find(Identifier.singleItem); - const checkIt = SelectCheckBoxElement.allCheckBoxesAreChecked($checkBoxes); - - this.$table.find(Identifier.toggleAll).prop('checked', checkIt); + const checkBoxes: NodeListOf<HTMLInputElement> = this.table.querySelectorAll(Identifier.singleItem); + (this.table.querySelector(Identifier.toggleAll) as HTMLInputElement).checked = SelectCheckBoxElement.allCheckBoxesAreChecked(checkBoxes); } /** * Enables the "Toggle all" checkbox on document load if all child checkboxes are checked */ private enableTriggerCheckBox(): void { - const $checkBoxes = this.$table.find(Identifier.singleItem); - const checkIt = SelectCheckBoxElement.allCheckBoxesAreChecked($checkBoxes); - $('#' + this.checkBoxId).prop('checked', checkIt); + const checkBoxes: NodeListOf<HTMLInputElement> = this.table.querySelectorAll(Identifier.singleItem); + (document.getElementById(this.checkBoxId) as HTMLInputElement).checked = SelectCheckBoxElement.allCheckBoxesAreChecked(checkBoxes); } } diff --git a/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/FormEngine/Element/SelectMultipleSideBySideElement.ts b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/FormEngine/Element/SelectMultipleSideBySideElement.ts index b4831e006034c91fe366135469896d8cb66a17f4..2b6399ffb9113e882d668b6085bc8c972a51e6d8 100644 --- a/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/FormEngine/Element/SelectMultipleSideBySideElement.ts +++ b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/FormEngine/Element/SelectMultipleSideBySideElement.ts @@ -12,7 +12,7 @@ */ import {AbstractSortableSelectItems} from './AbstractSortableSelectItems'; -import $ from 'jquery'; +import DocumentService = require('TYPO3/CMS/Core/DocumentService'); import FormEngine = require('TYPO3/CMS/Backend/FormEngine'); import SelectBoxFilter = require('./Extra/SelectBoxFilter'); @@ -23,7 +23,7 @@ class SelectMultipleSideBySideElement extends AbstractSortableSelectItems { constructor(selectedOptionsElementId: string, availableOptionsElementId: string) { super(); - $((): void => { + DocumentService.ready().then((document: Document): void => { this.selectedOptionsElement = <HTMLSelectElement>document.getElementById(selectedOptionsElementId); this.availableOptionsElement = <HTMLSelectElement>document.getElementById(availableOptionsElementId); this.registerEventHandler(); @@ -47,7 +47,7 @@ class SelectMultipleSideBySideElement extends AbstractSortableSelectItems { optionElement.textContent, optionElement.getAttribute('title'), exclusiveValues, - $(optionElement), + optionElement, ); }); } diff --git a/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/FormEngine/Element/SelectSingleElement.ts b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/FormEngine/Element/SelectSingleElement.ts index 36b165126a22af59e9ee352d3b5e00212cd5fd3f..5d436f200af7b88877247f5307a32de656a8a606 100644 --- a/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/FormEngine/Element/SelectSingleElement.ts +++ b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/FormEngine/Element/SelectSingleElement.ts @@ -11,7 +11,7 @@ * The TYPO3 project - inspiring people to share! */ -import $ from 'jquery'; +import RegularEvent = require('TYPO3/CMS/Core/Event/RegularEvent'); interface SelectSingleElementOptions { [key: string]: any; @@ -23,43 +23,52 @@ interface SelectSingleElementOptions { */ class SelectSingleElement { public initialize = (selector: string, options: SelectSingleElementOptions): void => { - let $selectElement: JQuery = $(selector); - let $groupIconContainer: JQuery = $selectElement.prev('.input-group-icon'); + let selectElement: HTMLSelectElement = document.querySelector(selector); options = options || {}; - $selectElement.on('change', (e: JQueryEventObject): void => { - let $me: JQuery = $(e.target); + new RegularEvent('change', (e: Event): void => { + const target = e.target as HTMLSelectElement; + const groupIconContainer: HTMLElement = target.parentElement.querySelector('.input-group-icon'); // Update prepended select icon - $groupIconContainer.html($selectElement.find(':selected').data('icon')); + if (groupIconContainer !== null) { + groupIconContainer.innerHTML = (target.options[target.selectedIndex].dataset.icon); + } - let $selectIcons: JQuery = $me.closest('.t3js-formengine-field-item').find('.t3js-forms-select-single-icons'); - $selectIcons.find('.item.active').removeClass('active'); - $selectIcons.find('[data-select-index="' + $me.prop('selectedIndex') + '"]').closest('.item').addClass('active'); - }); + const selectIcons: HTMLElement = target.closest('.t3js-formengine-field-item').querySelector('.t3js-forms-select-single-icons'); + if (selectIcons !== null) { + const activeItem = selectIcons.querySelector('.item.active'); + if (activeItem !== null) { + activeItem.classList.remove('active'); + } + + const selectionIcon = selectIcons.querySelector('[data-select-index="' + target.selectedIndex + '"]'); + if (selectionIcon !== null) { + selectionIcon.closest('.item').classList.add('active'); + } + } + }).bindTo(selectElement); // Append optionally passed additional "change" event callback if (typeof options.onChange === 'function') { - $selectElement.on('change', options.onChange); + new RegularEvent('change', options.onChange).bindTo(selectElement); } // Append optionally passed additional "focus" event callback if (typeof options.onFocus === 'function') { - $selectElement.on('focus', options.onFocus); + new RegularEvent('focus', options.onFocus).bindTo(selectElement); } - $selectElement.closest('.form-control-wrap').find('.t3js-forms-select-single-icons a').on('click', (e: JQueryEventObject): boolean => { - let $me: JQuery = $(e.target); - let $selectIcon: JQuery = $me.closest('[data-select-index]'); - - $me.closest('.t3js-forms-select-single-icons').find('.item.active').removeClass('active'); - $selectElement - .prop('selectedIndex', $selectIcon.data('selectIndex')) - .trigger('change'); - $selectIcon.closest('.item').addClass('active'); + new RegularEvent('click', (e: Event, target: HTMLAnchorElement): void => { + const currentActive = target.closest('.t3js-forms-select-single-icons').querySelector('.item.active'); + if (currentActive !== null) { + currentActive.classList.remove('active'); + } - return false; - }); + selectElement.selectedIndex = parseInt(target.dataset.selectIndex, 10); + selectElement.dispatchEvent(new Event('change')); + target.closest('.item').classList.add('active'); + }).delegateTo(selectElement.closest('.form-control-wrap'), '.t3js-forms-select-single-icons .item:not(.active) a'); } } diff --git a/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/FormEngine/Element/SlugElement.ts b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/FormEngine/Element/SlugElement.ts index 4309250fc85a427fcdb5dbd02d99bff1380120db..b17523912a392bb7268a76261fc23b3b5bd14dc9 100644 --- a/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/FormEngine/Element/SlugElement.ts +++ b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/FormEngine/Element/SlugElement.ts @@ -11,9 +11,11 @@ * The TYPO3 project - inspiring people to share! */ -import $ from 'jquery'; import {AjaxResponse} from 'TYPO3/CMS/Core/Ajax/AjaxResponse'; import AjaxRequest = require('TYPO3/CMS/Core/Ajax/AjaxRequest'); +import DocumentService = require('TYPO3/CMS/Core/DocumentService'); +import DebounceEvent = require('TYPO3/CMS/Core/Event/DebounceEvent'); +import RegularEvent = require('TYPO3/CMS/Core/Event/RegularEvent'); interface FieldOptions { pageId: number; @@ -63,11 +65,11 @@ enum ProposalModes { */ class SlugElement { private options: FieldOptions = null; - private $fullElement: JQuery = null; + private fullElement: HTMLElement = null; private manuallyChanged: boolean = false; - private $readOnlyField: JQuery = null; - private $inputField: JQuery = null; - private $hiddenField: JQuery = null; + private readOnlyField: HTMLInputElement = null; + private inputField: HTMLInputElement = null; + private hiddenField: HTMLInputElement = null; private request: AjaxRequest = null; private readonly fieldsToListenOn: { [key: string]: string } = {}; @@ -75,74 +77,77 @@ class SlugElement { this.options = options; this.fieldsToListenOn = this.options.listenerFieldNames || {}; - $((): void => { - this.$fullElement = $(selector); - this.$inputField = this.$fullElement.find(Selectors.inputField); - this.$readOnlyField = this.$fullElement.find(Selectors.readOnlyField); - this.$hiddenField = this.$fullElement.find(Selectors.hiddenField); + DocumentService.ready().then((document: Document): void => { + this.fullElement = document.querySelector(selector); + this.inputField = this.fullElement.querySelector(Selectors.inputField); + this.readOnlyField = this.fullElement.querySelector(Selectors.readOnlyField); + this.hiddenField = this.fullElement.querySelector(Selectors.hiddenField); this.registerEvents(); }); } private registerEvents(): void { - const fieldsToListenOnList = Object.keys(this.getAvailableFieldsForProposalGeneration()).map((k: string) => this.fieldsToListenOn[k]); + const fieldsToListenOnList = Object.values(this.getAvailableFieldsForProposalGeneration()).map((selector: string) => `[data-formengine-input-name="${selector}"]`); + const recreateButton: HTMLButtonElement = this.fullElement.querySelector(Selectors.recreateButton); // Listen on 'listenerFieldNames' for new pages. This is typically the 'title' field // of a page to create slugs from the title when title is set / changed. if (fieldsToListenOnList.length > 0) { if (this.options.command === 'new') { - $(this.$fullElement).on('keyup', fieldsToListenOnList.join(','), (): void => { + new DebounceEvent('input', (): void => { if (!this.manuallyChanged) { this.sendSlugProposal(ProposalModes.AUTO); } - }); + }).delegateTo(document, fieldsToListenOnList.join(',')); } // Clicking the recreate button makes new slug proposal created from 'title' field - $(this.$fullElement).on('click', Selectors.recreateButton, (e: JQueryEventObject): void => { + new RegularEvent('click', (e: Event): void => { e.preventDefault(); - if (this.$readOnlyField.hasClass('hidden')) { + if (this.readOnlyField.classList.contains('hidden')) { // Switch to readonly version - similar to 'new' page where field is // written on the fly with title change - this.$readOnlyField.toggleClass('hidden', false); - this.$inputField.toggleClass('hidden', true); + this.readOnlyField.classList.toggle('hidden', false); + this.inputField.classList.toggle('hidden', true); } this.sendSlugProposal(ProposalModes.RECREATE); - }); + }).bindTo(recreateButton); } else { - $(this.$fullElement).find(Selectors.recreateButton).addClass('disabled').prop('disabled', true); + recreateButton.classList.add('disabled'); + recreateButton.disabled = true; } // Scenario for new pages: Usually, slug is created from the page title. However, if user toggles the // input field and feeds an own slug, and then changes title again, the slug should stay. manuallyChanged // is used to track this. - $(this.$inputField).on('keyup', (): void => { + new DebounceEvent('input', (): void => { this.manuallyChanged = true; this.sendSlugProposal(ProposalModes.MANUAL); - }); + }).bindTo(this.inputField); // Clicking the toggle button toggles the read only field and the input field. // Also set the value of either the read only or the input field to the hidden field // and update the value of the read only field after manual change of the input field. - $(this.$fullElement).on('click', Selectors.toggleButton, (e: JQueryEventObject): void => { + const toggleButton = this.fullElement.querySelector(Selectors.toggleButton); + new RegularEvent('click', (e: Event): void => { e.preventDefault(); - const showReadOnlyField = this.$readOnlyField.hasClass('hidden'); - this.$readOnlyField.toggleClass('hidden', !showReadOnlyField); - this.$inputField.toggleClass('hidden', showReadOnlyField); + const showReadOnlyField = this.readOnlyField.classList.contains('hidden'); + this.readOnlyField.classList.toggle('hidden', !showReadOnlyField); + this.inputField.classList.toggle('hidden', showReadOnlyField); if (!showReadOnlyField) { - this.$hiddenField.val(this.$inputField.val()); + this.hiddenField.value = this.inputField.value; return; } - if (this.$inputField.val() !== this.$readOnlyField.val()) { - this.$readOnlyField.val(this.$inputField.val()); + if (this.inputField.value !== this.readOnlyField.value) { + this.readOnlyField.value = this.inputField.value; } else { this.manuallyChanged = false; - this.$fullElement.find('.t3js-form-proposal-accepted').addClass('hidden'); - this.$fullElement.find('.t3js-form-proposal-different').addClass('hidden'); + this.fullElement.querySelector('.t3js-form-proposal-accepted').classList.add('hidden'); + this.fullElement.querySelector('.t3js-form-proposal-different').classList.add('hidden'); } - this.$hiddenField.val(this.$readOnlyField.val()); - }); + this.hiddenField.value = this.readOnlyField.value; + }).bindTo(toggleButton); } /** @@ -151,14 +156,14 @@ class SlugElement { private sendSlugProposal(mode: ProposalModes): void { const input: { [key: string]: string } = {}; if (mode === ProposalModes.AUTO || mode === ProposalModes.RECREATE) { - $.each(this.getAvailableFieldsForProposalGeneration(), (fieldName: string, field: string): void => { - input[fieldName] = $('[data-formengine-input-name="' + field + '"]').val(); - }); + for (const [fieldName, selector] of Object.entries(this.getAvailableFieldsForProposalGeneration())) { + input[fieldName] = (document.querySelector('[data-formengine-input-name="' + selector + '"]') as HTMLInputElement).value; + } if (this.options.includeUidInValues === true) { input.uid = this.options.recordId.toString(); } } else { - input.manual = this.$inputField.val(); + input.manual = this.inputField.value; } if (this.request instanceof AjaxRequest) { this.request.abort(); @@ -176,25 +181,25 @@ class SlugElement { command: this.options.command, signature: this.options.signature, }).then(async (response: AjaxResponse): Promise<any> => { - const data = await response.resolve(); + const data: Response = await response.resolve(); const visualProposal = '/' + data.proposal.replace(/^\//, ''); - if (data.hasConflicts) { - this.$fullElement.find('.t3js-form-proposal-accepted').addClass('hidden'); - this.$fullElement.find('.t3js-form-proposal-different').removeClass('hidden').find('span').text(visualProposal); - } else { - this.$fullElement.find('.t3js-form-proposal-accepted').removeClass('hidden').find('span').text(visualProposal); - this.$fullElement.find('.t3js-form-proposal-different').addClass('hidden'); - } - const isChanged = this.$hiddenField.val() !== data.proposal; + const acceptedProposalField: HTMLElement = this.fullElement.querySelector('.t3js-form-proposal-accepted'); + const differentProposalField: HTMLElement = this.fullElement.querySelector('.t3js-form-proposal-different'); + + acceptedProposalField.classList.toggle('hidden', data.hasConflicts); + differentProposalField.classList.toggle('hidden', !data.hasConflicts); + (data.hasConflicts ? differentProposalField : acceptedProposalField).querySelector('span').innerText = visualProposal; + + const isChanged = this.hiddenField.value !== data.proposal; if (isChanged) { - this.$fullElement.find('input').trigger('change'); + this.fullElement.querySelector('input').dispatchEvent(new Event('change')); } if (mode === ProposalModes.AUTO || mode === ProposalModes.RECREATE) { - this.$readOnlyField.val(data.proposal); - this.$hiddenField.val(data.proposal); - this.$inputField.val(data.proposal); + this.readOnlyField.value = data.proposal; + this.hiddenField.value = data.proposal; + this.inputField.value = data.proposal; } else { - this.$hiddenField.val(data.proposal); + this.hiddenField.value = data.proposal; } }).finally((): void => { this.request = null; @@ -208,13 +213,12 @@ class SlugElement { */ private getAvailableFieldsForProposalGeneration(): { [key: string]: string } { const availableFields: { [key: string]: string } = {}; - - $.each(this.fieldsToListenOn, (fieldName: string, field: string): void => { - const $selector = $('[data-formengine-input-name="' + field + '"]'); - if ($selector.length > 0) { - availableFields[fieldName] = field; + for (const [fieldName, selector] of Object.entries(this.fieldsToListenOn)) { + const field = document.querySelector('[data-formengine-input-name="' + selector + '"]'); + if (field !== null) { + availableFields[fieldName] = selector; } - }); + } return availableFields; } diff --git a/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/FormEngine/FieldWizard/LocalizationStateSelector.ts b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/FormEngine/FieldWizard/LocalizationStateSelector.ts index 96a6f0c9dee9faf8e85bc861f2b55cdbb841d2c7..ac8e59a46688e25e62f1614194e80a21a596def7 100644 --- a/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/FormEngine/FieldWizard/LocalizationStateSelector.ts +++ b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/FormEngine/FieldWizard/LocalizationStateSelector.ts @@ -11,7 +11,8 @@ * The TYPO3 project - inspiring people to share! */ -import $ from 'jquery'; +import DocumentService = require('TYPO3/CMS/Core/DocumentService'); +import RegularEvent = require('TYPO3/CMS/Core/Event/RegularEvent'); enum States { CUSTOM = 'custom', @@ -19,7 +20,7 @@ enum States { class LocalizationStateSelector { constructor(fieldName: string) { - $((): void => { + DocumentService.ready().then((): void => { this.registerEventHandler(fieldName); }); } @@ -28,42 +29,38 @@ class LocalizationStateSelector { * @param {string} fieldName */ private registerEventHandler(fieldName: string): void { - $(document).on( - 'change', - '.t3js-l10n-state-container input[type="radio"][name="' + fieldName + '"]', - (e: JQueryEventObject): void => { - const $me = $(e.currentTarget); - const $input = $me.closest('.t3js-formengine-field-item').find('[data-formengine-input-name]'); + new RegularEvent('change', (e: Event): void => { + const target = e.target as HTMLInputElement; + const input: HTMLInputElement = target.closest('.t3js-formengine-field-item')?.querySelector('[data-formengine-input-name]'); + if (!input) { + return; + } - if ($input.length === 0) { - return; - } + const lastState = input.dataset.lastL10nState || false; + const currentState = target.value; - const lastState = $input.data('last-l10n-state') || false; - const currentState = $me.val(); + if (lastState && currentState === lastState) { + return; + } - if (lastState && currentState === lastState) { - return; + if (currentState === States.CUSTOM) { + if (lastState) { + target.dataset.originalLanguageValue = input.value; } - - if (currentState === States.CUSTOM) { - if (lastState) { - $me.attr('data-original-language-value', $input.val()); - } - $input.removeAttr('disabled'); - } else { - if (lastState === States.CUSTOM) { - $me.closest('.t3js-l10n-state-container') - .find('.t3js-l10n-state-custom') - .attr('data-original-language-value', $input.val()); - } - $input.attr('disabled', 'disabled'); + input.disabled = false; + } else { + if (lastState === States.CUSTOM) { + (target.closest('.t3js-l10n-state-container') + .querySelector('.t3js-l10n-state-custom') as HTMLElement) + .dataset.originalLanguageValue = input.value; } + input.disabled = true; + } - $input.val($me.attr('data-original-language-value')).trigger('change'); - $input.data('last-l10n-state', $me.val()); - }, - ); + input.value = target.dataset.originalLanguageValue; + input.dispatchEvent(new Event('change')); + input.dataset.lastL10nState = target.value; + }).delegateTo(document, '.t3js-l10n-state-container input[type="radio"][name="' + fieldName + '"]'); } } diff --git a/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/FormEngine/InlineRelation/AjaxDispatcher.ts b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/FormEngine/InlineRelation/AjaxDispatcher.ts index 1292c14df9a92a7fefbc064c912466c3b164e126..d0ef1c2e16d7e3d9179bb58e4bf9eceda4f681d1 100644 --- a/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/FormEngine/InlineRelation/AjaxDispatcher.ts +++ b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/FormEngine/InlineRelation/AjaxDispatcher.ts @@ -11,16 +11,30 @@ * The TYPO3 project - inspiring people to share! */ -import $ from 'jquery'; import {AjaxResponse} from 'TYPO3/CMS/Core/Ajax/AjaxResponse'; import AjaxRequest = require('TYPO3/CMS/Core/Ajax/AjaxRequest'); import Notification = require('../../Notification'); +import Utility = require('../../Utility'); interface Context { config: Object; hmac: string; } +interface Message { + title: string; + message: string; +} + +interface Response { + hasErrors: boolean; + messages: Message[]; + stylesheetFiles: string[]; + inlineData: object; + requireJsModules: string[]; + scriptCall: string[]; +} + export class AjaxDispatcher { private readonly objectGroup: string = null; @@ -77,18 +91,18 @@ export class AjaxDispatcher { return context; } - private processResponse(json: { [key: string]: any }): { [key: string]: any } { + private processResponse(json: Response): Response { if (json.hasErrors) { - $.each(json.messages, (position: number, message: { [key: string]: string }): void => { + for (const message of json.messages) { Notification.error(message.title, message.message); - }); + } } // If there are elements they should be added to the <HEAD> tag (e.g. for RTEhtmlarea): if (json.stylesheetFiles) { - $.each(json.stylesheetFiles, (index: number, stylesheetFile: string): void => { + for (const [index, stylesheetFile] of json.stylesheetFiles.entries()) { if (!stylesheetFile) { - return; + break; } const element = document.createElement('link'); element.rel = 'stylesheet'; @@ -96,11 +110,11 @@ export class AjaxDispatcher { element.href = stylesheetFile; document.querySelector('head').appendChild(element); delete json.stylesheetFiles[index]; - }); + } } if (typeof json.inlineData === 'object') { - TYPO3.settings.FormEngineInline = $.extend(true, TYPO3.settings.FormEngineInline, json.inlineData); + TYPO3.settings.FormEngineInline = Utility.mergeDeep(TYPO3.settings.FormEngineInline, json.inlineData); } if (typeof json.requireJsModules === 'object') { @@ -111,10 +125,10 @@ export class AjaxDispatcher { // TODO: This is subject to be removed if (json.scriptCall && json.scriptCall.length > 0) { - $.each(json.scriptCall, (index: number, value: string): void => { + for (const scriptCall of json.scriptCall) { // eslint-disable-next-line no-eval - eval(value); - }); + eval(scriptCall); + } } return json; diff --git a/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/Utility.ts b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/Utility.ts index 143bf309b2bd1837bb7e5001825bb2939aa8d600..60fce5cbae54f516d0d28ed75d6d4ef657bedfbd 100644 --- a/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/Utility.ts +++ b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/Utility.ts @@ -125,6 +125,38 @@ class Utility { return obj; } + + /** + * Performs a deep merge of `source` into `target`. + * Mutates `target` only but not its objects and arrays. + * + * @author inspired by [jhildenbiddle](https://stackoverflow.com/a/48218209/4828813). + */ + public static mergeDeep(...objects: object[]) { + type IndexedObject = { [key: string]: any }; + const isObject = (obj: any) => { + return obj && typeof obj === 'object'; + }; + + return objects.reduce((prev: IndexedObject, obj: IndexedObject): IndexedObject => { + Object.keys(obj).forEach((key: string): void => { + const pVal = prev[key]; + const oVal = obj[key]; + + if (Array.isArray(pVal) && Array.isArray(oVal)) { + prev[key] = pVal.concat(...oVal); + } + else if (isObject(pVal) && isObject(oVal)) { + prev[key] = Utility.mergeDeep(pVal, oVal); + } + else { + prev[key] = oVal; + } + }); + + return prev; + }, {}); + } } export = Utility; diff --git a/Build/types/TYPO3/index.d.ts b/Build/types/TYPO3/index.d.ts index a099089f25bd912f8442a1a77150543600106758..7f4b45c3ac52c9f2bfd535c4ba4aa2b314bd3019 100644 --- a/Build/types/TYPO3/index.d.ts +++ b/Build/types/TYPO3/index.d.ts @@ -58,7 +58,7 @@ declare namespace TYPO3 { label: string, title: string, exclusiveValues?: string, - $optionEl?: JQuery, + optionEl?: HTMLOptionElement | JQuery, ): void; public reinitialize(): void; public openPopupWindow(mode: string, params: string): JQuery; diff --git a/typo3/sysext/backend/Classes/Form/Element/SelectSingleElement.php b/typo3/sysext/backend/Classes/Form/Element/SelectSingleElement.php index 45fdf61591b5bf076a20153da2b49c4fc64a1a06..6d56462b5fa771e758a6394028d941e32d924e1f 100644 --- a/typo3/sysext/backend/Classes/Form/Element/SelectSingleElement.php +++ b/typo3/sysext/backend/Classes/Form/Element/SelectSingleElement.php @@ -256,8 +256,8 @@ class SelectSingleElement extends AbstractFormElement $resultArray['requireJsModules'][] = ['TYPO3/CMS/Backend/FormEngine/Element/SelectSingleElement' => implode(LF, [ 'function(SelectSingleElement) {', - 'require([\'jquery\'], function($) {', - '$(function() {', + 'require([\'TYPO3/CMS/Core/DocumentService\'], function(DocumentService) {', + 'DocumentService.ready().then(function() {', 'SelectSingleElement.initialize(', GeneralUtility::quoteJSvalue('#' . $selectId) . ',', '{', diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/DateTimePicker.js b/typo3/sysext/backend/Resources/Public/JavaScript/DateTimePicker.js index 8361f633b8cdc3066842d59fc1e80aaaa0924290..5336f482503331574790bb560d5cf11a924ffe06 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/DateTimePicker.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/DateTimePicker.js @@ -10,4 +10,4 @@ * * The TYPO3 project - inspiring people to share! */ -var __importDefault=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};define(["require","exports","jquery","moment","./Storage/Persistent"],(function(e,t,a,i,r){"use strict";a=__importDefault(a),i=__importDefault(i);class d{constructor(e){this.fieldSelector=".t3js-datetimepicker",this.format=(null!=opener&&void 0!==opener.top.TYPO3?opener.top:top).TYPO3.settings.DateTimePicker.DateFormat,a.default(()=>{this.initialize(e)})}static formatDateForHiddenField(e,t){return"time"!==t&&"timesec"!==t||e.year(1970).month(0).date(1),e.format()}initialize(t){const o=a.default(t||this.fieldSelector).filter((e,t)=>void 0===a.default(t).data("DateTimePicker"));o.length>0&&e(["twbs/bootstrap-datetimepicker"],()=>{let e=r.get("lang");"ch"===e&&(e="zh-cn");const t=e?i.default.locale(e):"";o.each((e,i)=>{this.initializeField(a.default(i),t)}),o.on("blur",e=>{const t=a.default(e.currentTarget),r=t.parent().parent().find('input[type="hidden"]');if(""===t.val())r.val("");else{const e=t.data("dateType"),a=t.data("DateTimePicker").format(),o=i.default.utc(t.val(),a);o.isValid()?r.val(d.formatDateForHiddenField(o,e)):t.val(d.formatDateForHiddenField(i.default.utc(r.val()),e))}}),o.on("dp.change",e=>{const t=a.default(e.currentTarget),i=t.parent().parent().find("input[type=hidden]"),r=t.data("dateType");let o="";""!==t.val()&&(o=d.formatDateForHiddenField(e.date.utc(),r)),i.val(o),a.default(document).trigger("formengine.dp.change",[t])})})}initializeField(e,t){const a=this.format,r={calendarWeeks:!0,format:"",locale:"",sideBySide:!0,showTodayButton:!0,toolbarPlacement:"bottom",icons:{time:"fa fa-clock-o",date:"fa fa-calendar",up:"fa fa-chevron-up",down:"fa fa-chevron-down",previous:"fa fa-chevron-left",next:"fa fa-chevron-right",today:"fa fa-calendar-o",clear:"fa fa-trash"}};switch(e.data("dateType")){case"datetime":r.format=a[1];break;case"date":r.format=a[0];break;case"time":r.format="HH:mm";break;case"timesec":r.format="HH:mm:ss";break;case"year":r.format="YYYY"}e.data("dateMindate")&&e.data("dateMindate",i.default.unix(e.data("dateMindate")).format(r.format)),e.data("dateMaxdate")&&e.data("dateMaxdate",i.default.unix(e.data("dateMaxdate")).format(r.format)),t&&(r.locale=t),e.datetimepicker(r)}}return new d})); \ No newline at end of file +var __importDefault=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};define(["require","exports","jquery","moment","./Storage/Persistent"],(function(e,t,a,i,d){"use strict";a=__importDefault(a),i=__importDefault(i);class r{constructor(e){this.fieldSelector=".t3js-datetimepicker",this.format=(null!=opener&&void 0!==opener.top.TYPO3?opener.top:top).TYPO3.settings.DateTimePicker.DateFormat,a.default(()=>{this.initialize(e)})}static formatDateForHiddenField(e,t){return"time"!==t&&"timesec"!==t||e.year(1970).month(0).date(1),e.format()}initialize(t){const o=a.default(t||this.fieldSelector).filter((e,t)=>void 0===a.default(t).data("DateTimePicker"));o.length>0&&e(["twbs/bootstrap-datetimepicker"],()=>{let e=d.get("lang");"ch"===e&&(e="zh-cn");const t=e?i.default.locale(e):"";o.each((e,i)=>{this.initializeField(a.default(i),t)}),o.on("blur",e=>{const t=a.default(e.currentTarget),d=t.parent().parent().find('input[type="hidden"]');if(""===t.val())d.val("");else{const e=t.data("dateType"),a=t.data("DateTimePicker").format(),o=i.default.utc(t.val(),a);o.isValid()?d.val(r.formatDateForHiddenField(o,e)):t.val(r.formatDateForHiddenField(i.default.utc(d.val()),e))}}),o.on("dp.change",e=>{const t=a.default(e.currentTarget),i=t.parent().parent().find("input[type=hidden]"),d=t.data("dateType");let o="";""!==t.val()&&(o=r.formatDateForHiddenField(e.date.utc(),d)),i.val(o),document.dispatchEvent(new CustomEvent("formengine.dp.change",{detail:{element:t}}))})})}initializeField(e,t){const a=this.format,d={calendarWeeks:!0,format:"",locale:"",sideBySide:!0,showTodayButton:!0,toolbarPlacement:"bottom",icons:{time:"fa fa-clock-o",date:"fa fa-calendar",up:"fa fa-chevron-up",down:"fa fa-chevron-down",previous:"fa fa-chevron-left",next:"fa fa-chevron-right",today:"fa fa-calendar-o",clear:"fa fa-trash"}};switch(e.data("dateType")){case"datetime":d.format=a[1];break;case"date":d.format=a[0];break;case"time":d.format="HH:mm";break;case"timesec":d.format="HH:mm:ss";break;case"year":d.format="YYYY"}e.data("dateMindate")&&e.data("dateMindate",i.default.unix(e.data("dateMindate")).format(d.format)),e.data("dateMaxdate")&&e.data("dateMaxdate",i.default.unix(e.data("dateMaxdate")).format(d.format)),t&&(d.locale=t),e.datetimepicker(d)}}return new r})); \ No newline at end of file diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine.js b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine.js index 76e5b4ee40d8d8d99ee3b7c0aadb593b08f41976..446767457826a47c6c2869bfdbfde6edaac566dc 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine.js @@ -85,9 +85,14 @@ define(['jquery', * @param {string} label The visible name in the selector * @param {string} title The title when hovering over it * @param {string} exclusiveValues If the select field has exclusive options that are not combine-able - * @param {$} $optionEl The jQuery object of the selected <option> tag + * @param {HTMLOptionElement|JQuery} optionEl The HTMLOptionElement object of the selected <option> tag */ - FormEngine.setSelectOptionFromExternalSource = function(fieldName, value, label, title, exclusiveValues, $optionEl) { + FormEngine.setSelectOptionFromExternalSource = function(fieldName, value, label, title, exclusiveValues, optionEl) { + if (optionEl instanceof $) { + console.warn('Passing the 6th argument (optionEl) of FormEngine.setSelectOptionFromExternalSource as a jQuery object has been marked as deprecated. Pass an element of type HTMLOptionElement instead.'); + optionEl = optionEl.get(0); + } + exclusiveValues = String(exclusiveValues); var $fieldEl, @@ -155,8 +160,11 @@ define(['jquery', } } - if (reenableOptions && typeof $optionEl !== 'undefined') { - $optionEl.closest('select').find('[disabled]').removeClass('hidden').prop('disabled', false) + if (reenableOptions && typeof optionEl !== 'undefined') { + optionEl.closest('select').querySelectorAll('[disabled]').forEach(function (disabledOption) { + disabledOption.classList.remove('hidden'); + disabledOption.disabled = false; + }); } } @@ -173,8 +181,9 @@ define(['jquery', } }); - if (addNewValue && typeof $optionEl !== 'undefined') { - $optionEl.addClass('hidden').prop('disabled', true); + if (addNewValue && typeof optionEl !== 'undefined') { + optionEl.classList.add('hidden'); + optionEl.disabled = true; } } diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Container/InlineControlContainer.js b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Container/InlineControlContainer.js index 8dd9977b4ffa5c8b60479473c34ddd937c5b4fd6..2829b26fb3c90b1a66e74e6b5cb33c1cb4a48419 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Container/InlineControlContainer.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Container/InlineControlContainer.js @@ -10,4 +10,4 @@ * * The TYPO3 project - inspiring people to share! */ -var __importDefault=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};define(["require","exports","jquery","../../Utility/MessageUtility","./../InlineRelation/AjaxDispatcher","nprogress","Sortable","TYPO3/CMS/Backend/FormEngine","TYPO3/CMS/Backend/FormEngineValidation","../../Icons","../../InfoWindow","../../Modal","../../Notification","TYPO3/CMS/Core/Event/RegularEvent","../../Severity","../../Utility"],(function(e,t,n,i,o,a,r,s,l,c,d,u,h,p,g,m){"use strict";var f,b,v,j;n=__importDefault(n),function(e){e.toggleSelector='[data-toggle="formengine-inline"]',e.controlSectionSelector=".t3js-formengine-irre-control",e.createNewRecordButtonSelector=".t3js-create-new-button",e.createNewRecordBySelectorSelector=".t3js-create-new-selector",e.deleteRecordButtonSelector=".t3js-editform-delete-inline-record",e.enableDisableRecordButtonSelector=".t3js-toggle-visibility-button",e.infoWindowButton='[data-action="infowindow"]',e.synchronizeLocalizeRecordButtonSelector=".t3js-synchronizelocalize-button",e.uniqueValueSelectors="select.t3js-inline-unique",e.revertUniqueness=".t3js-revert-unique",e.controlContainer=".t3js-inline-controls"}(f||(f={})),function(e){e.new="inlineIsNewRecord",e.visible="panel-visible",e.collapsed="panel-collapsed",e.notLoaded="t3js-not-loaded"}(b||(b={})),function(e){e.structureSeparator="-"}(v||(v={})),function(e){e.DOWN="down",e.UP="up"}(j||(j={}));class y{constructor(e){this.container=null,this.ajaxDispatcher=null,this.appearance=null,this.requestQueue={},this.progessQueue={},this.noTitleString=TYPO3.lang?TYPO3.lang["FormEngine.noRecordTitle"]:"[No title]",this.handlePostMessage=e=>{if(!i.MessageUtility.verifyOrigin(e.origin))throw"Denied message sent by "+e.origin;if("typo3:foreignRelation:insert"===e.data.actionName){if(void 0===e.data.objectGroup)throw"No object group defined for message";if(e.data.objectGroup!==this.container.dataset.objectGroup)return;if(this.isUniqueElementUsed(parseInt(e.data.uid,10),e.data.table))return void h.error("There is already a relation to the selected element");this.importRecord([e.data.objectGroup,e.data.uid]).then(()=>{if(e.source){const t={actionName:"typo3:foreignRelation:inserted",objectGroup:e.data.objectId,table:e.data.table,uid:e.data.uid};i.MessageUtility.send(t,e.source)}})}else console.warn(`Unhandled action "${e.data.actionName}"`)},n.default(()=>{this.container=document.getElementById(e),this.ajaxDispatcher=new o.AjaxDispatcher(this.container.dataset.objectGroup),this.registerEvents()})}static getInlineRecordContainer(e){return document.querySelector('[data-object-id="'+e+'"]')}static toggleElement(e){const t=y.getInlineRecordContainer(e);t.classList.contains(b.collapsed)?(t.classList.remove(b.collapsed),t.classList.add(b.visible)):(t.classList.remove(b.visible),t.classList.add(b.collapsed))}static isNewRecord(e){return y.getInlineRecordContainer(e).classList.contains(b.new)}static updateExpandedCollapsedStateLocally(e,t){const n=y.getInlineRecordContainer(e),i="uc[inlineView]["+n.dataset.topmostParentTable+"]["+n.dataset.topmostParentUid+"]"+n.dataset.fieldName,o=document.getElementsByName(i);o.length&&(o[0].value=t?"1":"0")}static getValuesFromHashMap(e){return Object.keys(e).map(t=>e[t])}static selectOptionValueExists(e,t){return null!==e.querySelector('option[value="'+t+'"]')}static removeSelectOptionByValue(e,t){const n=e.querySelector('option[value="'+t+'"]');null!==n&&n.remove()}static reAddSelectOption(e,t,n){if(y.selectOptionValueExists(e,t))return;const i=e.querySelectorAll("option");let o=-1;for(let e of Object.keys(n.possible)){if(e===t)break;for(let t=0;t<i.length;++t){if(i[t].value===e){o=t;break}}}-1===o?o=0:o<i.length&&o++;const a=document.createElement("option");a.text=n.possible[t],a.value=t,e.insertBefore(a,e.options[o])}registerEvents(){if(this.registerInfoButton(),this.registerSort(),this.registerCreateRecordButton(),this.registerEnableDisableButton(),this.registerDeleteButton(),this.registerSynchronizeLocalize(),this.registerRevertUniquenessAction(),this.registerToggle(),this.registerCreateRecordBySelector(),this.registerUniqueSelectFieldChanged(),new p("message",this.handlePostMessage).bindTo(window),this.getAppearance().useSortable){const e=document.getElementById(this.container.getAttribute("id")+"_records");new r(e,{group:e.getAttribute("id"),handle:".sortableHandle",onSort:()=>{this.updateSorting()}})}}registerToggle(){const e=this;new p("click",(function(t){t.preventDefault(),t.stopImmediatePropagation(),e.loadRecordDetails(this.closest(f.toggleSelector).parentElement.dataset.objectId)})).delegateTo(this.container,`${f.toggleSelector} .form-irre-header-cell:not(${f.controlSectionSelector}`)}registerSort(){const e=this;new p("click",(function(t){t.preventDefault(),t.stopImmediatePropagation(),e.changeSortingByButton(this.closest("[data-object-id]").dataset.objectId,this.dataset.direction)})).delegateTo(this.container,f.controlSectionSelector+' [data-action="sort"]')}registerCreateRecordButton(){const e=this;new p("click",(function(t){var n,i;if(t.preventDefault(),t.stopImmediatePropagation(),e.isBelowMax()){let t=e.container.dataset.objectGroup;void 0!==this.dataset.recordUid&&(t+=v.structureSeparator+this.dataset.recordUid),e.importRecord([t,null===(n=e.container.querySelector(f.createNewRecordBySelectorSelector))||void 0===n?void 0:n.value],null!==(i=this.dataset.recordUid)&&void 0!==i?i:null)}})).delegateTo(this.container,f.createNewRecordButtonSelector)}registerCreateRecordBySelector(){const e=this;new p("change",(function(t){t.preventDefault(),t.stopImmediatePropagation();const n=this.options[this.selectedIndex].getAttribute("value");e.importRecord([e.container.dataset.objectGroup,n])})).delegateTo(this.container,f.createNewRecordBySelectorSelector)}createRecord(e,t,n=null,i=null){let o=this.container.dataset.objectGroup;null!==n&&(o+=v.structureSeparator+n),null!==n?(y.getInlineRecordContainer(o).insertAdjacentHTML("afterend",t),this.memorizeAddRecord(e,n,i)):(document.getElementById(this.container.getAttribute("id")+"_records").insertAdjacentHTML("beforeend",t),this.memorizeAddRecord(e,null,i))}async importRecord(e,t){return this.ajaxDispatcher.send(this.ajaxDispatcher.newRequest(this.ajaxDispatcher.getEndpoint("record_inline_create")),e).then(async e=>{this.isBelowMax()&&(this.createRecord(e.compilerInput.uid,e.data,void 0!==t?t:null,void 0!==e.compilerInput.childChildUid?e.compilerInput.childChildUid:null),s.reinitialize(),s.Validation.initializeInputFields(),s.Validation.validate())})}registerEnableDisableButton(){new p("click",(e,t)=>{e.preventDefault(),e.stopImmediatePropagation();const n=t.closest("[data-object-id]").dataset.objectId,i=y.getInlineRecordContainer(n),o="data"+i.dataset.fieldName+"["+t.dataset.hiddenField+"]",a=document.querySelector('[data-formengine-input-name="'+o+'"'),r=document.querySelector('[name="'+o+'"');null!==a&&null!==r&&(a.checked=!a.checked,r.value=a.checked?"1":"0",TBE_EDITOR.fieldChanged(this.container.dataset.localTable,this.container.dataset.uid,this.container.dataset.localField,o));const s="t3-form-field-container-inline-hidden";let l="";i.classList.contains(s)?(l="actions-edit-hide",i.classList.remove(s)):(l="actions-edit-unhide",i.classList.add(s)),c.getIcon(l,c.sizes.small).then(e=>{t.replaceChild(document.createRange().createContextualFragment(e),t.querySelector(".t3js-icon"))})}).delegateTo(this.container,f.enableDisableRecordButtonSelector)}registerInfoButton(){new p("click",(function(e){e.preventDefault(),e.stopImmediatePropagation(),d.showItem(this.dataset.infoTable,this.dataset.infoUid)})).delegateTo(this.container,f.infoWindowButton)}registerDeleteButton(){const e=this;new p("click",(function(t){t.preventDefault(),t.stopImmediatePropagation();const n=TYPO3.lang["label.confirm.delete_record.title"]||"Delete this record?",i=TYPO3.lang["label.confirm.delete_record.content"]||"Are you sure you want to delete this record?";u.confirm(n,i,g.warning,[{text:TYPO3.lang["buttons.confirm.delete_record.no"]||"Cancel",active:!0,btnClass:"btn-default",name:"no"},{text:TYPO3.lang["buttons.confirm.delete_record.yes"]||"Yes, delete this record",btnClass:"btn-warning",name:"yes"}]).on("button.clicked",t=>{if("yes"===t.target.name){const t=this.closest("[data-object-id]").dataset.objectId;e.deleteRecord(t)}u.dismiss()})})).delegateTo(this.container,f.deleteRecordButtonSelector)}registerSynchronizeLocalize(){const e=this;new p("click",(function(t){t.preventDefault(),t.stopImmediatePropagation(),e.ajaxDispatcher.send(e.ajaxDispatcher.newRequest(e.ajaxDispatcher.getEndpoint("record_inline_synchronizelocalize")),[e.container.dataset.objectGroup,this.dataset.type]).then(async t=>{document.getElementById(e.container.getAttribute("id")+"_records").insertAdjacentHTML("beforeend",t.data);const n=e.container.dataset.objectGroup+v.structureSeparator;for(let i of t.compilerInput.delete)e.deleteRecord(n+i,!0);for(let i of Object.values(t.compilerInput.localize)){if(void 0!==i.remove){const e=y.getInlineRecordContainer(n+i.remove);e.parentElement.removeChild(e)}e.memorizeAddRecord(i.uid,null,i.selectedValue)}})})).delegateTo(this.container,f.synchronizeLocalizeRecordButtonSelector)}registerUniqueSelectFieldChanged(){const e=this;new p("change",(function(t){t.preventDefault(),t.stopImmediatePropagation();const n=this.closest("[data-object-id]");if(null!==n){const t=n.dataset.objectId,i=n.dataset.objectUid;e.handleChangedField(this,t);const o=e.getFormFieldForElements();if(null===o)return;e.updateUnique(this,o,i)}})).delegateTo(this.container,f.uniqueValueSelectors)}registerRevertUniquenessAction(){const e=this;new p("click",(function(t){t.preventDefault(),t.stopImmediatePropagation(),e.revertUnique(this.dataset.uid)})).delegateTo(this.container,f.revertUniqueness)}loadRecordDetails(e){const t=document.getElementById(e+"_fields"),n=y.getInlineRecordContainer(e),i=void 0!==this.requestQueue[e];if(null!==t&&!n.classList.contains(b.notLoaded))this.collapseExpandRecord(e);else{const o=this.getProgress(e,n.dataset.objectIdHash);if(i)this.requestQueue[e].abort(),delete this.requestQueue[e],delete this.progessQueue[e],o.done();else{const i=this.ajaxDispatcher.newRequest(this.ajaxDispatcher.getEndpoint("record_inline_details"));this.ajaxDispatcher.send(i,[e]).then(async i=>{if(delete this.requestQueue[e],delete this.progessQueue[e],n.classList.remove(b.notLoaded),t.innerHTML=i.data,this.collapseExpandRecord(e),o.done(),s.reinitialize(),s.Validation.initializeInputFields(),s.Validation.validate(),this.hasObjectGroupDefinedUniqueConstraints()){const t=y.getInlineRecordContainer(e);this.removeUsed(t)}}),this.requestQueue[e]=i,o.start()}}}collapseExpandRecord(e){const t=y.getInlineRecordContainer(e),n=!0===this.getAppearance().expandSingle,i=t.classList.contains(b.collapsed);let o=[];const a=[];n&&i&&(o=this.collapseAllRecords(t.dataset.objectUid)),y.toggleElement(e),y.isNewRecord(e)?y.updateExpandedCollapsedStateLocally(e,i):i?a.push(t.dataset.objectUid):i||o.push(t.dataset.objectUid),this.ajaxDispatcher.send(this.ajaxDispatcher.newRequest(this.ajaxDispatcher.getEndpoint("record_inline_expandcollapse")),[e,a.join(","),o.join(",")])}memorizeAddRecord(e,t=null,i=null){const o=this.getFormFieldForElements();if(null===o)return;let a=m.trimExplode(",",o.value);if(t){const n=[];for(let i=0;i<a.length;i++)a[i].length&&n.push(a[i]),t===a[i]&&n.push(e);a=n}else a.push(e);o.value=a.join(","),o.classList.add("has-change"),n.default(document).trigger("change"),this.redrawSortingButtons(this.container.dataset.objectGroup,a),this.setUnique(e,i),this.isBelowMax()||this.toggleContainerControls(!1),TBE_EDITOR.fieldChanged(this.container.dataset.localTable,this.container.dataset.uid,this.container.dataset.localField,o)}memorizeRemoveRecord(e){const t=this.getFormFieldForElements();if(null===t)return[];let i=m.trimExplode(",",t.value);const o=i.indexOf(e);return o>-1&&(delete i[o],t.value=i.join(","),t.classList.add("has-change"),n.default(document).trigger("change"),this.redrawSortingButtons(this.container.dataset.objectGroup,i)),i}changeSortingByButton(e,t){const n=y.getInlineRecordContainer(e),i=n.dataset.objectUid,o=document.getElementById(this.container.getAttribute("id")+"_records"),a=Array.from(o.children).map(e=>e.dataset.objectUid);let r=a.indexOf(i),s=!1;if(t===j.UP&&r>0?(a[r]=a[r-1],a[r-1]=i,s=!0):t===j.DOWN&&r<a.length-1&&(a[r]=a[r+1],a[r+1]=i,s=!0),s){const e=this.container.dataset.objectGroup+v.structureSeparator,i=t===j.UP?1:0;n.parentElement.insertBefore(y.getInlineRecordContainer(e+a[r-i]),y.getInlineRecordContainer(e+a[r+1-i])),this.updateSorting()}}updateSorting(){const e=this.getFormFieldForElements();if(null===e)return;const t=document.getElementById(this.container.getAttribute("id")+"_records"),i=Array.from(t.querySelectorAll('[data-placeholder-record="0"]')).map(e=>e.dataset.objectUid);e.value=i.join(","),e.classList.add("has-change"),n.default(document).trigger("inline:sorting-changed"),n.default(document).trigger("change"),this.redrawSortingButtons(this.container.dataset.objectGroup,i)}deleteRecord(e,t=!1){const n=y.getInlineRecordContainer(e),i=n.dataset.objectUid;if(n.classList.add("t3js-inline-record-deleted"),!y.isNewRecord(e)&&!t){const e=this.container.querySelector('[name="cmd'+n.dataset.fieldName+'[delete]"]');e.removeAttribute("disabled"),n.parentElement.insertAdjacentElement("afterbegin",e)}new p("transitionend",()=>{n.parentElement.removeChild(n),l.validate()}).bindTo(n),this.revertUnique(i),this.memorizeRemoveRecord(i),n.classList.add("form-irre-object--deleted"),this.isBelowMax()&&this.toggleContainerControls(!0)}toggleContainerControls(e){this.container.querySelector(f.controlContainer).querySelectorAll("a").forEach(t=>{t.style.display=e?null:"none"})}getProgress(e,t){const n="#"+t+"_header";let i;return void 0!==this.progessQueue[e]?i=this.progessQueue[e]:(i=a,i.configure({parent:n,showSpinner:!1}),this.progessQueue[e]=i),i}collapseAllRecords(e){const t=this.getFormFieldForElements(),n=[];if(null!==t){const i=m.trimExplode(",",t.value);for(let t of i){if(t===e)continue;const i=this.container.dataset.objectGroup+v.structureSeparator+t,o=y.getInlineRecordContainer(i);o.classList.contains(b.visible)&&(o.classList.remove(b.visible),o.classList.add(b.collapsed),y.isNewRecord(i)?y.updateExpandedCollapsedStateLocally(i,!1):n.push(t))}}return n}getFormFieldForElements(){const e=document.getElementsByName(this.container.dataset.formField);return e.length>0?e[0]:null}redrawSortingButtons(e,t=[]){if(0===t.length){const e=this.getFormFieldForElements();null!==e&&(t=m.trimExplode(",",e.value))}0!==t.length&&t.forEach((n,i)=>{const o=y.getInlineRecordContainer(e+v.structureSeparator+n).dataset.objectIdHash+"_header",a=document.getElementById(o),r=a.querySelector('[data-action="sort"][data-direction="'+j.UP+'"]');if(null!==r){let e="actions-move-up";0===i?(r.classList.add("disabled"),e="empty-empty"):r.classList.remove("disabled"),c.getIcon(e,c.sizes.small).then(e=>{r.replaceChild(document.createRange().createContextualFragment(e),r.querySelector(".t3js-icon"))})}const s=a.querySelector('[data-action="sort"][data-direction="'+j.DOWN+'"]');if(null!==s){let e="actions-move-down";i===t.length-1?(s.classList.add("disabled"),e="empty-empty"):s.classList.remove("disabled"),c.getIcon(e,c.sizes.small).then(e=>{s.replaceChild(document.createRange().createContextualFragment(e),s.querySelector(".t3js-icon"))})}})}isBelowMax(){const e=this.getFormFieldForElements();if(null===e)return!0;if(void 0!==TYPO3.settings.FormEngineInline.config[this.container.dataset.objectGroup]){if(m.trimExplode(",",e.value).length>=TYPO3.settings.FormEngineInline.config[this.container.dataset.objectGroup].max)return!1;if(this.hasObjectGroupDefinedUniqueConstraints()){const e=TYPO3.settings.FormEngineInline.unique[this.container.dataset.objectGroup];if(e.used.length>=e.max&&e.max>=0)return!1}}return!0}isUniqueElementUsed(e,t){if(!this.hasObjectGroupDefinedUniqueConstraints())return!1;const n=TYPO3.settings.FormEngineInline.unique[this.container.dataset.objectGroup],i=y.getValuesFromHashMap(n.used);if("select"===n.type&&-1!==i.indexOf(e))return!0;if("groupdb"===n.type)for(let n=i.length-1;n>=0;n--)if(i[n].table===t&&i[n].uid===e)return!0;return!1}removeUsed(e){if(!this.hasObjectGroupDefinedUniqueConstraints())return;const t=TYPO3.settings.FormEngineInline.unique[this.container.dataset.objectGroup];if("select"!==t.type)return;let n=e.querySelector('[name="data['+t.table+"]["+e.dataset.objectUid+"]["+t.field+']"]');const i=y.getValuesFromHashMap(t.used);if(null!==n){const e=n.options[n.selectedIndex].value;for(let t of i)t!==e&&y.removeSelectOptionByValue(n,t)}}setUnique(e,t){if(!this.hasObjectGroupDefinedUniqueConstraints())return;const n=document.getElementById(this.container.dataset.objectGroup+"_selector"),i=TYPO3.settings.FormEngineInline.unique[this.container.dataset.objectGroup];if("select"===i.type){if(!i.selector||-1!==i.max){const o=this.getFormFieldForElements(),a=this.container.dataset.objectGroup+v.structureSeparator+e;let r=y.getInlineRecordContainer(a).querySelector('[name="data['+i.table+"]["+e+"]["+i.field+']"]');const s=y.getValuesFromHashMap(i.used);if(null!==n){if(null!==r){for(let e of s)y.removeSelectOptionByValue(r,e);i.selector||(t=r.options[0].value,r.options[0].selected=!0,this.updateUnique(r,o,e),this.handleChangedField(r,this.container.dataset.objectGroup+"["+e+"]"))}for(let e of s)y.removeSelectOptionByValue(r,e);void 0!==i.used.length&&(i.used={}),i.used[e]={table:i.elTable,uid:t}}if(null!==o&&y.selectOptionValueExists(n,t)){const n=m.trimExplode(",",o.value);for(let o of n)r=document.querySelector('[name="data['+i.table+"]["+o+"]["+i.field+']"]'),null!==r&&o!==e&&y.removeSelectOptionByValue(r,t)}}}else"groupdb"===i.type&&(i.used[e]={table:i.elTable,uid:t});"select"===i.selector&&y.selectOptionValueExists(n,t)&&(y.removeSelectOptionByValue(n,t),i.used[e]={table:i.elTable,uid:t})}updateUnique(e,t,n){if(!this.hasObjectGroupDefinedUniqueConstraints())return;const i=TYPO3.settings.FormEngineInline.unique[this.container.dataset.objectGroup],o=i.used[n];if("select"===i.selector){const t=document.getElementById(this.container.dataset.objectGroup+"_selector");y.removeSelectOptionByValue(t,e.value),void 0!==o&&y.reAddSelectOption(t,o,i)}if(i.selector&&-1===i.max)return;if(!i||null===t)return;const a=m.trimExplode(",",t.value);let r;for(let t of a)r=document.querySelector('[name="data['+i.table+"]["+t+"]["+i.field+']"]'),null!==r&&r!==e&&(y.removeSelectOptionByValue(r,e.value),void 0!==o&&y.reAddSelectOption(r,o,i));i.used[n]=e.value}revertUnique(e){if(!this.hasObjectGroupDefinedUniqueConstraints())return;const t=TYPO3.settings.FormEngineInline.unique[this.container.dataset.objectGroup],n=this.container.dataset.objectGroup+v.structureSeparator+e,i=y.getInlineRecordContainer(n);let o=i.querySelector('[name="data['+t.table+"]["+i.dataset.objectUid+"]["+t.field+']"]');if("select"===t.type){let n;if(null!==o)n=o.value;else{if(""===i.dataset.tableUniqueOriginalValue)return;n=i.dataset.tableUniqueOriginalValue}if("select"===t.selector&&!isNaN(parseInt(n,10))){const e=document.getElementById(this.container.dataset.objectGroup+"_selector");y.reAddSelectOption(e,n,t)}if(t.selector&&-1===t.max)return;const a=this.getFormFieldForElements();if(null===a)return;const r=m.trimExplode(",",a.value);let s;for(let e=0;e<r.length;e++)s=document.querySelector('[name="data['+t.table+"]["+r[e]+"]["+t.field+']"]'),null!==s&&y.reAddSelectOption(s,n,t);delete t.used[e]}else"groupdb"===t.type&&delete t.used[e]}hasObjectGroupDefinedUniqueConstraints(){return void 0!==TYPO3.settings.FormEngineInline.unique&&void 0!==TYPO3.settings.FormEngineInline.unique[this.container.dataset.objectGroup]}handleChangedField(e,t){let n;n=e instanceof HTMLSelectElement?e.options[e.selectedIndex].text:e.value,document.getElementById(t+"_label").textContent=n.length?n:this.noTitleString}getAppearance(){if(null===this.appearance&&(this.appearance={},"string"==typeof this.container.dataset.appearance))try{this.appearance=JSON.parse(this.container.dataset.appearance)}catch(e){console.error(e)}return this.appearance}}return y})); \ No newline at end of file +define(["require","exports","../../Utility/MessageUtility","./../InlineRelation/AjaxDispatcher","TYPO3/CMS/Core/DocumentService","nprogress","Sortable","TYPO3/CMS/Backend/FormEngine","TYPO3/CMS/Backend/FormEngineValidation","../../Icons","../../InfoWindow","../../Modal","../../Notification","TYPO3/CMS/Core/Event/RegularEvent","../../Severity","../../Utility"],(function(e,t,n,i,o,a,r,s,l,c,d,u,h,p,g,m){"use strict";var f,b,v,j;!function(e){e.toggleSelector='[data-toggle="formengine-inline"]',e.controlSectionSelector=".t3js-formengine-irre-control",e.createNewRecordButtonSelector=".t3js-create-new-button",e.createNewRecordBySelectorSelector=".t3js-create-new-selector",e.deleteRecordButtonSelector=".t3js-editform-delete-inline-record",e.enableDisableRecordButtonSelector=".t3js-toggle-visibility-button",e.infoWindowButton='[data-action="infowindow"]',e.synchronizeLocalizeRecordButtonSelector=".t3js-synchronizelocalize-button",e.uniqueValueSelectors="select.t3js-inline-unique",e.revertUniqueness=".t3js-revert-unique",e.controlContainer=".t3js-inline-controls"}(f||(f={})),function(e){e.new="inlineIsNewRecord",e.visible="panel-visible",e.collapsed="panel-collapsed",e.notLoaded="t3js-not-loaded"}(b||(b={})),function(e){e.structureSeparator="-"}(v||(v={})),function(e){e.DOWN="down",e.UP="up"}(j||(j={}));class S{constructor(e){this.container=null,this.ajaxDispatcher=null,this.appearance=null,this.requestQueue={},this.progessQueue={},this.noTitleString=TYPO3.lang?TYPO3.lang["FormEngine.noRecordTitle"]:"[No title]",this.handlePostMessage=e=>{if(!n.MessageUtility.verifyOrigin(e.origin))throw"Denied message sent by "+e.origin;if("typo3:foreignRelation:insert"===e.data.actionName){if(void 0===e.data.objectGroup)throw"No object group defined for message";if(e.data.objectGroup!==this.container.dataset.objectGroup)return;if(this.isUniqueElementUsed(parseInt(e.data.uid,10),e.data.table))return void h.error("There is already a relation to the selected element");this.importRecord([e.data.objectGroup,e.data.uid]).then(()=>{if(e.source){const t={actionName:"typo3:foreignRelation:inserted",objectGroup:e.data.objectId,table:e.data.table,uid:e.data.uid};n.MessageUtility.send(t,e.source)}})}else console.warn(`Unhandled action "${e.data.actionName}"`)},o.ready().then(t=>{this.container=t.getElementById(e),this.ajaxDispatcher=new i.AjaxDispatcher(this.container.dataset.objectGroup),this.registerEvents()})}static getInlineRecordContainer(e){return document.querySelector('[data-object-id="'+e+'"]')}static toggleElement(e){const t=S.getInlineRecordContainer(e);t.classList.contains(b.collapsed)?(t.classList.remove(b.collapsed),t.classList.add(b.visible)):(t.classList.remove(b.visible),t.classList.add(b.collapsed))}static isNewRecord(e){return S.getInlineRecordContainer(e).classList.contains(b.new)}static updateExpandedCollapsedStateLocally(e,t){const n=S.getInlineRecordContainer(e),i="uc[inlineView]["+n.dataset.topmostParentTable+"]["+n.dataset.topmostParentUid+"]"+n.dataset.fieldName,o=document.getElementsByName(i);o.length&&(o[0].value=t?"1":"0")}static getValuesFromHashMap(e){return Object.keys(e).map(t=>e[t])}static selectOptionValueExists(e,t){return null!==e.querySelector('option[value="'+t+'"]')}static removeSelectOptionByValue(e,t){const n=e.querySelector('option[value="'+t+'"]');null!==n&&n.remove()}static reAddSelectOption(e,t,n){if(S.selectOptionValueExists(e,t))return;const i=e.querySelectorAll("option");let o=-1;for(let e of Object.keys(n.possible)){if(e===t)break;for(let t=0;t<i.length;++t){if(i[t].value===e){o=t;break}}}-1===o?o=0:o<i.length&&o++;const a=document.createElement("option");a.text=n.possible[t],a.value=t,e.insertBefore(a,e.options[o])}registerEvents(){if(this.registerInfoButton(),this.registerSort(),this.registerCreateRecordButton(),this.registerEnableDisableButton(),this.registerDeleteButton(),this.registerSynchronizeLocalize(),this.registerRevertUniquenessAction(),this.registerToggle(),this.registerCreateRecordBySelector(),this.registerUniqueSelectFieldChanged(),new p("message",this.handlePostMessage).bindTo(window),this.getAppearance().useSortable){const e=document.getElementById(this.container.getAttribute("id")+"_records");new r(e,{group:e.getAttribute("id"),handle:".sortableHandle",onSort:()=>{this.updateSorting()}})}}registerToggle(){const e=this;new p("click",(function(t){t.preventDefault(),t.stopImmediatePropagation(),e.loadRecordDetails(this.closest(f.toggleSelector).parentElement.dataset.objectId)})).delegateTo(this.container,`${f.toggleSelector} .form-irre-header-cell:not(${f.controlSectionSelector}`)}registerSort(){const e=this;new p("click",(function(t){t.preventDefault(),t.stopImmediatePropagation(),e.changeSortingByButton(this.closest("[data-object-id]").dataset.objectId,this.dataset.direction)})).delegateTo(this.container,f.controlSectionSelector+' [data-action="sort"]')}registerCreateRecordButton(){const e=this;new p("click",(function(t){var n,i;if(t.preventDefault(),t.stopImmediatePropagation(),e.isBelowMax()){let t=e.container.dataset.objectGroup;void 0!==this.dataset.recordUid&&(t+=v.structureSeparator+this.dataset.recordUid),e.importRecord([t,null===(n=e.container.querySelector(f.createNewRecordBySelectorSelector))||void 0===n?void 0:n.value],null!==(i=this.dataset.recordUid)&&void 0!==i?i:null)}})).delegateTo(this.container,f.createNewRecordButtonSelector)}registerCreateRecordBySelector(){const e=this;new p("change",(function(t){t.preventDefault(),t.stopImmediatePropagation();const n=this.options[this.selectedIndex].getAttribute("value");e.importRecord([e.container.dataset.objectGroup,n])})).delegateTo(this.container,f.createNewRecordBySelectorSelector)}createRecord(e,t,n=null,i=null){let o=this.container.dataset.objectGroup;null!==n&&(o+=v.structureSeparator+n),null!==n?(S.getInlineRecordContainer(o).insertAdjacentHTML("afterend",t),this.memorizeAddRecord(e,n,i)):(document.getElementById(this.container.getAttribute("id")+"_records").insertAdjacentHTML("beforeend",t),this.memorizeAddRecord(e,null,i))}async importRecord(e,t){return this.ajaxDispatcher.send(this.ajaxDispatcher.newRequest(this.ajaxDispatcher.getEndpoint("record_inline_create")),e).then(async e=>{this.isBelowMax()&&(this.createRecord(e.compilerInput.uid,e.data,void 0!==t?t:null,void 0!==e.compilerInput.childChildUid?e.compilerInput.childChildUid:null),s.reinitialize(),s.Validation.initializeInputFields(),s.Validation.validate())})}registerEnableDisableButton(){new p("click",(e,t)=>{e.preventDefault(),e.stopImmediatePropagation();const n=t.closest("[data-object-id]").dataset.objectId,i=S.getInlineRecordContainer(n),o="data"+i.dataset.fieldName+"["+t.dataset.hiddenField+"]",a=document.querySelector('[data-formengine-input-name="'+o+'"'),r=document.querySelector('[name="'+o+'"');null!==a&&null!==r&&(a.checked=!a.checked,r.value=a.checked?"1":"0",TBE_EDITOR.fieldChanged(this.container.dataset.localTable,this.container.dataset.uid,this.container.dataset.localField,o));const s="t3-form-field-container-inline-hidden";let l;i.classList.contains(s)?(l="actions-edit-hide",i.classList.remove(s)):(l="actions-edit-unhide",i.classList.add(s)),c.getIcon(l,c.sizes.small).then(e=>{t.replaceChild(document.createRange().createContextualFragment(e),t.querySelector(".t3js-icon"))})}).delegateTo(this.container,f.enableDisableRecordButtonSelector)}registerInfoButton(){new p("click",(function(e){e.preventDefault(),e.stopImmediatePropagation(),d.showItem(this.dataset.infoTable,this.dataset.infoUid)})).delegateTo(this.container,f.infoWindowButton)}registerDeleteButton(){const e=this;new p("click",(function(t){t.preventDefault(),t.stopImmediatePropagation();const n=TYPO3.lang["label.confirm.delete_record.title"]||"Delete this record?",i=TYPO3.lang["label.confirm.delete_record.content"]||"Are you sure you want to delete this record?";u.confirm(n,i,g.warning,[{text:TYPO3.lang["buttons.confirm.delete_record.no"]||"Cancel",active:!0,btnClass:"btn-default",name:"no"},{text:TYPO3.lang["buttons.confirm.delete_record.yes"]||"Yes, delete this record",btnClass:"btn-warning",name:"yes"}]).on("button.clicked",t=>{if("yes"===t.target.name){const t=this.closest("[data-object-id]").dataset.objectId;e.deleteRecord(t)}u.dismiss()})})).delegateTo(this.container,f.deleteRecordButtonSelector)}registerSynchronizeLocalize(){const e=this;new p("click",(function(t){t.preventDefault(),t.stopImmediatePropagation(),e.ajaxDispatcher.send(e.ajaxDispatcher.newRequest(e.ajaxDispatcher.getEndpoint("record_inline_synchronizelocalize")),[e.container.dataset.objectGroup,this.dataset.type]).then(async t=>{document.getElementById(e.container.getAttribute("id")+"_records").insertAdjacentHTML("beforeend",t.data);const n=e.container.dataset.objectGroup+v.structureSeparator;for(let i of t.compilerInput.delete)e.deleteRecord(n+i,!0);for(let i of Object.values(t.compilerInput.localize)){if(void 0!==i.remove){const e=S.getInlineRecordContainer(n+i.remove);e.parentElement.removeChild(e)}e.memorizeAddRecord(i.uid,null,i.selectedValue)}})})).delegateTo(this.container,f.synchronizeLocalizeRecordButtonSelector)}registerUniqueSelectFieldChanged(){const e=this;new p("change",(function(t){t.preventDefault(),t.stopImmediatePropagation();const n=this.closest("[data-object-id]");if(null!==n){const t=n.dataset.objectId,i=n.dataset.objectUid;e.handleChangedField(this,t);const o=e.getFormFieldForElements();if(null===o)return;e.updateUnique(this,o,i)}})).delegateTo(this.container,f.uniqueValueSelectors)}registerRevertUniquenessAction(){const e=this;new p("click",(function(t){t.preventDefault(),t.stopImmediatePropagation(),e.revertUnique(this.dataset.uid)})).delegateTo(this.container,f.revertUniqueness)}loadRecordDetails(e){const t=document.getElementById(e+"_fields"),n=S.getInlineRecordContainer(e),i=void 0!==this.requestQueue[e];if(null!==t&&!n.classList.contains(b.notLoaded))this.collapseExpandRecord(e);else{const o=this.getProgress(e,n.dataset.objectIdHash);if(i)this.requestQueue[e].abort(),delete this.requestQueue[e],delete this.progessQueue[e],o.done();else{const i=this.ajaxDispatcher.newRequest(this.ajaxDispatcher.getEndpoint("record_inline_details"));this.ajaxDispatcher.send(i,[e]).then(async i=>{if(delete this.requestQueue[e],delete this.progessQueue[e],n.classList.remove(b.notLoaded),t.innerHTML=i.data,this.collapseExpandRecord(e),o.done(),s.reinitialize(),s.Validation.initializeInputFields(),s.Validation.validate(),this.hasObjectGroupDefinedUniqueConstraints()){const t=S.getInlineRecordContainer(e);this.removeUsed(t)}}),this.requestQueue[e]=i,o.start()}}}collapseExpandRecord(e){const t=S.getInlineRecordContainer(e),n=!0===this.getAppearance().expandSingle,i=t.classList.contains(b.collapsed);let o=[];const a=[];n&&i&&(o=this.collapseAllRecords(t.dataset.objectUid)),S.toggleElement(e),S.isNewRecord(e)?S.updateExpandedCollapsedStateLocally(e,i):i?a.push(t.dataset.objectUid):i||o.push(t.dataset.objectUid),this.ajaxDispatcher.send(this.ajaxDispatcher.newRequest(this.ajaxDispatcher.getEndpoint("record_inline_expandcollapse")),[e,a.join(","),o.join(",")])}memorizeAddRecord(e,t=null,n=null){const i=this.getFormFieldForElements();if(null===i)return;let o=m.trimExplode(",",i.value);if(t){const n=[];for(let i=0;i<o.length;i++)o[i].length&&n.push(o[i]),t===o[i]&&n.push(e);o=n}else o.push(e);i.value=o.join(","),i.classList.add("has-change"),document.dispatchEvent(new Event("change")),this.redrawSortingButtons(this.container.dataset.objectGroup,o),this.setUnique(e,n),this.isBelowMax()||this.toggleContainerControls(!1),TBE_EDITOR.fieldChanged(this.container.dataset.localTable,this.container.dataset.uid,this.container.dataset.localField,i)}memorizeRemoveRecord(e){const t=this.getFormFieldForElements();if(null===t)return[];let n=m.trimExplode(",",t.value);const i=n.indexOf(e);return i>-1&&(delete n[i],t.value=n.join(","),t.classList.add("has-change"),document.dispatchEvent(new Event("change")),this.redrawSortingButtons(this.container.dataset.objectGroup,n)),n}changeSortingByButton(e,t){const n=S.getInlineRecordContainer(e),i=n.dataset.objectUid,o=document.getElementById(this.container.getAttribute("id")+"_records"),a=Array.from(o.children).map(e=>e.dataset.objectUid);let r=a.indexOf(i),s=!1;if(t===j.UP&&r>0?(a[r]=a[r-1],a[r-1]=i,s=!0):t===j.DOWN&&r<a.length-1&&(a[r]=a[r+1],a[r+1]=i,s=!0),s){const e=this.container.dataset.objectGroup+v.structureSeparator,i=t===j.UP?1:0;n.parentElement.insertBefore(S.getInlineRecordContainer(e+a[r-i]),S.getInlineRecordContainer(e+a[r+1-i])),this.updateSorting()}}updateSorting(){const e=this.getFormFieldForElements();if(null===e)return;const t=document.getElementById(this.container.getAttribute("id")+"_records"),n=Array.from(t.querySelectorAll('[data-placeholder-record="0"]')).map(e=>e.dataset.objectUid);e.value=n.join(","),e.classList.add("has-change"),document.dispatchEvent(new Event("inline:sorting-changed")),document.dispatchEvent(new Event("change")),this.redrawSortingButtons(this.container.dataset.objectGroup,n)}deleteRecord(e,t=!1){const n=S.getInlineRecordContainer(e),i=n.dataset.objectUid;if(n.classList.add("t3js-inline-record-deleted"),!S.isNewRecord(e)&&!t){const e=this.container.querySelector('[name="cmd'+n.dataset.fieldName+'[delete]"]');e.removeAttribute("disabled"),n.parentElement.insertAdjacentElement("afterbegin",e)}new p("transitionend",()=>{n.parentElement.removeChild(n),l.validate()}).bindTo(n),this.revertUnique(i),this.memorizeRemoveRecord(i),n.classList.add("form-irre-object--deleted"),this.isBelowMax()&&this.toggleContainerControls(!0)}toggleContainerControls(e){this.container.querySelector(f.controlContainer).querySelectorAll("a").forEach(t=>{t.style.display=e?null:"none"})}getProgress(e,t){const n="#"+t+"_header";let i;return void 0!==this.progessQueue[e]?i=this.progessQueue[e]:(i=a,i.configure({parent:n,showSpinner:!1}),this.progessQueue[e]=i),i}collapseAllRecords(e){const t=this.getFormFieldForElements(),n=[];if(null!==t){const i=m.trimExplode(",",t.value);for(let t of i){if(t===e)continue;const i=this.container.dataset.objectGroup+v.structureSeparator+t,o=S.getInlineRecordContainer(i);o.classList.contains(b.visible)&&(o.classList.remove(b.visible),o.classList.add(b.collapsed),S.isNewRecord(i)?S.updateExpandedCollapsedStateLocally(i,!1):n.push(t))}}return n}getFormFieldForElements(){const e=document.getElementsByName(this.container.dataset.formField);return e.length>0?e[0]:null}redrawSortingButtons(e,t=[]){if(0===t.length){const e=this.getFormFieldForElements();null!==e&&(t=m.trimExplode(",",e.value))}0!==t.length&&t.forEach((n,i)=>{const o=S.getInlineRecordContainer(e+v.structureSeparator+n).dataset.objectIdHash+"_header",a=document.getElementById(o),r=a.querySelector('[data-action="sort"][data-direction="'+j.UP+'"]');if(null!==r){let e="actions-move-up";0===i?(r.classList.add("disabled"),e="empty-empty"):r.classList.remove("disabled"),c.getIcon(e,c.sizes.small).then(e=>{r.replaceChild(document.createRange().createContextualFragment(e),r.querySelector(".t3js-icon"))})}const s=a.querySelector('[data-action="sort"][data-direction="'+j.DOWN+'"]');if(null!==s){let e="actions-move-down";i===t.length-1?(s.classList.add("disabled"),e="empty-empty"):s.classList.remove("disabled"),c.getIcon(e,c.sizes.small).then(e=>{s.replaceChild(document.createRange().createContextualFragment(e),s.querySelector(".t3js-icon"))})}})}isBelowMax(){const e=this.getFormFieldForElements();if(null===e)return!0;if(void 0!==TYPO3.settings.FormEngineInline.config[this.container.dataset.objectGroup]){if(m.trimExplode(",",e.value).length>=TYPO3.settings.FormEngineInline.config[this.container.dataset.objectGroup].max)return!1;if(this.hasObjectGroupDefinedUniqueConstraints()){const e=TYPO3.settings.FormEngineInline.unique[this.container.dataset.objectGroup];if(e.used.length>=e.max&&e.max>=0)return!1}}return!0}isUniqueElementUsed(e,t){if(!this.hasObjectGroupDefinedUniqueConstraints())return!1;const n=TYPO3.settings.FormEngineInline.unique[this.container.dataset.objectGroup],i=S.getValuesFromHashMap(n.used);if("select"===n.type&&-1!==i.indexOf(e))return!0;if("groupdb"===n.type)for(let n=i.length-1;n>=0;n--)if(i[n].table===t&&i[n].uid===e)return!0;return!1}removeUsed(e){if(!this.hasObjectGroupDefinedUniqueConstraints())return;const t=TYPO3.settings.FormEngineInline.unique[this.container.dataset.objectGroup];if("select"!==t.type)return;let n=e.querySelector('[name="data['+t.table+"]["+e.dataset.objectUid+"]["+t.field+']"]');const i=S.getValuesFromHashMap(t.used);if(null!==n){const e=n.options[n.selectedIndex].value;for(let t of i)t!==e&&S.removeSelectOptionByValue(n,t)}}setUnique(e,t){if(!this.hasObjectGroupDefinedUniqueConstraints())return;const n=document.getElementById(this.container.dataset.objectGroup+"_selector"),i=TYPO3.settings.FormEngineInline.unique[this.container.dataset.objectGroup];if("select"===i.type){if(!i.selector||-1!==i.max){const o=this.getFormFieldForElements(),a=this.container.dataset.objectGroup+v.structureSeparator+e;let r=S.getInlineRecordContainer(a).querySelector('[name="data['+i.table+"]["+e+"]["+i.field+']"]');const s=S.getValuesFromHashMap(i.used);if(null!==n){if(null!==r){for(let e of s)S.removeSelectOptionByValue(r,e);i.selector||(t=r.options[0].value,r.options[0].selected=!0,this.updateUnique(r,o,e),this.handleChangedField(r,this.container.dataset.objectGroup+"["+e+"]"))}for(let e of s)S.removeSelectOptionByValue(r,e);void 0!==i.used.length&&(i.used={}),i.used[e]={table:i.elTable,uid:t}}if(null!==o&&S.selectOptionValueExists(n,t)){const n=m.trimExplode(",",o.value);for(let o of n)r=document.querySelector('[name="data['+i.table+"]["+o+"]["+i.field+']"]'),null!==r&&o!==e&&S.removeSelectOptionByValue(r,t)}}}else"groupdb"===i.type&&(i.used[e]={table:i.elTable,uid:t});"select"===i.selector&&S.selectOptionValueExists(n,t)&&(S.removeSelectOptionByValue(n,t),i.used[e]={table:i.elTable,uid:t})}updateUnique(e,t,n){if(!this.hasObjectGroupDefinedUniqueConstraints())return;const i=TYPO3.settings.FormEngineInline.unique[this.container.dataset.objectGroup],o=i.used[n];if("select"===i.selector){const t=document.getElementById(this.container.dataset.objectGroup+"_selector");S.removeSelectOptionByValue(t,e.value),void 0!==o&&S.reAddSelectOption(t,o,i)}if(i.selector&&-1===i.max)return;if(!i||null===t)return;const a=m.trimExplode(",",t.value);let r;for(let t of a)r=document.querySelector('[name="data['+i.table+"]["+t+"]["+i.field+']"]'),null!==r&&r!==e&&(S.removeSelectOptionByValue(r,e.value),void 0!==o&&S.reAddSelectOption(r,o,i));i.used[n]=e.value}revertUnique(e){if(!this.hasObjectGroupDefinedUniqueConstraints())return;const t=TYPO3.settings.FormEngineInline.unique[this.container.dataset.objectGroup],n=this.container.dataset.objectGroup+v.structureSeparator+e,i=S.getInlineRecordContainer(n);let o=i.querySelector('[name="data['+t.table+"]["+i.dataset.objectUid+"]["+t.field+']"]');if("select"===t.type){let n;if(null!==o)n=o.value;else{if(""===i.dataset.tableUniqueOriginalValue)return;n=i.dataset.tableUniqueOriginalValue}if("select"===t.selector&&!isNaN(parseInt(n,10))){const e=document.getElementById(this.container.dataset.objectGroup+"_selector");S.reAddSelectOption(e,n,t)}if(t.selector&&-1===t.max)return;const a=this.getFormFieldForElements();if(null===a)return;const r=m.trimExplode(",",a.value);let s;for(let e=0;e<r.length;e++)s=document.querySelector('[name="data['+t.table+"]["+r[e]+"]["+t.field+']"]'),null!==s&&S.reAddSelectOption(s,n,t);delete t.used[e]}else"groupdb"===t.type&&delete t.used[e]}hasObjectGroupDefinedUniqueConstraints(){return void 0!==TYPO3.settings.FormEngineInline.unique&&void 0!==TYPO3.settings.FormEngineInline.unique[this.container.dataset.objectGroup]}handleChangedField(e,t){let n;n=e instanceof HTMLSelectElement?e.options[e.selectedIndex].text:e.value,document.getElementById(t+"_label").textContent=n.length?n:this.noTitleString}getAppearance(){if(null===this.appearance&&(this.appearance={},"string"==typeof this.container.dataset.appearance))try{this.appearance=JSON.parse(this.container.dataset.appearance)}catch(e){console.error(e)}return this.appearance}}return S})); \ No newline at end of file diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/Extra/SelectBoxFilter.js b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/Extra/SelectBoxFilter.js index 0ecaa6037e10f30c3a0199c4ae16f2df78ecbd9b..371d612b8c43d6c855164d4eadff6673af9b354a 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/Extra/SelectBoxFilter.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/Extra/SelectBoxFilter.js @@ -10,4 +10,4 @@ * * The TYPO3 project - inspiring people to share! */ -var __importDefault=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};define(["require","exports","jquery"],(function(e,t,i){"use strict";var l;i=__importDefault(i),function(e){e.fieldContainerSelector=".t3js-formengine-field-group",e.filterTextFieldSelector=".t3js-formengine-multiselect-filter-textfield",e.filterSelectFieldSelector=".t3js-formengine-multiselect-filter-dropdown"}(l||(l={}));return class{constructor(e){this.selectElement=null,this.filterText="",this.$availableOptions=null,this.selectElement=e,this.initializeEvents()}initializeEvents(){const e=this.selectElement.closest(".form-wizards-element");null!==e&&(e.addEventListener("keyup",e=>{e.target.matches(l.filterTextFieldSelector)&&this.filter(e.target.value)}),e.addEventListener("change",e=>{e.target.matches(l.filterSelectFieldSelector)&&this.filter(e.target.value)}))}filter(e){this.filterText=e,this.$availableOptions||(this.$availableOptions=i.default(this.selectElement).find("option").clone()),this.selectElement.innerHTML="";const t=new RegExp(e,"i");this.$availableOptions.each((i,l)=>{(0===e.length||l.textContent.match(t))&&this.selectElement.appendChild(l)})}}})); \ No newline at end of file +define(["require","exports","TYPO3/CMS/Core/Event/RegularEvent"],(function(e,t,l){"use strict";var i;!function(e){e.fieldContainerSelector=".t3js-formengine-field-group",e.filterTextFieldSelector=".t3js-formengine-multiselect-filter-textfield",e.filterSelectFieldSelector=".t3js-formengine-multiselect-filter-dropdown"}(i||(i={}));return class{constructor(e){this.selectElement=null,this.filterText="",this.availableOptions=null,this.selectElement=e,this.initializeEvents()}initializeEvents(){const e=this.selectElement.closest(".form-wizards-element");null!==e&&(new l("input",e=>{this.filter(e.target.value)}).delegateTo(e,i.filterTextFieldSelector),new l("change",e=>{this.filter(e.target.value)}).delegateTo(e,i.filterSelectFieldSelector))}filter(e){this.filterText=e,null===this.availableOptions&&(this.availableOptions=this.selectElement.querySelectorAll("option"));const t=new RegExp(e,"i");this.availableOptions.forEach(l=>{l.hidden=e.length>0&&null===l.textContent.match(t)})}}})); \ No newline at end of file diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/InputDateTimeElement.js b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/InputDateTimeElement.js index 245d17bdc0b44309fce5e5822eb8ff7068809101..70c82596fab744dd0b17515c9d1d62e92ab9cc4a 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/InputDateTimeElement.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/InputDateTimeElement.js @@ -10,4 +10,4 @@ * * The TYPO3 project - inspiring people to share! */ -var __importDefault=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};define(["require","exports","jquery","TYPO3/CMS/Backend/FormEngine"],(function(e,t,i,r){"use strict";i=__importDefault(i);return class{constructor(t){i.default(()=>{this.registerEventHandler(),e(["../../DateTimePicker"],e=>{e.initialize("#"+t)})})}registerEventHandler(){i.default(document).on("formengine.dp.change",(e,t)=>{r.Validation.validate(),r.Validation.markFieldAsChanged(t),i.default(".module-docheader-bar .btn").removeClass("disabled").prop("disabled",!1)})}}})); \ No newline at end of file +define(["require","exports","TYPO3/CMS/Core/DocumentService","TYPO3/CMS/Backend/FormEngine","TYPO3/CMS/Core/Event/RegularEvent"],(function(e,n,r,t,i){"use strict";return class{constructor(n){r.ready().then(()=>{this.registerEventHandler(),e(["../../DateTimePicker"],e=>{e.initialize("#"+n)})})}registerEventHandler(){new i("formengine.dp.change",e=>{t.Validation.validate(),t.Validation.markFieldAsChanged(e.detail.element),document.querySelectorAll(".module-docheader-bar .btn").forEach(e=>{e.classList.remove("disabled"),e.disabled=!1})}).bindTo(document)}}})); \ No newline at end of file diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/InputLinkElement.js b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/InputLinkElement.js index 81cb3d171df8bc7853ff69677718b4b83a39a45c..268bd43578b1e7f3263aac75330a8c7d560ce448 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/InputLinkElement.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/InputLinkElement.js @@ -10,4 +10,4 @@ * * The TYPO3 project - inspiring people to share! */ -var __importDefault=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};define(["require","exports","jquery"],(function(e,t,i){"use strict";var l;i=__importDefault(i),function(e){e.toggleSelector=".t3js-form-field-inputlink-explanation-toggle",e.inputFieldSelector=".t3js-form-field-inputlink-input",e.explanationSelector=".t3js-form-field-inputlink-explanation",e.iconSelector=".t3js-form-field-inputlink-icon"}(l||(l={}));return class{constructor(e){this.element=null,this.container=null,this.toggleSelector=null,this.explanationField=null,this.icon=null,i.default(()=>{this.element=document.getElementById(e),this.container=this.element.closest(".t3js-form-field-inputlink"),this.toggleSelector=this.container.querySelector(l.toggleSelector),this.explanationField=this.container.querySelector(l.explanationSelector),this.icon=this.container.querySelector(l.iconSelector),this.toggleVisibility(""===this.explanationField.value),this.registerEventHandler()})}toggleVisibility(e){this.explanationField.classList.toggle("hidden",e),this.element.classList.toggle("hidden",!e);const t=this.container.querySelector(".form-control-clearable button.close");null!==t&&t.classList.toggle("hidden",!e)}registerEventHandler(){this.toggleSelector.addEventListener("click",e=>{e.preventDefault();const t=!this.explanationField.classList.contains("hidden");this.toggleVisibility(t)}),this.container.querySelector(l.inputFieldSelector).addEventListener("change",()=>{const e=!this.explanationField.classList.contains("hidden");e&&this.toggleVisibility(e),this.disableToggle(),this.clearIcon()})}disableToggle(){this.toggleSelector.classList.add("disabled"),this.toggleSelector.setAttribute("disabled","disabled")}clearIcon(){this.icon.innerHTML=""}}})); \ No newline at end of file +define(["require","exports","TYPO3/CMS/Core/DocumentService"],(function(e,t,i){"use strict";var l;!function(e){e.toggleSelector=".t3js-form-field-inputlink-explanation-toggle",e.inputFieldSelector=".t3js-form-field-inputlink-input",e.explanationSelector=".t3js-form-field-inputlink-explanation",e.iconSelector=".t3js-form-field-inputlink-icon"}(l||(l={}));return class{constructor(e){this.element=null,this.container=null,this.toggleSelector=null,this.explanationField=null,this.icon=null,i.ready().then(t=>{this.element=t.getElementById(e),this.container=this.element.closest(".t3js-form-field-inputlink"),this.toggleSelector=this.container.querySelector(l.toggleSelector),this.explanationField=this.container.querySelector(l.explanationSelector),this.icon=this.container.querySelector(l.iconSelector),this.toggleVisibility(""===this.explanationField.value),this.registerEventHandler()})}toggleVisibility(e){this.explanationField.classList.toggle("hidden",e),this.element.classList.toggle("hidden",!e);const t=this.container.querySelector(".form-control-clearable button.close");null!==t&&t.classList.toggle("hidden",!e)}registerEventHandler(){this.toggleSelector.addEventListener("click",e=>{e.preventDefault();const t=!this.explanationField.classList.contains("hidden");this.toggleVisibility(t)}),this.container.querySelector(l.inputFieldSelector).addEventListener("change",()=>{const e=!this.explanationField.classList.contains("hidden");e&&this.toggleVisibility(e),this.disableToggle(),this.clearIcon()})}disableToggle(){this.toggleSelector.classList.add("disabled"),this.toggleSelector.setAttribute("disabled","disabled")}clearIcon(){this.icon.innerHTML=""}}})); \ No newline at end of file diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/SelectCheckBoxElement.js b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/SelectCheckBoxElement.js index b15b885c825f70b68459352bb541826bbf50a693..1a0871052f62d6f1983d69700283c2cad2351d81 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/SelectCheckBoxElement.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/SelectCheckBoxElement.js @@ -10,4 +10,4 @@ * * The TYPO3 project - inspiring people to share! */ -var __importDefault=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};define(["require","exports","jquery","TYPO3/CMS/Backend/FormEngine"],(function(e,t,l,c){"use strict";var s;l=__importDefault(l),function(e){e.toggleAll=".t3js-toggle-checkboxes",e.singleItem=".t3js-checkbox",e.revertSelection=".t3js-revert-selection"}(s||(s={}));class i{constructor(e){this.checkBoxId="",this.$table=null,this.checkedBoxes=null,this.checkBoxId=e,l.default(()=>{this.$table=l.default("#"+e).closest("table"),this.checkedBoxes=this.$table.find(s.singleItem+":checked"),this.enableTriggerCheckBox(),this.registerEventHandler()})}static allCheckBoxesAreChecked(e){return e.length===e.filter(":checked").length}registerEventHandler(){this.$table.on("change",s.toggleAll,e=>{const t=l.default(e.currentTarget),h=this.$table.find(s.singleItem),n=!i.allCheckBoxesAreChecked(h);h.prop("checked",n),t.prop("checked",n),c.Validation.markFieldAsChanged(t)}).on("change",s.singleItem,()=>{this.setToggleAllState()}).on("click",s.revertSelection,()=>{this.$table.find(s.singleItem).each((e,t)=>{t.checked=this.checkedBoxes.index(t)>-1}),this.setToggleAllState()})}setToggleAllState(){const e=this.$table.find(s.singleItem),t=i.allCheckBoxesAreChecked(e);this.$table.find(s.toggleAll).prop("checked",t)}enableTriggerCheckBox(){const e=this.$table.find(s.singleItem),t=i.allCheckBoxesAreChecked(e);l.default("#"+this.checkBoxId).prop("checked",t)}}return i})); \ No newline at end of file +define(["require","exports","TYPO3/CMS/Core/DocumentService","TYPO3/CMS/Core/Event/RegularEvent"],(function(e,t,l,c){"use strict";var s;!function(e){e.toggleAll=".t3js-toggle-checkboxes",e.singleItem=".t3js-checkbox",e.revertSelection=".t3js-revert-selection"}(s||(s={}));class r{constructor(e){this.checkBoxId="",this.table=null,this.checkedBoxes=null,this.checkBoxId=e,l.ready().then(t=>{this.table=t.getElementById(e).closest("table"),this.checkedBoxes=this.table.querySelectorAll(s.singleItem+":checked"),this.enableTriggerCheckBox(),this.registerEventHandler()})}static allCheckBoxesAreChecked(e){const t=Array.from(e);return e.length===t.filter(e=>e.checked).length}registerEventHandler(){new c("change",(e,t)=>{const l=this.table.querySelectorAll(s.singleItem),c=!r.allCheckBoxesAreChecked(l);l.forEach(e=>{e.checked=c}),t.checked=c}).delegateTo(this.table,s.toggleAll),new c("change",this.setToggleAllState.bind(this)).delegateTo(this.table,s.singleItem),new c("click",()=>{const e=this.table.querySelectorAll(s.singleItem),t=Array.from(this.checkedBoxes);e.forEach(e=>{e.checked=t.includes(e)}),this.setToggleAllState()}).delegateTo(this.table,s.revertSelection)}setToggleAllState(){const e=this.table.querySelectorAll(s.singleItem);this.table.querySelector(s.toggleAll).checked=r.allCheckBoxesAreChecked(e)}enableTriggerCheckBox(){const e=this.table.querySelectorAll(s.singleItem);document.getElementById(this.checkBoxId).checked=r.allCheckBoxesAreChecked(e)}}return r})); \ No newline at end of file diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/SelectMultipleSideBySideElement.js b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/SelectMultipleSideBySideElement.js index 7d79407a75011cdc795d49b80a30ce2a0cebbfd0..b179d40ee7b9dc5bb2bd15f28a56ca2e0c678969 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/SelectMultipleSideBySideElement.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/SelectMultipleSideBySideElement.js @@ -10,4 +10,4 @@ * * The TYPO3 project - inspiring people to share! */ -var __importDefault=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};define(["require","exports","./AbstractSortableSelectItems","jquery","TYPO3/CMS/Backend/FormEngine","./Extra/SelectBoxFilter"],(function(e,t,l,n,r,s){"use strict";n=__importDefault(n);class i extends l.AbstractSortableSelectItems{constructor(e,t){super(),this.selectedOptionsElement=null,this.availableOptionsElement=null,n.default(()=>{this.selectedOptionsElement=document.getElementById(e),this.availableOptionsElement=document.getElementById(t),this.registerEventHandler()})}registerEventHandler(){this.registerSortableEventHandler(this.selectedOptionsElement),this.availableOptionsElement.addEventListener("click",e=>{const t=e.currentTarget,l=t.dataset.relatedfieldname;if(l){const e=t.dataset.exclusiveValues,s=t.querySelectorAll("option:checked");s.length>0&&s.forEach(t=>{r.setSelectOptionFromExternalSource(l,t.value,t.textContent,t.getAttribute("title"),e,n.default(t))})}}),new s(this.availableOptionsElement)}}return i})); \ No newline at end of file +define(["require","exports","./AbstractSortableSelectItems","TYPO3/CMS/Core/DocumentService","TYPO3/CMS/Backend/FormEngine","./Extra/SelectBoxFilter"],(function(e,t,l,n,s,r){"use strict";class i extends l.AbstractSortableSelectItems{constructor(e,t){super(),this.selectedOptionsElement=null,this.availableOptionsElement=null,n.ready().then(l=>{this.selectedOptionsElement=l.getElementById(e),this.availableOptionsElement=l.getElementById(t),this.registerEventHandler()})}registerEventHandler(){this.registerSortableEventHandler(this.selectedOptionsElement),this.availableOptionsElement.addEventListener("click",e=>{const t=e.currentTarget,l=t.dataset.relatedfieldname;if(l){const e=t.dataset.exclusiveValues,n=t.querySelectorAll("option:checked");n.length>0&&n.forEach(t=>{s.setSelectOptionFromExternalSource(l,t.value,t.textContent,t.getAttribute("title"),e,t)})}}),new r(this.availableOptionsElement)}}return i})); \ No newline at end of file diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/SelectSingleElement.js b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/SelectSingleElement.js index c9119ed0f94ca9f42150770c5bee1759cdb45477..94a1361f610c9f43fa8010caf0de5c3d51ce4ebe 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/SelectSingleElement.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/SelectSingleElement.js @@ -10,4 +10,4 @@ * * The TYPO3 project - inspiring people to share! */ -var __importDefault=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};define(["require","exports","jquery"],(function(e,t,s){"use strict";s=__importDefault(s);return new class{constructor(){this.initialize=(e,t)=>{let n=s.default(e),i=n.prev(".input-group-icon");t=t||{},n.on("change",e=>{let t=s.default(e.target);i.html(n.find(":selected").data("icon"));let o=t.closest(".t3js-formengine-field-item").find(".t3js-forms-select-single-icons");o.find(".item.active").removeClass("active"),o.find('[data-select-index="'+t.prop("selectedIndex")+'"]').closest(".item").addClass("active")}),"function"==typeof t.onChange&&n.on("change",t.onChange),"function"==typeof t.onFocus&&n.on("focus",t.onFocus),n.closest(".form-control-wrap").find(".t3js-forms-select-single-icons a").on("click",e=>{let t=s.default(e.target),i=t.closest("[data-select-index]");return t.closest(".t3js-forms-select-single-icons").find(".item.active").removeClass("active"),n.prop("selectedIndex",i.data("selectIndex")).trigger("change"),i.closest(".item").addClass("active"),!1})}}}})); \ No newline at end of file +define(["require","exports","TYPO3/CMS/Core/Event/RegularEvent"],(function(e,t,n){"use strict";return new class{constructor(){this.initialize=(e,t)=>{let s=document.querySelector(e);t=t||{},new n("change",e=>{const t=e.target,n=t.parentElement.querySelector(".input-group-icon");null!==n&&(n.innerHTML=t.options[t.selectedIndex].dataset.icon);const s=t.closest(".t3js-formengine-field-item").querySelector(".t3js-forms-select-single-icons");if(null!==s){const e=s.querySelector(".item.active");null!==e&&e.classList.remove("active");const n=s.querySelector('[data-select-index="'+t.selectedIndex+'"]');null!==n&&n.closest(".item").classList.add("active")}}).bindTo(s),"function"==typeof t.onChange&&new n("change",t.onChange).bindTo(s),"function"==typeof t.onFocus&&new n("focus",t.onFocus).bindTo(s),new n("click",(e,t)=>{const n=t.closest(".t3js-forms-select-single-icons").querySelector(".item.active");null!==n&&n.classList.remove("active"),s.selectedIndex=parseInt(t.dataset.selectIndex,10),s.dispatchEvent(new Event("change")),t.closest(".item").classList.add("active")}).delegateTo(s.closest(".form-control-wrap"),".t3js-forms-select-single-icons .item:not(.active) a")}}}})); \ No newline at end of file diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/SlugElement.js b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/SlugElement.js index e0ae323bf085522917a212e0e33f17968f47e0a3..731c26a223681d3e139e21dceac62c10a18ba1b3 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/SlugElement.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/SlugElement.js @@ -10,4 +10,4 @@ * * The TYPO3 project - inspiring people to share! */ -var __importDefault=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};define(["require","exports","jquery","TYPO3/CMS/Core/Ajax/AjaxRequest"],(function(e,t,l,i){"use strict";var s,n;l=__importDefault(l),function(e){e.toggleButton=".t3js-form-field-slug-toggle",e.recreateButton=".t3js-form-field-slug-recreate",e.inputField=".t3js-form-field-slug-input",e.readOnlyField=".t3js-form-field-slug-readonly",e.hiddenField=".t3js-form-field-slug-hidden"}(s||(s={})),function(e){e.AUTO="auto",e.RECREATE="recreate",e.MANUAL="manual"}(n||(n={}));return class{constructor(e,t){this.options=null,this.$fullElement=null,this.manuallyChanged=!1,this.$readOnlyField=null,this.$inputField=null,this.$hiddenField=null,this.request=null,this.fieldsToListenOn={},this.options=t,this.fieldsToListenOn=this.options.listenerFieldNames||{},l.default(()=>{this.$fullElement=l.default(e),this.$inputField=this.$fullElement.find(s.inputField),this.$readOnlyField=this.$fullElement.find(s.readOnlyField),this.$hiddenField=this.$fullElement.find(s.hiddenField),this.registerEvents()})}registerEvents(){const e=Object.keys(this.getAvailableFieldsForProposalGeneration()).map(e=>this.fieldsToListenOn[e]);e.length>0?("new"===this.options.command&&l.default(this.$fullElement).on("keyup",e.join(","),()=>{this.manuallyChanged||this.sendSlugProposal(n.AUTO)}),l.default(this.$fullElement).on("click",s.recreateButton,e=>{e.preventDefault(),this.$readOnlyField.hasClass("hidden")&&(this.$readOnlyField.toggleClass("hidden",!1),this.$inputField.toggleClass("hidden",!0)),this.sendSlugProposal(n.RECREATE)})):l.default(this.$fullElement).find(s.recreateButton).addClass("disabled").prop("disabled",!0),l.default(this.$inputField).on("keyup",()=>{this.manuallyChanged=!0,this.sendSlugProposal(n.MANUAL)}),l.default(this.$fullElement).on("click",s.toggleButton,e=>{e.preventDefault();const t=this.$readOnlyField.hasClass("hidden");this.$readOnlyField.toggleClass("hidden",!t),this.$inputField.toggleClass("hidden",t),t?(this.$inputField.val()!==this.$readOnlyField.val()?this.$readOnlyField.val(this.$inputField.val()):(this.manuallyChanged=!1,this.$fullElement.find(".t3js-form-proposal-accepted").addClass("hidden"),this.$fullElement.find(".t3js-form-proposal-different").addClass("hidden")),this.$hiddenField.val(this.$readOnlyField.val())):this.$hiddenField.val(this.$inputField.val())})}sendSlugProposal(e){const t={};e===n.AUTO||e===n.RECREATE?(l.default.each(this.getAvailableFieldsForProposalGeneration(),(e,i)=>{t[e]=l.default('[data-formengine-input-name="'+i+'"]').val()}),!0===this.options.includeUidInValues&&(t.uid=this.options.recordId.toString())):t.manual=this.$inputField.val(),this.request instanceof i&&this.request.abort(),this.request=new i(TYPO3.settings.ajaxUrls.record_slug_suggest),this.request.post({values:t,mode:e,tableName:this.options.tableName,pageId:this.options.pageId,parentPageId:this.options.parentPageId,recordId:this.options.recordId,language:this.options.language,fieldName:this.options.fieldName,command:this.options.command,signature:this.options.signature}).then(async t=>{const l=await t.resolve(),i="/"+l.proposal.replace(/^\//,"");l.hasConflicts?(this.$fullElement.find(".t3js-form-proposal-accepted").addClass("hidden"),this.$fullElement.find(".t3js-form-proposal-different").removeClass("hidden").find("span").text(i)):(this.$fullElement.find(".t3js-form-proposal-accepted").removeClass("hidden").find("span").text(i),this.$fullElement.find(".t3js-form-proposal-different").addClass("hidden"));this.$hiddenField.val()!==l.proposal&&this.$fullElement.find("input").trigger("change"),e===n.AUTO||e===n.RECREATE?(this.$readOnlyField.val(l.proposal),this.$hiddenField.val(l.proposal),this.$inputField.val(l.proposal)):this.$hiddenField.val(l.proposal)}).finally(()=>{this.request=null})}getAvailableFieldsForProposalGeneration(){const e={};return l.default.each(this.fieldsToListenOn,(t,i)=>{l.default('[data-formengine-input-name="'+i+'"]').length>0&&(e[t]=i)}),e}}})); \ No newline at end of file +define(["require","exports","TYPO3/CMS/Core/Ajax/AjaxRequest","TYPO3/CMS/Core/DocumentService","TYPO3/CMS/Core/Event/DebounceEvent","TYPO3/CMS/Core/Event/RegularEvent"],(function(e,t,i,l,s,n){"use strict";var o,a;!function(e){e.toggleButton=".t3js-form-field-slug-toggle",e.recreateButton=".t3js-form-field-slug-recreate",e.inputField=".t3js-form-field-slug-input",e.readOnlyField=".t3js-form-field-slug-readonly",e.hiddenField=".t3js-form-field-slug-hidden"}(o||(o={})),function(e){e.AUTO="auto",e.RECREATE="recreate",e.MANUAL="manual"}(a||(a={}));return class{constructor(e,t){this.options=null,this.fullElement=null,this.manuallyChanged=!1,this.readOnlyField=null,this.inputField=null,this.hiddenField=null,this.request=null,this.fieldsToListenOn={},this.options=t,this.fieldsToListenOn=this.options.listenerFieldNames||{},l.ready().then(t=>{this.fullElement=t.querySelector(e),this.inputField=this.fullElement.querySelector(o.inputField),this.readOnlyField=this.fullElement.querySelector(o.readOnlyField),this.hiddenField=this.fullElement.querySelector(o.hiddenField),this.registerEvents()})}registerEvents(){const e=Object.values(this.getAvailableFieldsForProposalGeneration()).map(e=>`[data-formengine-input-name="${e}"]`),t=this.fullElement.querySelector(o.recreateButton);e.length>0?("new"===this.options.command&&new s("input",()=>{this.manuallyChanged||this.sendSlugProposal(a.AUTO)}).delegateTo(document,e.join(",")),new n("click",e=>{e.preventDefault(),this.readOnlyField.classList.contains("hidden")&&(this.readOnlyField.classList.toggle("hidden",!1),this.inputField.classList.toggle("hidden",!0)),this.sendSlugProposal(a.RECREATE)}).bindTo(t)):(t.classList.add("disabled"),t.disabled=!0),new s("input",()=>{this.manuallyChanged=!0,this.sendSlugProposal(a.MANUAL)}).bindTo(this.inputField);const i=this.fullElement.querySelector(o.toggleButton);new n("click",e=>{e.preventDefault();const t=this.readOnlyField.classList.contains("hidden");this.readOnlyField.classList.toggle("hidden",!t),this.inputField.classList.toggle("hidden",t),t?(this.inputField.value!==this.readOnlyField.value?this.readOnlyField.value=this.inputField.value:(this.manuallyChanged=!1,this.fullElement.querySelector(".t3js-form-proposal-accepted").classList.add("hidden"),this.fullElement.querySelector(".t3js-form-proposal-different").classList.add("hidden")),this.hiddenField.value=this.readOnlyField.value):this.hiddenField.value=this.inputField.value}).bindTo(i)}sendSlugProposal(e){const t={};if(e===a.AUTO||e===a.RECREATE){for(const[e,i]of Object.entries(this.getAvailableFieldsForProposalGeneration()))t[e]=document.querySelector('[data-formengine-input-name="'+i+'"]').value;!0===this.options.includeUidInValues&&(t.uid=this.options.recordId.toString())}else t.manual=this.inputField.value;this.request instanceof i&&this.request.abort(),this.request=new i(TYPO3.settings.ajaxUrls.record_slug_suggest),this.request.post({values:t,mode:e,tableName:this.options.tableName,pageId:this.options.pageId,parentPageId:this.options.parentPageId,recordId:this.options.recordId,language:this.options.language,fieldName:this.options.fieldName,command:this.options.command,signature:this.options.signature}).then(async t=>{const i=await t.resolve(),l="/"+i.proposal.replace(/^\//,""),s=this.fullElement.querySelector(".t3js-form-proposal-accepted"),n=this.fullElement.querySelector(".t3js-form-proposal-different");s.classList.toggle("hidden",i.hasConflicts),n.classList.toggle("hidden",!i.hasConflicts),(i.hasConflicts?n:s).querySelector("span").innerText=l;this.hiddenField.value!==i.proposal&&this.fullElement.querySelector("input").dispatchEvent(new Event("change")),e===a.AUTO||e===a.RECREATE?(this.readOnlyField.value=i.proposal,this.hiddenField.value=i.proposal,this.inputField.value=i.proposal):this.hiddenField.value=i.proposal}).finally(()=>{this.request=null})}getAvailableFieldsForProposalGeneration(){const e={};for(const[t,i]of Object.entries(this.fieldsToListenOn)){null!==document.querySelector('[data-formengine-input-name="'+i+'"]')&&(e[t]=i)}return e}}})); \ No newline at end of file diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/FieldWizard/LocalizationStateSelector.js b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/FieldWizard/LocalizationStateSelector.js index 475b87f66a38ab0942dc9bb26278210f8e61feb8..715b53f6a752856dfa0253873cd303beb293b588 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/FieldWizard/LocalizationStateSelector.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/FieldWizard/LocalizationStateSelector.js @@ -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"],(function(t,a,e){"use strict";var n;e=__importDefault(e),function(t){t.CUSTOM="custom"}(n||(n={}));return class{constructor(t){e.default(()=>{this.registerEventHandler(t)})}registerEventHandler(t){e.default(document).on("change",'.t3js-l10n-state-container input[type="radio"][name="'+t+'"]',t=>{const a=e.default(t.currentTarget),r=a.closest(".t3js-formengine-field-item").find("[data-formengine-input-name]");if(0===r.length)return;const l=r.data("last-l10n-state")||!1,i=a.val();l&&i===l||(i===n.CUSTOM?(l&&a.attr("data-original-language-value",r.val()),r.removeAttr("disabled")):(l===n.CUSTOM&&a.closest(".t3js-l10n-state-container").find(".t3js-l10n-state-custom").attr("data-original-language-value",r.val()),r.attr("disabled","disabled")),r.val(a.attr("data-original-language-value")).trigger("change"),r.data("last-l10n-state",a.val()))})}}})); \ No newline at end of file +define(["require","exports","TYPO3/CMS/Core/DocumentService","TYPO3/CMS/Core/Event/RegularEvent"],(function(e,t,a,n){"use strict";var r;!function(e){e.CUSTOM="custom"}(r||(r={}));return class{constructor(e){a.ready().then(()=>{this.registerEventHandler(e)})}registerEventHandler(e){new n("change",e=>{var t;const a=e.target,n=null===(t=a.closest(".t3js-formengine-field-item"))||void 0===t?void 0:t.querySelector("[data-formengine-input-name]");if(!n)return;const s=n.dataset.lastL10nState||!1,i=a.value;s&&i===s||(i===r.CUSTOM?(s&&(a.dataset.originalLanguageValue=n.value),n.disabled=!1):(s===r.CUSTOM&&(a.closest(".t3js-l10n-state-container").querySelector(".t3js-l10n-state-custom").dataset.originalLanguageValue=n.value),n.disabled=!0),n.value=a.dataset.originalLanguageValue,n.dispatchEvent(new Event("change")),n.dataset.lastL10nState=a.value)}).delegateTo(document,'.t3js-l10n-state-container input[type="radio"][name="'+e+'"]')}}})); \ No newline at end of file diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/InlineRelation/AjaxDispatcher.js b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/InlineRelation/AjaxDispatcher.js index 196a98e680fd6ac799c0dc73a03b1e2ad5484787..a2924f46fecae1cd0621e5842ef34ac5219611a0 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/InlineRelation/AjaxDispatcher.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/InlineRelation/AjaxDispatcher.js @@ -10,4 +10,4 @@ * * The TYPO3 project - inspiring people to share! */ -var __importDefault=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};define(["require","exports","jquery","TYPO3/CMS/Core/Ajax/AjaxRequest","../../Notification"],(function(require,exports,jquery_1,AjaxRequest,Notification){"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.AjaxDispatcher=void 0,jquery_1=__importDefault(jquery_1);class AjaxDispatcher{constructor(e){this.objectGroup=null,this.objectGroup=e}newRequest(e){return new AjaxRequest(e)}getEndpoint(e){if(void 0!==TYPO3.settings.ajaxUrls[e])return TYPO3.settings.ajaxUrls[e];throw'Undefined endpoint for route "'+e+'"'}send(e,t){const s=e.post(this.createRequestBody(t)).then(async e=>this.processResponse(await e.resolve()));return s.catch(e=>{Notification.error("Error "+e.message)}),s}createRequestBody(e){const t={};for(let s=0;s<e.length;s++)t["ajax["+s+"]"]=e[s];return t["ajax[context]"]=JSON.stringify(this.getContext()),t}getContext(){let e;return void 0!==TYPO3.settings.FormEngineInline.config[this.objectGroup]&&void 0!==TYPO3.settings.FormEngineInline.config[this.objectGroup].context&&(e=TYPO3.settings.FormEngineInline.config[this.objectGroup].context),e}processResponse(json){if(json.hasErrors&&jquery_1.default.each(json.messages,(e,t)=>{Notification.error(t.title,t.message)}),json.stylesheetFiles&&jquery_1.default.each(json.stylesheetFiles,(e,t)=>{if(!t)return;const s=document.createElement("link");s.rel="stylesheet",s.type="text/css",s.href=t,document.querySelector("head").appendChild(s),delete json.stylesheetFiles[e]}),"object"==typeof json.inlineData&&(TYPO3.settings.FormEngineInline=jquery_1.default.extend(!0,TYPO3.settings.FormEngineInline,json.inlineData)),"object"==typeof json.requireJsModules)for(let e of json.requireJsModules)new Function(e)();return json.scriptCall&&json.scriptCall.length>0&&jquery_1.default.each(json.scriptCall,(index,value)=>{eval(value)}),json}}exports.AjaxDispatcher=AjaxDispatcher})); \ No newline at end of file +define(["require","exports","TYPO3/CMS/Core/Ajax/AjaxRequest","../../Notification","../../Utility"],(function(require,exports,AjaxRequest,Notification,Utility){"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.AjaxDispatcher=void 0;class AjaxDispatcher{constructor(e){this.objectGroup=null,this.objectGroup=e}newRequest(e){return new AjaxRequest(e)}getEndpoint(e){if(void 0!==TYPO3.settings.ajaxUrls[e])return TYPO3.settings.ajaxUrls[e];throw'Undefined endpoint for route "'+e+'"'}send(e,t){const s=e.post(this.createRequestBody(t)).then(async e=>this.processResponse(await e.resolve()));return s.catch(e=>{Notification.error("Error "+e.message)}),s}createRequestBody(e){const t={};for(let s=0;s<e.length;s++)t["ajax["+s+"]"]=e[s];return t["ajax[context]"]=JSON.stringify(this.getContext()),t}getContext(){let e;return void 0!==TYPO3.settings.FormEngineInline.config[this.objectGroup]&&void 0!==TYPO3.settings.FormEngineInline.config[this.objectGroup].context&&(e=TYPO3.settings.FormEngineInline.config[this.objectGroup].context),e}processResponse(json){if(json.hasErrors)for(const e of json.messages)Notification.error(e.title,e.message);if(json.stylesheetFiles)for(const[e,t]of json.stylesheetFiles.entries()){if(!t)break;const s=document.createElement("link");s.rel="stylesheet",s.type="text/css",s.href=t,document.querySelector("head").appendChild(s),delete json.stylesheetFiles[e]}if("object"==typeof json.inlineData&&(TYPO3.settings.FormEngineInline=Utility.mergeDeep(TYPO3.settings.FormEngineInline,json.inlineData)),"object"==typeof json.requireJsModules)for(let e of json.requireJsModules)new Function(e)();if(json.scriptCall&&json.scriptCall.length>0)for(const scriptCall of json.scriptCall)eval(scriptCall);return json}}exports.AjaxDispatcher=AjaxDispatcher})); \ No newline at end of file diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/Utility.js b/typo3/sysext/backend/Resources/Public/JavaScript/Utility.js index fb7375e6b24ee991fddd39c402eab0c43b699dfa..a8fb0a23aa5f09bf0b0c866fa71bfd0ab75ca4c2 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/Utility.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/Utility.js @@ -10,4 +10,4 @@ * * The TYPO3 project - inspiring people to share! */ -define(["require","exports"],(function(t,e){"use strict";return class{static trimExplode(t,e){return e.split(t).map(t=>t.trim()).filter(t=>""!==t)}static intExplode(t,e,r=!1){return e.split(t).map(t=>parseInt(t,10)).filter(t=>!isNaN(t)||r&&0===t)}static isNumber(t){return!isNaN(parseFloat(t.toString()))&&isFinite(t)}static getParameterFromUrl(t,e){if("function"!=typeof t.split)return"";const r=t.split("?");let i="";if(r.length>=2){const t=r.join("?"),n=encodeURIComponent(e)+"=",s=t.split(/[&;]/g);for(let t=s.length;t-- >0;)if(-1!==s[t].lastIndexOf(n,0)){i=s[t].split("=")[1];break}}return i}static updateQueryStringParameter(t,e,r){const i=new RegExp("([?&])"+e+"=.*?(&|$)","i"),n=t.includes("?")?"&":"?";return t.match(i)?t.replace(i,"$1"+e+"="+r+"$2"):t+n+e+"="+r}static convertFormToObject(t){const e={};return t.querySelectorAll("input, select, textarea").forEach(t=>{const r=t.name,i=t.value;r&&(t instanceof HTMLInputElement&&"checkbox"==t.type?(void 0===e[r]&&(e[r]=[]),t.checked&&e[r].push(i)):e[r]=i)}),e}}})); \ No newline at end of file +define(["require","exports"],(function(t,e){"use strict";class r{static trimExplode(t,e){return e.split(t).map(t=>t.trim()).filter(t=>""!==t)}static intExplode(t,e,r=!1){return e.split(t).map(t=>parseInt(t,10)).filter(t=>!isNaN(t)||r&&0===t)}static isNumber(t){return!isNaN(parseFloat(t.toString()))&&isFinite(t)}static getParameterFromUrl(t,e){if("function"!=typeof t.split)return"";const r=t.split("?");let n="";if(r.length>=2){const t=r.join("?"),i=encodeURIComponent(e)+"=",s=t.split(/[&;]/g);for(let t=s.length;t-- >0;)if(-1!==s[t].lastIndexOf(i,0)){n=s[t].split("=")[1];break}}return n}static updateQueryStringParameter(t,e,r){const n=new RegExp("([?&])"+e+"=.*?(&|$)","i"),i=t.includes("?")?"&":"?";return t.match(n)?t.replace(n,"$1"+e+"="+r+"$2"):t+i+e+"="+r}static convertFormToObject(t){const e={};return t.querySelectorAll("input, select, textarea").forEach(t=>{const r=t.name,n=t.value;r&&(t instanceof HTMLInputElement&&"checkbox"==t.type?(void 0===e[r]&&(e[r]=[]),t.checked&&e[r].push(n)):e[r]=n)}),e}static mergeDeep(...t){const e=t=>t&&"object"==typeof t;return t.reduce((t,n)=>(Object.keys(n).forEach(i=>{const s=t[i],c=n[i];Array.isArray(s)&&Array.isArray(c)?t[i]=s.concat(...c):e(s)&&e(c)?t[i]=r.mergeDeep(s,c):t[i]=c}),t),{})}}return r})); \ No newline at end of file diff --git a/typo3/sysext/core/Documentation/Changelog/master/Deprecation-91911-OptionElOfTypeJQueryInFormEnginesetSelectOptionFromExternalSource.rst b/typo3/sysext/core/Documentation/Changelog/master/Deprecation-91911-OptionElOfTypeJQueryInFormEnginesetSelectOptionFromExternalSource.rst new file mode 100644 index 0000000000000000000000000000000000000000..76eec096a4928b8eca4151373cb9679c20c13826 --- /dev/null +++ b/typo3/sysext/core/Documentation/Changelog/master/Deprecation-91911-OptionElOfTypeJQueryInFormEnginesetSelectOptionFromExternalSource.rst @@ -0,0 +1,40 @@ +.. include:: ../../Includes.txt + +============================================================================================= +Deprecation: #91911 - optionEl of type jQuery in FormEngine.setSelectOptionFromExternalSource +============================================================================================= + +See :issue:`91911` + +Description +=========== + +The 6th argument :js:`optionEl` of the method +:js:`FormEngine.setSelectOptionFromExternalSource()` now accepts objects of type +`HTMLOptionElement`. + +In the same run, passing a jQuery object has been marked as deprecated. + + +Impact +====== + +jQuery objects automatically get converted to their native HTMLElement object. +Calling the method with passing a jQuery object will log a deprecation warning +to the browser's console. + + +Affected Installations +====================== + +All installations passing a jQuery object as :js:`optionEl` to +:js:`FormEngine.setSelectOptionFromExternalSource()` are affected. + + +Migration +========= + +Pass a native HTMLOptionElement to +:js:`FormEngine.setSelectOptionFromExternalSource()`. + +.. index:: Backend, JavaScript, NotScanned, ext:backend diff --git a/typo3/sysext/rte_ckeditor/Classes/Form/Element/RichTextElement.php b/typo3/sysext/rte_ckeditor/Classes/Form/Element/RichTextElement.php index c09a2849e26d0a54963dac854773bcd3f3ee94af..fdb65f08a6c4c2a0cdeea96ab0e53a5f5102e0ee 100644 --- a/typo3/sysext/rte_ckeditor/Classes/Form/Element/RichTextElement.php +++ b/typo3/sysext/rte_ckeditor/Classes/Form/Element/RichTextElement.php @@ -265,7 +265,7 @@ class RichTextElement extends AbstractFormElement }); } }); - $(document).on(\'inline:sorting-changed\', function() { + document.addEventListener(\'inline:sorting-changed\', function() { CKEDITOR.instances["' . $fieldId . '"].destroy(); CKEDITOR.replace("' . $fieldId . '", ' . $jsonConfiguration . '); });