!function(e,t){"function"==typeof define&&define.amd?define("ev-emitter/ev-emitter",t):"object"==typeof module&&module.exports?module.exports=t():e.EvEmitter=t()}("undefined"!=typeof window?window:this,function(){function e(){}var t=e.prototype;return t.on=function(e,t){if(e&&t){var i=this._events=this._events||{},n=i[e]=i[e]||[];return n.indexOf(t)==-1&&n.push(t),this}},t.once=function(e,t){if(e&&t){this.on(e,t);var i=this._onceEvents=this._onceEvents||{},n=i[e]=i[e]||{};return n[t]=!0,this}},t.off=function(e,t){var i=this._events&&this._events[e];if(i&&i.length){var n=i.indexOf(t);return n!=-1&&i.splice(n,1),this}},t.emitEvent=function(e,t){var i=this._events&&this._events[e];if(i&&i.length){i=i.slice(0),t=t||[];for(var n=this._onceEvents&&this._onceEvents[e],o=0;o<i.length;o++){var r=i[o],s=n&&n[r];s&&(this.off(e,r),delete n[r]),r.apply(this,t)}return this}},t.allOff=function(){delete this._events,delete this._onceEvents},e}),function(e,t){"use strict";"function"==typeof define&&define.amd?define(["ev-emitter/ev-emitter"],function(i){return t(e,i)}):"object"==typeof module&&module.exports?module.exports=t(e,require("ev-emitter")):e.imagesLoaded=t(e,e.EvEmitter)}("undefined"!=typeof window?window:this,function(e,t){function i(e,t){for(var i in t)e[i]=t[i];return e}function n(e){if(Array.isArray(e))return e;var t="object"==typeof e&&"number"==typeof e.length;return t?d.call(e):[e]}function o(e,t,r){if(!(this instanceof o))return new o(e,t,r);var s=e;return"string"==typeof e&&(s=document.querySelectorAll(e)),s?(this.elements=n(s),this.options=i({},this.options),"function"==typeof t?r=t:i(this.options,t),r&&this.on("always",r),this.getImages(),h&&(this.jqDeferred=new h.Deferred),void setTimeout(this.check.bind(this))):void a.error("Bad element for imagesLoaded "+(s||e))}function r(e){this.img=e}function s(e,t){this.url=e,this.element=t,this.img=new Image}var h=e.jQuery,a=e.console,d=Array.prototype.slice;o.prototype=Object.create(t.prototype),o.prototype.options={},o.prototype.getImages=function(){this.images=[],this.elements.forEach(this.addElementImages,this)},o.prototype.addElementImages=function(e){"IMG"==e.nodeName&&this.addImage(e),this.options.background===!0&&this.addElementBackgroundImages(e);var t=e.nodeType;if(t&&u[t]){for(var i=e.querySelectorAll("img"),n=0;n<i.length;n++){var o=i[n];this.addImage(o)}if("string"==typeof this.options.background){var r=e.querySelectorAll(this.options.background);for(n=0;n<r.length;n++){var s=r[n];this.addElementBackgroundImages(s)}}}};var u={1:!0,9:!0,11:!0};return o.prototype.addElementBackgroundImages=function(e){var t=getComputedStyle(e);if(t)for(var i=/url\((['"])?(.*?)\1\)/gi,n=i.exec(t.backgroundImage);null!==n;){var o=n&&n[2];o&&this.addBackground(o,e),n=i.exec(t.backgroundImage)}},o.prototype.addImage=function(e){var t=new r(e);this.images.push(t)},o.prototype.addBackground=function(e,t){var i=new s(e,t);this.images.push(i)},o.prototype.check=function(){function e(e,i,n){setTimeout(function(){t.progress(e,i,n)})}var t=this;return this.progressedCount=0,this.hasAnyBroken=!1,this.images.length?void this.images.forEach(function(t){t.once("progress",e),t.check()}):void this.complete()},o.prototype.progress=function(e,t,i){this.progressedCount++,this.hasAnyBroken=this.hasAnyBroken||!e.isLoaded,this.emitEvent("progress",[this,e,t]),this.jqDeferred&&this.jqDeferred.notify&&this.jqDeferred.notify(this,e),this.progressedCount==this.images.length&&this.complete(),this.options.debug&&a&&a.log("progress: "+i,e,t)},o.prototype.complete=function(){var e=this.hasAnyBroken?"fail":"done";if(this.isComplete=!0,this.emitEvent(e,[this]),this.emitEvent("always",[this]),this.jqDeferred){var t=this.hasAnyBroken?"reject":"resolve";this.jqDeferred[t](this)}},r.prototype=Object.create(t.prototype),r.prototype.check=function(){var e=this.getIsImageComplete();return e?void this.confirm(0!==this.img.naturalWidth,"naturalWidth"):(this.proxyImage=new Image,this.proxyImage.addEventListener("load",this),this.proxyImage.addEventListener("error",this),this.img.addEventListener("load",this),this.img.addEventListener("error",this),void(this.proxyImage.src=this.img.src))},r.prototype.getIsImageComplete=function(){return this.img.complete&&this.img.naturalWidth},r.prototype.confirm=function(e,t){this.isLoaded=e,this.emitEvent("progress",[this,this.img,t])},r.prototype.handleEvent=function(e){var t="on"+e.type;this[t]&&this[t](e)},r.prototype.onload=function(){this.confirm(!0,"onload"),this.unbindEvents()},r.prototype.onerror=function(){this.confirm(!1,"onerror"),this.unbindEvents()},r.prototype.unbindEvents=function(){this.proxyImage.removeEventListener("load",this),this.proxyImage.removeEventListener("error",this),this.img.removeEventListener("load",this),this.img.removeEventListener("error",this)},s.prototype=Object.create(r.prototype),s.prototype.check=function(){this.img.addEventListener("load",this),this.img.addEventListener("error",this),this.img.src=this.url;var e=this.getIsImageComplete();e&&(this.confirm(0!==this.img.naturalWidth,"naturalWidth"),this.unbindEvents())},s.prototype.unbindEvents=function(){this.img.removeEventListener("load",this),this.img.removeEventListener("error",this)},s.prototype.confirm=function(e,t){this.isLoaded=e,this.emitEvent("progress",[this,this.element,t])},o.makeJQueryPlugin=function(t){t=t||e.jQuery,t&&(h=t,h.fn.imagesLoaded=function(e,t){var i=new o(this,e,t);return i.jqDeferred.promise(h(this))})},o.makeJQueryPlugin(),o});
(function (){
const {
mergeObjects,
onResize,
matchMedia,
prefersReducedMotion,
isBuilder
}=BreakdanceFrontend.utils;
class BreakdanceEntrance {
enabledClass='breakdance-animation-enabled';
beforeClass='is-before';
animatingClass='is-animating';
completedClass='is-animated';
defaultOptions={
animation_type: null,
duration: { number: 500, unit: 'ms', style: '500ms' },
delay: { number: 0, unit: 'ms', style: '0ms' },
advanced: {
distance: { number: 100, unit: "px", style: "100px" },
offset: { number: 0, unit: 'px', style: '0px' },
ease: 'power1.out',
anchorPlacement: 'top bottom',
once: false,
disable_at: null
}};
delay=0;
initialized=false;
constructor(selector, options){
gsap.registerPlugin(ScrollTrigger);
this.cleanup=this.cleanup.bind(this);
this.reset=this.reset.bind(this);
this.selector=selector;
this.options=mergeObjects(this.defaultOptions, options);
this.rootEl=document.documentElement;
this.init();
}
getAnimations(){
const distance=this.options.advanced.distance.style;
const unit=this.options.advanced.distance.unit;
return {
fade: [
{ autoAlpha: 0 },
{ autoAlpha: 1 }
],
slideUp: [
{ y: distance },
{ y: `0${unit}` }
],
slideDown: [
{ y: `-=${distance}` },
{ y: `0${unit}` }
],
slideLeft: [
{ x: `-=${distance}` },
{ x: `0${unit}` }
],
slideRight: [
{ x: distance },
{ x: `0${unit}` }
],
flipUp: [
{ perspective: 2500, rotateX: `-=${distance}` },
{ rotateX: `0${unit}` }
],
flipDown: [
{ perspective: 2500, rotateX: distance },
{ rotateX: `0${unit}` }
],
flipLeft: [
{ perspective: 2500, rotateY: `-=${distance}` },
{ rotateY: `0${unit}` }
],
flipRight: [
{ perspective: 2500, rotateY: distance },
{ rotateY: `0${unit}` }
],
zoomIn: [
{ scale: 0.6 },
{ scale: 1 }
],
zoomOut: [
{ scale: 1.2 },
{ scale: 1 }
],
};}
canAnimate(){
const breakpoint=this.options.advanced.disable_at;
if(!breakpoint) return true;
return !matchMedia(breakpoint);
}
getDuration(value){
if(!value) return value;
if(value.unit==='s') return value.number;
return value.number / 1000;
}
cleanup(){
gsap.set(this.element, { clearProps: 'all' });
}
reset(element){
const el=element||this.element;
el.classList.add(this.beforeClass);
el.classList.remove(this.completedClass);
el.classList.remove(this.animatingClass);
}
getOffset(offset, anchor){
const defaultOffset=120;
if(anchor==='top bottom'&&offset.number===0){
return defaultOffset;
}
return offset.number;
}
createTween(){
const type=this.options.animation_type;
const animations=this.getAnimations();
if(!animations[type]){
console.error(`[ENTRANCE] The selected ${type} animation is invalid.`);
return;
}
const [from, to]=animations[type];
const { ease, once, anchorPlacement }=this.options.advanced;
const duration=this.getDuration(this.options.duration);
const delay=this.getDuration(this.options.delay) + this.delay;
const offset=this.getOffset(this.options.advanced.offset, anchorPlacement);
const [elementStart, viewportStart]=anchorPlacement.split(' ');
const anim=gsap.timeline({
delay,
paused: true
});
this.element.classList.add(this.beforeClass);
if(isBuilder()){
this.hideEl();
}
this.startTrigger=ScrollTrigger.create({
trigger: this.element,
start: `${elementStart}+=${offset} ${viewportStart}`,
toggleActions: "play none none none",
once,
onEnter: ()=> anim.play()
});
anim.fromTo(this.element, {
...from,
autoAlpha: 0,
},
{
...to,
duration,
delay,
ease,
autoAlpha: 1,
clearProps: 'all',
immediateRender: false,
onStart: ()=> {
this.element.classList.add(this.animatingClass);
this.element.classList.remove(this.beforeClass);
},
onComplete: ()=> {
this.element.classList.remove(this.animatingClass);
this.element.classList.add(this.completedClass);
},
onReverseComplete: ()=> {
this.element.classList.add(this.beforeClass);
this.element.classList.remove(this.animatingClass);
},
});
if(!once){
this.goToBeginningOnReverse(anim);
}
return anim;
}
goToBeginningOnReverse(animation){
this.endTrigger=ScrollTrigger.create({
trigger: this.element,
start: `top-=10 bottom`,
onLeaveBack: ()=> {
animation.pause(0);
this.cleanup();
if(isBuilder()){
this.hideEl();
}
this.reset();
}});
}
hideEl(){
gsap.set(this.element, { autoAlpha: 0 });
}
update(options){
this.options=mergeObjects(this.defaultOptions, options);
this.destroy();
this.init();
}
replay(delay=0){
this.destroy();
this.reset();
this.delay=delay;
this.init();
}
destroy(){
this.initialized=false;
if(!this.element) return;
this.element.classList.add(this.completedClass);
if(!this.tween) return;
this.tween.kill();
this.tween=null;
this.startTrigger?.kill();
this.endTrigger?.kill();
gsap.set(this.element, { clearProps: 'all' });
}
refresh(){
ScrollTrigger.refresh();
}
initTween(){
if(this.initialized) return;
this.initialized=true;
this.element.classList.remove(this.completedClass);
this.tween=this.createTween();
}
initOrDestroy(){
if(this.canAnimate()){
this.initTween();
}else{
this.destroy();
}}
init(){
if(!this.options.animation_type) return;
this.element=document.querySelector(this.selector);
this.element.bdAnim=this;
if(prefersReducedMotion()){
this.element.classList.add(this.completedClass);
return;
}
onResize(()=> this.initOrDestroy());
this.rootEl.classList.add(this.enabledClass);
}
static autoload(){
const loaded=imagesLoaded(document.body);
loaded.on("always", ()=> {
const event=new Event("breakdance_refresh_animations", { bubbles: true });
document.dispatchEvent(event);
ScrollTrigger.refresh(true);
});
addEventListener("breakdance_play_animations", (event)=> {
const target=event.target===window ? document.body:event.target;
const nodes=[
target,
...target.querySelectorAll("[data-entrance]")
];
nodes.forEach((el)=> el.bdAnim?.replay(event?.detail?.delay));
});
addEventListener("breakdance_refresh_animations", (event)=> {
const target=event.target===window ? document.body:event.target;
const nodes=[
target,
...target.querySelectorAll("[data-entrance]")
];
nodes.forEach((el)=> el.bdAnim?.cleanup());
});
addEventListener("breakdance_reset_animations", (event)=> {
const target=event.target===window ? document.body:event.target;
const nodes=[
target,
...target.querySelectorAll("[data-entrance]")
];
nodes.forEach((el)=> el.bdAnim?.reset(el));
});
}
static dontLetScrollTriggerMutateScrollPosition(){
window.addEventListener("load", ()=> {
if(!location.hash) return;
if(window.bdeAnimationScrolled) return;
const scrollElem=document.querySelector(location.hash);
if(!scrollElem) return;
requestAnimationFrame(()=> {
scrollElem.scrollIntoView({
behavior: "smooth",
});
});
window.bdeAnimationScrolled=true;
});
}}
window.BreakdanceEntrance=BreakdanceEntrance;
BreakdanceEntrance.autoload();
BreakdanceEntrance.dontLetScrollTriggerMutateScrollPosition();
}());
(function (){
const loadingClass="is-loading";
function formatError(error){
if(Array.isArray(error)&&error.length){
return error.map((e)=> e.message).join("<br />");
}
if(typeof error==="object") return error.message;
}
function interceptResponse(response){
return response.json().then((body)=> {
if(!response.ok){
throw new Error(formatError(body.data));
}
return body;
});
}
function postData(url, data){
const { makeAjaxRequest }=window.BreakdanceFrontend.utils;
const payload={
method: "POST",
credentials: "same-origin",
body: data,
};
return makeAjaxRequest(url, payload).then(interceptResponse);
}
function createMessage(text, type="success", onDismiss=null){
const node=document.createElement("div");
node.innerHTML=text;
node.classList.add("breakdance-form-message");
node.classList.add("breakdance-form-message--" + type);
if(typeof onDismiss==="function"){
node.classList.add("breakdance-form-message-dismissable");
const dismissWrapper=document.createElement("div");
dismissWrapper.classList.add("breakdance-form-message-dismiss");
const dismissButton=document.createElement("button");
dismissButton.classList.add("breakdance-form-message-dismiss-button");
dismissButton.innerHTML="&times;";
dismissButton.addEventListener("click", onDismiss);
dismissWrapper.appendChild(dismissButton);
node.appendChild(dismissWrapper);
}
return node;
}
function createErrorMessage(text){
return createMessage(text, "error");
}
function resetForm(form){
form.reset();
const fileFields=form.querySelectorAll(".breakdance-form-field--file");
fileFields.forEach((field)=> {
const fileText=field.querySelector(".breakdance-form-file-upload__text");
if(fileText){
const emptyText=field.querySelector(".breakdance-form-file-upload__input").dataset.i18nEmptyText;
fileText.textContent=emptyText;
}
const list=field.querySelector(".breakdance-form-files-list");
if(list){
list.innerHTML="";
list.classList.remove("is-files-visible");
}});
resetConditionalFields(form);
if(form.dataset.steps >=1) resetSteps(form);
}
function safeEval(code, form, formData){
const formValues={
post_id: formData.get("post_id"),
form_id: formData.get("form_id"),
};
for (const [name, value] of formData.entries()){
if(name.startsWith("fields[")){
const parts=name.match(/\[/g).length;
const index=name.match(/\[(.*?)\]/)[1];
if(parts >=2){
if(!formValues[index]){
formValues[index]=[];
}
formValues[index].push(value);
}else{
formValues[index]=value;
}}
}
try {
eval(code);
} catch (e){
console.warn("Could not run Custom JavaScript.", e);
}}
function getRecaptchaToken(apiKey){
const payload={ action: "breakdance_submit" };
return new Promise((resolve, reject)=> {
grecaptcha.ready(()=> {
try {
const token=grecaptcha.execute(apiKey, payload);
return resolve(token);
} catch (error){
return reject(error);
}});
});
}
function getOptions(form){
const options=JSON.parse(form.getAttribute("data-options"));
const defaultOptions={
name: "empty",
ajaxUrl: null,
successMessage: null,
errorMessage: null,
clearOnSuccess: true,
hideOnSuccess: false,
redirectUrl: null,
customJavaScript: {},
popupsOnSuccess: [],
popupsOnError: [],
recaptcha: {
key: null,
enabled: false,
},
};
if(!options){
return defaultOptions;
}
return Object.assign({}, defaultOptions, options);
}
async function onSubmit(event){
event.preventDefault();
const form=event.currentTarget;
const loading=form.classList.contains(loadingClass);
const options=getOptions(form);
if(loading) return;
const formData=new FormData(form);
formData.append("action", `breakdance_form_${options.slug}`);
beforeSubmit(form);
if(options.recaptcha.enabled){
try {
const token=await getRecaptchaToken(options.recaptcha.key);
formData.append("recaptcha_token", token);
} catch (error){
console.error(error);
}}
postData(options.ajaxUrl, formData)
.then((response)=> onRequestSuccess(response, form, formData))
.catch((error)=> onRequestError(error, form, formData))
.finally(()=> afterSubmit(form));
}
function beforeSubmit(form){
form.classList.add(loadingClass);
const messages=form.parentElement.querySelectorAll(".breakdance-form-message");
messages.forEach((msg)=> {
msg.remove();
})
}
function afterSubmit(form){
form.classList.remove(loadingClass);
}
function onRequestError(error, form, formData){
console.debug("[BREAKDANCE] Received a form error:", error.message);
const options=getOptions(form);
const message =
error.message||options.errorMessage||"An unexpected error occurred.";
const errorNode=createErrorMessage(message);
form.after(errorNode);
if(options.popupsOnError.length > 0){
options.popupsOnError.forEach((errorPopup)=> {
if(errorPopup.popup&&errorPopup.action){
BreakdancePopup.runAction(errorPopup.popup, errorPopup.action);
}});
}
safeEval(options.customJavaScript?.js_on_error, form, formData);
}
function onRequestSuccess(response, form, formData){
console.debug("[BREAKDANCE] Received form response:", response);
const options=getOptions(form);
const redirectOnSuccess=options.redirect&&options.redirectUrl;
if(options.successMessage&&!redirectOnSuccess){
let messageNode=createMessage(options.successMessage);
if(options.hideOnSuccess){
form.classList.add("breakdance-form--hidden");
messageNode=createMessage(options.successMessage, "success", ()=> {
form.classList.remove("breakdance-form--hidden");
messageNode.remove();
});
}
form.after(messageNode);
}
safeEval(options.customJavaScript?.js_on_success, form, formData);
if(options.clearOnSuccess){
resetForm(form);
}
if(options.popupsOnSuccess.length > 0){
options.popupsOnSuccess.forEach((successPopup)=> {
if(successPopup.popup&&successPopup.action){
BreakdancePopup.runAction(successPopup.popup, successPopup.action);
}});
}
if(redirectOnSuccess){
location.href=options.redirectUrl;
}}
function onInputUpdate(event){
const parent=event.currentTarget.closest(".breakdance-form-field");
const activeClass="breakdance-form-field--filled";
if(!parent) return;
if(event.currentTarget.value.length){
parent.classList.add(activeClass);
}else{
parent.classList.remove(activeClass);
}}
function removeFile(input, fileToRemove, fileIndex){
const dt=new DataTransfer();
for (let file of input.files){
if(file!==fileToRemove){
dt.items.add(file);
}}
input.files=dt.files;
onFileInputChange(input);
}
function maybeShowInlineFileValidation({ input, numOfFiles, maxNumOfFiles, i18nError }){
const parentField=input.closest(".breakdance-form-field");
const oldMsg=parentField.querySelector(".breakdance-form-message");
if(oldMsg) oldMsg.remove();
if(!maxNumOfFiles) return;
if(numOfFiles <=maxNumOfFiles) return;
const errorMessage=createErrorMessage(i18nError.replace("%n", `${maxNumOfFiles}`));
parentField.appendChild(errorMessage);
}
function updateFilesList(input, files, listNode){
const fragment=document.createDocumentFragment();
files.forEach((file, index)=> {
const li=document.createElement("li");
const size=file.size < 1000000 ?
Math.floor(file.size / 1000) + " KB" :
Math.floor(file.size / 1000000) + " MB";
const nameNode=document.createElement("span");
nameNode.appendChild(document.createTextNode(file.name));
nameNode.classList.add("breakdance-form-files-list-item__name");
const sizeNode=document.createElement("span");
sizeNode.appendChild(document.createTextNode(size));
sizeNode.classList.add("breakdance-form-files-list-item__size");
const deleteBtn=document.createElement("button");
deleteBtn.classList.add("breakdance-form-files-list-item__delete");
deleteBtn.setAttribute("aria-label", "Delete File");
deleteBtn.setAttribute("type", "button");
deleteBtn.addEventListener("click", ()=> {
removeFile(input, file, index);
})
li.appendChild(nameNode);
li.appendChild(sizeNode);
li.appendChild(deleteBtn);
li.classList.add("breakdance-form-files-list-item");
fragment.appendChild(li);
});
listNode.innerHTML="";
listNode.appendChild(fragment);
listNode.classList.add("is-files-visible");
}
function onFileInputChange(input){
const files=Array.from(input.files);
const names=files.map((f)=> f.name);
const maxNumOfFiles=Number(input.dataset.maxFiles);
const i18nFilledText=input.dataset.i18nFilledText;
const i18nError=input.dataset.i18nErrorText;
maybeShowInlineFileValidation({
input,
numOfFiles: files.length,
maxNumOfFiles,
i18nError
});
const textNode=input.parentElement.querySelector(".breakdance-form-file-upload__text"
);
if(textNode){
if(names.length > 1){
textNode.innerHTML=i18nFilledText.replace("%n", `${names.length}`);
}else{
textNode.innerHTML=names[0];
}}
const listNode=input.closest(".breakdance-form-field--file").querySelector(".breakdance-form-files-list");
if(!listNode) return;
updateFilesList(input, files, listNode);
}
function bindEvents(form){
bindFileEvents(form);
const inputs=Array.from(form.querySelectorAll("input, select, textarea"));
inputs.forEach((input)=> {
input.addEventListener("input", onInputUpdate);
});
form.addEventListener("submit", onSubmit);
}
function bindDropzone(dropzone){
const dragOver=(event)=> {
event.preventDefault();
event.stopPropagation();
dropzone.classList.add("is-dragging");
};
const dragLeave=(event)=> {
event.preventDefault();
event.stopPropagation();
dropzone.classList.remove("is-dragging");
};
const drop=(event)=> {
event.preventDefault();
event.stopPropagation();
const fileInput=dropzone.querySelector("input[type='file']");
if(fileInput){
fileInput.files=event.dataTransfer.files;
onFileInputChange(fileInput);
}};
dropzone.addEventListener("dragover", dragOver);
dropzone.addEventListener("dragenter", dragOver);
dropzone.addEventListener("dragleave", dragLeave);
dropzone.addEventListener("dragend", dragLeave);
dropzone.addEventListener("drop", dragLeave);
dropzone.addEventListener("drop", drop);
}
function bindFileEvents(form){
const dropZones=Array.from(form.querySelectorAll(".breakdance-form-file-upload")
);
const inputs=Array.from(form.querySelectorAll(".breakdance-form-file-upload__input")
);
inputs.forEach((input)=>
input.addEventListener("change", ()=> {
if(!input.files.length) return;
onFileInputChange(input);
})
);
dropZones.forEach((dropzone)=> bindDropzone(dropzone));
}
function unbindEvents(form){
const inputs=Array.from(form.querySelectorAll("input, select, textarea"));
inputs.forEach((input)=> {
input.removeEventListener("input", onInputUpdate);
});
form.removeEventListener("submit", onSubmit);
form.bdMask?.destroy();
}
function scrollIntoViewIfNeeded(element){
const rect=element.getBoundingClientRect();
const notVisible=rect.top < 0;
if(notVisible){
element.scrollIntoView({ behavior: "smooth", block: "start" });
}}
function initConditionalFields(form, attachEventListeners=false){
const inputs=Array.from(form.querySelectorAll("input, select, textarea, .form-input-html")
);
inputs.forEach((input)=> {
const { conditionalFieldId, conditionalValue, conditionalOperand } =
input.dataset;
if(!conditionalFieldId){
return;
}
const conditionalFields=form.querySelectorAll(`[name="fields[${conditionalFieldId}]"],[name="fields[${conditionalFieldId}][]"]`
);
const wrapper=input.closest(".breakdance-form-field");
conditionalFields.forEach((conditionalField)=> {
const runValidation=()=> {
showOrHideConditionalField(
form,
input,
wrapper,
conditionalFieldId,
conditionalValue,
conditionalOperand
);
};
if(attachEventListeners){
const useChangeEvent=conditionalField.matches("input[type=radio], input[type=checkbox], input[type=file], select, input[type=number], input[type=date]"
);
if(useChangeEvent){
conditionalField.addEventListener("input", ()=> runValidation());
conditionalField.addEventListener("change", ()=> runValidation());
}else{
conditionalField.addEventListener("keyup", ()=> runValidation());
}}
runValidation();
});
});
}
function showOrHideConditionalField(
form,
inputElement,
fieldElement,
conditionalFieldId,
conditionalValue,
conditionalOperand
){
const fieldValue=getConditionalFieldValue(form, conditionalFieldId);
if(shouldShowField(fieldValue, conditionalOperand, conditionalValue)){
inputElement.removeAttribute("disabled");
fieldElement.classList.remove("breakdance-form-field--condition-hidden");
return;
}
inputElement.disabled=true;
fieldElement.classList.add("breakdance-form-field--condition-hidden");
}
function getConditionalFieldValue(form, conditionalFieldId){
const selector=`[name="fields[${conditionalFieldId}]"],[name="fields[${conditionalFieldId}][]"], [type='file'][name="fields[${conditionalFieldId}][]"]`;
const conditionalFields=Array.from(form.querySelectorAll(selector));
if(!conditionalFields.length) return null;
const values=conditionalFields.map((field)=> {
const isCheckboxOrRadio=["checkbox", "radio"].includes(field.type);
if(isCheckboxOrRadio&&!field.checked){
return null;
}
return field.value;
});
return values?.filter((v)=> v!==null).join(",");
}
function resetConditionalFields(form){
initConditionalFields(form, false);
}
function shouldShowField(aValue, operand, bValue){
const aValueIsEmpty=aValue===""||aValue===null;
const bValueIsEmpty=bValue===""||bValue===null;
if(operand==="equals"){
return aValue==bValue;
}else if(operand==="not equals"){
return aValue!=bValue;
}else if(operand==="is set"){
return aValue;
}else if(operand==="is not set"){
return !aValue;
}else if(operand==="is one of"){
const bValueArray=bValue.split(",");
return bValueArray.some((x)=> x.trim()==aValue);
}else if(operand==="is none of"){
const bValueArray=bValue.split(",");
return !bValueArray.some((x)=> x.trim()==aValue);
}else if(operand==="contains"){
if(typeof aValue==="string"&&typeof bValue==="string"){
return aValue.toLowerCase().includes(bValue.toLowerCase());
}
return false;
}else if(operand==="does not contain"){
if(typeof aValue==="string"&&typeof bValue==="string"){
return !aValue.toLowerCase().includes(bValue.toLowerCase());
}
return true;
}else if(operand==="is greater than"){
const aValueInteger=parseInt(aValue);
const bValueInteger=parseInt(bValue);
if(isNaN(aValueInteger)||isNaN(bValueInteger)){
return false;
}
return aValueInteger > bValueInteger;
}else if(operand==="is less than"){
const aValueInteger=parseInt(aValue);
const bValueInteger=parseInt(bValue);
if(isNaN(aValueInteger)||isNaN(bValueInteger)){
return false;
}
return aValueInteger < bValueInteger;
}else if(operand==="is before date"){
if(aValueIsEmpty||bValueIsEmpty){
return false;
}
const aDateValue=new Date(aValue);
const bDateValue=new Date(bValue);
const aValueIsValidDate =
aDateValue instanceof Date&&isFinite(aDateValue);
const bValueIsValidDate =
bDateValue instanceof Date&&isFinite(bDateValue);
if(!aValueIsValidDate||!bValueIsValidDate){
return false;
}
return aDateValue < bDateValue;
}else if(operand==="is after date"){
if(aValueIsEmpty||bValueIsEmpty){
return false;
}
const aDateValue=new Date(aValue);
const bDateValue=new Date(bValue);
const aValueIsValidDate =
aDateValue instanceof Date&&isFinite(aDateValue);
const bValueIsValidDate =
bDateValue instanceof Date&&isFinite(bDateValue);
if(!aValueIsValidDate||!bValueIsValidDate){
return false;
}
return aDateValue > bDateValue;
}else if(operand==="is before time"){
if(aValueIsEmpty||bValueIsEmpty){
return false;
}
const todaysDate=new Date().toDateString();
const aDateValue=new Date(`${todaysDate} ${aValue}`);
const bDateValue=new Date(`${todaysDate} ${bValue}`);
const aValueIsValidDate =
aDateValue instanceof Date&&isFinite(aDateValue);
const bValueIsValidDate =
bDateValue instanceof Date&&isFinite(bDateValue);
if(!aValueIsValidDate||!bValueIsValidDate){
return false;
}
return aDateValue < bDateValue;
}else if(operand==="is after time"){
if(aValueIsEmpty||bValueIsEmpty){
return false;
}
const todaysDate=new Date().toDateString();
const aDateValue=new Date(`${todaysDate} ${aValue}`);
const bDateValue=new Date(`${todaysDate} ${bValue}`);
const aValueIsValidDate =
aDateValue instanceof Date&&isFinite(aDateValue);
const bValueIsValidDate =
bDateValue instanceof Date&&isFinite(bDateValue);
if(!aValueIsValidDate||!bValueIsValidDate){
return false;
}
return aDateValue > bDateValue;
}
return true;
}
function destroy(selector){
const form=document.querySelector(selector);
if(!form){
console.warn("[BREAKDANCE] Could not find form to destroy:", selector);
return;
}
unbindEvents(form);
}
function initSteps(form, isBuilder=false){
if(form.dataset.steps==0) return;
const nextStepButtons=form.querySelectorAll(".breakdance-form-button__next-step"
);
nextStepButtons.forEach((button)=>
button.addEventListener("click", ()=> {
nextStep(form, isBuilder);
})
);
const previousStepButtons=form.querySelectorAll(".breakdance-form-button__previous-step"
);
previousStepButtons.forEach((button)=>
button.addEventListener("click", ()=> {
previousStep(form);
})
);
showOrHideSteps(form);
}
function validateStep(form, step){
const inputs=Array.from(form.querySelectorAll(`[data-form-step='${step}'] input,[data-form-step='${step}'] select, [data-form-step='${step}'] textarea`
)
);
return inputs.every((input)=> {
input.reportValidity();
return input.checkValidity();
});
}
function getFirstInputInStep(form, step){
const firstFieldInStep=form.querySelector(`.breakdance-form-field[data-form-step="${step}"]:not(.breakdance-form-field--hidden, .breakdance-form-field--html, .breakdance-form-field--condition-hidden)`
);
if(firstFieldInStep){
return firstFieldInStep.querySelector(`input, textarea, select`
);
}
return null;
}
function nextStep(form, isBuilder){
const currentStep=parseInt(form.dataset.currentStep);
if(!validateStep(form, currentStep)&&!isBuilder){
return;
}
const nextStep=currentStep + 1;
setStep(form, nextStep);
const firstInput=getFirstInputInStep(form, nextStep);
if(firstInput){
firstInput.focus();
}
scrollIntoViewIfNeeded(form);
}
function previousStep(form){
const currentStep=parseInt(form.dataset.currentStep);
setStep(form, currentStep - 1);
scrollIntoViewIfNeeded(form);
}
function setStep(form, step){
form.dataset.currentStep=step.toString();
showOrHideSteps(form);
}
function showOrHideSteps(form){
const currentStep=parseInt(form.dataset.currentStep);
const totalSteps=parseInt(form.dataset.steps);
const fields=form.querySelectorAll(".breakdance-form-field:not(.breakdance-form-footer)"
);
fields.forEach((field)=> {
const formStep=parseInt(field.dataset.formStep);
if(formStep===currentStep){
field.classList.remove("hidden-step");
}else{
field.classList.add("hidden-step");
}});
const submitButton=form.querySelector(".breakdance-form-button__submit");
const nextStepButton=form.querySelector(`.breakdance-form-field[data-form-step="${currentStep}"] .breakdance-form-button__next-step`
);
const previousStepButton=form.querySelector(`.breakdance-form-field[data-form-step="${currentStep}"] .breakdance-form-button__previous-step`
);
if(currentStep===totalSteps){
submitButton.classList.remove("hidden");
nextStepButton.classList.add("hidden");
}else{
submitButton.classList.add("hidden");
nextStepButton.classList.remove("hidden");
}
if(currentStep > 1){
previousStepButton.classList.remove("hidden");
}else{
previousStepButton.classList.add("hidden");
}
const steps=form.querySelectorAll(".breakdance-form-stepper__step");
if(steps){
steps.forEach((step)=> {
const stepperStep=parseInt(step.dataset.stepperStep);
if(stepperStep <=currentStep){
step.classList.add("is-active");
}else{
step.classList.remove("is-active");
}});
const currentStepper=form.querySelector(`[data-stepper-step="${currentStep}"]`
);
if(currentStepper){
currentStepper.classList.add("is-active");
}}
}
function resetSteps(form){
setStep(form, 1);
}
function initMask(form, selector){
if(typeof Maska==="undefined") return;
const tokens={
'z': {
pattern: /[a-z|A-Z]/,
multiple: true
},
'Z': {
pattern: /[A-Z]/,
multiple: true,
transform: (chr)=> chr.toLocaleUpperCase(),
},
0: { pattern: /[0-9]/, optional: true },
9: { pattern: /[0-9]/, repeated: true },
}
form.bdMask=new Maska.MaskInput(`${selector} [data-maska]`, {
tokens
});
}
function init(selector){
const form=document.querySelector(selector);
if(!form){
console.warn("[BREAKDANCE] Could not find form:", selector);
return;
}
bindEvents(form);
initConditionalFields(form, true);
initSteps(form);
initMask(form, selector);
}
window.breakdanceForm={
init,
destroy,
initMask,
initConditionalFields,
initSteps,
};})();
(function (){
const { mergeObjects }=BreakdanceFrontend.utils;
const isSelectorValid=(selector)=> {
const queryCheck=(s)=>
document.createDocumentFragment().querySelector(s);
try {
queryCheck(selector);
} catch {
return false;
}
return true;
};
class BreakdanceScrollProgress {
defaultOptions={
type: "line",
direction: "right",
selector: null,
track: null,
};
constructor(selector, options){
this.selector=selector;
this.element=document.querySelector(`${this.selector}`);
this.percentageSpan=this.element.querySelector(".js-current-percentage"
);
this.options=mergeObjects(this.defaultOptions, options);
this.scrollTarget =
this.options.selector &&
this.options.track=="custom" &&
isSelectorValid(this.options.selector)
? document.querySelector(this.options.selector)
: document.body;
this.init();
}
updateProgressCircle(progress){
const pathLength=this.progressPath.getTotalLength();
let progressAsStroke=pathLength - (progress / 100) * pathLength;
if(this.options.direction=="left")
progressAsStroke=progressAsStroke * -1;
this.progressPath.style.strokeDashoffset=progressAsStroke;
if(this.percentageSpan){
this.percentageSpan.innerHTML=`${progress}%`;
}}
updateProgressLine(progress){
this.element.style.setProperty("--bde-scroll-progress-current",
`${progress}%`
);
if(this.percentageSpan){
this.percentageSpan.innerHTML=`${progress}%`;
}}
updateScrollValue(){
if(typeof ScrollTrigger!=="function") return;
const start=this.options.track=="custom" ? "top bottom":"top top";
this.scrollTrigger=ScrollTrigger.create({
trigger: this.scrollTarget,
start,
end: "bottom bottom",
scrub: true,
onUpdate: (self)=> {
this.updateTracker(self.progress);
},
});
}
updateTracker(value){
let percentageValue=(value * 100).toFixed(0);
if(this.options.type=="circle"){
this.updateProgressCircle(percentageValue);
}else{
this.updateProgressLine(percentageValue);
}}
initCircularTracker(){
this.progressPath=this.element.querySelector(".js-progress-svg path.progress"
);
const pathLength=this.progressPath.getTotalLength();
this.progressPath.style.transition =
this.progressPath.style.WebkitTransition="none";
this.progressPath.style.strokeDasharray=pathLength + " " + pathLength;
this.progressPath.style.strokeDashoffset=pathLength;
this.progressPath.getBoundingClientRect();
this.progressPath.style.transition =
this.progressPath.style.WebkitTransition =
"stroke-dashoffset 10ms linear";
}
update(){
this.destroy();
this.init();
}
destroy(){
this.scrollTrigger.kill(true);
this.scrollTrigger=null;
this.scrollTarget=null;
}
init(){
if(this.options.type=="circle") this.initCircularTracker();
this.updateScrollValue();
}}
window.BreakdanceScrollProgress=BreakdanceScrollProgress;
})();
(function (){
const { mergeObjects }=BreakdanceFrontend.utils;
class BreakdanceFaq {
options={
accordion: false,
openFirst: false,
};
constructor(selector, options){
this.selector=selector;
this.options=mergeObjects(this.options, options||{});
this.init();
}
toggleItem(event, item){
const targetEl=item ? item:event.target;
const faqEl=targetEl.closest(".bde-faq__item");
const isActive=faqEl.classList.contains("is-active");
if(this.options.accordion){
this.closeAllItemsExcept(targetEl);
}
if(isActive){
this.closeItem(targetEl);
}else{
this.showItem(targetEl);
}}
closeAllItems(){
this.elements.forEach((item)=> this.closeItem(item));
}
closeAllItemsExcept(item){
this.elements
.filter((el)=> el!==item)
.forEach((el)=> this.closeItem(el));
}
isTransitioning(item){
return item.classList.contains("is-collapsing");
}
isActive(item){
return item.classList.contains("is-active");
}
async closeItem(item){
const faqEl=item.closest(".bde-faq__item");
if(this.isTransitioning(faqEl)) return;
if(!this.isActive(faqEl)) return;
const faqButton=faqEl.querySelector(".bde-faq__question");
const faqContent=faqEl.querySelector(".bde-faq__answer");
const endHeight=this.getEndHeight(faqContent);
faqContent.style.height=`${endHeight}px`;
this.reflow(faqContent);
faqEl.classList.add("is-collapsing");
faqEl.classList.remove("is-active");
faqContent.style.height="";
faqButton.setAttribute("aria-expanded", false);
await this.onTransitionEnd(faqContent);
faqEl.classList.remove("is-collapsing");
}
async showItem(item, instant=false){
const faqEl=item.closest(".bde-faq__item");
if(this.isTransitioning(faqEl)) return;
if(this.isActive(faqEl)) return;
const faqButton=faqEl.querySelector(".bde-faq__question");
const faqContent=faqEl.querySelector(".bde-faq__answer");
const complete=()=> {
faqEl.classList.add("is-active");
faqEl.classList.remove("is-collapsing");
faqContent.style.height="";
};
if(instant){
complete();
faqButton.setAttribute("aria-expanded", true);
return;
}
faqEl.classList.add("is-collapsing");
faqContent.style.height="0px";
const endHeight=this.getEndHeight(faqContent);
faqContent.style.height=`${endHeight}px`;
faqButton.setAttribute("aria-expanded", true);
await this.onTransitionEnd(faqContent);
complete();
}
getEndHeight(element){
const height=element.getBoundingClientRect().height;
return Math.max(element.scrollHeight, height);
}
reflow(element){
element.offsetHeight;
}
update(options={}){
this.options=mergeObjects(this.options, options);
this.destroy();
this.init();
}
openFirst(){
if(!this.elements[0]) return;
this.showItem(this.elements[0], true);
}
onTransitionEnd(item){
const duration=window.getComputedStyle(item)
.getPropertyValue("transition-duration");
if(duration==="0s"){
return Promise.resolve();
}
return new Promise((resolve)=> {
item.addEventListener("transitionend", resolve, { once: true });
});
}
destroy(){
this.elements=Array.from(document.querySelectorAll(`${this.selector} .js-faq-item`
));
if(!this.elements) return;
this.closeAllItems();
this.elements.forEach((item)=>
item.removeEventListener("click", this.onClick)
);
}
bindClickListeners(){
this.onClick=this.toggleItem.bind(this);
this.elements.forEach((item)=> {
item.addEventListener("click", this.onClick);
});
}
init(){
this.elements=Array.from(document.querySelectorAll(`${this.selector} .js-faq-item`
));
if(this.options.openFirst===true){
this.openFirst();
}
this.bindClickListeners();
}}
window.BreakdanceFaq=BreakdanceFaq;
})();