From 6cdf26cdb9fb3483919853984dbce6758caab0df Mon Sep 17 00:00:00 2001
From: Tobias Jungmann <tobias.jungmann@tritum.de>
Date: Wed, 13 Jul 2022 11:29:33 +0200
Subject: [PATCH] [BUGFIX] Fix page reloading on click on preview button
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

If a preview page is already open, clicking on the "view" button in the
content editor window would not reload the page. That means, that the
preview page would not show changes if the preview page url and the
target url are similar (e.g. only differentiate in hash/query or are
exactly the same).

This patch looks if a window with the given windowName is already open
(looking in `this.windows` did not work well because the existing
windows aren't saved in a global context, yet) and compares the URL of
an open window (if there's one) with the given URL. If the URLs are
similiar (i.e. the origin and the path name are the same) the page will
be reloaded.

Resolves: #93706
Releases: main, 11.5
Change-Id: Ib3d9e49f56e6ef45df1cd7d82fa58dffb74a3750
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/75164
Tested-by: Benjamin Franzke <bfr@qbus.de>
Tested-by: core-ci <typo3@b13.com>
Tested-by: Stefan Bürk <stefan@buerk.tech>
Reviewed-by: Benjamin Franzke <bfr@qbus.de>
Reviewed-by: Stefan Bürk <stefan@buerk.tech>
---
 .../Sources/TypeScript/backend/form-engine.ts |  6 ++-
 Build/Sources/TypeScript/backend/utility.ts   | 44 +++++++++++++++++++
 .../TypeScript/backend/window-manager.ts      | 12 +++--
 .../Public/JavaScript/form-engine.js          |  2 +-
 .../Resources/Public/JavaScript/utility.js    |  2 +-
 .../Public/JavaScript/window-manager.js       |  2 +-
 .../Application/Frontend/SitemapXmlCest.php   | 25 ++++++++++-
 7 files changed, 83 insertions(+), 10 deletions(-)

diff --git a/Build/Sources/TypeScript/backend/form-engine.ts b/Build/Sources/TypeScript/backend/form-engine.ts
index 2a5152e9bc56..7f123b0da31b 100644
--- a/Build/Sources/TypeScript/backend/form-engine.ts
+++ b/Build/Sources/TypeScript/backend/form-engine.ts
@@ -34,6 +34,7 @@ import * as BackendExceptionModule from '@typo3/backend/backend-exception';
 import InteractionRequestMap from '@typo3/backend/event/interaction-request-map';
 import InteractionRequest from '@typo3/backend/event/interaction-request';
 import TriggerRequest from '@typo3/backend/event/trigger-request';
+import Utility from '@typo3/backend/utility';
 
 interface OnFieldChangeItem {
   name: string;
@@ -901,7 +902,7 @@ export default (function() {
   FormEngine.previewAction = function(event: Event, callback: Function): void {
     callback = callback || FormEngine.previewActionCallback;
 
-    const previewUrl = (event.target as HTMLAnchorElement).href;
+    const previewUrl = (event.currentTarget as HTMLAnchorElement).href;
     const isNew = (event.target as HTMLAnchorElement).dataset.hasOwnProperty('isNew');
     const $actionElement = $('<input />').attr('type', 'hidden').attr('name', '_savedokview').attr('value', '1');
     if (FormEngine.hasChange()) {
@@ -926,7 +927,8 @@ export default (function() {
       case 'discard':
         const previewWin = window.open(previewUrl, 'newTYPO3frontendWindow');
         previewWin.focus();
-        if (previewWin.location.href === previewUrl) {
+
+        if (Utility.urlsPointToSameServerSideResource(previewWin.location.href, previewUrl)) {
           previewWin.location.reload();
         }
         break;
diff --git a/Build/Sources/TypeScript/backend/utility.ts b/Build/Sources/TypeScript/backend/utility.ts
index af22a842db54..52c3059e2f55 100644
--- a/Build/Sources/TypeScript/backend/utility.ts
+++ b/Build/Sources/TypeScript/backend/utility.ts
@@ -171,6 +171,50 @@ class Utility {
       return prev;
     }, {});
   }
+
+  /**
+   * Checks if the origin, pathnames and query string are equal (ignoring different fragments),
+   * and therefore point to the same server side resource.
+   *
+   * @param {string|null} url1
+   * @param {string|null} url2
+   *
+   * @returns {boolean}
+   */
+  public static urlsPointToSameServerSideResource(url1: null|string, url2: null|string): boolean {
+    if (!url1 || !url2) {
+      return false;
+    }
+
+    const currentWindowUrlOrigin = window.location.origin;
+
+    try {
+      const uriObject1 = new URL(url1, Utility.isValidUrl(url1) ? undefined : currentWindowUrlOrigin);
+      const uriObject2 = new URL(url2, Utility.isValidUrl(url2) ? undefined : currentWindowUrlOrigin);
+      const resource1 = uriObject1.origin + uriObject1.pathname + uriObject1.search;
+      const resource2 = uriObject2.origin + uriObject2.pathname + uriObject2.search;
+
+      return resource1 === resource2;
+    } catch (exception) {
+      return false;
+    }
+  }
+
+
+  /**
+   * Checks, if the given URL is valid.
+   *
+   * @param {null|string} url
+   * @private
+   */
+  private static isValidUrl(url: null|string): boolean {
+    try {
+      new URL(url)
+      return true;
+    } catch (e) {
+      return false;
+    }
+  }
 }
 
 export default Utility;
diff --git a/Build/Sources/TypeScript/backend/window-manager.ts b/Build/Sources/TypeScript/backend/window-manager.ts
index 9c3df64bf3e4..08b706fd5a0f 100644
--- a/Build/Sources/TypeScript/backend/window-manager.ts
+++ b/Build/Sources/TypeScript/backend/window-manager.ts
@@ -11,6 +11,8 @@
  * The TYPO3 project - inspiring people to share!
  */
 
+import Utility from '@typo3/backend/utility';
+
 /**
  * Module: @typo3/backend/window-manager
  */
@@ -34,10 +36,14 @@ class WindowManager {
     } else if (switchFocus === undefined) {
       switchFocus = true;
     }
-    const existingWindow = this.windows[windowName];
-    const existingUri = existingWindow instanceof Window && !existingWindow.closed ? existingWindow.location.href : null;
+    const existingWindow = this.windows[windowName] ?? window.open('', windowName, windowFeatures);
+    // Note: `existingWindow instanceof Window` wouldn't work here as `existingWindow` is from a another browser context/window.
+    // see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/instanceof#instanceof_and_multiple_contexts_e.g._frames_or_windows
+    const isInstanceOfWindow = existingWindow.constructor.name === 'Window';
+    const existingUri = isInstanceOfWindow && !existingWindow.closed ? existingWindow.location.href : null;
 
-    if (existingUri === uri) {
+    if (Utility.urlsPointToSameServerSideResource(uri, existingUri)) {
+      existingWindow.location.replace(uri);
       existingWindow.location.reload();
       return existingWindow;
     }
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/form-engine.js b/typo3/sysext/backend/Resources/Public/JavaScript/form-engine.js
index 8302899234c7..6cbfe10c3987 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/form-engine.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/form-engine.js
@@ -10,4 +10,4 @@
  *
  * The TYPO3 project - inspiring people to share!
  */
-import $ from"jquery";import FormEngineValidation from"@typo3/backend/form-engine-validation.js";import Icons from"@typo3/backend/icons.js";import Modal from"@typo3/backend/modal.js";import*as MessageUtility from"@typo3/backend/utility/message-utility.js";import Severity from"@typo3/backend/severity.js";import*as BackendExceptionModule from"@typo3/backend/backend-exception.js";import InteractionRequestMap from"@typo3/backend/event/interaction-request-map.js";export default(function(){function e(e,t){t?n.interactionRequestMap.resolveFor(e):n.interactionRequestMap.rejectFor(e)}const t=new Map;t.set("typo3-backend-form-update-value",(e,t)=>{const n=document.querySelector('[name="'+CSS.escape(e.elementName)+'"]'),a=document.querySelector('[data-formengine-input-name="'+CSS.escape(e.elementName)+'"]');FormEngineValidation.updateInputField(e.elementName),null!==n&&(FormEngineValidation.markFieldAsChanged(n),FormEngineValidation.validateField(n)),null!==a&&a!==n&&FormEngineValidation.validateField(a)}),t.set("typo3-backend-form-reload",(e,t)=>{e.confirmation?Modal.confirm(TYPO3.lang["FormEngine.refreshRequiredTitle"],TYPO3.lang["FormEngine.refreshRequiredContent"]).on("button.clicked",e=>{"ok"==e.target.name&&n.saveDocument(),Modal.dismiss()}):n.saveDocument()}),t.set("typo3-backend-form-update-bitmask",(e,t)=>{const n=t.target,a=document.editform[e.elementName],o=n.checked!==e.invert,i=Math.pow(2,e.position),r=Math.pow(2,e.total)-i-1;a.value=o?a.value|i:a.value&r,a.dispatchEvent(new Event("change",{bubbles:!0,cancelable:!0}))});const n={consumeTypes:["typo3.setUrl","typo3.beforeSetUrl","typo3.refresh"],Validation:FormEngineValidation,interactionRequestMap:InteractionRequestMap,formName:TYPO3.settings.FormEngine.formName,openedPopupWindow:null,legacyFieldChangedCb:function(){!$.isFunction(TYPO3.settings.FormEngine.legacyFieldChangedCb)||TYPO3.settings.FormEngine.legacyFieldChangedCb()},browserUrl:"",openPopupWindow:function(e,t,a){return Modal.advanced({type:Modal.types.iframe,content:n.browserUrl+"&mode="+e+"&bparams="+t+(a?"&"+("db"===e?"expandPage":"expandFolder")+"="+a:""),size:Modal.sizes.large})},setSelectOptionFromExternalSource:function(e,t,a,o,i,r){i=String(i);let c,l,s=!1,d=!1;if(c=n.getFieldElement(e),l=c.get(0),null===l||"--div--"===t||l instanceof HTMLOptGroupElement)return;const u=n.getFieldElement(e,"_list",!0);if(u.length>0&&(c=u,s=c.prop("multiple")&&"1"!=c.prop("size"),d=!0),s||d){const d=n.getFieldElement(e,"_avail");if(s||(c.find("option").each((e,t)=>{const a=d.find('option[value="'+$.escapeSelector($(t).attr("value"))+'"]');a.length&&(a.removeClass("hidden").prop("disabled",!1),n.enableOptGroup(a.get(0)))}),c.empty()),i){let e=!1,a=new RegExp("(^|,)"+t+"($|,)");i.match(a)?(c.empty(),e=!0):1==c.find("option").length&&(a=new RegExp("(^|,)"+c.find("option").prop("value")+"($|,)"),i.match(a)&&(c.empty(),e=!0)),e&&void 0!==r&&r.closest("select").querySelectorAll("[disabled]").forEach((function(e){e.classList.remove("hidden"),e.disabled=!1,n.enableOptGroup(e)}))}let u=!0;const m=n.getFieldElement(e,"_mul",!0);if((0==m.length||0==m.val())&&(c.find("option").each((function(e,n){if($(n).prop("value")==t)return u=!1,!1})),u&&void 0!==r)){r.classList.add("hidden"),r.disabled=!0;const e=r.parentElement;e instanceof HTMLOptGroupElement&&0===e.querySelectorAll("option:not([disabled]):not([hidden]):not(.hidden)").length&&(e.disabled=!0,e.classList.add("hidden"))}if(u){const e=$("<option></option>");e.attr({value:t,title:o}).text(a),e.appendTo(c),n.updateHiddenFieldValueFromSelect(c,l),n.legacyFieldChangedCb(),FormEngineValidation.markFieldAsChanged(l),n.Validation.validateField(c),n.Validation.validateField(d)}}else{const e=/_(\d+)$/,a=t.toString().match(e);null!=a&&(t=a[1]),c.val(t),n.Validation.validateField(c)}},updateHiddenFieldValueFromSelect:function(e,t){const n=[];$(e).find("option").each((e,t)=>{n.push($(t).prop("value"))}),t.value=n.join(","),t.dispatchEvent(new Event("change",{bubbles:!0,cancelable:!0}))},getFormElement:function(e){const t=$('form[name="'+n.formName+'"]:first');if(!e)return t;{const a=n.getFieldElement(e),o=n.getFieldElement(e,"_list");if(a.length>0&&("select-one"===a.prop("type")||o.length>0&&o.prop("type").match(/select-(one|multiple)/)))return t;console.error("Form fields missing: form: "+n.formName+", field name: "+e),alert("Form field is invalid")}},getFieldElement:function(e,t,a){const o=$('form[name="'+n.formName+'"]:first');if(t){let n;switch(t){case"_list":n=$(':input[data-formengine-input-name="'+e+'"]:not([type=hidden])',o);break;case"_avail":n=$(':input[data-relatedfieldname="'+e+'"]',o);break;case"_mul":case"_hr":n=$(':input[type=hidden][data-formengine-input-name="'+e+'"]',o);break;default:n=null}if(n&&n.length>0||!0===a)return n}return $(':input[name="'+e+'"]',o)},initializeEvents:function(){top.TYPO3&&void 0!==top.TYPO3.Backend&&(top.TYPO3.Backend.consumerScope.attach(n),$(window).on("unload",(function(){top.TYPO3.Backend.consumerScope.detach(n)}))),$(document).on("click",".t3js-editform-close",e=>{e.preventDefault(),n.preventExitIfNotSaved(n.preventExitIfNotSavedCallback)}).on("click",".t3js-editform-view",e=>{e.preventDefault(),n.previewAction(e,n.previewActionCallback)}).on("click",".t3js-editform-new",e=>{e.preventDefault(),n.newAction(e,n.newActionCallback)}).on("click",".t3js-editform-duplicate",e=>{e.preventDefault(),n.duplicateAction(e,n.duplicateActionCallback)}).on("click",".t3js-editform-delete-record",e=>{e.preventDefault(),n.deleteAction(e,n.deleteActionCallback)}).on("click",".t3js-editform-submitButton",e=>{const t=$(e.currentTarget),n=t.data("name")||e.currentTarget.name,a=$("<input />").attr("type","hidden").attr("name",n).attr("value","1");t.parents("form").append(a)}).on("change",'.t3-form-field-eval-null-checkbox input[type="checkbox"]',e=>{$(e.currentTarget).closest(".t3js-formengine-field-item").toggleClass("disabled")}).on("change",'.t3js-form-field-eval-null-placeholder-checkbox input[type="checkbox"]',e=>{n.toggleCheckboxField($(e.currentTarget)),FormEngineValidation.markFieldAsChanged($(e.currentTarget))}).on("change",(function(e){$(".module-docheader-bar .btn").removeClass("disabled").prop("disabled",!1)})).on("click",".t3js-element-browser",(function(e){e.preventDefault(),e.stopPropagation();const t=$(e.currentTarget),a=t.data("mode"),o=t.data("params"),i=t.data("entryPoint");n.openPopupWindow(a,o,i)})).on("click",'[data-formengine-field-change-event="click"]',e=>{const t=JSON.parse(e.currentTarget.dataset.formengineFieldChangeItems);n.processOnFieldChange(t,e)}).on("change",'[data-formengine-field-change-event="change"]',e=>{const t=JSON.parse(e.currentTarget.dataset.formengineFieldChangeItems);n.processOnFieldChange(t,e)}),document.editform.addEventListener("submit",(function(){if(document.editform.closeDoc.value)return;const e=["button[form]",'button[name^="_save"]','a[data-name^="_save"]','button[name="CMD"][value^="save"]','a[data-name="CMD"][data-value^="save"]'].join(","),t=document.querySelector(e);null!==t&&(t.disabled=!0,Icons.getIcon("spinner-circle-dark",Icons.sizes.small).then((function(e){t.querySelector(".t3js-icon").outerHTML=e})))})),window.addEventListener("message",n.handlePostMessage)},consume:function(t){if(!t)throw new BackendExceptionModule.BackendException("No interaction request given",1496589980);const a=$.Deferred();if(t.concernsTypes(n.consumeTypes)){const o=t.outerMostRequest;n.interactionRequestMap.attachFor(o,a),o.isProcessed()?e(o,o.getProcessedData().response):n.hasChange()?n.preventExitIfNotSaved((function(t){o.setProcessedData({response:t}),e(o,t)})):n.interactionRequestMap.resolveFor(o)}return a},handlePostMessage:function(e){if(!MessageUtility.MessageUtility.verifyOrigin(e.origin))throw"Denied message sent by "+e.origin;if("typo3:elementBrowser:elementAdded"===e.data.actionName){if(void 0===e.data.fieldName)throw"fieldName not defined in message";if(void 0===e.data.value)throw"value not defined in message";const t=e.data.label||e.data.value,a=e.data.title||t,o=e.data.exclusiveValues||"";n.setSelectOptionFromExternalSource(e.data.fieldName,e.data.value,t,a,o)}},initializeRemainingCharacterViews:function(){const e=$("[maxlength]").not(".t3js-datetimepicker").not(".t3js-color-picker").not(".t3js-charcounter-initialized");e.on("focus",e=>{const t=$(e.currentTarget),a=t.parents(".t3js-formengine-field-item:first"),o=n.getCharacterCounterProperties(t);let i=a.find(".t3js-charcounter-wrapper");i.length||(i=$("<div>"),i.addClass("t3js-charcounter-wrapper"),a.append(i)),i.append($("<div />",{class:"t3js-charcounter"}).append($("<span />",{class:o.labelClass}).text(TYPO3.lang["FormEngine.remainingCharacters"].replace("{0}",o.remainingCharacters))))}).on("blur",e=>{$(e.currentTarget).parents(".t3js-formengine-field-item:first").find(".t3js-charcounter").remove()}).on("keyup",e=>{const t=$(e.currentTarget),a=t.parents(".t3js-formengine-field-item:first"),o=n.getCharacterCounterProperties(t);a.find(".t3js-charcounter span").removeClass().addClass(o.labelClass).text(TYPO3.lang["FormEngine.remainingCharacters"].replace("{0}",o.remainingCharacters))}),e.addClass("t3js-charcounter-initialized")},getCharacterCounterProperties:function(e){const t=e.val(),n=e.attr("maxlength")-t.length-(t.match(/\n/g)||[]).length;let a="";return a=n<15?"badge-danger":n<30?"badge-warning":"badge-info",{remainingCharacters:n,labelClass:"badge "+a}},initializeMinimumCharactersLeftViews:function(){const e=(t,n)=>t&&(n(t)?t:e(t.parentNode,n)),t=(t,n)=>{const a=e(n.currentTarget,e=>e.classList.contains("t3js-formengine-field-item")),o=a.querySelector(".t3js-charcounter-min"),i=TYPO3.lang["FormEngine.minCharactersLeft"].replace("{0}",t);if(o)o.querySelector("span").innerHTML=i;else{const e=document.createElement("div");e.classList.add("t3js-charcounter-min");const t=document.createElement("span");t.classList.add("badge","badge-danger"),t.innerHTML=i,e.append(t);let n=a.querySelector(".t3js-charcounter-wrapper");n||(n=document.createElement("div"),n.classList.add("t3js-charcounter-wrapper"),a.append(n)),n.prepend(e)}},a=t=>{const n=e(t.currentTarget,e=>e.classList.contains("t3js-formengine-field-item")).querySelector(".t3js-charcounter-min");n&&n.remove()};document.querySelectorAll("[minlength]:not(.t3js-datetimepicker):not(.t3js-charcounter-min-initialized)").forEach(e=>{e.addEventListener("focus",a=>{const o=n.getMinCharacterLeftCount(e);o>0&&t(o,a)}),e.addEventListener("blur",a),e.addEventListener("keyup",o=>{const i=n.getMinCharacterLeftCount(e);i>0?t(i,o):a(o)})})},getMinCharacterLeftCount:function(e){const t=e.value,n=e.minLength,a=t.length;if(0===a)return 0;return n-a-(t.match(/\n/g)||[]).length},initializeNullNoPlaceholderCheckboxes:function(){$(".t3-form-field-eval-null-checkbox").each((function(e,t){const n=$(t),a=n.find('input[type="checkbox"]'),o=n.closest(".t3js-formengine-field-item");a.attr("checked")||o.addClass("disabled")}))},initializeNullWithPlaceholderCheckboxes:function(){$(".t3js-form-field-eval-null-placeholder-checkbox").each((e,t)=>{n.toggleCheckboxField($(t).find('input[type="checkbox"]'),!1)})},toggleCheckboxField:function(e,t=!0){const n=e.closest(".t3js-formengine-field-item");e.prop("checked")?(n.find(".t3js-formengine-placeholder-placeholder").hide(),n.find(".t3js-formengine-placeholder-formfield").show(),t&&n.find(".t3js-formengine-placeholder-formfield").find(":input").trigger("focus")):(n.find(".t3js-formengine-placeholder-placeholder").show(),n.find(".t3js-formengine-placeholder-formfield").hide())},reinitialize:function(){const e=Array.from(document.querySelectorAll(".t3js-clearable"));e.length>0&&import("@typo3/backend/input/clearable.js").then((function(){e.forEach(e=>e.clearable())})),n.initializeNullNoPlaceholderCheckboxes(),n.initializeNullWithPlaceholderCheckboxes(),n.initializeLocalizationStateSelector(),n.initializeMinimumCharactersLeftViews(),n.initializeRemainingCharacterViews()},initializeLocalizationStateSelector:function(){$(".t3js-l10n-state-container").each((e,t)=>{const n=$(t),a=n.closest(".t3js-formengine-field-item").find("[data-formengine-input-name]"),o=n.find('input[type="radio"]:checked').val();"parent"!==o&&"source"!==o||a.attr("disabled","disabled")})},hasChange:function(){const e=$('form[name="'+n.formName+'"] .has-change').length>0,t=$('[name^="data["].has-change').length>0;return e||t},preventExitIfNotSavedCallback:function(e){n.closeDocument()},preventFollowLinkIfNotSaved:function(e){return n.preventExitIfNotSaved((function(){window.location.href=e})),!1},preventExitIfNotSaved:function(e){if(e=e||n.preventExitIfNotSavedCallback,n.hasChange()){const t=TYPO3.lang["label.confirm.close_without_save.title"]||"Do you want to close without saving?",a=TYPO3.lang["label.confirm.close_without_save.content"]||"You currently have unsaved changes. Are you sure you want to discard these changes?",o=$("<input />").attr("type","hidden").attr("name","_saveandclosedok").attr("value","1"),i=[{text:TYPO3.lang["buttons.confirm.close_without_save.no"]||"No, I will continue editing",btnClass:"btn-default",name:"no"},{text:TYPO3.lang["buttons.confirm.close_without_save.yes"]||"Yes, discard my changes",btnClass:"btn-default",name:"yes"}];0===$(".has-error").length&&i.push({text:TYPO3.lang["buttons.confirm.save_and_close"]||"Save and close",btnClass:"btn-warning",name:"save",active:!0});Modal.confirm(t,a,Severity.warning,i).on("button.clicked",(function(t){"no"===t.target.name?Modal.dismiss():"yes"===t.target.name?(Modal.dismiss(),e.call(null,!0)):"save"===t.target.name&&($("form[name="+n.formName+"]").append(o),Modal.dismiss(),n.saveDocument())}))}else e.call(null,!0)},preventSaveIfHasErrors:function(){if($(".has-error").length>0){const e=TYPO3.lang["label.alert.save_with_error.title"]||"You have errors in your form!",t=TYPO3.lang["label.alert.save_with_error.content"]||"Please check the form, there is at least one error in your form.";return Modal.confirm(e,t,Severity.error,[{text:TYPO3.lang["buttons.alert.save_with_error.ok"]||"OK",btnClass:"btn-danger",name:"ok"}]).on("button.clicked",(function(e){"ok"===e.target.name&&Modal.dismiss()})),!1}return!0},requestFormEngineUpdate:function(e){if(e){Modal.confirm(TYPO3.lang["FormEngine.refreshRequiredTitle"],TYPO3.lang["FormEngine.refreshRequiredContent"]).on("button.clicked",(function(e){"ok"===e.target.name?(n.closeModalsRecursive(),n.saveDocument()):Modal.dismiss()}))}else n.saveDocument()},processOnFieldChange:function(e,n){e.forEach(e=>{const a=t.get(e.name);a instanceof Function&&a.call(null,e.data||null,n)})},registerOnFieldChangeHandler:function(e,n){t.has(e)&&console.warn("Handler for onFieldChange name `"+e+"` has been overridden."),t.set(e,n)},closeModalsRecursive:function(){void 0!==Modal.currentModal&&null!==Modal.currentModal&&(Modal.currentModal.on("hidden.bs.modal",(function(){n.closeModalsRecursive(Modal.currentModal)})),Modal.currentModal.trigger("modal-dismiss"))},previewAction:function(e,t){t=t||n.previewActionCallback;const a=e.target.href,o=e.target.dataset.hasOwnProperty("isNew"),i=$("<input />").attr("type","hidden").attr("name","_savedokview").attr("value","1");n.hasChange()?n.showPreviewModal(a,o,i,t):($("form[name="+n.formName+"]").append(i),window.open("","newTYPO3frontendWindow"),document.editform.submit())},previewActionCallback:function(e,t,a){switch(Modal.dismiss(),e){case"discard":const e=window.open(t,"newTYPO3frontendWindow");e.focus(),e.location.href===t&&e.location.reload();break;case"save":$("form[name="+n.formName+"]").append(a),window.open("","newTYPO3frontendWindow"),n.saveDocument()}},showPreviewModal:function(e,t,n,a){const o=TYPO3.lang["label.confirm.view_record_changed.title"]||"Do you want to save before viewing?",i={text:TYPO3.lang["buttons.confirm.view_record_changed.cancel"]||"Cancel",btnClass:"btn-default",name:"cancel"},r={text:TYPO3.lang["buttons.confirm.view_record_changed.no-save"]||"View without changes",btnClass:"btn-info",name:"discard"},c={text:TYPO3.lang["buttons.confirm.view_record_changed.save"]||"Save changes and view",btnClass:"btn-info",name:"save",active:!0};let l=[],s="";t?(l=[i,c],s=TYPO3.lang["label.confirm.view_record_changed.content.is-new-page"]||"You need to save your changes before viewing the page. Do you want to save and view them now?"):(l=[i,r,c],s=TYPO3.lang["label.confirm.view_record_changed.content"]||"You currently have unsaved changes. You can either discard these changes or save and view them.");const d=Modal.confirm(o,s,Severity.info,l);d.on("button.clicked",(function(t){a(t.target.name,e,n,d)}))},newAction:function(e,t){t=t||n.newActionCallback;const a=$("<input />").attr("type","hidden").attr("name","_savedoknew").attr("value","1"),o=e.target.dataset.hasOwnProperty("isNew");n.hasChange()?n.showNewModal(o,a,t):($("form[name="+n.formName+"]").append(a),document.editform.submit())},newActionCallback:function(e,t){const a=$("form[name="+n.formName+"]");switch(Modal.dismiss(),e){case"no":a.append(t),document.editform.submit();break;case"yes":a.append(t),n.saveDocument()}},showNewModal:function(e,t,n){const a=TYPO3.lang["label.confirm.new_record_changed.title"]||"Do you want to save before adding?",o=TYPO3.lang["label.confirm.new_record_changed.content"]||"You need to save your changes before creating a new record. Do you want to save and create now?";let i=[];const r={text:TYPO3.lang["buttons.confirm.new_record_changed.cancel"]||"Cancel",btnClass:"btn-default",name:"cancel"},c={text:TYPO3.lang["buttons.confirm.new_record_changed.no"]||"No, just add",btnClass:"btn-default",name:"no"},l={text:TYPO3.lang["buttons.confirm.new_record_changed.yes"]||"Yes, save and create now",btnClass:"btn-info",name:"yes",active:!0};i=e?[r,l]:[r,c,l];Modal.confirm(a,o,Severity.info,i).on("button.clicked",(function(e){n(e.target.name,t)}))},duplicateAction:function(e,t){t=t||n.duplicateActionCallback;const a=$("<input />").attr("type","hidden").attr("name","_duplicatedoc").attr("value","1"),o=e.target.dataset.hasOwnProperty("isNew");n.hasChange()?n.showDuplicateModal(o,a,t):($("form[name="+n.formName+"]").append(a),document.editform.submit())},duplicateActionCallback:function(e,t){const a=$("form[name="+n.formName+"]");switch(Modal.dismiss(),e){case"no":a.append(t),document.editform.submit();break;case"yes":a.append(t),n.saveDocument()}},showDuplicateModal:function(e,t,n){const a=TYPO3.lang["label.confirm.duplicate_record_changed.title"]||"Do you want to save before duplicating this record?",o=TYPO3.lang["label.confirm.duplicate_record_changed.content"]||"You currently have unsaved changes. Do you want to save your changes before duplicating this record?";let i=[];const r={text:TYPO3.lang["buttons.confirm.duplicate_record_changed.cancel"]||"Cancel",btnClass:"btn-default",name:"cancel"},c={text:TYPO3.lang["buttons.confirm.duplicate_record_changed.no"]||"No, just duplicate the original",btnClass:"btn-default",name:"no"},l={text:TYPO3.lang["buttons.confirm.duplicate_record_changed.yes"]||"Yes, save and duplicate this record",btnClass:"btn-info",name:"yes",active:!0};i=e?[r,l]:[r,c,l];Modal.confirm(a,o,Severity.info,i).on("button.clicked",(function(e){n(e.target.name,t)}))},deleteAction:function(e,t){t=t||n.deleteActionCallback;const a=$(e.target);n.showDeleteModal(a,t)},deleteActionCallback:function(e,t){Modal.dismiss(),"yes"===e&&n.invokeRecordDeletion(t)},showDeleteModal:function(e,t){const n=TYPO3.lang["label.confirm.delete_record.title"]||"Delete this record?";let a=(TYPO3.lang["label.confirm.delete_record.content"]||"Are you sure you want to delete the record '%s'?").replace("%s",e.data("record-info"));e.data("reference-count-message")&&(a+="\n"+e.data("reference-count-message")),e.data("translation-count-message")&&(a+="\n"+e.data("translation-count-message"));Modal.confirm(n,a,Severity.warning,[{text:TYPO3.lang["buttons.confirm.delete_record.no"]||"Cancel",btnClass:"btn-default",name:"no"},{text:TYPO3.lang["buttons.confirm.delete_record.yes"]||"Yes, delete this record",btnClass:"btn-warning",name:"yes",active:!0}]).on("button.clicked",(function(n){t(n.target.name,e)}))},enableOptGroup:function(e){const t=e.parentElement;t instanceof HTMLOptGroupElement&&t.querySelectorAll("option:not([hidden]):not([disabled]):not(.hidden)").length&&(t.hidden=!1,t.disabled=!1,t.classList.remove("hidden"))},closeDocument:function(){document.editform.closeDoc.value=1,n.dispatchSubmitEvent(),document.editform.submit()},saveDocument:function(){document.editform.doSave.value=1,n.dispatchSubmitEvent(),document.editform.submit()},dispatchSubmitEvent:function(){const e=document.createEvent("Event");e.initEvent("submit",!1,!0),document.editform.dispatchEvent(e)},initialize:function(e){n.browserUrl=e,$((function(){n.initializeEvents(),n.Validation.initialize(),n.reinitialize(),$("#t3js-ui-block").remove()}))},invokeRecordDeletion:function(e){window.location.href=e.attr("href")}};return void 0!==TYPO3.settings.RequireJS&&void 0!==TYPO3.settings.RequireJS.PostInitializationModules["TYPO3/CMS/Backend/FormEngine"]&&$.each(TYPO3.settings.RequireJS.PostInitializationModules["TYPO3/CMS/Backend/FormEngine"],(function(e,t){window.require([t])})),TYPO3.FormEngine=n,n}());
\ No newline at end of file
+import $ from"jquery";import FormEngineValidation from"@typo3/backend/form-engine-validation.js";import Icons from"@typo3/backend/icons.js";import Modal from"@typo3/backend/modal.js";import*as MessageUtility from"@typo3/backend/utility/message-utility.js";import Severity from"@typo3/backend/severity.js";import*as BackendExceptionModule from"@typo3/backend/backend-exception.js";import InteractionRequestMap from"@typo3/backend/event/interaction-request-map.js";import Utility from"@typo3/backend/utility.js";export default(function(){function e(e,t){t?n.interactionRequestMap.resolveFor(e):n.interactionRequestMap.rejectFor(e)}const t=new Map;t.set("typo3-backend-form-update-value",(e,t)=>{const n=document.querySelector('[name="'+CSS.escape(e.elementName)+'"]'),a=document.querySelector('[data-formengine-input-name="'+CSS.escape(e.elementName)+'"]');FormEngineValidation.updateInputField(e.elementName),null!==n&&(FormEngineValidation.markFieldAsChanged(n),FormEngineValidation.validateField(n)),null!==a&&a!==n&&FormEngineValidation.validateField(a)}),t.set("typo3-backend-form-reload",(e,t)=>{e.confirmation?Modal.confirm(TYPO3.lang["FormEngine.refreshRequiredTitle"],TYPO3.lang["FormEngine.refreshRequiredContent"]).on("button.clicked",e=>{"ok"==e.target.name&&n.saveDocument(),Modal.dismiss()}):n.saveDocument()}),t.set("typo3-backend-form-update-bitmask",(e,t)=>{const n=t.target,a=document.editform[e.elementName],o=n.checked!==e.invert,i=Math.pow(2,e.position),r=Math.pow(2,e.total)-i-1;a.value=o?a.value|i:a.value&r,a.dispatchEvent(new Event("change",{bubbles:!0,cancelable:!0}))});const n={consumeTypes:["typo3.setUrl","typo3.beforeSetUrl","typo3.refresh"],Validation:FormEngineValidation,interactionRequestMap:InteractionRequestMap,formName:TYPO3.settings.FormEngine.formName,openedPopupWindow:null,legacyFieldChangedCb:function(){!$.isFunction(TYPO3.settings.FormEngine.legacyFieldChangedCb)||TYPO3.settings.FormEngine.legacyFieldChangedCb()},browserUrl:"",openPopupWindow:function(e,t,a){return Modal.advanced({type:Modal.types.iframe,content:n.browserUrl+"&mode="+e+"&bparams="+t+(a?"&"+("db"===e?"expandPage":"expandFolder")+"="+a:""),size:Modal.sizes.large})},setSelectOptionFromExternalSource:function(e,t,a,o,i,r){i=String(i);let c,l,s=!1,d=!1;if(c=n.getFieldElement(e),l=c.get(0),null===l||"--div--"===t||l instanceof HTMLOptGroupElement)return;const u=n.getFieldElement(e,"_list",!0);if(u.length>0&&(c=u,s=c.prop("multiple")&&"1"!=c.prop("size"),d=!0),s||d){const d=n.getFieldElement(e,"_avail");if(s||(c.find("option").each((e,t)=>{const a=d.find('option[value="'+$.escapeSelector($(t).attr("value"))+'"]');a.length&&(a.removeClass("hidden").prop("disabled",!1),n.enableOptGroup(a.get(0)))}),c.empty()),i){let e=!1,a=new RegExp("(^|,)"+t+"($|,)");i.match(a)?(c.empty(),e=!0):1==c.find("option").length&&(a=new RegExp("(^|,)"+c.find("option").prop("value")+"($|,)"),i.match(a)&&(c.empty(),e=!0)),e&&void 0!==r&&r.closest("select").querySelectorAll("[disabled]").forEach((function(e){e.classList.remove("hidden"),e.disabled=!1,n.enableOptGroup(e)}))}let u=!0;const m=n.getFieldElement(e,"_mul",!0);if((0==m.length||0==m.val())&&(c.find("option").each((function(e,n){if($(n).prop("value")==t)return u=!1,!1})),u&&void 0!==r)){r.classList.add("hidden"),r.disabled=!0;const e=r.parentElement;e instanceof HTMLOptGroupElement&&0===e.querySelectorAll("option:not([disabled]):not([hidden]):not(.hidden)").length&&(e.disabled=!0,e.classList.add("hidden"))}if(u){const e=$("<option></option>");e.attr({value:t,title:o}).text(a),e.appendTo(c),n.updateHiddenFieldValueFromSelect(c,l),n.legacyFieldChangedCb(),FormEngineValidation.markFieldAsChanged(l),n.Validation.validateField(c),n.Validation.validateField(d)}}else{const e=/_(\d+)$/,a=t.toString().match(e);null!=a&&(t=a[1]),c.val(t),n.Validation.validateField(c)}},updateHiddenFieldValueFromSelect:function(e,t){const n=[];$(e).find("option").each((e,t)=>{n.push($(t).prop("value"))}),t.value=n.join(","),t.dispatchEvent(new Event("change",{bubbles:!0,cancelable:!0}))},getFormElement:function(e){const t=$('form[name="'+n.formName+'"]:first');if(!e)return t;{const a=n.getFieldElement(e),o=n.getFieldElement(e,"_list");if(a.length>0&&("select-one"===a.prop("type")||o.length>0&&o.prop("type").match(/select-(one|multiple)/)))return t;console.error("Form fields missing: form: "+n.formName+", field name: "+e),alert("Form field is invalid")}},getFieldElement:function(e,t,a){const o=$('form[name="'+n.formName+'"]:first');if(t){let n;switch(t){case"_list":n=$(':input[data-formengine-input-name="'+e+'"]:not([type=hidden])',o);break;case"_avail":n=$(':input[data-relatedfieldname="'+e+'"]',o);break;case"_mul":case"_hr":n=$(':input[type=hidden][data-formengine-input-name="'+e+'"]',o);break;default:n=null}if(n&&n.length>0||!0===a)return n}return $(':input[name="'+e+'"]',o)},initializeEvents:function(){top.TYPO3&&void 0!==top.TYPO3.Backend&&(top.TYPO3.Backend.consumerScope.attach(n),$(window).on("unload",(function(){top.TYPO3.Backend.consumerScope.detach(n)}))),$(document).on("click",".t3js-editform-close",e=>{e.preventDefault(),n.preventExitIfNotSaved(n.preventExitIfNotSavedCallback)}).on("click",".t3js-editform-view",e=>{e.preventDefault(),n.previewAction(e,n.previewActionCallback)}).on("click",".t3js-editform-new",e=>{e.preventDefault(),n.newAction(e,n.newActionCallback)}).on("click",".t3js-editform-duplicate",e=>{e.preventDefault(),n.duplicateAction(e,n.duplicateActionCallback)}).on("click",".t3js-editform-delete-record",e=>{e.preventDefault(),n.deleteAction(e,n.deleteActionCallback)}).on("click",".t3js-editform-submitButton",e=>{const t=$(e.currentTarget),n=t.data("name")||e.currentTarget.name,a=$("<input />").attr("type","hidden").attr("name",n).attr("value","1");t.parents("form").append(a)}).on("change",'.t3-form-field-eval-null-checkbox input[type="checkbox"]',e=>{$(e.currentTarget).closest(".t3js-formengine-field-item").toggleClass("disabled")}).on("change",'.t3js-form-field-eval-null-placeholder-checkbox input[type="checkbox"]',e=>{n.toggleCheckboxField($(e.currentTarget)),FormEngineValidation.markFieldAsChanged($(e.currentTarget))}).on("change",(function(e){$(".module-docheader-bar .btn").removeClass("disabled").prop("disabled",!1)})).on("click",".t3js-element-browser",(function(e){e.preventDefault(),e.stopPropagation();const t=$(e.currentTarget),a=t.data("mode"),o=t.data("params"),i=t.data("entryPoint");n.openPopupWindow(a,o,i)})).on("click",'[data-formengine-field-change-event="click"]',e=>{const t=JSON.parse(e.currentTarget.dataset.formengineFieldChangeItems);n.processOnFieldChange(t,e)}).on("change",'[data-formengine-field-change-event="change"]',e=>{const t=JSON.parse(e.currentTarget.dataset.formengineFieldChangeItems);n.processOnFieldChange(t,e)}),document.editform.addEventListener("submit",(function(){if(document.editform.closeDoc.value)return;const e=["button[form]",'button[name^="_save"]','a[data-name^="_save"]','button[name="CMD"][value^="save"]','a[data-name="CMD"][data-value^="save"]'].join(","),t=document.querySelector(e);null!==t&&(t.disabled=!0,Icons.getIcon("spinner-circle-dark",Icons.sizes.small).then((function(e){t.querySelector(".t3js-icon").outerHTML=e})))})),window.addEventListener("message",n.handlePostMessage)},consume:function(t){if(!t)throw new BackendExceptionModule.BackendException("No interaction request given",1496589980);const a=$.Deferred();if(t.concernsTypes(n.consumeTypes)){const o=t.outerMostRequest;n.interactionRequestMap.attachFor(o,a),o.isProcessed()?e(o,o.getProcessedData().response):n.hasChange()?n.preventExitIfNotSaved((function(t){o.setProcessedData({response:t}),e(o,t)})):n.interactionRequestMap.resolveFor(o)}return a},handlePostMessage:function(e){if(!MessageUtility.MessageUtility.verifyOrigin(e.origin))throw"Denied message sent by "+e.origin;if("typo3:elementBrowser:elementAdded"===e.data.actionName){if(void 0===e.data.fieldName)throw"fieldName not defined in message";if(void 0===e.data.value)throw"value not defined in message";const t=e.data.label||e.data.value,a=e.data.title||t,o=e.data.exclusiveValues||"";n.setSelectOptionFromExternalSource(e.data.fieldName,e.data.value,t,a,o)}},initializeRemainingCharacterViews:function(){const e=$("[maxlength]").not(".t3js-datetimepicker").not(".t3js-color-picker").not(".t3js-charcounter-initialized");e.on("focus",e=>{const t=$(e.currentTarget),a=t.parents(".t3js-formengine-field-item:first"),o=n.getCharacterCounterProperties(t);let i=a.find(".t3js-charcounter-wrapper");i.length||(i=$("<div>"),i.addClass("t3js-charcounter-wrapper"),a.append(i)),i.append($("<div />",{class:"t3js-charcounter"}).append($("<span />",{class:o.labelClass}).text(TYPO3.lang["FormEngine.remainingCharacters"].replace("{0}",o.remainingCharacters))))}).on("blur",e=>{$(e.currentTarget).parents(".t3js-formengine-field-item:first").find(".t3js-charcounter").remove()}).on("keyup",e=>{const t=$(e.currentTarget),a=t.parents(".t3js-formengine-field-item:first"),o=n.getCharacterCounterProperties(t);a.find(".t3js-charcounter span").removeClass().addClass(o.labelClass).text(TYPO3.lang["FormEngine.remainingCharacters"].replace("{0}",o.remainingCharacters))}),e.addClass("t3js-charcounter-initialized")},getCharacterCounterProperties:function(e){const t=e.val(),n=e.attr("maxlength")-t.length-(t.match(/\n/g)||[]).length;let a="";return a=n<15?"badge-danger":n<30?"badge-warning":"badge-info",{remainingCharacters:n,labelClass:"badge "+a}},initializeMinimumCharactersLeftViews:function(){const e=(t,n)=>t&&(n(t)?t:e(t.parentNode,n)),t=(t,n)=>{const a=e(n.currentTarget,e=>e.classList.contains("t3js-formengine-field-item")),o=a.querySelector(".t3js-charcounter-min"),i=TYPO3.lang["FormEngine.minCharactersLeft"].replace("{0}",t);if(o)o.querySelector("span").innerHTML=i;else{const e=document.createElement("div");e.classList.add("t3js-charcounter-min");const t=document.createElement("span");t.classList.add("badge","badge-danger"),t.innerHTML=i,e.append(t);let n=a.querySelector(".t3js-charcounter-wrapper");n||(n=document.createElement("div"),n.classList.add("t3js-charcounter-wrapper"),a.append(n)),n.prepend(e)}},a=t=>{const n=e(t.currentTarget,e=>e.classList.contains("t3js-formengine-field-item")).querySelector(".t3js-charcounter-min");n&&n.remove()};document.querySelectorAll("[minlength]:not(.t3js-datetimepicker):not(.t3js-charcounter-min-initialized)").forEach(e=>{e.addEventListener("focus",a=>{const o=n.getMinCharacterLeftCount(e);o>0&&t(o,a)}),e.addEventListener("blur",a),e.addEventListener("keyup",o=>{const i=n.getMinCharacterLeftCount(e);i>0?t(i,o):a(o)})})},getMinCharacterLeftCount:function(e){const t=e.value,n=e.minLength,a=t.length;if(0===a)return 0;return n-a-(t.match(/\n/g)||[]).length},initializeNullNoPlaceholderCheckboxes:function(){$(".t3-form-field-eval-null-checkbox").each((function(e,t){const n=$(t),a=n.find('input[type="checkbox"]'),o=n.closest(".t3js-formengine-field-item");a.attr("checked")||o.addClass("disabled")}))},initializeNullWithPlaceholderCheckboxes:function(){$(".t3js-form-field-eval-null-placeholder-checkbox").each((e,t)=>{n.toggleCheckboxField($(t).find('input[type="checkbox"]'),!1)})},toggleCheckboxField:function(e,t=!0){const n=e.closest(".t3js-formengine-field-item");e.prop("checked")?(n.find(".t3js-formengine-placeholder-placeholder").hide(),n.find(".t3js-formengine-placeholder-formfield").show(),t&&n.find(".t3js-formengine-placeholder-formfield").find(":input").trigger("focus")):(n.find(".t3js-formengine-placeholder-placeholder").show(),n.find(".t3js-formengine-placeholder-formfield").hide())},reinitialize:function(){const e=Array.from(document.querySelectorAll(".t3js-clearable"));e.length>0&&import("@typo3/backend/input/clearable.js").then((function(){e.forEach(e=>e.clearable())})),n.initializeNullNoPlaceholderCheckboxes(),n.initializeNullWithPlaceholderCheckboxes(),n.initializeLocalizationStateSelector(),n.initializeMinimumCharactersLeftViews(),n.initializeRemainingCharacterViews()},initializeLocalizationStateSelector:function(){$(".t3js-l10n-state-container").each((e,t)=>{const n=$(t),a=n.closest(".t3js-formengine-field-item").find("[data-formengine-input-name]"),o=n.find('input[type="radio"]:checked').val();"parent"!==o&&"source"!==o||a.attr("disabled","disabled")})},hasChange:function(){const e=$('form[name="'+n.formName+'"] .has-change').length>0,t=$('[name^="data["].has-change').length>0;return e||t},preventExitIfNotSavedCallback:function(e){n.closeDocument()},preventFollowLinkIfNotSaved:function(e){return n.preventExitIfNotSaved((function(){window.location.href=e})),!1},preventExitIfNotSaved:function(e){if(e=e||n.preventExitIfNotSavedCallback,n.hasChange()){const t=TYPO3.lang["label.confirm.close_without_save.title"]||"Do you want to close without saving?",a=TYPO3.lang["label.confirm.close_without_save.content"]||"You currently have unsaved changes. Are you sure you want to discard these changes?",o=$("<input />").attr("type","hidden").attr("name","_saveandclosedok").attr("value","1"),i=[{text:TYPO3.lang["buttons.confirm.close_without_save.no"]||"No, I will continue editing",btnClass:"btn-default",name:"no"},{text:TYPO3.lang["buttons.confirm.close_without_save.yes"]||"Yes, discard my changes",btnClass:"btn-default",name:"yes"}];0===$(".has-error").length&&i.push({text:TYPO3.lang["buttons.confirm.save_and_close"]||"Save and close",btnClass:"btn-warning",name:"save",active:!0});Modal.confirm(t,a,Severity.warning,i).on("button.clicked",(function(t){"no"===t.target.name?Modal.dismiss():"yes"===t.target.name?(Modal.dismiss(),e.call(null,!0)):"save"===t.target.name&&($("form[name="+n.formName+"]").append(o),Modal.dismiss(),n.saveDocument())}))}else e.call(null,!0)},preventSaveIfHasErrors:function(){if($(".has-error").length>0){const e=TYPO3.lang["label.alert.save_with_error.title"]||"You have errors in your form!",t=TYPO3.lang["label.alert.save_with_error.content"]||"Please check the form, there is at least one error in your form.";return Modal.confirm(e,t,Severity.error,[{text:TYPO3.lang["buttons.alert.save_with_error.ok"]||"OK",btnClass:"btn-danger",name:"ok"}]).on("button.clicked",(function(e){"ok"===e.target.name&&Modal.dismiss()})),!1}return!0},requestFormEngineUpdate:function(e){if(e){Modal.confirm(TYPO3.lang["FormEngine.refreshRequiredTitle"],TYPO3.lang["FormEngine.refreshRequiredContent"]).on("button.clicked",(function(e){"ok"===e.target.name?(n.closeModalsRecursive(),n.saveDocument()):Modal.dismiss()}))}else n.saveDocument()},processOnFieldChange:function(e,n){e.forEach(e=>{const a=t.get(e.name);a instanceof Function&&a.call(null,e.data||null,n)})},registerOnFieldChangeHandler:function(e,n){t.has(e)&&console.warn("Handler for onFieldChange name `"+e+"` has been overridden."),t.set(e,n)},closeModalsRecursive:function(){void 0!==Modal.currentModal&&null!==Modal.currentModal&&(Modal.currentModal.on("hidden.bs.modal",(function(){n.closeModalsRecursive(Modal.currentModal)})),Modal.currentModal.trigger("modal-dismiss"))},previewAction:function(e,t){t=t||n.previewActionCallback;const a=e.currentTarget.href,o=e.target.dataset.hasOwnProperty("isNew"),i=$("<input />").attr("type","hidden").attr("name","_savedokview").attr("value","1");n.hasChange()?n.showPreviewModal(a,o,i,t):($("form[name="+n.formName+"]").append(i),window.open("","newTYPO3frontendWindow"),document.editform.submit())},previewActionCallback:function(e,t,a){switch(Modal.dismiss(),e){case"discard":const e=window.open(t,"newTYPO3frontendWindow");e.focus(),Utility.urlsPointToSameServerSideResource(e.location.href,t)&&e.location.reload();break;case"save":$("form[name="+n.formName+"]").append(a),window.open("","newTYPO3frontendWindow"),n.saveDocument()}},showPreviewModal:function(e,t,n,a){const o=TYPO3.lang["label.confirm.view_record_changed.title"]||"Do you want to save before viewing?",i={text:TYPO3.lang["buttons.confirm.view_record_changed.cancel"]||"Cancel",btnClass:"btn-default",name:"cancel"},r={text:TYPO3.lang["buttons.confirm.view_record_changed.no-save"]||"View without changes",btnClass:"btn-info",name:"discard"},c={text:TYPO3.lang["buttons.confirm.view_record_changed.save"]||"Save changes and view",btnClass:"btn-info",name:"save",active:!0};let l=[],s="";t?(l=[i,c],s=TYPO3.lang["label.confirm.view_record_changed.content.is-new-page"]||"You need to save your changes before viewing the page. Do you want to save and view them now?"):(l=[i,r,c],s=TYPO3.lang["label.confirm.view_record_changed.content"]||"You currently have unsaved changes. You can either discard these changes or save and view them.");const d=Modal.confirm(o,s,Severity.info,l);d.on("button.clicked",(function(t){a(t.target.name,e,n,d)}))},newAction:function(e,t){t=t||n.newActionCallback;const a=$("<input />").attr("type","hidden").attr("name","_savedoknew").attr("value","1"),o=e.target.dataset.hasOwnProperty("isNew");n.hasChange()?n.showNewModal(o,a,t):($("form[name="+n.formName+"]").append(a),document.editform.submit())},newActionCallback:function(e,t){const a=$("form[name="+n.formName+"]");switch(Modal.dismiss(),e){case"no":a.append(t),document.editform.submit();break;case"yes":a.append(t),n.saveDocument()}},showNewModal:function(e,t,n){const a=TYPO3.lang["label.confirm.new_record_changed.title"]||"Do you want to save before adding?",o=TYPO3.lang["label.confirm.new_record_changed.content"]||"You need to save your changes before creating a new record. Do you want to save and create now?";let i=[];const r={text:TYPO3.lang["buttons.confirm.new_record_changed.cancel"]||"Cancel",btnClass:"btn-default",name:"cancel"},c={text:TYPO3.lang["buttons.confirm.new_record_changed.no"]||"No, just add",btnClass:"btn-default",name:"no"},l={text:TYPO3.lang["buttons.confirm.new_record_changed.yes"]||"Yes, save and create now",btnClass:"btn-info",name:"yes",active:!0};i=e?[r,l]:[r,c,l];Modal.confirm(a,o,Severity.info,i).on("button.clicked",(function(e){n(e.target.name,t)}))},duplicateAction:function(e,t){t=t||n.duplicateActionCallback;const a=$("<input />").attr("type","hidden").attr("name","_duplicatedoc").attr("value","1"),o=e.target.dataset.hasOwnProperty("isNew");n.hasChange()?n.showDuplicateModal(o,a,t):($("form[name="+n.formName+"]").append(a),document.editform.submit())},duplicateActionCallback:function(e,t){const a=$("form[name="+n.formName+"]");switch(Modal.dismiss(),e){case"no":a.append(t),document.editform.submit();break;case"yes":a.append(t),n.saveDocument()}},showDuplicateModal:function(e,t,n){const a=TYPO3.lang["label.confirm.duplicate_record_changed.title"]||"Do you want to save before duplicating this record?",o=TYPO3.lang["label.confirm.duplicate_record_changed.content"]||"You currently have unsaved changes. Do you want to save your changes before duplicating this record?";let i=[];const r={text:TYPO3.lang["buttons.confirm.duplicate_record_changed.cancel"]||"Cancel",btnClass:"btn-default",name:"cancel"},c={text:TYPO3.lang["buttons.confirm.duplicate_record_changed.no"]||"No, just duplicate the original",btnClass:"btn-default",name:"no"},l={text:TYPO3.lang["buttons.confirm.duplicate_record_changed.yes"]||"Yes, save and duplicate this record",btnClass:"btn-info",name:"yes",active:!0};i=e?[r,l]:[r,c,l];Modal.confirm(a,o,Severity.info,i).on("button.clicked",(function(e){n(e.target.name,t)}))},deleteAction:function(e,t){t=t||n.deleteActionCallback;const a=$(e.target);n.showDeleteModal(a,t)},deleteActionCallback:function(e,t){Modal.dismiss(),"yes"===e&&n.invokeRecordDeletion(t)},showDeleteModal:function(e,t){const n=TYPO3.lang["label.confirm.delete_record.title"]||"Delete this record?";let a=(TYPO3.lang["label.confirm.delete_record.content"]||"Are you sure you want to delete the record '%s'?").replace("%s",e.data("record-info"));e.data("reference-count-message")&&(a+="\n"+e.data("reference-count-message")),e.data("translation-count-message")&&(a+="\n"+e.data("translation-count-message"));Modal.confirm(n,a,Severity.warning,[{text:TYPO3.lang["buttons.confirm.delete_record.no"]||"Cancel",btnClass:"btn-default",name:"no"},{text:TYPO3.lang["buttons.confirm.delete_record.yes"]||"Yes, delete this record",btnClass:"btn-warning",name:"yes",active:!0}]).on("button.clicked",(function(n){t(n.target.name,e)}))},enableOptGroup:function(e){const t=e.parentElement;t instanceof HTMLOptGroupElement&&t.querySelectorAll("option:not([hidden]):not([disabled]):not(.hidden)").length&&(t.hidden=!1,t.disabled=!1,t.classList.remove("hidden"))},closeDocument:function(){document.editform.closeDoc.value=1,n.dispatchSubmitEvent(),document.editform.submit()},saveDocument:function(){document.editform.doSave.value=1,n.dispatchSubmitEvent(),document.editform.submit()},dispatchSubmitEvent:function(){const e=document.createEvent("Event");e.initEvent("submit",!1,!0),document.editform.dispatchEvent(e)},initialize:function(e){n.browserUrl=e,$((function(){n.initializeEvents(),n.Validation.initialize(),n.reinitialize(),$("#t3js-ui-block").remove()}))},invokeRecordDeletion:function(e){window.location.href=e.attr("href")}};return void 0!==TYPO3.settings.RequireJS&&void 0!==TYPO3.settings.RequireJS.PostInitializationModules["TYPO3/CMS/Backend/FormEngine"]&&$.each(TYPO3.settings.RequireJS.PostInitializationModules["TYPO3/CMS/Backend/FormEngine"],(function(e,t){window.require([t])})),TYPO3.FormEngine=n,n}());
\ No newline at end of file
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/utility.js b/typo3/sysext/backend/Resources/Public/JavaScript/utility.js
index 32b94e3edd9e..2221019a4166 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/utility.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/utility.js
@@ -10,4 +10,4 @@
  *
  * The TYPO3 project - inspiring people to share!
  */
-class Utility{static trimExplode(t,e){return e.split(t).map(t=>t.trim()).filter(t=>""!==t)}static trimItems(t){return t.map(t=>t instanceof String?t.trim():t)}static intExplode(t,e,r=!1){return e.split(t).map(t=>parseInt(t,10)).filter(t=>!isNaN(t)||r&&0===t)}static isNumber(t){return!isNaN(parseFloat(t.toString()))&&isFinite(t)}static getParameterFromUrl(t,e){if("function"!=typeof t.split)return"";const r=t.split("?");let i="";if(r.length>=2){const t=r.join("?"),n=encodeURIComponent(e)+"=",a=t.split(/[&;]/g);for(let t=a.length;t-- >0;)if(-1!==a[t].lastIndexOf(n,0)){i=a[t].split("=")[1];break}}return i}static updateQueryStringParameter(t,e,r){const i=new RegExp("([?&])"+e+"=.*?(&|$)","i"),n=t.includes("?")?"&":"?";return t.match(i)?t.replace(i,"$1"+e+"="+r+"$2"):t+n+e+"="+r}static convertFormToObject(t){const e={};return t.querySelectorAll("input, select, textarea").forEach(t=>{const r=t.name,i=t.value;r&&(t instanceof HTMLInputElement&&"checkbox"==t.type?(void 0===e[r]&&(e[r]=[]),t.checked&&e[r].push(i)):e[r]=i)}),e}static mergeDeep(...t){const e=t=>t&&"object"==typeof t;return t.reduce((t,r)=>(Object.keys(r).forEach(i=>{const n=t[i],a=r[i];Array.isArray(n)&&Array.isArray(a)?t[i]=n.concat(...a):e(n)&&e(a)?t[i]=Utility.mergeDeep(n,a):t[i]=a}),t),{})}}export default Utility;
\ No newline at end of file
+class Utility{static trimExplode(t,e){return e.split(t).map(t=>t.trim()).filter(t=>""!==t)}static trimItems(t){return t.map(t=>t instanceof String?t.trim():t)}static intExplode(t,e,r=!1){return e.split(t).map(t=>parseInt(t,10)).filter(t=>!isNaN(t)||r&&0===t)}static isNumber(t){return!isNaN(parseFloat(t.toString()))&&isFinite(t)}static getParameterFromUrl(t,e){if("function"!=typeof t.split)return"";const r=t.split("?");let i="";if(r.length>=2){const t=r.join("?"),n=encodeURIComponent(e)+"=",a=t.split(/[&;]/g);for(let t=a.length;t-- >0;)if(-1!==a[t].lastIndexOf(n,0)){i=a[t].split("=")[1];break}}return i}static updateQueryStringParameter(t,e,r){const i=new RegExp("([?&])"+e+"=.*?(&|$)","i"),n=t.includes("?")?"&":"?";return t.match(i)?t.replace(i,"$1"+e+"="+r+"$2"):t+n+e+"="+r}static convertFormToObject(t){const e={};return t.querySelectorAll("input, select, textarea").forEach(t=>{const r=t.name,i=t.value;r&&(t instanceof HTMLInputElement&&"checkbox"==t.type?(void 0===e[r]&&(e[r]=[]),t.checked&&e[r].push(i)):e[r]=i)}),e}static mergeDeep(...t){const e=t=>t&&"object"==typeof t;return t.reduce((t,r)=>(Object.keys(r).forEach(i=>{const n=t[i],a=r[i];Array.isArray(n)&&Array.isArray(a)?t[i]=n.concat(...a):e(n)&&e(a)?t[i]=Utility.mergeDeep(n,a):t[i]=a}),t),{})}static urlsPointToSameServerSideResource(t,e){if(!t||!e)return!1;const r=window.location.origin;try{const i=new URL(t,Utility.isValidUrl(t)?void 0:r),n=new URL(e,Utility.isValidUrl(e)?void 0:r),a=i.origin+i.pathname+i.search;return a===n.origin+n.pathname+n.search}catch(t){return!1}}static isValidUrl(t){try{return new URL(t),!0}catch(t){return!1}}}export default Utility;
\ No newline at end of file
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/window-manager.js b/typo3/sysext/backend/Resources/Public/JavaScript/window-manager.js
index 05a57bbf3159..109e4e761f1c 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/window-manager.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/window-manager.js
@@ -10,4 +10,4 @@
  *
  * The TYPO3 project - inspiring people to share!
  */
-class WindowManager{constructor(){this.windows={},this.open=(...n)=>this._localOpen.apply(this,n),this.globalOpen=(...n)=>this._localOpen.apply(this,n),this.localOpen=(n,o,e="newTYPO3frontendWindow",i="")=>this._localOpen(n,o,e,i)}_localOpen(n,o,e="newTYPO3frontendWindow",i=""){if(!n)return null;null===o?o=!window.opener:void 0===o&&(o=!0);const a=this.windows[e];if((a instanceof Window&&!a.closed?a.location.href:null)===n)return a.location.reload(),a;const t=window.open(n,e,i);return this.windows[e]=t,o&&t.focus(),t}}const windowManager=new WindowManager;top.TYPO3.WindowManager||(top.document===window.document?top.TYPO3.WindowManager=windowManager:top.TYPO3.WindowManager=new WindowManager);export default windowManager;
\ No newline at end of file
+import Utility from"@typo3/backend/utility.js";class WindowManager{constructor(){this.windows={},this.open=(...n)=>this._localOpen.apply(this,n),this.globalOpen=(...n)=>this._localOpen.apply(this,n),this.localOpen=(n,o,e="newTYPO3frontendWindow",i="")=>this._localOpen(n,o,e,i)}_localOpen(n,o,e="newTYPO3frontendWindow",i=""){if(!n)return null;null===o?o=!window.opener:void 0===o&&(o=!0);const t=this.windows[e]??window.open("",e,i),a="Window"===t.constructor.name&&!t.closed?t.location.href:null;if(Utility.urlsPointToSameServerSideResource(n,a))return t.location.replace(n),t.location.reload(),t;const w=window.open(n,e,i);return this.windows[e]=w,o&&w.focus(),w}}const windowManager=new WindowManager;top.TYPO3.WindowManager||(top.document===window.document?top.TYPO3.WindowManager=windowManager:top.TYPO3.WindowManager=new WindowManager);export default windowManager;
\ No newline at end of file
diff --git a/typo3/sysext/core/Tests/Acceptance/Application/Frontend/SitemapXmlCest.php b/typo3/sysext/core/Tests/Acceptance/Application/Frontend/SitemapXmlCest.php
index 552c2d133a7c..fe7e7e9ae5b1 100644
--- a/typo3/sysext/core/Tests/Acceptance/Application/Frontend/SitemapXmlCest.php
+++ b/typo3/sysext/core/Tests/Acceptance/Application/Frontend/SitemapXmlCest.php
@@ -48,12 +48,33 @@ class SitemapXmlCest
         });
 
         // Get current url
+        $url = $this->getCurrentURL($I);
+
+        // Add Sitemap parameter to URL
+        $I->amOnUrl($url . '?type=1533906435');
+    }
+
+    /**
+     * @param ApplicationTester $I
+     * @param int $attempt
+     * @return string
+     */
+    private function getCurrentURL(ApplicationTester $I, int $attempt = 1): string
+    {
         $url = $I->executeInSelenium(function (RemoteWebDriver $webdriver) {
             return $webdriver->getCurrentURL();
         });
 
-        // Add Sitemap parameter to URL
-        $I->amOnUrl($url . '?type=1533906435');
+        if ($attempt > 4) {
+            return $url ?? '';
+        }
+
+        if (!$url || str_contains($url, 'about:blank')) {
+            $I->wait(0.5);
+            $url = $this->getCurrentURL($I, $attempt + 1);
+        }
+
+        return $url;
     }
 
     /**
-- 
GitLab