14 lines
8.8 KiB
JavaScript
14 lines
8.8 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{DateTime as p}from"luxon";import y from"@typo3/backend/hashing/md5.js";import g from"@typo3/backend/modal.js";import w from"@typo3/backend/severity.js";import b from"@typo3/backend/utility.js";import k from"@typo3/core/event/regular-event.js";import E from"@typo3/core/event/throttle-event.js";import x from"@typo3/backend/utility/dom-helper.js";import{selector as d}from"@typo3/core/literals.js";import N from"@typo3/backend/form/submit-interceptor.js";import{FormEngineReview as T}from"@typo3/backend/form-engine-review.js";import v from"~labels/core.core";import C from"~labels/core.mod_web_list";let o,S=!1;const h=new Map;class a{static{this.rulesSelector="[data-formengine-validation-rules]"}static{this.inputSelector="[data-formengine-input-params]"}static{this.markerSelector=".t3js-formengine-validation-marker"}static{this.labelSelector=".t3js-formengine-label"}static{this.errorClass="has-error"}static{this.validationErrorClass="has-validation-error"}static{this.passwordDummy="********"}static initialize(t){o=t,o.formElement.querySelectorAll("."+a.errorClass).forEach(e=>e.classList.remove(a.errorClass)),a.initializeInputFields(),new T(o.formElement),new k("change",(e,s)=>{a.validateField(s),o.markFieldAsChanged(s)}).delegateTo(o.formElement,a.rulesSelector),new E("input",(e,s)=>{a.validateField(s)},100).delegateTo(o.formElement,a.rulesSelector),a.registerSubmitCallback(),a.validate()}static initializeInputFields(){o.formElement.querySelectorAll(a.inputSelector).forEach(t=>{if("formengineInputInitialized"in t.dataset)return;const s=JSON.parse(t.dataset.formengineInputParams).field,r=o.formElement.querySelector(d`[name="${s}"]`);r.dataset.config=t.dataset.formengineInputParams,a.initializeInputField(s)})}static initializeInputField(t){const e=o.formElement.querySelector(d`[name="${t}"]`),s=o.formElement.querySelector(d`[data-formengine-input-name="${t}"]`);if(e.dataset.config!==void 0){const r=JSON.parse(e.dataset.config),i=a.formatByEvals(r,e.value);i.length&&(s.value=i)}new k("change",()=>{a.updateInputField(s.dataset.formengineInputName)}).bindTo(s),s.dataset.formengineInputInitialized="true",s.dispatchEvent(new Event("formengine:input:initialized"))}static registerCustomEvaluation(t,e){h.has(t)||h.set(t,e)}static formatByEvals(t,e){if(t.evalList!==void 0){const s=b.trimExplode(",",t.evalList);for(const r of s)e=a.formatValue(r,e)}return e}static formatValue(t,e){switch(t){case"date":case"datetime":case"time":case"timesec":case"datetimesec":if(e==="")return"";const s=p.fromISO(String(e));if(!s.isValid)throw new Error("Invalid ISO8601 DateTime string: "+e);return s.toISO({suppressMilliseconds:!0,includeOffset:!1});case"password":return e?a.passwordDummy:"";default:return e.toString()}}static updateInputField(t){const e=o.formElement.querySelector(d`[name="${t}"]`),s=o.formElement.querySelector(d`[data-formengine-input-name="${t}"]`);if(e.dataset.config!==void 0){const r=JSON.parse(e.dataset.config),i=a.processByEvals(r,s.value),u=a.formatByEvals(r,i);e.value!==i&&(e.disabled&&e.dataset.enableOnModification&&(e.disabled=!1),e.value=i,e.dispatchEvent(new Event("change"))),s.value!==u&&(s.value=u)}}static validateField(t){if(t.dataset.formengineValidationRules===void 0)return;let e=t.value||"";const s=JSON.parse(t.dataset.formengineValidationRules);let r=!1,i=0,u,n,c;Array.isArray(e)||(e=e.trimStart());for(const l of s){if(r)break;switch(l.type){case"required":e===""&&(r=!0,t.classList.add(a.errorClass),t.closest(a.markerSelector)?.querySelector(a.labelSelector)?.classList.add(a.errorClass));break;case"range":if(e!==""){if((l.minItems||l.maxItems)&&(u=o.formElement.querySelector(d`[name="${t.dataset.relatedfieldname}"]`),u!==null?i=b.trimExplode(",",u.value).length:i=parseInt(t.value,10),l.minItems!==void 0&&(n=l.minItems*1,!isNaN(n)&&i<n&&(r=!0)),l.maxItems!==void 0&&(c=l.maxItems*1,!isNaN(c)&&i>c&&(r=!0))),l.lower!==void 0)if(t.dataset.inputType==="datetimepicker"){const m=p.fromISO(e,{zone:"utc"}),I=p.fromISO(l.lower,{zone:"utc"});(!m.isValid||m<I.minus(I.second*1e3))&&(r=!0)}else{const m=l.lower*1;!isNaN(m)&&parseInt(e,10)<m&&(r=!0)}if(l.upper!==void 0)if(t.dataset.inputType==="datetimepicker"){const m=p.fromISO(e,{zone:"utc"}),I=p.fromISO(l.upper,{zone:"utc"});(!m.isValid||m>I.plus((59-I.second)*1e3))&&(r=!0)}else{const m=l.upper*1;!isNaN(m)&&parseInt(e,10)>m&&(r=!0)}}break;case"select":case"category":(l.minItems||l.maxItems)&&(u=o.formElement.querySelector(d`[name="${t.dataset.relatedfieldname}"]`),u!==null?i=b.trimExplode(",",u.value).length:t instanceof HTMLSelectElement?i=t.querySelectorAll("option:checked").length:i=t.querySelectorAll("input[value]:checked").length,l.minItems!==void 0&&(n=l.minItems*1,!isNaN(n)&&i<n&&(r=!0)),l.maxItems!==void 0&&(c=l.maxItems*1,!isNaN(c)&&i>c&&(r=!0)));break;case"group":case"folder":(l.minItems||l.maxItems)&&(i=b.trimExplode(",",t.value).length,l.minItems!==void 0&&(n=l.minItems*1,!isNaN(n)&&i<n&&(r=!0)),l.maxItems!==void 0&&(c=l.maxItems*1,!isNaN(c)&&i>c&&(r=!0)));break;case"inline":(l.minItems||l.maxItems)&&(i=b.trimExplode(",",t.value).length,l.minItems!==void 0&&(n=l.minItems*1,!isNaN(n)&&i<n&&(r=!0)),l.maxItems!==void 0&&(c=l.maxItems*1,!isNaN(c)&&i>c&&(r=!0)));break;case"min":(t instanceof HTMLInputElement||t instanceof HTMLTextAreaElement)&&t.value.length>0&&t.value.length<t.minLength&&(r=!0);break;case"null":break;default:break}}const f=!r;t.classList.toggle(a.errorClass,!f),t.setAttribute("aria-invalid",r.toString()),t.closest(a.markerSelector)?.querySelector(a.labelSelector)?.classList.toggle(a.errorClass,!f),a.markParentTab(t,f),o.formElement.dispatchEvent(new CustomEvent("t3-formengine-postfieldvalidation",{detail:{field:t,isValid:f},cancelable:!1,bubbles:!0}))}static processByEvals(t,e){if(t.evalList!==void 0){const s=b.trimExplode(",",t.evalList);for(const r of s)e=a.processValue(r,e,t)}return e}static processValue(t,e,s){let r="",i="",u=0,n=e;switch(t){case"alpha":case"num":case"alphanum":case"alphanum_x":for(r="",u=0;u<e.length;u++){const c=e.substr(u,1);let f=c==="_"||c==="-",l=c>="a"&&c<="z"||c>="A"&&c<="Z",m=c>="0"&&c<="9";switch(t){case"alphanum":f=!1;break;case"alpha":m=!1,f=!1;break;case"num":l=!1,f=!1;break;default:break}(l||m||f)&&(r+=c)}r!==e&&(n=r);break;case"is_in":if(s.is_in){i=""+e,s.is_in=s.is_in.replace(/[-[\]{}()*+?.,\\^$|#\s]/g,"\\$&");const c=new RegExp("[^"+s.is_in+"]+","g");r=i.replace(c,"")}else r=i;n=r;break;case"nospace":n=(""+e).replace(/ /g,"");break;case"md5":e!==""&&(n=y.hash(e));break;case"upper":n=e.toUpperCase();break;case"lower":n=e.toLowerCase();break;case"integer":e!==""&&(n=a.parseInt(e).toString());break;case"decimal":e!==""&&(n=a.parseDouble(e));break;case"trim":n=String(e).trim();break;case"time":case"timesec":e!==""&&(n=p.fromISO(e).set({year:1970,month:1,day:1}).toISO({suppressMilliseconds:!0,includeOffset:!1}));break;case"null":break;case"password":break;default:h.has(t)?n=h.get(t).call(null,e):typeof TBE_EDITOR=="object"&&TBE_EDITOR.customEvalFunctions!==void 0&&typeof TBE_EDITOR.customEvalFunctions[t]=="function"&&(n=TBE_EDITOR.customEvalFunctions[t](e))}return n}static validate(t){(typeof t>"u"||t instanceof Document)&&o.formElement.querySelectorAll(a.markerSelector+', [role="tablist"] > .nav-item').forEach(s=>{s.classList.remove(a.validationErrorClass)});const e=t||document;for(const s of e.querySelectorAll(a.rulesSelector))s.closest(".t3js-flex-section-deleted, .t3js-inline-record-deleted, .t3js-file-reference-deleted")===null&&a.validateField(s)}static parseInt(t){const e=""+t;if(!t)return 0;const s=parseInt(e,10);return isNaN(s)?0:s}static parseDouble(t,e=2){let s=""+t;s=s.replace(/[^0-9,.-]/g,"");const r=s.startsWith("-");s=s.replace(/-/g,""),s=s.replace(/,/g,"."),s.indexOf(".")===-1&&(s+=".0");const i=s.split("."),u=i.pop();let n=+(i.join("")+"."+u);return r&&(n*=-1),s=n.toFixed(e),s}static markParentTab(t,e){x.parents(t,".tab-pane").forEach(r=>{e&&(e=r.querySelector(".has-error")===null);const i=r.id;o.formElement.querySelector(d`[data-typo3-tab="${"#"+i}"]`).closest(".nav-item").classList.toggle(a.validationErrorClass,!e)})}static suspend(){S=!0}static resume(){S=!1}static isValid(){return document.querySelector("."+a.errorClass)===null}static showErrorModal(){const t=g.confirm(v.get("labels.fieldsMissing.title"),v.get("labels.fieldsMissing"),w.error,[{text:C.get("button.ok"),active:!0,btnClass:"btn-default",name:"ok"}]);t.addEventListener("button.clicked",()=>t.hideModal())}static registerSubmitCallback(){new N(o.formElement).addPreSubmitCallback(()=>S||a.isValid()?!0:(a.showErrorModal(),!1))}}export{a as default};
|