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,83 @@
|
|
|
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 { AbstractSortableSelectItems } from './abstract-sortable-select-items';
|
|
15
|
+
import DocumentService from '@typo3/core/document-service';
|
|
16
|
+
import FormEngine from '@typo3/backend/form-engine';
|
|
17
|
+
import SelectBoxFilter from './extra/select-box-filter';
|
|
18
|
+
import RegularEvent from '@typo3/core/event/regular-event';
|
|
19
|
+
import Utility from '@typo3/backend/utility';
|
|
20
|
+
|
|
21
|
+
class SelectMultipleSideBySideElement extends AbstractSortableSelectItems {
|
|
22
|
+
private selectedOptionsElement: HTMLSelectElement = null;
|
|
23
|
+
private availableOptionsElement: HTMLSelectElement = null;
|
|
24
|
+
|
|
25
|
+
constructor(selectedOptionsElementId: string, availableOptionsElementId: string) {
|
|
26
|
+
super();
|
|
27
|
+
|
|
28
|
+
DocumentService.ready().then((document: Document): void => {
|
|
29
|
+
this.selectedOptionsElement = <HTMLSelectElement>document.getElementById(selectedOptionsElementId);
|
|
30
|
+
this.availableOptionsElement = <HTMLSelectElement>document.getElementById(availableOptionsElementId);
|
|
31
|
+
if (this.selectedOptionsElement === null || this.availableOptionsElement === null) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
this.registerEventHandler();
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
private registerEventHandler(): void {
|
|
39
|
+
this.registerSortableEventHandler(this.selectedOptionsElement);
|
|
40
|
+
this.registerKeyboardEvents();
|
|
41
|
+
|
|
42
|
+
this.availableOptionsElement.addEventListener('click', (e: Event): void => {
|
|
43
|
+
const el = <HTMLSelectElement>e.currentTarget;
|
|
44
|
+
this.handleOptionChecked(el);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
// tslint:disable-next-line:no-unused-expression
|
|
48
|
+
new SelectBoxFilter(this.availableOptionsElement);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
private handleOptionChecked(element: HTMLSelectElement): void {
|
|
52
|
+
const fieldName = element.dataset.relatedfieldname;
|
|
53
|
+
if (fieldName) {
|
|
54
|
+
const exclusiveValues = Utility.trimExplode(',', element.dataset?.exclusivevalues ?? '');
|
|
55
|
+
const selectedOptions = element.querySelectorAll('option:checked'); // Yep, :checked finds selected options
|
|
56
|
+
if (selectedOptions.length > 0) {
|
|
57
|
+
selectedOptions.forEach((optionElement: HTMLOptionElement): void => {
|
|
58
|
+
FormEngine.setSelectOptionFromExternalSource(
|
|
59
|
+
fieldName,
|
|
60
|
+
optionElement.value,
|
|
61
|
+
optionElement.textContent,
|
|
62
|
+
optionElement.getAttribute('title'),
|
|
63
|
+
exclusiveValues,
|
|
64
|
+
optionElement,
|
|
65
|
+
);
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
private registerKeyboardEvents(): void {
|
|
72
|
+
new RegularEvent('keydown', (e: KeyboardEvent): void => {
|
|
73
|
+
const el = <HTMLSelectElement>e.currentTarget;
|
|
74
|
+
if (e.code === 'Enter') {
|
|
75
|
+
e.preventDefault();
|
|
76
|
+
this.handleOptionChecked(el);
|
|
77
|
+
}
|
|
78
|
+
}).bindTo(this.availableOptionsElement);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export default SelectMultipleSideBySideElement;
|
|
@@ -0,0 +1,82 @@
|
|
|
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
|
+
import DocumentService from '@typo3/core/document-service';
|
|
16
|
+
import FormEngine, { type OnFieldChangeItem } from '@typo3/backend/form-engine';
|
|
17
|
+
import { selector } from '@typo3/core/literals';
|
|
18
|
+
|
|
19
|
+
interface SelectSingleElementOptions {
|
|
20
|
+
onChange?: OnFieldChangeItem[];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Module: @typo3/backend/form-engine/element/select-single-element
|
|
25
|
+
* Logic for SelectSingleElement
|
|
26
|
+
*/
|
|
27
|
+
class SelectSingleElement {
|
|
28
|
+
public initializeOnReady(selector: string, options: SelectSingleElementOptions): void {
|
|
29
|
+
DocumentService.ready().then(() => {
|
|
30
|
+
this.initialize(selector, options);
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
public initialize = (elementSelector: string, options: SelectSingleElementOptions): void => {
|
|
35
|
+
const selectElement: HTMLSelectElement = document.querySelector(elementSelector);
|
|
36
|
+
if (selectElement === null) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
options = options || {};
|
|
40
|
+
|
|
41
|
+
new RegularEvent('change', (e: Event): void => {
|
|
42
|
+
const target = e.target as HTMLSelectElement;
|
|
43
|
+
const groupIconContainer: HTMLElement = target.parentElement.querySelector('.input-group-icon');
|
|
44
|
+
|
|
45
|
+
// Update prepended select icon
|
|
46
|
+
if (groupIconContainer !== null) {
|
|
47
|
+
groupIconContainer.innerHTML = (target.options[target.selectedIndex].dataset.icon);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const selectIcons: HTMLElement = target.closest('.t3js-formengine-field-item').querySelector('.t3js-forms-select-single-icons');
|
|
51
|
+
if (selectIcons !== null) {
|
|
52
|
+
const activeItem = selectIcons.querySelector('.form-wizard-icon-list-item button.active, .form-wizard-icon-list-item a.active');
|
|
53
|
+
if (activeItem !== null) {
|
|
54
|
+
activeItem.classList.remove('active');
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const selectionIcon = selectIcons.querySelector(selector`[data-select-index="${target.selectedIndex.toString(10)}"]`);
|
|
58
|
+
if (selectionIcon !== null) {
|
|
59
|
+
selectionIcon.closest('.form-wizard-icon-list-item button, .form-wizard-icon-list-item a').classList.add('active');
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}).bindTo(selectElement);
|
|
63
|
+
|
|
64
|
+
if (options.onChange instanceof Array) {
|
|
65
|
+
// hand `OnFieldChange` processing over to `FormEngine`
|
|
66
|
+
new RegularEvent('change', () => FormEngine.processOnFieldChange(options.onChange)).bindTo(selectElement);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
new RegularEvent('click', (e: Event, target: HTMLAnchorElement): void => {
|
|
70
|
+
const currentActive = target.closest('.t3js-forms-select-single-icons').querySelector('.form-wizard-icon-list-item button.active, .form-wizard-icon-list-item a.active');
|
|
71
|
+
if (currentActive !== null) {
|
|
72
|
+
currentActive.classList.remove('active');
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
selectElement.selectedIndex = parseInt(target.dataset.selectIndex, 10);
|
|
76
|
+
selectElement.dispatchEvent(new Event('change'));
|
|
77
|
+
target.closest('.form-wizard-icon-list-item button, .form-wizard-icon-list-item a').classList.add('active');
|
|
78
|
+
}).delegateTo(selectElement.closest('.form-control-wrap'), '.t3js-forms-select-single-icons .form-wizard-icon-list-item button:not(.active), .t3js-forms-select-single-icons .form-wizard-icon-list-item a:not(.active)');
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export default new SelectSingleElement();
|
|
@@ -0,0 +1,148 @@
|
|
|
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 { type SelectTree } from './select-tree';
|
|
15
|
+
import { type SelectTreeToolbar } from './select-tree-toolbar';
|
|
16
|
+
import '@typo3/backend/element/icon-element';
|
|
17
|
+
import DocumentService from '@typo3/core/document-service';
|
|
18
|
+
import FormEngine, { type OnFieldChangeItem } from '@typo3/backend/form-engine';
|
|
19
|
+
import type { TreeNodeInterface } from '@typo3/backend/tree/tree-node';
|
|
20
|
+
|
|
21
|
+
export class SelectTreeElement {
|
|
22
|
+
private recordField: HTMLInputElement = null;
|
|
23
|
+
private tree: SelectTree = null;
|
|
24
|
+
|
|
25
|
+
constructor(treeWrapperId: string, treeRecordFieldId: string, callback?: () => void, onFieldChangeItems?: OnFieldChangeItem[]) {
|
|
26
|
+
if (callback instanceof Function) {
|
|
27
|
+
throw new Error('Function `callback` is not supported anymore since TYPO3 v12.0');
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
DocumentService.ready().then((): void => {
|
|
31
|
+
this.initialize(treeWrapperId, treeRecordFieldId, onFieldChangeItems);
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
private initialize(treeWrapperId: string, treeRecordFieldId: string, onFieldChangeItems?: OnFieldChangeItem[]): void {
|
|
36
|
+
this.recordField = <HTMLInputElement>document.getElementById(treeRecordFieldId);
|
|
37
|
+
const treeWrapper = <HTMLElement>document.getElementById(treeWrapperId);
|
|
38
|
+
this.tree = document.createElement('typo3-backend-form-selecttree') as SelectTree;
|
|
39
|
+
this.tree.classList.add('tree-wrapper');
|
|
40
|
+
this.tree.addEventListener('typo3:tree:nodes-prepared', this.loadDataAfter);
|
|
41
|
+
this.tree.addEventListener('typo3:tree:node-selected', this.selectNode);
|
|
42
|
+
|
|
43
|
+
if (onFieldChangeItems instanceof Array) {
|
|
44
|
+
this.tree.addEventListener('typo3:tree:node-selected', () => { FormEngine.processOnFieldChange(onFieldChangeItems); } );
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const settings = {
|
|
48
|
+
id: treeWrapperId,
|
|
49
|
+
dataUrl: this.generateRequestUrl(),
|
|
50
|
+
readOnlyMode: parseInt(this.recordField.dataset.readOnly, 10) === 1,
|
|
51
|
+
input: this.recordField,
|
|
52
|
+
exclusiveNodesIdentifiers: this.recordField.dataset.treeExclusiveKeys,
|
|
53
|
+
validation: JSON.parse(this.recordField.dataset.formengineValidationRules)[0],
|
|
54
|
+
expandUpToLevel: this.recordField.dataset.treeExpandUpToLevel,
|
|
55
|
+
unselectableElements: [] as Array<any>
|
|
56
|
+
};
|
|
57
|
+
this.tree.addEventListener('tree:initialized', () => {
|
|
58
|
+
if (this.recordField.dataset.treeShowToolbar) {
|
|
59
|
+
const toolbarElement = document.createElement('typo3-backend-form-selecttree-toolbar') as SelectTreeToolbar;
|
|
60
|
+
toolbarElement.tree = this.tree;
|
|
61
|
+
this.tree.prepend(toolbarElement);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
this.tree.setup = settings;
|
|
65
|
+
treeWrapper.append(this.tree);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
private generateRequestUrl(): string {
|
|
69
|
+
const params = {
|
|
70
|
+
tableName: this.recordField.dataset.tablename,
|
|
71
|
+
fieldName: this.recordField.dataset.fieldname,
|
|
72
|
+
uid: this.recordField.dataset.uid,
|
|
73
|
+
defaultValues: this.recordField.dataset.defaultvalues,
|
|
74
|
+
overrideValues: this.recordField.dataset.overridevalues,
|
|
75
|
+
recordTypeValue: this.recordField.dataset.recordtypevalue,
|
|
76
|
+
dataStructureIdentifier: this.recordField.dataset.datastructureidentifier,
|
|
77
|
+
flexFormSheetName: this.recordField.dataset.flexformsheetname,
|
|
78
|
+
flexFormFieldName: this.recordField.dataset.flexformfieldname,
|
|
79
|
+
flexFormContainerName: this.recordField.dataset.flexformcontainername,
|
|
80
|
+
flexFormContainerIdentifier: this.recordField.dataset.flexformcontaineridentifier,
|
|
81
|
+
flexFormContainerFieldName: this.recordField.dataset.flexformcontainerfieldname,
|
|
82
|
+
flexFormSectionContainerIsNew: this.recordField.dataset.flexformsectioncontainerisnew,
|
|
83
|
+
command: this.recordField.dataset.command,
|
|
84
|
+
};
|
|
85
|
+
return TYPO3.settings.ajaxUrls.record_tree_data + '&' + new URLSearchParams(params).toString();
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
private readonly selectNode = (evt: CustomEvent) => {
|
|
89
|
+
const node = evt.detail.node as TreeNodeInterface;
|
|
90
|
+
this.updateAncestorsIndeterminateState(node);
|
|
91
|
+
// check all nodes again, to ensure correct display of __indeterminate state
|
|
92
|
+
this.calculateIndeterminate(this.tree.nodes);
|
|
93
|
+
this.saveCheckboxes();
|
|
94
|
+
this.tree.setup.input.dispatchEvent(new Event('change', { bubbles: true, cancelable: true }));
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Resets the node.__indeterminate for the whole tree.
|
|
99
|
+
* It's done once after loading data.
|
|
100
|
+
* Later __indeterminate state is updated just for the subset of nodes
|
|
101
|
+
*/
|
|
102
|
+
private readonly loadDataAfter = (evt: CustomEvent) => {
|
|
103
|
+
this.tree.nodes = evt.detail.nodes.map((node: TreeNodeInterface) => {
|
|
104
|
+
node.__indeterminate = false;
|
|
105
|
+
return node;
|
|
106
|
+
});
|
|
107
|
+
this.calculateIndeterminate(this.tree.nodes);
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Sets a comma-separated list of selected nodes identifiers to configured input
|
|
112
|
+
*/
|
|
113
|
+
private readonly saveCheckboxes = (): void => {
|
|
114
|
+
if (typeof this.recordField === 'undefined') {
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
this.recordField.value = this.tree.getSelectedNodes().map((node: TreeNodeInterface): string => node.identifier).join(',');
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Updates the __indeterminate state for ancestors of the current node
|
|
122
|
+
*/
|
|
123
|
+
private updateAncestorsIndeterminateState(node: TreeNodeInterface): void {
|
|
124
|
+
// foreach ancestor except node itself
|
|
125
|
+
let __indeterminate = false;
|
|
126
|
+
node.__treeParents.forEach((treeParentIdentifier: string) => {
|
|
127
|
+
const TreeNodeInterface = this.tree.getNodeByTreeIdentifier(treeParentIdentifier);
|
|
128
|
+
TreeNodeInterface.__indeterminate = (node.checked || node.__indeterminate || __indeterminate);
|
|
129
|
+
// check state for the next level
|
|
130
|
+
__indeterminate = (TreeNodeInterface.checked || TreeNodeInterface.__indeterminate || node.checked || node.__indeterminate);
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Sets __indeterminate state for a subtree.
|
|
136
|
+
* It relays on the tree to have __indeterminate state reset beforehand.
|
|
137
|
+
*/
|
|
138
|
+
private calculateIndeterminate(nodes: ReadonlyArray<TreeNodeInterface>): void {
|
|
139
|
+
nodes.forEach((node: TreeNodeInterface) => {
|
|
140
|
+
if ((node.checked || node.__indeterminate) && node.__treeParents && node.__treeParents.length > 0) {
|
|
141
|
+
node.__treeParents.forEach((treeParentIdentifier: string) => {
|
|
142
|
+
const TreeNodeInterface = this.tree.getNodeByTreeIdentifier(treeParentIdentifier);
|
|
143
|
+
TreeNodeInterface.__indeterminate = true;
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
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 { html, LitElement, type TemplateResult } from 'lit';
|
|
15
|
+
import { customElement } from 'lit/decorators';
|
|
16
|
+
import { lll } from '@typo3/core/lit-helper';
|
|
17
|
+
import type { SelectTree } from './select-tree';
|
|
18
|
+
import type { TreeNodeInterface } from '../../tree/tree-node';
|
|
19
|
+
|
|
20
|
+
@customElement('typo3-backend-form-selecttree-toolbar')
|
|
21
|
+
export class SelectTreeToolbar extends LitElement {
|
|
22
|
+
public tree: SelectTree;
|
|
23
|
+
private readonly settings = {
|
|
24
|
+
collapseAllBtn: 'collapse-all-btn',
|
|
25
|
+
expandAllBtn: 'expand-all-btn',
|
|
26
|
+
searchInput: 'search-input',
|
|
27
|
+
toggleHideUnchecked: 'hide-unchecked-btn'
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* State of the hide unchecked toggle button
|
|
32
|
+
*
|
|
33
|
+
* @type {boolean}
|
|
34
|
+
*/
|
|
35
|
+
private hideUncheckedState: boolean = false;
|
|
36
|
+
|
|
37
|
+
// disable shadow dom for now
|
|
38
|
+
protected override createRenderRoot(): HTMLElement | ShadowRoot {
|
|
39
|
+
return this;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
protected override render(): TemplateResult {
|
|
43
|
+
return html`
|
|
44
|
+
<div class="tree-toolbar btn-toolbar">
|
|
45
|
+
<div class="input-group">
|
|
46
|
+
<span class="input-group-text input-group-icon filter">
|
|
47
|
+
<typo3-backend-icon identifier="actions-filter" size="small"></typo3-backend-icon>
|
|
48
|
+
</span>
|
|
49
|
+
<input type="search" class="form-control ${this.settings.searchInput}" placeholder="${lll('tcatree.findItem')}" @input="${(evt: InputEvent) => this.filter(evt)}">
|
|
50
|
+
</div>
|
|
51
|
+
<div class="btn-group">
|
|
52
|
+
<button type="button" class="btn btn-default ${this.settings.expandAllBtn}" title="${lll('tcatree.expandAll')}" @click="${() => this.expandAll()}">
|
|
53
|
+
<typo3-backend-icon identifier="apps-pagetree-category-expand-all" size="small"></typo3-backend-icon>
|
|
54
|
+
</button>
|
|
55
|
+
<button type="button" class="btn btn-default ${this.settings.collapseAllBtn}" title="${lll('tcatree.collapseAll')}" @click="${(evt: MouseEvent) => this.collapseAll(evt)}">
|
|
56
|
+
<typo3-backend-icon identifier="apps-pagetree-category-collapse-all" size="small"></typo3-backend-icon>
|
|
57
|
+
</button>
|
|
58
|
+
<button type="button" class="btn btn-default ${this.settings.toggleHideUnchecked}" title="${lll('tcatree.toggleHideUnchecked')}" @click="${() => this.toggleHideUnchecked()}">
|
|
59
|
+
<typo3-backend-icon identifier="apps-pagetree-category-toggle-hide-checked" size="small"></typo3-backend-icon>
|
|
60
|
+
</button>
|
|
61
|
+
</div>
|
|
62
|
+
</div>
|
|
63
|
+
`;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Collapse children of root node
|
|
68
|
+
*/
|
|
69
|
+
private collapseAll(evt: MouseEvent): void {
|
|
70
|
+
evt.preventDefault();
|
|
71
|
+
// Only collapse nodes that aren't on the root level
|
|
72
|
+
this.tree.nodes.forEach((node: TreeNodeInterface) => {
|
|
73
|
+
if (node.__parents.length) {
|
|
74
|
+
this.tree.hideChildren(node);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Expand all nodes
|
|
82
|
+
*/
|
|
83
|
+
private expandAll() {
|
|
84
|
+
this.tree.expandAll();
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
private filter(event: InputEvent): void {
|
|
88
|
+
const inputEl = <HTMLInputElement>event.target;
|
|
89
|
+
this.tree.filter(inputEl.value.trim());
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Show only checked items
|
|
94
|
+
*/
|
|
95
|
+
private toggleHideUnchecked(): void {
|
|
96
|
+
this.hideUncheckedState = !this.hideUncheckedState;
|
|
97
|
+
if (this.hideUncheckedState) {
|
|
98
|
+
this.tree.nodes.forEach((node: any) => {
|
|
99
|
+
if (node.checked) {
|
|
100
|
+
this.tree.showParents(node);
|
|
101
|
+
node.expanded = true;
|
|
102
|
+
node.__hidden = false;
|
|
103
|
+
} else {
|
|
104
|
+
node.expanded = false;
|
|
105
|
+
node.__hidden = true;
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
} else {
|
|
109
|
+
this.tree.nodes.forEach((node: any) => node.__hidden = false);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
declare global {
|
|
115
|
+
interface HTMLElementTagNameMap {
|
|
116
|
+
'typo3-backend-form-selecttree-toolbar': SelectTreeToolbar;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
@@ -0,0 +1,210 @@
|
|
|
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 { html, type TemplateResult } from 'lit';
|
|
15
|
+
import { Tree, type TreeSettings } from '@typo3/backend/tree/tree';
|
|
16
|
+
import { customElement, state } from 'lit/decorators';
|
|
17
|
+
import type { TreeNodeInterface } from '@typo3/backend/tree/tree-node';
|
|
18
|
+
|
|
19
|
+
interface SelectTreeSettings extends TreeSettings {
|
|
20
|
+
exclusiveNodesIdentifiers: '';
|
|
21
|
+
validation: {[keys: string]: any};
|
|
22
|
+
unselectableElements: Array<any>,
|
|
23
|
+
readOnlyMode: false
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
@customElement('typo3-backend-form-selecttree')
|
|
27
|
+
export class SelectTree extends Tree
|
|
28
|
+
{
|
|
29
|
+
@state() override settings: SelectTreeSettings = {
|
|
30
|
+
unselectableElements: [],
|
|
31
|
+
exclusiveNodesIdentifiers: '',
|
|
32
|
+
validation: {},
|
|
33
|
+
readOnlyMode: false,
|
|
34
|
+
showIcons: true,
|
|
35
|
+
width: 300,
|
|
36
|
+
dataUrl: '',
|
|
37
|
+
defaultProperties: {},
|
|
38
|
+
expandUpToLevel: null as any,
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Exclusive node which is currently selected
|
|
43
|
+
*/
|
|
44
|
+
@state() exclusiveSelectedNode: TreeNodeInterface = null;
|
|
45
|
+
|
|
46
|
+
constructor() {
|
|
47
|
+
super();
|
|
48
|
+
this.addEventListener('typo3:tree:nodes-prepared', this.prepareLoadedNodes);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Expand all nodes and refresh view
|
|
53
|
+
*/
|
|
54
|
+
public expandAll(): void {
|
|
55
|
+
this.nodes.forEach((node: TreeNodeInterface) => { this.showChildren(node); });
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Node selection logic (triggered by different events) to select multiple
|
|
60
|
+
* nodes (unlike SVG Tree itself).
|
|
61
|
+
*/
|
|
62
|
+
public override selectNode(node: TreeNodeInterface, propagate: boolean = true): void {
|
|
63
|
+
if (!this.isNodeSelectable(node)) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const checked = node.checked;
|
|
68
|
+
this.handleExclusiveNodeSelection(node);
|
|
69
|
+
|
|
70
|
+
if (this.settings.validation && this.settings.validation.maxItems) {
|
|
71
|
+
if (!checked && this.getSelectedNodes().length >= this.settings.validation.maxItems) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
node.checked = !checked;
|
|
77
|
+
this.dispatchEvent(new CustomEvent('typo3:tree:node-selected', { detail: { node: node, propagate: propagate } }));
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
public override filter(searchTerm?: string|null): void {
|
|
81
|
+
const results: TreeNodeInterface[] = [];
|
|
82
|
+
this.searchTerm = searchTerm;
|
|
83
|
+
if (this.nodes.length) {
|
|
84
|
+
this.nodes[0].__expanded = false;
|
|
85
|
+
}
|
|
86
|
+
const firstNode = this.nodes[0];
|
|
87
|
+
const regex = new RegExp(searchTerm, 'i');
|
|
88
|
+
|
|
89
|
+
this.nodes.forEach((node: any) => {
|
|
90
|
+
// skip the root node in searches
|
|
91
|
+
if (node === firstNode) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
node.__expanded = false;
|
|
96
|
+
node.__hidden = true;
|
|
97
|
+
|
|
98
|
+
if (regex.test(node.name)) {
|
|
99
|
+
results.push(node);
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
results.forEach((node) => {
|
|
104
|
+
node.__hidden = false;
|
|
105
|
+
this.showParents(node);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
// filter for children of results and show them
|
|
109
|
+
const children = this.nodes.filter(node => results.some(result => node.__parents.includes(result.identifier)));
|
|
110
|
+
children.forEach((child) => {
|
|
111
|
+
child.__hidden = false;
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Finds and show all parents of node
|
|
117
|
+
*/
|
|
118
|
+
public showParents(node: any): void {
|
|
119
|
+
if (node.__parents.length === 0) {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
const parent = this.nodes.find((searchNode) => searchNode.identifier === node.__parents.at(-1));
|
|
123
|
+
parent.__hidden = false;
|
|
124
|
+
parent.__expanded = true;
|
|
125
|
+
this.showParents(parent);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Check whether node can be selected.
|
|
130
|
+
* In some cases (e.g. selecting a parent) it should not be possible to select
|
|
131
|
+
* element (as it's own parent).
|
|
132
|
+
*/
|
|
133
|
+
protected override isNodeSelectable(node: TreeNodeInterface): boolean {
|
|
134
|
+
return !this.settings.readOnlyMode && this.settings.unselectableElements.indexOf(node.identifier) === -1;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Add checkbox before the icon
|
|
139
|
+
*/
|
|
140
|
+
protected override createNodeContent(node: TreeNodeInterface): TemplateResult {
|
|
141
|
+
return html`
|
|
142
|
+
${this.renderCheckbox(node)}
|
|
143
|
+
${super.createNodeContent(node)}
|
|
144
|
+
`;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Adds svg elements for checkbox rendering.
|
|
149
|
+
*/
|
|
150
|
+
private renderCheckbox(node: TreeNodeInterface): TemplateResult {
|
|
151
|
+
const checked = Boolean(node.checked);
|
|
152
|
+
|
|
153
|
+
let icon = 'actions-square';
|
|
154
|
+
if (!this.isNodeSelectable(node) && !checked) {
|
|
155
|
+
icon = 'actions-minus-circle';
|
|
156
|
+
} else if (node.checked) {
|
|
157
|
+
icon = 'actions-check-square';
|
|
158
|
+
} else if (node.__indeterminate && !checked) {
|
|
159
|
+
icon = 'actions-minus-square';
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return html`
|
|
163
|
+
<span class="node-select">
|
|
164
|
+
<typo3-backend-icon identifier="${icon}" size="small"></typo3-backend-icon>
|
|
165
|
+
</span>
|
|
166
|
+
`;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Check if a node has all information to be used.
|
|
171
|
+
*/
|
|
172
|
+
private prepareLoadedNodes(evt: CustomEvent): void {
|
|
173
|
+
const nodes = evt.detail.nodes as Array<TreeNodeInterface>;
|
|
174
|
+
evt.detail.nodes = nodes.map((node: TreeNodeInterface) => {
|
|
175
|
+
if (node.selectable === false) {
|
|
176
|
+
this.settings.unselectableElements.push(node.identifier);
|
|
177
|
+
}
|
|
178
|
+
return node;
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Handle exclusive nodes functionality
|
|
184
|
+
* If a node is one of the exclusiveNodesIdentifiers list,
|
|
185
|
+
* all other nodes has to be unselected before selecting this node.
|
|
186
|
+
*
|
|
187
|
+
* @param {Node} node
|
|
188
|
+
*/
|
|
189
|
+
private handleExclusiveNodeSelection(node: TreeNodeInterface): void {
|
|
190
|
+
const exclusiveKeys = this.settings.exclusiveNodesIdentifiers.split(',');
|
|
191
|
+
if (this.settings.exclusiveNodesIdentifiers.length && node.checked === false) {
|
|
192
|
+
if (exclusiveKeys.indexOf('' + node.identifier) > -1) {
|
|
193
|
+
// this key is exclusive, so uncheck all others
|
|
194
|
+
this.resetSelectedNodes();
|
|
195
|
+
this.exclusiveSelectedNode = node;
|
|
196
|
+
} else if (exclusiveKeys.indexOf('' + node.identifier) === -1 && this.exclusiveSelectedNode) {
|
|
197
|
+
|
|
198
|
+
// current node is not exclusive, but other exclusive node is already selected
|
|
199
|
+
this.exclusiveSelectedNode.checked = false;
|
|
200
|
+
this.exclusiveSelectedNode = null;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
declare global {
|
|
207
|
+
interface HTMLElementTagNameMap {
|
|
208
|
+
'typo3-backend-form-selecttree': SelectTree;
|
|
209
|
+
}
|
|
210
|
+
}
|