typo3-typescript-sources 13.4.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/sync-and-publish.yml +265 -0
- package/.last-synced-tag +1 -0
- package/LICENSE.txt +339 -0
- package/README-TYPO3.md +166 -0
- package/README.md +28 -0
- package/adminpanel/admin-panel.ts +375 -0
- package/adminpanel/modules/cache.ts +27 -0
- package/adminpanel/modules/preview.ts +75 -0
- package/backend/action-button/abstract-action.ts +22 -0
- package/backend/action-button/deferred-action.ts +41 -0
- package/backend/action-button/immediate-action.ts +31 -0
- package/backend/action-dispatcher.ts +104 -0
- package/backend/ajax-data-handler/message-interface.ts +18 -0
- package/backend/ajax-data-handler/response-interface.ts +20 -0
- package/backend/ajax-data-handler.ts +214 -0
- package/backend/backend-exception.ts +22 -0
- package/backend/broadcast-message.ts +50 -0
- package/backend/broadcast-service.ts +52 -0
- package/backend/browse-database.ts +38 -0
- package/backend/clear-cache.ts +88 -0
- package/backend/clipboard-panel.ts +240 -0
- package/backend/close-current-window.ts +2 -0
- package/backend/code-editor/autocomplete/completion-result.ts +105 -0
- package/backend/code-editor/autocomplete/ts-code-completion.ts +142 -0
- package/backend/code-editor/autocomplete/ts-parser.ts +485 -0
- package/backend/code-editor/autocomplete/ts-ref.ts +164 -0
- package/backend/code-editor/element/code-mirror-element.ts +282 -0
- package/backend/code-editor/language/typoscript.ts +181 -0
- package/backend/code-editor/stream-parser/typoscript.ts +1600 -0
- package/backend/color-picker.ts +158 -0
- package/backend/color-scheme-switch.ts +179 -0
- package/backend/column-selector-button.ts +302 -0
- package/backend/context-help.ts +68 -0
- package/backend/context-menu-actions.ts +322 -0
- package/backend/context-menu.ts +751 -0
- package/backend/copy-to-clipboard.ts +79 -0
- package/backend/date-time-picker.ts +270 -0
- package/backend/document-save-actions.ts +159 -0
- package/backend/drag-tooltip.ts +285 -0
- package/backend/drag-uploader.ts +914 -0
- package/backend/element/alert-element.ts +116 -0
- package/backend/element/dispatch-modal-button.ts +50 -0
- package/backend/element/draggable-resizable-element.ts +249 -0
- package/backend/element/editable-page-title.ts +306 -0
- package/backend/element/icon-element.ts +84 -0
- package/backend/element/immediate-action-element.ts +89 -0
- package/backend/element/pagination.ts +59 -0
- package/backend/element/progress-bar-element.ts +172 -0
- package/backend/element/progress-tracker-element.ts +119 -0
- package/backend/element/pseudo-button.ts +58 -0
- package/backend/element/spinner-element.ts +51 -0
- package/backend/element/thumbnail-element.ts +80 -0
- package/backend/element-browser.ts +182 -0
- package/backend/enum/data-transfer-types.ts +21 -0
- package/backend/enum/icon-types.ts +31 -0
- package/backend/enum/key-types.ts +27 -0
- package/backend/enum/severity.ts +20 -0
- package/backend/enum/viewport/scaffold-identifier.ts +24 -0
- package/backend/event/client-request.ts +25 -0
- package/backend/event/consumable.ts +18 -0
- package/backend/event/consumer-scope.ts +54 -0
- package/backend/event/event-dispatcher.ts +26 -0
- package/backend/event/interaction-request-assignment.ts +24 -0
- package/backend/event/interaction-request-map.ts +75 -0
- package/backend/event/interaction-request.ts +48 -0
- package/backend/event/trigger-request.ts +56 -0
- package/backend/form/submit-interceptor.ts +66 -0
- package/backend/form-engine/container/files-control-container.ts +716 -0
- package/backend/form-engine/container/flex-form-container-container.ts +166 -0
- package/backend/form-engine/container/flex-form-section-container.ts +210 -0
- package/backend/form-engine/container/inline-control-container.ts +1230 -0
- package/backend/form-engine/container/site-language-container.ts +616 -0
- package/backend/form-engine/element/abstract-sortable-select-items.ts +186 -0
- package/backend/form-engine/element/category-element.ts +160 -0
- package/backend/form-engine/element/color-element.ts +81 -0
- package/backend/form-engine/element/datetime-element.ts +66 -0
- package/backend/form-engine/element/extra/char-counter.ts +112 -0
- package/backend/form-engine/element/extra/select-box-filter.ts +85 -0
- package/backend/form-engine/element/folder-element.ts +66 -0
- package/backend/form-engine/element/group-element.ts +47 -0
- package/backend/form-engine/element/json-element.ts +52 -0
- package/backend/form-engine/element/link-element.ts +121 -0
- package/backend/form-engine/element/mfa-info-element.ts +169 -0
- package/backend/form-engine/element/modifier/resizable.ts +27 -0
- package/backend/form-engine/element/modifier/tabbable.ts +29 -0
- package/backend/form-engine/element/online-media-form-element.ts +65 -0
- package/backend/form-engine/element/password-element.ts +71 -0
- package/backend/form-engine/element/select-multiple-side-by-side-element.ts +83 -0
- package/backend/form-engine/element/select-single-element.ts +82 -0
- package/backend/form-engine/element/select-tree-element.ts +148 -0
- package/backend/form-engine/element/select-tree-toolbar.ts +118 -0
- package/backend/form-engine/element/select-tree.ts +210 -0
- package/backend/form-engine/element/slug-element.ts +243 -0
- package/backend/form-engine/element/suggest/result-container.ts +118 -0
- package/backend/form-engine/element/suggest/result-item.ts +90 -0
- package/backend/form-engine/element/table-permission-element.ts +101 -0
- package/backend/form-engine/element/table-wizard-element.ts +427 -0
- package/backend/form-engine/element/text-element.ts +52 -0
- package/backend/form-engine/element/text-table-element.ts +31 -0
- package/backend/form-engine/field-control/add-record.ts +40 -0
- package/backend/form-engine/field-control/edit-popup.ts +64 -0
- package/backend/form-engine/field-control/insert-clipboard.ts +50 -0
- package/backend/form-engine/field-control/link-popup.ts +53 -0
- package/backend/form-engine/field-control/list-module.ts +40 -0
- package/backend/form-engine/field-control/password-generator.ts +102 -0
- package/backend/form-engine/field-control/reset-selection.ts +48 -0
- package/backend/form-engine/field-wizard/localization-state-selector.ts +67 -0
- package/backend/form-engine/field-wizard/value-picker.ts +123 -0
- package/backend/form-engine/field-wizard/value-slider.ts +86 -0
- package/backend/form-engine/inline-relation/ajax-dispatcher.ts +124 -0
- package/backend/form-engine/inline-relation/inline-response-interface.ts +41 -0
- package/backend/form-engine-link-browser-adapter.ts +129 -0
- package/backend/form-engine-review.ts +155 -0
- package/backend/form-engine-suggest.ts +133 -0
- package/backend/form-engine-validation.ts +686 -0
- package/backend/form-engine.ts +1391 -0
- package/backend/global-event-handler.ts +252 -0
- package/backend/grid-editor.ts +1077 -0
- package/backend/hashing/md5.ts +252 -0
- package/backend/helper.ts +24 -0
- package/backend/hotkeys/hotkey-storage.ts +63 -0
- package/backend/hotkeys.ts +216 -0
- package/backend/icons.ts +236 -0
- package/backend/image-manipulation.ts +885 -0
- package/backend/info-window.ts +46 -0
- package/backend/input/clearable.ts +128 -0
- package/backend/input/index.d.ts +8 -0
- package/backend/java-script-module-import-event-handler.ts +19 -0
- package/backend/key-bindings.ts +42 -0
- package/backend/layout-module/drag-drop.ts +359 -0
- package/backend/layout-module/paste.ts +165 -0
- package/backend/link-browser.ts +89 -0
- package/backend/live-search/element/backend-search.ts +34 -0
- package/backend/live-search/element/hint.ts +33 -0
- package/backend/live-search/element/provider/default-result-item.ts +52 -0
- package/backend/live-search/element/provider/page-provider-result-item.ts +52 -0
- package/backend/live-search/element/result/item/action/action-container.ts +135 -0
- package/backend/live-search/element/result/item/action/action.ts +56 -0
- package/backend/live-search/element/result/item/item-container.ts +224 -0
- package/backend/live-search/element/result/item/item.ts +74 -0
- package/backend/live-search/element/result/result-container.ts +110 -0
- package/backend/live-search/element/result/result-detail-container.ts +50 -0
- package/backend/live-search/element/result/result-pagination.ts +122 -0
- package/backend/live-search/element/search-option-item.ts +70 -0
- package/backend/live-search/live-search-configurator.ts +54 -0
- package/backend/live-search/live-search-shortcut.ts +29 -0
- package/backend/live-search/result-types/backend-module-result-type.ts +8 -0
- package/backend/live-search/result-types/default-result-type.ts +21 -0
- package/backend/live-search/result-types/page-result-type.ts +23 -0
- package/backend/localization.ts +390 -0
- package/backend/login-refresh.ts +525 -0
- package/backend/login.ts +179 -0
- package/backend/mail-link-handler.ts +45 -0
- package/backend/modal-interface.ts +19 -0
- package/backend/modal.ts +685 -0
- package/backend/module/iframe.ts +125 -0
- package/backend/module/router.ts +275 -0
- package/backend/module-menu.ts +550 -0
- package/backend/module.ts +133 -0
- package/backend/multi-record-selection-action.ts +44 -0
- package/backend/multi-record-selection-delete-action.ts +108 -0
- package/backend/multi-record-selection-edit-action.ts +56 -0
- package/backend/multi-record-selection.ts +468 -0
- package/backend/multi-step-wizard.ts +568 -0
- package/backend/new-content-element-wizard-button.ts +51 -0
- package/backend/new-multiple-pages.ts +108 -0
- package/backend/new-record-wizard.ts +680 -0
- package/backend/notification.ts +366 -0
- package/backend/offset.ts +40 -0
- package/backend/online-media.ts +110 -0
- package/backend/page-actions.ts +91 -0
- package/backend/page-link-handler.ts +51 -0
- package/backend/pagetsconfig/pagetsconfig-includes.ts +77 -0
- package/backend/popover.ts +165 -0
- package/backend/record-download-button.ts +104 -0
- package/backend/record-link-handler.ts +31 -0
- package/backend/record-search.ts +44 -0
- package/backend/recordlist.ts +230 -0
- package/backend/resource/resource.ts +35 -0
- package/backend/security/element/csp-reports.ts +406 -0
- package/backend/security/element/sudo-mode.ts +249 -0
- package/backend/security/sudo-mode-interceptor.ts +19 -0
- package/backend/settings/editor/editable-setting.ts +231 -0
- package/backend/settings/editor.ts +451 -0
- package/backend/settings/enum/settings-mode.enum.ts +24 -0
- package/backend/settings/type/base.ts +200 -0
- package/backend/settings/type/bool.ts +56 -0
- package/backend/settings/type/color.ts +64 -0
- package/backend/settings/type/int.ts +85 -0
- package/backend/settings/type/number.ts +61 -0
- package/backend/settings/type/page.ts +100 -0
- package/backend/settings/type/string.ts +77 -0
- package/backend/settings/type/stringlist.ts +87 -0
- package/backend/severity.ts +88 -0
- package/backend/site-inline-actions.ts +32 -0
- package/backend/sortable-table.ts +208 -0
- package/backend/storage/abstract-client-storage.ts +76 -0
- package/backend/storage/browser-session.ts +28 -0
- package/backend/storage/client.ts +28 -0
- package/backend/storage/module-state-storage.ts +118 -0
- package/backend/storage/persistent.ts +204 -0
- package/backend/switch-user.ts +82 -0
- package/backend/tabs.ts +72 -0
- package/backend/telephone-link-handler.ts +40 -0
- package/backend/tests/backend/storage/browser-storage-test.ts +87 -0
- package/backend/tests/backend/storage/client-test.ts +87 -0
- package/backend/tests/backend/utility/dom-helper-test.ts +51 -0
- package/backend/tests/backend-exception-test.ts +28 -0
- package/backend/tests/element/immediate-action-element-test.ts +81 -0
- package/backend/tests/form-engine-validation-test.ts +304 -0
- package/backend/tests/grid-editor-test.ts +29 -0
- package/backend/tests/hashing/md5Test.ts +28 -0
- package/backend/tests/icons-test.ts +23 -0
- package/backend/tests/notification-test.ts +161 -0
- package/backend/tests/popover-test.ts +83 -0
- package/backend/toolbar/clear-cache-menu.ts +88 -0
- package/backend/toolbar/live-search.ts +284 -0
- package/backend/toolbar/shortcut-menu.ts +254 -0
- package/backend/toolbar/system-information-menu.ts +161 -0
- package/backend/toolbar.ts +41 -0
- package/backend/tree/file-storage-browser.ts +194 -0
- package/backend/tree/file-storage-tree-container.ts +465 -0
- package/backend/tree/file-storage-tree.ts +42 -0
- package/backend/tree/page-browser.ts +272 -0
- package/backend/tree/page-tree-element.ts +602 -0
- package/backend/tree/page-tree.ts +152 -0
- package/backend/tree/tree-module-state.ts +159 -0
- package/backend/tree/tree-node-toggle.ts +31 -0
- package/backend/tree/tree-node.ts +97 -0
- package/backend/tree/tree-toolbar.ts +117 -0
- package/backend/tree/tree.ts +1595 -0
- package/backend/url-link-handler.ts +36 -0
- package/backend/user-pass-login.ts +255 -0
- package/backend/user-settings-manager.ts +189 -0
- package/backend/utility/collapse-state-persister.ts +205 -0
- package/backend/utility/collapse-state-search.ts +183 -0
- package/backend/utility/dom-helper.ts +91 -0
- package/backend/utility/drag-drop-utility.ts +47 -0
- package/backend/utility/message-utility.ts +45 -0
- package/backend/utility/top-level-module-import.ts +32 -0
- package/backend/utility.ts +194 -0
- package/backend/viewport/abstract-container.ts +22 -0
- package/backend/viewport/content-container.ts +98 -0
- package/backend/viewport/loader.ts +28 -0
- package/backend/viewport/navigation-container.ts +119 -0
- package/backend/viewport/resizable-navigation.ts +176 -0
- package/backend/viewport/toolbar.ts +27 -0
- package/backend/viewport/topbar.ts +39 -0
- package/backend/viewport.ts +46 -0
- package/backend/window-manager.ts +84 -0
- package/backend/wizard/move-content-element.ts +107 -0
- package/backend/wizard/move-page.ts +74 -0
- package/backend/wizard.ts +331 -0
- package/belog/backend-log.ts +88 -0
- package/beuser/backend-user-listing.ts +40 -0
- package/beuser/permissions.ts +291 -0
- package/core/ajax/ajax-request-types.ts +15 -0
- package/core/ajax/ajax-request.ts +202 -0
- package/core/ajax/ajax-response.ts +57 -0
- package/core/ajax/input-transformer.ts +92 -0
- package/core/ajax/simple-response-interface.ts +5 -0
- package/core/authentication/mfa-provider/totp.ts +54 -0
- package/core/cache/dedupe-async-task.ts +95 -0
- package/core/directive/markdown.ts +82 -0
- package/core/directive/nl2br.ts +16 -0
- package/core/document-service.ts +35 -0
- package/core/event/debounce-event.ts +40 -0
- package/core/event/event-interface.ts +24 -0
- package/core/event/regular-event.ts +58 -0
- package/core/event/request-animation-frame-event.ts +42 -0
- package/core/event/throttle-event.ts +54 -0
- package/core/java-script-item-handler.ts +29 -0
- package/core/java-script-item-processor.ts +171 -0
- package/core/lit-helper.ts +126 -0
- package/core/literals.ts +17 -0
- package/core/referrer-refresh.ts +2 -0
- package/core/security-utility.ts +89 -0
- package/core/tests/ajax/ajax-request-test.ts +290 -0
- package/core/tests/ajax/input-transformer-test.ts +64 -0
- package/core/tests/cache/dedupe-async-task-test.ts +152 -0
- package/core/tests/event/throttle-event-test.ts +47 -0
- package/core/tests/literals-test.ts +24 -0
- package/core/tests/security-utility-test.ts +50 -0
- package/core/utility/types.ts +9 -0
- package/dashboard/chart-initializer.ts +136 -0
- package/dashboard/dashboard.ts +1487 -0
- package/extensionmanager/distribution-image.ts +55 -0
- package/extensionmanager/main.ts +291 -0
- package/extensionmanager/repository.ts +195 -0
- package/extensionmanager/update.ts +118 -0
- package/extensionmanager/upload-form.ts +42 -0
- package/filelist/browse-files.ts +148 -0
- package/filelist/browse-folders.ts +94 -0
- package/filelist/context-menu-actions.ts +335 -0
- package/filelist/create-folder.ts +69 -0
- package/filelist/file-delete.ts +69 -0
- package/filelist/file-list-actions.ts +132 -0
- package/filelist/file-list-dragdrop.ts +139 -0
- package/filelist/file-list-rename-handler.ts +128 -0
- package/filelist/file-list-transfer-handler.ts +138 -0
- package/filelist/file-list.ts +396 -0
- package/filelist/file-replace.ts +37 -0
- package/filelist/linkbrowser-file-handler.ts +94 -0
- package/filelist/linkbrowser-folder-handler.ts +74 -0
- package/filelist/rename-file.ts +109 -0
- package/form/backend/form-editor/component/property-grid-editor.ts +340 -0
- package/form/backend/form-editor/core.ts +2104 -0
- package/form/backend/form-editor/helper.ts +226 -0
- package/form/backend/form-editor/inspector-component.ts +2323 -0
- package/form/backend/form-editor/mediator.ts +941 -0
- package/form/backend/form-editor/modals-component.ts +433 -0
- package/form/backend/form-editor/stage-component.ts +908 -0
- package/form/backend/form-editor/tree-component.ts +548 -0
- package/form/backend/form-editor/view-model.ts +1343 -0
- package/form/backend/form-editor.ts +846 -0
- package/form/backend/form-manager/main.ts +39 -0
- package/form/backend/form-manager/view-model.ts +789 -0
- package/form/backend/form-manager.ts +180 -0
- package/form/backend/helper.ts +60 -0
- package/form/frontend/date-picker.ts +38 -0
- package/frontend/default_frontend.ts +82 -0
- package/impexp/context-menu-actions.ts +50 -0
- package/impexp/import-export.ts +62 -0
- package/indexed-search/pagination.ts +26 -0
- package/indexed-search/statistics.ts +50 -0
- package/info/translation-status.ts +48 -0
- package/install/ajax/ajax-queue.ts +83 -0
- package/install/init-install.ts +2 -0
- package/install/init-installer.ts +2 -0
- package/install/install.ts +25 -0
- package/install/installer.ts +458 -0
- package/install/message-interface.ts +18 -0
- package/install/module/abstract-inline-module.ts +27 -0
- package/install/module/abstract-interactable-module.ts +107 -0
- package/install/module/environment/environment-check.ts +92 -0
- package/install/module/environment/folder-structure.ts +145 -0
- package/install/module/environment/image-processing.ts +141 -0
- package/install/module/environment/mail-test.ts +127 -0
- package/install/module/environment/php-info.ts +50 -0
- package/install/module/environment/system-information.ts +50 -0
- package/install/module/maintenance/cache.ts +59 -0
- package/install/module/maintenance/clear-tables.ts +134 -0
- package/install/module/maintenance/clear-typo3temp-files.ts +137 -0
- package/install/module/maintenance/create-admin.ts +126 -0
- package/install/module/maintenance/database-analyzer.ts +266 -0
- package/install/module/maintenance/dump-autoload.ts +58 -0
- package/install/module/maintenance/language-packs.ts +338 -0
- package/install/module/maintenance/reset-backend-user-uc.ts +58 -0
- package/install/module/password-strength.ts +56 -0
- package/install/module/settings/change-install-tool-password.ts +101 -0
- package/install/module/settings/extension-configuration.ts +224 -0
- package/install/module/settings/features.ts +102 -0
- package/install/module/settings/local-configuration.ts +316 -0
- package/install/module/settings/presets.ts +147 -0
- package/install/module/settings/system-maintainer.ts +111 -0
- package/install/module/upgrade/core-update.ts +255 -0
- package/install/module/upgrade/extension-compat-tester.ts +195 -0
- package/install/module/upgrade/extension-scanner.ts +381 -0
- package/install/module/upgrade/tca-ext-tables-check.ts +93 -0
- package/install/module/upgrade/tca-migrations-check.ts +101 -0
- package/install/module/upgrade/upgrade-docs.ts +310 -0
- package/install/module/upgrade/upgrade-wizards.ts +612 -0
- package/install/renderable/clearable.ts +113 -0
- package/install/renderable/flash-message.ts +64 -0
- package/install/renderable/info-box.ts +66 -0
- package/install/renderable/language-packs.ts +304 -0
- package/install/renderable/offset-group.ts +38 -0
- package/install/renderable/severity.ts +49 -0
- package/install/renderable/wrap-group.ts +36 -0
- package/install/router.ts +468 -0
- package/linkvalidator/linkvalidator-modal.ts +45 -0
- package/linkvalidator/linkvalidator.ts +101 -0
- package/lowlevel/query-generator.ts +132 -0
- package/lowlevel/reference-index.ts +44 -0
- package/opendocs/toolbar/opendocs-menu.ts +117 -0
- package/package.json +34 -0
- package/recycler/recycler.ts +539 -0
- package/redirects/event-handler.ts +108 -0
- package/redirects/form-engine-evaluation.ts +34 -0
- package/redirects/redirects-module.ts +58 -0
- package/rte-ckeditor/ckeditor5.ts +402 -0
- package/rte-ckeditor/css-prefixer.ts +94 -0
- package/rte-ckeditor/legacy/ckeditor5-bundle.ts +17 -0
- package/rte-ckeditor/legacy/ckeditor5-inspector.ts +2 -0
- package/rte-ckeditor/plugin/typo3-link.ts +810 -0
- package/rte-ckeditor/plugin/whitespace.ts +114 -0
- package/rte-ckeditor/rte-link-browser.ts +112 -0
- package/rte-ckeditor/tests/css-prefixer-test.ts +314 -0
- package/scheduler/scheduler-add-group.ts +119 -0
- package/scheduler/scheduler-editable-group-name.ts +307 -0
- package/scheduler/scheduler-sortable-groups.ts +59 -0
- package/scheduler/scheduler.ts +466 -0
- package/setup/setup-module.ts +122 -0
- package/styleguide/checkbox-demo.ts +5 -0
- package/styleguide/element/theme-switcher-element.ts +101 -0
- package/styleguide/filter.ts +22 -0
- package/styleguide/find-icons.ts +78 -0
- package/styleguide/processing-indicator.ts +78 -0
- package/styleguide/render-notifications.ts +64 -0
- package/sys-note/element/delete-button.ts +78 -0
- package/tstemplate/constant-editor.ts +64 -0
- package/tstemplate/information-module.ts +31 -0
- package/tstemplate/template-analyzer.ts +77 -0
- package/viewpage/main.ts +253 -0
- package/workspaces/backend.ts +979 -0
- package/workspaces/preview.ts +232 -0
- package/workspaces/renderable/comment-view.ts +79 -0
- package/workspaces/renderable/diff-view.ts +58 -0
- package/workspaces/renderable/history-view.ts +97 -0
- package/workspaces/renderable/record-information.ts +118 -0
- package/workspaces/renderable/record-table.ts +355 -0
- package/workspaces/renderable/send-to-stage-form.ts +108 -0
- package/workspaces/toolbar/workspaces-menu.ts +190 -0
- package/workspaces/utility/icon-helper.ts +57 -0
- package/workspaces/workspaces.ts +136 -0
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file is part of the TYPO3 CMS project.
|
|
3
|
+
*
|
|
4
|
+
* It is free software; you can redistribute it and/or modify it under
|
|
5
|
+
* the terms of the GNU General Public License, either version 2
|
|
6
|
+
* of the License, or any later version.
|
|
7
|
+
*
|
|
8
|
+
* For the full copyright and license information, please read the
|
|
9
|
+
* LICENSE.txt file that was distributed with this source code.
|
|
10
|
+
*
|
|
11
|
+
* The TYPO3 project - inspiring people to share!
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import FormEngine from '@typo3/backend/form-engine';
|
|
15
|
+
import FormEngineValidation from '@typo3/backend/form-engine-validation';
|
|
16
|
+
import RegularEvent from '@typo3/core/event/regular-event';
|
|
17
|
+
import { selector } from '@typo3/core/literals';
|
|
18
|
+
|
|
19
|
+
export abstract class AbstractSortableSelectItems {
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Moves currently selected options from a select field to the very top,
|
|
23
|
+
* can be multiple entries as well
|
|
24
|
+
*
|
|
25
|
+
* @param {HTMLSelectElement} fieldElement
|
|
26
|
+
*/
|
|
27
|
+
private static moveOptionToTop(fieldElement: HTMLSelectElement): void {
|
|
28
|
+
Array.from(fieldElement.querySelectorAll(':checked')).reverse().forEach((optionEl: HTMLOptionElement): void => {
|
|
29
|
+
fieldElement.insertBefore(optionEl, fieldElement.firstElementChild);
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Moves currently selected options from a select field as the very last entries
|
|
35
|
+
*
|
|
36
|
+
* @param {HTMLSelectElement} fieldElement
|
|
37
|
+
*/
|
|
38
|
+
private static moveOptionToBottom(fieldElement: HTMLSelectElement): void {
|
|
39
|
+
fieldElement.querySelectorAll(':checked').forEach((optionEl: HTMLOptionElement): void => {
|
|
40
|
+
fieldElement.insertBefore(optionEl, null);
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Moves currently selected options from a select field up by one position,
|
|
46
|
+
* can be multiple entries as well
|
|
47
|
+
*
|
|
48
|
+
* @param {HTMLSelectElement} fieldElement
|
|
49
|
+
*/
|
|
50
|
+
private static moveOptionUp(fieldElement: HTMLSelectElement): void {
|
|
51
|
+
const allChildren = Array.from(fieldElement.children);
|
|
52
|
+
const selectedOptions = Array.from(fieldElement.querySelectorAll(':checked'));
|
|
53
|
+
for (const optionEl of selectedOptions) {
|
|
54
|
+
if (allChildren.indexOf(optionEl) === 0 && optionEl.previousElementSibling === null) {
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
fieldElement.insertBefore(optionEl, optionEl.previousElementSibling);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Moves currently selected options from a select field up by one position,
|
|
64
|
+
* can be multiple entries as well
|
|
65
|
+
*
|
|
66
|
+
* @param {HTMLSelectElement} fieldElement
|
|
67
|
+
*/
|
|
68
|
+
private static moveOptionDown(fieldElement: HTMLSelectElement): void {
|
|
69
|
+
const allChildren = Array.from(fieldElement.children).reverse();
|
|
70
|
+
const selectedOptions = Array.from(fieldElement.querySelectorAll(':checked')).reverse();
|
|
71
|
+
for (const optionEl of selectedOptions) {
|
|
72
|
+
if (allChildren.indexOf(optionEl) === 0 && optionEl.nextElementSibling === null) {
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
fieldElement.insertBefore(optionEl, optionEl.nextElementSibling.nextElementSibling);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Removes currently selected options from a select field
|
|
82
|
+
*
|
|
83
|
+
* @param {HTMLSelectElement} fieldElement
|
|
84
|
+
* @param {HTMLSelectElement} availableFieldElement
|
|
85
|
+
*/
|
|
86
|
+
private static removeOption(fieldElement: HTMLSelectElement, availableFieldElement: HTMLSelectElement): void {
|
|
87
|
+
const previousSelectIndex = fieldElement.selectedIndex;
|
|
88
|
+
fieldElement.querySelectorAll(':checked').forEach((option: HTMLOptionElement): void => {
|
|
89
|
+
const originalOption = <HTMLOptionElement>availableFieldElement.querySelector(selector`option[value="${option.value}"]`);
|
|
90
|
+
if (originalOption !== null) {
|
|
91
|
+
originalOption.classList.remove('hidden');
|
|
92
|
+
originalOption.disabled = false;
|
|
93
|
+
FormEngine.enableOptGroup(originalOption);
|
|
94
|
+
}
|
|
95
|
+
fieldElement.removeChild(option);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
// set the next selected option to the previous sibling removed
|
|
99
|
+
fieldElement.selectedIndex = previousSelectIndex > 0 ? (previousSelectIndex - 1) : 0;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* @param {HTMLSelectElement} fieldElement
|
|
104
|
+
*/
|
|
105
|
+
protected registerSortableEventHandler = (fieldElement: HTMLSelectElement): void => {
|
|
106
|
+
this.registerKeyboardEventHandler(fieldElement);
|
|
107
|
+
|
|
108
|
+
const aside = fieldElement.closest('.form-wizards-wrap').querySelector('.form-wizards-item-aside');
|
|
109
|
+
if (aside === null) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
aside.addEventListener('click', (e: Event): void => {
|
|
114
|
+
const target: HTMLButtonElement = (<Element>e.target).closest('.t3js-btn-option');
|
|
115
|
+
if (target === null) {
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
e.preventDefault();
|
|
120
|
+
|
|
121
|
+
const relatedFieldName = target.dataset.fieldname;
|
|
122
|
+
const relatedField = FormEngine.getFieldElement(relatedFieldName).get(0) as HTMLSelectElement;
|
|
123
|
+
const relatedAvailableValuesField = FormEngine.getFieldElement(relatedFieldName,'_avail').get(0) as HTMLSelectElement;
|
|
124
|
+
|
|
125
|
+
if (target.classList.contains('t3js-btn-moveoption-top')) {
|
|
126
|
+
AbstractSortableSelectItems.moveOptionToTop(fieldElement);
|
|
127
|
+
} else if (target.classList.contains('t3js-btn-moveoption-up')) {
|
|
128
|
+
AbstractSortableSelectItems.moveOptionUp(fieldElement);
|
|
129
|
+
} else if (target.classList.contains('t3js-btn-moveoption-down')) {
|
|
130
|
+
AbstractSortableSelectItems.moveOptionDown(fieldElement);
|
|
131
|
+
} else if (target.classList.contains('t3js-btn-moveoption-bottom')) {
|
|
132
|
+
AbstractSortableSelectItems.moveOptionToBottom(fieldElement);
|
|
133
|
+
} else if (target.classList.contains('t3js-btn-removeoption')) {
|
|
134
|
+
AbstractSortableSelectItems.removeOption(
|
|
135
|
+
fieldElement,
|
|
136
|
+
relatedAvailableValuesField,
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
FormEngine.updateHiddenFieldValueFromSelect(fieldElement, relatedField);
|
|
141
|
+
FormEngineValidation.markFieldAsChanged(relatedAvailableValuesField);
|
|
142
|
+
FormEngineValidation.validateField(relatedAvailableValuesField);
|
|
143
|
+
});
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* @param {HTMLSelectElement} fieldElement
|
|
148
|
+
*/
|
|
149
|
+
private readonly registerKeyboardEventHandler = (fieldElement: HTMLSelectElement): void => {
|
|
150
|
+
const relatedFieldName = fieldElement.dataset.formengineInputName;
|
|
151
|
+
const relatedField = FormEngine.getFieldElement(relatedFieldName).get(0) as HTMLSelectElement;
|
|
152
|
+
const relatedAvailableValuesField = FormEngine.getFieldElement(relatedFieldName,'_avail').get(0) as HTMLSelectElement;
|
|
153
|
+
|
|
154
|
+
new RegularEvent('keydown', (e: KeyboardEvent): void => {
|
|
155
|
+
if (e.code === 'Delete' || e.code === 'Backspace') {
|
|
156
|
+
e.preventDefault();
|
|
157
|
+
AbstractSortableSelectItems.removeOption(
|
|
158
|
+
fieldElement,
|
|
159
|
+
relatedAvailableValuesField,
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
if (e.code === 'ArrowUp' && e.altKey) {
|
|
163
|
+
e.preventDefault();
|
|
164
|
+
AbstractSortableSelectItems.moveOptionUp(fieldElement);
|
|
165
|
+
}
|
|
166
|
+
if (e.code === 'ArrowDown' && e.altKey) {
|
|
167
|
+
e.preventDefault();
|
|
168
|
+
AbstractSortableSelectItems.moveOptionDown(fieldElement);
|
|
169
|
+
}
|
|
170
|
+
if (e.code === 'ArrowUp' && e.altKey && e.shiftKey) {
|
|
171
|
+
e.preventDefault();
|
|
172
|
+
AbstractSortableSelectItems.moveOptionToTop(fieldElement);
|
|
173
|
+
}
|
|
174
|
+
if (e.code === 'ArrowDown' && e.altKey && e.shiftKey) {
|
|
175
|
+
e.preventDefault();
|
|
176
|
+
AbstractSortableSelectItems.moveOptionToBottom(fieldElement);
|
|
177
|
+
}
|
|
178
|
+
if (e.defaultPrevented) {
|
|
179
|
+
FormEngine.updateHiddenFieldValueFromSelect(fieldElement, relatedField);
|
|
180
|
+
FormEngineValidation.markFieldAsChanged(relatedAvailableValuesField);
|
|
181
|
+
FormEngineValidation.validateField(relatedAvailableValuesField);
|
|
182
|
+
}
|
|
183
|
+
}).bindTo(fieldElement);
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file is part of the TYPO3 CMS project.
|
|
3
|
+
*
|
|
4
|
+
* It is free software; you can redistribute it and/or modify it under
|
|
5
|
+
* the terms of the GNU General Public License, either version 2
|
|
6
|
+
* of the License, or any later version.
|
|
7
|
+
*
|
|
8
|
+
* For the full copyright and license information, please read the
|
|
9
|
+
* LICENSE.txt file that was distributed with this source code.
|
|
10
|
+
*
|
|
11
|
+
* The TYPO3 project - inspiring people to share!
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import DocumentService from '@typo3/core/document-service';
|
|
15
|
+
import { selector } from '@typo3/core/literals';
|
|
16
|
+
import { type SelectTree } from './select-tree';
|
|
17
|
+
import { type SelectTreeToolbar } from './select-tree-toolbar';
|
|
18
|
+
import '@typo3/backend/element/icon-element';
|
|
19
|
+
import type { TreeNodeInterface } from '@typo3/backend/tree/tree-node';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Module: @typo3/backend/form-engine/element/category-element
|
|
23
|
+
*
|
|
24
|
+
* Functionality for the category element (renders a tree view)
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* <typo3-formengine-element-category recordFieldId="some-id" treeWrapperId="some-id">
|
|
28
|
+
* ...
|
|
29
|
+
* </typo3-formengine-element-category>
|
|
30
|
+
*
|
|
31
|
+
* This is based on W3C custom elements ("web components") specification, see
|
|
32
|
+
* https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements
|
|
33
|
+
*/
|
|
34
|
+
class CategoryElement extends HTMLElement {
|
|
35
|
+
private recordField: HTMLInputElement = null;
|
|
36
|
+
private treeWrapper: HTMLElement = null;
|
|
37
|
+
private tree: SelectTree = null;
|
|
38
|
+
|
|
39
|
+
public async connectedCallback(): Promise<void> {
|
|
40
|
+
if (this.tree !== null) {
|
|
41
|
+
// Element is already initialized, which means the component has been rendered before. Nothing to do here.
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
await DocumentService.ready();
|
|
46
|
+
this.recordField = <HTMLInputElement>this.querySelector(selector`#${this.getAttribute('recordFieldId') || '' as string}`);
|
|
47
|
+
this.treeWrapper = <HTMLElement>this.querySelector(selector`#${this.getAttribute('treeWrapperId') || '' as string}`);
|
|
48
|
+
|
|
49
|
+
if (!this.recordField || !this.treeWrapper) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
this.tree = document.createElement('typo3-backend-form-selecttree') as SelectTree;
|
|
54
|
+
this.tree.classList.add('tree-wrapper');
|
|
55
|
+
this.tree.setup = {
|
|
56
|
+
id: this.treeWrapper.id,
|
|
57
|
+
dataUrl: this.generateDataUrl(),
|
|
58
|
+
readOnlyMode: this.recordField.dataset.readOnly,
|
|
59
|
+
input: this.recordField,
|
|
60
|
+
exclusiveNodesIdentifiers: this.recordField.dataset.treeExclusiveKeys,
|
|
61
|
+
validation: JSON.parse(this.recordField.dataset.formengineValidationRules)[0],
|
|
62
|
+
expandUpToLevel: this.recordField.dataset.treeExpandUpToLevel,
|
|
63
|
+
unselectableElements: [] as Array<any>
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
this.treeWrapper.append(this.tree);
|
|
67
|
+
this.registerTreeEventListeners();
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
private registerTreeEventListeners(): void {
|
|
71
|
+
this.tree.addEventListener('typo3:tree:nodes-prepared', this.loadDataAfter);
|
|
72
|
+
this.tree.addEventListener('typo3:tree:node-selected', this.selectNode);
|
|
73
|
+
this.tree.addEventListener('tree:initialized', () => {
|
|
74
|
+
if (this.recordField.dataset.treeShowToolbar) {
|
|
75
|
+
const toolbarElement = document.createElement('typo3-backend-form-selecttree-toolbar') as SelectTreeToolbar;
|
|
76
|
+
toolbarElement.tree = this.tree;
|
|
77
|
+
this.tree.prepend(toolbarElement);
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
private generateDataUrl(): string {
|
|
83
|
+
return TYPO3.settings.ajaxUrls.record_tree_data + '&' + new URLSearchParams({
|
|
84
|
+
uid: this.recordField.dataset.uid,
|
|
85
|
+
command: this.recordField.dataset.command,
|
|
86
|
+
tableName: this.recordField.dataset.tablename,
|
|
87
|
+
fieldName: this.recordField.dataset.fieldname,
|
|
88
|
+
defaultValues: this.recordField.dataset.defaultvalues,
|
|
89
|
+
overrideValues: this.recordField.dataset.overridevalues,
|
|
90
|
+
recordTypeValue: this.recordField.dataset.recordtypevalue,
|
|
91
|
+
flexFormSheetName: this.recordField.dataset.flexformsheetname,
|
|
92
|
+
flexFormFieldName: this.recordField.dataset.flexformfieldname,
|
|
93
|
+
flexFormContainerName: this.recordField.dataset.flexformcontainername,
|
|
94
|
+
dataStructureIdentifier: this.recordField.dataset.datastructureidentifier,
|
|
95
|
+
flexFormContainerFieldName: this.recordField.dataset.flexformcontainerfieldname,
|
|
96
|
+
flexFormContainerIdentifier: this.recordField.dataset.flexformcontaineridentifier,
|
|
97
|
+
flexFormSectionContainerIsNew: this.recordField.dataset.flexformsectioncontainerisnew,
|
|
98
|
+
}).toString();
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
private readonly selectNode = (evt: CustomEvent) => {
|
|
102
|
+
const node = evt.detail.node as TreeNodeInterface;
|
|
103
|
+
this.updateAncestorsIndeterminateState(node);
|
|
104
|
+
// check all nodes again, to ensure correct display of __indeterminate state
|
|
105
|
+
this.calculateIndeterminate(this.tree.nodes);
|
|
106
|
+
this.saveCheckboxes();
|
|
107
|
+
this.tree.setup.input.dispatchEvent(new Event('change', { bubbles: true, cancelable: true }));
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Resets the node.__indeterminate for the whole tree.
|
|
112
|
+
* It's done once after loading data.
|
|
113
|
+
* Later __indeterminate state is updated just for the subset of nodes
|
|
114
|
+
*/
|
|
115
|
+
private readonly loadDataAfter = (evt: CustomEvent) => {
|
|
116
|
+
this.tree.nodes = evt.detail.nodes.map((node: TreeNodeInterface) => {
|
|
117
|
+
node.__indeterminate = false;
|
|
118
|
+
return node;
|
|
119
|
+
});
|
|
120
|
+
this.calculateIndeterminate(this.tree.nodes);
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Sets a comma-separated list of selected nodes identifiers to configured input
|
|
125
|
+
*/
|
|
126
|
+
private readonly saveCheckboxes = (): void => {
|
|
127
|
+
this.recordField.value = this.tree.getSelectedNodes().map((node: TreeNodeInterface): string => node.identifier).join(',');
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Updates the __indeterminate state for ancestors of the current node
|
|
132
|
+
*/
|
|
133
|
+
private updateAncestorsIndeterminateState(node: TreeNodeInterface): void {
|
|
134
|
+
// foreach ancestor except node itself
|
|
135
|
+
let __indeterminate = false;
|
|
136
|
+
node.__treeParents.forEach((treeIdentifier: string) => {
|
|
137
|
+
const TreeNodeInterface = this.tree.getNodeByTreeIdentifier(treeIdentifier);
|
|
138
|
+
TreeNodeInterface.__indeterminate = (node.checked || node.__indeterminate || __indeterminate);
|
|
139
|
+
// check state for the next level
|
|
140
|
+
__indeterminate = (TreeNodeInterface.checked || TreeNodeInterface.__indeterminate || node.checked || node.__indeterminate);
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Sets __indeterminate state for a subtree.
|
|
146
|
+
* It relays on the tree to have __indeterminate state reset beforehand.
|
|
147
|
+
*/
|
|
148
|
+
private calculateIndeterminate(nodes: ReadonlyArray<TreeNodeInterface>): void {
|
|
149
|
+
nodes.forEach((node: TreeNodeInterface) => {
|
|
150
|
+
if ((node.checked || node.__indeterminate) && node.__treeParents && node.__treeParents.length > 0) {
|
|
151
|
+
node.__treeParents.forEach((treeParentIdentifier: string) => {
|
|
152
|
+
const TreeNodeInterface = this.tree.getNodeByTreeIdentifier(treeParentIdentifier);
|
|
153
|
+
TreeNodeInterface.__indeterminate = true;
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
window.customElements.define('typo3-formengine-element-category', CategoryElement);
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file is part of the TYPO3 CMS project.
|
|
3
|
+
*
|
|
4
|
+
* It is free software; you can redistribute it and/or modify it under
|
|
5
|
+
* the terms of the GNU General Public License, either version 2
|
|
6
|
+
* of the License, or any later version.
|
|
7
|
+
*
|
|
8
|
+
* For the full copyright and license information, please read the
|
|
9
|
+
* LICENSE.txt file that was distributed with this source code.
|
|
10
|
+
*
|
|
11
|
+
* The TYPO3 project - inspiring people to share!
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import DocumentService from '@typo3/core/document-service';
|
|
15
|
+
import RegularEvent from '@typo3/core/event/regular-event';
|
|
16
|
+
import FormEngineValidation from '@typo3/backend/form-engine-validation';
|
|
17
|
+
import { selector } from '@typo3/core/literals';
|
|
18
|
+
import '@typo3/backend/color-picker';
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Module: @typo3/backend/form-engine/element/color-element
|
|
22
|
+
*
|
|
23
|
+
* Functionality for the color element
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* <typo3-formengine-element-color recordFieldId="some-id">
|
|
27
|
+
* ...
|
|
28
|
+
* </typo3-formengine-element-color>
|
|
29
|
+
*
|
|
30
|
+
* This is based on W3C custom elements ("web components") specification, see
|
|
31
|
+
* https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements
|
|
32
|
+
*/
|
|
33
|
+
class ColorElement extends HTMLElement {
|
|
34
|
+
private element: HTMLInputElement = null;
|
|
35
|
+
|
|
36
|
+
public async connectedCallback(): Promise<void> {
|
|
37
|
+
if (this.element !== null) {
|
|
38
|
+
// Element is already initialized, which means the component has been rendered before. Nothing to do here.
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const recordFieldId = this.getAttribute('recordFieldId');
|
|
43
|
+
if (recordFieldId === null) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
await DocumentService.ready();
|
|
48
|
+
this.element = this.querySelector<HTMLInputElement>(selector`#${recordFieldId}`);
|
|
49
|
+
if (!this.element) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
this.registerEventHandler();
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
private registerEventHandler(): void {
|
|
57
|
+
const hiddenElement: HTMLInputElement|null = document.querySelector(selector`input[name="${this.element.dataset.formengineInputName}"]`);
|
|
58
|
+
|
|
59
|
+
new RegularEvent('blur', (e: Event): void => {
|
|
60
|
+
hiddenElement.value = (e.target as HTMLInputElement).value;
|
|
61
|
+
this.handleEvent(e);
|
|
62
|
+
}).bindTo(this.element);
|
|
63
|
+
|
|
64
|
+
new RegularEvent('formengine.cp.change', (e: Event): void => {
|
|
65
|
+
this.handleEvent(e);
|
|
66
|
+
}).bindTo(this.element);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
private handleEvent(e: Event): void {
|
|
71
|
+
FormEngineValidation.validateField(e.target as HTMLInputElement);
|
|
72
|
+
FormEngineValidation.markFieldAsChanged(e.target as HTMLInputElement);
|
|
73
|
+
|
|
74
|
+
document.querySelectorAll('.module-docheader-bar .btn').forEach((btn: HTMLButtonElement): void => {
|
|
75
|
+
btn.classList.remove('disabled');
|
|
76
|
+
btn.disabled = false;
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
window.customElements.define('typo3-formengine-element-color', ColorElement);
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file is part of the TYPO3 CMS project.
|
|
3
|
+
*
|
|
4
|
+
* It is free software; you can redistribute it and/or modify it under
|
|
5
|
+
* the terms of the GNU General Public License, either version 2
|
|
6
|
+
* of the License, or any later version.
|
|
7
|
+
*
|
|
8
|
+
* For the full copyright and license information, please read the
|
|
9
|
+
* LICENSE.txt file that was distributed with this source code.
|
|
10
|
+
*
|
|
11
|
+
* The TYPO3 project - inspiring people to share!
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import DocumentService from '@typo3/core/document-service';
|
|
15
|
+
import FormEngineValidation from '@typo3/backend/form-engine-validation';
|
|
16
|
+
import RegularEvent from '@typo3/core/event/regular-event';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Module: @typo3/backend/form-engine/element/datetime-element
|
|
20
|
+
*
|
|
21
|
+
* Functionality for the datetime element
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* <typo3-formengine-element-datetime recordFieldId="some-id">
|
|
25
|
+
* ...
|
|
26
|
+
* </typo3-formengine-element-datetime>
|
|
27
|
+
*
|
|
28
|
+
* This is based on W3C custom elements ("web components") specification, see
|
|
29
|
+
* https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements
|
|
30
|
+
*/
|
|
31
|
+
class DatetimeElement extends HTMLElement {
|
|
32
|
+
private element: HTMLInputElement = null;
|
|
33
|
+
|
|
34
|
+
public async connectedCallback(): Promise<void> {
|
|
35
|
+
if (this.element !== null) {
|
|
36
|
+
// Element is already initialized, which means the component has been rendered before. Nothing to do here.
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
await DocumentService.ready();
|
|
41
|
+
this.element = document.getElementById((this.getAttribute('recordFieldId') || '' as string)) as HTMLInputElement;
|
|
42
|
+
|
|
43
|
+
if (!this.element) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
this.registerEventHandler();
|
|
48
|
+
import('../../date-time-picker').then(({ default: DateTimePicker }): void => {
|
|
49
|
+
DateTimePicker.initialize(this.element);
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
private registerEventHandler(): void {
|
|
54
|
+
new RegularEvent('formengine.dp.change', (e: CustomEvent): void => {
|
|
55
|
+
FormEngineValidation.validateField(e.target as HTMLInputElement);
|
|
56
|
+
FormEngineValidation.markFieldAsChanged(e.target as HTMLInputElement);
|
|
57
|
+
|
|
58
|
+
document.querySelectorAll('.module-docheader-bar .btn').forEach((btn: HTMLButtonElement): void => {
|
|
59
|
+
btn.classList.remove('disabled');
|
|
60
|
+
btn.disabled = false;
|
|
61
|
+
});
|
|
62
|
+
}).bindTo(this.element);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
window.customElements.define('typo3-formengine-element-datetime', DatetimeElement);
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file is part of the TYPO3 CMS project.
|
|
3
|
+
*
|
|
4
|
+
* It is free software; you can redistribute it and/or modify it under
|
|
5
|
+
* the terms of the GNU General Public License, either version 2
|
|
6
|
+
* of the License, or any later version.
|
|
7
|
+
*
|
|
8
|
+
* For the full copyright and license information, please read the
|
|
9
|
+
* LICENSE.txt file that was distributed with this source code.
|
|
10
|
+
*
|
|
11
|
+
* The TYPO3 project - inspiring people to share!
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { customElement, property, state } from 'lit/decorators';
|
|
15
|
+
import { html, LitElement, type TemplateResult } from 'lit';
|
|
16
|
+
import { lll } from '@typo3/core/lit-helper';
|
|
17
|
+
|
|
18
|
+
@customElement('typo3-backend-formengine-char-counter')
|
|
19
|
+
export class CharCounter extends LitElement {
|
|
20
|
+
@property() target: string;
|
|
21
|
+
@state() private remainingCharacters: number = 0;
|
|
22
|
+
|
|
23
|
+
private targetElement: HTMLInputElement|HTMLTextAreaElement = null;
|
|
24
|
+
private readonly threshold = 15;
|
|
25
|
+
|
|
26
|
+
public override connectedCallback(): void {
|
|
27
|
+
super.connectedCallback();
|
|
28
|
+
this.registerCallbacks();
|
|
29
|
+
|
|
30
|
+
this.hidden = true;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
public override disconnectedCallback(): void {
|
|
34
|
+
super.disconnectedCallback();
|
|
35
|
+
this.removeCallbacks();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
protected override createRenderRoot(): HTMLElement | ShadowRoot {
|
|
39
|
+
return this;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
protected override updated(changedProperties: Map<string, any>): void {
|
|
43
|
+
if (changedProperties.has('target')) {
|
|
44
|
+
this.removeCallbacks();
|
|
45
|
+
this.targetElement = document.querySelector(this.target);
|
|
46
|
+
this.registerCallbacks();
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
protected override render(): TemplateResult {
|
|
51
|
+
return html`
|
|
52
|
+
<span class="form-hint form-hint--${this.determineCounterClass()}">
|
|
53
|
+
${lll(('FormEngine.remainingCharacters')).replace('{0}', this.remainingCharacters.toString(10))}
|
|
54
|
+
</span>
|
|
55
|
+
`;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
private registerCallbacks(): void {
|
|
59
|
+
if (this.targetElement === null) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
this.targetElement.addEventListener('input', this.onInput);
|
|
63
|
+
this.targetElement.addEventListener('focus', this.onFocus);
|
|
64
|
+
this.targetElement.addEventListener('blur', this.onBlur);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
private removeCallbacks(): void {
|
|
68
|
+
if (this.targetElement === null) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
this.targetElement.removeEventListener('input', this.onInput);
|
|
72
|
+
this.targetElement.removeEventListener('focus', this.onFocus);
|
|
73
|
+
this.targetElement.removeEventListener('blur', this.onBlur);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
private readonly onInput = (e: InputEvent): void => {
|
|
77
|
+
this.determineRemainingCharacters(e.target as HTMLInputElement|HTMLTextAreaElement);
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
private readonly onFocus = (e: FocusEvent): void => {
|
|
81
|
+
this.determineRemainingCharacters(e.target as HTMLInputElement|HTMLTextAreaElement);
|
|
82
|
+
this.hidden = false;
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
private readonly onBlur = (): void => {
|
|
86
|
+
this.hidden = true;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
private determineRemainingCharacters(field: HTMLInputElement|HTMLTextAreaElement): void {
|
|
90
|
+
const fieldText = field.value;
|
|
91
|
+
const currentFieldLength = fieldText.length;
|
|
92
|
+
const numberOfLineBreaks = (fieldText.match(/\n/g) || []).length;
|
|
93
|
+
|
|
94
|
+
this.remainingCharacters = this.targetElement.maxLength - currentFieldLength - numberOfLineBreaks;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
private determineCounterClass(): string {
|
|
98
|
+
if (this.remainingCharacters < this.threshold) {
|
|
99
|
+
return 'danger';
|
|
100
|
+
}
|
|
101
|
+
if (this.remainingCharacters < this.threshold * 2) {
|
|
102
|
+
return 'warning';
|
|
103
|
+
}
|
|
104
|
+
return 'info';
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
declare global {
|
|
109
|
+
interface HTMLElementTagNameMap {
|
|
110
|
+
'typo3-backend-formengine-char-counter': CharCounter;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file is part of the TYPO3 CMS project.
|
|
3
|
+
*
|
|
4
|
+
* It is free software; you can redistribute it and/or modify it under
|
|
5
|
+
* the terms of the GNU General Public License, either version 2
|
|
6
|
+
* of the License, or any later version.
|
|
7
|
+
*
|
|
8
|
+
* For the full copyright and license information, please read the
|
|
9
|
+
* LICENSE.txt file that was distributed with this source code.
|
|
10
|
+
*
|
|
11
|
+
* The TYPO3 project - inspiring people to share!
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import RegularEvent from '@typo3/core/event/regular-event';
|
|
15
|
+
|
|
16
|
+
enum Selectors {
|
|
17
|
+
fieldContainerSelector = '.t3js-formengine-field-group',
|
|
18
|
+
filterTextFieldSelector = '.t3js-formengine-multiselect-filter-textfield',
|
|
19
|
+
filterSelectFieldSelector = '.t3js-formengine-multiselect-filter-dropdown',
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Select field filter functions, see TCA option "multiSelectFilterItems"
|
|
24
|
+
*/
|
|
25
|
+
class SelectBoxFilter {
|
|
26
|
+
private readonly selectElement: HTMLSelectElement = null;
|
|
27
|
+
private availableOptions: NodeListOf<HTMLOptionElement> = null;
|
|
28
|
+
|
|
29
|
+
constructor(selectElement: HTMLSelectElement) {
|
|
30
|
+
this.selectElement = selectElement;
|
|
31
|
+
|
|
32
|
+
this.initializeEvents();
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
private static toggleOptGroup(option: HTMLOptionElement): void {
|
|
36
|
+
const optGroup = <HTMLOptGroupElement>option.parentElement;
|
|
37
|
+
if (!(optGroup instanceof HTMLOptGroupElement)) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
if (optGroup.querySelectorAll('option:not([hidden]):not([disabled]):not(.hidden)').length === 0) {
|
|
41
|
+
optGroup.hidden = true;
|
|
42
|
+
} else {
|
|
43
|
+
optGroup.hidden = false;
|
|
44
|
+
optGroup.disabled = false;
|
|
45
|
+
optGroup.classList.remove('hidden');
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
private initializeEvents(): void {
|
|
50
|
+
const wizardsElement = this.selectElement.closest('.form-wizards-wrap');
|
|
51
|
+
if (wizardsElement === null) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
new RegularEvent('input', (e: Event): void => {
|
|
56
|
+
this.filter((<HTMLInputElement>e.target).value);
|
|
57
|
+
}).delegateTo(wizardsElement, Selectors.filterTextFieldSelector);
|
|
58
|
+
|
|
59
|
+
new RegularEvent('change', (e: Event): void => {
|
|
60
|
+
this.filter((<HTMLInputElement>e.target).value);
|
|
61
|
+
}).delegateTo(wizardsElement, Selectors.filterSelectFieldSelector);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Filter the actual items
|
|
66
|
+
*
|
|
67
|
+
* @param {string} filterText
|
|
68
|
+
*/
|
|
69
|
+
private filter(filterText: string): void {
|
|
70
|
+
if (this.availableOptions === null) {
|
|
71
|
+
this.availableOptions = this.selectElement.querySelectorAll('option');
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Escape filter text to prevent RegExp() exceptions
|
|
75
|
+
const escapedFilterText = filterText.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
76
|
+
|
|
77
|
+
const matchFilter = new RegExp(escapedFilterText, 'i');
|
|
78
|
+
this.availableOptions.forEach((option: HTMLOptionElement): void => {
|
|
79
|
+
option.hidden = filterText.length > 0 && option.textContent.match(matchFilter) === null;
|
|
80
|
+
SelectBoxFilter.toggleOptGroup(option);
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export default SelectBoxFilter;
|