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.
Files changed (415) hide show
  1. package/.github/workflows/sync-and-publish.yml +265 -0
  2. package/.last-synced-tag +1 -0
  3. package/LICENSE.txt +339 -0
  4. package/README-TYPO3.md +166 -0
  5. package/README.md +28 -0
  6. package/adminpanel/admin-panel.ts +375 -0
  7. package/adminpanel/modules/cache.ts +27 -0
  8. package/adminpanel/modules/preview.ts +75 -0
  9. package/backend/action-button/abstract-action.ts +22 -0
  10. package/backend/action-button/deferred-action.ts +41 -0
  11. package/backend/action-button/immediate-action.ts +31 -0
  12. package/backend/action-dispatcher.ts +104 -0
  13. package/backend/ajax-data-handler/message-interface.ts +18 -0
  14. package/backend/ajax-data-handler/response-interface.ts +20 -0
  15. package/backend/ajax-data-handler.ts +214 -0
  16. package/backend/backend-exception.ts +22 -0
  17. package/backend/broadcast-message.ts +50 -0
  18. package/backend/broadcast-service.ts +52 -0
  19. package/backend/browse-database.ts +38 -0
  20. package/backend/clear-cache.ts +88 -0
  21. package/backend/clipboard-panel.ts +240 -0
  22. package/backend/close-current-window.ts +2 -0
  23. package/backend/code-editor/autocomplete/completion-result.ts +105 -0
  24. package/backend/code-editor/autocomplete/ts-code-completion.ts +142 -0
  25. package/backend/code-editor/autocomplete/ts-parser.ts +485 -0
  26. package/backend/code-editor/autocomplete/ts-ref.ts +164 -0
  27. package/backend/code-editor/element/code-mirror-element.ts +282 -0
  28. package/backend/code-editor/language/typoscript.ts +181 -0
  29. package/backend/code-editor/stream-parser/typoscript.ts +1600 -0
  30. package/backend/color-picker.ts +158 -0
  31. package/backend/color-scheme-switch.ts +179 -0
  32. package/backend/column-selector-button.ts +302 -0
  33. package/backend/context-help.ts +68 -0
  34. package/backend/context-menu-actions.ts +322 -0
  35. package/backend/context-menu.ts +751 -0
  36. package/backend/copy-to-clipboard.ts +79 -0
  37. package/backend/date-time-picker.ts +270 -0
  38. package/backend/document-save-actions.ts +159 -0
  39. package/backend/drag-tooltip.ts +285 -0
  40. package/backend/drag-uploader.ts +914 -0
  41. package/backend/element/alert-element.ts +116 -0
  42. package/backend/element/dispatch-modal-button.ts +50 -0
  43. package/backend/element/draggable-resizable-element.ts +249 -0
  44. package/backend/element/editable-page-title.ts +306 -0
  45. package/backend/element/icon-element.ts +84 -0
  46. package/backend/element/immediate-action-element.ts +89 -0
  47. package/backend/element/pagination.ts +59 -0
  48. package/backend/element/progress-bar-element.ts +172 -0
  49. package/backend/element/progress-tracker-element.ts +119 -0
  50. package/backend/element/pseudo-button.ts +58 -0
  51. package/backend/element/spinner-element.ts +51 -0
  52. package/backend/element/thumbnail-element.ts +80 -0
  53. package/backend/element-browser.ts +182 -0
  54. package/backend/enum/data-transfer-types.ts +21 -0
  55. package/backend/enum/icon-types.ts +31 -0
  56. package/backend/enum/key-types.ts +27 -0
  57. package/backend/enum/severity.ts +20 -0
  58. package/backend/enum/viewport/scaffold-identifier.ts +24 -0
  59. package/backend/event/client-request.ts +25 -0
  60. package/backend/event/consumable.ts +18 -0
  61. package/backend/event/consumer-scope.ts +54 -0
  62. package/backend/event/event-dispatcher.ts +26 -0
  63. package/backend/event/interaction-request-assignment.ts +24 -0
  64. package/backend/event/interaction-request-map.ts +75 -0
  65. package/backend/event/interaction-request.ts +48 -0
  66. package/backend/event/trigger-request.ts +56 -0
  67. package/backend/form/submit-interceptor.ts +66 -0
  68. package/backend/form-engine/container/files-control-container.ts +716 -0
  69. package/backend/form-engine/container/flex-form-container-container.ts +166 -0
  70. package/backend/form-engine/container/flex-form-section-container.ts +210 -0
  71. package/backend/form-engine/container/inline-control-container.ts +1230 -0
  72. package/backend/form-engine/container/site-language-container.ts +616 -0
  73. package/backend/form-engine/element/abstract-sortable-select-items.ts +186 -0
  74. package/backend/form-engine/element/category-element.ts +160 -0
  75. package/backend/form-engine/element/color-element.ts +81 -0
  76. package/backend/form-engine/element/datetime-element.ts +66 -0
  77. package/backend/form-engine/element/extra/char-counter.ts +112 -0
  78. package/backend/form-engine/element/extra/select-box-filter.ts +85 -0
  79. package/backend/form-engine/element/folder-element.ts +66 -0
  80. package/backend/form-engine/element/group-element.ts +47 -0
  81. package/backend/form-engine/element/json-element.ts +52 -0
  82. package/backend/form-engine/element/link-element.ts +121 -0
  83. package/backend/form-engine/element/mfa-info-element.ts +169 -0
  84. package/backend/form-engine/element/modifier/resizable.ts +27 -0
  85. package/backend/form-engine/element/modifier/tabbable.ts +29 -0
  86. package/backend/form-engine/element/online-media-form-element.ts +65 -0
  87. package/backend/form-engine/element/password-element.ts +71 -0
  88. package/backend/form-engine/element/select-multiple-side-by-side-element.ts +83 -0
  89. package/backend/form-engine/element/select-single-element.ts +82 -0
  90. package/backend/form-engine/element/select-tree-element.ts +148 -0
  91. package/backend/form-engine/element/select-tree-toolbar.ts +118 -0
  92. package/backend/form-engine/element/select-tree.ts +210 -0
  93. package/backend/form-engine/element/slug-element.ts +243 -0
  94. package/backend/form-engine/element/suggest/result-container.ts +118 -0
  95. package/backend/form-engine/element/suggest/result-item.ts +90 -0
  96. package/backend/form-engine/element/table-permission-element.ts +101 -0
  97. package/backend/form-engine/element/table-wizard-element.ts +427 -0
  98. package/backend/form-engine/element/text-element.ts +52 -0
  99. package/backend/form-engine/element/text-table-element.ts +31 -0
  100. package/backend/form-engine/field-control/add-record.ts +40 -0
  101. package/backend/form-engine/field-control/edit-popup.ts +64 -0
  102. package/backend/form-engine/field-control/insert-clipboard.ts +50 -0
  103. package/backend/form-engine/field-control/link-popup.ts +53 -0
  104. package/backend/form-engine/field-control/list-module.ts +40 -0
  105. package/backend/form-engine/field-control/password-generator.ts +102 -0
  106. package/backend/form-engine/field-control/reset-selection.ts +48 -0
  107. package/backend/form-engine/field-wizard/localization-state-selector.ts +67 -0
  108. package/backend/form-engine/field-wizard/value-picker.ts +123 -0
  109. package/backend/form-engine/field-wizard/value-slider.ts +86 -0
  110. package/backend/form-engine/inline-relation/ajax-dispatcher.ts +124 -0
  111. package/backend/form-engine/inline-relation/inline-response-interface.ts +41 -0
  112. package/backend/form-engine-link-browser-adapter.ts +129 -0
  113. package/backend/form-engine-review.ts +155 -0
  114. package/backend/form-engine-suggest.ts +133 -0
  115. package/backend/form-engine-validation.ts +686 -0
  116. package/backend/form-engine.ts +1391 -0
  117. package/backend/global-event-handler.ts +252 -0
  118. package/backend/grid-editor.ts +1077 -0
  119. package/backend/hashing/md5.ts +252 -0
  120. package/backend/helper.ts +24 -0
  121. package/backend/hotkeys/hotkey-storage.ts +63 -0
  122. package/backend/hotkeys.ts +216 -0
  123. package/backend/icons.ts +236 -0
  124. package/backend/image-manipulation.ts +885 -0
  125. package/backend/info-window.ts +46 -0
  126. package/backend/input/clearable.ts +128 -0
  127. package/backend/input/index.d.ts +8 -0
  128. package/backend/java-script-module-import-event-handler.ts +19 -0
  129. package/backend/key-bindings.ts +42 -0
  130. package/backend/layout-module/drag-drop.ts +359 -0
  131. package/backend/layout-module/paste.ts +165 -0
  132. package/backend/link-browser.ts +89 -0
  133. package/backend/live-search/element/backend-search.ts +34 -0
  134. package/backend/live-search/element/hint.ts +33 -0
  135. package/backend/live-search/element/provider/default-result-item.ts +52 -0
  136. package/backend/live-search/element/provider/page-provider-result-item.ts +52 -0
  137. package/backend/live-search/element/result/item/action/action-container.ts +135 -0
  138. package/backend/live-search/element/result/item/action/action.ts +56 -0
  139. package/backend/live-search/element/result/item/item-container.ts +224 -0
  140. package/backend/live-search/element/result/item/item.ts +74 -0
  141. package/backend/live-search/element/result/result-container.ts +110 -0
  142. package/backend/live-search/element/result/result-detail-container.ts +50 -0
  143. package/backend/live-search/element/result/result-pagination.ts +122 -0
  144. package/backend/live-search/element/search-option-item.ts +70 -0
  145. package/backend/live-search/live-search-configurator.ts +54 -0
  146. package/backend/live-search/live-search-shortcut.ts +29 -0
  147. package/backend/live-search/result-types/backend-module-result-type.ts +8 -0
  148. package/backend/live-search/result-types/default-result-type.ts +21 -0
  149. package/backend/live-search/result-types/page-result-type.ts +23 -0
  150. package/backend/localization.ts +390 -0
  151. package/backend/login-refresh.ts +525 -0
  152. package/backend/login.ts +179 -0
  153. package/backend/mail-link-handler.ts +45 -0
  154. package/backend/modal-interface.ts +19 -0
  155. package/backend/modal.ts +685 -0
  156. package/backend/module/iframe.ts +125 -0
  157. package/backend/module/router.ts +275 -0
  158. package/backend/module-menu.ts +550 -0
  159. package/backend/module.ts +133 -0
  160. package/backend/multi-record-selection-action.ts +44 -0
  161. package/backend/multi-record-selection-delete-action.ts +108 -0
  162. package/backend/multi-record-selection-edit-action.ts +56 -0
  163. package/backend/multi-record-selection.ts +468 -0
  164. package/backend/multi-step-wizard.ts +568 -0
  165. package/backend/new-content-element-wizard-button.ts +51 -0
  166. package/backend/new-multiple-pages.ts +108 -0
  167. package/backend/new-record-wizard.ts +680 -0
  168. package/backend/notification.ts +366 -0
  169. package/backend/offset.ts +40 -0
  170. package/backend/online-media.ts +110 -0
  171. package/backend/page-actions.ts +91 -0
  172. package/backend/page-link-handler.ts +51 -0
  173. package/backend/pagetsconfig/pagetsconfig-includes.ts +77 -0
  174. package/backend/popover.ts +165 -0
  175. package/backend/record-download-button.ts +104 -0
  176. package/backend/record-link-handler.ts +31 -0
  177. package/backend/record-search.ts +44 -0
  178. package/backend/recordlist.ts +230 -0
  179. package/backend/resource/resource.ts +35 -0
  180. package/backend/security/element/csp-reports.ts +406 -0
  181. package/backend/security/element/sudo-mode.ts +249 -0
  182. package/backend/security/sudo-mode-interceptor.ts +19 -0
  183. package/backend/settings/editor/editable-setting.ts +231 -0
  184. package/backend/settings/editor.ts +451 -0
  185. package/backend/settings/enum/settings-mode.enum.ts +24 -0
  186. package/backend/settings/type/base.ts +200 -0
  187. package/backend/settings/type/bool.ts +56 -0
  188. package/backend/settings/type/color.ts +64 -0
  189. package/backend/settings/type/int.ts +85 -0
  190. package/backend/settings/type/number.ts +61 -0
  191. package/backend/settings/type/page.ts +100 -0
  192. package/backend/settings/type/string.ts +77 -0
  193. package/backend/settings/type/stringlist.ts +87 -0
  194. package/backend/severity.ts +88 -0
  195. package/backend/site-inline-actions.ts +32 -0
  196. package/backend/sortable-table.ts +208 -0
  197. package/backend/storage/abstract-client-storage.ts +76 -0
  198. package/backend/storage/browser-session.ts +28 -0
  199. package/backend/storage/client.ts +28 -0
  200. package/backend/storage/module-state-storage.ts +118 -0
  201. package/backend/storage/persistent.ts +204 -0
  202. package/backend/switch-user.ts +82 -0
  203. package/backend/tabs.ts +72 -0
  204. package/backend/telephone-link-handler.ts +40 -0
  205. package/backend/tests/backend/storage/browser-storage-test.ts +87 -0
  206. package/backend/tests/backend/storage/client-test.ts +87 -0
  207. package/backend/tests/backend/utility/dom-helper-test.ts +51 -0
  208. package/backend/tests/backend-exception-test.ts +28 -0
  209. package/backend/tests/element/immediate-action-element-test.ts +81 -0
  210. package/backend/tests/form-engine-validation-test.ts +304 -0
  211. package/backend/tests/grid-editor-test.ts +29 -0
  212. package/backend/tests/hashing/md5Test.ts +28 -0
  213. package/backend/tests/icons-test.ts +23 -0
  214. package/backend/tests/notification-test.ts +161 -0
  215. package/backend/tests/popover-test.ts +83 -0
  216. package/backend/toolbar/clear-cache-menu.ts +88 -0
  217. package/backend/toolbar/live-search.ts +284 -0
  218. package/backend/toolbar/shortcut-menu.ts +254 -0
  219. package/backend/toolbar/system-information-menu.ts +161 -0
  220. package/backend/toolbar.ts +41 -0
  221. package/backend/tree/file-storage-browser.ts +194 -0
  222. package/backend/tree/file-storage-tree-container.ts +465 -0
  223. package/backend/tree/file-storage-tree.ts +42 -0
  224. package/backend/tree/page-browser.ts +272 -0
  225. package/backend/tree/page-tree-element.ts +602 -0
  226. package/backend/tree/page-tree.ts +152 -0
  227. package/backend/tree/tree-module-state.ts +159 -0
  228. package/backend/tree/tree-node-toggle.ts +31 -0
  229. package/backend/tree/tree-node.ts +97 -0
  230. package/backend/tree/tree-toolbar.ts +117 -0
  231. package/backend/tree/tree.ts +1595 -0
  232. package/backend/url-link-handler.ts +36 -0
  233. package/backend/user-pass-login.ts +255 -0
  234. package/backend/user-settings-manager.ts +189 -0
  235. package/backend/utility/collapse-state-persister.ts +205 -0
  236. package/backend/utility/collapse-state-search.ts +183 -0
  237. package/backend/utility/dom-helper.ts +91 -0
  238. package/backend/utility/drag-drop-utility.ts +47 -0
  239. package/backend/utility/message-utility.ts +45 -0
  240. package/backend/utility/top-level-module-import.ts +32 -0
  241. package/backend/utility.ts +194 -0
  242. package/backend/viewport/abstract-container.ts +22 -0
  243. package/backend/viewport/content-container.ts +98 -0
  244. package/backend/viewport/loader.ts +28 -0
  245. package/backend/viewport/navigation-container.ts +119 -0
  246. package/backend/viewport/resizable-navigation.ts +176 -0
  247. package/backend/viewport/toolbar.ts +27 -0
  248. package/backend/viewport/topbar.ts +39 -0
  249. package/backend/viewport.ts +46 -0
  250. package/backend/window-manager.ts +84 -0
  251. package/backend/wizard/move-content-element.ts +107 -0
  252. package/backend/wizard/move-page.ts +74 -0
  253. package/backend/wizard.ts +331 -0
  254. package/belog/backend-log.ts +88 -0
  255. package/beuser/backend-user-listing.ts +40 -0
  256. package/beuser/permissions.ts +291 -0
  257. package/core/ajax/ajax-request-types.ts +15 -0
  258. package/core/ajax/ajax-request.ts +202 -0
  259. package/core/ajax/ajax-response.ts +57 -0
  260. package/core/ajax/input-transformer.ts +92 -0
  261. package/core/ajax/simple-response-interface.ts +5 -0
  262. package/core/authentication/mfa-provider/totp.ts +54 -0
  263. package/core/cache/dedupe-async-task.ts +95 -0
  264. package/core/directive/markdown.ts +82 -0
  265. package/core/directive/nl2br.ts +16 -0
  266. package/core/document-service.ts +35 -0
  267. package/core/event/debounce-event.ts +40 -0
  268. package/core/event/event-interface.ts +24 -0
  269. package/core/event/regular-event.ts +58 -0
  270. package/core/event/request-animation-frame-event.ts +42 -0
  271. package/core/event/throttle-event.ts +54 -0
  272. package/core/java-script-item-handler.ts +29 -0
  273. package/core/java-script-item-processor.ts +171 -0
  274. package/core/lit-helper.ts +126 -0
  275. package/core/literals.ts +17 -0
  276. package/core/referrer-refresh.ts +2 -0
  277. package/core/security-utility.ts +89 -0
  278. package/core/tests/ajax/ajax-request-test.ts +290 -0
  279. package/core/tests/ajax/input-transformer-test.ts +64 -0
  280. package/core/tests/cache/dedupe-async-task-test.ts +152 -0
  281. package/core/tests/event/throttle-event-test.ts +47 -0
  282. package/core/tests/literals-test.ts +24 -0
  283. package/core/tests/security-utility-test.ts +50 -0
  284. package/core/utility/types.ts +9 -0
  285. package/dashboard/chart-initializer.ts +136 -0
  286. package/dashboard/dashboard.ts +1487 -0
  287. package/extensionmanager/distribution-image.ts +55 -0
  288. package/extensionmanager/main.ts +291 -0
  289. package/extensionmanager/repository.ts +195 -0
  290. package/extensionmanager/update.ts +118 -0
  291. package/extensionmanager/upload-form.ts +42 -0
  292. package/filelist/browse-files.ts +148 -0
  293. package/filelist/browse-folders.ts +94 -0
  294. package/filelist/context-menu-actions.ts +335 -0
  295. package/filelist/create-folder.ts +69 -0
  296. package/filelist/file-delete.ts +69 -0
  297. package/filelist/file-list-actions.ts +132 -0
  298. package/filelist/file-list-dragdrop.ts +139 -0
  299. package/filelist/file-list-rename-handler.ts +128 -0
  300. package/filelist/file-list-transfer-handler.ts +138 -0
  301. package/filelist/file-list.ts +396 -0
  302. package/filelist/file-replace.ts +37 -0
  303. package/filelist/linkbrowser-file-handler.ts +94 -0
  304. package/filelist/linkbrowser-folder-handler.ts +74 -0
  305. package/filelist/rename-file.ts +109 -0
  306. package/form/backend/form-editor/component/property-grid-editor.ts +340 -0
  307. package/form/backend/form-editor/core.ts +2104 -0
  308. package/form/backend/form-editor/helper.ts +226 -0
  309. package/form/backend/form-editor/inspector-component.ts +2323 -0
  310. package/form/backend/form-editor/mediator.ts +941 -0
  311. package/form/backend/form-editor/modals-component.ts +433 -0
  312. package/form/backend/form-editor/stage-component.ts +908 -0
  313. package/form/backend/form-editor/tree-component.ts +548 -0
  314. package/form/backend/form-editor/view-model.ts +1343 -0
  315. package/form/backend/form-editor.ts +846 -0
  316. package/form/backend/form-manager/main.ts +39 -0
  317. package/form/backend/form-manager/view-model.ts +789 -0
  318. package/form/backend/form-manager.ts +180 -0
  319. package/form/backend/helper.ts +60 -0
  320. package/form/frontend/date-picker.ts +38 -0
  321. package/frontend/default_frontend.ts +82 -0
  322. package/impexp/context-menu-actions.ts +50 -0
  323. package/impexp/import-export.ts +62 -0
  324. package/indexed-search/pagination.ts +26 -0
  325. package/indexed-search/statistics.ts +50 -0
  326. package/info/translation-status.ts +48 -0
  327. package/install/ajax/ajax-queue.ts +83 -0
  328. package/install/init-install.ts +2 -0
  329. package/install/init-installer.ts +2 -0
  330. package/install/install.ts +25 -0
  331. package/install/installer.ts +458 -0
  332. package/install/message-interface.ts +18 -0
  333. package/install/module/abstract-inline-module.ts +27 -0
  334. package/install/module/abstract-interactable-module.ts +107 -0
  335. package/install/module/environment/environment-check.ts +92 -0
  336. package/install/module/environment/folder-structure.ts +145 -0
  337. package/install/module/environment/image-processing.ts +141 -0
  338. package/install/module/environment/mail-test.ts +127 -0
  339. package/install/module/environment/php-info.ts +50 -0
  340. package/install/module/environment/system-information.ts +50 -0
  341. package/install/module/maintenance/cache.ts +59 -0
  342. package/install/module/maintenance/clear-tables.ts +134 -0
  343. package/install/module/maintenance/clear-typo3temp-files.ts +137 -0
  344. package/install/module/maintenance/create-admin.ts +126 -0
  345. package/install/module/maintenance/database-analyzer.ts +266 -0
  346. package/install/module/maintenance/dump-autoload.ts +58 -0
  347. package/install/module/maintenance/language-packs.ts +338 -0
  348. package/install/module/maintenance/reset-backend-user-uc.ts +58 -0
  349. package/install/module/password-strength.ts +56 -0
  350. package/install/module/settings/change-install-tool-password.ts +101 -0
  351. package/install/module/settings/extension-configuration.ts +224 -0
  352. package/install/module/settings/features.ts +102 -0
  353. package/install/module/settings/local-configuration.ts +316 -0
  354. package/install/module/settings/presets.ts +147 -0
  355. package/install/module/settings/system-maintainer.ts +111 -0
  356. package/install/module/upgrade/core-update.ts +255 -0
  357. package/install/module/upgrade/extension-compat-tester.ts +195 -0
  358. package/install/module/upgrade/extension-scanner.ts +381 -0
  359. package/install/module/upgrade/tca-ext-tables-check.ts +93 -0
  360. package/install/module/upgrade/tca-migrations-check.ts +101 -0
  361. package/install/module/upgrade/upgrade-docs.ts +310 -0
  362. package/install/module/upgrade/upgrade-wizards.ts +612 -0
  363. package/install/renderable/clearable.ts +113 -0
  364. package/install/renderable/flash-message.ts +64 -0
  365. package/install/renderable/info-box.ts +66 -0
  366. package/install/renderable/language-packs.ts +304 -0
  367. package/install/renderable/offset-group.ts +38 -0
  368. package/install/renderable/severity.ts +49 -0
  369. package/install/renderable/wrap-group.ts +36 -0
  370. package/install/router.ts +468 -0
  371. package/linkvalidator/linkvalidator-modal.ts +45 -0
  372. package/linkvalidator/linkvalidator.ts +101 -0
  373. package/lowlevel/query-generator.ts +132 -0
  374. package/lowlevel/reference-index.ts +44 -0
  375. package/opendocs/toolbar/opendocs-menu.ts +117 -0
  376. package/package.json +34 -0
  377. package/recycler/recycler.ts +539 -0
  378. package/redirects/event-handler.ts +108 -0
  379. package/redirects/form-engine-evaluation.ts +34 -0
  380. package/redirects/redirects-module.ts +58 -0
  381. package/rte-ckeditor/ckeditor5.ts +402 -0
  382. package/rte-ckeditor/css-prefixer.ts +94 -0
  383. package/rte-ckeditor/legacy/ckeditor5-bundle.ts +17 -0
  384. package/rte-ckeditor/legacy/ckeditor5-inspector.ts +2 -0
  385. package/rte-ckeditor/plugin/typo3-link.ts +810 -0
  386. package/rte-ckeditor/plugin/whitespace.ts +114 -0
  387. package/rte-ckeditor/rte-link-browser.ts +112 -0
  388. package/rte-ckeditor/tests/css-prefixer-test.ts +314 -0
  389. package/scheduler/scheduler-add-group.ts +119 -0
  390. package/scheduler/scheduler-editable-group-name.ts +307 -0
  391. package/scheduler/scheduler-sortable-groups.ts +59 -0
  392. package/scheduler/scheduler.ts +466 -0
  393. package/setup/setup-module.ts +122 -0
  394. package/styleguide/checkbox-demo.ts +5 -0
  395. package/styleguide/element/theme-switcher-element.ts +101 -0
  396. package/styleguide/filter.ts +22 -0
  397. package/styleguide/find-icons.ts +78 -0
  398. package/styleguide/processing-indicator.ts +78 -0
  399. package/styleguide/render-notifications.ts +64 -0
  400. package/sys-note/element/delete-button.ts +78 -0
  401. package/tstemplate/constant-editor.ts +64 -0
  402. package/tstemplate/information-module.ts +31 -0
  403. package/tstemplate/template-analyzer.ts +77 -0
  404. package/viewpage/main.ts +253 -0
  405. package/workspaces/backend.ts +979 -0
  406. package/workspaces/preview.ts +232 -0
  407. package/workspaces/renderable/comment-view.ts +79 -0
  408. package/workspaces/renderable/diff-view.ts +58 -0
  409. package/workspaces/renderable/history-view.ts +97 -0
  410. package/workspaces/renderable/record-information.ts +118 -0
  411. package/workspaces/renderable/record-table.ts +355 -0
  412. package/workspaces/renderable/send-to-stage-form.ts +108 -0
  413. package/workspaces/toolbar/workspaces-menu.ts +190 -0
  414. package/workspaces/utility/icon-helper.ts +57 -0
  415. package/workspaces/workspaces.ts +136 -0
@@ -0,0 +1,686 @@
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
+ /**
15
+ * Module: @typo3/backend/form-engine-validation
16
+ * Contains all JS functions related to TYPO3 TCEforms/FormEngineValidation
17
+ * @internal
18
+ */
19
+ import $ from 'jquery';
20
+ import { DateTime } from 'luxon';
21
+ import Md5 from '@typo3/backend/hashing/md5';
22
+ import Modal from '@typo3/backend/modal';
23
+ import Severity from '@typo3/backend/severity';
24
+ import Utility from './utility';
25
+ import RegularEvent from '@typo3/core/event/regular-event';
26
+ import DomHelper from '@typo3/backend/utility/dom-helper';
27
+ import { selector } from '@typo3/core/literals';
28
+ import SubmitInterceptor from '@typo3/backend/form/submit-interceptor';
29
+ import { FormEngineReview } from '@typo3/backend/form-engine-review';
30
+ import type FormEngine from '@typo3/backend/form-engine';
31
+
32
+ type FormEngineFieldElement = HTMLInputElement|HTMLTextAreaElement|HTMLSelectElement;
33
+ type CustomEvaluationCallback = (value: string) => string;
34
+ type FormEngineInputParams = { field: string, evalList?: string, is_in?: string };
35
+
36
+ export interface PostValidationEvent {
37
+ field: FormEngineFieldElement,
38
+ isValid: boolean,
39
+ }
40
+
41
+ let formEngineInstance: typeof FormEngine;
42
+ let validationSuspended = false;
43
+
44
+ const customEvaluations: Map<string, CustomEvaluationCallback> = new Map();
45
+
46
+ /**
47
+ * The main FormEngineValidation object
48
+ *
49
+ * @exports @typo3/backend/form-engine-validation
50
+ */
51
+ export default class FormEngineValidation {
52
+
53
+ public static rulesSelector: string = '[data-formengine-validation-rules]';
54
+ public static inputSelector: string = '[data-formengine-input-params]';
55
+ public static markerSelector: string = '.t3js-formengine-validation-marker';
56
+ public static labelSelector: string = '.t3js-formengine-label';
57
+ public static errorClass: string = 'has-error';
58
+ public static validationErrorClass: string = 'has-validation-error';
59
+ public static passwordDummy: string = '********';
60
+
61
+ /**
62
+ * Initialize validation for the first time
63
+ */
64
+ public static initialize(formEngine: typeof FormEngine): void {
65
+ formEngineInstance = formEngine;
66
+ formEngineInstance.formElement.querySelectorAll('.' + FormEngineValidation.errorClass).forEach((e: HTMLElement) => e.classList.remove(FormEngineValidation.errorClass));
67
+
68
+ // Initialize input fields
69
+ FormEngineValidation.initializeInputFields();
70
+
71
+ new FormEngineReview(formEngineInstance.formElement);
72
+
73
+ // Bind to field changes
74
+ new RegularEvent('change', (e: Event, target: FormEngineFieldElement): void => {
75
+ FormEngineValidation.validateField(target);
76
+ FormEngineValidation.markFieldAsChanged(target);
77
+ }).delegateTo(formEngineInstance.formElement, FormEngineValidation.rulesSelector);
78
+
79
+ FormEngineValidation.registerSubmitCallback();
80
+
81
+ FormEngineValidation.validate();
82
+ }
83
+
84
+ /**
85
+ * Initialize all input fields
86
+ */
87
+ public static initializeInputFields(): void {
88
+ formEngineInstance.formElement.querySelectorAll(FormEngineValidation.inputSelector).forEach((visibleField: FormEngineFieldElement): void => {
89
+ // ignore fields which already have been initialized
90
+ if ('formengineInputInitialized' in visibleField.dataset) {
91
+ return;
92
+ }
93
+
94
+ const config = JSON.parse(visibleField.dataset.formengineInputParams);
95
+ const fieldName = config.field;
96
+ const actualValueField = formEngineInstance.formElement.querySelector(selector`[name="${fieldName}"]`) as HTMLInputElement;
97
+
98
+ actualValueField.dataset.config = visibleField.dataset.formengineInputParams;
99
+ FormEngineValidation.initializeInputField(fieldName);
100
+ });
101
+ }
102
+
103
+ /**
104
+ * Initialize field by name
105
+ */
106
+ public static initializeInputField(fieldName: string): void {
107
+ const field = formEngineInstance.formElement.querySelector(selector`[name="${fieldName}"]`) as HTMLInputElement;
108
+ const humanReadableField = formEngineInstance.formElement.querySelector(selector`[data-formengine-input-name="${fieldName}"]`) as FormEngineFieldElement;
109
+
110
+ if (field.dataset.config !== undefined) {
111
+ const config = JSON.parse(field.dataset.config);
112
+ const value = FormEngineValidation.formatByEvals(config, field.value);
113
+ if (value.length) {
114
+ humanReadableField.value = value;
115
+ }
116
+ }
117
+
118
+ new RegularEvent('change', (): void => {
119
+ FormEngineValidation.updateInputField(humanReadableField.dataset.formengineInputName);
120
+ }).bindTo(humanReadableField);
121
+
122
+ // add the attribute so that acceptance tests can know when the field initialization has completed
123
+ humanReadableField.dataset.formengineInputInitialized = 'true';
124
+ }
125
+
126
+ public static registerCustomEvaluation(name: string, handler: CustomEvaluationCallback): void {
127
+ if (!customEvaluations.has(name)) {
128
+ customEvaluations.set(name, handler);
129
+ }
130
+ }
131
+
132
+ public static formatByEvals(config: FormEngineInputParams, value: string): string {
133
+ if (config.evalList !== undefined) {
134
+ const evalList = Utility.trimExplode(',', config.evalList);
135
+ for (const evalInstruction of evalList) {
136
+ value = FormEngineValidation.formatValue(evalInstruction, value);
137
+ }
138
+ }
139
+ return value;
140
+ }
141
+
142
+ /**
143
+ * Format field value
144
+ */
145
+ public static formatValue(type: string, value: string|number): string {
146
+ switch (type) {
147
+ case 'date':
148
+ case 'datetime':
149
+ case 'time':
150
+ case 'timesec':
151
+ if (value === '') {
152
+ return '';
153
+ }
154
+ const isoDt = DateTime.fromISO(String(value), { zone: 'utc' });
155
+ if (!isoDt.isValid) {
156
+ throw new Error('Invalid ISO8601 DateTime string: ' + value);
157
+ }
158
+ return isoDt.toISO({ suppressMilliseconds: true });
159
+ case 'password':
160
+ return (value) ? FormEngineValidation.passwordDummy : '';
161
+ default:
162
+ return value.toString();
163
+ }
164
+ }
165
+
166
+ /**
167
+ * Update input field after change
168
+ */
169
+ public static updateInputField(fieldName: string): void {
170
+ const field = formEngineInstance.formElement.querySelector(selector`[name="${fieldName}"]`) as HTMLInputElement;
171
+ const humanReadableField = formEngineInstance.formElement.querySelector(selector`[data-formengine-input-name="${fieldName}"]`) as FormEngineFieldElement;
172
+
173
+ if (field.dataset.config !== undefined) {
174
+ const config = JSON.parse(field.dataset.config);
175
+ const newValue = FormEngineValidation.processByEvals(config, humanReadableField.value);
176
+ const formattedValue = FormEngineValidation.formatByEvals(config, newValue);
177
+
178
+ // Only update value field if value actually changed
179
+ if (field.value !== newValue) {
180
+ if (field.disabled && field.dataset.enableOnModification) {
181
+ field.disabled = false;
182
+ }
183
+ field.value = newValue;
184
+ // After updating the value of the main field, dispatch a "change" event to inform e.g. the "RequestUpdate"
185
+ // component, which always listens to the main field instead of the "human readable field", about it.
186
+ field.dispatchEvent(new Event('change'));
187
+ }
188
+
189
+ // Synchronize the "human-readable field" as the data normalization may have cleared invalid characters
190
+ if (humanReadableField.value !== formattedValue) {
191
+ humanReadableField.value = formattedValue;
192
+ }
193
+ }
194
+ }
195
+
196
+ /**
197
+ * Run validation for field
198
+ */
199
+ public static validateField(field: FormEngineFieldElement|JQuery, value?: string): string {
200
+ if (field instanceof $) {
201
+ // @deprecated
202
+ console.warn('Passing a jQuery element to FormEngineValidation.validateField() is deprecated and will be removed in TYPO3 v14.');
203
+ console.trace();
204
+ field = <FormEngineFieldElement>(field as JQuery).get(0);
205
+ }
206
+ if (!(field instanceof HTMLElement)) {
207
+ // Can be removed altogether with jQuery support in TYPO3 v14
208
+ return value;
209
+ }
210
+ value = value || field.value || '';
211
+
212
+ if (typeof field.dataset.formengineValidationRules === 'undefined') {
213
+ return value;
214
+ }
215
+
216
+ const rules: any = JSON.parse(field.dataset.formengineValidationRules);
217
+ let markParent = false;
218
+ let selected = 0;
219
+ // keep the original value, validateField should not alter it
220
+ const returnValue: string = value;
221
+ let relatedField: FormEngineFieldElement;
222
+ let minItems: number;
223
+ let maxItems: number;
224
+
225
+ if (!Array.isArray(value)) {
226
+ value = value.trimStart();
227
+ }
228
+
229
+ for (const rule of rules) {
230
+ if (markParent) {
231
+ // abort any further validation as validating the field already failed
232
+ break;
233
+ }
234
+ switch (rule.type) {
235
+ case 'required':
236
+ if (value === '') {
237
+ markParent = true;
238
+ field.classList.add(FormEngineValidation.errorClass);
239
+ field.closest(FormEngineValidation.markerSelector)?.querySelector(FormEngineValidation.labelSelector)?.classList.add(FormEngineValidation.errorClass);
240
+ }
241
+ break;
242
+ case 'range':
243
+ if (value !== '') {
244
+ if (rule.minItems || rule.maxItems) {
245
+ relatedField = formEngineInstance.formElement.querySelector(selector`[name="${field.dataset.relatedfieldname}"]`) as FormEngineFieldElement;
246
+ if (relatedField !== null) {
247
+ selected = Utility.trimExplode(',', relatedField.value).length;
248
+ } else {
249
+ selected = parseInt(field.value, 10);
250
+ }
251
+ if (rule.minItems !== undefined) {
252
+ minItems = rule.minItems * 1;
253
+ if (!isNaN(minItems) && selected < minItems) {
254
+ markParent = true;
255
+ }
256
+ }
257
+ if (rule.maxItems !== undefined) {
258
+ maxItems = rule.maxItems * 1;
259
+ if (!isNaN(maxItems) && selected > maxItems) {
260
+ markParent = true;
261
+ }
262
+ }
263
+ }
264
+ if (rule.lower !== undefined) {
265
+ if (field.dataset.inputType === 'datetimepicker') {
266
+ // HEADS up: value and range.lower are both fake UTC-0 ISO8601 strings (they are not UTC-0, but actually server localtime!)
267
+ // But it's fine to compare them in UTC for this comparison and not map to localtime as in date-time-picker parseDate.
268
+ const dt = DateTime.fromISO(value, { zone: 'utc' });
269
+ const lower = DateTime.fromISO(rule.lower, { zone: 'utc' });
270
+ if (!dt.isValid || dt < lower.minus(lower.second * 1000)) {
271
+ markParent = true;
272
+ }
273
+ } else {
274
+ const minValue = rule.lower * 1;
275
+ if (!isNaN(minValue) && parseInt(value, 10) < minValue) {
276
+ markParent = true;
277
+ }
278
+ }
279
+ }
280
+ if (rule.upper !== undefined) {
281
+ if (field.dataset.inputType === 'datetimepicker') {
282
+ // HEADS up: value and range.upper are both fake UTC-0 ISO8601 strings (they are not UTC-0, but actually server localtime!)
283
+ // But it's fine to compare them in UTC-0 for this comparison and not map to localtime as in date-time-picker parseDate.
284
+ const dt = DateTime.fromISO(value, { zone: 'utc' });
285
+ const upper = DateTime.fromISO(rule.upper, { zone: 'utc' });
286
+ if (!dt.isValid || dt > upper.plus((59 - upper.second) * 1000)) {
287
+ markParent = true;
288
+ }
289
+ } else {
290
+ const maxValue = rule.upper * 1;
291
+ if (!isNaN(maxValue) && parseInt(value, 10) > maxValue) {
292
+ markParent = true;
293
+ }
294
+ }
295
+ }
296
+ }
297
+ break;
298
+ case 'select':
299
+ case 'category':
300
+ if (rule.minItems || rule.maxItems) {
301
+ relatedField = formEngineInstance.formElement.querySelector(selector`[name="${field.dataset.relatedfieldname}"]`) as FormEngineFieldElement;
302
+ if (relatedField !== null) {
303
+ selected = Utility.trimExplode(',', relatedField.value).length;
304
+ } else if (field instanceof HTMLSelectElement) {
305
+ selected = field.querySelectorAll('option:checked').length;
306
+ } else {
307
+ selected = field.querySelectorAll('input[value]:checked').length;
308
+ }
309
+
310
+ if (rule.minItems !== undefined) {
311
+ minItems = rule.minItems * 1;
312
+ if (!isNaN(minItems) && selected < minItems) {
313
+ markParent = true;
314
+ }
315
+ }
316
+ if (rule.maxItems !== undefined) {
317
+ maxItems = rule.maxItems * 1;
318
+ if (!isNaN(maxItems) && selected > maxItems) {
319
+ markParent = true;
320
+ }
321
+ }
322
+ }
323
+ break;
324
+ case 'group':
325
+ case 'folder':
326
+ if (rule.minItems || rule.maxItems) {
327
+ selected = Utility.trimExplode(',', field.value).length;
328
+ if (rule.minItems !== undefined) {
329
+ minItems = rule.minItems * 1;
330
+ if (!isNaN(minItems) && selected < minItems) {
331
+ markParent = true;
332
+ }
333
+ }
334
+ if (rule.maxItems !== undefined) {
335
+ maxItems = rule.maxItems * 1;
336
+ if (!isNaN(maxItems) && selected > maxItems) {
337
+ markParent = true;
338
+ }
339
+ }
340
+ }
341
+ break;
342
+ case 'inline':
343
+ if (rule.minItems || rule.maxItems) {
344
+ selected = Utility.trimExplode(',', field.value).length;
345
+ if (rule.minItems !== undefined) {
346
+ minItems = rule.minItems * 1;
347
+ if (!isNaN(minItems) && selected < minItems) {
348
+ markParent = true;
349
+ }
350
+ }
351
+ if (rule.maxItems !== undefined) {
352
+ maxItems = rule.maxItems * 1;
353
+ if (!isNaN(maxItems) && selected > maxItems) {
354
+ markParent = true;
355
+ }
356
+ }
357
+ }
358
+ break;
359
+ case 'min':
360
+ if (field instanceof HTMLInputElement || field instanceof HTMLTextAreaElement) {
361
+ if (field.value.length > 0 && field.value.length < field.minLength) {
362
+ markParent = true;
363
+ }
364
+ }
365
+ break;
366
+ case 'null':
367
+ // unknown type null, we ignore it
368
+ break;
369
+ default:
370
+ break;
371
+ }
372
+ }
373
+
374
+ const isValid = !markParent;
375
+ field.classList.toggle(FormEngineValidation.errorClass, !isValid);
376
+ field.setAttribute('aria-invalid', markParent.toString());
377
+ field.closest(FormEngineValidation.markerSelector)?.querySelector(FormEngineValidation.labelSelector)?.classList.toggle(FormEngineValidation.errorClass, !isValid);
378
+
379
+ FormEngineValidation.markParentTab(field, isValid);
380
+ formEngineInstance.formElement.dispatchEvent(new CustomEvent<PostValidationEvent>('t3-formengine-postfieldvalidation', { detail: { field: field, isValid: isValid }, cancelable: false, bubbles: true }));
381
+
382
+ return returnValue;
383
+ }
384
+
385
+ public static processByEvals(config: FormEngineInputParams, value: string): string {
386
+ if (config.evalList !== undefined) {
387
+ const evalList = Utility.trimExplode(',', config.evalList);
388
+ for (const evalInstruction of evalList) {
389
+ value = FormEngineValidation.processValue(evalInstruction, value, config);
390
+ }
391
+ }
392
+ return value;
393
+ }
394
+
395
+ /**
396
+ * Process a value by given command and config
397
+ */
398
+ public static processValue(command: string, value: string, config: FormEngineInputParams): string {
399
+ let newString = '';
400
+ let theValue = '';
401
+ let a = 0;
402
+ let returnValue = value;
403
+ switch (command) {
404
+ case 'alpha':
405
+ case 'num':
406
+ case 'alphanum':
407
+ case 'alphanum_x':
408
+ newString = '';
409
+ for (a = 0; a < value.length; a++) {
410
+ const theChar = value.substr(a, 1);
411
+ let special = (theChar === '_' || theChar === '-');
412
+ let alpha = (theChar >= 'a' && theChar <= 'z') || (theChar >= 'A' && theChar <= 'Z');
413
+ let num = (theChar >= '0' && theChar <= '9');
414
+ switch (command) {
415
+ case 'alphanum':
416
+ special = false;
417
+ break;
418
+ case 'alpha':
419
+ num = false;
420
+ special = false;
421
+ break;
422
+ case 'num':
423
+ alpha = false;
424
+ special = false;
425
+ break;
426
+ default:
427
+ break;
428
+ }
429
+ if (alpha || num || special) {
430
+ newString += theChar;
431
+ }
432
+ }
433
+ if (newString !== value) {
434
+ returnValue = newString;
435
+ }
436
+ break;
437
+ case 'is_in':
438
+ if (config.is_in) {
439
+ theValue = '' + value;
440
+ // Escape special characters, see https://stackoverflow.com/a/6969486/4828813
441
+ config.is_in = config.is_in.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
442
+ const re = new RegExp('[^' + config.is_in + ']+', 'g');
443
+ newString = theValue.replace(re, '');
444
+ } else {
445
+ newString = theValue;
446
+ }
447
+ returnValue = newString;
448
+ break;
449
+ case 'nospace':
450
+ returnValue = ('' + value).replace(/ /g, '');
451
+ break;
452
+ case 'md5':
453
+ if (value !== '') {
454
+ returnValue = Md5.hash(value);
455
+ }
456
+ break;
457
+ case 'upper':
458
+ returnValue = value.toUpperCase();
459
+ break;
460
+ case 'lower':
461
+ returnValue = value.toLowerCase();
462
+ break;
463
+ case 'integer':
464
+ if (value !== '') {
465
+ returnValue = FormEngineValidation.parseInt(value).toString();
466
+ }
467
+ break;
468
+ case 'decimal':
469
+ if (value !== '') {
470
+ returnValue = FormEngineValidation.parseDouble(value);
471
+ }
472
+ break;
473
+ case 'trim':
474
+ returnValue = String(value).trim();
475
+ break;
476
+ case 'time':
477
+ case 'timesec':
478
+ if (value !== '') {
479
+ const dt = DateTime.fromISO(value, { zone: 'utc' }).set({
480
+ year: 1970,
481
+ month: 1,
482
+ day: 1
483
+ });
484
+ returnValue = dt.toISO({ suppressMilliseconds: true });
485
+ }
486
+ break;
487
+ case 'year':
488
+ if (value !== '') {
489
+ let year = parseInt(value, 10);
490
+ if (isNaN(year)) {
491
+ year = new Date().getUTCFullYear();
492
+ }
493
+ returnValue = year.toString(10);
494
+ }
495
+ break;
496
+ case 'null':
497
+ // unknown type null, we ignore it
498
+ break;
499
+ case 'password':
500
+ // password is only a display evaluation, we ignore it
501
+ break;
502
+ default:
503
+ if (customEvaluations.has(command)) {
504
+ returnValue = customEvaluations.get(command).call(null, value);
505
+ } else if (typeof TBE_EDITOR === 'object' && TBE_EDITOR.customEvalFunctions !== undefined && typeof TBE_EDITOR.customEvalFunctions[command] === 'function') {
506
+ returnValue = TBE_EDITOR.customEvalFunctions[command](value);
507
+ }
508
+ }
509
+ return returnValue;
510
+ }
511
+
512
+ /**
513
+ * Validate the complete form
514
+ */
515
+ public static validate(section?: Element): void {
516
+ if (typeof section === 'undefined' || section instanceof Document) {
517
+ formEngineInstance.formElement.querySelectorAll(FormEngineValidation.markerSelector + ', .t3js-tabmenu-item').forEach((tabMenuItem: HTMLElement): void => {
518
+ tabMenuItem.classList.remove(FormEngineValidation.validationErrorClass);
519
+ });
520
+ }
521
+
522
+ const sectionElement = section || document;
523
+ for (const field of sectionElement.querySelectorAll<FormEngineFieldElement>(FormEngineValidation.rulesSelector)) {
524
+ if (field.closest('.t3js-flex-section-deleted, .t3js-inline-record-deleted, .t3js-file-reference-deleted') === null) {
525
+ let modified = false;
526
+ const currentValue = field.value;
527
+ const newValue = FormEngineValidation.validateField(field, currentValue);
528
+ if (Array.isArray(newValue) && Array.isArray(currentValue)) {
529
+ // handling for multi-selects
530
+ if (newValue.length !== currentValue.length) {
531
+ modified = true;
532
+ } else {
533
+ for (let i = 0; i < newValue.length; i++) {
534
+ if (newValue[i] !== currentValue[i]) {
535
+ modified = true;
536
+ break;
537
+ }
538
+ }
539
+ }
540
+ } else if (newValue.length && currentValue !== newValue) {
541
+ modified = true;
542
+ }
543
+ if (modified) {
544
+ if (field.disabled && field.dataset.enableOnModification) {
545
+ field.disabled = false;
546
+ }
547
+ field.value = newValue;
548
+ }
549
+ }
550
+ }
551
+ }
552
+
553
+ /**
554
+ * Helper function to mark a field as changed.
555
+ */
556
+ public static markFieldAsChanged(field: FormEngineFieldElement|JQuery): void {
557
+ if (field instanceof $) {
558
+ // @deprecated
559
+ console.warn('Passing a jQuery element to FormEngineValidation.markFieldAsChanged() is deprecated and will be removed in TYPO3 v14.');
560
+ console.trace();
561
+ field = <FormEngineFieldElement>(field as JQuery).get(0);
562
+ }
563
+ if (!(field instanceof HTMLElement)) {
564
+ // Can be removed altogether with jQuery support in TYPO3 v14
565
+ return;
566
+ }
567
+ field.classList.add('has-change');
568
+ const fieldLabel = field.closest('.t3js-formengine-palette-field')?.querySelector('.t3js-formengine-label');
569
+ if (fieldLabel !== null) {
570
+ fieldLabel.classList.add('has-change');
571
+ }
572
+ }
573
+
574
+ /**
575
+ * Parse value to integer
576
+ */
577
+ public static parseInt(value: number|string|boolean): number {
578
+ const theVal = '' + value;
579
+
580
+ if (!value) {
581
+ return 0;
582
+ }
583
+
584
+ const returnValue = parseInt(theVal, 10);
585
+ if (isNaN(returnValue)) {
586
+ return 0;
587
+ }
588
+ return returnValue;
589
+ }
590
+
591
+ /**
592
+ * Parse value to double
593
+ */
594
+ public static parseDouble(value: number|string|boolean, precision: number = 2): string {
595
+ let theVal = '' + value;
596
+ theVal = theVal.replace(/[^0-9,.-]/g, '');
597
+ const negative = theVal.startsWith('-');
598
+ theVal = theVal.replace(/-/g, '');
599
+ theVal = theVal.replace(/,/g, '.');
600
+ if (theVal.indexOf('.') === -1) {
601
+ theVal += '.0';
602
+ }
603
+ const parts = theVal.split('.');
604
+ const dec = parts.pop();
605
+ let theNumberVal = Number(parts.join('') + '.' + dec);
606
+ if (negative) {
607
+ theNumberVal *= -1;
608
+ }
609
+ theVal = theNumberVal.toFixed(precision);
610
+
611
+ return theVal;
612
+ }
613
+
614
+ public static pol(foreign: string, value: string): object {
615
+ // @todo deprecate
616
+ // eslint-disable-next-line no-eval
617
+ return eval(((foreign == '-') ? '-' : '') + value);
618
+ }
619
+
620
+ /**
621
+ * Find tab by field and mark it as has-validation-error
622
+ */
623
+ public static markParentTab(element: FormEngineFieldElement, isValid: boolean): void {
624
+ const panes = DomHelper.parents(element, '.tab-pane');
625
+ panes.forEach((pane: HTMLElement): void => {
626
+ if (isValid) {
627
+ // If incoming element is valid, check for errors in the same sheet
628
+ isValid = pane.querySelector('.has-error') === null;
629
+ }
630
+
631
+ const id = pane.id;
632
+ formEngineInstance.formElement
633
+ .querySelector('[data-bs-target="#' + id + '"]')
634
+ .closest('.t3js-tabmenu-item')
635
+ .classList.toggle(FormEngineValidation.validationErrorClass, !isValid);
636
+ });
637
+ }
638
+
639
+ /**
640
+ * @internal
641
+ */
642
+ public static suspend() {
643
+ validationSuspended = true;
644
+ }
645
+
646
+ /**
647
+ * @internal
648
+ */
649
+ public static resume() {
650
+ validationSuspended = false;
651
+ }
652
+
653
+ public static isValid(): boolean {
654
+ return document.querySelector('.' + FormEngineValidation.errorClass) === null;
655
+ }
656
+
657
+ public static showErrorModal(): void {
658
+ const modal = Modal.confirm(
659
+ TYPO3.lang.alert || 'Alert',
660
+ TYPO3.lang['FormEngine.fieldsMissing'],
661
+ Severity.error,
662
+ [
663
+ {
664
+ text: TYPO3.lang['button.ok'] || 'OK',
665
+ active: true,
666
+ btnClass: 'btn-default',
667
+ name: 'ok',
668
+ },
669
+ ]
670
+ );
671
+ modal.addEventListener('button.clicked', () => modal.hideModal());
672
+ }
673
+
674
+ public static registerSubmitCallback() {
675
+ const submitInterceptor = new SubmitInterceptor(formEngineInstance.formElement);
676
+ submitInterceptor.addPreSubmitCallback((): boolean => {
677
+ if (validationSuspended || FormEngineValidation.isValid()) {
678
+ return true;
679
+ }
680
+
681
+ FormEngineValidation.showErrorModal();
682
+
683
+ return false;
684
+ });
685
+ }
686
+ }