diff --git a/Build/Sources/TypeScript/form/backend/form-editor/inspector-component.ts b/Build/Sources/TypeScript/form/backend/form-editor/inspector-component.ts new file mode 100644 index 0000000000000000000000000000000000000000..97e0a4edc760a6bc92a5135da2174d6a7105db48 --- /dev/null +++ b/Build/Sources/TypeScript/form/backend/form-editor/inspector-component.ts @@ -0,0 +1,2518 @@ +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +/** + * Module: @typo3/form/backend/form-editor/inspector-component + */ + +import $ from 'jquery'; +import * as Helper from '@typo3/form/backend/form-editor/helper'; +import Icons from '@typo3/backend/icons'; +import Modal from '@typo3/backend/modal'; +import { MessageUtility } from '@typo3/backend/utility/message-utility'; +import Sortable from 'sortablejs'; + +import type { + FormEditor, + ViewModel, +} from '@typo3/form/backend/form-editor'; +import type { + Utility, + EditorConfiguration, + FormEditorDefinitions, + FormElement, + FormElementDefinition, + PublisherSubscriber, +} from '@typo3/form/backend/form-editor/core'; +import type { + Configuration as HelperConfiguration, +} from '@typo3/form/backend/form-editor/helper'; + +interface Configuration extends Partial<HelperConfiguration> { + isSortable: boolean, +} + +type PropertyData = Array<{code: string, message: string}>; + +const defaultConfiguration: Configuration = { + domElementClassNames: { + buttonFormElementRemove: 't3-form-remove-element-button', + collectionElement: 't3-form-collection-element', + finisherEditorPrefix: 't3-form-inspector-finishers-editor-', + inspectorEditor: 'form-editor', + inspectorInputGroup: 'input-group', + validatorEditorPrefix: 't3-form-inspector-validators-editor-' + }, + domElementDataAttributeNames: { + contentElementSelectorTarget: 'data-insert-target', + finisher: 'data-finisher-identifier', + validator: 'data-validator-identifier', + randomId: 'data-random-id', + randomIdTarget: 'data-random-id-attribute', + randomIdIndex: 'data-random-id-number', + maximumFileSize: 'data-maximumFileSize' + }, + domElementDataAttributeValues: { + collapse: 'actions-view-table-expand', + editorControlsInputGroup: 'inspectorEditorControlsGroup', + editorWrapper: 'editorWrapper', + editorControlsWrapper: 'inspectorEditorControlsWrapper', + formElementHeaderEditor: 'inspectorFormElementHeaderEditor', + formElementSelectorControlsWrapper: 'inspectorEditorFormElementSelectorControlsWrapper', + formElementSelectorSplitButtonContainer: 'inspectorEditorFormElementSelectorSplitButtonContainer', + formElementSelectorSplitButtonListContainer: 'inspectorEditorFormElementSelectorSplitButtonListContainer', + iconNotAvailable: 'actions-close', + inspector: 'inspector', + 'Inspector-CheckboxEditor': 'Inspector-CheckboxEditor', + 'Inspector-CollectionElementHeaderEditor': 'Inspector-CollectionElementHeaderEditor', + 'Inspector-FinishersEditor': 'Inspector-FinishersEditor', + 'Inspector-FormElementHeaderEditor': 'Inspector-FormElementHeaderEditor', + 'Inspector-PropertyGridEditor': 'Inspector-PropertyGridEditor', + 'Inspector-RemoveElementEditor': 'Inspector-RemoveElementEditor', + 'Inspector-RequiredValidatorEditor': 'Inspector-RequiredValidatorEditor', + 'Inspector-SingleSelectEditor': 'Inspector-SingleSelectEditor', + 'Inspector-MultiSelectEditor': 'Inspector-MultiSelectEditor', + 'Inspector-GridColumnViewPortConfigurationEditor': 'Inspector-GridColumnViewPortConfigurationEditor', + 'Inspector-TextareaEditor': 'Inspector-TextareaEditor', + 'Inspector-TextEditor': 'Inspector-TextEditor', + 'Inspector-Typo3WinBrowserEditor': 'Inspector-Typo3WinBrowserEditor', + 'Inspector-ValidatorsEditor': 'Inspector-ValidatorsEditor', + 'Inspector-ValidationErrorMessageEditor': 'Inspector-ValidationErrorMessageEditor', + + inspectorFinishers: 'inspectorFinishers', + inspectorValidators: 'inspectorValidators', + propertyGridEditorHeaderRow: 'headerRow', + propertyGridEditorAddRow: 'addRow', + propertyGridEditorAddRowItem: 'addRowItem', + propertyGridEditorContainer: 'propertyGridContainer', + propertyGridEditorDeleteRow: 'deleteRow', + propertyGridEditorLabel: 'label', + propertyGridEditorRowItem: 'rowItem', + propertyGridEditorColumn: 'column', + propertyGridEditorSelectValue: 'selectValue', + propertyGridEditorSortRow: 'sortRow', + propertyGridEditorValue: 'value', + viewportButton: 'viewportButton' + }, + domElementIdNames: { + finisherPrefix: 't3-form-inspector-finishers-', + validatorPrefix: 't3-form-inspector-validators-' + }, + isSortable: true +}; + +let configuration: Configuration = null; + +let formEditorApp: FormEditor = null; + +function getFormEditorApp(): FormEditor { + return formEditorApp; +} + +function getViewModel(): ViewModel { + return getFormEditorApp().getViewModel(); +} + +function getHelper(_configuration?: HelperConfiguration): typeof Helper { + if (getUtility().isUndefinedOrNull(_configuration)) { + return Helper.setConfiguration(configuration); + } + return Helper.setConfiguration(_configuration); +} + +function getUtility(): Utility { + return getFormEditorApp().getUtility(); +} + +function assert(test: boolean|(() => boolean), message: string, messageCode: number): void { + return getFormEditorApp().assert(test, message, messageCode); +} + +function getRootFormElement(): FormElement { + return getFormEditorApp().getRootFormElement(); +} + +function getCurrentlySelectedFormElement(): FormElement { + return getFormEditorApp().getCurrentlySelectedFormElement(); +} + +function getPublisherSubscriber(): PublisherSubscriber { + return getFormEditorApp().getPublisherSubscriber(); +} + +function getFormElementDefinition<T extends keyof FormElementDefinition>( + formElement: FormElement | string, + formElementDefinitionKey?: T +): T extends keyof FormElementDefinition ? FormElementDefinition[T] : FormElementDefinition { + return getFormEditorApp().getFormElementDefinition(formElement, formElementDefinitionKey); +} + +/** + * @publish view/inspector/editor/insert/perform + */ +function renderEditorDispatcher( + editorConfiguration: EditorConfiguration, + editorHtml: HTMLElement | JQuery, + collectionElementIdentifier?: string, + collectionName?: keyof FormEditorDefinitions +): void { + switch (editorConfiguration.templateName) { + case 'Inspector-FormElementHeaderEditor': + renderFormElementHeaderEditor( + editorConfiguration, + editorHtml + ); + break; + case 'Inspector-CollectionElementHeaderEditor': + renderCollectionElementHeaderEditor( + editorConfiguration, + editorHtml, + collectionElementIdentifier, + collectionName + ); + break; + case 'Inspector-MaximumFileSizeEditor': + renderFileMaxSizeEditor( + editorConfiguration, + editorHtml + ); + break; + case 'Inspector-TextEditor': + renderTextEditor( + editorConfiguration, + editorHtml, + collectionElementIdentifier, + collectionName + ); + break; + case 'Inspector-FinishersEditor': + renderCollectionElementSelectionEditor( + 'finishers', + editorConfiguration, + editorHtml + ); + break; + case 'Inspector-ValidatorsEditor': + renderCollectionElementSelectionEditor( + 'validators', + editorConfiguration, + editorHtml + ); + break; + case 'Inspector-ValidationErrorMessageEditor': + renderValidationErrorMessageEditor( + editorConfiguration, + editorHtml + ); + break; + case 'Inspector-RemoveElementEditor': + renderRemoveElementEditor( + editorConfiguration, + editorHtml, + collectionElementIdentifier, + collectionName + ); + break; + case 'Inspector-RequiredValidatorEditor': + renderRequiredValidatorEditor( + editorConfiguration, + editorHtml, + collectionElementIdentifier, + collectionName + ); + break; + case 'Inspector-CheckboxEditor': + renderCheckboxEditor( + editorConfiguration, + editorHtml, + collectionElementIdentifier, + collectionName + ); + break; + case 'Inspector-CountrySelectEditor': + renderCountrySelectEditor( + editorConfiguration, + editorHtml, + collectionElementIdentifier, + collectionName + ); + break; + case 'Inspector-SingleSelectEditor': + renderSingleSelectEditor( + editorConfiguration, + editorHtml, + collectionElementIdentifier, + collectionName + ); + break; + case 'Inspector-MultiSelectEditor': + renderMultiSelectEditor( + editorConfiguration, + editorHtml, + collectionElementIdentifier, + collectionName + ); + break; + case 'Inspector-GridColumnViewPortConfigurationEditor': + renderGridColumnViewPortConfigurationEditor( + editorConfiguration, + editorHtml + ); + break; + case 'Inspector-PropertyGridEditor': + renderPropertyGridEditor( + editorConfiguration, + editorHtml, + collectionElementIdentifier, + collectionName + ); + break; + case 'Inspector-TextareaEditor': + renderTextareaEditor( + editorConfiguration, + editorHtml, + collectionElementIdentifier, + collectionName + ); + break; + case 'Inspector-Typo3WinBrowserEditor': + renderTypo3WinBrowserEditor( + editorConfiguration, + editorHtml, + collectionElementIdentifier, + collectionName + ); + break; + default: + break; + } + getPublisherSubscriber().publish('view/inspector/editor/insert/perform', [ + editorConfiguration, editorHtml, collectionElementIdentifier, collectionName + ]); +} + +/** + * opens a popup window with the element browser + */ +function openTypo3WinBrowser(mode: string, params: string): void { + Modal.advanced({ + type: Modal.types.iframe, + content: TYPO3.settings.FormEditor.typo3WinBrowserUrl + '&mode=' + mode + '&bparams=' + params, + size: Modal.sizes.large + }); +} + +/** + * Listens on messages sent by ElementBrowser + */ +function listenOnElementBrowser(): void { + window.addEventListener('message', function (e) { + if (!MessageUtility.verifyOrigin(e.origin)) { + throw 'Denied message sent by ' + e.origin; + } + + if (e.data.actionName === 'typo3:elementBrowser:elementAdded') { + if (typeof e.data.fieldName === 'undefined') { + throw 'fieldName not defined in message'; + } + + if (typeof e.data.value === 'undefined') { + throw 'value not defined in message'; + } + + const result = e.data.value.split('_'); + $(getHelper().getDomElementDataAttribute('contentElementSelectorTarget', 'bracesWithKeyValue', [e.data.fieldName])) + .val(result.pop()) + .trigger('paste'); + } + }); +} + +function getCollectionElementClass( + collectionName: keyof FormEditorDefinitions, + collectionElementIdentifier: string +): string { + if (collectionName === 'finishers') { + return getHelper() + .getDomElementClassName('finisherEditorPrefix') + collectionElementIdentifier; + } else { + return getHelper() + .getDomElementClassName('validatorEditorPrefix') + collectionElementIdentifier; + } +} + +function getCollectionElementId( + collectionName: keyof FormEditorDefinitions, + collectionElementIdentifier: string, + asSelector?: boolean +): string { + if (collectionName === 'finishers') { + return getHelper() + .getDomElementIdName('finisherPrefix', asSelector) + collectionElementIdentifier; + } else { + return getHelper() + .getDomElementIdName('validatorPrefix', asSelector) + collectionElementIdentifier; + } +} + +function addSortableCollectionElementsEvents( + sortableDomElement: JQuery, + collectionName: keyof FormEditorDefinitions, +): void { + sortableDomElement.addClass(getHelper().getDomElementClassName('sortable')); + new Sortable(sortableDomElement.get(0), { + draggable: getHelper().getDomElementClassName('collectionElement', true), + filter: 'input,textarea,select', + preventOnFilter: false, + animation: 200, + fallbackTolerance: 200, + swapThreshold: 0.6, + dragClass: 'form-sortable-drag', + ghostClass: 'form-sortable-ghost', + onEnd: function (e) { + let dataAttributeName; + + if (collectionName === 'finishers') { + dataAttributeName = getHelper().getDomElementDataAttribute('finisher'); + } else { + dataAttributeName = getHelper().getDomElementDataAttribute('validator'); + } + + const movedCollectionElementIdentifier = $(e.item).attr(dataAttributeName); + const previousCollectionElementIdentifier = $(e.item) + .prevAll(getHelper().getDomElementClassName('collectionElement', true)) + .first() + .attr(dataAttributeName); + const nextCollectionElementIdentifier = $(e.item) + .nextAll(getHelper().getDomElementClassName('collectionElement', true)) + .first() + .attr(dataAttributeName); + + getPublisherSubscriber().publish('view/inspector/collectionElements/dnd/update', [ + movedCollectionElementIdentifier, + previousCollectionElementIdentifier, + nextCollectionElementIdentifier, + collectionName + ]); + } + }); +} + +function setPropertyGridData( + editorHtml: HTMLElement | JQuery, + multiSelection: boolean, + propertyPath: string, + propertyPathPrefix: string +): void { + let value; + + if (multiSelection) { + const defaultValue: number[] = []; + + $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorContainer') + ' ' + + getHelper().getDomElementDataIdentifierSelector('propertyGridEditorSelectValue') + ':checked', + $(editorHtml) + ).each(function(this: HTMLElement) { + value = $(this) + .closest(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem')) + .find(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorValue')) + .val(); + + if (getUtility().canBeInterpretedAsInteger(value)) { + value = parseInt(value, 10); + } + + defaultValue.push(value); + }); + getCurrentlySelectedFormElement().set(propertyPathPrefix + 'defaultValue', defaultValue); + } else { + value = $( + getHelper().getDomElementDataIdentifierSelector('propertyGridEditorContainer') + ' ' + + getHelper().getDomElementDataIdentifierSelector('propertyGridEditorSelectValue') + ':checked', + $(editorHtml) + ).first() + .closest(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem')) + .find(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorValue')) + .val(); + + if (getUtility().canBeInterpretedAsInteger(value)) { + value = parseInt(value, 10); + } + + getCurrentlySelectedFormElement().set(propertyPathPrefix + 'defaultValue', value, true); + } + + const newPropertyData: Array<{_label: string, _value: string}> = []; + $( + getHelper().getDomElementDataIdentifierSelector('propertyGridEditorContainer') + ' ' + + getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem'), + $(editorHtml) + ).each(function(this: HTMLElement) { + let value = $(this) + .find(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorValue')) + .val(); + const label = $(this) + .find(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorLabel')) + .val(); + + if ('' === value) { + value = label; + } + + const tmpObject: Record<string, string> = {}; + tmpObject[value] = label; + newPropertyData.push({ + _label: label, + _value: value + }); + }); + + getCurrentlySelectedFormElement().set(propertyPathPrefix + propertyPath, newPropertyData); + validateCollectionElement(propertyPathPrefix + propertyPath, editorHtml); +} + +function getEditorWrapperDomElement(editorDomElement: HTMLElement | JQuery): JQuery { + return $(getHelper().getDomElementDataIdentifierSelector('editorWrapper'), $(editorDomElement)); +} + +function getEditorControlsWrapperDomElement(editorDomElement: HTMLElement | JQuery): JQuery { + return $(getHelper().getDomElementDataIdentifierSelector('editorControlsWrapper'), $(editorDomElement)); +} + +function validateCollectionElement(propertyPath: string, editorHtml: HTMLElement | JQuery): void { + let hasError, propertyPrefix, validationResults; + + validationResults = getFormEditorApp().validateCurrentlySelectedFormElementProperty(propertyPath); + + if (validationResults.length > 0) { + getHelper() + .getTemplatePropertyDomElement('validationErrors', editorHtml) + .text(validationResults[0]); + getViewModel().setElementValidationErrorClass( + getHelper().getTemplatePropertyDomElement('validationErrors', editorHtml) + ); + getViewModel().setElementValidationErrorClass( + getEditorControlsWrapperDomElement(editorHtml), + 'hasError' + ); + } else { + getHelper().getTemplatePropertyDomElement('validationErrors', editorHtml).text(''); + getViewModel().removeElementValidationErrorClass( + getHelper().getTemplatePropertyDomElement('validationErrors', editorHtml) + ); + getViewModel().removeElementValidationErrorClass( + getEditorControlsWrapperDomElement(editorHtml), + 'hasError' + ); + } + + validationResults = getFormEditorApp().validateFormElement(getCurrentlySelectedFormElement()); + propertyPrefix = propertyPath.split('.'); + propertyPrefix = propertyPrefix[0] + '.' + propertyPrefix[1]; + + hasError = false; + for (let i = 0, len = validationResults.length; i < len; ++i) { + if ( + validationResults[i].propertyPath.indexOf(propertyPrefix, 0) === 0 + && validationResults[i].validationResults + && validationResults[i].validationResults.length > 0 + ) { + hasError = true; + break; + } + } + + if (hasError) { + getViewModel().setElementValidationErrorClass( + getEditorControlsWrapperDomElement(editorHtml).closest(getHelper().getDomElementClassName('collectionElement', true)) + ); + } else { + getViewModel().removeElementValidationErrorClass( + getEditorControlsWrapperDomElement(editorHtml).closest(getHelper().getDomElementClassName('collectionElement', true)) + ); + } +} + +/** + * @throws 1489932939 + * @throws 1489932940 + */ +function getFirstAvailableValidationErrorMessage(errorCodes: string[], propertyData: PropertyData): string | null { + assert( + 'array' === $.type(errorCodes), + 'Invalid configuration "errorCodes"', + 1489932939 + ); + assert( + 'array' === $.type(propertyData), + 'Invalid configuration "propertyData"', + 1489932940 + ); + + for (let i = 0, len1 = errorCodes.length; i < len1; ++i) { + for (let j = 0, len2 = propertyData.length; j < len2; ++j) { + if (parseInt(errorCodes[i], 10) === parseInt(propertyData[j].code, 10)) { + if (getUtility().isNonEmptyString(propertyData[j].message)) { + return propertyData[j].message; + } + } + } + } + + return null; +} + +/** + * @throws 1489932942 + */ +function renewValidationErrorMessages( + errorCodes: string[], + propertyData: PropertyData, + value: string +): PropertyData { + assert( + 'array' === $.type(propertyData), + 'Invalid configuration "propertyData"', + 1489932942 + ); + + if ( + !getUtility().isUndefinedOrNull(errorCodes) + && 'array' === $.type(errorCodes) + ) { + const errorCodeSubset: PropertyData = []; + for (let i = 0, len1 = errorCodes.length; i < len1; ++i) { + let errorCodeFound = false; + + for (let j = 0, len2 = propertyData.length; j < len2; ++j) { + if (parseInt(errorCodes[i], 10) === parseInt(propertyData[j].code, 10)) { + errorCodeFound = true; + if (getUtility().isNonEmptyString(value)) { + // error code exists and should be updated because message is not empty + propertyData[j].message = value; + } else { + // error code exists but should be removed because message is empty + propertyData.splice(j, 1); + --len2; + } + } + } + + if (!errorCodeFound) { + // add new codes because message is not empty + if (getUtility().isNonEmptyString(value)) { + errorCodeSubset.push({ + code: errorCodes[i], + message: value + }); + } + } + } + + propertyData = propertyData.concat(errorCodeSubset); + } + + return propertyData; +} + +/** + * @throws 1523904699 + */ +function setRandomIds(html: JQuery): void { + assert( + 'object' === $.type(html), + 'Invalid input "html"', + 1523904699 + ); + + $(getHelper().getDomElementClassName('inspectorEditor', true)).each(function(this: HTMLElement) { + const $parent = $(this); + const idReplacements: Record<string, string> = {}; + + $(getHelper().getDomElementDataAttribute('randomId', 'bracesWithKey'), $parent).each(function(this: HTMLElement) { + const $element = $(this), + targetAttribute = $element.attr(getHelper().getDomElementDataAttribute('randomIdTarget')), + randomIdIndex = $element.attr(getHelper().getDomElementDataAttribute('randomIdIndex')); + + if ($element.is('[' + targetAttribute + ']')) { + return; + } + + if (!(randomIdIndex in idReplacements)) { + idReplacements[randomIdIndex] = 'fe' + Math.floor(Math.random() * 42) + Date.now(); + } + $element.attr(targetAttribute, idReplacements[randomIdIndex]); + }); + }); +} + +export function getInspectorDomElement(): JQuery { + return $(getHelper().getDomElementDataIdentifierSelector('inspector')); +} + +export function getFinishersContainerDomElement(): JQuery { + return $(getHelper().getDomElementDataIdentifierSelector('inspectorFinishers'), getInspectorDomElement()); +} + +export function getValidatorsContainerDomElement(): JQuery { + return $(getHelper().getDomElementDataIdentifierSelector('inspectorValidators'), getInspectorDomElement()); +} + +export function getCollectionElementDomElement( + collectionName: keyof FormEditorDefinitions, + collectionElementIdentifier: string +): JQuery { + if (collectionName === 'finishers') { + return $(getHelper().getDomElementDataAttribute( + 'finisher', + 'bracesWithKeyValue', + [collectionElementIdentifier] + ), getFinishersContainerDomElement()); + } else { + return $(getHelper().getDomElementDataAttribute( + 'validator', + 'bracesWithKeyValue', + [collectionElementIdentifier] + ), getValidatorsContainerDomElement()); + } +} + +export function renderEditors( + formElement?: FormElement | string, + callback?: () => void +): void { + if (getUtility().isUndefinedOrNull(formElement)) { + formElement = getCurrentlySelectedFormElement(); + } + + getInspectorDomElement().off().empty(); + + const formElementTypeDefinition = getFormElementDefinition(formElement, undefined); + if ('array' !== $.type(formElementTypeDefinition.editors)) { + return; + } + + for (let i = 0, len = formElementTypeDefinition.editors.length; i < len; ++i) { + const template = getHelper() + .getTemplate(formElementTypeDefinition.editors[i].templateName) + .clone(); + if (!template.length) { + continue; + } + const html = $(template.html()); + + $(html) + .first() + .addClass(getHelper().getDomElementClassName('inspectorEditor')); + getInspectorDomElement().append($(html)); + + setRandomIds(html); + renderEditorDispatcher(formElementTypeDefinition.editors[i], html); + } + + if ('function' === $.type(callback)) { + callback(); + } +} + +/** + * @publish view/inspector/collectionElements/dnd/update + * @throws 1478354853 + * @throws 1478354854 + */ +export function renderCollectionElementEditors( + collectionName: keyof FormEditorDefinitions, + collectionElementIdentifier: string +): void { + let collapseWrapper, collectionContainer; + + assert( + getUtility().isNonEmptyString(collectionName), + 'Invalid parameter "collectionName"', + 1478354853 + ); + assert( + getUtility().isNonEmptyString(collectionElementIdentifier), + 'Invalid parameter "collectionElementIdentifier"', + 1478354854 + ); + + const collectionElementConfiguration = getFormEditorApp().getPropertyCollectionElementConfiguration( + collectionElementIdentifier, + collectionName + ); + if ('array' !== $.type(collectionElementConfiguration.editors)) { + return; + } + + const collectionContainerElementWrapper = $('<div></div>').addClass(getHelper().getDomElementClassName('collectionElement')); + if (collectionName === 'finishers') { + collectionContainer = getFinishersContainerDomElement(); + collectionContainerElementWrapper + .attr(getHelper().getDomElementDataAttribute('finisher'), collectionElementIdentifier); + } else { + collectionContainer = getValidatorsContainerDomElement(); + collectionContainerElementWrapper + .attr(getHelper().getDomElementDataAttribute('validator'), collectionElementIdentifier); + } + collectionContainer.append(collectionContainerElementWrapper); + + const collectionElementEditorsLength = collectionElementConfiguration.editors.length; + if ( + collectionElementEditorsLength > 0 + && collectionElementConfiguration.editors[0].identifier === 'header' + ) { + collapseWrapper = $('<div role="tabpanel"></div>') + .addClass('panel-collapse collapse') + .prop('id', getCollectionElementId( + collectionName, + collectionElementIdentifier + )); + } + + for (let i = 0; i < collectionElementEditorsLength; ++i) { + const template = getHelper() + .getTemplate(collectionElementConfiguration.editors[i].templateName) + .clone(); + if (!template.length) { + continue; + } + const html = $(template.html()); + + $(html).first() + .addClass(getCollectionElementClass( + collectionName, + collectionElementConfiguration.editors[i].identifier + )) + .addClass(getHelper().getDomElementClassName('inspectorEditor')); + + if (i === 0 && collapseWrapper) { + getCollectionElementDomElement(collectionName, collectionElementIdentifier) + .append(html) + .append(collapseWrapper); + } else if ( + i === (collectionElementEditorsLength - 1) + && collapseWrapper + && collectionElementConfiguration.editors[i].identifier === 'removeButton' + ) { + getCollectionElementDomElement(collectionName, collectionElementIdentifier).append(html); + } else if (i > 0 && collapseWrapper) { + collapseWrapper.append(html); + } else { + getCollectionElementDomElement(collectionName, collectionElementIdentifier).append(html); + } + + setRandomIds(html); + renderEditorDispatcher( + collectionElementConfiguration.editors[i], + html, + collectionElementIdentifier, + collectionName + ); + } + + if ( + ( + collectionElementEditorsLength === 2 + && collectionElementConfiguration.editors[0].identifier === 'header' + && collectionElementConfiguration.editors[1].identifier === 'removeButton' + ) || ( + collectionElementEditorsLength === 1 + && collectionElementConfiguration.editors[0].identifier === 'header' + ) + ) { + $(getHelper().getDomElementDataIdentifierSelector('collapse'), collectionContainerElementWrapper).remove(); + } + + if (configuration.isSortable) { + addSortableCollectionElementsEvents(collectionContainer, collectionName); + } +} + +/** + * @publish view/inspector/collectionElement/existing/selected + * @publish view/inspector/collectionElement/new/selected + * @throws 1475423098 + * @throws 1475423099 + * @throws 1475423100 + * @throws 1475423101 + * @throws 1478362968 + */ +export function renderCollectionElementSelectionEditor( + collectionName: keyof FormEditorDefinitions, + editorConfiguration: EditorConfiguration, + editorHtml: HTMLElement | JQuery, +): void { + let alreadySelectedCollectionElements, collectionContainer, + removeSelectElement; + assert( + getUtility().isNonEmptyString(collectionName), + 'Invalid configuration "collectionName"', + 1478362968 + ); + assert( + 'object' === $.type(editorConfiguration), + 'Invalid parameter "editorConfiguration"', + 1475423098 + ); + assert( + 'object' === $.type(editorHtml), + 'Invalid parameter "editorHtml"', + 1475423099 + ); + assert( + getUtility().isNonEmptyString(editorConfiguration.label), + 'Invalid configuration "label"', + 1475423100 + ); + assert( + 'array' === $.type(editorConfiguration.selectOptions), + 'Invalid configuration "selectOptions"', + 1475423101 + ); + + if (collectionName === 'finishers') { + collectionContainer = getFinishersContainerDomElement(); + alreadySelectedCollectionElements = getRootFormElement().get(collectionName); + } else { + collectionContainer = getValidatorsContainerDomElement(); + alreadySelectedCollectionElements = getCurrentlySelectedFormElement().get(collectionName); + } + + collectionContainer.off().empty(); + + getHelper().getTemplatePropertyDomElement('label', editorHtml).text(editorConfiguration.label); + const selectElement = getHelper().getTemplatePropertyDomElement('selectOptions', editorHtml); + + if (!getUtility().isUndefinedOrNull(alreadySelectedCollectionElements)) { + for (let i = 0, len = alreadySelectedCollectionElements.length; i < len; ++i) { + getPublisherSubscriber().publish('view/inspector/collectionElement/existing/selected', [ + alreadySelectedCollectionElements[i].identifier, + collectionName + ]); + } + } + + removeSelectElement = true; + for (let i = 0, len1 = editorConfiguration.selectOptions.length; i < len1; ++i) { + let appendOption = true; + if (!getUtility().isUndefinedOrNull(alreadySelectedCollectionElements)) { + for (let j = 0, len2 = alreadySelectedCollectionElements.length; j < len2; ++j) { + if (alreadySelectedCollectionElements[j].identifier === editorConfiguration.selectOptions[i].value) { + appendOption = false; + break; + } + } + } + if (appendOption) { + selectElement.append(new Option( + editorConfiguration.selectOptions[i].label, + editorConfiguration.selectOptions[i].value + )); + if (editorConfiguration.selectOptions[i].value !== '') { + removeSelectElement = false; + } + } + } + + if (removeSelectElement) { + selectElement.off().empty().remove(); + } + + selectElement.on('change', function(this: HTMLSelectElement) { + if ($(this).val() !== '') { + const value = $(this).val(); + $('option[value="' + value + '"]', $(this)).remove(); + + getFormEditorApp().getPublisherSubscriber().publish( + 'view/inspector/collectionElement/new/selected', + [value, collectionName] + ); + } + }); +} + +/** + * @throws 1475421525 + * @throws 1475421526 + * @throws 1475421527 + * @throws 1475421528 + */ +export function renderFormElementHeaderEditor( + editorConfiguration: EditorConfiguration, + editorHtml: HTMLElement | JQuery, +): void { + assert('object' === $.type(editorConfiguration), 'Invalid parameter "editorConfiguration"', 1475421525); + assert('object' === $.type(editorHtml), 'Invalid parameter "editorHtml"', 1475421526); + + Icons.getIcon( + getFormElementDefinition(getCurrentlySelectedFormElement(), 'iconIdentifier'), + Icons.sizes.small, + null, + Icons.states.default + ).then(function(icon) { + getHelper().getTemplatePropertyDomElement('header-label', editorHtml) + .append($(icon).addClass(getHelper().getDomElementClassName('icon'))) + .append(buildTitleByFormElement()); + }); +} + +/** + * @throws 1475421257 + * @throws 1475421258 + * @throws 1475421259 + */ +export function renderCollectionElementHeaderEditor( + editorConfiguration: EditorConfiguration, + editorHtml: HTMLElement | JQuery, + collectionElementIdentifier: string, + collectionName: keyof FormEditorDefinitions +): void { + assert( + 'object' === $.type(editorConfiguration), + 'Invalid parameter "editorConfiguration"', + 1475421258 + ); + assert( + getUtility().isNonEmptyString(editorConfiguration.label), + 'Invalid configuration "label"', + 1475421257 + ); + assert( + 'object' === $.type(editorHtml), + 'Invalid parameter "editorHtml"', + 1475421259 + ); + + const setData = function(icon?: string) { + if (icon) { + getHelper() + .getTemplatePropertyDomElement('header-label', editorHtml) + .prepend($(icon)); + } + + const editors = getFormEditorApp().getPropertyCollectionElementConfiguration( + collectionElementIdentifier, + collectionName + ).editors; + + if (!( + ( + editors.length === 2 + && editors[0].identifier === 'header' + && editors[1].identifier === 'removeButton' + ) || ( + editors.length === 1 + && editors[0].identifier === 'header' + )) + ) { + Icons.getIcon( + getHelper().getDomElementDataAttributeValue('collapse'), + Icons.sizes.small, + null, + Icons.states.default, + Icons.markupIdentifiers.inline + ).then(function(icon) { + const iconWrap = $('<a></a>') + .attr('href', getCollectionElementId(collectionName, collectionElementIdentifier, true)) + .attr('data-bs-toggle', 'collapse') + .attr('aria-expanded', 'false') + .attr('aria-controls', getCollectionElementId(collectionName, collectionElementIdentifier)) + .addClass('collapsed') + .append($(icon)); + + getHelper() + .getTemplatePropertyDomElement('header-label', editorHtml) + .prepend(iconWrap); + }); + } + } + + const collectionElementConfiguration = getFormEditorApp().getFormEditorDefinition(collectionName, collectionElementIdentifier); + if ('iconIdentifier' in collectionElementConfiguration) { + Icons.getIcon( + collectionElementConfiguration.iconIdentifier, + Icons.sizes.small, + null, + Icons.states.default + ).then(function(icon) { + setData(icon); + }); + } else { + setData(); + } + + if (editorConfiguration.label) { + getHelper().getTemplatePropertyDomElement('label', editorHtml).append(editorConfiguration.label); + } +} + +export function renderFileMaxSizeEditor( + editorConfiguration: EditorConfiguration, + editorHtml: HTMLElement | JQuery, +): void { + assert( + 'object' === $.type(editorConfiguration), + 'Invalid parameter "editorConfiguration"', + 1475421258 + ); + assert( + getUtility().isNonEmptyString(editorConfiguration.label), + 'Invalid configuration "label"', + 1475421257 + ); + assert( + 'object' === $.type(editorHtml), + 'Invalid parameter "editorHtml"', + 1475421259 + ); + + if (editorConfiguration.label) { + const element = getHelper().getTemplatePropertyDomElement('label', editorHtml); + const maximumFileSize = element.attr(getHelper().getDomElementDataAttribute('maximumFileSize')); + element.append(editorConfiguration.label.replace('{0}', maximumFileSize)); + } +} + +/** + * @throws 1475421053 + * @throws 1475421054 + * @throws 1475421055 + * @throws 1475421056 + */ +export function renderTextEditor( + editorConfiguration: EditorConfiguration, + editorHtml: HTMLElement | JQuery, + collectionElementIdentifier: string, + collectionName: keyof FormEditorDefinitions +): void { + assert( + 'object' === $.type(editorConfiguration), + 'Invalid parameter "editorConfiguration"', + 1475421053 + ); + assert( + 'object' === $.type(editorHtml), + 'Invalid parameter "editorHtml"', + 1475421054 + ); + assert( + getUtility().isNonEmptyString(editorConfiguration.label), + 'Invalid configuration "label"', + 1475421055 + ); + assert( + getUtility().isNonEmptyString(editorConfiguration.propertyPath), + 'Invalid configuration "propertyPath"', + 1475421056 + ); + + getHelper() + .getTemplatePropertyDomElement('label', editorHtml) + .append(editorConfiguration.label); + if (getUtility().isNonEmptyString(editorConfiguration.fieldExplanationText)) { + getHelper() + .getTemplatePropertyDomElement('fieldExplanationText', editorHtml) + .text(editorConfiguration.fieldExplanationText); + } else { + getHelper() + .getTemplatePropertyDomElement('fieldExplanationText', editorHtml) + .remove(); + } + + if (getUtility().isNonEmptyString(editorConfiguration.placeholder)) { + getHelper() + .getTemplatePropertyDomElement('propertyPath', editorHtml) + .attr('placeholder', editorConfiguration.placeholder); + } + + const propertyPath = getFormEditorApp().buildPropertyPath( + editorConfiguration.propertyPath, + collectionElementIdentifier, + collectionName + ); + const propertyData = getCurrentlySelectedFormElement().get(propertyPath); + + validateCollectionElement(propertyPath, editorHtml); + + getHelper().getTemplatePropertyDomElement('propertyPath', editorHtml).val(propertyData); + + if ( + !getUtility().isUndefinedOrNull(editorConfiguration.additionalElementPropertyPaths) + && 'array' === $.type(editorConfiguration.additionalElementPropertyPaths) + ) { + for (let i = 0, len = editorConfiguration.additionalElementPropertyPaths.length; i < len; ++i) { + getCurrentlySelectedFormElement().set(editorConfiguration.additionalElementPropertyPaths[i], propertyData); + } + } + + renderFormElementSelectorEditorAddition(editorConfiguration, editorHtml, propertyPath); + + getHelper().getTemplatePropertyDomElement('propertyPath', editorHtml).on('keyup paste', function(this: HTMLInputElement) { + if ( + !!editorConfiguration.doNotSetIfPropertyValueIsEmpty + && !getUtility().isNonEmptyString($(this).val()) + ) { + getCurrentlySelectedFormElement().unset(propertyPath); + } else { + getCurrentlySelectedFormElement().set(propertyPath, $(this).val()); + } + validateCollectionElement(propertyPath, editorHtml); + if ( + !getUtility().isUndefinedOrNull(editorConfiguration.additionalElementPropertyPaths) + && 'array' === $.type(editorConfiguration.additionalElementPropertyPaths) + ) { + for (let i = 0, len = editorConfiguration.additionalElementPropertyPaths.length; i < len; ++i) { + if ( + !!editorConfiguration.doNotSetIfPropertyValueIsEmpty + && !getUtility().isNonEmptyString($(this).val()) + ) { + getCurrentlySelectedFormElement().unset(editorConfiguration.additionalElementPropertyPaths[i]); + } else { + getCurrentlySelectedFormElement().set(editorConfiguration.additionalElementPropertyPaths[i], $(this).val()); + } + } + } + }); +} + +/** + * @throws 1489874120 + * @throws 1489874121 + * @throws 1489874122 + * @throws 1489874123 + */ +export function renderValidationErrorMessageEditor( + editorConfiguration: EditorConfiguration, + editorHtml: HTMLElement | JQuery +): void { + assert( + 'object' === $.type(editorConfiguration), + 'Invalid parameter "editorConfiguration"', + 1489874121 + ); + assert( + 'object' === $.type(editorHtml), + 'Invalid parameter "editorHtml"', + 1489874122 + ); + assert( + getUtility().isNonEmptyString(editorConfiguration.label), + 'Invalid configuration "label"', + 1489874123 + ); + assert( + getUtility().isNonEmptyString(editorConfiguration.propertyPath), + 'Invalid configuration "propertyPath"', + 1489874124 + ); + + getHelper() + .getTemplatePropertyDomElement('label', editorHtml) + .append(editorConfiguration.label); + if (getUtility().isNonEmptyString(editorConfiguration.fieldExplanationText)) { + getHelper() + .getTemplatePropertyDomElement('fieldExplanationText', editorHtml) + .text(editorConfiguration.fieldExplanationText); + } else { + getHelper() + .getTemplatePropertyDomElement('fieldExplanationText', editorHtml) + .remove(); + } + + const propertyPath = getFormEditorApp().buildPropertyPath( + editorConfiguration.propertyPath + ); + + let propertyData: PropertyData = getCurrentlySelectedFormElement().get(propertyPath); + + if ( + !getUtility().isUndefinedOrNull(propertyData) + && 'array' === $.type(propertyData) + ) { + const validationErrorMessage = getFirstAvailableValidationErrorMessage(editorConfiguration.errorCodes, propertyData); + + if (!getUtility().isUndefinedOrNull(validationErrorMessage)) { + getHelper().getTemplatePropertyDomElement('propertyPath', editorHtml).val(validationErrorMessage); + } + } + + getHelper().getTemplatePropertyDomElement('propertyPath', editorHtml).on('keyup paste', function(this: HTMLInputElement) { + propertyData = getCurrentlySelectedFormElement().get(propertyPath); + if (getUtility().isUndefinedOrNull(propertyData)) { + propertyData = []; + } + getCurrentlySelectedFormElement().set(propertyPath, renewValidationErrorMessages( + editorConfiguration.errorCodes, + propertyData, + $(this).val() + )); + }); +} + +/** + * @throws 1674826430 + * @throws 1674826431 + * @throws 1674826432 + */ +export function renderCountrySelectEditor( + editorConfiguration: EditorConfiguration, + editorHtml: HTMLElement | JQuery, + collectionElementIdentifier: string, + collectionName: keyof FormEditorDefinitions +): void { + assert( + 'object' === $.type(editorConfiguration), + 'Invalid parameter "editorConfiguration"', + 1674826430 + ); + assert( + 'object' === $.type(editorHtml), + 'Invalid parameter "editorHtml"', + 1674826431 + ); + assert( + getUtility().isNonEmptyString(editorConfiguration.label), + 'Invalid configuration "label"', + 1674826432 + ); + + const propertyPath = getFormEditorApp().buildPropertyPath( + editorConfiguration.propertyPath, + collectionElementIdentifier, + collectionName + ); + + getHelper() + .getTemplatePropertyDomElement('label', editorHtml) + .append(editorConfiguration.label); + + const selectElement = getHelper() + .getTemplatePropertyDomElement('selectOptions', editorHtml); + + const propertyData: Record<string, string> = getCurrentlySelectedFormElement().get(propertyPath) || {}; + + const options = $('option', selectElement); + selectElement.empty(); + + for (let i = 0, len = options.length; i < len; ++i) { + let selected = false; + + for (const propertyDataKey of Object.keys(propertyData)) { + if ((options[i] as HTMLOptionElement).value === propertyData[propertyDataKey]) { + selected = true; + break; + } + } + + const option = new Option((options[i] as HTMLOptionElement).text, i.toString(), false, selected); + $(option).data({ value: (options[i] as HTMLOptionElement).value }); + selectElement.append(option); + } + + selectElement.on('change', function(this: HTMLSelectElement) { + const selectValues: string[] = []; + $('option:selected', $(this)).each(function(this: HTMLOptionElement) { + selectValues.push($(this).data('value')); + }); + + getCurrentlySelectedFormElement().set(propertyPath, selectValues); + }); +} + +/** + * @throws 1475421048 + * @throws 1475421049 + * @throws 1475421050 + * @throws 1475421051 + * @throws 1475421052 + */ +export function renderSingleSelectEditor( + editorConfiguration: EditorConfiguration, + editorHtml: HTMLElement | JQuery, + collectionElementIdentifier: string, + collectionName: keyof FormEditorDefinitions +): void { + assert( + 'object' === $.type(editorConfiguration), + 'Invalid parameter "editorConfiguration"', + 1475421048 + ); + assert( + 'object' === $.type(editorHtml), + 'Invalid parameter "editorHtml"', + 1475421049 + ); + assert( + getUtility().isNonEmptyString(editorConfiguration.label), + 'Invalid configuration "label"', + 1475421050 + ); + assert( + getUtility().isNonEmptyString(editorConfiguration.propertyPath), + 'Invalid configuration "propertyPath"', + 1475421051 + ); + assert( + 'array' === $.type(editorConfiguration.selectOptions), + 'Invalid configuration "selectOptions"', + 1475421052 + ); + + const propertyPath = getFormEditorApp().buildPropertyPath( + editorConfiguration.propertyPath, + collectionElementIdentifier, + collectionName + ); + + getHelper() + .getTemplatePropertyDomElement('label', editorHtml) + .append(editorConfiguration.label); + + const selectElement = getHelper() + .getTemplatePropertyDomElement('selectOptions', editorHtml); + + const propertyData = getCurrentlySelectedFormElement().get(propertyPath); + + for (let i = 0, len = editorConfiguration.selectOptions.length; i < len; ++i) { + let option; + + if (editorConfiguration.selectOptions[i].value === propertyData) { + option = new Option(editorConfiguration.selectOptions[i].label, i.toString(), false, true); + } else { + option = new Option(editorConfiguration.selectOptions[i].label, i.toString()); + } + $(option).data({ value: editorConfiguration.selectOptions[i].value }); + selectElement.append(option); + } + + selectElement.on('change', function(this: HTMLSelectElement) { + getCurrentlySelectedFormElement().set(propertyPath, $('option:selected', $(this)).data('value')); + }); +} + +/** + * @throws 1485712399 + * @throws 1485712400 + * @throws 1485712401 + * @throws 1485712402 + * @throws 1485712403 + */ +export function renderMultiSelectEditor( + editorConfiguration: EditorConfiguration, + editorHtml: HTMLElement | JQuery, + collectionElementIdentifier: string, + collectionName: keyof FormEditorDefinitions +): void { + assert( + 'object' === $.type(editorConfiguration), + 'Invalid parameter "editorConfiguration"', + 1485712399 + ); + assert( + 'object' === $.type(editorHtml), + 'Invalid parameter "editorHtml"', + 1485712400 + ); + assert( + getUtility().isNonEmptyString(editorConfiguration.label), + 'Invalid configuration "label"', + 1485712401 + ); + assert( + getUtility().isNonEmptyString(editorConfiguration.propertyPath), + 'Invalid configuration "propertyPath"', + 1485712402 + ); + assert( + 'array' === $.type(editorConfiguration.selectOptions), + 'Invalid configuration "selectOptions"', + 1485712403 + ); + + const propertyPath = getFormEditorApp().buildPropertyPath( + editorConfiguration.propertyPath, + collectionElementIdentifier, + collectionName + ); + + getHelper() + .getTemplatePropertyDomElement('label', editorHtml) + .append(editorConfiguration.label); + + const selectElement = getHelper() + .getTemplatePropertyDomElement('selectOptions', editorHtml); + + const propertyData: Record<string, string> = getCurrentlySelectedFormElement().get(propertyPath) || {}; + + for (let i = 0, len1 = editorConfiguration.selectOptions.length; i < len1; ++i) { + let option = null; + for (const propertyDataKey of Object.keys(propertyData)) { + if (editorConfiguration.selectOptions[i].value === propertyData[propertyDataKey]) { + option = new Option(editorConfiguration.selectOptions[i].label, i.toString(), false, true); + break; + } + } + + if (!option) { + option = new Option(editorConfiguration.selectOptions[i].label, i.toString()); + } + + $(option).data({ value: editorConfiguration.selectOptions[i].value }); + + selectElement.append(option); + } + + selectElement.on('change', function(this: HTMLSelectElement) { + const selectValues: string[] = []; + $('option:selected', $(this)).each(function(this: HTMLOptionElement) { + selectValues.push($(this).data('value')); + }); + + getCurrentlySelectedFormElement().set(propertyPath, selectValues); + }); +} + +/** + * @throws 1489528242 + * @throws 1489528243 + * @throws 1489528244 + * @throws 1489528245 + * @throws 1489528246 + * @throws 1489528247 + */ +export function renderGridColumnViewPortConfigurationEditor( + editorConfiguration: EditorConfiguration, + editorHtml: HTMLElement | JQuery +): void { + assert( + 'object' === $.type(editorConfiguration), + 'Invalid parameter "editorConfiguration"', + 1489528242 + ); + assert( + 'object' === $.type(editorHtml), + 'Invalid parameter "editorHtml"', + 1489528243 + ); + assert( + getUtility().isNonEmptyString(editorConfiguration.label), + 'Invalid configuration "label"', + 1489528244 + ); + assert( + 'array' === $.type(editorConfiguration.configurationOptions.viewPorts), + 'Invalid configurationOptions "viewPorts"', + 1489528245 + ); + assert( + !getUtility().isUndefinedOrNull(editorConfiguration.configurationOptions.numbersOfColumnsToUse.label), + 'Invalid configurationOptions "numbersOfColumnsToUse"', + 1489528246 + ); + assert( + !getUtility().isUndefinedOrNull(editorConfiguration.configurationOptions.numbersOfColumnsToUse.propertyPath), + 'Invalid configuration "selectOptions"', + 1489528247 + ); + + if (!getFormElementDefinition(getCurrentlySelectedFormElement().get('__parentRenderable'), '_isGridRowFormElement')) { + editorHtml.remove(); + return; + } + + getHelper() + .getTemplatePropertyDomElement('label', editorHtml) + .append(editorConfiguration.label); + + + const viewportButtonTemplate = $(getHelper() + .getDomElementDataIdentifierSelector('viewportButton'), $(editorHtml)) + .clone(); + + $(getHelper() + .getDomElementDataIdentifierSelector('viewportButton'), $(editorHtml)) + .remove(); + + const numbersOfColumnsTemplate = getHelper() + .getTemplatePropertyDomElement('numbersOfColumnsToUse', $(editorHtml)) + .clone(); + + getHelper() + .getTemplatePropertyDomElement('numbersOfColumnsToUse', $(editorHtml)) + .remove(); + + const editorControlsWrapper = getEditorControlsWrapperDomElement(editorHtml); + + const initNumbersOfColumnsField = function(element: JQuery) { + getHelper().getTemplatePropertyDomElement('numbersOfColumnsToUse', $(editorHtml)) + .off() + .empty() + .remove(); + + const numbersOfColumnsTemplateClone = $(numbersOfColumnsTemplate).clone(true, true); + getEditorWrapperDomElement(editorHtml).after(numbersOfColumnsTemplateClone); + + $('input', numbersOfColumnsTemplateClone).focus(); + + getHelper() + .getTemplatePropertyDomElement('numbersOfColumnsToUse-label', numbersOfColumnsTemplateClone) + .append( + editorConfiguration.configurationOptions.numbersOfColumnsToUse.label + .replace('{@viewPortLabel}', element.data('viewPortLabel')) + ); + + getHelper() + .getTemplatePropertyDomElement('numbersOfColumnsToUse-fieldExplanationText', numbersOfColumnsTemplateClone) + .append(editorConfiguration.configurationOptions.numbersOfColumnsToUse.fieldExplanationText); + + const propertyPath = editorConfiguration.configurationOptions.numbersOfColumnsToUse.propertyPath + .replace('{@viewPortIdentifier}', element.data('viewPortIdentifier')); + + getHelper() + .getTemplatePropertyDomElement('numbersOfColumnsToUse-propertyPath', numbersOfColumnsTemplateClone) + .val(getCurrentlySelectedFormElement().get(propertyPath)); + + getHelper().getTemplatePropertyDomElement('numbersOfColumnsToUse-propertyPath', numbersOfColumnsTemplateClone).on('keyup paste change', function(this: HTMLInputElement) { + const that = $(this); + if (!$.isNumeric(that.val())) { + that.val(''); + } + getCurrentlySelectedFormElement().set(propertyPath, that.val()); + }); + }; + + for (let i = 0, len = editorConfiguration.configurationOptions.viewPorts.length; i < len; ++i) { + const viewPortIdentifier = editorConfiguration.configurationOptions.viewPorts[i].viewPortIdentifier; + const viewPortLabel = editorConfiguration.configurationOptions.viewPorts[i].label; + + const viewportButtonTemplateClone = $(viewportButtonTemplate).clone(true, true); + viewportButtonTemplateClone.text(viewPortIdentifier); + viewportButtonTemplateClone.data('viewPortIdentifier', viewPortIdentifier); + viewportButtonTemplateClone.data('viewPortLabel', viewPortLabel); + viewportButtonTemplateClone.attr('title', viewPortLabel); + editorControlsWrapper.append(viewportButtonTemplateClone); + + if (i === (len - 1)) { + const numbersOfColumnsTemplateClone = $(numbersOfColumnsTemplate).clone(true, true); + getEditorWrapperDomElement(editorHtml).after(numbersOfColumnsTemplateClone); + initNumbersOfColumnsField(viewportButtonTemplateClone); + viewportButtonTemplateClone.addClass(getHelper().getDomElementClassName('active')); + } + + $('button', editorControlsWrapper).on('click', function(this: HTMLButtonElement) { + const that = $(this); + + $('button', editorControlsWrapper).removeClass(getHelper().getDomElementClassName('active')); + that.addClass(getHelper().getDomElementClassName('active')); + + initNumbersOfColumnsField(that); + }); + } +} + +/** + * @throws 1475419226 + * @throws 1475419227 + * @throws 1475419228 + * @throws 1475419229 + * @throws 1475419230 + * @throws 1475419231 + * @throws 1475419232 + */ +export function renderPropertyGridEditor( + editorConfiguration: EditorConfiguration, + editorHtml: HTMLElement | JQuery, + collectionElementIdentifier: string, + collectionName: keyof FormEditorDefinitions +): void { + assert( + 'object' === $.type(editorConfiguration), + 'Invalid parameter "editorConfiguration"', + 1475419226 + ); + assert( + 'object' === $.type(editorHtml), + 'Invalid parameter "editorHtml"', + 1475419227 + ); + assert( + 'boolean' === $.type(editorConfiguration.enableAddRow), + 'Invalid configuration "enableAddRow"', + 1475419228 + ); + assert( + 'boolean' === $.type(editorConfiguration.enableDeleteRow), + 'Invalid configuration "enableDeleteRow"', + 1475419230 + ); + assert( + 'boolean' === $.type(editorConfiguration.isSortable), + 'Invalid configuration "isSortable"', + 1475419229 + ); + assert( + getUtility().isNonEmptyString(editorConfiguration.propertyPath), + 'Invalid configuration "propertyPath"', + 1475419231 + ); + assert( + getUtility().isNonEmptyString(editorConfiguration.label), + 'Invalid configuration "label"', + 1475419232 + ); + + getHelper().getTemplatePropertyDomElement('label', editorHtml) + .append(editorConfiguration.label); + if (getUtility().isNonEmptyString(editorConfiguration.fieldExplanationText)) { + getHelper() + .getTemplatePropertyDomElement('fieldExplanationText', editorHtml) + .text(editorConfiguration.fieldExplanationText); + } else { + getHelper() + .getTemplatePropertyDomElement('fieldExplanationText', editorHtml) + .remove(); + } + + let propertyPathPrefix = getFormEditorApp().buildPropertyPath( + undefined, + collectionElementIdentifier, + collectionName, + undefined, + true + ); + if (getUtility().isNonEmptyString(propertyPathPrefix)) { + propertyPathPrefix = propertyPathPrefix + '.'; + } + + let useLabelAsFallbackValue: boolean; + if (getUtility().isUndefinedOrNull(editorConfiguration.useLabelAsFallbackValue)) { + useLabelAsFallbackValue = true; + } else { + useLabelAsFallbackValue = editorConfiguration.useLabelAsFallbackValue; + } + + let gridColumns = [ + { name: 'label', title: 'Label' }, + { name: 'value', title: 'Value' }, + { name: 'selected', title: 'Selected' }, + ]; + if (getUtility().isNonEmptyArray(editorConfiguration.gridColumns)) { + gridColumns = editorConfiguration.gridColumns; + } + const orderedGridColumnNames = gridColumns.map(function(item) { + return item.name; + }); + const orderedGridColumnTitles = gridColumns.map(function(item) { + return item.title || null; + }); + + $([ + getHelper().getDomElementDataIdentifierSelector('propertyGridEditorHeaderRow'), + getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem'), + getHelper().getDomElementDataIdentifierSelector('propertyGridEditorAddRowItem'), + ].join(','), $(editorHtml)).each(function (i, row) { + const $columns = $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorColumn'), row); + const $columnsAfter = $columns.last().nextAll(); + const columnsByName: Record<string, JQuery> = {}; + + // Collect columns by names, skip undesired columns + $columns + .detach() + .each(function(i, element) { + const $column = $(element); + const columnName = $column.data('column'); + + if (!orderedGridColumnNames.includes(columnName)) { + return; + } + + columnsByName[columnName] = $column; + }); + + // Insert columns in desired order + orderedGridColumnNames.forEach(function(columnName, i) { + const $column = columnsByName[columnName]; + + if ($column.is('th')) { + $column.append(orderedGridColumnTitles[i]); + } + + $column.appendTo(row); + }); + + // Insert remaining columns + $columnsAfter.appendTo(row); + }); + + let multiSelection: boolean; + if (getUtility().isUndefinedOrNull(editorConfiguration.multiSelection)) { + multiSelection = false; + } else { + multiSelection = !!editorConfiguration.multiSelection; + } + + const rowItemTemplate = $( + getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem'), + $(editorHtml) + ).clone(); + $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem'), $(editorHtml)).remove(); + + if (editorConfiguration.enableDeleteRow) { + $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorDeleteRow'), + $(rowItemTemplate) + ).on('click', function(this: HTMLElement) { + $(this) + .closest(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem')) + .off() + .empty() + .remove(); + + setPropertyGridData( + $(editorHtml), + multiSelection, + editorConfiguration.propertyPath, + propertyPathPrefix + ); + }); + } else { + $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorDeleteRow'), $(rowItemTemplate)) + .parent() + .off() + .empty(); + } + + if (editorConfiguration.isSortable) { + $(editorHtml).get(0).querySelectorAll(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorContainer') + ' tbody').forEach(function (sortableList: HTMLElement) { + new Sortable(sortableList, { + group: getHelper().getDomElementDataAttributeValue('propertyGridEditorContainer'), + handle: getHelper().getDomElementDataIdentifierSelector('propertyGridEditorSortRow'), + draggable: getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem'), + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + pull: 'clone', + swapThreshold: 0.6, + dragClass: 'form-sortable-drag', + ghostClass: 'form-sortable-ghost', + onUpdate: function() { + setPropertyGridData( + $(editorHtml), + multiSelection, + editorConfiguration.propertyPath, + propertyPathPrefix + ); + } + }); + }); + } else { + $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorSortRow'), $(rowItemTemplate)) + .parent() + .off() + .empty(); + } + + $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorSelectValue'), + $(rowItemTemplate) + ).on('change', function(this: HTMLElement) { + if (!multiSelection) { + $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorSelectValue') + ':checked', $(editorHtml)) + .not($(this)) + .prop('checked', false); + } + setPropertyGridData( + $(editorHtml), + multiSelection, + editorConfiguration.propertyPath, + propertyPathPrefix + ); + }); + + $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorLabel') + ',' + + getHelper().getDomElementDataIdentifierSelector('propertyGridEditorValue'), + $(rowItemTemplate) + ).on('keyup paste', function() { + setPropertyGridData( + $(editorHtml), + multiSelection, + editorConfiguration.propertyPath, + propertyPathPrefix + ); + }); + + if (useLabelAsFallbackValue) { + $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorLabel'), + $(rowItemTemplate) + ).on('focusout', function(this: HTMLElement) { + if ('' === $(this) + .closest(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem')) + .find(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorValue')) + .val() + ) { + $(this) + .closest(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem')) + .find(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorValue')) + .val($(this).val()); + } + }); + } + + if (editorConfiguration.enableAddRow) { + const addRowTemplate = $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorAddRowItem'), $(editorHtml)).clone(); + $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorAddRowItem'), $(editorHtml)).remove(); + + $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorAddRow'), $(addRowTemplate)).on('click', function(this: HTMLElement) { + $(this) + .closest(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorAddRowItem')) + .before($(rowItemTemplate).clone(true, true)); + + setPropertyGridData( + $(editorHtml), + multiSelection, + editorConfiguration.propertyPath, + propertyPathPrefix + ); + }); + $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorContainer'), $(editorHtml)) + .prepend($(addRowTemplate).clone(true, true)); + } else { + $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorAddRowItem'), $(editorHtml)).remove(); + } + + let defaultValue: Record<string, string> = {}; + if (multiSelection) { + if (!getUtility().isUndefinedOrNull(getCurrentlySelectedFormElement().get(propertyPathPrefix + 'defaultValue'))) { + defaultValue = getCurrentlySelectedFormElement().get(propertyPathPrefix + 'defaultValue'); + } + } else { + if (!getUtility().isUndefinedOrNull(getCurrentlySelectedFormElement().get(propertyPathPrefix + 'defaultValue'))) { + defaultValue = { 0: getCurrentlySelectedFormElement().get(propertyPathPrefix + 'defaultValue') }; + } + } + const propertyData = getCurrentlySelectedFormElement().get(propertyPathPrefix + editorConfiguration.propertyPath) || {}; + + const setData = function(label: string, value: string) { + let isPreselected = false; + const newRowTemplate = $(rowItemTemplate).clone(true, true); + + for (const defaultValueKey of Object.keys(defaultValue)) { + if (defaultValue[defaultValueKey] === value) { + isPreselected = true; + break; + } + } + + $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorLabel'), $(newRowTemplate)).val(label); + $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorValue'), $(newRowTemplate)).val(value); + + if (isPreselected) { + $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorSelectValue'), $(newRowTemplate)) + .prop('checked', true); + } + + if (editorConfiguration.enableAddRow) { + $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorAddRowItem'), $(editorHtml)) + .before($(newRowTemplate)); + } else { + $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorContainer'), $(editorHtml)) + .prepend($(newRowTemplate)); + } + }; + + if ('object' === $.type(propertyData)) { + for (const propertyDataKey of Object.keys(propertyData)) { + setData(propertyData[propertyDataKey], propertyDataKey); + } + } else if ('array' === $.type(propertyData)) { + for (const propertyDataKey in propertyData) { + // eslint-disable-next-line no-prototype-builtins + if (!propertyData.hasOwnProperty(propertyDataKey)) { + continue; + } + if (getUtility().isUndefinedOrNull(propertyData[propertyDataKey]._label)) { + setData(propertyData[propertyDataKey], propertyDataKey); + } else { + setData(propertyData[propertyDataKey]._label, propertyData[propertyDataKey]._value); + } + } + } + + validateCollectionElement(propertyPathPrefix + editorConfiguration.propertyPath, editorHtml); +} + +/** + * @publish view/inspector/collectionElement/new/selected + * @publish view/inspector/removeCollectionElement/perform + * @throws 1475417093 + * @throws 1475417094 + * @throws 1475417095 + * @throws 1475417096 + */ +export function renderRequiredValidatorEditor( + editorConfiguration: EditorConfiguration, + editorHtml: HTMLElement | JQuery, + collectionElementIdentifier: string, + collectionName: keyof FormEditorDefinitions +): void { + assert( + 'object' === $.type(editorConfiguration), + 'Invalid parameter "editorConfiguration"', + 1475417093 + ); + assert( + 'object' === $.type(editorHtml), + 'Invalid parameter "editorHtml"', + 1475417094 + ); + assert( + getUtility().isNonEmptyString(editorConfiguration.validatorIdentifier), + 'Invalid configuration "validatorIdentifier"', + 1475417095 + ); + assert( + getUtility().isNonEmptyString(editorConfiguration.label), + 'Invalid configuration "label"', + 1475417096 + ); + + const validatorIdentifier = editorConfiguration.validatorIdentifier; + getHelper().getTemplatePropertyDomElement('label', editorHtml).append(editorConfiguration.label); + + let propertyValue: string; + let propertyPath: string; + let propertyData: PropertyData; + if (getUtility().isNonEmptyString(editorConfiguration.propertyPath)) { + propertyPath = getFormEditorApp() + .buildPropertyPath(editorConfiguration.propertyPath, collectionElementIdentifier, collectionName); + } + if (getUtility().isNonEmptyString(editorConfiguration.propertyValue)) { + propertyValue = editorConfiguration.propertyValue; + } else { + propertyValue = ''; + } + + const validationErrorMessagePropertyPath = getFormEditorApp() + .buildPropertyPath(editorConfiguration.configurationOptions.validationErrorMessage.propertyPath); + + const validationErrorMessageTemplate = getHelper() + .getTemplatePropertyDomElement('validationErrorMessage', $(editorHtml)) + .clone(); + + getHelper() + .getTemplatePropertyDomElement('validationErrorMessage', $(editorHtml)) + .remove(); + + const showValidationErrorMessage = function() { + const validationErrorMessageTemplateClone = $(validationErrorMessageTemplate).clone(true, true); + getEditorWrapperDomElement(editorHtml).after(validationErrorMessageTemplateClone); + + getHelper() + .getTemplatePropertyDomElement('validationErrorMessage-label', validationErrorMessageTemplateClone) + .append(editorConfiguration.configurationOptions.validationErrorMessage.label); + + getHelper() + .getTemplatePropertyDomElement('validationErrorMessage-fieldExplanationText', validationErrorMessageTemplateClone) + .append(editorConfiguration.configurationOptions.validationErrorMessage.fieldExplanationText); + + propertyData = getCurrentlySelectedFormElement().get(validationErrorMessagePropertyPath); + if (getUtility().isUndefinedOrNull(propertyData)) { + propertyData = []; + } + + const validationErrorMessage = getFirstAvailableValidationErrorMessage( + editorConfiguration.configurationOptions.validationErrorMessage.errorCodes, + propertyData + ); + if (!getUtility().isUndefinedOrNull(validationErrorMessage)) { + getHelper() + .getTemplatePropertyDomElement('validationErrorMessage-propertyPath', validationErrorMessageTemplateClone) + .val(validationErrorMessage); + } + + getHelper().getTemplatePropertyDomElement('validationErrorMessage-propertyPath', validationErrorMessageTemplateClone).on('keyup paste', function(this: HTMLInputElement) { + let propertyData = getCurrentlySelectedFormElement().get(validationErrorMessagePropertyPath); + if (getUtility().isUndefinedOrNull(propertyData)) { + propertyData = []; + } + + getCurrentlySelectedFormElement().set(validationErrorMessagePropertyPath, renewValidationErrorMessages( + editorConfiguration.configurationOptions.validationErrorMessage.errorCodes, + propertyData, + $(this).val() + )); + }); + } + + if (-1 !== getFormEditorApp().getIndexFromPropertyCollectionElement(validatorIdentifier, 'validators')) { + $('input[type="checkbox"]', $(editorHtml)).prop('checked', true); + if (getUtility().isNonEmptyString(propertyPath)) { + getCurrentlySelectedFormElement().set(propertyPath, propertyValue); + } + showValidationErrorMessage(); + } + + $('input[type="checkbox"]', $(editorHtml)).on('change', function(this: HTMLInputElement) { + getHelper().getTemplatePropertyDomElement('validationErrorMessage', $(editorHtml)) + .off() + .empty() + .remove(); + + if ($(this).is(':checked')) { + showValidationErrorMessage(); + getPublisherSubscriber().publish( + 'view/inspector/collectionElement/new/selected', + [validatorIdentifier, 'validators'] + ); + + if (getUtility().isNonEmptyString(propertyPath)) { + getCurrentlySelectedFormElement().set(propertyPath, propertyValue); + } + } else { + getPublisherSubscriber().publish( + 'view/inspector/removeCollectionElement/perform', + [validatorIdentifier, 'validators'] + ); + if (getUtility().isNonEmptyString(propertyPath)) { + getCurrentlySelectedFormElement().unset(propertyPath); + } + + propertyData = getCurrentlySelectedFormElement().get(validationErrorMessagePropertyPath); + if (getUtility().isUndefinedOrNull(propertyData)) { + propertyData = []; + } + + getCurrentlySelectedFormElement().set(validationErrorMessagePropertyPath, renewValidationErrorMessages( + editorConfiguration.configurationOptions.validationErrorMessage.errorCodes, + propertyData, + '' + )); + } + }); +} + +/** + * @throws 1476218671 + * @throws 1476218672 + * @throws 1476218673 + * @throws 1476218674 + */ +export function renderCheckboxEditor( + editorConfiguration: EditorConfiguration, + editorHtml: HTMLElement | JQuery, + collectionElementIdentifier: string, + collectionName: keyof FormEditorDefinitions +): void { + assert( + 'object' === $.type(editorConfiguration), + 'Invalid parameter "editorConfiguration"', + 1476218671 + ); + assert( + 'object' === $.type(editorHtml), + 'Invalid parameter "editorHtml"', + 1476218672 + ); + assert( + getUtility().isNonEmptyString(editorConfiguration.label), + 'Invalid configuration "label"', + 1476218673 + ); + assert( + getUtility().isNonEmptyString(editorConfiguration.propertyPath), + 'Invalid configuration "propertyPath"', + 1476218674 + ); + + getHelper() + .getTemplatePropertyDomElement('label', editorHtml) + .append(editorConfiguration.label); + if (getUtility().isNonEmptyString(editorConfiguration.fieldExplanationText)) { + getHelper() + .getTemplatePropertyDomElement('fieldExplanationText', editorHtml) + .text(editorConfiguration.fieldExplanationText); + } else { + getHelper() + .getTemplatePropertyDomElement('fieldExplanationText', editorHtml) + .remove(); + } + + const propertyPath = getFormEditorApp() + .buildPropertyPath(editorConfiguration.propertyPath, collectionElementIdentifier, collectionName); + const propertyData = getCurrentlySelectedFormElement().get(propertyPath); + + if ( + ('boolean' === $.type(propertyData) && propertyData) + || propertyData === 'true' + || propertyData === 1 + || propertyData === '1' + ) { + $('input[type="checkbox"]', $(editorHtml)).prop('checked', true); + } + + $('input[type="checkbox"]', $(editorHtml)).on('change', function(this: HTMLInputElement) { + if ($(this).is(':checked')) { + getCurrentlySelectedFormElement().set(propertyPath, true); + } else { + getCurrentlySelectedFormElement().set(propertyPath, false); + } + }); +} + +/** + * @throws 1475412567 + * @throws 1475412568 + * @throws 1475416098 + * @throws 1475416099 + */ +export function renderTextareaEditor( + editorConfiguration: EditorConfiguration, + editorHtml: HTMLElement | JQuery, + collectionElementIdentifier: string, + collectionName: keyof FormEditorDefinitions +): void { + assert( + 'object' === $.type(editorConfiguration), + 'Invalid parameter "editorConfiguration"', + 1475412567 + ); + assert( + 'object' === $.type(editorHtml), + 'Invalid parameter "editorHtml"', + 1475412568 + ); + assert( + getUtility().isNonEmptyString(editorConfiguration.propertyPath), + 'Invalid configuration "propertyPath"', + 1475416098 + ); + assert( + getUtility().isNonEmptyString(editorConfiguration.label), + 'Invalid configuration "label"', + 1475416099 + ); + + const propertyPath = getFormEditorApp() + .buildPropertyPath(editorConfiguration.propertyPath, collectionElementIdentifier, collectionName); + + getHelper() + .getTemplatePropertyDomElement('label', editorHtml).append(editorConfiguration.label); + + if (getUtility().isNonEmptyString(editorConfiguration.fieldExplanationText)) { + getHelper() + .getTemplatePropertyDomElement('fieldExplanationText', editorHtml) + .text(editorConfiguration.fieldExplanationText); + } else { + getHelper() + .getTemplatePropertyDomElement('fieldExplanationText', editorHtml) + .remove(); + } + + const propertyData = getCurrentlySelectedFormElement().get(propertyPath); + $('textarea', $(editorHtml)).val(propertyData); + + $('textarea', $(editorHtml)).on('keyup paste', function(this: HTMLTextAreaElement) { + getCurrentlySelectedFormElement().set(propertyPath, $(this).val()); + }); +} + +/** + * @throws 1477300587 + * @throws 1477300588 + * @throws 1477300589 + * @throws 1477300590 + * @throws 1477318981 + * @throws 1477319859 + */ +export function renderTypo3WinBrowserEditor( + editorConfiguration: EditorConfiguration, + editorHtml: HTMLElement | JQuery, + collectionElementIdentifier: string, + collectionName: keyof FormEditorDefinitions +): void { + assert( + 'object' === $.type(editorConfiguration), + 'Invalid parameter "editorConfiguration"', + 1477300587 + ); + assert( + 'object' === $.type(editorHtml), + 'Invalid parameter "editorHtml"', + 1477300588 + ); + assert( + getUtility().isNonEmptyString(editorConfiguration.label), + 'Invalid configuration "label"', + 1477300589 + ); + assert( + getUtility().isNonEmptyString(editorConfiguration.buttonLabel), + 'Invalid configuration "buttonLabel"', + 1477318981 + ); + assert( + getUtility().isNonEmptyString(editorConfiguration.propertyPath), + 'Invalid configuration "propertyPath"', + 1477300590 + ); + + getHelper() + .getTemplatePropertyDomElement('label', editorHtml) + .append(editorConfiguration.label); + getHelper() + .getTemplatePropertyDomElement('buttonLabel', editorHtml) + .append(editorConfiguration.buttonLabel); + + if (getUtility().isNonEmptyString(editorConfiguration.fieldExplanationText)) { + getHelper() + .getTemplatePropertyDomElement('fieldExplanationText', editorHtml) + .text(editorConfiguration.fieldExplanationText); + } else { + getHelper() + .getTemplatePropertyDomElement('fieldExplanationText', editorHtml) + .remove(); + } + + $('form', $(editorHtml)).prop('name', editorConfiguration.propertyPath); + + Icons.getIcon(editorConfiguration.iconIdentifier, Icons.sizes.small).then(function(icon) { + getHelper().getTemplatePropertyDomElement('image', editorHtml).append($(icon)); + }); + + getHelper().getTemplatePropertyDomElement('onclick', editorHtml).on('click', function(this: HTMLElement) { + const randomIdentifier = Math.floor((Math.random() * 100000) + 1); + const insertTarget = $(this) + .closest(getHelper().getDomElementDataIdentifierSelector('editorControlsWrapper')) + .find(getHelper().getDomElementDataAttribute('contentElementSelectorTarget', 'bracesWithKey')); + + insertTarget.attr(getHelper().getDomElementDataAttribute('contentElementSelectorTarget'), randomIdentifier); + openTypo3WinBrowser('db', randomIdentifier + '|||' + editorConfiguration.browsableType); + }); + + listenOnElementBrowser(); + + const propertyPath = getFormEditorApp().buildPropertyPath(editorConfiguration.propertyPath, collectionElementIdentifier, collectionName); + const propertyData = getCurrentlySelectedFormElement().get(propertyPath); + + validateCollectionElement(propertyPath, editorHtml); + getHelper() + .getTemplatePropertyDomElement('propertyPath', editorHtml) + .val(propertyData); + + getHelper().getTemplatePropertyDomElement('propertyPath', editorHtml).on('keyup paste', function(this: HTMLInputElement) { + getCurrentlySelectedFormElement().set(propertyPath, $(this).val()); + validateCollectionElement(propertyPath, editorHtml); + }); +} + +/** + * @throws 1475412563 + * @throws 1475412564 + */ +export function renderRemoveElementEditor( + editorConfiguration: EditorConfiguration, + editorHtml: HTMLElement | JQuery, + collectionElementIdentifier: string, + collectionName: keyof FormEditorDefinitions +): void { + assert('object' === $.type(editorConfiguration), 'Invalid parameter "editorConfiguration"', 1475412563); + assert('object' === $.type(editorHtml), 'Invalid parameter "editorHtml"', 1475412564); + + if (getUtility().isUndefinedOrNull(collectionElementIdentifier)) { + + $('button', $(editorHtml)) + .addClass( + getHelper().getDomElementClassName('buttonFormElementRemove') + ' ' + + getHelper().getDomElementClassName('buttonFormEditor') + ); + } else { + $('button', $(editorHtml)).addClass( + getHelper().getDomElementClassName('buttonCollectionElementRemove') + ); + } + + $('button', $(editorHtml)).on('click', function() { + if (getUtility().isUndefinedOrNull(collectionElementIdentifier)) { + getViewModel().showRemoveFormElementModal(); + } else { + getViewModel().showRemoveCollectionElementModal(collectionElementIdentifier, collectionName); + } + }); +} + +/** + * @throws 1484574704 + * @throws 1484574705 + * @throws 1484574706 + */ +export function renderFormElementSelectorEditorAddition( + editorConfiguration: EditorConfiguration, + editorHtml: HTMLElement | JQuery, + propertyPath: string +): void { + assert( + 'object' === $.type(editorConfiguration), + 'Invalid parameter "editorConfiguration"', + 1484574704 + ); + assert( + 'object' === $.type(editorHtml), + 'Invalid parameter "editorHtml"', + 1484574705 + ); + assert( + getUtility().isNonEmptyString(propertyPath), + 'Invalid parameter "propertyPath"', + 1484574706 + ); + + const formElementSelectorControlsWrapper = $( + getHelper().getDomElementDataIdentifierSelector('formElementSelectorControlsWrapper'), editorHtml + ); + + if (editorConfiguration.enableFormelementSelectionButton === true) { + if (formElementSelectorControlsWrapper.length === 0) { + return; + } + + const formElementSelectorSplitButtonListContainer = $( + getHelper().getDomElementDataIdentifierSelector('formElementSelectorSplitButtonListContainer'), editorHtml + ); + + formElementSelectorSplitButtonListContainer.off().empty(); + const nonCompositeNonToplevelFormElements = getFormEditorApp().getNonCompositeNonToplevelFormElements(); + + if (nonCompositeNonToplevelFormElements.length === 0) { + Icons.getIcon( + getHelper().getDomElementDataAttributeValue('iconNotAvailable'), + Icons.sizes.small, + null, + Icons.states.default + ).then(function(icon) { + const itemTemplate = $('<li data-no-sorting>' + + '<a href="#"></a>' + + '</li>'); + + itemTemplate + .append($(icon)) + .append(' ' + getFormElementDefinition(getRootFormElement(), 'inspectorEditorFormElementSelectorNoElements')); + formElementSelectorSplitButtonListContainer.append(itemTemplate); + }); + } else { + $.each(nonCompositeNonToplevelFormElements, function(i, nonCompositeNonToplevelFormElement) { + Icons.getIcon( + getFormElementDefinition(nonCompositeNonToplevelFormElement, 'iconIdentifier'), + Icons.sizes.small, + null, + Icons.states.default + ).then(function(icon) { + const itemTemplate = $('<li data-no-sorting>' + + '<a href="#" class="dropdown-item" data-formelement-identifier="' + nonCompositeNonToplevelFormElement.get('identifier') + '">' + + '</a>' + + '</li>'); + + $('[data-formelement-identifier="' + nonCompositeNonToplevelFormElement.get('identifier') + '"]', itemTemplate) + .append($(icon)) + .append(' ' + nonCompositeNonToplevelFormElement.get('label')); + + $('a', itemTemplate).on('click', function(this: HTMLElement) { + let propertyData; + + propertyData = getCurrentlySelectedFormElement().get(propertyPath) || ''; + + if (propertyData.length === 0) { + propertyData = '{' + $(this).attr('data-formelement-identifier') + '}'; + } else { + propertyData = propertyData + ' ' + '{' + $(this).attr('data-formelement-identifier') + '}'; + } + + getCurrentlySelectedFormElement().set(propertyPath, propertyData); + getHelper().getTemplatePropertyDomElement('propertyPath', editorHtml).val(propertyData); + validateCollectionElement(propertyPath, editorHtml); + }); + + formElementSelectorSplitButtonListContainer.append(itemTemplate); + }); + }); + } + } else { + $(getHelper().getDomElementDataIdentifierSelector('editorControlsInputGroup'), editorHtml) + .removeClass(getHelper().getDomElementClassName('inspectorInputGroup')); + formElementSelectorControlsWrapper.off().empty().remove(); + } +} + +/** + * @throws 1478967319 + */ +export function buildTitleByFormElement(formElement?: FormElement): HTMLElement { + if (getUtility().isUndefinedOrNull(formElement)) { + formElement = getCurrentlySelectedFormElement(); + } + assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1478967319); + + let label; + if (formElement.get('type') === 'Form') { + label = formElement.get('type'); + } else { + label = getFormElementDefinition(formElement, 'label') + ? getFormElementDefinition(formElement, 'label') + : formElement.get('identifier'); + } + + const span = document.createElement('span'); + span.textContent = label; + return span; +} + +export function bootstrap( + this: typeof import('./inspector-component'), + _formEditorApp: FormEditor, + customConfiguration?: Configuration +): typeof import('./inspector-component') { + formEditorApp = _formEditorApp; + configuration = $.extend(true, defaultConfiguration, customConfiguration || {}); + Helper.bootstrap(formEditorApp); + return this; +} + +declare global { + interface PublisherSubscriberTopicArgumentsMap { + 'view/inspector/removeCollectionElement/perform': readonly [ + validatorIdentifier: string, + info: 'validators', + // @todo formElement is never published, but used by + // media subscribe('view/inspector/removeCollectionElement/perform', .) + // Can this be removed or is it possibly used by extensions? + formElement?: FormElement, + ]; + 'view/inspector/collectionElement/new/selected': readonly [ + value: string, + collectionName: keyof FormEditorDefinitions + ]; + 'view/inspector/collectionElement/existing/selected': readonly [ + alreadySelectedCollectionElementIdentifier: string, + collectionName: keyof FormEditorDefinitions + ]; + 'view/inspector/collectionElements/dnd/update': readonly [ + movedCollectionElementIdentifier: string, + previousCollectionElementIdentifier: string, + nextCollectionElementIdentifier: string, + collectionName: keyof FormEditorDefinitions + ]; + 'view/inspector/editor/insert/perform': readonly [ + editorConfiguration: EditorConfiguration, + editorHtml: HTMLElement | JQuery, + collectionElementIdentifier: string, + collectionName: keyof FormEditorDefinitions + ]; + } +} diff --git a/typo3/sysext/form/Resources/Public/JavaScript/backend/form-editor/inspector-component.js b/typo3/sysext/form/Resources/Public/JavaScript/backend/form-editor/inspector-component.js index 411ef0e6b149b9f600e18832e729f1dd0d477160..ca9c70a8db01b40b35db977f2607b6a2cad1e220 100644 --- a/typo3/sysext/form/Resources/Public/JavaScript/backend/form-editor/inspector-component.js +++ b/typo3/sysext/form/Resources/Public/JavaScript/backend/form-editor/inspector-component.js @@ -10,2792 +10,4 @@ * * The TYPO3 project - inspiring people to share! */ - -/** - * Module: @typo3/form/backend/form-editor/inspector-component - */ - -import $ from 'jquery'; -import * as Helper from '@typo3/form/backend/form-editor/helper.js'; -import Icons from '@typo3/backend/icons.js'; -import Notification from '@typo3/backend/notification.js'; -import Modal from '@typo3/backend/modal.js'; -import {MessageUtility} from '@typo3/backend/utility/message-utility.js'; -import Sortable from 'sortablejs'; - -const { - bootstrap, - buildTitleByFormElement, - getCollectionElementDomElement, - getFinishersContainerDomElement, - getInspectorDomElement, - getValidatorsContainerDomElement, - renderCheckboxEditor, - renderCollectionElementEditors, - renderCollectionElementHeaderEditor, - renderCountrySelectEditor, - renderFileMaxSizeEditor, - renderCollectionElementSelectionEditor, - renderEditors, - renderFormElementHeaderEditor, - renderFormElementSelectorEditorAddition, - renderPropertyGridEditor, - renderRemoveElementEditor, - renderRequiredValidatorEditor, - renderSingleSelectEditor, - renderMultiSelectEditor, - renderTextareaEditor, - renderTextEditor, - renderTypo3WinBrowserEditor -} = factory($, Helper, Icons, Notification, Modal, MessageUtility); - -export { - bootstrap, - buildTitleByFormElement, - getCollectionElementDomElement, - getFinishersContainerDomElement, - getInspectorDomElement, - getValidatorsContainerDomElement, - renderCheckboxEditor, - renderCollectionElementEditors, - renderCollectionElementHeaderEditor, - renderFileMaxSizeEditor, - renderCollectionElementSelectionEditor, - renderEditors, - renderFormElementHeaderEditor, - renderFormElementSelectorEditorAddition, - renderPropertyGridEditor, - renderRemoveElementEditor, - renderRequiredValidatorEditor, - renderSingleSelectEditor, - renderMultiSelectEditor, - renderTextareaEditor, - renderTextEditor, - renderTypo3WinBrowserEditor -}; - -function factory($, Helper, Icons, Notification, Modal, MessageUtility) { - return (function($, Helper, Icons, Notification) { - - /** - * @private - * - * @var object - */ - var _configuration = null; - - /** - * @private - * - * @var object - */ - var _defaultConfiguration = { - domElementClassNames: { - buttonFormElementRemove: 't3-form-remove-element-button', - collectionElement: 't3-form-collection-element', - finisherEditorPrefix: 't3-form-inspector-finishers-editor-', - inspectorEditor: 'form-editor', - inspectorInputGroup: 'input-group', - validatorEditorPrefix: 't3-form-inspector-validators-editor-' - }, - domElementDataAttributeNames: { - contentElementSelectorTarget: 'data-insert-target', - finisher: 'data-finisher-identifier', - validator: 'data-validator-identifier', - randomId: 'data-random-id', - randomIdTarget: 'data-random-id-attribute', - randomIdIndex: 'data-random-id-number', - maximumFileSize: 'data-maximumFileSize' - }, - domElementDataAttributeValues: { - collapse: 'actions-view-table-expand', - editorControlsInputGroup: 'inspectorEditorControlsGroup', - editorWrapper: 'editorWrapper', - editorControlsWrapper: 'inspectorEditorControlsWrapper', - formElementHeaderEditor: 'inspectorFormElementHeaderEditor', - formElementSelectorControlsWrapper: 'inspectorEditorFormElementSelectorControlsWrapper', - formElementSelectorSplitButtonContainer: 'inspectorEditorFormElementSelectorSplitButtonContainer', - formElementSelectorSplitButtonListContainer: 'inspectorEditorFormElementSelectorSplitButtonListContainer', - iconNotAvailable: 'actions-close', - inspector: 'inspector', - 'Inspector-CheckboxEditor': 'Inspector-CheckboxEditor', - 'Inspector-CollectionElementHeaderEditor': 'Inspector-CollectionElementHeaderEditor', - 'Inspector-FinishersEditor': 'Inspector-FinishersEditor', - 'Inspector-FormElementHeaderEditor': 'Inspector-FormElementHeaderEditor', - 'Inspector-PropertyGridEditor': 'Inspector-PropertyGridEditor', - 'Inspector-RemoveElementEditor': 'Inspector-RemoveElementEditor', - 'Inspector-RequiredValidatorEditor': 'Inspector-RequiredValidatorEditor', - 'Inspector-SingleSelectEditor': 'Inspector-SingleSelectEditor', - 'Inspector-MultiSelectEditor': 'Inspector-MultiSelectEditor', - 'Inspector-GridColumnViewPortConfigurationEditor': 'Inspector-GridColumnViewPortConfigurationEditor', - 'Inspector-TextareaEditor': 'Inspector-TextareaEditor', - 'Inspector-TextEditor': 'Inspector-TextEditor', - 'Inspector-Typo3WinBrowserEditor': 'Inspector-Typo3WinBrowserEditor', - 'Inspector-ValidatorsEditor': 'Inspector-ValidatorsEditor', - 'Inspector-ValidationErrorMessageEditor': 'Inspector-ValidationErrorMessageEditor', - - inspectorFinishers: 'inspectorFinishers', - inspectorValidators: 'inspectorValidators', - propertyGridEditorHeaderRow: 'headerRow', - propertyGridEditorAddRow: 'addRow', - propertyGridEditorAddRowItem: 'addRowItem', - propertyGridEditorContainer: 'propertyGridContainer', - propertyGridEditorDeleteRow: 'deleteRow', - propertyGridEditorLabel: 'label', - propertyGridEditorRowItem: 'rowItem', - propertyGridEditorColumn: 'column', - propertyGridEditorSelectValue: 'selectValue', - propertyGridEditorSortRow: 'sortRow', - propertyGridEditorValue: 'value', - viewportButton: 'viewportButton' - }, - domElementIdNames: { - finisherPrefix: 't3-form-inspector-finishers-', - validatorPrefix: 't3-form-inspector-validators-' - }, - isSortable: true - }; - - /** - * @private - * - * @var object - */ - var _formEditorApp = null; - - /* ************************************************************* - * Private Methods - * ************************************************************/ - - /** - * @private - * - * @return void - * @throws 1478268638 - */ - function _helperSetup() { - assert('function' === $.type(Helper.bootstrap), - 'The view model helper does not implement the method "bootstrap"', - 1478268638 - ); - Helper.bootstrap(getFormEditorApp()); - }; - - /** - * @private - * - * @return object - */ - function getFormEditorApp() { - return _formEditorApp; - }; - - /** - * @private - * - * @return object - */ - function getViewModel() { - return getFormEditorApp().getViewModel(); - }; - - /** - * @private - * - * @param object - * @return object - */ - function getHelper(configuration) { - if (getUtility().isUndefinedOrNull(configuration)) { - return Helper.setConfiguration(_configuration); - } - return Helper.setConfiguration(configuration); - }; - - /** - * @private - * - * @return object - */ - function getUtility() { - return getFormEditorApp().getUtility(); - }; - - /** - * @private - * - * @param mixed test - * @param string message - * @param int messageCode - * @return void - */ - function assert(test, message, messageCode) { - return getFormEditorApp().assert(test, message, messageCode); - }; - - /** - * @private - * - * @return object - */ - function getCurrentlySelectedFormElement() { - return getFormEditorApp().getCurrentlySelectedFormElement(); - }; - - /** - * @private - * - * @return object - */ - function getRootFormElement() { - return getFormEditorApp().getRootFormElement(); - }; - - /** - * @private - * - * @return object - */ - function getPublisherSubscriber() { - return getFormEditorApp().getPublisherSubscriber(); - }; - - /** - * @private - * - * @param object - * @param string - * @return mixed - */ - function getFormElementDefinition(formElement, formElementDefinitionKey) { - return getFormEditorApp().getFormElementDefinition(formElement, formElementDefinitionKey); - }; - - /** - * @private - * - * @param object - * @param object - * @param string - * @param string - * @return void - * @publish view/inspector/editor/insert/perform - */ - function _renderEditorDispatcher(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) { - switch (editorConfiguration['templateName']) { - case 'Inspector-FormElementHeaderEditor': - renderFormElementHeaderEditor( - editorConfiguration, - editorHtml, - collectionElementIdentifier, - collectionName - ); - break; - case 'Inspector-CollectionElementHeaderEditor': - renderCollectionElementHeaderEditor( - editorConfiguration, - editorHtml, - collectionElementIdentifier, - collectionName - ); - break; - case 'Inspector-MaximumFileSizeEditor': - renderMaximumFileSizeEditor( - editorConfiguration, - editorHtml - ); - break; - case 'Inspector-TextEditor': - renderTextEditor( - editorConfiguration, - editorHtml, - collectionElementIdentifier, - collectionName - ); - break; - case 'Inspector-FinishersEditor': - renderCollectionElementSelectionEditor( - 'finishers', - editorConfiguration, - editorHtml, - collectionElementIdentifier, - collectionName - ); - break; - case 'Inspector-ValidatorsEditor': - renderCollectionElementSelectionEditor( - 'validators', - editorConfiguration, - editorHtml, - collectionElementIdentifier, - collectionName - ); - break; - case 'Inspector-ValidationErrorMessageEditor': - renderValidationErrorMessageEditor( - editorConfiguration, - editorHtml, - collectionElementIdentifier, - collectionName - ); - break; - case 'Inspector-RemoveElementEditor': - renderRemoveElementEditor( - editorConfiguration, - editorHtml, - collectionElementIdentifier, - collectionName - ); - break; - case 'Inspector-RequiredValidatorEditor': - renderRequiredValidatorEditor( - editorConfiguration, - editorHtml, - collectionElementIdentifier, - collectionName - ); - break; - case 'Inspector-CheckboxEditor': - renderCheckboxEditor( - editorConfiguration, - editorHtml, - collectionElementIdentifier, - collectionName - ); - break; - case 'Inspector-CountrySelectEditor': - renderCountrySelectEditor( - editorConfiguration, - editorHtml, - collectionElementIdentifier, - collectionName - ); - break; - case 'Inspector-SingleSelectEditor': - renderSingleSelectEditor( - editorConfiguration, - editorHtml, - collectionElementIdentifier, - collectionName - ); - break; - case 'Inspector-MultiSelectEditor': - renderMultiSelectEditor( - editorConfiguration, - editorHtml, - collectionElementIdentifier, - collectionName - ); - break; - case 'Inspector-GridColumnViewPortConfigurationEditor': - renderGridColumnViewPortConfigurationEditor( - editorConfiguration, - editorHtml, - collectionElementIdentifier, - collectionName - ); - break; - case 'Inspector-PropertyGridEditor': - renderPropertyGridEditor( - editorConfiguration, - editorHtml, - collectionElementIdentifier, - collectionName - ); - break; - case 'Inspector-TextareaEditor': - renderTextareaEditor( - editorConfiguration, - editorHtml, - collectionElementIdentifier, - collectionName - ); - break; - case 'Inspector-Typo3WinBrowserEditor': - renderTypo3WinBrowserEditor( - editorConfiguration, - editorHtml, - collectionElementIdentifier, - collectionName - ); - break; - } - getPublisherSubscriber().publish('view/inspector/editor/insert/perform', [ - editorConfiguration, editorHtml, collectionElementIdentifier, collectionName - ]); - }; - - /** - * @private - * - * opens a popup window with the element browser - * - * @param string mode - * @param string params - */ - function _openTypo3WinBrowser(mode, params) { - Modal.advanced({ - type: Modal.types.iframe, - content: TYPO3.settings.FormEditor.typo3WinBrowserUrl + '&mode=' + mode + '&bparams=' + params, - size: Modal.sizes.large - }); - }; - - /** - * @private - * - * Listens on messages sent by ElementBrowser - */ - function _listenOnElementBrowser() { - window.addEventListener('message', function (e) { - if (!MessageUtility.verifyOrigin(e.origin)) { - throw 'Denied message sent by ' + e.origin; - } - - if (e.data.actionName === 'typo3:elementBrowser:elementAdded') { - if (typeof e.data.fieldName === 'undefined') { - throw 'fieldName not defined in message'; - } - - if (typeof e.data.value === 'undefined') { - throw 'value not defined in message'; - } - - var result = e.data.value.split('_'); - $(getHelper().getDomElementDataAttribute('contentElementSelectorTarget', 'bracesWithKeyValue', [e.data.fieldName])) - .val(result.pop()) - .trigger('paste'); - } - }); - } - - /** - * @private - * - * @param string - * @param string - * @return object - */ - function _getCollectionElementClass(collectionName, collectionElementIdentifier) { - if (collectionName === 'finishers') { - return getHelper() - .getDomElementClassName('finisherEditorPrefix') + collectionElementIdentifier; - } else { - return getHelper() - .getDomElementClassName('validatorEditorPrefix') + collectionElementIdentifier; - } - }; - - /** - * @private - * - * @param string - * @param string - * @param bool - * @return object - */ - function _getCollectionElementId(collectionName, collectionElementIdentifier, asSelector) { - if (collectionName === 'finishers') { - return getHelper() - .getDomElementIdName('finisherPrefix', asSelector) + collectionElementIdentifier; - } else { - return getHelper() - .getDomElementIdName('validatorPrefix', asSelector) + collectionElementIdentifier; - } - }; - - /** - * @private - * - * @param object - * @param string - * @return void - */ - function _addSortableCollectionElementsEvents(sortableDomElement, collectionName) { - sortableDomElement.addClass(getHelper().getDomElementClassName('sortable')); - new Sortable(sortableDomElement.get(0), { - draggable: getHelper().getDomElementClassName('collectionElement', true), - filter: 'input,textarea,select', - preventOnFilter: false, - animation: 200, - fallbackTolerance: 200, - swapThreshold: 0.6, - dragClass: 'form-sortable-drag', - ghostClass: 'form-sortable-ghost', - onEnd: function (e) { - let dataAttributeName; - - if (collectionName === 'finishers') { - dataAttributeName = getHelper().getDomElementDataAttribute('finisher'); - } else { - dataAttributeName = getHelper().getDomElementDataAttribute('validator'); - } - - const movedCollectionElementIdentifier = $(e.item).attr(dataAttributeName); - const previousCollectionElementIdentifier = $(e.item) - .prevAll(getHelper().getDomElementClassName('collectionElement', true)) - .first() - .attr(dataAttributeName); - const nextCollectionElementIdentifier = $(e.item) - .nextAll(getHelper().getDomElementClassName('collectionElement', true)) - .first() - .attr(dataAttributeName); - - getPublisherSubscriber().publish('view/inspector/collectionElements/dnd/update', [ - movedCollectionElementIdentifier, - previousCollectionElementIdentifier, - nextCollectionElementIdentifier, - collectionName - ]); - } - }); - }; - - /** - * @private - * - * @param object editorHtml - * @param bool multiSelection - * @param string propertyPath - * @param string propertyPathPrefix - * @return void - */ - function _setPropertyGridData(editorHtml, multiSelection, propertyPath, propertyPathPrefix) { - var defaultValue, newPropertyData, value; - - if (multiSelection) { - defaultValue = []; - - $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorContainer') + ' ' + - getHelper().getDomElementDataIdentifierSelector('propertyGridEditorSelectValue') + ':checked', - $(editorHtml) - ).each(function(i) { - value = $(this) - .closest(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem')) - .find(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorValue')) - .val(); - - if (getUtility().canBeInterpretedAsInteger(value)) { - value = parseInt(value, 10); - } - - defaultValue.push(value); - }); - getCurrentlySelectedFormElement().set(propertyPathPrefix + 'defaultValue', defaultValue); - } else { - value = $( - getHelper().getDomElementDataIdentifierSelector('propertyGridEditorContainer') + ' ' + - getHelper().getDomElementDataIdentifierSelector('propertyGridEditorSelectValue') + ':checked', - $(editorHtml) - ).first() - .closest(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem')) - .find(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorValue')) - .val(); - - if (getUtility().canBeInterpretedAsInteger(value)) { - value = parseInt(value, 10); - } - - getCurrentlySelectedFormElement().set(propertyPathPrefix + 'defaultValue', value, true); - } - - newPropertyData = []; - $( - getHelper().getDomElementDataIdentifierSelector('propertyGridEditorContainer') + ' ' + - getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem'), - $(editorHtml) - ).each(function(i) { - var value, label, tmpObject; - - value = $(this) - .find(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorValue')) - .val(); - label = $(this) - .find(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorLabel')) - .val(); - - if ('' === value) { - value = label; - } - - tmpObject = {}; - tmpObject[value] = label; - newPropertyData.push({ - _label: label, - _value: value - }); - }); - - getCurrentlySelectedFormElement().set(propertyPathPrefix + propertyPath, newPropertyData); - _validateCollectionElement(propertyPathPrefix + propertyPath, editorHtml); - }; - - /** - * @private - * - * @param object - * @return object - */ - function _getEditorWrapperDomElement(editorDomElement) { - return $(getHelper().getDomElementDataIdentifierSelector('editorWrapper'), $(editorDomElement)); - }; - - /** - * @private - * - * @param object - * @return object - */ - function _getEditorControlsWrapperDomElement(editorDomElement) { - return $(getHelper().getDomElementDataIdentifierSelector('editorControlsWrapper'), $(editorDomElement)); - }; - - /** - * @private - * - * @param string - * @param object - * @return void - */ - function _validateCollectionElement(propertyPath, editorHtml) { - var hasError, propertyPrefix, validationResults; - - validationResults = getFormEditorApp().validateCurrentlySelectedFormElementProperty(propertyPath); - - if (validationResults.length > 0) { - getHelper() - .getTemplatePropertyDomElement('validationErrors', editorHtml) - .text(validationResults[0]); - getViewModel().setElementValidationErrorClass( - getHelper().getTemplatePropertyDomElement('validationErrors', editorHtml) - ); - getViewModel().setElementValidationErrorClass( - _getEditorControlsWrapperDomElement(editorHtml), - 'hasError' - ); - } else { - getHelper().getTemplatePropertyDomElement('validationErrors', editorHtml).text(''); - getViewModel().removeElementValidationErrorClass( - getHelper().getTemplatePropertyDomElement('validationErrors', editorHtml) - ); - getViewModel().removeElementValidationErrorClass( - _getEditorControlsWrapperDomElement(editorHtml), - 'hasError' - ); - } - - validationResults = getFormEditorApp().validateFormElement(getCurrentlySelectedFormElement()); - propertyPrefix = propertyPath.split('.'); - propertyPrefix = propertyPrefix[0] + '.' + propertyPrefix[1]; - - hasError = false; - for (var i = 0, len = validationResults.length; i < len; ++i) { - if ( - validationResults[i]['propertyPath'].indexOf(propertyPrefix, 0) === 0 - && validationResults[i]['validationResults'] - && validationResults[i]['validationResults'].length > 0 - ) { - hasError = true; - break; - } - } - - if (hasError) { - getViewModel().setElementValidationErrorClass( - _getEditorControlsWrapperDomElement(editorHtml).closest(getHelper().getDomElementClassName('collectionElement', true)) - ); - } else { - getViewModel().removeElementValidationErrorClass( - _getEditorControlsWrapperDomElement(editorHtml).closest(getHelper().getDomElementClassName('collectionElement', true)) - ); - } - }; - - /** - * @private - * - * @param object - * @param object - * @return null|string - * @throws 1489932939 - * @throws 1489932940 - */ - function _getFirstAvailableValidationErrorMessage(errorCodes, propertyData) { - assert( - 'array' === $.type(errorCodes), - 'Invalid configuration "errorCodes"', - 1489932939 - ); - assert( - 'array' === $.type(propertyData), - 'Invalid configuration "propertyData"', - 1489932940 - ); - - for (var i = 0, len1 = errorCodes.length; i < len1; ++i) { - for (var j = 0, len2 = propertyData.length; j < len2; ++j) { - if (parseInt(errorCodes[i]) === parseInt(propertyData[j]['code'])) { - if (getUtility().isNonEmptyString(propertyData[j]['message'])) { - return propertyData[j]['message']; - } - } - } - } - - return null; - }; - - /** - * @private - * - * @param object - * @param object - * @param string - * @return object - * @throws 1489932942 - */ - function _renewValidationErrorMessages(errorCodes, propertyData, value) { - var errorCodeSubset; - - assert( - 'array' === $.type(propertyData), - 'Invalid configuration "propertyData"', - 1489932942 - ); - - if ( - !getUtility().isUndefinedOrNull(errorCodes) - && 'array' === $.type(errorCodes) - ) { - errorCodeSubset = []; - for (var i = 0, len1 = errorCodes.length; i < len1; ++i) { - var errorCodeFound = false; - - for (var j = 0, len2 = propertyData.length; j < len2; ++j) { - if (parseInt(errorCodes[i]) === parseInt(propertyData[j]['code'])) { - errorCodeFound = true; - if (getUtility().isNonEmptyString(value)) { - // error code exists and should be updated because message is not empty - propertyData[j]['message'] = value; - } else { - // error code exists but should be removed because message is empty - propertyData.splice(j, 1); - --len2; - } - } - } - - if (!errorCodeFound) { - // add new codes because message is not empty - if (getUtility().isNonEmptyString(value)) { - errorCodeSubset.push({ - code: errorCodes[i], - message: value - }); - } - } - } - - propertyData = propertyData.concat(errorCodeSubset); - } - - return propertyData; - }; - - /** - * @private - * - * @param object - * @throws 1523904699 - */ - function _setRandomIds(html) { - assert( - 'object' === $.type(html), - 'Invalid input "html"', - 1523904699 - ); - - $(getHelper().getDomElementClassName('inspectorEditor', true)).each(function(e) { - var $parent = $(this), - idReplacements = {}; - - $(getHelper().getDomElementDataAttribute('randomId', 'bracesWithKey'), $parent).each(function(e) { - var $element = $(this), - targetAttribute = $element.attr(getHelper().getDomElementDataAttribute('randomIdTarget')), - randomIdIndex = $element.attr(getHelper().getDomElementDataAttribute('randomIdIndex')); - - if ($element.is('[' + targetAttribute + ']')) { - return true; - } - - if (!idReplacements.hasOwnProperty(randomIdIndex)) { - idReplacements[randomIdIndex] = 'fe' + Math.floor(Math.random() * 42) + Date.now(); - } - $element.attr(targetAttribute, idReplacements[randomIdIndex]); - }); - }); - }; - - /* ************************************************************* - * Public Methods - * ************************************************************/ - - /** - * @public - * - * @return object - */ - function getInspectorDomElement() { - return $(getHelper().getDomElementDataIdentifierSelector('inspector')); - }; - - /** - * @public - * - * @return object - */ - function getFinishersContainerDomElement() { - return $(getHelper().getDomElementDataIdentifierSelector('inspectorFinishers'), getInspectorDomElement()); - }; - - /** - * @public - * - * @return object - */ - function getValidatorsContainerDomElement() { - return $(getHelper().getDomElementDataIdentifierSelector('inspectorValidators'), getInspectorDomElement()); - }; - - /** - * @public - * - * @param string - * @param string - * @return object - */ - function getCollectionElementDomElement(collectionName, collectionElementIdentifier) { - if (collectionName === 'finishers') { - return $(getHelper().getDomElementDataAttribute( - 'finisher', - 'bracesWithKeyValue', - [collectionElementIdentifier] - ), getFinishersContainerDomElement()); - } else { - return $(getHelper().getDomElementDataAttribute( - 'validator', - 'bracesWithKeyValue', - [collectionElementIdentifier] - ), getValidatorsContainerDomElement()); - } - }; - - /** - * @public - * - * @param object - * @param function - * @return void - */ - function renderEditors(formElement, callback) { - var formElementTypeDefinition; - if (getUtility().isUndefinedOrNull(formElement)) { - formElement = getCurrentlySelectedFormElement(); - } - - getInspectorDomElement().off().empty(); - - formElementTypeDefinition = getFormElementDefinition(formElement); - if ('array' !== $.type(formElementTypeDefinition['editors'])) { - return; - } - - for (var i = 0, len = formElementTypeDefinition['editors'].length; i < len; ++i) { - var html, template; - - template = getHelper() - .getTemplate(formElementTypeDefinition['editors'][i]['templateName']) - .clone(); - if (!template.length) { - continue; - } - html = $(template.html()); - - $(html) - .first() - .addClass(getHelper().getDomElementClassName('inspectorEditor')); - getInspectorDomElement().append($(html)); - - _setRandomIds(html); - _renderEditorDispatcher(formElementTypeDefinition['editors'][i], html); - } - - if ('function' === $.type(callback)) { - callback(); - } - }; - - /** - * @public - * - * @param string collectionName - * @param string collectionElementIdentifier - * @return void - * @publish view/inspector/collectionElements/dnd/update - * @throws 1478354853 - * @throws 1478354854 - */ - function renderCollectionElementEditors(collectionName, collectionElementIdentifier) { - var collapseWrapper, collectionContainer, collectionContainerElementWrapper, - collectionElementConfiguration, collectionElementEditorsLength; - - assert( - getUtility().isNonEmptyString(collectionName), - 'Invalid parameter "collectionName"', - 1478354853 - ); - assert( - getUtility().isNonEmptyString(collectionElementIdentifier), - 'Invalid parameter "collectionElementIdentifier"', - 1478354854 - ); - - collectionElementConfiguration = getFormEditorApp().getPropertyCollectionElementConfiguration( - collectionElementIdentifier, - collectionName - ); - if ('array' !== $.type(collectionElementConfiguration['editors'])) { - return; - } - - collectionContainerElementWrapper = $('<div></div>').addClass(getHelper().getDomElementClassName('collectionElement')); - if (collectionName === 'finishers') { - collectionContainer = getFinishersContainerDomElement(); - collectionContainerElementWrapper - .attr(getHelper().getDomElementDataAttribute('finisher'), collectionElementIdentifier); - } else { - collectionContainer = getValidatorsContainerDomElement(); - collectionContainerElementWrapper - .attr(getHelper().getDomElementDataAttribute('validator'), collectionElementIdentifier); - } - collectionContainer.append(collectionContainerElementWrapper); - - collectionElementEditorsLength = collectionElementConfiguration['editors'].length; - if ( - collectionElementEditorsLength > 0 - && collectionElementConfiguration['editors'][0]['identifier'] === 'header' - ) { - collapseWrapper = $('<div role="tabpanel"></div>') - .addClass('panel-collapse collapse') - .prop('id', _getCollectionElementId( - collectionName, - collectionElementIdentifier - )); - } - - for (var i = 0; i < collectionElementEditorsLength; ++i) { - var html, template; - - template = getHelper() - .getTemplate(collectionElementConfiguration['editors'][i]['templateName']) - .clone(); - if (!template.length) { - continue; - } - html = $(template.html()); - - $(html).first() - .addClass(_getCollectionElementClass( - collectionName, - collectionElementConfiguration['editors'][i]['identifier'] - )) - .addClass(getHelper().getDomElementClassName('inspectorEditor')); - - if (i === 0 && collapseWrapper) { - getCollectionElementDomElement(collectionName, collectionElementIdentifier) - .append(html) - .append(collapseWrapper); - } else if ( - i === (collectionElementEditorsLength - 1) - && collapseWrapper - && collectionElementConfiguration['editors'][i]['identifier'] === 'removeButton' - ) { - getCollectionElementDomElement(collectionName, collectionElementIdentifier).append(html); - } else if (i > 0 && collapseWrapper) { - collapseWrapper.append(html); - } else { - getCollectionElementDomElement(collectionName, collectionElementIdentifier).append(html); - } - - _setRandomIds(html); - _renderEditorDispatcher( - collectionElementConfiguration['editors'][i], - html, - collectionElementIdentifier, - collectionName - ); - } - - if ( - ( - collectionElementEditorsLength === 2 - && collectionElementConfiguration['editors'][0]['identifier'] === 'header' - && collectionElementConfiguration['editors'][1]['identifier'] === 'removeButton' - ) || ( - collectionElementEditorsLength === 1 - && collectionElementConfiguration['editors'][0]['identifier'] === 'header' - ) - ) { - $(getHelper().getDomElementDataIdentifierSelector('collapse'), collectionContainerElementWrapper).remove(); - } - - if (_configuration['isSortable']) { - _addSortableCollectionElementsEvents(collectionContainer, collectionName); - } - }; - - /** - * @public - * - * @string collectionName - * @param object editorConfiguration - * @param object editorHtml - * @return void - * @publish view/inspector/collectionElement/existing/selected - * @publish view/inspector/collectionElement/new/selected - * @throws 1475423098 - * @throws 1475423099 - * @throws 1475423100 - * @throws 1475423101 - * @throws 1478362968 - */ - function renderCollectionElementSelectionEditor(collectionName, editorConfiguration, editorHtml) { - var alreadySelectedCollectionElements, selectElement, collectionContainer, - removeSelectElement; - assert( - getUtility().isNonEmptyString(collectionName), - 'Invalid configuration "collectionName"', - 1478362968 - ); - assert( - 'object' === $.type(editorConfiguration), - 'Invalid parameter "editorConfiguration"', - 1475423098 - ); - assert( - 'object' === $.type(editorHtml), - 'Invalid parameter "editorHtml"', - 1475423099 - ); - assert( - getUtility().isNonEmptyString(editorConfiguration['label']), - 'Invalid configuration "label"', - 1475423100 - ); - assert( - 'array' === $.type(editorConfiguration['selectOptions']), - 'Invalid configuration "selectOptions"', - 1475423101 - ); - - if (collectionName === 'finishers') { - collectionContainer = getFinishersContainerDomElement(); - alreadySelectedCollectionElements = getRootFormElement().get(collectionName); - } else { - collectionContainer = getValidatorsContainerDomElement(); - alreadySelectedCollectionElements = getCurrentlySelectedFormElement().get(collectionName); - } - - collectionContainer.off().empty(); - - getHelper().getTemplatePropertyDomElement('label', editorHtml).text(editorConfiguration['label']); - selectElement = getHelper().getTemplatePropertyDomElement('selectOptions', editorHtml); - - if (!getUtility().isUndefinedOrNull(alreadySelectedCollectionElements)) { - for (var i = 0, len = alreadySelectedCollectionElements.length; i < len; ++i) { - getPublisherSubscriber().publish('view/inspector/collectionElement/existing/selected', [ - alreadySelectedCollectionElements[i]['identifier'], - collectionName - ]); - } - } - - removeSelectElement = true; - for (var i = 0, len1 = editorConfiguration['selectOptions'].length; i < len1; ++i) { - var appendOption = true; - if (!getUtility().isUndefinedOrNull(alreadySelectedCollectionElements)) { - for (var j = 0, len2 = alreadySelectedCollectionElements.length; j < len2; ++j) { - if (alreadySelectedCollectionElements[j]['identifier'] === editorConfiguration['selectOptions'][i]['value']) { - appendOption = false; - break; - } - } - } - if (appendOption) { - selectElement.append(new Option( - editorConfiguration['selectOptions'][i]['label'], - editorConfiguration['selectOptions'][i]['value'] - )); - if (editorConfiguration['selectOptions'][i]['value'] !== '') { - removeSelectElement = false; - } - } - } - - if (removeSelectElement) { - selectElement.off().empty().remove(); - } - - selectElement.on('change', function() { - if ($(this).val() !== '') { - var value = $(this).val(); - $('option[value="' + value + '"]', $(this)).remove(); - - getFormEditorApp().getPublisherSubscriber().publish( - 'view/inspector/collectionElement/new/selected', - [value, collectionName] - ); - } - }); - }; - - /** - * @public - * - * @param object editorConfiguration - * @param object editorHtml - * @param string collectionElementIdentifier - * @param string collectionName - * @return void - * @throws 1475421525 - * @throws 1475421526 - * @throws 1475421527 - * @throws 1475421528 - */ - function renderFormElementHeaderEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) { - assert('object' === $.type(editorConfiguration), 'Invalid parameter "editorConfiguration"', 1475421525); - assert('object' === $.type(editorHtml), 'Invalid parameter "editorHtml"', 1475421526); - - Icons.getIcon( - getFormElementDefinition(getCurrentlySelectedFormElement(), 'iconIdentifier'), - Icons.sizes.small, - null, - Icons.states.default - ).then(function(icon) { - getHelper().getTemplatePropertyDomElement('header-label', editorHtml) - .append($(icon).addClass(getHelper().getDomElementClassName('icon'))) - .append(buildTitleByFormElement()); - }); - }; - - /** - * @public - * - * @param object editorConfiguration - * @param object editorHtml - * @param string collectionElementIdentifier - * @param string collectionName - * @return void - * @throws 1475421257 - * @throws 1475421258 - * @throws 1475421259 - */ - function renderCollectionElementHeaderEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) { - var collectionElementConfiguration, setData; - - assert( - 'object' === $.type(editorConfiguration), - 'Invalid parameter "editorConfiguration"', - 1475421258 - ); - assert( - getUtility().isNonEmptyString(editorConfiguration['label']), - 'Invalid configuration "label"', - 1475421257 - ); - assert( - 'object' === $.type(editorHtml), - 'Invalid parameter "editorHtml"', - 1475421259 - ); - - setData = function(icon) { - getHelper() - .getTemplatePropertyDomElement('header-label', editorHtml) - .prepend($(icon)); - - const editors = getFormEditorApp().getPropertyCollectionElementConfiguration( - collectionElementIdentifier, - collectionName - ).editors; - - if (!( - ( - editors.length === 2 - && editors[0]['identifier'] === 'header' - && editors[1]['identifier'] === 'removeButton' - ) || ( - editors.length === 1 - && editors[0]['identifier'] === 'header' - )) - ) { - Icons.getIcon( - getHelper().getDomElementDataAttributeValue('collapse'), - Icons.sizes.small, - null, - Icons.states.default, - Icons.markupIdentifiers.inline - ).then(function(icon) { - var iconWrap; - iconWrap = $('<a></a>') - .attr('href', _getCollectionElementId(collectionName, collectionElementIdentifier, true)) - .attr('data-bs-toggle', 'collapse') - .attr('aria-expanded', 'false') - .attr('aria-controls', _getCollectionElementId(collectionName, collectionElementIdentifier)) - .addClass('collapsed') - .append($(icon)); - - getHelper() - .getTemplatePropertyDomElement('header-label', editorHtml) - .prepend(iconWrap); - }); - }; - } - - collectionElementConfiguration = getFormEditorApp().getFormEditorDefinition(collectionName, collectionElementIdentifier); - Icons.getIcon( - collectionElementConfiguration['iconIdentifier'], - Icons.sizes.small, - null, - Icons.states.default - ).then(function(icon) { - setData(icon); - }); - - if (editorConfiguration['label']) { - getHelper().getTemplatePropertyDomElement('label', editorHtml).append(editorConfiguration['label']); - } - }; - - function renderMaximumFileSizeEditor(editorConfiguration, editorHtml) { - assert( - 'object' === $.type(editorConfiguration), - 'Invalid parameter "editorConfiguration"', - 1475421258 - ); - assert( - getUtility().isNonEmptyString(editorConfiguration['label']), - 'Invalid configuration "label"', - 1475421257 - ); - assert( - 'object' === $.type(editorHtml), - 'Invalid parameter "editorHtml"', - 1475421259 - ); - - if (editorConfiguration['label']) { - var element = getHelper().getTemplatePropertyDomElement('label', editorHtml); - var maximumFileSize = element.attr(getHelper().getDomElementDataAttribute('maximumFileSize')); - element.append(editorConfiguration['label'].replace('{0}', maximumFileSize)); - } - }; - - /** - * @public - * - * @param object editorConfiguration - * @param object editorHtml - * @param string collectionElementIdentifier - * @param string collectionName - * @return void - * @throws 1475421053 - * @throws 1475421054 - * @throws 1475421055 - * @throws 1475421056 - */ - function renderTextEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) { - var propertyData, propertyPath; - assert( - 'object' === $.type(editorConfiguration), - 'Invalid parameter "editorConfiguration"', - 1475421053 - ); - assert( - 'object' === $.type(editorHtml), - 'Invalid parameter "editorHtml"', - 1475421054 - ); - assert( - getUtility().isNonEmptyString(editorConfiguration['label']), - 'Invalid configuration "label"', - 1475421055 - ); - assert( - getUtility().isNonEmptyString(editorConfiguration['propertyPath']), - 'Invalid configuration "propertyPath"', - 1475421056 - ); - - getHelper() - .getTemplatePropertyDomElement('label', editorHtml) - .append(editorConfiguration['label']); - if (getUtility().isNonEmptyString(editorConfiguration['fieldExplanationText'])) { - getHelper() - .getTemplatePropertyDomElement('fieldExplanationText', editorHtml) - .text(editorConfiguration['fieldExplanationText']); - } else { - getHelper() - .getTemplatePropertyDomElement('fieldExplanationText', editorHtml) - .remove(); - } - - if (getUtility().isNonEmptyString(editorConfiguration['placeholder'])) { - getHelper() - .getTemplatePropertyDomElement('propertyPath', editorHtml) - .attr('placeholder', editorConfiguration['placeholder']); - } - - propertyPath = getFormEditorApp().buildPropertyPath( - editorConfiguration['propertyPath'], - collectionElementIdentifier, - collectionName - ); - propertyData = getCurrentlySelectedFormElement().get(propertyPath); - - _validateCollectionElement(propertyPath, editorHtml); - - getHelper().getTemplatePropertyDomElement('propertyPath', editorHtml).val(propertyData); - - if ( - !getUtility().isUndefinedOrNull(editorConfiguration['additionalElementPropertyPaths']) - && 'array' === $.type(editorConfiguration['additionalElementPropertyPaths']) - ) { - for (var i = 0, len = editorConfiguration['additionalElementPropertyPaths'].length; i < len; ++i) { - getCurrentlySelectedFormElement().set(editorConfiguration['additionalElementPropertyPaths'][i], propertyData); - } - } - - renderFormElementSelectorEditorAddition(editorConfiguration, editorHtml, propertyPath); - - getHelper().getTemplatePropertyDomElement('propertyPath', editorHtml).on('keyup paste', function() { - if ( - !!editorConfiguration['doNotSetIfPropertyValueIsEmpty'] - && !getUtility().isNonEmptyString($(this).val()) - ) { - getCurrentlySelectedFormElement().unset(propertyPath); - } else { - getCurrentlySelectedFormElement().set(propertyPath, $(this).val()); - } - _validateCollectionElement(propertyPath, editorHtml); - if ( - !getUtility().isUndefinedOrNull(editorConfiguration['additionalElementPropertyPaths']) - && 'array' === $.type(editorConfiguration['additionalElementPropertyPaths']) - ) { - for (var i = 0, len = editorConfiguration['additionalElementPropertyPaths'].length; i < len; ++i) { - if ( - !!editorConfiguration['doNotSetIfPropertyValueIsEmpty'] - && !getUtility().isNonEmptyString($(this).val()) - ) { - getCurrentlySelectedFormElement().unset(editorConfiguration['additionalElementPropertyPaths'][i]); - } else { - getCurrentlySelectedFormElement().set(editorConfiguration['additionalElementPropertyPaths'][i], $(this).val()); - } - } - } - }); - }; - - /** - * @public - * - * @param object editorConfiguration - * @param object editorHtml - * @param string collectionElementIdentifier - * @param string collectionName - * @return void - * @throws 1489874120 - * @throws 1489874121 - * @throws 1489874122 - * @throws 1489874123 - */ - function renderValidationErrorMessageEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) { - var propertyData, propertyPath, validationErrorMessage; - assert( - 'object' === $.type(editorConfiguration), - 'Invalid parameter "editorConfiguration"', - 1489874121 - ); - assert( - 'object' === $.type(editorHtml), - 'Invalid parameter "editorHtml"', - 1489874122 - ); - assert( - getUtility().isNonEmptyString(editorConfiguration['label']), - 'Invalid configuration "label"', - 1489874123 - ); - assert( - getUtility().isNonEmptyString(editorConfiguration['propertyPath']), - 'Invalid configuration "propertyPath"', - 1489874124 - ); - - getHelper() - .getTemplatePropertyDomElement('label', editorHtml) - .append(editorConfiguration['label']); - if (getUtility().isNonEmptyString(editorConfiguration['fieldExplanationText'])) { - getHelper() - .getTemplatePropertyDomElement('fieldExplanationText', editorHtml) - .text(editorConfiguration['fieldExplanationText']); - } else { - getHelper() - .getTemplatePropertyDomElement('fieldExplanationText', editorHtml) - .remove(); - } - - propertyPath = getFormEditorApp().buildPropertyPath( - editorConfiguration['propertyPath'] - ); - - propertyData = getCurrentlySelectedFormElement().get(propertyPath); - - if ( - !getUtility().isUndefinedOrNull(propertyData) - && 'array' === $.type(propertyData) - ) { - validationErrorMessage = _getFirstAvailableValidationErrorMessage(editorConfiguration['errorCodes'], propertyData); - - if (!getUtility().isUndefinedOrNull(validationErrorMessage)) { - getHelper().getTemplatePropertyDomElement('propertyPath', editorHtml).val(validationErrorMessage); - } - } - - getHelper().getTemplatePropertyDomElement('propertyPath', editorHtml).on('keyup paste', function() { - propertyData = getCurrentlySelectedFormElement().get(propertyPath); - if (getUtility().isUndefinedOrNull(propertyData)) { - propertyData = []; - } - getCurrentlySelectedFormElement().set(propertyPath, _renewValidationErrorMessages( - editorConfiguration['errorCodes'], - propertyData, - $(this).val() - )); - }); - }; - - /** - * @public - * - * @param object editorConfiguration - * @param object editorHtml - * @param string collectionElementIdentifier - * @param string collectionName - * @return void - * @throws 1674826430 - * @throws 1674826431 - * @throws 1674826432 - */ - function renderCountrySelectEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) { - var propertyData, propertyPath, selectElement, options; - assert( - 'object' === $.type(editorConfiguration), - 'Invalid parameter "editorConfiguration"', - 1674826430 - ); - assert( - 'object' === $.type(editorHtml), - 'Invalid parameter "editorHtml"', - 1674826431 - ); - assert( - getUtility().isNonEmptyString(editorConfiguration['label']), - 'Invalid configuration "label"', - 1674826432 - ); - - propertyPath = getFormEditorApp().buildPropertyPath( - editorConfiguration['propertyPath'], - collectionElementIdentifier, - collectionName - ); - - getHelper() - .getTemplatePropertyDomElement('label', editorHtml) - .append(editorConfiguration['label']); - - selectElement = getHelper() - .getTemplatePropertyDomElement('selectOptions', editorHtml); - - propertyData = getCurrentlySelectedFormElement().get(propertyPath); - - options = $('option', selectElement); - selectElement.empty(); - - for (var i = 0, len = options.length; i < len; ++i) { - var option, selected = false; - - for (var propertyDataKey in propertyData) { - if (!propertyData.hasOwnProperty(propertyDataKey)) { - continue; - } - - if (options[i].value === propertyData[propertyDataKey]) { - selected = true; - break; - } - } - - option = new Option(options[i].text, i, false, selected); - $(option).data({value: options[i].value}); - selectElement.append(option); - } - - selectElement.on('change', function() { - var selectValues = []; - $('option:selected', $(this)).each(function(i) { - selectValues.push($(this).data('value')); - }); - - getCurrentlySelectedFormElement().set(propertyPath, selectValues); - }); - }; - - /** - * @public - * - * @param object editorConfiguration - * @param object editorHtml - * @param string collectionElementIdentifier - * @param string collectionName - * @return void - * @throws 1475421048 - * @throws 1475421049 - * @throws 1475421050 - * @throws 1475421051 - * @throws 1475421052 - */ - function renderSingleSelectEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) { - var propertyData, propertyPath, selectElement; - assert( - 'object' === $.type(editorConfiguration), - 'Invalid parameter "editorConfiguration"', - 1475421048 - ); - assert( - 'object' === $.type(editorHtml), - 'Invalid parameter "editorHtml"', - 1475421049 - ); - assert( - getUtility().isNonEmptyString(editorConfiguration['label']), - 'Invalid configuration "label"', - 1475421050 - ); - assert( - getUtility().isNonEmptyString(editorConfiguration['propertyPath']), - 'Invalid configuration "propertyPath"', - 1475421051 - ); - assert( - 'array' === $.type(editorConfiguration['selectOptions']), - 'Invalid configuration "selectOptions"', - 1475421052 - ); - - propertyPath = getFormEditorApp().buildPropertyPath( - editorConfiguration['propertyPath'], - collectionElementIdentifier, - collectionName - ); - - getHelper() - .getTemplatePropertyDomElement('label', editorHtml) - .append(editorConfiguration['label']); - - selectElement = getHelper() - .getTemplatePropertyDomElement('selectOptions', editorHtml); - - propertyData = getCurrentlySelectedFormElement().get(propertyPath); - - for (var i = 0, len = editorConfiguration['selectOptions'].length; i < len; ++i) { - var option; - - if (editorConfiguration['selectOptions'][i]['value'] === propertyData) { - option = new Option(editorConfiguration['selectOptions'][i]['label'], i, false, true); - } else { - option = new Option(editorConfiguration['selectOptions'][i]['label'], i); - } - $(option).data({value: editorConfiguration['selectOptions'][i]['value']}); - selectElement.append(option); - } - - selectElement.on('change', function() { - getCurrentlySelectedFormElement().set(propertyPath, $('option:selected', $(this)).data('value')); - }); - }; - - /** - * @public - * - * @param object editorConfiguration - * @param object editorHtml - * @param string collectionElementIdentifier - * @param string collectionName - * @return void - * @throws 1485712399 - * @throws 1485712400 - * @throws 1485712401 - * @throws 1485712402 - * @throws 1485712403 - */ - function renderMultiSelectEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) { - var propertyData, propertyPath, selectElement; - assert( - 'object' === $.type(editorConfiguration), - 'Invalid parameter "editorConfiguration"', - 1485712399 - ); - assert( - 'object' === $.type(editorHtml), - 'Invalid parameter "editorHtml"', - 1485712400 - ); - assert( - getUtility().isNonEmptyString(editorConfiguration['label']), - 'Invalid configuration "label"', - 1485712401 - ); - assert( - getUtility().isNonEmptyString(editorConfiguration['propertyPath']), - 'Invalid configuration "propertyPath"', - 1485712402 - ); - assert( - 'array' === $.type(editorConfiguration['selectOptions']), - 'Invalid configuration "selectOptions"', - 1485712403 - ); - - propertyPath = getFormEditorApp().buildPropertyPath( - editorConfiguration['propertyPath'], - collectionElementIdentifier, - collectionName - ); - - getHelper() - .getTemplatePropertyDomElement('label', editorHtml) - .append(editorConfiguration['label']); - - selectElement = getHelper() - .getTemplatePropertyDomElement('selectOptions', editorHtml); - - propertyData = getCurrentlySelectedFormElement().get(propertyPath); - - for (var i = 0, len1 = editorConfiguration['selectOptions'].length; i < len1; ++i) { - var option, value; - - option = null; - for (var propertyDataKey in propertyData) { - if (!propertyData.hasOwnProperty(propertyDataKey)) { - continue; - } - if (editorConfiguration['selectOptions'][i]['value'] === propertyData[propertyDataKey]) { - option = new Option(editorConfiguration['selectOptions'][i]['label'], i, false, true); - break; - } - } - - if (!option) { - option = new Option(editorConfiguration['selectOptions'][i]['label'], i); - } - - $(option).data({value: editorConfiguration['selectOptions'][i]['value']}); - - selectElement.append(option); - } - - selectElement.on('change', function() { - var selectValues = []; - $('option:selected', $(this)).each(function(i) { - selectValues.push($(this).data('value')); - }); - - getCurrentlySelectedFormElement().set(propertyPath, selectValues); - }); - }; - - /** - * @public - * - * @param object editorConfiguration - * @param object editorHtml - * @param string collectionElementIdentifier - * @param string collectionName - * @return void - * @throws 1489528242 - * @throws 1489528243 - * @throws 1489528244 - * @throws 1489528245 - * @throws 1489528246 - * @throws 1489528247 - */ - function renderGridColumnViewPortConfigurationEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) { - var editorControlsWrapper, initNumbersOfColumnsField, numbersOfColumnsTemplate, selectElement, - viewportButtonTemplate; - assert( - 'object' === $.type(editorConfiguration), - 'Invalid parameter "editorConfiguration"', - 1489528242 - ); - assert( - 'object' === $.type(editorHtml), - 'Invalid parameter "editorHtml"', - 1489528243 - ); - assert( - getUtility().isNonEmptyString(editorConfiguration['label']), - 'Invalid configuration "label"', - 1489528244 - ); - assert( - 'array' === $.type(editorConfiguration['configurationOptions']['viewPorts']), - 'Invalid configurationOptions "viewPorts"', - 1489528245 - ); - assert( - !getUtility().isUndefinedOrNull(editorConfiguration['configurationOptions']['numbersOfColumnsToUse']['label']), - 'Invalid configurationOptions "numbersOfColumnsToUse"', - 1489528246 - ); - assert( - !getUtility().isUndefinedOrNull(editorConfiguration['configurationOptions']['numbersOfColumnsToUse']['propertyPath']), - 'Invalid configuration "selectOptions"', - 1489528247 - ); - - if (!getFormElementDefinition(getCurrentlySelectedFormElement().get('__parentRenderable'), '_isGridRowFormElement')) { - editorHtml.remove(); - return; - } - - getHelper() - .getTemplatePropertyDomElement('label', editorHtml) - .append(editorConfiguration['label']); - - - viewportButtonTemplate = $(getHelper() - .getDomElementDataIdentifierSelector('viewportButton'), $(editorHtml)) - .clone(); - - $(getHelper() - .getDomElementDataIdentifierSelector('viewportButton'), $(editorHtml)) - .remove(); - - numbersOfColumnsTemplate = getHelper() - .getTemplatePropertyDomElement('numbersOfColumnsToUse', $(editorHtml)) - .clone(); - - getHelper() - .getTemplatePropertyDomElement('numbersOfColumnsToUse', $(editorHtml)) - .remove(); - - editorControlsWrapper = _getEditorControlsWrapperDomElement(editorHtml); - - initNumbersOfColumnsField = function(element) { - var numbersOfColumnsTemplateClone, propertyPath; - - getHelper().getTemplatePropertyDomElement('numbersOfColumnsToUse', $(editorHtml)) - .off() - .empty() - .remove(); - - numbersOfColumnsTemplateClone = $(numbersOfColumnsTemplate).clone(true, true); - _getEditorWrapperDomElement(editorHtml).after(numbersOfColumnsTemplateClone); - - $('input', numbersOfColumnsTemplateClone).focus(); - - getHelper() - .getTemplatePropertyDomElement('numbersOfColumnsToUse-label', numbersOfColumnsTemplateClone) - .append( - editorConfiguration['configurationOptions']['numbersOfColumnsToUse']['label'] - .replace('{@viewPortLabel}', element.data('viewPortLabel')) - ); - - getHelper() - .getTemplatePropertyDomElement('numbersOfColumnsToUse-fieldExplanationText', numbersOfColumnsTemplateClone) - .append(editorConfiguration['configurationOptions']['numbersOfColumnsToUse']['fieldExplanationText']); - - propertyPath = editorConfiguration['configurationOptions']['numbersOfColumnsToUse']['propertyPath'] - .replace('{@viewPortIdentifier}', element.data('viewPortIdentifier')); - - getHelper() - .getTemplatePropertyDomElement('numbersOfColumnsToUse-propertyPath', numbersOfColumnsTemplateClone) - .val(getCurrentlySelectedFormElement().get(propertyPath)); - - getHelper().getTemplatePropertyDomElement('numbersOfColumnsToUse-propertyPath', numbersOfColumnsTemplateClone).on('keyup paste change', function() { - var that = $(this); - if (!$.isNumeric(that.val())) { - that.val(''); - } - getCurrentlySelectedFormElement().set(propertyPath, that.val()); - }); - }; - - for (var i = 0, len = editorConfiguration['configurationOptions']['viewPorts'].length; i < len; ++i) { - var numbersOfColumnsTemplateClone, viewportButtonTemplateClone, viewPortIdentifier, - viewPortLabel; - - viewPortIdentifier = editorConfiguration['configurationOptions']['viewPorts'][i]['viewPortIdentifier']; - viewPortLabel = editorConfiguration['configurationOptions']['viewPorts'][i]['label']; - - viewportButtonTemplateClone = $(viewportButtonTemplate).clone(true, true); - viewportButtonTemplateClone.text(viewPortIdentifier); - viewportButtonTemplateClone.data('viewPortIdentifier', viewPortIdentifier); - viewportButtonTemplateClone.data('viewPortLabel', viewPortLabel); - viewportButtonTemplateClone.attr('title', viewPortLabel); - editorControlsWrapper.append(viewportButtonTemplateClone); - - if (i === (len - 1)) { - numbersOfColumnsTemplateClone = $(numbersOfColumnsTemplate).clone(true, true); - _getEditorWrapperDomElement(editorHtml).after(numbersOfColumnsTemplateClone); - initNumbersOfColumnsField(viewportButtonTemplateClone); - viewportButtonTemplateClone.addClass(getHelper().getDomElementClassName('active')); - } - - $('button', editorControlsWrapper).on('click', function() { - var that = $(this); - - $('button', editorControlsWrapper).removeClass(getHelper().getDomElementClassName('active')); - that.addClass(getHelper().getDomElementClassName('active')); - - initNumbersOfColumnsField(that); - }); - } - }; - - /** - * @public - * - * @param object editorConfiguration - * @param object editorHtml - * @param string collectionElementIdentifier - * @param string collectionName - * @return void - * @throws 1475419226 - * @throws 1475419227 - * @throws 1475419228 - * @throws 1475419229 - * @throws 1475419230 - * @throws 1475419231 - * @throws 1475419232 - */ - function renderPropertyGridEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) { - var addRowTemplate, gridColumns, defaultValue, multiSelection, propertyData, propertyPathPrefix, - rowItemTemplate, setData, useLabelAsFallbackValue; - assert( - 'object' === $.type(editorConfiguration), - 'Invalid parameter "editorConfiguration"', - 1475419226 - ); - assert( - 'object' === $.type(editorHtml), - 'Invalid parameter "editorHtml"', - 1475419227 - ); - assert( - 'boolean' === $.type(editorConfiguration['enableAddRow']), - 'Invalid configuration "enableAddRow"', - 1475419228 - ); - assert( - 'boolean' === $.type(editorConfiguration['enableDeleteRow']), - 'Invalid configuration "enableDeleteRow"', - 1475419230 - ); - assert( - 'boolean' === $.type(editorConfiguration['isSortable']), - 'Invalid configuration "isSortable"', - 1475419229 - ); - assert( - getUtility().isNonEmptyString(editorConfiguration['propertyPath']), - 'Invalid configuration "propertyPath"', - 1475419231 - ); - assert( - getUtility().isNonEmptyString(editorConfiguration['label']), - 'Invalid configuration "label"', - 1475419232 - ); - - getHelper().getTemplatePropertyDomElement('label', editorHtml) - .append(editorConfiguration['label']); - if (getUtility().isNonEmptyString(editorConfiguration['fieldExplanationText'])) { - getHelper() - .getTemplatePropertyDomElement('fieldExplanationText', editorHtml) - .text(editorConfiguration['fieldExplanationText']); - } else { - getHelper() - .getTemplatePropertyDomElement('fieldExplanationText', editorHtml) - .remove(); - } - - propertyPathPrefix = getFormEditorApp().buildPropertyPath( - undefined, - collectionElementIdentifier, - collectionName, - undefined, - true - ); - if (getUtility().isNonEmptyString(propertyPathPrefix)) { - propertyPathPrefix = propertyPathPrefix + '.'; - } - - if (getUtility().isUndefinedOrNull(editorConfiguration['useLabelAsFallbackValue'])) { - useLabelAsFallbackValue = true; - } else { - useLabelAsFallbackValue = editorConfiguration['useLabelAsFallbackValue']; - } - - gridColumns = [ - {name: 'label', title: 'Label'}, - {name: 'value', title: 'Value'}, - {name: 'selected', title: 'Selected'}, - ]; - if (getUtility().isNonEmptyArray(editorConfiguration['gridColumns'])) { - gridColumns = editorConfiguration['gridColumns']; - } - var orderedGridColumnNames = gridColumns.map(function(item) { - return item.name; - }); - var orderedGridColumnTitles = gridColumns.map(function(item) { - return item.title || null; - }); - - $([ - getHelper().getDomElementDataIdentifierSelector('propertyGridEditorHeaderRow'), - getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem'), - getHelper().getDomElementDataIdentifierSelector('propertyGridEditorAddRowItem'), - ].join(','), $(editorHtml)).each(function (i, row) { - var $columns = $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorColumn'), row); - var $columnsAfter = $columns.last().nextAll(); - var columnsByName = {}; - - // Collect columns by names, skip undesired columns - $columns - .detach() - .each(function(i, element) { - var $column = $(element); - var columnName = $column.data('column'); - - if (!orderedGridColumnNames.includes(columnName)) { - return; - } - - columnsByName[columnName] = $column; - }); - - // Insert columns in desired order - orderedGridColumnNames.forEach(function(columnName, i) { - var $column = columnsByName[columnName]; - - if ($column.is('th')) { - $column.append(orderedGridColumnTitles[i]); - } - - $column.appendTo(row); - }); - - // Insert remaining columns - $columnsAfter.appendTo(row); - }); - - if (getUtility().isUndefinedOrNull(editorConfiguration['multiSelection'])) { - multiSelection = false; - } else { - multiSelection = !!editorConfiguration['multiSelection']; - } - - rowItemTemplate = $( - getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem'), - $(editorHtml) - ).clone(); - $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem'), $(editorHtml)).remove(); - - if (!!editorConfiguration['enableDeleteRow']) { - $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorDeleteRow'), - $(rowItemTemplate) - ).on('click', function() { - $(this) - .closest(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem')) - .off() - .empty() - .remove(); - - _setPropertyGridData( - $(editorHtml), - multiSelection, - editorConfiguration['propertyPath'], - propertyPathPrefix - ); - }); - } else { - $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorDeleteRow'), $(rowItemTemplate)) - .parent() - .off() - .empty(); - } - - if (!!editorConfiguration['isSortable']) { - editorHtml.get(0).querySelectorAll(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorContainer') + ' tbody').forEach(function (sortableList) { - new Sortable(sortableList, { - group: getHelper().getDomElementDataAttributeValue('propertyGridEditorContainer'), - handle: getHelper().getDomElementDataIdentifierSelector('propertyGridEditorSortRow'), - draggable: getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem'), - pull: 'clone', - swapThreshold: 0.6, - dragClass: 'form-sortable-drag', - ghostClass: 'form-sortable-ghost', - onUpdate: function() { - _setPropertyGridData( - $(editorHtml), - multiSelection, - editorConfiguration['propertyPath'], - propertyPathPrefix - ); - } - }); - }); - } else { - $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorSortRow'), $(rowItemTemplate)) - .parent() - .off() - .empty(); - } - - $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorSelectValue'), - $(rowItemTemplate) - ).on('change', function() { - if (!multiSelection) { - $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorSelectValue') + ':checked', $(editorHtml)) - .not($(this)) - .prop('checked', false); - } - _setPropertyGridData( - $(editorHtml), - multiSelection, - editorConfiguration['propertyPath'], - propertyPathPrefix - ); - }); - - $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorLabel') + ',' + - getHelper().getDomElementDataIdentifierSelector('propertyGridEditorValue'), - $(rowItemTemplate) - ).on('keyup paste', function() { - _setPropertyGridData( - $(editorHtml), - multiSelection, - editorConfiguration['propertyPath'], - propertyPathPrefix - ); - }); - - if (useLabelAsFallbackValue) { - $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorLabel'), - $(rowItemTemplate) - ).on('focusout', function() { - if ('' === $(this) - .closest(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem')) - .find(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorValue')) - .val() - ) { - $(this) - .closest(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem')) - .find(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorValue')) - .val($(this).val()); - } - }); - } - - if (!!editorConfiguration['enableAddRow']) { - addRowTemplate = $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorAddRowItem'), $(editorHtml)).clone(); - $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorAddRowItem'), $(editorHtml)).remove(); - - $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorAddRow'), $(addRowTemplate)).on('click', function() { - $(this) - .closest(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorAddRowItem')) - .before($(rowItemTemplate).clone(true, true)); - - _setPropertyGridData( - $(editorHtml), - multiSelection, - editorConfiguration['propertyPath'], - propertyPathPrefix - ); - }); - $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorContainer'), $(editorHtml)) - .prepend($(addRowTemplate).clone(true, true)); - } else { - $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorAddRowItem'), $(editorHtml)).remove(); - } - - defaultValue = {}; - if (multiSelection) { - if (!getUtility().isUndefinedOrNull(getCurrentlySelectedFormElement().get(propertyPathPrefix + 'defaultValue'))) { - defaultValue = getCurrentlySelectedFormElement().get(propertyPathPrefix + 'defaultValue'); - } - } else { - if (!getUtility().isUndefinedOrNull(getCurrentlySelectedFormElement().get(propertyPathPrefix + 'defaultValue'))) { - defaultValue = {0: getCurrentlySelectedFormElement().get(propertyPathPrefix + 'defaultValue')}; - } - } - propertyData = getCurrentlySelectedFormElement().get(propertyPathPrefix + editorConfiguration['propertyPath']) || {}; - - setData = function(label, value) { - var isPreselected, newRowTemplate; - - isPreselected = false; - newRowTemplate = $(rowItemTemplate).clone(true, true); - - for (var defaultValueKey in defaultValue) { - if (!defaultValue.hasOwnProperty(defaultValueKey)) { - continue; - } - if (defaultValue[defaultValueKey] === value) { - isPreselected = true; - break; - } - } - - $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorLabel'), $(newRowTemplate)).val(label); - $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorValue'), $(newRowTemplate)).val(value); - - if (isPreselected) { - $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorSelectValue'), $(newRowTemplate)) - .prop('checked', true); - } - - if (!!editorConfiguration['enableAddRow']) { - $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorAddRowItem'), $(editorHtml)) - .before($(newRowTemplate)); - } else { - $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorContainer'), $(editorHtml)) - .prepend($(newRowTemplate)); - } - }; - - if ('object' === $.type(propertyData)) { - for (var propertyDataKey in propertyData) { - if (!propertyData.hasOwnProperty(propertyDataKey)) { - continue; - } - setData(propertyData[propertyDataKey], propertyDataKey); - } - } else if ('array' === $.type(propertyData)) { - for (var propertyDataKey in propertyData) { - if (!propertyData.hasOwnProperty(propertyDataKey)) { - continue; - } - if (getUtility().isUndefinedOrNull(propertyData[propertyDataKey]['_label'])) { - setData(propertyData[propertyDataKey], propertyDataKey); - } else { - setData(propertyData[propertyDataKey]['_label'], propertyData[propertyDataKey]['_value']); - } - } - } - - _validateCollectionElement(propertyPathPrefix + editorConfiguration['propertyPath'], editorHtml); - }; - - /** - * @public - * - * @param object editorConfiguration - * @param object editorHtml - * @param string collectionElementIdentifier - * @param string collectionName - * @return void - * @publish view/inspector/collectionElement/new/selected - * @publish view/inspector/removeCollectionElement/perform - * @throws 1475417093 - * @throws 1475417094 - * @throws 1475417095 - * @throws 1475417096 - */ - function renderRequiredValidatorEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) { - var propertyData, propertyPath, propertyValue, showValidationErrorMessage, validationErrorMessage, validationErrorMessagePropertyPath, validationErrorMessageTemplate, validationErrorMessageTemplateClone, validatorIdentifier; - assert( - 'object' === $.type(editorConfiguration), - 'Invalid parameter "editorConfiguration"', - 1475417093 - ); - assert( - 'object' === $.type(editorHtml), - 'Invalid parameter "editorHtml"', - 1475417094 - ); - assert( - getUtility().isNonEmptyString(editorConfiguration['validatorIdentifier']), - 'Invalid configuration "validatorIdentifier"', - 1475417095 - ); - assert( - getUtility().isNonEmptyString(editorConfiguration['label']), - 'Invalid configuration "label"', - 1475417096 - ); - - validatorIdentifier = editorConfiguration['validatorIdentifier']; - getHelper().getTemplatePropertyDomElement('label', editorHtml).append(editorConfiguration['label']); - - if (getUtility().isNonEmptyString(editorConfiguration['propertyPath'])) { - propertyPath = getFormEditorApp() - .buildPropertyPath(editorConfiguration['propertyPath'], collectionElementIdentifier, collectionName); - } - if (getUtility().isNonEmptyString(editorConfiguration['propertyValue'])) { - propertyValue = editorConfiguration['propertyValue']; - } else { - propertyValue = ''; - } - - validationErrorMessagePropertyPath = getFormEditorApp() - .buildPropertyPath(editorConfiguration['configurationOptions']['validationErrorMessage']['propertyPath']); - - validationErrorMessageTemplate = getHelper() - .getTemplatePropertyDomElement('validationErrorMessage', $(editorHtml)) - .clone(); - - getHelper() - .getTemplatePropertyDomElement('validationErrorMessage', $(editorHtml)) - .remove(); - - showValidationErrorMessage = function() { - validationErrorMessageTemplateClone = $(validationErrorMessageTemplate).clone(true, true); - _getEditorWrapperDomElement(editorHtml).after(validationErrorMessageTemplateClone); - - getHelper() - .getTemplatePropertyDomElement('validationErrorMessage-label', validationErrorMessageTemplateClone) - .append(editorConfiguration['configurationOptions']['validationErrorMessage']['label']); - - getHelper() - .getTemplatePropertyDomElement('validationErrorMessage-fieldExplanationText', validationErrorMessageTemplateClone) - .append(editorConfiguration['configurationOptions']['validationErrorMessage']['fieldExplanationText']); - - propertyData = getCurrentlySelectedFormElement().get(validationErrorMessagePropertyPath); - if (getUtility().isUndefinedOrNull(propertyData)) { - propertyData = []; - } - - validationErrorMessage = _getFirstAvailableValidationErrorMessage( - editorConfiguration['configurationOptions']['validationErrorMessage']['errorCodes'], - propertyData - ); - if (!getUtility().isUndefinedOrNull(validationErrorMessage)) { - getHelper() - .getTemplatePropertyDomElement('validationErrorMessage-propertyPath', validationErrorMessageTemplateClone) - .val(validationErrorMessage); - } - - getHelper().getTemplatePropertyDomElement('validationErrorMessage-propertyPath', validationErrorMessageTemplateClone).on('keyup paste', function() { - propertyData = getCurrentlySelectedFormElement().get(validationErrorMessagePropertyPath); - if (getUtility().isUndefinedOrNull(propertyData)) { - propertyData = []; - } - - getCurrentlySelectedFormElement().set(validationErrorMessagePropertyPath, _renewValidationErrorMessages( - editorConfiguration['configurationOptions']['validationErrorMessage']['errorCodes'], - propertyData, - $(this).val() - )); - }); - } - - if (-1 !== getFormEditorApp().getIndexFromPropertyCollectionElement(validatorIdentifier, 'validators')) { - $('input[type="checkbox"]', $(editorHtml)).prop('checked', true); - if (getUtility().isNonEmptyString(propertyPath)) { - getCurrentlySelectedFormElement().set(propertyPath, propertyValue); - } - showValidationErrorMessage(); - } - - $('input[type="checkbox"]', $(editorHtml)).on('change', function() { - getHelper().getTemplatePropertyDomElement('validationErrorMessage', $(editorHtml)) - .off() - .empty() - .remove(); - - if ($(this).is(":checked")) { - showValidationErrorMessage(); - getPublisherSubscriber().publish( - 'view/inspector/collectionElement/new/selected', - [validatorIdentifier, 'validators'] - ); - - if (getUtility().isNonEmptyString(propertyPath)) { - getCurrentlySelectedFormElement().set(propertyPath, propertyValue); - } - } else { - getPublisherSubscriber().publish( - 'view/inspector/removeCollectionElement/perform', - [validatorIdentifier, 'validators'] - ); - if (getUtility().isNonEmptyString(propertyPath)) { - getCurrentlySelectedFormElement().unset(propertyPath); - } - - propertyData = getCurrentlySelectedFormElement().get(validationErrorMessagePropertyPath); - if (getUtility().isUndefinedOrNull(propertyData)) { - propertyData = []; - } - - getCurrentlySelectedFormElement().set(validationErrorMessagePropertyPath, _renewValidationErrorMessages( - editorConfiguration['configurationOptions']['validationErrorMessage']['errorCodes'], - propertyData, - '' - )); - } - }); - }; - - /** - * @public - * - * @param object editorConfiguration - * @param object editorHtml - * @param string collectionElementIdentifier - * @param string collectionName - * @return void - * @throws 1476218671 - * @throws 1476218672 - * @throws 1476218673 - * @throws 1476218674 - */ - function renderCheckboxEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) { - var propertyData, propertyPath; - assert( - 'object' === $.type(editorConfiguration), - 'Invalid parameter "editorConfiguration"', - 1476218671 - ); - assert( - 'object' === $.type(editorHtml), - 'Invalid parameter "editorHtml"', - 1476218672 - ); - assert( - getUtility().isNonEmptyString(editorConfiguration['label']), - 'Invalid configuration "label"', - 1476218673 - ); - assert( - getUtility().isNonEmptyString(editorConfiguration['propertyPath']), - 'Invalid configuration "propertyPath"', - 1476218674 - ); - - getHelper() - .getTemplatePropertyDomElement('label', editorHtml) - .append(editorConfiguration['label']); - if (getUtility().isNonEmptyString(editorConfiguration['fieldExplanationText'])) { - getHelper() - .getTemplatePropertyDomElement('fieldExplanationText', editorHtml) - .text(editorConfiguration['fieldExplanationText']); - } else { - getHelper() - .getTemplatePropertyDomElement('fieldExplanationText', editorHtml) - .remove(); - } - - propertyPath = getFormEditorApp() - .buildPropertyPath(editorConfiguration['propertyPath'], collectionElementIdentifier, collectionName); - propertyData = getCurrentlySelectedFormElement().get(propertyPath); - - if ( - ('boolean' === $.type(propertyData) && propertyData) - || propertyData === 'true' - || propertyData === 1 - || propertyData === "1" - ) { - $('input[type="checkbox"]', $(editorHtml)).prop('checked', true); - } - - $('input[type="checkbox"]', $(editorHtml)).on('change', function() { - if ($(this).is(":checked")) { - getCurrentlySelectedFormElement().set(propertyPath, true); - } else { - getCurrentlySelectedFormElement().set(propertyPath, false); - } - }); - }; - - /** - * @public - * - * @param object editorConfiguration - * @param object editorHtml - * @param string collectionElementIdentifier - * @param string collectionName - * @return void - * @throws 1475412567 - * @throws 1475412568 - * @throws 1475416098 - * @throws 1475416099 - */ - function renderTextareaEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) { - var propertyPath, propertyData; - assert( - 'object' === $.type(editorConfiguration), - 'Invalid parameter "editorConfiguration"', - 1475412567 - ); - assert( - 'object' === $.type(editorHtml), - 'Invalid parameter "editorHtml"', - 1475412568 - ); - assert( - getUtility().isNonEmptyString(editorConfiguration['propertyPath']), - 'Invalid configuration "propertyPath"', - 1475416098 - ); - assert( - getUtility().isNonEmptyString(editorConfiguration['label']), - 'Invalid configuration "label"', - 1475416099 - ); - - propertyPath = getFormEditorApp() - .buildPropertyPath(editorConfiguration['propertyPath'], collectionElementIdentifier, collectionName); - - getHelper() - .getTemplatePropertyDomElement('label', editorHtml).append(editorConfiguration['label']); - - if (getUtility().isNonEmptyString(editorConfiguration['fieldExplanationText'])) { - getHelper() - .getTemplatePropertyDomElement('fieldExplanationText', editorHtml) - .text(editorConfiguration['fieldExplanationText']); - } else { - getHelper() - .getTemplatePropertyDomElement('fieldExplanationText', editorHtml) - .remove(); - } - - propertyData = getCurrentlySelectedFormElement().get(propertyPath); - $('textarea', $(editorHtml)).val(propertyData); - - $('textarea', $(editorHtml)).on('keyup paste', function() { - getCurrentlySelectedFormElement().set(propertyPath, $(this).val()); - }); - }; - - /** - * @public - * - * @param object editorConfiguration - * @param object editorHtml - * @param string collectionElementIdentifier - * @param string collectionName - * @return void - * @throws 1477300587 - * @throws 1477300588 - * @throws 1477300589 - * @throws 1477300590 - * @throws 1477318981 - * @throws 1477319859 - */ - function renderTypo3WinBrowserEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) { - var propertyPath, propertyData; - assert( - 'object' === $.type(editorConfiguration), - 'Invalid parameter "editorConfiguration"', - 1477300587 - ); - assert( - 'object' === $.type(editorHtml), - 'Invalid parameter "editorHtml"', - 1477300588 - ); - assert( - getUtility().isNonEmptyString(editorConfiguration['label']), - 'Invalid configuration "label"', - 1477300589 - ); - assert( - getUtility().isNonEmptyString(editorConfiguration['buttonLabel']), - 'Invalid configuration "buttonLabel"', - 1477318981 - ); - assert( - getUtility().isNonEmptyString(editorConfiguration['propertyPath']), - 'Invalid configuration "propertyPath"', - 1477300590 - ); - - getHelper() - .getTemplatePropertyDomElement('label', editorHtml) - .append(editorConfiguration['label']); - getHelper() - .getTemplatePropertyDomElement('buttonLabel', editorHtml) - .append(editorConfiguration['buttonLabel']); - - if (getUtility().isNonEmptyString(editorConfiguration['fieldExplanationText'])) { - getHelper() - .getTemplatePropertyDomElement('fieldExplanationText', editorHtml) - .text(editorConfiguration['fieldExplanationText']); - } else { - getHelper() - .getTemplatePropertyDomElement('fieldExplanationText', editorHtml) - .remove(); - } - - $('form', $(editorHtml)).prop('name', editorConfiguration['propertyPath']); - - Icons.getIcon(editorConfiguration['iconIdentifier'], Icons.sizes.small).then(function(icon) { - getHelper().getTemplatePropertyDomElement('image', editorHtml).append($(icon)); - }); - - getHelper().getTemplatePropertyDomElement('onclick', editorHtml).on('click', function() { - var insertTarget, randomIdentifier; - - randomIdentifier = Math.floor((Math.random() * 100000) + 1); - insertTarget = $(this) - .closest(getHelper().getDomElementDataIdentifierSelector('editorControlsWrapper')) - .find(getHelper().getDomElementDataAttribute('contentElementSelectorTarget', 'bracesWithKey')); - - insertTarget.attr(getHelper().getDomElementDataAttribute('contentElementSelectorTarget'), randomIdentifier); - _openTypo3WinBrowser('db', randomIdentifier + '|||' + editorConfiguration['browsableType']); - }); - - _listenOnElementBrowser(); - - propertyPath = getFormEditorApp().buildPropertyPath(editorConfiguration['propertyPath'], collectionElementIdentifier, collectionName); - propertyData = getCurrentlySelectedFormElement().get(propertyPath); - - _validateCollectionElement(propertyPath, editorHtml); - getHelper() - .getTemplatePropertyDomElement('propertyPath', editorHtml) - .val(propertyData); - - getHelper().getTemplatePropertyDomElement('propertyPath', editorHtml).on('keyup paste', function() { - getCurrentlySelectedFormElement().set(propertyPath, $(this).val()); - _validateCollectionElement(propertyPath, editorHtml); - }); - }; - - /** - * @public - * - * @param object editorConfiguration - * @param object editorHtml - * @param string collectionElementIdentifier - * @param string collectionName - * @return void - * @throws 1475412563 - * @throws 1475412564 - */ - function renderRemoveElementEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) { - assert('object' === $.type(editorConfiguration), 'Invalid parameter "editorConfiguration"', 1475412563); - assert('object' === $.type(editorHtml), 'Invalid parameter "editorHtml"', 1475412564); - - if (getUtility().isUndefinedOrNull(collectionElementIdentifier)) { - - $('button', $(editorHtml)) - .addClass( - getHelper().getDomElementClassName('buttonFormElementRemove') + ' ' + - getHelper().getDomElementClassName('buttonFormEditor') - ); - } else { - $('button', $(editorHtml)).addClass( - getHelper().getDomElementClassName('buttonCollectionElementRemove') - ); - } - - $('button', $(editorHtml)).on('click', function(e) { - if (getUtility().isUndefinedOrNull(collectionElementIdentifier)) { - getViewModel().showRemoveFormElementModal(); - } else { - getViewModel().showRemoveCollectionElementModal(collectionElementIdentifier, collectionName); - } - }); - }; - - /** - * @public - * - * @param object editorConfiguration - * @param object editorHtml - * @param string propertyPath - * @return void - * @throws 1484574704 - * @throws 1484574705 - * @throws 1484574706 - */ - function renderFormElementSelectorEditorAddition(editorConfiguration, editorHtml, propertyPath) { - var nonCompositeNonToplevelFormElements, formElementSelectorControlsWrapper, - formElementSelectorSplitButtonListContainer, itemTemplate; - - assert( - 'object' === $.type(editorConfiguration), - 'Invalid parameter "editorConfiguration"', - 1484574704 - ); - assert( - 'object' === $.type(editorHtml), - 'Invalid parameter "editorHtml"', - 1484574705 - ); - assert( - getUtility().isNonEmptyString(propertyPath), - 'Invalid parameter "propertyPath"', - 1484574706 - ); - - formElementSelectorControlsWrapper = $( - getHelper().getDomElementDataIdentifierSelector('formElementSelectorControlsWrapper'), editorHtml - ); - - if (editorConfiguration['enableFormelementSelectionButton'] === true) { - if (formElementSelectorControlsWrapper.length === 0) { - return; - } - - formElementSelectorSplitButtonListContainer = $( - getHelper().getDomElementDataIdentifierSelector('formElementSelectorSplitButtonListContainer'), editorHtml - ); - - formElementSelectorSplitButtonListContainer.off().empty(); - nonCompositeNonToplevelFormElements = getFormEditorApp().getNonCompositeNonToplevelFormElements(); - - if (nonCompositeNonToplevelFormElements.length === 0) { - Icons.getIcon( - getHelper().getDomElementDataAttributeValue('iconNotAvailable'), - Icons.sizes.small, - null, - Icons.states.default - ).then(function(icon) { - itemTemplate = $('<li data-no-sorting>' - + '<a href="#"></a>' - + '</li>'); - - itemTemplate - .append($(icon)) - .append(' ' + getFormElementDefinition(getRootFormElement(), 'inspectorEditorFormElementSelectorNoElements')); - formElementSelectorSplitButtonListContainer.append(itemTemplate); - }); - } else { - $.each(nonCompositeNonToplevelFormElements, function(i, nonCompositeNonToplevelFormElement) { - Icons.getIcon( - getFormElementDefinition(nonCompositeNonToplevelFormElement, 'iconIdentifier'), - Icons.sizes.small, - null, - Icons.states.default - ).then(function(icon) { - itemTemplate = $('<li data-no-sorting>' - + '<a href="#" class="dropdown-item" data-formelement-identifier="' + nonCompositeNonToplevelFormElement.get('identifier') + '">' - + '</a>' - + '</li>'); - - $('[data-formelement-identifier="' + nonCompositeNonToplevelFormElement.get('identifier') + '"]', itemTemplate) - .append($(icon)) - .append(' ' + nonCompositeNonToplevelFormElement.get('label')); - - $('a', itemTemplate).on('click', function() { - var propertyData; - - propertyData = getCurrentlySelectedFormElement().get(propertyPath) || ''; - - if (propertyData.length === 0) { - propertyData = '{' + $(this).attr('data-formelement-identifier') + '}'; - } else { - propertyData = propertyData + ' ' + '{' + $(this).attr('data-formelement-identifier') + '}'; - } - - getCurrentlySelectedFormElement().set(propertyPath, propertyData); - getHelper().getTemplatePropertyDomElement('propertyPath', editorHtml).val(propertyData); - _validateCollectionElement(propertyPath, editorHtml); - }); - - formElementSelectorSplitButtonListContainer.append(itemTemplate); - }); - }); - } - } else { - $(getHelper().getDomElementDataIdentifierSelector('editorControlsInputGroup'), editorHtml) - .removeClass(getHelper().getDomElementClassName('inspectorInputGroup')); - formElementSelectorControlsWrapper.off().empty().remove(); - } - } - - /** - * @public - * - * @param object - * @return object - * @throws 1478967319 - */ - function buildTitleByFormElement(formElement) { - var label; - if (getUtility().isUndefinedOrNull(formElement)) { - formElement = getCurrentlySelectedFormElement(); - } - assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1478967319); - - if (formElement.get('type') === 'Form') { - label = formElement.get('type'); - } else { - label = getFormElementDefinition(formElement, 'label') - ? getFormElementDefinition(formElement, 'label') - : formElement.get('identifier'); - } - - return $('<span></span>').text(label); - }; - - /** - * @public - * - * @param object - * @param object - * @return this - */ - function bootstrap(formEditorApp, configuration) { - _formEditorApp = formEditorApp; - _configuration = $.extend(true, _defaultConfiguration, configuration || {}); - _helperSetup(); - return this; - }; - - /** - * Publish the public methods. - * Implements the "Revealing Module Pattern". - */ - return { - bootstrap: bootstrap, - buildTitleByFormElement: buildTitleByFormElement, - getCollectionElementDomElement: getCollectionElementDomElement, - getFinishersContainerDomElement: getFinishersContainerDomElement, - getInspectorDomElement: getInspectorDomElement, - getValidatorsContainerDomElement: getValidatorsContainerDomElement, - renderCheckboxEditor: renderCheckboxEditor, - renderCollectionElementEditors: renderCollectionElementEditors, - renderCollectionElementHeaderEditor: renderCollectionElementHeaderEditor, - renderFileMaxSizeEditor: renderMaximumFileSizeEditor, - renderCollectionElementSelectionEditor: renderCollectionElementSelectionEditor, - renderEditors: renderEditors, - renderFormElementHeaderEditor: renderFormElementHeaderEditor, - renderFormElementSelectorEditorAddition: renderFormElementSelectorEditorAddition, - renderPropertyGridEditor: renderPropertyGridEditor, - renderRemoveElementEditor: renderRemoveElementEditor, - renderRequiredValidatorEditor: renderRequiredValidatorEditor, - renderCountrySelectEditor: renderCountrySelectEditor, - renderSingleSelectEditor: renderSingleSelectEditor, - renderMultiSelectEditor: renderMultiSelectEditor, - renderTextareaEditor: renderTextareaEditor, - renderTextEditor: renderTextEditor, - renderTypo3WinBrowserEditor: renderTypo3WinBrowserEditor - }; - })($, Helper, Icons, Notification); -} +import $ from"jquery";import*as Helper from"@typo3/form/backend/form-editor/helper.js";import Icons from"@typo3/backend/icons.js";import Modal from"@typo3/backend/modal.js";import{MessageUtility}from"@typo3/backend/utility/message-utility.js";import Sortable from"sortablejs";const defaultConfiguration={domElementClassNames:{buttonFormElementRemove:"t3-form-remove-element-button",collectionElement:"t3-form-collection-element",finisherEditorPrefix:"t3-form-inspector-finishers-editor-",inspectorEditor:"form-editor",inspectorInputGroup:"input-group",validatorEditorPrefix:"t3-form-inspector-validators-editor-"},domElementDataAttributeNames:{contentElementSelectorTarget:"data-insert-target",finisher:"data-finisher-identifier",validator:"data-validator-identifier",randomId:"data-random-id",randomIdTarget:"data-random-id-attribute",randomIdIndex:"data-random-id-number",maximumFileSize:"data-maximumFileSize"},domElementDataAttributeValues:{collapse:"actions-view-table-expand",editorControlsInputGroup:"inspectorEditorControlsGroup",editorWrapper:"editorWrapper",editorControlsWrapper:"inspectorEditorControlsWrapper",formElementHeaderEditor:"inspectorFormElementHeaderEditor",formElementSelectorControlsWrapper:"inspectorEditorFormElementSelectorControlsWrapper",formElementSelectorSplitButtonContainer:"inspectorEditorFormElementSelectorSplitButtonContainer",formElementSelectorSplitButtonListContainer:"inspectorEditorFormElementSelectorSplitButtonListContainer",iconNotAvailable:"actions-close",inspector:"inspector","Inspector-CheckboxEditor":"Inspector-CheckboxEditor","Inspector-CollectionElementHeaderEditor":"Inspector-CollectionElementHeaderEditor","Inspector-FinishersEditor":"Inspector-FinishersEditor","Inspector-FormElementHeaderEditor":"Inspector-FormElementHeaderEditor","Inspector-PropertyGridEditor":"Inspector-PropertyGridEditor","Inspector-RemoveElementEditor":"Inspector-RemoveElementEditor","Inspector-RequiredValidatorEditor":"Inspector-RequiredValidatorEditor","Inspector-SingleSelectEditor":"Inspector-SingleSelectEditor","Inspector-MultiSelectEditor":"Inspector-MultiSelectEditor","Inspector-GridColumnViewPortConfigurationEditor":"Inspector-GridColumnViewPortConfigurationEditor","Inspector-TextareaEditor":"Inspector-TextareaEditor","Inspector-TextEditor":"Inspector-TextEditor","Inspector-Typo3WinBrowserEditor":"Inspector-Typo3WinBrowserEditor","Inspector-ValidatorsEditor":"Inspector-ValidatorsEditor","Inspector-ValidationErrorMessageEditor":"Inspector-ValidationErrorMessageEditor",inspectorFinishers:"inspectorFinishers",inspectorValidators:"inspectorValidators",propertyGridEditorHeaderRow:"headerRow",propertyGridEditorAddRow:"addRow",propertyGridEditorAddRowItem:"addRowItem",propertyGridEditorContainer:"propertyGridContainer",propertyGridEditorDeleteRow:"deleteRow",propertyGridEditorLabel:"label",propertyGridEditorRowItem:"rowItem",propertyGridEditorColumn:"column",propertyGridEditorSelectValue:"selectValue",propertyGridEditorSortRow:"sortRow",propertyGridEditorValue:"value",viewportButton:"viewportButton"},domElementIdNames:{finisherPrefix:"t3-form-inspector-finishers-",validatorPrefix:"t3-form-inspector-validators-"},isSortable:!0};let configuration=null,formEditorApp=null;function getFormEditorApp(){return formEditorApp}function getViewModel(){return getFormEditorApp().getViewModel()}function getHelper(e){return getUtility().isUndefinedOrNull(e)?Helper.setConfiguration(configuration):Helper.setConfiguration(e)}function getUtility(){return getFormEditorApp().getUtility()}function assert(e,t,r){return getFormEditorApp().assert(e,t,r)}function getRootFormElement(){return getFormEditorApp().getRootFormElement()}function getCurrentlySelectedFormElement(){return getFormEditorApp().getCurrentlySelectedFormElement()}function getPublisherSubscriber(){return getFormEditorApp().getPublisherSubscriber()}function getFormElementDefinition(e,t){return getFormEditorApp().getFormElementDefinition(e,t)}function renderEditorDispatcher(e,t,r,o){switch(e.templateName){case"Inspector-FormElementHeaderEditor":renderFormElementHeaderEditor(e,t);break;case"Inspector-CollectionElementHeaderEditor":renderCollectionElementHeaderEditor(e,t,r,o);break;case"Inspector-MaximumFileSizeEditor":renderFileMaxSizeEditor(e,t);break;case"Inspector-TextEditor":renderTextEditor(e,t,r,o);break;case"Inspector-FinishersEditor":renderCollectionElementSelectionEditor("finishers",e,t);break;case"Inspector-ValidatorsEditor":renderCollectionElementSelectionEditor("validators",e,t);break;case"Inspector-ValidationErrorMessageEditor":renderValidationErrorMessageEditor(e,t);break;case"Inspector-RemoveElementEditor":renderRemoveElementEditor(e,t,r,o);break;case"Inspector-RequiredValidatorEditor":renderRequiredValidatorEditor(e,t,r,o);break;case"Inspector-CheckboxEditor":renderCheckboxEditor(e,t,r,o);break;case"Inspector-CountrySelectEditor":renderCountrySelectEditor(e,t,r,o);break;case"Inspector-SingleSelectEditor":renderSingleSelectEditor(e,t,r,o);break;case"Inspector-MultiSelectEditor":renderMultiSelectEditor(e,t,r,o);break;case"Inspector-GridColumnViewPortConfigurationEditor":renderGridColumnViewPortConfigurationEditor(e,t);break;case"Inspector-PropertyGridEditor":renderPropertyGridEditor(e,t,r,o);break;case"Inspector-TextareaEditor":renderTextareaEditor(e,t,r,o);break;case"Inspector-Typo3WinBrowserEditor":renderTypo3WinBrowserEditor(e,t,r,o)}getPublisherSubscriber().publish("view/inspector/editor/insert/perform",[e,t,r,o])}function openTypo3WinBrowser(e,t){Modal.advanced({type:Modal.types.iframe,content:TYPO3.settings.FormEditor.typo3WinBrowserUrl+"&mode="+e+"&bparams="+t,size:Modal.sizes.large})}function listenOnElementBrowser(){window.addEventListener("message",(function(e){if(!MessageUtility.verifyOrigin(e.origin))throw"Denied message sent by "+e.origin;if("typo3:elementBrowser:elementAdded"===e.data.actionName){if(void 0===e.data.fieldName)throw"fieldName not defined in message";if(void 0===e.data.value)throw"value not defined in message";const t=e.data.value.split("_");$(getHelper().getDomElementDataAttribute("contentElementSelectorTarget","bracesWithKeyValue",[e.data.fieldName])).val(t.pop()).trigger("paste")}}))}function getCollectionElementClass(e,t){return"finishers"===e?getHelper().getDomElementClassName("finisherEditorPrefix")+t:getHelper().getDomElementClassName("validatorEditorPrefix")+t}function getCollectionElementId(e,t,r){return"finishers"===e?getHelper().getDomElementIdName("finisherPrefix",r)+t:getHelper().getDomElementIdName("validatorPrefix",r)+t}function addSortableCollectionElementsEvents(e,t){e.addClass(getHelper().getDomElementClassName("sortable")),new Sortable(e.get(0),{draggable:getHelper().getDomElementClassName("collectionElement",!0),filter:"input,textarea,select",preventOnFilter:!1,animation:200,fallbackTolerance:200,swapThreshold:.6,dragClass:"form-sortable-drag",ghostClass:"form-sortable-ghost",onEnd:function(e){let r;r="finishers"===t?getHelper().getDomElementDataAttribute("finisher"):getHelper().getDomElementDataAttribute("validator");const o=$(e.item).attr(r),n=$(e.item).prevAll(getHelper().getDomElementClassName("collectionElement",!0)).first().attr(r),i=$(e.item).nextAll(getHelper().getDomElementClassName("collectionElement",!0)).first().attr(r);getPublisherSubscriber().publish("view/inspector/collectionElements/dnd/update",[o,n,i,t])}})}function setPropertyGridData(e,t,r,o){let n;if(t){const t=[];$(getHelper().getDomElementDataIdentifierSelector("propertyGridEditorContainer")+" "+getHelper().getDomElementDataIdentifierSelector("propertyGridEditorSelectValue")+":checked",$(e)).each((function(){n=$(this).closest(getHelper().getDomElementDataIdentifierSelector("propertyGridEditorRowItem")).find(getHelper().getDomElementDataIdentifierSelector("propertyGridEditorValue")).val(),getUtility().canBeInterpretedAsInteger(n)&&(n=parseInt(n,10)),t.push(n)})),getCurrentlySelectedFormElement().set(o+"defaultValue",t)}else n=$(getHelper().getDomElementDataIdentifierSelector("propertyGridEditorContainer")+" "+getHelper().getDomElementDataIdentifierSelector("propertyGridEditorSelectValue")+":checked",$(e)).first().closest(getHelper().getDomElementDataIdentifierSelector("propertyGridEditorRowItem")).find(getHelper().getDomElementDataIdentifierSelector("propertyGridEditorValue")).val(),getUtility().canBeInterpretedAsInteger(n)&&(n=parseInt(n,10)),getCurrentlySelectedFormElement().set(o+"defaultValue",n,!0);const i=[];$(getHelper().getDomElementDataIdentifierSelector("propertyGridEditorContainer")+" "+getHelper().getDomElementDataIdentifierSelector("propertyGridEditorRowItem"),$(e)).each((function(){let e=$(this).find(getHelper().getDomElementDataIdentifierSelector("propertyGridEditorValue")).val();const t=$(this).find(getHelper().getDomElementDataIdentifierSelector("propertyGridEditorLabel")).val();""===e&&(e=t);i.push({_label:t,_value:e})})),getCurrentlySelectedFormElement().set(o+r,i),validateCollectionElement(o+r,e)}function getEditorWrapperDomElement(e){return $(getHelper().getDomElementDataIdentifierSelector("editorWrapper"),$(e))}function getEditorControlsWrapperDomElement(e){return $(getHelper().getDomElementDataIdentifierSelector("editorControlsWrapper"),$(e))}function validateCollectionElement(e,t){let r,o,n;n=getFormEditorApp().validateCurrentlySelectedFormElementProperty(e),n.length>0?(getHelper().getTemplatePropertyDomElement("validationErrors",t).text(n[0]),getViewModel().setElementValidationErrorClass(getHelper().getTemplatePropertyDomElement("validationErrors",t)),getViewModel().setElementValidationErrorClass(getEditorControlsWrapperDomElement(t),"hasError")):(getHelper().getTemplatePropertyDomElement("validationErrors",t).text(""),getViewModel().removeElementValidationErrorClass(getHelper().getTemplatePropertyDomElement("validationErrors",t)),getViewModel().removeElementValidationErrorClass(getEditorControlsWrapperDomElement(t),"hasError")),n=getFormEditorApp().validateFormElement(getCurrentlySelectedFormElement()),o=e.split("."),o=o[0]+"."+o[1],r=!1;for(let e=0,t=n.length;e<t;++e)if(0===n[e].propertyPath.indexOf(o,0)&&n[e].validationResults&&n[e].validationResults.length>0){r=!0;break}r?getViewModel().setElementValidationErrorClass(getEditorControlsWrapperDomElement(t).closest(getHelper().getDomElementClassName("collectionElement",!0))):getViewModel().removeElementValidationErrorClass(getEditorControlsWrapperDomElement(t).closest(getHelper().getDomElementClassName("collectionElement",!0)))}function getFirstAvailableValidationErrorMessage(e,t){assert("array"===$.type(e),'Invalid configuration "errorCodes"',1489932939),assert("array"===$.type(t),'Invalid configuration "propertyData"',1489932940);for(let r=0,o=e.length;r<o;++r)for(let o=0,n=t.length;o<n;++o)if(parseInt(e[r],10)===parseInt(t[o].code,10)&&getUtility().isNonEmptyString(t[o].message))return t[o].message;return null}function renewValidationErrorMessages(e,t,r){if(assert("array"===$.type(t),'Invalid configuration "propertyData"',1489932942),!getUtility().isUndefinedOrNull(e)&&"array"===$.type(e)){const o=[];for(let n=0,i=e.length;n<i;++n){let i=!1;for(let o=0,l=t.length;o<l;++o)parseInt(e[n],10)===parseInt(t[o].code,10)&&(i=!0,getUtility().isNonEmptyString(r)?t[o].message=r:(t.splice(o,1),--l));i||getUtility().isNonEmptyString(r)&&o.push({code:e[n],message:r})}t=t.concat(o)}return t}function setRandomIds(e){assert("object"===$.type(e),'Invalid input "html"',1523904699),$(getHelper().getDomElementClassName("inspectorEditor",!0)).each((function(){const e=$(this),t={};$(getHelper().getDomElementDataAttribute("randomId","bracesWithKey"),e).each((function(){const e=$(this),r=e.attr(getHelper().getDomElementDataAttribute("randomIdTarget")),o=e.attr(getHelper().getDomElementDataAttribute("randomIdIndex"));e.is("["+r+"]")||(o in t||(t[o]="fe"+Math.floor(42*Math.random())+Date.now()),e.attr(r,t[o]))}))}))}export function getInspectorDomElement(){return $(getHelper().getDomElementDataIdentifierSelector("inspector"))}export function getFinishersContainerDomElement(){return $(getHelper().getDomElementDataIdentifierSelector("inspectorFinishers"),getInspectorDomElement())}export function getValidatorsContainerDomElement(){return $(getHelper().getDomElementDataIdentifierSelector("inspectorValidators"),getInspectorDomElement())}export function getCollectionElementDomElement(e,t){return"finishers"===e?$(getHelper().getDomElementDataAttribute("finisher","bracesWithKeyValue",[t]),getFinishersContainerDomElement()):$(getHelper().getDomElementDataAttribute("validator","bracesWithKeyValue",[t]),getValidatorsContainerDomElement())}export function renderEditors(e,t){getUtility().isUndefinedOrNull(e)&&(e=getCurrentlySelectedFormElement()),getInspectorDomElement().off().empty();const r=getFormElementDefinition(e,void 0);if("array"===$.type(r.editors)){for(let e=0,t=r.editors.length;e<t;++e){const t=getHelper().getTemplate(r.editors[e].templateName).clone();if(!t.length)continue;const o=$(t.html());$(o).first().addClass(getHelper().getDomElementClassName("inspectorEditor")),getInspectorDomElement().append($(o)),setRandomIds(o),renderEditorDispatcher(r.editors[e],o)}"function"===$.type(t)&&t()}}export function renderCollectionElementEditors(e,t){let r,o;assert(getUtility().isNonEmptyString(e),'Invalid parameter "collectionName"',1478354853),assert(getUtility().isNonEmptyString(t),'Invalid parameter "collectionElementIdentifier"',1478354854);const n=getFormEditorApp().getPropertyCollectionElementConfiguration(t,e);if("array"!==$.type(n.editors))return;const i=$("<div></div>").addClass(getHelper().getDomElementClassName("collectionElement"));"finishers"===e?(o=getFinishersContainerDomElement(),i.attr(getHelper().getDomElementDataAttribute("finisher"),t)):(o=getValidatorsContainerDomElement(),i.attr(getHelper().getDomElementDataAttribute("validator"),t)),o.append(i);const l=n.editors.length;l>0&&"header"===n.editors[0].identifier&&(r=$('<div role="tabpanel"></div>').addClass("panel-collapse collapse").prop("id",getCollectionElementId(e,t)));for(let o=0;o<l;++o){const i=getHelper().getTemplate(n.editors[o].templateName).clone();if(!i.length)continue;const a=$(i.html());$(a).first().addClass(getCollectionElementClass(e,n.editors[o].identifier)).addClass(getHelper().getDomElementClassName("inspectorEditor")),0===o&&r?getCollectionElementDomElement(e,t).append(a).append(r):o===l-1&&r&&"removeButton"===n.editors[o].identifier?getCollectionElementDomElement(e,t).append(a):o>0&&r?r.append(a):getCollectionElementDomElement(e,t).append(a),setRandomIds(a),renderEditorDispatcher(n.editors[o],a,t,e)}(2===l&&"header"===n.editors[0].identifier&&"removeButton"===n.editors[1].identifier||1===l&&"header"===n.editors[0].identifier)&&$(getHelper().getDomElementDataIdentifierSelector("collapse"),i).remove(),configuration.isSortable&&addSortableCollectionElementsEvents(o,e)}export function renderCollectionElementSelectionEditor(e,t,r){let o,n,i;assert(getUtility().isNonEmptyString(e),'Invalid configuration "collectionName"',1478362968),assert("object"===$.type(t),'Invalid parameter "editorConfiguration"',1475423098),assert("object"===$.type(r),'Invalid parameter "editorHtml"',1475423099),assert(getUtility().isNonEmptyString(t.label),'Invalid configuration "label"',1475423100),assert("array"===$.type(t.selectOptions),'Invalid configuration "selectOptions"',1475423101),"finishers"===e?(n=getFinishersContainerDomElement(),o=getRootFormElement().get(e)):(n=getValidatorsContainerDomElement(),o=getCurrentlySelectedFormElement().get(e)),n.off().empty(),getHelper().getTemplatePropertyDomElement("label",r).text(t.label);const l=getHelper().getTemplatePropertyDomElement("selectOptions",r);if(!getUtility().isUndefinedOrNull(o))for(let t=0,r=o.length;t<r;++t)getPublisherSubscriber().publish("view/inspector/collectionElement/existing/selected",[o[t].identifier,e]);i=!0;for(let e=0,r=t.selectOptions.length;e<r;++e){let r=!0;if(!getUtility().isUndefinedOrNull(o))for(let n=0,i=o.length;n<i;++n)if(o[n].identifier===t.selectOptions[e].value){r=!1;break}r&&(l.append(new Option(t.selectOptions[e].label,t.selectOptions[e].value)),""!==t.selectOptions[e].value&&(i=!1))}i&&l.off().empty().remove(),l.on("change",(function(){if(""!==$(this).val()){const t=$(this).val();$('option[value="'+t+'"]',$(this)).remove(),getFormEditorApp().getPublisherSubscriber().publish("view/inspector/collectionElement/new/selected",[t,e])}}))}export function renderFormElementHeaderEditor(e,t){assert("object"===$.type(e),'Invalid parameter "editorConfiguration"',1475421525),assert("object"===$.type(t),'Invalid parameter "editorHtml"',1475421526),Icons.getIcon(getFormElementDefinition(getCurrentlySelectedFormElement(),"iconIdentifier"),Icons.sizes.small,null,Icons.states.default).then((function(e){getHelper().getTemplatePropertyDomElement("header-label",t).append($(e).addClass(getHelper().getDomElementClassName("icon"))).append(buildTitleByFormElement())}))}export function renderCollectionElementHeaderEditor(e,t,r,o){assert("object"===$.type(e),'Invalid parameter "editorConfiguration"',1475421258),assert(getUtility().isNonEmptyString(e.label),'Invalid configuration "label"',1475421257),assert("object"===$.type(t),'Invalid parameter "editorHtml"',1475421259);const n=function(e){e&&getHelper().getTemplatePropertyDomElement("header-label",t).prepend($(e));const n=getFormEditorApp().getPropertyCollectionElementConfiguration(r,o).editors;2===n.length&&"header"===n[0].identifier&&"removeButton"===n[1].identifier||1===n.length&&"header"===n[0].identifier||Icons.getIcon(getHelper().getDomElementDataAttributeValue("collapse"),Icons.sizes.small,null,Icons.states.default,Icons.markupIdentifiers.inline).then((function(e){const n=$("<a></a>").attr("href",getCollectionElementId(o,r,!0)).attr("data-bs-toggle","collapse").attr("aria-expanded","false").attr("aria-controls",getCollectionElementId(o,r)).addClass("collapsed").append($(e));getHelper().getTemplatePropertyDomElement("header-label",t).prepend(n)}))},i=getFormEditorApp().getFormEditorDefinition(o,r);"iconIdentifier"in i?Icons.getIcon(i.iconIdentifier,Icons.sizes.small,null,Icons.states.default).then((function(e){n(e)})):n(),e.label&&getHelper().getTemplatePropertyDomElement("label",t).append(e.label)}export function renderFileMaxSizeEditor(e,t){if(assert("object"===$.type(e),'Invalid parameter "editorConfiguration"',1475421258),assert(getUtility().isNonEmptyString(e.label),'Invalid configuration "label"',1475421257),assert("object"===$.type(t),'Invalid parameter "editorHtml"',1475421259),e.label){const r=getHelper().getTemplatePropertyDomElement("label",t),o=r.attr(getHelper().getDomElementDataAttribute("maximumFileSize"));r.append(e.label.replace("{0}",o))}}export function renderTextEditor(e,t,r,o){assert("object"===$.type(e),'Invalid parameter "editorConfiguration"',1475421053),assert("object"===$.type(t),'Invalid parameter "editorHtml"',1475421054),assert(getUtility().isNonEmptyString(e.label),'Invalid configuration "label"',1475421055),assert(getUtility().isNonEmptyString(e.propertyPath),'Invalid configuration "propertyPath"',1475421056),getHelper().getTemplatePropertyDomElement("label",t).append(e.label),getUtility().isNonEmptyString(e.fieldExplanationText)?getHelper().getTemplatePropertyDomElement("fieldExplanationText",t).text(e.fieldExplanationText):getHelper().getTemplatePropertyDomElement("fieldExplanationText",t).remove(),getUtility().isNonEmptyString(e.placeholder)&&getHelper().getTemplatePropertyDomElement("propertyPath",t).attr("placeholder",e.placeholder);const n=getFormEditorApp().buildPropertyPath(e.propertyPath,r,o),i=getCurrentlySelectedFormElement().get(n);if(validateCollectionElement(n,t),getHelper().getTemplatePropertyDomElement("propertyPath",t).val(i),!getUtility().isUndefinedOrNull(e.additionalElementPropertyPaths)&&"array"===$.type(e.additionalElementPropertyPaths))for(let t=0,r=e.additionalElementPropertyPaths.length;t<r;++t)getCurrentlySelectedFormElement().set(e.additionalElementPropertyPaths[t],i);renderFormElementSelectorEditorAddition(e,t,n),getHelper().getTemplatePropertyDomElement("propertyPath",t).on("keyup paste",(function(){if(e.doNotSetIfPropertyValueIsEmpty&&!getUtility().isNonEmptyString($(this).val())?getCurrentlySelectedFormElement().unset(n):getCurrentlySelectedFormElement().set(n,$(this).val()),validateCollectionElement(n,t),!getUtility().isUndefinedOrNull(e.additionalElementPropertyPaths)&&"array"===$.type(e.additionalElementPropertyPaths))for(let t=0,r=e.additionalElementPropertyPaths.length;t<r;++t)e.doNotSetIfPropertyValueIsEmpty&&!getUtility().isNonEmptyString($(this).val())?getCurrentlySelectedFormElement().unset(e.additionalElementPropertyPaths[t]):getCurrentlySelectedFormElement().set(e.additionalElementPropertyPaths[t],$(this).val())}))}export function renderValidationErrorMessageEditor(e,t){assert("object"===$.type(e),'Invalid parameter "editorConfiguration"',1489874121),assert("object"===$.type(t),'Invalid parameter "editorHtml"',1489874122),assert(getUtility().isNonEmptyString(e.label),'Invalid configuration "label"',1489874123),assert(getUtility().isNonEmptyString(e.propertyPath),'Invalid configuration "propertyPath"',1489874124),getHelper().getTemplatePropertyDomElement("label",t).append(e.label),getUtility().isNonEmptyString(e.fieldExplanationText)?getHelper().getTemplatePropertyDomElement("fieldExplanationText",t).text(e.fieldExplanationText):getHelper().getTemplatePropertyDomElement("fieldExplanationText",t).remove();const r=getFormEditorApp().buildPropertyPath(e.propertyPath);let o=getCurrentlySelectedFormElement().get(r);if(!getUtility().isUndefinedOrNull(o)&&"array"===$.type(o)){const r=getFirstAvailableValidationErrorMessage(e.errorCodes,o);getUtility().isUndefinedOrNull(r)||getHelper().getTemplatePropertyDomElement("propertyPath",t).val(r)}getHelper().getTemplatePropertyDomElement("propertyPath",t).on("keyup paste",(function(){o=getCurrentlySelectedFormElement().get(r),getUtility().isUndefinedOrNull(o)&&(o=[]),getCurrentlySelectedFormElement().set(r,renewValidationErrorMessages(e.errorCodes,o,$(this).val()))}))}export function renderCountrySelectEditor(e,t,r,o){assert("object"===$.type(e),'Invalid parameter "editorConfiguration"',1674826430),assert("object"===$.type(t),'Invalid parameter "editorHtml"',1674826431),assert(getUtility().isNonEmptyString(e.label),'Invalid configuration "label"',1674826432);const n=getFormEditorApp().buildPropertyPath(e.propertyPath,r,o);getHelper().getTemplatePropertyDomElement("label",t).append(e.label);const i=getHelper().getTemplatePropertyDomElement("selectOptions",t),l=getCurrentlySelectedFormElement().get(n)||{},a=$("option",i);i.empty();for(let e=0,t=a.length;e<t;++e){let t=!1;for(const r of Object.keys(l))if(a[e].value===l[r]){t=!0;break}const r=new Option(a[e].text,e.toString(),!1,t);$(r).data({value:a[e].value}),i.append(r)}i.on("change",(function(){const e=[];$("option:selected",$(this)).each((function(){e.push($(this).data("value"))})),getCurrentlySelectedFormElement().set(n,e)}))}export function renderSingleSelectEditor(e,t,r,o){assert("object"===$.type(e),'Invalid parameter "editorConfiguration"',1475421048),assert("object"===$.type(t),'Invalid parameter "editorHtml"',1475421049),assert(getUtility().isNonEmptyString(e.label),'Invalid configuration "label"',1475421050),assert(getUtility().isNonEmptyString(e.propertyPath),'Invalid configuration "propertyPath"',1475421051),assert("array"===$.type(e.selectOptions),'Invalid configuration "selectOptions"',1475421052);const n=getFormEditorApp().buildPropertyPath(e.propertyPath,r,o);getHelper().getTemplatePropertyDomElement("label",t).append(e.label);const i=getHelper().getTemplatePropertyDomElement("selectOptions",t),l=getCurrentlySelectedFormElement().get(n);for(let t=0,r=e.selectOptions.length;t<r;++t){let r;r=e.selectOptions[t].value===l?new Option(e.selectOptions[t].label,t.toString(),!1,!0):new Option(e.selectOptions[t].label,t.toString()),$(r).data({value:e.selectOptions[t].value}),i.append(r)}i.on("change",(function(){getCurrentlySelectedFormElement().set(n,$("option:selected",$(this)).data("value"))}))}export function renderMultiSelectEditor(e,t,r,o){assert("object"===$.type(e),'Invalid parameter "editorConfiguration"',1485712399),assert("object"===$.type(t),'Invalid parameter "editorHtml"',1485712400),assert(getUtility().isNonEmptyString(e.label),'Invalid configuration "label"',1485712401),assert(getUtility().isNonEmptyString(e.propertyPath),'Invalid configuration "propertyPath"',1485712402),assert("array"===$.type(e.selectOptions),'Invalid configuration "selectOptions"',1485712403);const n=getFormEditorApp().buildPropertyPath(e.propertyPath,r,o);getHelper().getTemplatePropertyDomElement("label",t).append(e.label);const i=getHelper().getTemplatePropertyDomElement("selectOptions",t),l=getCurrentlySelectedFormElement().get(n)||{};for(let t=0,r=e.selectOptions.length;t<r;++t){let r=null;for(const o of Object.keys(l))if(e.selectOptions[t].value===l[o]){r=new Option(e.selectOptions[t].label,t.toString(),!1,!0);break}r||(r=new Option(e.selectOptions[t].label,t.toString())),$(r).data({value:e.selectOptions[t].value}),i.append(r)}i.on("change",(function(){const e=[];$("option:selected",$(this)).each((function(){e.push($(this).data("value"))})),getCurrentlySelectedFormElement().set(n,e)}))}export function renderGridColumnViewPortConfigurationEditor(e,t){if(assert("object"===$.type(e),'Invalid parameter "editorConfiguration"',1489528242),assert("object"===$.type(t),'Invalid parameter "editorHtml"',1489528243),assert(getUtility().isNonEmptyString(e.label),'Invalid configuration "label"',1489528244),assert("array"===$.type(e.configurationOptions.viewPorts),'Invalid configurationOptions "viewPorts"',1489528245),assert(!getUtility().isUndefinedOrNull(e.configurationOptions.numbersOfColumnsToUse.label),'Invalid configurationOptions "numbersOfColumnsToUse"',1489528246),assert(!getUtility().isUndefinedOrNull(e.configurationOptions.numbersOfColumnsToUse.propertyPath),'Invalid configuration "selectOptions"',1489528247),!getFormElementDefinition(getCurrentlySelectedFormElement().get("__parentRenderable"),"_isGridRowFormElement"))return void t.remove();getHelper().getTemplatePropertyDomElement("label",t).append(e.label);const r=$(getHelper().getDomElementDataIdentifierSelector("viewportButton"),$(t)).clone();$(getHelper().getDomElementDataIdentifierSelector("viewportButton"),$(t)).remove();const o=getHelper().getTemplatePropertyDomElement("numbersOfColumnsToUse",$(t)).clone();getHelper().getTemplatePropertyDomElement("numbersOfColumnsToUse",$(t)).remove();const n=getEditorControlsWrapperDomElement(t),i=function(r){getHelper().getTemplatePropertyDomElement("numbersOfColumnsToUse",$(t)).off().empty().remove();const n=$(o).clone(!0,!0);getEditorWrapperDomElement(t).after(n),$("input",n).focus(),getHelper().getTemplatePropertyDomElement("numbersOfColumnsToUse-label",n).append(e.configurationOptions.numbersOfColumnsToUse.label.replace("{@viewPortLabel}",r.data("viewPortLabel"))),getHelper().getTemplatePropertyDomElement("numbersOfColumnsToUse-fieldExplanationText",n).append(e.configurationOptions.numbersOfColumnsToUse.fieldExplanationText);const i=e.configurationOptions.numbersOfColumnsToUse.propertyPath.replace("{@viewPortIdentifier}",r.data("viewPortIdentifier"));getHelper().getTemplatePropertyDomElement("numbersOfColumnsToUse-propertyPath",n).val(getCurrentlySelectedFormElement().get(i)),getHelper().getTemplatePropertyDomElement("numbersOfColumnsToUse-propertyPath",n).on("keyup paste change",(function(){const e=$(this);$.isNumeric(e.val())||e.val(""),getCurrentlySelectedFormElement().set(i,e.val())}))};for(let l=0,a=e.configurationOptions.viewPorts.length;l<a;++l){const p=e.configurationOptions.viewPorts[l].viewPortIdentifier,s=e.configurationOptions.viewPorts[l].label,d=$(r).clone(!0,!0);if(d.text(p),d.data("viewPortIdentifier",p),d.data("viewPortLabel",s),d.attr("title",s),n.append(d),l===a-1){const e=$(o).clone(!0,!0);getEditorWrapperDomElement(t).after(e),i(d),d.addClass(getHelper().getDomElementClassName("active"))}$("button",n).on("click",(function(){const e=$(this);$("button",n).removeClass(getHelper().getDomElementClassName("active")),e.addClass(getHelper().getDomElementClassName("active")),i(e)}))}}export function renderPropertyGridEditor(e,t,r,o){assert("object"===$.type(e),'Invalid parameter "editorConfiguration"',1475419226),assert("object"===$.type(t),'Invalid parameter "editorHtml"',1475419227),assert("boolean"===$.type(e.enableAddRow),'Invalid configuration "enableAddRow"',1475419228),assert("boolean"===$.type(e.enableDeleteRow),'Invalid configuration "enableDeleteRow"',1475419230),assert("boolean"===$.type(e.isSortable),'Invalid configuration "isSortable"',1475419229),assert(getUtility().isNonEmptyString(e.propertyPath),'Invalid configuration "propertyPath"',1475419231),assert(getUtility().isNonEmptyString(e.label),'Invalid configuration "label"',1475419232),getHelper().getTemplatePropertyDomElement("label",t).append(e.label),getUtility().isNonEmptyString(e.fieldExplanationText)?getHelper().getTemplatePropertyDomElement("fieldExplanationText",t).text(e.fieldExplanationText):getHelper().getTemplatePropertyDomElement("fieldExplanationText",t).remove();let n,i=getFormEditorApp().buildPropertyPath(void 0,r,o,void 0,!0);getUtility().isNonEmptyString(i)&&(i+="."),n=!!getUtility().isUndefinedOrNull(e.useLabelAsFallbackValue)||e.useLabelAsFallbackValue;let l=[{name:"label",title:"Label"},{name:"value",title:"Value"},{name:"selected",title:"Selected"}];getUtility().isNonEmptyArray(e.gridColumns)&&(l=e.gridColumns);const a=l.map((function(e){return e.name})),p=l.map((function(e){return e.title||null}));let s;$([getHelper().getDomElementDataIdentifierSelector("propertyGridEditorHeaderRow"),getHelper().getDomElementDataIdentifierSelector("propertyGridEditorRowItem"),getHelper().getDomElementDataIdentifierSelector("propertyGridEditorAddRowItem")].join(","),$(t)).each((function(e,t){const r=$(getHelper().getDomElementDataIdentifierSelector("propertyGridEditorColumn"),t),o=r.last().nextAll(),n={};r.detach().each((function(e,t){const r=$(t),o=r.data("column");a.includes(o)&&(n[o]=r)})),a.forEach((function(e,r){const o=n[e];o.is("th")&&o.append(p[r]),o.appendTo(t)})),o.appendTo(t)})),s=!getUtility().isUndefinedOrNull(e.multiSelection)&&!!e.multiSelection;const d=$(getHelper().getDomElementDataIdentifierSelector("propertyGridEditorRowItem"),$(t)).clone();if($(getHelper().getDomElementDataIdentifierSelector("propertyGridEditorRowItem"),$(t)).remove(),e.enableDeleteRow?$(getHelper().getDomElementDataIdentifierSelector("propertyGridEditorDeleteRow"),$(d)).on("click",(function(){$(this).closest(getHelper().getDomElementDataIdentifierSelector("propertyGridEditorRowItem")).off().empty().remove(),setPropertyGridData($(t),s,e.propertyPath,i)})):$(getHelper().getDomElementDataIdentifierSelector("propertyGridEditorDeleteRow"),$(d)).parent().off().empty(),e.isSortable?$(t).get(0).querySelectorAll(getHelper().getDomElementDataIdentifierSelector("propertyGridEditorContainer")+" tbody").forEach((function(r){new Sortable(r,{group:getHelper().getDomElementDataAttributeValue("propertyGridEditorContainer"),handle:getHelper().getDomElementDataIdentifierSelector("propertyGridEditorSortRow"),draggable:getHelper().getDomElementDataIdentifierSelector("propertyGridEditorRowItem"),pull:"clone",swapThreshold:.6,dragClass:"form-sortable-drag",ghostClass:"form-sortable-ghost",onUpdate:function(){setPropertyGridData($(t),s,e.propertyPath,i)}})})):$(getHelper().getDomElementDataIdentifierSelector("propertyGridEditorSortRow"),$(d)).parent().off().empty(),$(getHelper().getDomElementDataIdentifierSelector("propertyGridEditorSelectValue"),$(d)).on("change",(function(){s||$(getHelper().getDomElementDataIdentifierSelector("propertyGridEditorSelectValue")+":checked",$(t)).not($(this)).prop("checked",!1),setPropertyGridData($(t),s,e.propertyPath,i)})),$(getHelper().getDomElementDataIdentifierSelector("propertyGridEditorLabel")+","+getHelper().getDomElementDataIdentifierSelector("propertyGridEditorValue"),$(d)).on("keyup paste",(function(){setPropertyGridData($(t),s,e.propertyPath,i)})),n&&$(getHelper().getDomElementDataIdentifierSelector("propertyGridEditorLabel"),$(d)).on("focusout",(function(){""===$(this).closest(getHelper().getDomElementDataIdentifierSelector("propertyGridEditorRowItem")).find(getHelper().getDomElementDataIdentifierSelector("propertyGridEditorValue")).val()&&$(this).closest(getHelper().getDomElementDataIdentifierSelector("propertyGridEditorRowItem")).find(getHelper().getDomElementDataIdentifierSelector("propertyGridEditorValue")).val($(this).val())})),e.enableAddRow){const r=$(getHelper().getDomElementDataIdentifierSelector("propertyGridEditorAddRowItem"),$(t)).clone();$(getHelper().getDomElementDataIdentifierSelector("propertyGridEditorAddRowItem"),$(t)).remove(),$(getHelper().getDomElementDataIdentifierSelector("propertyGridEditorAddRow"),$(r)).on("click",(function(){$(this).closest(getHelper().getDomElementDataIdentifierSelector("propertyGridEditorAddRowItem")).before($(d).clone(!0,!0)),setPropertyGridData($(t),s,e.propertyPath,i)})),$(getHelper().getDomElementDataIdentifierSelector("propertyGridEditorContainer"),$(t)).prepend($(r).clone(!0,!0))}else $(getHelper().getDomElementDataIdentifierSelector("propertyGridEditorAddRowItem"),$(t)).remove();let m={};s?getUtility().isUndefinedOrNull(getCurrentlySelectedFormElement().get(i+"defaultValue"))||(m=getCurrentlySelectedFormElement().get(i+"defaultValue")):getUtility().isUndefinedOrNull(getCurrentlySelectedFormElement().get(i+"defaultValue"))||(m={0:getCurrentlySelectedFormElement().get(i+"defaultValue")});const g=getCurrentlySelectedFormElement().get(i+e.propertyPath)||{},c=function(r,o){let n=!1;const i=$(d).clone(!0,!0);for(const e of Object.keys(m))if(m[e]===o){n=!0;break}$(getHelper().getDomElementDataIdentifierSelector("propertyGridEditorLabel"),$(i)).val(r),$(getHelper().getDomElementDataIdentifierSelector("propertyGridEditorValue"),$(i)).val(o),n&&$(getHelper().getDomElementDataIdentifierSelector("propertyGridEditorSelectValue"),$(i)).prop("checked",!0),e.enableAddRow?$(getHelper().getDomElementDataIdentifierSelector("propertyGridEditorAddRowItem"),$(t)).before($(i)):$(getHelper().getDomElementDataIdentifierSelector("propertyGridEditorContainer"),$(t)).prepend($(i))};if("object"===$.type(g))for(const e of Object.keys(g))c(g[e],e);else if("array"===$.type(g))for(const e in g)g.hasOwnProperty(e)&&(getUtility().isUndefinedOrNull(g[e]._label)?c(g[e],e):c(g[e]._label,g[e]._value));validateCollectionElement(i+e.propertyPath,t)}export function renderRequiredValidatorEditor(e,t,r,o){assert("object"===$.type(e),'Invalid parameter "editorConfiguration"',1475417093),assert("object"===$.type(t),'Invalid parameter "editorHtml"',1475417094),assert(getUtility().isNonEmptyString(e.validatorIdentifier),'Invalid configuration "validatorIdentifier"',1475417095),assert(getUtility().isNonEmptyString(e.label),'Invalid configuration "label"',1475417096);const n=e.validatorIdentifier;let i,l,a;getHelper().getTemplatePropertyDomElement("label",t).append(e.label),getUtility().isNonEmptyString(e.propertyPath)&&(l=getFormEditorApp().buildPropertyPath(e.propertyPath,r,o)),i=getUtility().isNonEmptyString(e.propertyValue)?e.propertyValue:"";const p=getFormEditorApp().buildPropertyPath(e.configurationOptions.validationErrorMessage.propertyPath),s=getHelper().getTemplatePropertyDomElement("validationErrorMessage",$(t)).clone();getHelper().getTemplatePropertyDomElement("validationErrorMessage",$(t)).remove();const d=function(){const r=$(s).clone(!0,!0);getEditorWrapperDomElement(t).after(r),getHelper().getTemplatePropertyDomElement("validationErrorMessage-label",r).append(e.configurationOptions.validationErrorMessage.label),getHelper().getTemplatePropertyDomElement("validationErrorMessage-fieldExplanationText",r).append(e.configurationOptions.validationErrorMessage.fieldExplanationText),a=getCurrentlySelectedFormElement().get(p),getUtility().isUndefinedOrNull(a)&&(a=[]);const o=getFirstAvailableValidationErrorMessage(e.configurationOptions.validationErrorMessage.errorCodes,a);getUtility().isUndefinedOrNull(o)||getHelper().getTemplatePropertyDomElement("validationErrorMessage-propertyPath",r).val(o),getHelper().getTemplatePropertyDomElement("validationErrorMessage-propertyPath",r).on("keyup paste",(function(){let t=getCurrentlySelectedFormElement().get(p);getUtility().isUndefinedOrNull(t)&&(t=[]),getCurrentlySelectedFormElement().set(p,renewValidationErrorMessages(e.configurationOptions.validationErrorMessage.errorCodes,t,$(this).val()))}))};-1!==getFormEditorApp().getIndexFromPropertyCollectionElement(n,"validators")&&($('input[type="checkbox"]',$(t)).prop("checked",!0),getUtility().isNonEmptyString(l)&&getCurrentlySelectedFormElement().set(l,i),d()),$('input[type="checkbox"]',$(t)).on("change",(function(){getHelper().getTemplatePropertyDomElement("validationErrorMessage",$(t)).off().empty().remove(),$(this).is(":checked")?(d(),getPublisherSubscriber().publish("view/inspector/collectionElement/new/selected",[n,"validators"]),getUtility().isNonEmptyString(l)&&getCurrentlySelectedFormElement().set(l,i)):(getPublisherSubscriber().publish("view/inspector/removeCollectionElement/perform",[n,"validators"]),getUtility().isNonEmptyString(l)&&getCurrentlySelectedFormElement().unset(l),a=getCurrentlySelectedFormElement().get(p),getUtility().isUndefinedOrNull(a)&&(a=[]),getCurrentlySelectedFormElement().set(p,renewValidationErrorMessages(e.configurationOptions.validationErrorMessage.errorCodes,a,"")))}))}export function renderCheckboxEditor(e,t,r,o){assert("object"===$.type(e),'Invalid parameter "editorConfiguration"',1476218671),assert("object"===$.type(t),'Invalid parameter "editorHtml"',1476218672),assert(getUtility().isNonEmptyString(e.label),'Invalid configuration "label"',1476218673),assert(getUtility().isNonEmptyString(e.propertyPath),'Invalid configuration "propertyPath"',1476218674),getHelper().getTemplatePropertyDomElement("label",t).append(e.label),getUtility().isNonEmptyString(e.fieldExplanationText)?getHelper().getTemplatePropertyDomElement("fieldExplanationText",t).text(e.fieldExplanationText):getHelper().getTemplatePropertyDomElement("fieldExplanationText",t).remove();const n=getFormEditorApp().buildPropertyPath(e.propertyPath,r,o),i=getCurrentlySelectedFormElement().get(n);("boolean"===$.type(i)&&i||"true"===i||1===i||"1"===i)&&$('input[type="checkbox"]',$(t)).prop("checked",!0),$('input[type="checkbox"]',$(t)).on("change",(function(){$(this).is(":checked")?getCurrentlySelectedFormElement().set(n,!0):getCurrentlySelectedFormElement().set(n,!1)}))}export function renderTextareaEditor(e,t,r,o){assert("object"===$.type(e),'Invalid parameter "editorConfiguration"',1475412567),assert("object"===$.type(t),'Invalid parameter "editorHtml"',1475412568),assert(getUtility().isNonEmptyString(e.propertyPath),'Invalid configuration "propertyPath"',1475416098),assert(getUtility().isNonEmptyString(e.label),'Invalid configuration "label"',1475416099);const n=getFormEditorApp().buildPropertyPath(e.propertyPath,r,o);getHelper().getTemplatePropertyDomElement("label",t).append(e.label),getUtility().isNonEmptyString(e.fieldExplanationText)?getHelper().getTemplatePropertyDomElement("fieldExplanationText",t).text(e.fieldExplanationText):getHelper().getTemplatePropertyDomElement("fieldExplanationText",t).remove();const i=getCurrentlySelectedFormElement().get(n);$("textarea",$(t)).val(i),$("textarea",$(t)).on("keyup paste",(function(){getCurrentlySelectedFormElement().set(n,$(this).val())}))}export function renderTypo3WinBrowserEditor(e,t,r,o){assert("object"===$.type(e),'Invalid parameter "editorConfiguration"',1477300587),assert("object"===$.type(t),'Invalid parameter "editorHtml"',1477300588),assert(getUtility().isNonEmptyString(e.label),'Invalid configuration "label"',1477300589),assert(getUtility().isNonEmptyString(e.buttonLabel),'Invalid configuration "buttonLabel"',1477318981),assert(getUtility().isNonEmptyString(e.propertyPath),'Invalid configuration "propertyPath"',1477300590),getHelper().getTemplatePropertyDomElement("label",t).append(e.label),getHelper().getTemplatePropertyDomElement("buttonLabel",t).append(e.buttonLabel),getUtility().isNonEmptyString(e.fieldExplanationText)?getHelper().getTemplatePropertyDomElement("fieldExplanationText",t).text(e.fieldExplanationText):getHelper().getTemplatePropertyDomElement("fieldExplanationText",t).remove(),$("form",$(t)).prop("name",e.propertyPath),Icons.getIcon(e.iconIdentifier,Icons.sizes.small).then((function(e){getHelper().getTemplatePropertyDomElement("image",t).append($(e))})),getHelper().getTemplatePropertyDomElement("onclick",t).on("click",(function(){const t=Math.floor(1e5*Math.random()+1);$(this).closest(getHelper().getDomElementDataIdentifierSelector("editorControlsWrapper")).find(getHelper().getDomElementDataAttribute("contentElementSelectorTarget","bracesWithKey")).attr(getHelper().getDomElementDataAttribute("contentElementSelectorTarget"),t),openTypo3WinBrowser("db",t+"|||"+e.browsableType)})),listenOnElementBrowser();const n=getFormEditorApp().buildPropertyPath(e.propertyPath,r,o),i=getCurrentlySelectedFormElement().get(n);validateCollectionElement(n,t),getHelper().getTemplatePropertyDomElement("propertyPath",t).val(i),getHelper().getTemplatePropertyDomElement("propertyPath",t).on("keyup paste",(function(){getCurrentlySelectedFormElement().set(n,$(this).val()),validateCollectionElement(n,t)}))}export function renderRemoveElementEditor(e,t,r,o){assert("object"===$.type(e),'Invalid parameter "editorConfiguration"',1475412563),assert("object"===$.type(t),'Invalid parameter "editorHtml"',1475412564),getUtility().isUndefinedOrNull(r)?$("button",$(t)).addClass(getHelper().getDomElementClassName("buttonFormElementRemove")+" "+getHelper().getDomElementClassName("buttonFormEditor")):$("button",$(t)).addClass(getHelper().getDomElementClassName("buttonCollectionElementRemove")),$("button",$(t)).on("click",(function(){getUtility().isUndefinedOrNull(r)?getViewModel().showRemoveFormElementModal():getViewModel().showRemoveCollectionElementModal(r,o)}))}export function renderFormElementSelectorEditorAddition(e,t,r){assert("object"===$.type(e),'Invalid parameter "editorConfiguration"',1484574704),assert("object"===$.type(t),'Invalid parameter "editorHtml"',1484574705),assert(getUtility().isNonEmptyString(r),'Invalid parameter "propertyPath"',1484574706);const o=$(getHelper().getDomElementDataIdentifierSelector("formElementSelectorControlsWrapper"),t);if(!0===e.enableFormelementSelectionButton){if(0===o.length)return;const e=$(getHelper().getDomElementDataIdentifierSelector("formElementSelectorSplitButtonListContainer"),t);e.off().empty();const n=getFormEditorApp().getNonCompositeNonToplevelFormElements();0===n.length?Icons.getIcon(getHelper().getDomElementDataAttributeValue("iconNotAvailable"),Icons.sizes.small,null,Icons.states.default).then((function(t){const r=$('<li data-no-sorting><a href="#"></a></li>');r.append($(t)).append(" "+getFormElementDefinition(getRootFormElement(),"inspectorEditorFormElementSelectorNoElements")),e.append(r)})):$.each(n,(function(o,n){Icons.getIcon(getFormElementDefinition(n,"iconIdentifier"),Icons.sizes.small,null,Icons.states.default).then((function(o){const i=$('<li data-no-sorting><a href="#" class="dropdown-item" data-formelement-identifier="'+n.get("identifier")+'"></a></li>');$('[data-formelement-identifier="'+n.get("identifier")+'"]',i).append($(o)).append(" "+n.get("label")),$("a",i).on("click",(function(){let e;e=getCurrentlySelectedFormElement().get(r)||"",e=0===e.length?"{"+$(this).attr("data-formelement-identifier")+"}":e+" {"+$(this).attr("data-formelement-identifier")+"}",getCurrentlySelectedFormElement().set(r,e),getHelper().getTemplatePropertyDomElement("propertyPath",t).val(e),validateCollectionElement(r,t)})),e.append(i)}))}))}else $(getHelper().getDomElementDataIdentifierSelector("editorControlsInputGroup"),t).removeClass(getHelper().getDomElementClassName("inspectorInputGroup")),o.off().empty().remove()}export function buildTitleByFormElement(e){let t;getUtility().isUndefinedOrNull(e)&&(e=getCurrentlySelectedFormElement()),assert("object"===$.type(e),'Invalid parameter "formElement"',1478967319),t="Form"===e.get("type")?e.get("type"):getFormElementDefinition(e,"label")?getFormElementDefinition(e,"label"):e.get("identifier");const r=document.createElement("span");return r.textContent=t,r}export function bootstrap(e,t){return formEditorApp=e,configuration=$.extend(!0,defaultConfiguration,t||{}),Helper.bootstrap(formEditorApp),this} \ No newline at end of file