Files
cms-backend/Resources/Public/JavaScript/modal.js
T

14 lines
15 KiB
JavaScript

/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
import{LitElement as S,html as r,nothing as B}from"lit";import{property as c,state as q,query as N,customElement as Y}from"lit/decorators.js";import{unsafeHTML as A}from"lit/directives/unsafe-html.js";import{classMap as D}from"lit/directives/class-map.js";import{ifDefined as $}from"lit/directives/if-defined.js";import{classesArrayToClassInfo as E}from"@typo3/core/lit-helper.js";import I from"@typo3/core/event/regular-event.js";import{SeverityEnum as y}from"@typo3/backend/enum/severity.js";import F from"@typo3/core/ajax/ajax-request.js";import R from"@typo3/backend/severity.js";import"@typo3/backend/element/icon-element.js";import"@typo3/backend/element/spinner-element.js";import U from"~labels/core.core";import j from"~labels/core.mod_web_list";var n=function(s,t,e,i){var a=arguments.length,l=a<3?t:i===null?i=Object.getOwnPropertyDescriptor(t,e):i,u;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")l=Reflect.decorate(s,t,e,i);else for(var m=s.length-1;m>=0;m--)(u=s[m])&&(l=(a<3?u(l):a>3?u(t,e,l):u(t,e))||l);return a>3&&l&&Object.defineProperty(t,e,l),l},T;(function(s){s.modal=".t3js-modal",s.header=".t3js-modal-header",s.close=".t3js-modal-close",s.body=".t3js-modal-body",s.footer=".t3js-modal-footer"})(T||(T={}));var h;(function(s){s.small="small",s.default="default",s.medium="medium",s.large="large",s.full="full",s.expand="expand"})(h||(h={}));var x;(function(s){s.small="small",s.default="default",s.medium="medium",s.large="large",s.full="full"})(x||(x={}));const O=s=>{if(typeof s=="string")return s in h;if(typeof s!="object"||s===null)return!1;const t=s;return Object.keys(s).length>0&&Object.keys(s).every(e=>e==="width"||e==="height")&&(t.width===void 0||t.width in x)&&(t.height===void 0||t.height in x)};var p;(function(s){s.center="center",s.top="top",s.end="end",s.bottom="bottom",s.start="start",s.sheet="sheet"})(p||(p={}));var v;(function(s){s.default="default",s.light="light",s.dark="dark"})(v||(v={}));var d;(function(s){s.default="default",s.template="template",s.ajax="ajax",s.iframe="iframe"})(d||(d={}));let K=0,o=class extends S{#t;constructor(){super(),this.modalTitle="",this.content="",this.type=d.default,this.severity=y.notice,this.variant=v.default,this.position=p.center,this.staticBackdrop=!1,this.hideCloseButton=!1,this.hideHeader=!1,this.additionalCssClasses=[],this.buttons=[],this.templateResultContent=null,this.activeButton=null,this.callback=null,this.ajaxCallback=null,this.userData={},this.#t=h.default,this.handleIframeKeydown=t=>{if(t.key==="Escape"){if(t.target instanceof t.view.window.HTMLInputElement&&t.target.type==="search"){t.target.value===""&&this.requestClose();return}if(t.defaultPrevented)return;this.requestClose()}},this.uniqueId=++K}get size(){return this.#t}set size(t){const e=O(t);if(this.#t=e?t:h.default,!e&&this.isConnected){const i=typeof this.#t=="string"?this.#t:JSON.stringify(this.#t);this.getAttribute("size")!==i&&this.setAttribute("size",i)}}setContent(t){this.templateResultContent=t}hideModal(){this.doHideModal()}async doHideModal(){if(this.trigger("typo3-modal-hide",!0).defaultPrevented)return;this.dialog.classList.add("modal-closing");const e=new Promise(a=>this.dialog.addEventListener("transitionend",a,{once:!0})),i=new Promise(a=>setTimeout(a,305));await Promise.race([e,i]),this.dialog.classList.remove("modal-closing"),this.dialog.close()}createRenderRoot(){return this}async showModal(){await new Promise(i=>requestAnimationFrame(i)),this.trigger("typo3-modal-show"),this.dialog.showModal();const t=new Promise(i=>this.dialog.addEventListener("transitionend",i,{once:!0})),e=new Promise(i=>setTimeout(i,305));await Promise.race([t,e]),this.trigger("typo3-modal-shown")}firstUpdated(){this.showModal(),this.callback&&this.callback(this)}updated(t){t.has("templateResultContent")&&this.dispatchEvent(new CustomEvent("modal-updated",{bubbles:!0}))}render(){const t=E(["modal","t3js-modal",`modal-type-${this.type}`,`modal-style-${this.variant}`,`modal-severity-${R.getCssClass(this.severity)}`,...this.getSizeClasses(),`modal-position-${this.position}`,...this.additionalCssClasses]);return r`<dialog class=${D(t)} aria-labelledby=${$(this.hideHeader?void 0:`t3-modal-header-${this.uniqueId}`)} aria-label=${$(this.hideHeader?this.modalTitle:void 0)} closedby=${this.hideCloseButton?"none":"closerequest"} @close=${this.handleDialogClose} @cancel=${this.handleDialogCancel} @click=${this.handleDialogClick}>${this.hideHeader?B:r`<div class="modal-header t3js-modal-header"><div class="modal-header-title t3js-modal-title" id=t3-modal-header-${this.uniqueId}>${this.modalTitle}</div>${this.hideCloseButton?B:r`<button class="modal-header-close t3js-modal-close" @click=${()=>this.hideModal()}><typo3-backend-icon identifier=actions-close size=small></typo3-backend-icon><span class=visually-hidden>${j.get("button.close")+" "+this.modalTitle}</span></button>`}</div>`}<div class="modal-body t3js-modal-body">${this.renderModalBody()}</div>${this.buttons.length===0?B:r`<div class="modal-footer t3js-modal-footer">${this.buttons.map(e=>this.renderModalButton(e))}</div>`}</dialog>`}getSizeClasses(){if(typeof this.size=="string")return[`modal-size-${this.size}`];const t=[];return this.size.width!==void 0&&t.push(`modal-width-${this.size.width}`),this.size.height!==void 0&&t.push(`modal-height-${this.size.height}`),t}handleDialogClose(){this.trigger("typo3-modal-hidden")}handleDialogCancel(t){this.hideCloseButton&&t.preventDefault(),t.defaultPrevented?this.shake():(t.preventDefault(),this.hideModal())}handleDialogClick(t){t.target===this.dialog&&(this.staticBackdrop?this.shake():this.requestClose())}_buttonClick(t,e){const i=t.currentTarget;e.action?(this.activeButton=e,e.action.execute(i).then(()=>this.hideModal())):e.trigger&&e.trigger(t,this),i.dispatchEvent(new CustomEvent("button.clicked",{bubbles:!0}))}renderAjaxBody(){return this.templateResultContent===null?(new F(this.content).get().then(async t=>{const e=await t.raw().text();this.templateResultContent=r`${A(e)}`,this.updateComplete.then(()=>{this.ajaxCallback&&this.ajaxCallback(this),this.dispatchEvent(new CustomEvent("modal-loaded"))})}).catch(async t=>{const e=await t.raw().text();e?this.templateResultContent=r`${A(e)}`:this.templateResultContent=r`<p><strong>Oops, received a ${t.response.status} response from </strong><span class=text-break>${this.content}</span>.</p>`}),r`<div class=modal-loading><typo3-backend-spinner size=large></typo3-backend-spinner></div>`):this.templateResultContent}renderModalBody(){if(this.type===d.iframe){const t=e=>{const i=e.currentTarget;i.contentDocument.title&&(this.modalTitle=i.contentDocument.title),i.contentDocument.addEventListener("keydown",this.handleIframeKeydown)};return r`<iframe src=${this.content} name=modal_frame class="modal-iframe t3js-modal-iframe" @load=${t}></iframe>`}return this.type===d.ajax?this.renderAjaxBody():this.type===d.template?this.templateResultContent:r`<p>${this.content}</p>`}renderModalButton(t){const i={btn:!0,[t.btnClass||"btn-default"]:!0,"t3js-active":t.active,disabled:this.activeButton&&this.activeButton!==t};return r`<button class=${D(i)} name=${$(t.name||void 0)} form=${$(t.form||void 0)} @click=${a=>this._buttonClick(a,t)}>${t.icon?r`<typo3-backend-icon identifier=${t.icon} size=small></typo3-backend-icon>`:B} ${t.text}</button>`}trigger(t,e=!1){const i=new CustomEvent(t,{bubbles:!0,composed:!0,cancelable:e});return this.dispatchEvent(i),i}requestClose(){"requestClose"in this.dialog?this.dialog.requestClose():this.hideCloseButton?this.hideModal():this.shake()}shake(){window.matchMedia("(prefers-reduced-motion: reduce)").matches||this.dialog.animate([{transform:"translateX(0px)"},{transform:"translateX(-2px)"},{transform:"translateX(0px)"},{transform:"translateX(2px)"},{transform:"translateX(0px)"}],150)}};n([c({type:String,reflect:!0})],o.prototype,"modalTitle",void 0),n([c({type:String,reflect:!0})],o.prototype,"content",void 0),n([c({type:String,reflect:!0})],o.prototype,"type",void 0),n([c({type:String,reflect:!0})],o.prototype,"severity",void 0),n([c({type:String,reflect:!0})],o.prototype,"variant",void 0),n([c({type:String,reflect:!0})],o.prototype,"position",void 0),n([c({type:Boolean})],o.prototype,"staticBackdrop",void 0),n([c({type:Boolean})],o.prototype,"hideCloseButton",void 0),n([c({type:Boolean})],o.prototype,"hideHeader",void 0),n([c({type:Array})],o.prototype,"additionalCssClasses",void 0),n([c({type:Array,attribute:!1})],o.prototype,"buttons",void 0),n([q()],o.prototype,"templateResultContent",void 0),n([q()],o.prototype,"activeButton",void 0),n([N("dialog",!0)],o.prototype,"dialog",void 0),n([c({reflect:!0,converter:{toAttribute:s=>typeof s=="string"?s:JSON.stringify(s),fromAttribute:s=>{if(s===null)return h.default;if(O(s))return s;try{return JSON.parse(s)}catch{return s}}}})],o.prototype,"size",null),o=n([Y("typo3-backend-modal")],o);class z{constructor(){this.sizes=h,this.styles=v,this.types=d,this.positions=p,this.currentModal=null,this.instances=[],this.defaultConfiguration={type:d.default,title:"Information",content:"No content provided, please check your <code>Modal</code> configuration.",severity:y.notice,buttons:[],style:v.default,size:h.default,position:p.center,additionalCssClasses:[],callback:null,ajaxCallback:null,staticBackdrop:!1,hideCloseButton:!1,hideHeader:!1},this.initializeMarkupTrigger(document)}static createModalResponseEventFromElement(t,e){return t.dataset.eventName?new CustomEvent(t.dataset.eventName,{bubbles:!0,detail:{result:e,payload:t.dataset.eventPayload||null}}):null}dismiss(){this.currentModal&&this.currentModal.hideModal()}confirm(t,e,i=y.warning,a=[],l){a.length===0&&a.push({text:j.get("button.cancel"),active:!0,btnClass:"btn-default",name:"cancel"},{text:j.get("button.ok"),btnClass:"btn-"+R.getCssClass(i),name:"ok"});const u=this.advanced({title:t,content:e,severity:i,buttons:a,additionalCssClasses:l});return u.addEventListener("button.clicked",m=>{const b=m.target;b.getAttribute("name")==="cancel"?b.dispatchEvent(new CustomEvent("confirm.button.cancel",{bubbles:!0})):b.getAttribute("name")==="ok"&&b.dispatchEvent(new CustomEvent("confirm.button.ok",{bubbles:!0}))}),u}loadUrl(t,e=y.info,i,a,l){return this.advanced({type:d.ajax,title:t,severity:e,buttons:i,ajaxCallback:l,content:a})}show(t,e,i=y.info,a,l){return this.advanced({type:d.default,title:t,content:e,severity:i,buttons:a,additionalCssClasses:l})}advanced(t){return t.type=typeof t.type=="string"&&t.type in d?t.type:this.defaultConfiguration.type,t.title=typeof t.title=="string"?t.title:this.defaultConfiguration.title,t.content=typeof t.content=="string"||typeof t.content=="object"?t.content:this.defaultConfiguration.content,t.severity=typeof t.severity<"u"?t.severity:this.defaultConfiguration.severity,t.buttons=t.buttons||this.defaultConfiguration.buttons,t.size=O(t.size)?t.size:this.defaultConfiguration.size,t.style=typeof t.style=="string"&&t.style in v?t.style:this.defaultConfiguration.style,t.position=typeof t.position=="string"&&t.position in p?t.position:this.defaultConfiguration.position,t.additionalCssClasses=t.additionalCssClasses||this.defaultConfiguration.additionalCssClasses,t.callback=typeof t.callback=="function"?t.callback:this.defaultConfiguration.callback,t.ajaxCallback=typeof t.ajaxCallback=="function"?t.ajaxCallback:this.defaultConfiguration.ajaxCallback,t.hideCloseButton=t.hideCloseButton||this.defaultConfiguration.hideCloseButton,t.staticBackdrop=t.staticBackdrop||this.defaultConfiguration.staticBackdrop,t.hideHeader=t.hideHeader||this.defaultConfiguration.hideHeader,this.generate(t)}setButtons(t){return this.currentModal.buttons=t,this.currentModal}initializeMarkupTrigger(t){const e=(i,a)=>{i.preventDefault(),"bsContent"in a.dataset&&!("content"in a.dataset)&&console.error("TYPO3 v14 modal trigger dropped support for the legacy `data-bs-content` attribute. Use `data-content` instead. Affected element:",a);const l=a.dataset.content||U.get("message.confirmation");let u=y.notice;if(a.dataset.severity in y){const f=a.dataset.severity;u=y[f]}let m=h.default;if(a.dataset.size in h){const f=a.dataset.size;m=h[f]}let b=p.center;if(a.dataset.position in p){const f=a.dataset.position;b=p[f]}const H=a.dataset.hideHeader!==void 0,L=a.dataset.staticBackdrop!==void 0;let C=a.dataset.url||null;if(C!==null){const f=C.includes("?")?"&":"?",w=new URLSearchParams(a.dataset).toString();C=C+f+w}this.advanced({type:C!==null?d.ajax:d.default,title:a.dataset.title||"Alert",content:C!==null?C:l,size:m,severity:u,position:b,hideHeader:H,staticBackdrop:L,buttons:[{text:a.dataset.buttonCloseText||j.get("button.close"),active:!0,btnClass:"btn-default",trigger:(f,w)=>{w.hideModal();const M=z.createModalResponseEventFromElement(a,!1);M!==null&&a.dispatchEvent(M)}},{text:a.dataset.buttonOkText||j.get("button.ok"),btnClass:"btn-"+R.getCssClass(u),trigger:(f,w)=>{w.hideModal();const M=z.createModalResponseEventFromElement(a,!0);M!==null&&a.dispatchEvent(M);const g=a.dataset.uri||a.dataset.href||a.getAttribute("href");if(g&&g!=="#"&&(a.ownerDocument.location.href=g),a.getAttribute("type")==="submit"&&(a.tagName==="BUTTON"||a.tagName==="INPUT")){const P=a;P.form?.requestSubmit(P)}a.dataset.targetForm&&a.ownerDocument.querySelector("form#"+a.dataset.targetForm)?.submit()}}]})};new I("click",e).delegateTo(t,".t3js-modal-trigger")}generate(t){const e=document.createElement("typo3-backend-modal");return e.type=t.type,typeof t.content=="string"?e.content=t.content:t.type===d.default&&(e.type=d.template,e.templateResultContent=t.content),e.severity=t.severity,e.variant=t.style,e.size=t.size,e.position=t.position,e.modalTitle=t.title,e.additionalCssClasses=t.additionalCssClasses,e.buttons=t.buttons,e.hideCloseButton=t.hideCloseButton,e.staticBackdrop=t.staticBackdrop,e.hideHeader=t.hideHeader,t.callback&&(e.callback=t.callback),t.ajaxCallback&&(e.ajaxCallback=t.ajaxCallback),e.addEventListener("typo3-modal-shown",()=>{const i=e.querySelector(`${T.footer} .t3js-active`);i!==null&&i.focus()}),e.addEventListener("typo3-modal-hide",()=>{if(this.instances.length>0){const i=this.instances.length-1;this.instances.splice(i,1),this.currentModal=this.instances[i-1]}}),e.addEventListener("typo3-modal-hidden",()=>{e.remove()}),e.addEventListener("typo3-modal-show",()=>{this.currentModal=e,this.instances.push(e)}),document.body.appendChild(e),e}}let k=null;try{parent&&parent.window.TYPO3&&parent.window.TYPO3.Modal?(parent.window.TYPO3.Modal.initializeMarkupTrigger(document),k=parent.window.TYPO3.Modal):top&&top.TYPO3.Modal&&(top.TYPO3.Modal.initializeMarkupTrigger(document),k=top.TYPO3.Modal)}catch{}k||(k=new z,typeof TYPO3<"u"&&(TYPO3.Modal=k));var X=k;export{T as Identifiers,o as ModalElement,p as Positions,x as Size,h as Sizes,v as Styles,d as Types,X as default};