This commit is contained in:
Nivanka Fonseka 2024-03-05 05:31:22 +13:00 committed by GitHub
commit afacbebf56
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 622 additions and 788 deletions

5
.gitignore vendored
View File

@ -1,3 +1,8 @@
.DS_Store
.sass-cache/
node_modules/
userforms-cms.js.map
userforms.js.map
userforms-cms.css.map
userforms.css.map

View File

@ -1 +1 @@
!function(t){function e(n){if(r[n])return r[n].exports;var i=r[n]={i:n,l:!1,exports:{}};return t[n].call(i.exports,i,i.exports,e),i.l=!0,i.exports}var r={};e.m=t,e.c=r,e.i=function(t){return t},e.d=function(t,r,n){e.o(t,r)||Object.defineProperty(t,r,{configurable:!1,enumerable:!0,get:n})},e.n=function(t){var r=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(r,"a",r),r},e.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},e.p="",e(e.s="./client/src/bundles/bundle.js")}({"./client/src/bundles/UserForms.js":function(t,e,r){"use strict";function n(t){return t&&t.__esModule?t:{default:t}}var i=r(1),s=n(i),o=r(0),a=n(o);(0,s.default)(document).ready(function(t){function e(e){return this.$el=e instanceof t?e:t(e),this.$el.find("h4").text(a.default._t("UserForms.ERROR_CONTAINER_HEADER","Please correct the following errors and try again:")),this}function r(r){var n=this;this.$el=r instanceof t?r:t(r);var i=this.$el.closest(".userform").data("inst");return this.$elButton=t(".step-button-wrapper[data-for='"+this.$el.prop("id")+"']"),this.viewed=!1,this.valid=!1,this.id=null,this.hide(),u.DISPLAY_ERROR_MESSAGES_AT_TOP&&(this.errorContainer=new e(this.$el.find(".error-container")),i.$el.on("userform.form.error",function(e,r){n.$el.is(":visible")&&t.each(r.errorList,function(e,r){n.errorContainer.updateErrorMessage(t(r.element),r.message)})}),i.$el.on("userform.form.valid",function(t,e){n.errorContainer.removeErrorMessage(e)})),this.$elButton.on("userform.field.hide userform.field.show",function(){i.$el.trigger("userform.form.conditionalstep")}),this}function n(e){var r=this;this.$el=e instanceof t?e:t(e),this.$buttons=this.$el.find(".step-button-jump"),this.$jsAlign=this.$el.find(".js-align");var n=this.$el.closest(".userform").data("inst");return this.$buttons.each(function(e,n){t(n).on("click",function(e){e.preventDefault();var n=parseInt(t(e.target).data("step"),10);r.$el.trigger("userform.progress.changestep",n)})}),n.$el.on("userform.form.changestep",function(t,e){r.update(e)}),n.$el.on("userform.form.conditionalstep",function(){var e=r.$buttons.filter(":visible");e.each(function(e,r){t(r).text(e+1)}),r.$el.find(".progress-bar").attr("aria-valuemax",e.length),r.$el.find(".total-step-number").text(e.length)}),this.$jsAlign.each(function(e,n){var i=t(n),s=100/(r.$jsAlign.length-1)*e,o=s+"%",a=i.innerWidth()/2*-1;i.css({left:o,marginLeft:a}),e===r.$jsAlign.length-1?i.css({marginLeft:2*a}):0===e&&i.css({marginLeft:0})}),this}function i(e){var r=this;this.$el=e instanceof t?e:t(e);var n=this.$el.closest(".userform");this.userformInstance=n.data("inst"),this.$prevButton=this.$el.find(".step-button-prev"),this.$nextButton=this.$el.find(".step-button-next"),this.$prevButton.parent().attr("aria-hidden",!1).show(),this.$nextButton.parent().attr("aria-hidden",!1).show();var i=function(){var e=n.offset();t("html, body").animate({scrollTop:e.top},"slow")};return this.$prevButton.on("click",function(t){t.preventDefault(),i(),r.$el.trigger("userform.action.prev")}),this.$nextButton.on("click",function(t){t.preventDefault(),i(),r.$el.trigger("userform.action.next")}),this.userformInstance.$el.on("userform.form.changestep userform.form.conditionalstep",function(){r.update()}),this}function s(r){var n=this;return this.$el=r instanceof t?r:t(r),this.steps=[],this.errorContainer=new e(this.$el.children(".error-container")),this.$el.on("userform.action.prev",function(){n.prevStep()}),this.$el.on("userform.action.next",function(){n.nextStep()}),this.$el.find(".userform-progress").on("userform.progress.changestep",function(t,e){n.jumpToStep(e-1)}),this.$el.on("userform.form.valid",function(t,e){n.errorContainer.removeStepLink(e)}),this.$el.validate(this.validationOptions),this.$el.find(".optionset.requiredField input").each(function(e,r){t(r).rules("add",{required:!0})}),this}function o(o,d){var f=this,c=t(d);if(0!==c.length){u.ENABLE_LIVE_VALIDATION=void 0!==c.data("livevalidation"),u.DISPLAY_ERROR_MESSAGES_AT_TOP=void 0!==c.data("toperrors"),!1===u.ENABLE_LIVE_VALIDATION&&t.extend(s.prototype.validationOptions,{onfocusout:!1}),u.DISPLAY_ERROR_MESSAGES_AT_TOP&&t.extend(s.prototype.validationOptions,{invalidHandler:function(t,e){c.trigger("userform.form.error",[e])},onfocusout:!1}),c.find(".userform-progress, .step-navigation").attr("aria-hidden",!1).show(),t.extend(r.prototype,l),t.extend(e.prototype,l);var h=new s(c);c.data("inst",h),u.HIDE_FIELD_LABELS&&c.find("label.left").each(function(){var e=t(f);t('[name="'+e.attr("for")+'"]').attr("placeholder",e.text()),e.remove()}),h.$el.find(".form-step").each(function(t,e){var n=new r(e);h.addStep(n)}),h.setCurrentStep(h.steps[0]);var p=c.find(".userform-progress");p.length&&new n(p).update(0);var m=c.find(".step-navigation");m.length&&new i(m).update(),t(document).on("click","input.text[data-showcalendar]",function(){var e=t(f);e.ssDatepicker(),e.data("datepicker")&&e.datepicker("show")}),setInterval(function(){t.ajax({url:"UserDefinedFormController/ping"})},18e4),void 0!==c.areYouSure&&c.areYouSure({message:a.default._t("UserForms.LEAVE_CONFIRMATION","You have unsaved changes!")})}}var u={},l={show:function(){this.$el.attr("aria-hidden",!1).show()},hide:function(){this.$el.attr("aria-hidden",!0).hide()}};e.prototype.hasErrors=function(){return this.$el.find(".error-list").children().length>0},e.prototype.removeErrorMessage=function(t){this.$el.find("#"+t+"-top-error").remove(),this.hasErrors()||this.hide()},e.prototype.addStepLink=function(e){var r=this.$el.closest(".userform").data("inst"),n=e.$el.attr("id")+"-error-link",i=this.$el.find("#"+n),s=e.$el.attr("id"),o=e.$el.data("title");i.length||(i=t('<li id="'+n+'"><a href="#'+s+'">'+o+"</a></li>"),i.on("click",function(t){t.preventDefault(),r.jumpToStep(e.id)}),this.$el.find(".error-list").append(i))},e.prototype.removeStepLink=function(e){var r=t("#"+e).closest(".form-step").attr("id");this.$el.find("#"+r+"-error-link").remove(),this.$el.find(".error-list").is(":empty")&&this.hide()},e.prototype.updateErrorMessage=function(e,r){var n=this,i=e.attr("id"),s="#"+i,o=i+"-top-error",a=t("#"+o),u=e.attr("aria-describedby");if(!r)return void a.addClass("fixed");a.removeClass("fixed"),this.show(),1===a.length?a.show().find("a").html(r):(e.closest(".field[id]").each(function(){var e=t(n).attr("id");e&&(s="#"+e)}),a=t("<li><a></a></li>"),a.attr("id",o).find("a").attr("href",location.pathname+location.search+s).html(r),this.$el.find("ul").append(a),u?u.match(new RegExp("\\b"+o+"\\b"))||(u+=" "+o):u=o,e.attr("aria-describedby",u))},r.prototype.conditionallyHidden=function(){return!this.$elButton.find("button").is(":visible")},n.prototype.update=function(e){var r=t(this.$el.parent(".userform").find(".form-step")[e]),n=0,i=e/(this.$buttons.length-1)*100;this.$buttons.each(function(r,i){return!(r>e||(t(i).is(":visible")&&(n+=1),0))}),this.$el.find(".current-step-number").each(function(e,r){t(r).text(n)}),this.$el.find("[aria-valuenow]").each(function(e,r){t(r).attr("aria-valuenow",n)}),this.$buttons.each(function(e,r){var i=t(r),s=i.parent();if(parseInt(i.data("step"),10)===n&&i.is(":visible"))return s.addClass("current viewed"),void i.removeAttr("disabled");s.removeClass("current")}),this.$el.siblings(".progress-title").text(r.data("title")),i=i?i+"%":"",this.$el.find(".progress-bar").width(i)},i.prototype.update=function(){var t=this.userformInstance.steps.length,e=this.userformInstance.currentStep?this.userformInstance.currentStep.id:0,r=null,n=null;for(this.$el.find(".step-button-prev")[0===e?"hide":"show"](),r=t-1;r>=0;r--)if(n=this.userformInstance.steps[r],!n.conditionallyHidden()){this.$el.find(".step-button-next")[e>=r?"hide":"show"](),this.$el.find(".btn-toolbar")[e>=r?"show":"hide"]();break}},s.prototype.validationOptions={ignore:":hidden,ul",errorClass:"error",errorElement:"span",errorPlacement:function(t,e){t.addClass("message"),e.is(":radio")||e.parents(".checkboxset").length>0?t.appendTo(e.closest(".middleColumn, .field")):e.parents(".checkbox").length>0?t.appendTo(e.closest(".field")):t.insertAfter(e)},invalidHandler:function(t,e){setTimeout(function(){e.currentElements.filter(".error").first().focus()},0)},submitHandler:function(e){var r=!0,n=t(e).closest(".userform").data("inst");if(n.currentStep&&(n.currentStep.valid=t(e).valid()),t.each(n.steps,function(t,e){e.valid||e.conditionallyHidden()||(r=!1,n.errorContainer.addStepLink(e))}),r){var i=t(e).find(".field.requiredField.hide input");i.length>0&&i.removeAttr("required aria-required data-rule-required").valid(),t(e).removeClass("dirty"),e.submit(),n.$el.trigger("userform.form.submit")}else n.errorContainer.show()},success:function(e){var r=t(e).closest(".userform").data("inst"),n=t(e).attr("id"),i=n.substr(0,n.indexOf("-error")).replace(/[\\[\\]]/,"");e.remove(),r.$el.trigger("userform.form.valid",[i])}},s.prototype.addStep=function(t){t instanceof r&&(t.id=this.steps.length,this.steps.push(t))},s.prototype.setCurrentStep=function(t){t instanceof r&&(this.currentStep=t,this.currentStep.show(),this.currentStep.viewed=!0,this.currentStep.$el.addClass("viewed"))},s.prototype.jumpToStep=function(t,e){var r=this.steps[t],n=!1,i=void 0===e||e;if(void 0!==r){if(r.conditionallyHidden())return void(i?this.jumpToStep(t+1,e):this.jumpToStep(t-1,e));n=this.$el.valid(),this.currentStep.valid=n,!1===n&&!1===r.viewed||(this.currentStep.hide(),this.setCurrentStep(r),this.$el.trigger("userform.form.changestep",[r.id]))}},s.prototype.nextStep=function(){this.jumpToStep(this.steps.indexOf(this.currentStep)+1,!0)},s.prototype.prevStep=function(){this.jumpToStep(this.steps.indexOf(this.currentStep)-1,!1)},t(".userform").each(o)})},"./client/src/bundles/bundle.js":function(t,e,r){"use strict";r("./client/src/bundles/UserForms.js")},0:function(t,e){t.exports=i18n},1:function(t,e){t.exports=jQuery}});
!function(e){function t(n){if(r[n])return r[n].exports;var i=r[n]={i:n,l:!1,exports:{}};return e[n].call(i.exports,i,i.exports,t),i.l=!0,i.exports}var r={};t.m=e,t.c=r,t.i=function(e){return e},t.d=function(e,r,n){t.o(e,r)||Object.defineProperty(e,r,{configurable:!1,enumerable:!0,get:n})},t.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(r,"a",r),r},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="",t(t.s="./client/src/bundles/bundle.js")}({"./client/src/bundles/UserForms.js":function(e,t,r){"use strict";function n(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function i(e){return"none"!==e.style.display&&"hidden"!==e.style.visibility&&!e.classList.contains("hide")}var u=function(){function e(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}return function(t,r,n){return r&&e(t.prototype,r),n&&e(t,n),t}}(),s=r("./node_modules/async-validator/dist-web/index.js"),o=function(e){return e&&e.__esModule?e:{default:e}}(s),a=function(){function e(t,r){n(this,e),this.dom=t,this.userForm=r,this.progressTitle=this.userForm.dom.querySelector(".progress-title"),this.buttons=this.dom.querySelectorAll(".step-button-jump"),this.currentStepNumber=this.dom.querySelector(".current-step-number"),this.init()}return u(e,[{key:"init",value:function(){var e=this;this.dom.style.display="initial",this.buttons.forEach(function(t){t.addEventListener("click",function(r){r.preventDefault();var n=parseInt(t.getAttribute("data-step"),10);return e.userForm.jumpToStep(n-1),!1})}),this.userForm.dom.addEventListener("userform.form.changestep",function(t){e.update(t.detail.stepId)}),this.update(0)}},{key:"update",value:function(e){var t=this.userForm.getCurrentStepID()+1,r=this.userForm.getStep(e),n=r.step,u=e/(this.buttons.length-1)*100;this.currentStepNumber.innerText=t,this.dom.querySelectorAll("[aria-valuenow]").forEach(function(e){e.setAttribute("aria-valuenow",t)}),this.buttons.forEach(function(e){var r=e,n=r.parentNode;parseInt(r.getAttribute("data-step"),10)===t&&i(r)&&(n.classList.add("current"),n.classList.add("viewed"),r.disabled=!1),n.classList.remove("current")}),this.progressTitle.innerText=n.getAttribute("data-title"),u=u?u+"%":"",this.dom.querySelector(".progress-bar").style.width=u}}]),e}(),l=function(){function e(t,r){n(this,e),this.step=t,this.userForm=r,this.viewed=!1,this.buttonHolder=null,this.id=0,this.init()}return u(e,[{key:"init",value:function(){var e=this,t=this.getHTMLId();this.buttonHolder=document.querySelector(".step-button-wrapper[data-for='"+t+"']"),this.buttonHolder&&["userform.field.hide","userform.field.show"].forEach(function(t){e.buttonHolder.addEventListener(t,function(){e.userForm.dom.trigger("userform.form.conditionalstep")})})}},{key:"setId",value:function(e){this.id=e}},{key:"getHTMLId",value:function(){return this.step.getAttribute("id")}},{key:"show",value:function(){this.step.setAttribute("aria-hidden",!1),this.step.classList.remove("hide"),this.step.classList.add("viewed"),this.viewed=!0}},{key:"hide",value:function(){this.step.setAttribute("aria-hidden",!0),this.step.classList.add("hide")}},{key:"conditionallyHidden",value:function(){var e=this.buttonHolder.querySelector("button");return!("none"!==e.style.display&&"hidden"!==e.visibility&&!e.classList.contains("hide"))}},{key:"getValidatorType",value:function(e){return"email"===e.getAttribute("type")?"email":"date"===e.getAttribute("type")?"date":"file"===e.getAttribute("type")?"object":e.classList.contains("numeric")||"numeric"===e.getAttribute("type")?"number":"string"}},{key:"getValidatorMessage",value:function(e){return e.getAttribute("data-msg-required")?e.getAttribute("data-msg-required"):this.getFieldLabel(e)+" is required"}},{key:"getHolderForField",value:function(e){return window.closest(e,".field")}},{key:"getFieldLabel",value:function(e){var t=this.getHolderForField(e);if(t){var r=t.querySelector("label.left, legend.left");if(r)return r.innerText}return e.getAttribute("name")}},{key:"isInputNumeric",value:function(e){return"number"===this.getValidatorType(e)}},{key:"isInputFile",value:function(e){return"file"===e.getAttribute("type")}},{key:"getInputByName",value:function(e){return this.step.querySelector('input[name="'+e+'"]')}},{key:"getValidationsDescriptors",value:function(e){var t=this,r={};return this.step.querySelectorAll("input, textarea, select").forEach(function(n){if(i(n)&&(!e||e&&n.classList.contains("focused"))){var u=t.getFieldLabel(n),s=t.getHolderForField(n);r[n.getAttribute("name")]={title:u,type:t.getValidatorType(n),required:s.classList.contains("requiredField"),message:t.getValidatorMessage(n)};var o=n.getAttribute("data-rule-min"),a=n.getAttribute("data-rule-max");null===o&&null===a||(r[n.getAttribute("name")].asyncValidator=function(e,t){return new Promise(function(e,r){null!==o&&t<o?r(u+" cannot be less than "+o):null!==a&&t>a?r(u+" cannot be greater than "+a):e()})});var l=n.getAttribute("data-rule-minlength"),c=n.getAttribute("data-rule-maxlength");null===l&&null===c||(r[n.getAttribute("name")].asyncValidator=function(e,t){return new Promise(function(e,r){null!==l&&t.length<l?r(u+" cannot be shorter than "+l):null!==c&&t.length>c?r(u+" cannot be longer than "+c):e()})})}}),r}},{key:"validate",value:function(e){var t=this,r=this.getValidationsDescriptors(e);if(Object.keys(r).length){var n=new o.default(r),i=new FormData(this.userForm.dom),u={};return i.forEach(function(e,r){var n=e,i=t.getInputByName(r);n&&i&&t.isInputNumeric(i)&&(n=parseFloat(n)),u[r]=n}),this.step.querySelectorAll('input[type="radio"],input[type="checkbox"]').forEach(function(e){var t=e.getAttribute("name");void 0===u[t]&&(u[t]="")}),new Promise(function(e,r){n.validate(u,function(n){n&&n.length?(t.displayErrorMessages(n),r(n)):(t.displayErrorMessages([]),e())})})}return new Promise(function(e){e()})}},{key:"enableLiveValidation",value:function(){var e=this;this.step.querySelectorAll("input, textarea, select").forEach(function(t){t.addEventListener("focusin",function(){t.classList.add("focused")}),t.addEventListener("change",function(){t.classList.add("dirty")}),t.addEventListener("focusout",function(){e.validate(!0).then(function(){}).catch(function(){})})})}},{key:"displayErrorMessages",value:function(e){var t=this,r=[];e.forEach(function(e){var n=t.userForm.dom.querySelector("#"+e.field);if(n){var i=n.querySelector("span.error");i||(i=document.createElement("span"),i.classList.add("error"),i.setAttribute("data-id",e.field)),r.push(e.field),i.innerHTML=e.message,n.append(i)}}),this.step.querySelectorAll("span.error").forEach(function(e){var t=e.getAttribute("data-id");-1===r.indexOf(t)&&e.remove()})}}]),e}(),c=function(){function e(t,r){n(this,e),this.dom=t,this.userForm=r,this.prevButton=t.querySelector(".step-button-prev"),this.nextButton=t.querySelector(".step-button-next"),this.init()}return u(e,[{key:"init",value:function(){var e=this;this.prevButton.addEventListener("click",function(t){t.preventDefault(),window.triggerDispatchEvent(e.userForm.dom,"userform.action.prev")}),this.nextButton.addEventListener("click",function(t){t.preventDefault(),window.triggerDispatchEvent(e.userForm.dom,"userform.action.next")}),this.update(),this.userForm.dom.addEventListener("userform.form.changestep",function(){e.update()}),this.userForm.dom.addEventListener("userform.form.conditionalstep",function(){e.update()})}},{key:"update",value:function(){var e=this.userForm.getNumberOfSteps(),t=this.userForm.getCurrentStepID(),r=null,n=null;for(r=e-1;r>=0;r--)if(n=this.userForm.getStep(r),!n.conditionallyHidden()){t>=r?this.nextButton.parentNode.classList.add("hide"):this.nextButton.parentNode.classList.remove("hide"),t>0&&t<=r?this.prevButton.parentNode.classList.remove("hide"):this.prevButton.parentNode.classList.add("hide"),t>=r?this.dom.querySelector(".btn-toolbar").classList.remove("hide"):this.dom.querySelector(".btn-toolbar").classList.add("hide");break}}}]),e}(),f=function(){function e(t){n(this,e),this.dom=t,this.CONSTANTS={},this.steps=[],this.progressBar=null,this.actions=null,this.currentStep=null,this.CONSTANTS.ENABLE_LIVE_VALIDATION=void 0!==this.dom.getAttribute("livevalidation"),this.CONSTANTS.DISPLAY_ERROR_MESSAGES_AT_TOP=void 0!==this.dom.getAttribute("toperrors"),this.CONSTANTS.ENABLE_ARE_YOU_SURE=void 0!==this.dom.getAttribute("enableareyousure")}return u(e,[{key:"init",value:function(){this.initialiseFormSteps(),this.CONSTANTS.ENABLE_ARE_YOU_SURE&&this.initAreYouSure()}},{key:"initialiseFormSteps",value:function(){var e=this;this.dom.querySelectorAll(".form-step").forEach(function(t){var r=new l(t,e);r.hide(),e.addStep(r),e.CONSTANTS.ENABLE_LIVE_VALIDATION&&r.enableLiveValidation()}),this.setCurrentStep(this.steps[0]);var t=this.dom.querySelector(".userform-progress");t&&(this.progressBar=new a(t,this));var r=this.dom.querySelector(".step-navigation");r&&(this.formActions=new c(r,this),this.formActions.update()),this.setUpPing(),this.dom.addEventListener("userform.action.next",function(){e.nextStep()}),this.dom.addEventListener("userform.action.prev",function(){e.prevStep()}),this.dom.addEventListener("submit",function(t){e.validateForm(t)})}},{key:"validateForm",value:function(e){var t=this;e.preventDefault(),this.currentStep.validate().then(function(e){e||t.dom.submit()}).catch(function(){})}},{key:"setCurrentStep",value:function(e){e instanceof l&&(this.currentStep=e,this.currentStep.show())}},{key:"addStep",value:function(e){e instanceof l&&(e.setId(this.steps.length),this.steps.push(e))}},{key:"getNumberOfSteps",value:function(){return this.steps.length}},{key:"getCurrentStepID",value:function(){return this.currentStep.id?this.currentStep.id:0}},{key:"getStep",value:function(e){return this.steps[e]}},{key:"nextStep",value:function(){var e=this;this.currentStep.validate().then(function(){e.jumpToStep(e.steps.indexOf(e.currentStep)+1,!0)}).catch(function(){})}},{key:"prevStep",value:function(){this.jumpToStep(this.steps.indexOf(this.currentStep)-1,!0)}},{key:"jumpToStep",value:function(e,t){var r=this.steps[e],n=void 0===t||t;if(void 0!==r){if(r.conditionallyHidden())return void(n?this.jumpToStep(e+1,t):this.jumpToStep(e-1,t));this.currentStep&&this.currentStep.hide(),this.setCurrentStep(r),window.triggerDispatchEvent(this.dom,"userform.form.changestep",{stepId:r.id})}}},{key:"setUpPing",value:function(){window.setInterval(function(){fetch("UserDefinedFormController/ping")},18e4)}},{key:"doConfirm",value:function(e){if(0===this.dom.querySelectorAll(".dirty").length)return!0;if(navigator.userAgent.toLowerCase().match(/msie|chrome/)){if(window.hasUserFormsPropted)return!0;window.hasUserFormsPropted=!0,window.setTimeout(function(){window.hasUserFormsPropted=!1},900)}return e.preventDefault(),void 0!==window.i18n?event.returnValue=window.i18n._t("UserForms.LEAVE_CONFIRMATION","You have unsaved changes!"):event.returnValue="You have unsaved changes!",!0}},{key:"initAreYouSure",value:function(){var e=this.doConfirm.bind(this);this.dom.addEventListener("submit",function(t){window.removeEventListener("beforeunload",e)}),window.addEventListener("beforeunload",e)}}]),e}();document.addEventListener("DOMContentLoaded",function(){document.querySelectorAll("form.userform").forEach(function(e){new f(e).init()})})},"./client/src/bundles/bundle.js":function(e,t,r){"use strict";r("./client/src/bundles/UserForms.js")},"./node_modules/async-validator/dist-web/index.js":function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),function(e){function n(){return n=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var r=arguments[t];for(var n in r)Object.prototype.hasOwnProperty.call(r,n)&&(e[n]=r[n])}return e},n.apply(this,arguments)}function i(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,s(e,t)}function u(e){return(u=Object.setPrototypeOf?Object.getPrototypeOf.bind():function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function s(e,t){return(s=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e})(e,t)}function o(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){})),!0}catch(e){return!1}}function a(e,t,r){return a=o()?Reflect.construct.bind():function(e,t,r){var n=[null];n.push.apply(n,t);var i=Function.bind.apply(e,n),u=new i;return r&&s(u,r.prototype),u},a.apply(null,arguments)}function l(e){return-1!==Function.toString.call(e).indexOf("[native code]")}function c(e){var t="function"==typeof Map?new Map:void 0;return(c=function(e){function r(){return a(e,arguments,u(this).constructor)}if(null===e||!l(e))return e;if("function"!=typeof e)throw new TypeError("Super expression must either be null or a function");if(void 0!==t){if(t.has(e))return t.get(e);t.set(e,r)}return r.prototype=Object.create(e.prototype,{constructor:{value:r,enumerable:!1,writable:!0,configurable:!0}}),s(r,e)})(e)}function f(e){if(!e||!e.length)return null;var t={};return e.forEach(function(e){var r=e.field;t[r]=t[r]||[],t[r].push(e)}),t}function d(e){for(var t=arguments.length,r=new Array(t>1?t-1:0),n=1;n<t;n++)r[n-1]=arguments[n];var i=0,u=r.length;return"function"==typeof e?e.apply(null,r):"string"==typeof e?e.replace(E,function(e){if("%%"===e)return"%";if(i>=u)return e;switch(e){case"%s":return String(r[i++]);case"%d":return Number(r[i++]);case"%j":try{return JSON.stringify(r[i++])}catch(e){return"[Circular]"}break;default:return e}}):e}function p(e){return"string"===e||"url"===e||"hex"===e||"email"===e||"date"===e||"pattern"===e}function h(e,t){return void 0===e||null===e||!("array"!==t||!Array.isArray(e)||e.length)||!(!p(t)||"string"!=typeof e||e)}function m(e,t,r){function n(e){i.push.apply(i,e||[]),++u===s&&r(i)}var i=[],u=0,s=e.length;e.forEach(function(e){t(e,n)})}function v(e,t,r){function n(s){if(s&&s.length)return void r(s);var o=i;i+=1,o<u?t(e[o],n):r([])}var i=0,u=e.length;n([])}function y(e){var t=[];return Object.keys(e).forEach(function(r){t.push.apply(t,e[r]||[])}),t}function g(e,t,r,n,i){if(t.first){var u=new Promise(function(t,u){var s=function(e){return n(e),e.length?u(new x(e,f(e))):t(i)};v(y(e),r,s)});return u.catch(function(e){return e}),u}var s=!0===t.firstFields?Object.keys(e):t.firstFields||[],o=Object.keys(e),a=o.length,l=0,c=[],d=new Promise(function(t,u){var d=function(e){if(c.push.apply(c,e),++l===a)return n(c),c.length?u(new x(c,f(c))):t(i)};o.length||(n(c),t(i)),o.forEach(function(t){var n=e[t];-1!==s.indexOf(t)?v(n,r,d):m(n,r,d)})});return d.catch(function(e){return e}),d}function b(e){return!(!e||void 0===e.message)}function w(e,t){for(var r=e,n=0;n<t.length;n++){if(void 0==r)return r;r=r[t[n]]}return r}function F(e,t){return function(r){var n;return n=e.fullFields?w(t,e.fullFields):t[r.field||e.fullField],b(r)?(r.field=r.field||e.fullField,r.fieldValue=n,r):{message:"function"==typeof r?r():r,fieldValue:n,field:r.field||e.fullField}}}function q(e,t){if(t)for(var r in t)if(t.hasOwnProperty(r)){var i=t[r];"object"==typeof i&&"object"==typeof e[r]?e[r]=n({},e[r],i):e[r]=i}return e}function A(){return{default:"Validation error on field %s",required:"%s is required",enum:"%s must be one of %s",whitespace:"%s cannot be empty",date:{format:"%s date %s is invalid for format %s",parse:"%s date could not be parsed, %s is invalid ",invalid:"%s date %s is invalid"},types:{string:"%s is not a %s",method:"%s is not a %s (function)",array:"%s is not an %s",object:"%s is not an %s",number:"%s is not a %s",date:"%s is not a %s",boolean:"%s is not a %s",integer:"%s is not an %s",float:"%s is not a %s",regexp:"%s is not a valid %s",email:"%s is not a valid %s",url:"%s is not a valid %s",hex:"%s is not a valid %s"},string:{len:"%s must be exactly %s characters",min:"%s must be at least %s characters",max:"%s cannot be longer than %s characters",range:"%s must be between %s and %s characters"},number:{len:"%s must equal %s",min:"%s cannot be less than %s",max:"%s cannot be greater than %s",range:"%s must be between %s and %s"},array:{len:"%s must be exactly %s in length",min:"%s cannot be less than %s in length",max:"%s cannot be greater than %s in length",range:"%s must be between %s and %s in length"},pattern:{mismatch:"%s value %s does not match pattern %s"},clone:function(){var e=JSON.parse(JSON.stringify(this));return e.clone=this.clone,e}}}r.d(t,"default",function(){return te});var E=/%[sdj%]/g,S=function(){};void 0!==e&&r.i({NODE_ENV:"production"});var O,x=function(e){function t(t,r){var n;return n=e.call(this,"Async Validation Error")||this,n.errors=t,n.fields=r,n}return i(t,e),t}(c(Error)),L=function(e,t,r,n,i,u){!e.required||r.hasOwnProperty(e.field)&&!h(t,u||e.type)||n.push(d(i.messages.required,e.fullField))},T=function(e,t,r,n,i){(/^\s+$/.test(t)||""===t)&&n.push(d(i.messages.whitespace,e.fullField))},k=function(){if(O)return O;var e=function(e){return e&&e.includeBoundaries?"(?:(?<=\\s|^)(?=[a-fA-F\\d:])|(?<=[a-fA-F\\d:])(?=\\s|$))":""},t="(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}",r="[a-fA-F\\d]{1,4}",n=("\n(?:\n(?:"+r+":){7}(?:"+r+"|:)| // 1:2:3:4:5:6:7:: 1:2:3:4:5:6:7:8\n(?:"+r+":){6}(?:"+t+"|:"+r+"|:)| // 1:2:3:4:5:6:: 1:2:3:4:5:6::8 1:2:3:4:5:6::8 1:2:3:4:5:6::1.2.3.4\n(?:"+r+":){5}(?::"+t+"|(?::"+r+"){1,2}|:)| // 1:2:3:4:5:: 1:2:3:4:5::7:8 1:2:3:4:5::8 1:2:3:4:5::7:1.2.3.4\n(?:"+r+":){4}(?:(?::"+r+"){0,1}:"+t+"|(?::"+r+"){1,3}|:)| // 1:2:3:4:: 1:2:3:4::6:7:8 1:2:3:4::8 1:2:3:4::6:7:1.2.3.4\n(?:"+r+":){3}(?:(?::"+r+"){0,2}:"+t+"|(?::"+r+"){1,4}|:)| // 1:2:3:: 1:2:3::5:6:7:8 1:2:3::8 1:2:3::5:6:7:1.2.3.4\n(?:"+r+":){2}(?:(?::"+r+"){0,3}:"+t+"|(?::"+r+"){1,5}|:)| // 1:2:: 1:2::4:5:6:7:8 1:2::8 1:2::4:5:6:7:1.2.3.4\n(?:"+r+":){1}(?:(?::"+r+"){0,4}:"+t+"|(?::"+r+"){1,6}|:)| // 1:: 1::3:4:5:6:7:8 1::8 1::3:4:5:6:7:1.2.3.4\n(?::(?:(?::"+r+"){0,5}:"+t+"|(?::"+r+"){1,7}|:)) // ::2:3:4:5:6:7:8 ::2:3:4:5:6:7:8 ::8 ::1.2.3.4\n)(?:%[0-9a-zA-Z]{1,})? // %eth0 %1\n").replace(/\s*\/\/.*$/gm,"").replace(/\n/g,"").trim(),i=new RegExp("(?:^"+t+"$)|(?:^"+n+"$)"),u=new RegExp("^"+t+"$"),s=new RegExp("^"+n+"$"),o=function(r){return r&&r.exact?i:new RegExp("(?:"+e(r)+t+e(r)+")|(?:"+e(r)+n+e(r)+")","g")};o.v4=function(r){return r&&r.exact?u:new RegExp(""+e(r)+t+e(r),"g")},o.v6=function(t){return t&&t.exact?s:new RegExp(""+e(t)+n+e(t),"g")};var a=o.v4().source,l=o.v6().source,c="(?:(?:(?:[a-z]+:)?//)|www\\.)(?:\\S+(?::\\S*)?@)?(?:localhost|"+a+"|"+l+'|(?:(?:[a-z\\u00a1-\\uffff0-9][-_]*)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))(?::\\d{2,5})?(?:[/?#][^\\s"]*)?';return O=new RegExp("(?:^"+c+"$)","i")},j={email:/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+\.)+[a-zA-Z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]{2,}))$/,hex:/^#?([a-f0-9]{6}|[a-f0-9]{3})$/i},N={integer:function(e){return N.number(e)&&parseInt(e,10)===e},float:function(e){return N.number(e)&&!N.integer(e)},array:function(e){return Array.isArray(e)},regexp:function(e){if(e instanceof RegExp)return!0;try{return!!new RegExp(e)}catch(e){return!1}},date:function(e){return"function"==typeof e.getTime&&"function"==typeof e.getMonth&&"function"==typeof e.getYear&&!isNaN(e.getTime())},number:function(e){return!isNaN(e)&&"number"==typeof e},object:function(e){return"object"==typeof e&&!N.array(e)},method:function(e){return"function"==typeof e},email:function(e){return"string"==typeof e&&e.length<=320&&!!e.match(j.email)},url:function(e){return"string"==typeof e&&e.length<=2048&&!!e.match(k())},hex:function(e){return"string"==typeof e&&!!e.match(j.hex)}},P=function(e,t,r,n,i){if(e.required&&void 0===t)return void L(e,t,r,n,i);var u=["integer","float","array","regexp","object","method","email","number","date","url","hex"],s=e.type;u.indexOf(s)>-1?N[s](t)||n.push(d(i.messages.types[s],e.fullField,e.type)):s&&typeof t!==e.type&&n.push(d(i.messages.types[s],e.fullField,e.type))},_=function(e,t,r,n,i){var u="number"==typeof e.len,s="number"==typeof e.min,o="number"==typeof e.max,a=/[\uD800-\uDBFF][\uDC00-\uDFFF]/g,l=t,c=null,f="number"==typeof t,p="string"==typeof t,h=Array.isArray(t);if(f?c="number":p?c="string":h&&(c="array"),!c)return!1;h&&(l=t.length),p&&(l=t.replace(a,"_").length),u?l!==e.len&&n.push(d(i.messages[c].len,e.fullField,e.len)):s&&!o&&l<e.min?n.push(d(i.messages[c].min,e.fullField,e.min)):o&&!s&&l>e.max?n.push(d(i.messages[c].max,e.fullField,e.max)):s&&o&&(l<e.min||l>e.max)&&n.push(d(i.messages[c].range,e.fullField,e.min,e.max))},D=function(e,t,r,n,i){e.enum=Array.isArray(e.enum)?e.enum:[],-1===e.enum.indexOf(t)&&n.push(d(i.messages.enum,e.fullField,e.enum.join(", ")))},I=function(e,t,r,n,i){if(e.pattern)if(e.pattern instanceof RegExp)e.pattern.lastIndex=0,e.pattern.test(t)||n.push(d(i.messages.pattern.mismatch,e.fullField,t,e.pattern));else if("string"==typeof e.pattern){var u=new RegExp(e.pattern);u.test(t)||n.push(d(i.messages.pattern.mismatch,e.fullField,t,e.pattern))}},V={required:L,whitespace:T,type:P,range:_,enum:D,pattern:I},R=function(e,t,r,n,i){var u=[];if(e.required||!e.required&&n.hasOwnProperty(e.field)){if(h(t,"string")&&!e.required)return r();V.required(e,t,n,u,i,"string"),h(t,"string")||(V.type(e,t,n,u,i),V.range(e,t,n,u,i),V.pattern(e,t,n,u,i),!0===e.whitespace&&V.whitespace(e,t,n,u,i))}r(u)},C=function(e,t,r,n,i){var u=[];if(e.required||!e.required&&n.hasOwnProperty(e.field)){if(h(t)&&!e.required)return r();V.required(e,t,n,u,i),void 0!==t&&V.type(e,t,n,u,i)}r(u)},B=function(e,t,r,n,i){var u=[];if(e.required||!e.required&&n.hasOwnProperty(e.field)){if(""===t&&(t=void 0),h(t)&&!e.required)return r();V.required(e,t,n,u,i),void 0!==t&&(V.type(e,t,n,u,i),V.range(e,t,n,u,i))}r(u)},M=function(e,t,r,n,i){var u=[];if(e.required||!e.required&&n.hasOwnProperty(e.field)){if(h(t)&&!e.required)return r();V.required(e,t,n,u,i),void 0!==t&&V.type(e,t,n,u,i)}r(u)},H=function(e,t,r,n,i){var u=[];if(e.required||!e.required&&n.hasOwnProperty(e.field)){if(h(t)&&!e.required)return r();V.required(e,t,n,u,i),h(t)||V.type(e,t,n,u,i)}r(u)},U=function(e,t,r,n,i){var u=[];if(e.required||!e.required&&n.hasOwnProperty(e.field)){if(h(t)&&!e.required)return r();V.required(e,t,n,u,i),void 0!==t&&(V.type(e,t,n,u,i),V.range(e,t,n,u,i))}r(u)},$=function(e,t,r,n,i){var u=[];if(e.required||!e.required&&n.hasOwnProperty(e.field)){if(h(t)&&!e.required)return r();V.required(e,t,n,u,i),void 0!==t&&(V.type(e,t,n,u,i),V.range(e,t,n,u,i))}r(u)},z=function(e,t,r,n,i){var u=[];if(e.required||!e.required&&n.hasOwnProperty(e.field)){if((void 0===t||null===t)&&!e.required)return r();V.required(e,t,n,u,i,"array"),void 0!==t&&null!==t&&(V.type(e,t,n,u,i),V.range(e,t,n,u,i))}r(u)},Y=function(e,t,r,n,i){var u=[];if(e.required||!e.required&&n.hasOwnProperty(e.field)){if(h(t)&&!e.required)return r();V.required(e,t,n,u,i),void 0!==t&&V.type(e,t,n,u,i)}r(u)},J=function(e,t,r,n,i){var u=[];if(e.required||!e.required&&n.hasOwnProperty(e.field)){if(h(t)&&!e.required)return r();V.required(e,t,n,u,i),void 0!==t&&V.enum(e,t,n,u,i)}r(u)},Z=function(e,t,r,n,i){var u=[];if(e.required||!e.required&&n.hasOwnProperty(e.field)){if(h(t,"string")&&!e.required)return r();V.required(e,t,n,u,i),h(t,"string")||V.pattern(e,t,n,u,i)}r(u)},G=function(e,t,r,n,i){var u=[];if(e.required||!e.required&&n.hasOwnProperty(e.field)){if(h(t,"date")&&!e.required)return r();if(V.required(e,t,n,u,i),!h(t,"date")){var s;s=t instanceof Date?t:new Date(t),V.type(e,s,n,u,i),s&&V.range(e,s.getTime(),n,u,i)}}r(u)},W=function(e,t,r,n,i){var u=[],s=Array.isArray(t)?"array":typeof t;V.required(e,t,n,u,i,s),r(u)},K=function(e,t,r,n,i){var u=e.type,s=[];if(e.required||!e.required&&n.hasOwnProperty(e.field)){if(h(t,u)&&!e.required)return r();V.required(e,t,n,s,i,u),h(t,u)||V.type(e,t,n,s,i)}r(s)},Q=function(e,t,r,n,i){var u=[];if(e.required||!e.required&&n.hasOwnProperty(e.field)){if(h(t)&&!e.required)return r();V.required(e,t,n,u,i)}r(u)},X={string:R,method:C,number:B,boolean:M,regexp:H,integer:U,float:$,array:z,object:Y,enum:J,pattern:Z,date:G,url:K,hex:K,email:K,required:W,any:Q},ee=A(),te=function(){function e(e){this.rules=null,this._messages=ee,this.define(e)}var t=e.prototype;return t.define=function(e){var t=this;if(!e)throw new Error("Cannot configure a schema with no rules");if("object"!=typeof e||Array.isArray(e))throw new Error("Rules must be an object");this.rules={},Object.keys(e).forEach(function(r){var n=e[r];t.rules[r]=Array.isArray(n)?n:[n]})},t.messages=function(e){return e&&(this._messages=q(A(),e)),this._messages},t.validate=function(t,r,i){function u(e){for(var t=[],r={},n=0;n<e.length;n++)!function(e){if(Array.isArray(e)){var r;t=(r=t).concat.apply(r,e)}else t.push(e)}(e[n]);t.length?(r=f(t),l(t,r)):l(null,o)}var s=this;void 0===r&&(r={}),void 0===i&&(i=function(){});var o=t,a=r,l=i;if("function"==typeof a&&(l=a,a={}),!this.rules||0===Object.keys(this.rules).length)return l&&l(null,o),Promise.resolve(o);if(a.messages){var c=this.messages();c===ee&&(c=A()),q(c,a.messages),a.messages=c}else a.messages=this.messages();var p={};(a.keys||Object.keys(this.rules)).forEach(function(e){var r=s.rules[e],i=o[e];r.forEach(function(r){var u=r;"function"==typeof u.transform&&(o===t&&(o=n({},o)),i=o[e]=u.transform(i)),u="function"==typeof u?{validator:u}:n({},u),u.validator=s.getValidationMethod(u),u.validator&&(u.field=e,u.fullField=u.fullField||e,u.type=s.getType(u),p[e]=p[e]||[],p[e].push({rule:u,value:i,source:o,field:e}))})});var h={};return g(p,a,function(t,r){function i(e,t){return n({},t,{fullField:s.fullField+"."+e,fullFields:s.fullFields?[].concat(s.fullFields,[e]):[e]})}function u(u){void 0===u&&(u=[]);var c=Array.isArray(u)?u:[u];!a.suppressWarning&&c.length&&e.warning("async-validator:",c),c.length&&void 0!==s.message&&(c=[].concat(s.message));var f=c.map(F(s,o));if(a.first&&f.length)return h[s.field]=1,r(f);if(l){if(s.required&&!t.value)return void 0!==s.message?f=[].concat(s.message).map(F(s,o)):a.error&&(f=[a.error(s,d(a.messages.required,s.field))]),r(f);var p={};s.defaultField&&Object.keys(t.value).map(function(e){p[e]=s.defaultField}),p=n({},p,t.rule.fields);var m={};Object.keys(p).forEach(function(e){var t=p[e],r=Array.isArray(t)?t:[t];m[e]=r.map(i.bind(null,e))});var v=new e(m);v.messages(a.messages),t.rule.options&&(t.rule.options.messages=a.messages,t.rule.options.error=a.error),v.validate(t.value,t.rule.options||a,function(e){var t=[];f&&f.length&&t.push.apply(t,f),e&&e.length&&t.push.apply(t,e),r(t.length?t:null)})}else r(f)}var s=t.rule,l=!("object"!==s.type&&"array"!==s.type||"object"!=typeof s.fields&&"object"!=typeof s.defaultField);l=l&&(s.required||!s.required&&t.value),s.field=t.field;var c;if(s.asyncValidator)c=s.asyncValidator(s,t.value,u,t.source,a);else if(s.validator){try{c=s.validator(s,t.value,u,t.source,a)}catch(e){null==console.error||console.error(e),a.suppressValidatorError||setTimeout(function(){throw e},0),u(e.message)}!0===c?u():!1===c?u("function"==typeof s.message?s.message(s.fullField||s.field):s.message||(s.fullField||s.field)+" fails"):c instanceof Array?u(c):c instanceof Error&&u(c.message)}c&&c.then&&c.then(function(){return u()},function(e){return u(e)})},function(e){u(e)},o)},t.getType=function(e){if(void 0===e.type&&e.pattern instanceof RegExp&&(e.type="pattern"),"function"!=typeof e.validator&&e.type&&!X.hasOwnProperty(e.type))throw new Error(d("Unknown rule type %s",e.type));return e.type||"string"},t.getValidationMethod=function(e){if("function"==typeof e.validator)return e.validator;var t=Object.keys(e),r=t.indexOf("message");return-1!==r&&t.splice(r,1),1===t.length&&"required"===t[0]?X.required:X[this.getType(e)]||void 0},e}();te.register=function(e,t){if("function"!=typeof t)throw new Error("Cannot register a validator by type, validator is not a function");X[e]=t},te.warning=S,te.messages=ee,te.validators=X}.call(t,r("./node_modules/process/browser.js"))},"./node_modules/process/browser.js":function(e,t){function r(){throw new Error("setTimeout has not been defined")}function n(){throw new Error("clearTimeout has not been defined")}function i(e){if(c===setTimeout)return setTimeout(e,0);if((c===r||!c)&&setTimeout)return c=setTimeout,setTimeout(e,0);try{return c(e,0)}catch(t){try{return c.call(null,e,0)}catch(t){return c.call(this,e,0)}}}function u(e){if(f===clearTimeout)return clearTimeout(e);if((f===n||!f)&&clearTimeout)return f=clearTimeout,clearTimeout(e);try{return f(e)}catch(t){try{return f.call(null,e)}catch(t){return f.call(this,e)}}}function s(){m&&p&&(m=!1,p.length?h=p.concat(h):v=-1,h.length&&o())}function o(){if(!m){var e=i(s);m=!0;for(var t=h.length;t;){for(p=h,h=[];++v<t;)p&&p[v].run();v=-1,t=h.length}p=null,m=!1,u(e)}}function a(e,t){this.fun=e,this.array=t}function l(){}var c,f,d=e.exports={};!function(){try{c="function"==typeof setTimeout?setTimeout:r}catch(e){c=r}try{f="function"==typeof clearTimeout?clearTimeout:n}catch(e){f=n}}();var p,h=[],m=!1,v=-1;d.nextTick=function(e){var t=new Array(arguments.length-1);if(arguments.length>1)for(var r=1;r<arguments.length;r++)t[r-1]=arguments[r];h.push(new a(e,t)),1!==h.length||m||i(o)},a.prototype.run=function(){this.fun.apply(null,this.array)},d.title="browser",d.browser=!0,d.env={},d.argv=[],d.version="",d.versions={},d.on=l,d.addListener=l,d.once=l,d.off=l,d.removeListener=l,d.removeAllListeners=l,d.emit=l,d.prependListener=l,d.prependOnceListener=l,d.listeners=function(e){return[]},d.binding=function(e){throw new Error("process.binding is not supported")},d.cwd=function(){return"/"},d.chdir=function(e){throw new Error("process.chdir is not supported")},d.umask=function(){return 0}}});

View File

@ -1 +1 @@
.userform-progress .progress{position:relative;height:1em;background:#ced5e1}.userform-progress .progress-bar{position:absolute;height:1em;background:#566b8d}.userform-progress .step-buttons{margin-left:0;position:relative}.userform-progress .step-button-wrapper{display:inline-block;list-style-type:none}.userform-progress .step-button-wrapper.viewed .step-button-jump{opacity:1}.userform-progress .step-button-jump{position:absolute;top:0;opacity:.7}.step-navigation .step-buttons{margin-left:0}.step-navigation .step-button-wrapper{display:inline-block;list-style-type:none}.userform{clear:both;width:100%;max-width:100%}.userform .hide{display:none}.userform .field label.right{color:#303b4d}.userformsgroup{border:1px solid #aebace;border-radius:4px;padding:8px;margin-top:12px;margin-bottom:12px}.userformsgroup>legend{padding-left:4px;padding-right:4px;border:0;width:auto}.right-title{clear:both;display:block}.checkbox .right-title{display:inline}.userform .left{margin-bottom:5px;font-weight:700}
.userform-progress .progress{position:relative;height:1em;background:#ced5e1}.userform-progress .progress-bar{position:absolute;height:1em;background:#566b8d}.userform-progress .step-buttons{margin-left:0;padding-left:0;width:100%;display:-webkit-box;display:-webkit-flex;display:flex;-webkit-box-pack:justify;-webkit-justify-content:space-between;justify-content:space-between;position:relative}.userform-progress .step-button-wrapper{display:inline-block;list-style-type:none}.userform-progress .step-button-wrapper.viewed .step-button-jump{opacity:1}.userform-progress .step-button-jump{opacity:.7}.step-navigation .step-buttons{margin-left:0}.step-navigation .step-button-wrapper{display:inline-block;list-style-type:none}.userform{clear:both;width:100%;max-width:100%}.userform .hide{display:none}.userform .field label.right{color:#303b4d}.userformsgroup{border:1px solid #aebace;border-radius:4px;padding:8px;margin-top:12px;margin-bottom:12px}.userformsgroup>legend{padding-left:4px;padding-right:4px;border:0;width:auto}.right-title{clear:both;display:block}.checkbox .right-title{display:inline}.userform .left{margin-bottom:5px;font-weight:700}

View File

@ -1,774 +1,577 @@
/**
* @file Manages the multi-step navigation.
*/
import Schema from 'async-validator';
import jQuery from 'jquery';
import i18n from 'i18n';
const DIRTY_CLASS = 'dirty';
const FOCUSED_CLASS = 'focused';
jQuery(document).ready(($) => {
// Settings that come from the CMS.
const CONSTANTS = {};
function isVisible(element) {
return element.style.display !== 'none'
&& element.style.visibility !== 'hidden'
&& !element.classList.contains('hide');
}
// Common functions that extend multiple classes.
const commonMixin = {
/**
* @func show
* @desc Show the form step. Looks after aria attributes too.
*/
show() {
this.$el.attr('aria-hidden', false).show();
},
/**
* @func hide
* @desc Hide the form step. Looks after aria attributes too.
*/
hide() {
this.$el.attr('aria-hidden', true).hide();
},
};
/**
* @func ErrorContainer
* @constructor
* @param {object} element - The error container element.
* @return {object} - The ErrorContainer instance.
* @desc Creates an error container. Used to display step error messages at the top.
*/
function ErrorContainer(element) {
this.$el = element instanceof $ ? element : $(element);
// Set the error container's heading.
this.$el.find('h4').text(i18n._t('UserForms.ERROR_CONTAINER_HEADER',
'Please correct the following errors and try again:'));
return this;
class ProgressBar {
constructor(dom, userForm) {
this.dom = dom;
this.userForm = userForm;
this.progressTitle = this.userForm.dom.querySelector('.progress-title');
this.buttons = this.dom.querySelectorAll('.step-button-jump');
this.currentStepNumber = this.dom.querySelector('.current-step-number');
this.init();
}
/**
* @func hasErrors
* @return boolean
* @desc Checks if the error container has any error messages.
*/
ErrorContainer.prototype.hasErrors = function hasErrors() {
return this.$el.find('.error-list').children().length > 0;
};
/**
* @func removeErrorMessage
* @desc Removes an error message from the error container.
*/
ErrorContainer.prototype.removeErrorMessage = function removeErrorMessage(fieldId) {
this.$el.find(`#${fieldId}-top-error`).remove();
// If there are no more error then hide the container.
if (!this.hasErrors()) {
this.hide();
}
};
/**
* @func addStepLink
* @param {object} step - FormStep instance.
* @desc Adds a link to a form step as an error message.
*/
ErrorContainer.prototype.addStepLink = function addStepLink(step) {
const userform = this.$el.closest('.userform').data('inst');
const itemID = `${step.$el.attr('id')}-error-link`;
let $itemElement = this.$el.find(`#${itemID}`);
const stepID = step.$el.attr('id');
const stepTitle = step.$el.data('title');
// If the item already exists we don't need to do anything.
if ($itemElement.length) {
return;
}
$itemElement = $(`<li id="${itemID}"><a href="#${stepID}">${stepTitle}</a></li>`);
$itemElement.on('click', (e) => {
e.preventDefault();
userform.jumpToStep(step.id);
});
this.$el.find('.error-list').append($itemElement);
};
/**
* @func removeStepLink
* @param {object} step - FormStep instance.
* @desc Removes a step link from the error container.
*/
ErrorContainer.prototype.removeStepLink = function removeStepLink(fieldId) {
const stepID = $(`#${fieldId}`).closest('.form-step').attr('id');
this.$el.find(`#${stepID}-error-link`).remove();
// Hide the error container if we've just removed the last error.
if (this.$el.find('.error-list').is(':empty')) {
this.hide();
}
};
/**
* @func ErrorContainer.updateErrorMessage
* @param {object} $input - The jQuery input object which contains the field to validate.
* @param {object} message - The error message to display (html escaped).
* @desc Update an error message (displayed at the top of the form).
*/
ErrorContainer.prototype.updateErrorMessage = function updateErrorMessage($input, message) {
const inputID = $input.attr('id');
let anchor = `#${inputID}`;
const elementID = `${inputID}-top-error`;
let messageElement = $(`#${elementID}`);
let describedBy = $input.attr('aria-describedby');
// The 'message' param will be an empty string if the field is valid.
if (!message) {
// Style issues as fixed if they already exist
messageElement.addClass('fixed');
return;
}
messageElement.removeClass('fixed');
this.show();
if (messageElement.length === 1) {
// Update the existing error message.
messageElement.show().find('a').html(message);
} else {
// Generate better link to field
$input.closest('.field[id]').each(() => {
const anchorID = $(this).attr('id');
if (!anchorID) {
return;
}
anchor = `#${anchorID}`;
});
// Add a new error message
messageElement = $('<li><a></a></li>');
messageElement
.attr('id', elementID)
.find('a')
.attr('href', location.pathname + location.search + anchor)
.html(message);
this.$el.find('ul').append(messageElement);
// Link back to original input via aria
// Respect existing non-error aria-describedby
if (!describedBy) {
describedBy = elementID;
} else if (!describedBy.match(new RegExp(`\\b${elementID}\\b`))) {
// Add to end of list if not already present
describedBy += ` ${elementID}`;
}
$input.attr('aria-describedby', describedBy);
}
};
/**
* @func FormStep
* @constructor
* @param {object} element
* @return {object} - The FormStep instance.
* @desc Creates a form step.
*/
function FormStep(element) {
const self = this;
this.$el = element instanceof $ ? element : $(element);
const userform = this.$el.closest('.userform').data('inst');
// Find button for this step
this.$elButton = $(`.step-button-wrapper[data-for='${this.$el.prop('id')}']`);
// Has the step been viewed by the user?
this.viewed = false;
// Is the form step valid?
// This value is used on form submission, which fails, if any of the steps are invalid.
this.valid = false;
// The internal id of the step. Used for getting the step from the UserForm.steps array.
this.id = null;
this.hide();
if (CONSTANTS.DISPLAY_ERROR_MESSAGES_AT_TOP) {
this.errorContainer = new ErrorContainer(this.$el.find('.error-container'));
// Listen for errors on the UserForm.
userform.$el.on('userform.form.error', (e, validator) => {
// The step only cares about errors if it's currently visible.
if (!self.$el.is(':visible')) {
return;
}
// Add or update each error in the list.
$.each(validator.errorList, (i, error) => {
self.errorContainer.updateErrorMessage($(error.element), error.message);
});
});
// Listen for fields becoming valid
userform.$el.on('userform.form.valid', (e, fieldId) => {
self.errorContainer.removeErrorMessage(fieldId);
});
}
// Ensure that page visibilty updates the step navigation
this
.$elButton
.on('userform.field.hide userform.field.show', () => {
userform.$el.trigger('userform.form.conditionalstep');
});
return this;
}
/**
* Determine if this step is conditionally disabled
*
* @returns {Boolean}
*/
// Because the element itself could be visible but 0 height, so check visibility of button
FormStep.prototype.conditionallyHidden = function conditionallyHidden() {
return !this.$elButton.find('button').is(':visible');
};
/**
* @func ProgressBar
* @constructor
* @param {object} element
* @return {object} - The Progress bar instance.
* @desc Creates a progress bar.
*/
function ProgressBar(element) {
const self = this;
this.$el = element instanceof $ ? element : $(element);
this.$buttons = this.$el.find('.step-button-jump');
this.$jsAlign = this.$el.find('.js-align');
const userform = this.$el.closest('.userform').data('inst');
// Update the progress bar when 'step' buttons are clicked.
this.$buttons.each((i, stepButton) => {
$(stepButton).on('click', (e) => {
init() {
this.dom.style.display = 'initial';
const buttons = this.buttons;
buttons.forEach((button) => {
button.addEventListener('click', (e) => {
e.preventDefault();
const stepNumber = parseInt($(e.target).data('step'), 10);
self.$el.trigger('userform.progress.changestep', stepNumber);
const stepNumber = parseInt(button.getAttribute('data-step'), 10);
this.userForm.jumpToStep(stepNumber - 1);
return false;
});
});
// Update the progress bar when 'prev' and 'next' buttons are clicked.
userform.$el.on('userform.form.changestep', (e, stepID) => {
self.update(stepID);
this.userForm.dom.addEventListener('userform.form.changestep', (e) => {
this.update(e.detail.stepId);
});
// Listen for steps being conditionally shown / hidden by display rules.
// We need to update step related UI like the number of step buttons
// and any text that shows the total number of steps.
userform.$el.on('userform.form.conditionalstep', () => {
// Update the step numbers on the buttons.
const $visibleButtons = self.$buttons.filter(':visible');
$visibleButtons.each((i, button) => {
$(button).text(i + 1);
});
// Update the actual progress bar.
self.$el.find('.progress-bar').attr('aria-valuemax', $visibleButtons.length);
// Update any text that uses the total number of steps.
self.$el.find('.total-step-number').text($visibleButtons.length);
});
// Spaces out the steps below progress bar evenly
this.$jsAlign.each((index, button) => {
const $button = $(button);
const leftPercent = (100 / (self.$jsAlign.length - 1)) * index;
const leftPercentCssValue = `${leftPercent}%`;
const buttonOffset = -1 * ($button.innerWidth() / 2);
$button.css({
left: leftPercentCssValue,
marginLeft: buttonOffset,
});
// First and last buttons are kept within userform-progress container
if (index === self.$jsAlign.length - 1) {
$button.css({ marginLeft: buttonOffset * 2 });
} else if (index === 0) {
$button.css({ marginLeft: 0 });
}
});
return this;
this.update(0);
}
/**
* @func ProgressBar.update
* @param {number} stepID - Zero based index of the new step.
* @desc Update the progress element to show a new step.
*/
ProgressBar.prototype.update = function update(stepID) {
const $newStepElement = $(this.$el.parent('.userform').find('.form-step')[stepID]);
let stepNumber = 0;
let barWidth = (stepID / (this.$buttons.length - 1)) * 100;
update(stepId) {
const stepNumber = this.userForm.getCurrentStepID() + 1;
const newStep = this.userForm.getStep(stepId);
const newStepElement = newStep.step;
let barWidth = (stepId / (this.buttons.length - 1)) * 100;
// Set the current step number.
this.$buttons.each((i, button) => {
if (i > stepID) {
// Break the loop
return false;
this.currentStepNumber.innerText = stepNumber;
this.dom.querySelectorAll('[aria-valuenow]').forEach((e) => {
e.setAttribute('aria-valuenow', stepNumber);
});
this.buttons.forEach((button) => {
const btn = button;
const parent = btn.parentNode;
if (parseInt(btn.getAttribute('data-step'), 10) === stepNumber
&& isVisible(btn)) {
parent.classList.add('current');
parent.classList.add('viewed');
btn.disabled = false;
}
if ($(button).is(':visible')) {
stepNumber += 1;
}
return true;
parent.classList.remove('current');
});
// Update elements that contain the current step number.
this.$el.find('.current-step-number').each((i, element) => {
$(element).text(stepNumber);
});
// Update aria attributes.
this.$el.find('[aria-valuenow]').each((i, element) => {
$(element).attr('aria-valuenow', stepNumber);
});
// Update the CSS classes on step buttons.
this.$buttons.each((i, element) => {
const $element = $(element);
const $item = $element.parent();
if (parseInt($element.data('step'), 10) === stepNumber && $element.is(':visible')) {
$item.addClass('current viewed');
$element.removeAttr('disabled');
return;
}
$item.removeClass('current');
});
// Update the progress bar's title with the new step's title.
this.$el.siblings('.progress-title').text($newStepElement.data('title'));
this.progressTitle.innerText = newStepElement.getAttribute('data-title');
// Update the width of the progress bar.
barWidth = barWidth ? `${barWidth}%` : '';
this.$el.find('.progress-bar').width(barWidth);
};
this.dom.querySelector('.progress-bar').style.width = barWidth;
}
}
/**
* @func FormActions
* @constructor
* @param {object} element
* @desc Creates the navigation and actions (Prev, Next, Submit buttons).
*/
function FormActions(element) {
const self = this;
class FormStep {
constructor(step, userForm) {
this.step = step;
this.userForm = userForm;
this.viewed = false;
this.buttonHolder = null;
this.id = 0;
this.$el = element instanceof $ ? element : $(element);
const $elFormItself = this.$el.closest('.userform');
this.userformInstance = $elFormItself.data('inst');
this.$prevButton = this.$el.find('.step-button-prev');
this.$nextButton = this.$el.find('.step-button-next');
// Show the buttons.
this.$prevButton.parent().attr('aria-hidden', false).show();
this.$nextButton.parent().attr('aria-hidden', false).show();
// Scroll up to the next page...
const scrollUpFx = function () {
const scrollTop = $elFormItself.offset();
$('html, body').animate({ scrollTop: scrollTop.top }, 'slow');
};
// Bind the step navigation event listeners.
this.$prevButton.on('click', (e) => {
e.preventDefault();
scrollUpFx();
self.$el.trigger('userform.action.prev');
});
this.$nextButton.on('click', (e) => {
e.preventDefault();
scrollUpFx();
self.$el.trigger('userform.action.next');
});
// Listen for changes to the current form step, or conditional pages,
// so we can show hide buttons appropriately.
this.userformInstance.$el.on('userform.form.changestep userform.form.conditionalstep', () => {
self.update();
});
return this;
this.init();
}
/**
* @func FormActions.update
* @param {number} stepID - Zero based ID of the current step.
* @desc Updates the form actions element to reflect the current state of the page.
*/
FormActions.prototype.update = function update() {
const numberOfSteps = this.userformInstance.steps.length;
const stepID = this.userformInstance.currentStep ? this.userformInstance.currentStep.id : 0;
init() {
const id = this.getHTMLId();
this.buttonHolder = document.querySelector(`.step-button-wrapper[data-for='${id}']`);
if (this.buttonHolder) {
['userform.field.hide', 'userform.field.show'].forEach((action) => {
this.buttonHolder.addEventListener(action, () => {
this.userForm.dom.trigger('userform.form.conditionalstep');
});
});
}
}
setId(id) {
this.id = id;
}
getHTMLId() {
return this.step.getAttribute('id');
}
show() {
this.step.setAttribute('aria-hidden', false);
this.step.classList.remove('hide');
this.step.classList.add('viewed');
this.viewed = true;
}
hide() {
this.step.setAttribute('aria-hidden', true);
this.step.classList.add('hide');
}
conditionallyHidden() {
const button = this.buttonHolder.querySelector('button');
return !(button.style.display !== 'none' && button.visibility !== 'hidden' && !button.classList.contains('hide'));
}
getValidatorType(input) {
if (input.getAttribute('type') === 'email') {
return 'email';
}
if (input.getAttribute('type') === 'date') {
return 'date';
}
if (input.getAttribute('type') === 'file') {
return 'object';
}
if (input.classList.contains('numeric') || input.getAttribute('type') === 'numeric') {
return 'number';
}
return 'string';
}
getValidatorMessage(input) {
if (input.getAttribute('data-msg-required')) {
return input.getAttribute('data-msg-required');
}
return `${this.getFieldLabel(input)} is required`;
}
getHolderForField(input) {
return window.closest(input, '.field');
}
getFieldLabel(input) {
const holder = this.getHolderForField(input);
if (holder) {
const label = holder.querySelector('label.left, legend.left');
if (label) {
return label.innerText;
}
}
return input.getAttribute('name');
}
isInputNumeric(input) {
return this.getValidatorType(input) === 'number';
}
isInputFile(input) {
return input.getAttribute('type') === 'file';
}
getInputByName(name) {
return this.step.querySelector(`input[name="${name}"]`);
}
getValidationsDescriptors(onlyDirty) {
const descriptors = {};
const fields = this.step.querySelectorAll('input, textarea, select');
fields.forEach((field) => {
if (isVisible(field)
&& (!onlyDirty || (onlyDirty && field.classList.contains(FOCUSED_CLASS)))
) {
const label = this.getFieldLabel(field);
const holder = this.getHolderForField(field);
descriptors[field.getAttribute('name')] = {
title: label,
type: this.getValidatorType(field),
required: holder.classList.contains('requiredField'),
message: this.getValidatorMessage(field)
};
const min = field.getAttribute('data-rule-min');
const max = field.getAttribute('data-rule-max');
if (min !== null || max !== null) {
descriptors[field.getAttribute('name')].asyncValidator = function numericValidator(rule, value) {
return new Promise((resolve, reject) => {
if (min !== null && value < min) {
reject(`${label} cannot be less than ${min}`);
} else if (max !== null && value > max) {
reject(`${label} cannot be greater than ${max}`);
} else {
resolve();
}
});
};
}
const minL = field.getAttribute('data-rule-minlength');
const maxL = field.getAttribute('data-rule-maxlength');
if (minL !== null || maxL !== null) {
descriptors[field.getAttribute('name')].asyncValidator = function lengthValidator(rule, value) {
return new Promise((resolve, reject) => {
if (minL !== null && value.length < minL) {
reject(`${label} cannot be shorter than ${minL}`);
} else if (maxL !== null && value.length > maxL) {
reject(`${label} cannot be longer than ${maxL}`);
} else {
resolve();
}
});
};
}
}
});
return descriptors;
}
validate(onlyDirty) {
const descriptors = this.getValidationsDescriptors(onlyDirty);
if (Object.keys(descriptors).length) {
const validator = new Schema(descriptors);
const formData = new FormData(this.userForm.dom);
const data = {};
formData.forEach((value, key) => {
let sanitised = value;
const input = this.getInputByName(key);
if (sanitised && input && this.isInputNumeric(input)) {
sanitised = parseFloat(sanitised); // because FormData reads all the values as strings
}
data[key] = sanitised;
});
// now check for unselected checkboxes and radio buttons
const selectableFields = this.step.querySelectorAll('input[type="radio"],input[type="checkbox"]');
selectableFields.forEach((selectableField) => {
const fieldName = selectableField.getAttribute('name');
if (typeof data[fieldName] === 'undefined') {
data[fieldName] = '';
}
});
const promise = new Promise((resolve, reject) => {
validator.validate(data, (errors) => {
if (errors && errors.length) {
this.displayErrorMessages(errors);
reject(errors);
} else {
this.displayErrorMessages([]);
resolve();
}
});
});
return promise;
}
const promise = new Promise((resolve) => {
resolve();
});
return promise;
}
enableLiveValidation() {
const fields = this.step.querySelectorAll('input, textarea, select');
fields.forEach((field) => {
field.addEventListener('focusin', () => {
field.classList.add(FOCUSED_CLASS);
});
field.addEventListener('change', () => {
field.classList.add(DIRTY_CLASS);
});
field.addEventListener('focusout', () => {
this.validate(true).then(() => {
}).catch(() => {
});
});
});
}
displayErrorMessages(errors) {
const errorIds = [];
errors.forEach((error) => {
const fieldHolder = this.userForm.dom.querySelector(`#${error.field}`);
if (fieldHolder) {
let errorLabel = fieldHolder.querySelector('span.error');
if (!errorLabel) {
errorLabel = document.createElement('span');
errorLabel.classList.add('error');
errorLabel.setAttribute('data-id', error.field);
}
errorIds.push(error.field);
errorLabel.innerHTML = error.message;
fieldHolder.append(errorLabel);
}
});
// remove any thats not required
const messages = this.step.querySelectorAll('span.error');
messages.forEach((mesasge) => {
const id = mesasge.getAttribute('data-id');
if (errorIds.indexOf(id) === -1) {
mesasge.remove();
}
});
}
}
class FormActions {
constructor(dom, userForm) {
this.dom = dom;
this.userForm = userForm;
this.prevButton = dom.querySelector('.step-button-prev');
this.nextButton = dom.querySelector('.step-button-next');
this.init();
}
init() {
this.prevButton.addEventListener('click', (e) => {
e.preventDefault();
// scrollUpFx();
window.triggerDispatchEvent(this.userForm.dom, 'userform.action.prev');
});
this.nextButton.addEventListener('click', (e) => {
e.preventDefault();
// scrollUpFx();
window.triggerDispatchEvent(this.userForm.dom, 'userform.action.next');
});
this.update();
this.userForm.dom.addEventListener('userform.form.changestep', () => {
this.update();
});
this.userForm.dom.addEventListener('userform.form.conditionalstep', () => {
this.update();
});
}
update() {
const numberOfSteps = this.userForm.getNumberOfSteps();
const stepId = this.userForm.getCurrentStepID();
let i = null;
let lastStep = null;
// Update the "Prev" button.
this.$el.find('.step-button-prev')[stepID === 0 ? 'hide' : 'show']();
// Find last step, skipping hidden ones
for (i = numberOfSteps - 1; i >= 0; i--) {
lastStep = this.userformInstance.steps[i];
// Skip if step is hidden
lastStep = this.userForm.getStep(i);
if (!lastStep.conditionallyHidden()) {
// Update the "Next" button.
this.$el.find('.step-button-next')[stepID >= i ? 'hide' : 'show']();
if (stepId >= i) {
this.nextButton.parentNode.classList.add('hide');
} else {
this.nextButton.parentNode.classList.remove('hide');
}
// Update the "Actions".
this.$el.find('.btn-toolbar')[stepID >= i ? 'show' : 'hide']();
if (stepId > 0 && stepId <= i) {
this.prevButton.parentNode.classList.remove('hide');
} else {
this.prevButton.parentNode.classList.add('hide');
}
if (stepId >= i) {
this.dom.querySelector('.btn-toolbar').classList.remove('hide');
} else {
this.dom.querySelector('.btn-toolbar').classList.add('hide');
}
// Stop processing last step
break;
}
}
};
}
}
/**
* @func UserForm
* @constructor
* @param {object} element
* @return {object} - The UserForm instance.
* @desc The form
*/
function UserForm(element) {
const self = this;
this.$el = element instanceof $ ? element : $(element);
class UserForm {
constructor(form) {
this.dom = form;
this.CONSTANTS = {}; // Settings that come from the CMS.
this.steps = [];
this.progressBar = null;
this.actions = null;
this.currentStep = null;
// Add an error container which displays a list of invalid steps on form submission.
this.errorContainer = new ErrorContainer(this.$el.children('.error-container'));
// Listen for events triggered by form steps.
this.$el.on('userform.action.prev', () => {
self.prevStep();
});
this.$el.on('userform.action.next', () => {
self.nextStep();
});
// Listen for events triggered by the progress bar.
this.$el.find('.userform-progress').on('userform.progress.changestep', (e, stepNumber) => {
self.jumpToStep(stepNumber - 1);
});
// When a field becomes valid, remove errors from the error container.
this.$el.on('userform.form.valid', (e, fieldId) => {
self.errorContainer.removeStepLink(fieldId);
});
this.$el.validate(this.validationOptions);
// Ensure checkbox groups are validated correctly
this.$el.find('.optionset.requiredField input').each((a, field) => {
$(field).rules('add', {
required: true,
});
});
return this;
this.CONSTANTS.ENABLE_LIVE_VALIDATION = this.dom.getAttribute('livevalidation') !== undefined;
this.CONSTANTS.DISPLAY_ERROR_MESSAGES_AT_TOP = this.dom.getAttribute('toperrors') !== undefined;
this.CONSTANTS.ENABLE_ARE_YOU_SURE = this.dom.getAttribute('enableareyousure') !== undefined;
}
/*
* Default options for step validation. These get extended in main().
*/
UserForm.prototype.validationOptions = {
ignore: ':hidden,ul',
errorClass: 'error',
errorElement: 'span',
errorPlacement: (error, element) => {
error.addClass('message');
init() {
this.initialiseFormSteps();
if (element.is(':radio') || element.parents('.checkboxset').length > 0) {
error.appendTo(element.closest('.middleColumn, .field'));
} else if (element.parents('.checkbox').length > 0) {
error.appendTo(element.closest('.field'));
} else {
error.insertAfter(element);
if (this.CONSTANTS.ENABLE_ARE_YOU_SURE) {
this.initAreYouSure();
}
}
initialiseFormSteps() {
const steps = this.dom.querySelectorAll('.form-step');
steps.forEach((stepDom) => {
const step = new FormStep(stepDom, this);
step.hide();
this.addStep(step);
if (this.CONSTANTS.ENABLE_LIVE_VALIDATION) {
step.enableLiveValidation();
}
},
invalidHandler: (event, validator) => {
// setTimeout 0 so it runs after errorPlacement
setTimeout(() => {
validator.currentElements.filter('.error').first().focus();
}, 0);
},
// Callback for handling the actual submit when the form is valid.
// Submission in the jQuery.validate sence is handled at step level.
// So when the final step is submitted we have to also check all previous steps are valid.
submitHandler: (form) => {
let isValid = true;
const userform = $(form).closest('.userform').data('inst');
});
// Validate the current step
if (userform.currentStep) {
userform.currentStep.valid = $(form).valid();
}
this.setCurrentStep(this.steps[0]);
// Check for invalid previous steps.
$.each(userform.steps, (i, step) => {
if (!step.valid && !step.conditionallyHidden()) {
isValid = false;
userform.errorContainer.addStepLink(step);
const progressBarDom = this.dom.querySelector('.userform-progress');
if (progressBarDom) {
this.progressBar = new ProgressBar(progressBarDom, this);
}
const stepNavigation = this.dom.querySelector('.step-navigation');
if (stepNavigation) {
this.formActions = new FormActions(stepNavigation, this);
this.formActions.update();
}
this.setUpPing();
this.dom.addEventListener('userform.action.next', () => {
this.nextStep();
});
this.dom.addEventListener('userform.action.prev', () => {
this.prevStep();
});
this.dom.addEventListener('submit', (e) => {
this.validateForm(e);
});
}
validateForm(e) {
e.preventDefault();
this.currentStep.validate()
.then((errors) => {
if (!errors) {
this.dom.submit();
}
});
})
.catch(() => {});
}
if (isValid) {
// Remove required attributes on hidden fields
const hiddenInputs = $(form).find('.field.requiredField.hide input');
if (hiddenInputs.length > 0) {
hiddenInputs.removeAttr('required aria-required data-rule-required').valid();
}
// When using the "are you sure?" plugin, ensure the form immediately submits.
$(form).removeClass('dirty');
form.submit();
userform.$el.trigger('userform.form.submit');
} else {
userform.errorContainer.show();
}
},
// When a field becomes valid.
success: (error) => {
const userform = $(error).closest('.userform').data('inst');
const errorId = $(error).attr('id');
const fieldId = errorId.substr(0, errorId.indexOf('-error')).replace(/[\\[\\]]/, '');
// Remove square brackets since jQuery.validate.js uses idOrName,
// which breaks further on when using a selector that end with
// square brackets.
error.remove();
// Pass the field's ID with the event
userform.$el.trigger('userform.form.valid', [fieldId]);
},
};
/**
* @func UserForm.addStep
* @param {object} step - An instance of FormStep.
* @desc Adds a step to the UserForm.
*/
UserForm.prototype.addStep = function addStep(step) {
setCurrentStep(step) {
// Make sure we're dealing with a form step.
if (!(step instanceof FormStep)) {
return;
}
// eslint-disable-next-line no-param-reassign
step.id = this.steps.length;
this.steps.push(step);
};
/**
* @func UserForm.setCurrentStep
* @param {object} step - An instance of FormStep.
* @desc Sets the step the user is currently on.
*/
UserForm.prototype.setCurrentStep = function setCurrentStep(step) {
// Make sure we're dealing with a form step.
if (!(step instanceof FormStep)) {
return;
}
this.currentStep = step;
this.currentStep.show();
}
// Record the user has viewed the step.
this.currentStep.viewed = true;
this.currentStep.$el.addClass('viewed');
};
addStep(step) {
if (!(step instanceof FormStep)) {
return;
}
step.setId(this.steps.length);
this.steps.push(step);
}
/**
* @func UserForm.jumpToStep
* @param {number} stepNumber
* @param {boolean} [direction] - Defaults to forward (true).
* @desc Jumps to a specific form step.
*/
UserForm.prototype.jumpToStep = function jumpToStep(stepNumber, direction) {
getNumberOfSteps() {
return this.steps.length;
}
getCurrentStepID() {
return this.currentStep.id ? this.currentStep.id : 0;
}
getStep(index) {
return this.steps[index];
}
nextStep() {
this.currentStep.validate().then(() => {
this.jumpToStep(this.steps.indexOf(this.currentStep) + 1, true);
}).catch(() => {});
}
prevStep() {
this.jumpToStep(this.steps.indexOf(this.currentStep) - 1, true);
}
jumpToStep(stepNumber, direction) {
const targetStep = this.steps[stepNumber];
let isValid = false;
const forward = direction === undefined ? true : direction;
// Make sure the target step exists.
if (targetStep === undefined) {
return;
}
// Make sure the step we're trying to set as current is not
// hidden by custom display rules. If it is then jump to the next step.
if (targetStep.conditionallyHidden()) {
if (forward) {
this.jumpToStep(stepNumber + 1, direction);
} else {
this.jumpToStep(stepNumber - 1, direction);
}
return;
}
// Validate the form.
// This well effectivly validate the current step and not the entire form.
// This is because hidden fields are excluded from validation, and all fields
// on all other steps, are currently hidden.
isValid = this.$el.valid();
// Set the 'valid' property on the current step.
this.currentStep.valid = isValid;
// Users can navigate to step's they've already viewed even if the current step is invalid.
if (isValid === false && targetStep.viewed === false) {
return;
if (this.currentStep) {
this.currentStep.hide();
}
this.currentStep.hide();
this.setCurrentStep(targetStep);
this.$el.trigger('userform.form.changestep', [targetStep.id]);
};
/**
* @func UserForm.nextStep
* @desc Advances the form to the next step.
*/
UserForm.prototype.nextStep = function nextStep() {
this.jumpToStep(this.steps.indexOf(this.currentStep) + 1, true);
};
/**
* @func UserForm.prevStep
* @desc Goes back one step (not bound to browser history).
*/
UserForm.prototype.prevStep = function prevStep() {
this.jumpToStep(this.steps.indexOf(this.currentStep) - 1, false);
};
/**
* @func main
* @desc Bootstraps the front-end.
*/
function main(index, userformElement) {
const $userform = $(userformElement);
// If there's no userform, do nothing.
if ($userform.length === 0) {
return;
}
CONSTANTS.ENABLE_LIVE_VALIDATION = $userform.data('livevalidation') !== undefined;
CONSTANTS.DISPLAY_ERROR_MESSAGES_AT_TOP = $userform.data('toperrors') !== undefined;
// Extend the default validation options with conditional options
// that are set by the user in the CMS.
if (CONSTANTS.ENABLE_LIVE_VALIDATION === false) {
$.extend(UserForm.prototype.validationOptions, {
onfocusout: false,
});
}
if (CONSTANTS.DISPLAY_ERROR_MESSAGES_AT_TOP) {
$.extend(UserForm.prototype.validationOptions, {
// Callback for custom code when an invalid form / step is submitted.
invalidHandler: (event, validator) => {
$userform.trigger('userform.form.error', [validator]);
},
onfocusout: false,
});
}
// Display all the things that are hidden when JavaScript is disabled.
$userform.find('.userform-progress, .step-navigation').attr('aria-hidden', false).show();
// Extend classes with common functionality.
$.extend(FormStep.prototype, commonMixin);
$.extend(ErrorContainer.prototype, commonMixin);
const userform = new UserForm($userform);
$userform.data('inst', userform);
// Conditionally hide field labels and use HTML5 placeholder instead.
if (CONSTANTS.HIDE_FIELD_LABELS) {
$userform.find('label.left').each(() => {
const $label = $(this);
$(`[name="${$label.attr('for')}"]`).attr('placeholder', $label.text());
$label.remove();
});
}
// Initialise the form steps.
userform.$el.find('.form-step').each((i, element) => {
const step = new FormStep(element);
userform.addStep(step);
window.triggerDispatchEvent(this.dom, 'userform.form.changestep', {
stepId: targetStep.id
});
userform.setCurrentStep(userform.steps[0]);
// Initialise actions and progressbar
const $progressEl = $userform.find('.userform-progress');
if ($progressEl.length) {
const progressBar = new ProgressBar($progressEl);
progressBar.update(0);
}
const $formActionsEl = $userform.find('.step-navigation');
if ($formActionsEl.length) {
const formActions = new FormActions($formActionsEl);
formActions.update();
}
// Enable jQuery UI datepickers
$(document).on('click', 'input.text[data-showcalendar]', () => {
const $element = $(this);
$element.ssDatepicker();
if ($element.data('datepicker')) {
$element.datepicker('show');
}
});
// Make sure the form doesn't expire on the user. Pings every 3 mins.
setInterval(() => {
$.ajax({ url: 'UserDefinedFormController/ping' });
}, 180 * 1000);
// Bind a confirmation message when navigating away from a partially completed form.
if (typeof $userform.areYouSure !== 'undefined') {
$userform.areYouSure({
message: i18n._t('UserForms.LEAVE_CONFIRMATION', 'You have unsaved changes!'),
});
}
}
$('.userform').each(main);
setUpPing() {
// Make sure the form doesn't expire on the user. Pings every 3 mins.
window.setInterval(() => {
fetch('UserDefinedFormController/ping');
}, 180 * 1000);
}
doConfirm(e) {
const dirtyFields = this.dom.querySelectorAll(`.${DIRTY_CLASS}`);
if (dirtyFields.length === 0) {
return true;
}
if (navigator.userAgent.toLowerCase().match(/msie|chrome/)) {
if (window.hasUserFormsPropted) {
return true;
}
window.hasUserFormsPropted = true;
window.setTimeout(
() => {
window.hasUserFormsPropted = false;
},
900
);
}
e.preventDefault();
if (typeof window.i18n !== 'undefined') {
event.returnValue = window.i18n._t('UserForms.LEAVE_CONFIRMATION', 'You have unsaved changes!');
} else {
event.returnValue = 'You have unsaved changes!';
}
return true;
}
initAreYouSure() {
const confirmFunction = this.doConfirm.bind(this);
this.dom.addEventListener('submit', (e) => {
window.removeEventListener('beforeunload', confirmFunction);
})
window.addEventListener('beforeunload', confirmFunction);
}
}
document.addEventListener('DOMContentLoaded', () => {
const forms = document.querySelectorAll('form.userform');
forms.forEach((form) => {
const userForm = new UserForm(form);
userForm.init();
});
});

View File

@ -15,6 +15,10 @@
.step-buttons {
margin-left: 0;
padding-left: 0;
width: 100%;
display: flex;
justify-content: space-between;
position: relative;
}
@ -28,8 +32,6 @@
}
.step-button-jump {
position: absolute;
top: 0;
opacity: .7;
}
}

View File

@ -79,22 +79,11 @@ class UserDefinedFormController extends PageController
// load the jquery
if (!$page->config()->get('block_default_userforms_js')) {
Requirements::javascript('silverstripe/userforms:client/dist/js/jquery.min.js');
Requirements::javascript(
'silverstripe/userforms:client/dist/js/jquery-validation/jquery.validate.min.js'
);
Requirements::javascript('silverstripe/admin:client/dist/js/i18n.js');
Requirements::add_i18n_javascript('silverstripe/userforms:client/lang');
Requirements::javascript('silverstripe/userforms:client/dist/js/userforms.js');
$this->addUserFormsValidatei18n();
// Bind a confirmation message when navigating away from a partially completed form.
if ($page::config()->get('enable_are_you_sure')) {
Requirements::javascript(
'silverstripe/userforms:client/dist/js/jquery.are-you-sure/jquery.are-you-sure.js'
);
}
}
}
@ -177,10 +166,16 @@ class UserDefinedFormController extends PageController
*/
public function Form()
{
$page = $this->data();
$form = UserForm::create($this, 'Form_' . $this->ID);
/** @skipUpgrade */
$form->setFormAction(Controller::join_links($this->Link(), 'Form'));
$this->generateConditionalJavascript();
if ($page::config()->get('enable_are_you_sure')) {
$form->setAttribute('enableareyousure', 1);
}
return $form;
}
@ -212,14 +207,35 @@ class UserDefinedFormController extends PageController
$rules .= $this->buildWatchJS($watch);
}
// add the custom scripts thats used by the steps.
Requirements::customScript(<<<JS
function closest(el, sel) {
while ((el = el.parentElement) && !((el.matches || el.matchesSelector).call(el,sel)));
return el;
}
window.closest = closest;
function triggerDispatchEvent(element, eventName, arg) {
const event = new CustomEvent(eventName, {
detail: arg
});
element.dispatchEvent(event);
}
window.triggerDispatchEvent = triggerDispatchEvent;
JS
);
// Only add customScript if $default or $rules is defined
if ($rules) {
Requirements::customScript(<<<JS
(function($) {
$(document).ready(function() {
document.addEventListener("DOMContentLoaded", function() {
var form = document.querySelector('form.userform');
if (form) {
{$rules}
});
})(jQuery);
}
})
JS
, 'UserFormsConditional-' . $form->ID);
}
@ -626,10 +642,11 @@ JS
*/
protected function buildWatchJS($watch)
{
$result = '';
foreach ($watch as $key => $rule) {
$events = implode(' ', $rule['events']);
$selectors = implode(', ', $rule['selectors']);
$events = implode(',', $rule['events']);
$selectors = implode(',', $rule['selectors']);
$conjunction = $rule['conjunction'];
$operations = implode(" {$conjunction} ", $rule['operations']);
$target = $rule['targetFieldID'];
@ -638,16 +655,21 @@ JS
$result .= <<<EOS
\n
$('.userform').on('{$events}',
"{$selectors}",
function (){
if ({$operations}) {
$('{$target}').{$rule['view']};
{$holder}.{$rule['view']}.trigger('{$rule['holder_event']}');
} else {
$('{$target}').{$rule['opposite']};
{$holder}.{$rule['opposite']}.trigger('{$rule['holder_event_opposite']}');
}
"{$events}".split(',').forEach(function(event) {
form.addEventListener(event, function(e) {
"{$selectors}".split(',').forEach(function(selector) {
if (e.target.matches(selector)) {
if ({$operations}) {
document.querySelector('{$target}').{$rule['view']};
triggerDispatchEvent({$holder}, '{$rule['holder_event']}');
} else {
document.querySelector('{$target}').{$rule['opposite']};
triggerDispatchEvent({$holder}, '{$rule['holder_event_opposite']}');
}
}
})
});
});
EOS;
if ($isFormStep) {
@ -657,7 +679,7 @@ EOS;
// The HTML for the FormStep buttons is defined in UserFormProgress.ss
$id = str_replace('#', '', $target ?? '');
$result .= <<<EOS
$('.step-button-wrapper[data-for="{$id}"]').addClass('hide');
document.querySelector('.step-button-wrapper[data-for="{$id}"]').addClass('hide');
EOS;
} else {
// If a field's initial state is set to be hidden, a '.hide' class will be added to the field as well
@ -666,7 +688,9 @@ EOS;
// though we need to ensure we don't do this on FormSteps (page breaks) otherwise we'll mistakenly
// target fields contained within the formstep
$result .= <<<EOS
$("{$target}").find('.hide').removeClass('hide');
if (document.querySelector('{$target}').querySelector('.hide')) {
document.querySelector('{$target}').querySelector('.hide').classList.remove('hide');
}
EOS;
}
}

View File

@ -160,7 +160,7 @@ class EditableCustomRule extends DataObject
// is this field a special option field
$checkboxField = $formFieldWatch->isCheckBoxField();
$radioField = $formFieldWatch->isRadioField();
$target = sprintf('$("%s")', $formFieldWatch->getSelectorFieldOnly());
$target = $formFieldWatch->getSelectorFieldOnly();
$fieldValue = Convert::raw2js($this->FieldValue);
$conditionOptions = [
@ -174,7 +174,9 @@ class EditableCustomRule extends DataObject
switch ($this->ConditionOption) {
case 'IsNotBlank':
case 'IsBlank':
$expression = ($checkboxField || $radioField) ? "!{$target}.is(\":checked\")" : "{$target}.val() == ''";
$expression = ($checkboxField || $radioField)
? sprintf("document.querySelector(\"%s:checked\") !== null", $target)
: "document.querySelector(\"{$target}\").value == ''";
if ((string) $this->ConditionOption === 'IsNotBlank') {
//Negate
$expression = "!({$expression})";
@ -185,9 +187,9 @@ class EditableCustomRule extends DataObject
if ($checkboxField) {
if ($formFieldWatch->isCheckBoxGroupField()) {
$expression = sprintf(
"$.inArray('%s', %s.filter(':checked').map(function(){ return $(this).val();}).get()) > -1",
'[...document.querySelectorAll("%s:checked")].map(function(i) { return i ? i.getAttribute("value") : null; }).indexOf(\'%s\') > -1',
$target,
$fieldValue,
$target
);
} else {
$expression = "{$target}.prop('checked')";
@ -195,12 +197,12 @@ class EditableCustomRule extends DataObject
} elseif ($radioField) {
// We cannot simply get the value of the radio group, we need to find the checked option first.
$expression = sprintf(
'%s.closest(".field, .control-group").find("input:checked").val() == "%s"',
'closest(document.querySelector("%s"), ".field, .control-group").querySelector("input:checked").value == "%s"',
$target,
$fieldValue
);
} else {
$expression = sprintf('%s.val() == "%s"', $target, $fieldValue);
$expression = sprintf('document.querySelector("%s").value == "%s"', $target, $fieldValue);
}
if ((string) $this->ConditionOption === 'ValueNot') {
@ -213,7 +215,7 @@ class EditableCustomRule extends DataObject
case 'ValueGreaterThan':
case 'ValueGreaterThanEqual':
$expression = sprintf(
'%s.val() %s parseFloat("%s")',
'document.querySelector("%s").value %s parseFloat("%s")',
$target,
$conditionOptions[$this->ConditionOption],
$fieldValue
@ -299,11 +301,11 @@ class EditableCustomRule extends DataObject
*/
public function toggleDisplayText($initialState, $invert = false)
{
$action = strtolower($initialState ?? '') === 'hide' ? 'removeClass' : 'addClass';
$action = strtolower($initialState ?? '') === 'hide' ? 'remove' : 'add';
if ($invert) {
$action = $action === 'removeClass' ? 'addClass' : 'removeClass';
$action = $action === 'remove' ? 'add' : 'remove';
}
return sprintf('%s("hide")', $action);
return sprintf('classList.%s("hide")', $action);
}
/**

View File

@ -868,7 +868,7 @@ class EditableFormField extends DataObject
*/
public function getSelectorHolder()
{
return sprintf('$("%s")', $this->getSelectorOnly());
return sprintf('document.querySelector("%s")', $this->getSelectorOnly());
}
/**
@ -891,7 +891,7 @@ class EditableFormField extends DataObject
*/
public function getSelectorField(EditableCustomRule $rule, $forOnLoad = false)
{
return sprintf("$(%s)", $this->getSelectorFieldOnly());
return sprintf("document.querySelector(%s)", $this->getSelectorFieldOnly());
}
/**

View File

@ -48,7 +48,7 @@ class EditableFieldGroup extends EditableFormField
public function getCMSFields()
{
$this->beforeUpdateCMSFields(function (FieldList $fields) {
$fields->removeByName(['MergeField', 'Default', 'Validation', 'DisplayRules']);
$fields->removeByName(['MergeField', 'Default', 'Validation']);
});
return parent::getCMSFields();
@ -98,5 +98,10 @@ class EditableFieldGroup extends EditableFormField
if ($this->ExtraClass) {
$field->addExtraClass($this->ExtraClass);
}
// if ShowOnLoad is false hide the field
if (!$this->ShowOnLoad) {
$field->addExtraClass($this->ShowOnLoadNice());
}
}
}

View File

@ -37,10 +37,10 @@
"node-dir": "^0.1.17"
},
"dependencies": {
"babel-preset-es2016": "^6.24.1",
"jquery": "^3.5.0",
"jquery-validation": "^1.19.5",
"jquery.are-you-sure": "^1.9.0",
"babel-preset-es2016": "^6.24.1",
"validator": "13.9.0",
"async-validator": "4.2.5",
"mime": "^1.4.1",
"qs": "^6.9.4",
"react": "^16.13.1",

View File

@ -1,19 +1,21 @@
<% if $Steps.Count > 1 %>
<div id="userform-progress" class="userform-progress" aria-hidden="true" style="display:none;">
<p>Page <span class="current-step-number">1</span> of <span class="total-step-number">$Steps.Count</span></p>
<div class="progress">
<div class="progress-bar" role="progressbar" aria-valuenow="1" aria-valuemin="1" aria-valuemax="$Steps.Count"></div>
</div>
<nav aria-label="Pages in this form">
<ul class="step-buttons">
<% loop $Steps %>
<li class="step-button-wrapper<% if $IsFirst %> current<% end_if %>" data-for="$Name">
<%-- Remove js-align class to remove javascript positioning --%>
<button class="step-button-jump js-align" disabled="disabled" data-step="$Pos"><% if $Top.ButtonText %>$Top.ButtonText <% end_if %>$Pos</button>
</li>
<% end_loop %>
</ul>
</nav>
<div class="userform-progress-navigator">
<div class="progress">
<div class="progress-bar" role="progressbar" aria-valuenow="1" aria-valuemin="1" aria-valuemax="$Steps.Count"></div>
</div>
<nav aria-label="Pages in this form">
<ul class="step-buttons">
<% loop $Steps %>
<li class="step-button-wrapper<% if $IsFirst %> current<% end_if %>" data-for="$Name">
<%-- Remove js-align class to remove javascript positioning --%>
<button class="step-button-jump js-align" disabled="disabled" data-step="$Pos"><% if $Top.ButtonText %>$Top.ButtonText <% end_if %>$Pos</button>
</li>
<% end_loop %>
</ul>
</nav>
</div>
</div>
<h2 class="progress-title"></h2>
<% end_if %>

View File

@ -4,12 +4,12 @@
If JavaScript is disabled multi-step forms are displayed as a single page
so the 'prev' and 'next' button are not used. These buttons are made visible via JavaScript.
--%>
<li class="step-button-wrapper" aria-hidden="true" style="display:none;">
<li class="step-button-wrapper hide" aria-hidden="true">
<button class="step-button-prev">
<%t SilverStripe\\UserForms\\Model\\EditableFormField\\EditableFormStep.STEP_PREV "Prev" %>
</button>
</li>
<li class="step-button-wrapper" aria-hidden="true" style="display:none;">
<li class="step-button-wrapper hide" aria-hidden="true">
<button class="step-button-next">
<%t SilverStripe\\UserForms\\Model\\EditableFormField\\EditableFormStep.STEP_NEXT "Next" %>
</button>

View File

@ -1,4 +1,6 @@
<$Tag class="CompositeField $extraClass<% if $ColumnCount %> multicolumn<% end_if %>"<% if $Tag == 'fieldset' && $RightTitle %> aria-describedby="{$Name}_right_title"<% end_if %>>
<$Tag id="{$Name}"
class="CompositeField $extraClass<% if $ColumnCount %> multicolumn<% end_if %>"<% if $Tag == 'fieldset' && $RightTitle %>
aria-describedby="{$Name}_right_title"<% end_if %>>
<% if $Tag == 'fieldset' && $Legend %>
<legend>$Legend</legend>
<% end_if %>

View File

@ -28,15 +28,7 @@ const copyData = [
{
from: 'client/src/images',
to: 'images'
},
{
from: PATHS.MODULES + '/jquery/dist/jquery.min.js',
to: PATHS.DIST_JS
},
{
from: PATHS.MODULES + '/jquery.are-you-sure/jquery.are-you-sure.js',
to: PATHS.DIST_JS + '/jquery.are-you-sure/jquery.are-you-sure.js'
},
}
];
/**
@ -60,7 +52,6 @@ const addMinFiles = (from, to) => {
});
};
addMinFiles('/jquery-validation/dist', '/jquery-validation');
const config = [

View File

@ -463,6 +463,11 @@ async-limiter@~1.0.0:
resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd"
integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==
async-validator@4.2.5:
version "4.2.5"
resolved "https://registry.yarnpkg.com/async-validator/-/async-validator-4.2.5.tgz#c96ea3332a521699d0afaaceed510a54656c6339"
integrity sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==
async@^2.1.2:
version "2.6.4"
resolved "https://registry.yarnpkg.com/async/-/async-2.6.4.tgz#706b7ff6084664cd7eae713f6f965433b5504221"
@ -4313,22 +4318,10 @@ isstream@~0.1.2:
resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=
jquery-validation@^1.19.5:
version "1.19.5"
resolved "https://registry.yarnpkg.com/jquery-validation/-/jquery-validation-1.19.5.tgz#557495b7cad79716897057c4447ad3cd76fda811"
integrity sha512-X2SmnPq1mRiDecVYL8edWx+yTBZDyC8ohWXFhXdtqFHgU9Wd4KHkvcbCoIZ0JaSaumzS8s2gXSkP8F7ivg/8ZQ==
jquery.are-you-sure@^1.9.0:
version "1.9.0"
resolved "https://registry.yarnpkg.com/jquery.are-you-sure/-/jquery.are-you-sure-1.9.0.tgz#16aaa2c6080fa214f64027239ae3a34ad6a6265e"
integrity sha512-2r0uFx8CyAopjeHGOdvvwpFP921TnW1+v1uJXcAWQYHYGB1tryTDhQY+5u6HsVeMwbWiRTKVZFWnLaFpDvIqZQ==
dependencies:
jquery ">=1.4.2"
jquery@>=1.4.2, jquery@^3.5.0:
version "3.6.0"
resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.6.0.tgz#c72a09f15c1bdce142f49dbf1170bdf8adac2470"
integrity sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw==
jquery@^3.5.0:
version "3.6.4"
resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.6.4.tgz#ba065c188142100be4833699852bf7c24dc0252f"
integrity sha512-v28EW9DWDFpzcD9O5iyJXg3R3+q+mET5JhnjJzQUZMHOv67bpSIHq81GEYpPNZHG+XXHsfSme3nxp/hndKEcsQ==
js-base64@^2.1.8, js-base64@^2.1.9:
version "2.6.4"
@ -8447,6 +8440,11 @@ validate-npm-package-name@^3.0.0, validate-npm-package-name@~3.0.0:
dependencies:
builtins "^1.0.3"
validator@13.9.0:
version "13.9.0"
resolved "https://registry.yarnpkg.com/validator/-/validator-13.9.0.tgz#33e7b85b604f3bbce9bb1a05d5c3e22e1c2ff855"
integrity sha512-B+dGG8U3fdtM0/aNK4/X8CXq/EcxU2WPrPEkJGslb47qyHsxmbggTWK0yEA4qnYVNF+nxNlN88o14hIcPmSIEA==
vary@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"