").addClass(c.dotsClass).appendTo(this.$element)).addClass("disabled"),this._controls.$absolute.on("click","div",a.proxy(function(b){var d=a(b.target).parent().is(this._controls.$absolute)?a(b.target).index():a(b.target).parent().index();b.preventDefault(),this.to(d,c.dotsSpeed)},this));for(b in this._overrides)this._core[b]=a.proxy(this[b],this)},e.prototype.destroy=function(){var a,b,c,d;for(a in this._handlers)this.$element.off(a,this._handlers[a]);for(b in this._controls)this._controls[b].remove();for(d in this.overides)this._core[d]=this._overrides[d];for(c in Object.getOwnPropertyNames(this))"function"!=typeof this[c]&&(this[c]=null)},e.prototype.update=function(){var a,b,c,d=this._core.clones().length/2,e=d+this._core.items().length,f=this._core.maximum(!0),g=this._core.settings,h=g.center||g.autoWidth||g.dotsData?1:g.dotsEach||g.items;if("page"!==g.slideBy&&(g.slideBy=Math.min(g.slideBy,g.items)),g.dots||"page"==g.slideBy)for(this._pages=[],a=d,b=0,c=0;a
=h||0===b){if(this._pages.push({start:Math.min(f,a-d),end:a-d+h-1}),Math.min(f,a-d)===f)break;b=0,++c}b+=this._core.mergers(this._core.relative(a))}},e.prototype.draw=function(){var b,c=this._core.settings,d=this._core.items().length<=c.items,e=this._core.relative(this._core.current()),f=c.loop||c.rewind;this._controls.$relative.toggleClass("disabled",!c.nav||d),c.nav&&(this._controls.$previous.toggleClass("disabled",!f&&e<=this._core.minimum(!0)),this._controls.$next.toggleClass("disabled",!f&&e>=this._core.maximum(!0))),this._controls.$absolute.toggleClass("disabled",!c.dots||d),c.dots&&(b=this._pages.length-this._controls.$absolute.children().length,c.dotsData&&0!==b?this._controls.$absolute.html(this._templates.join("")):b>0?this._controls.$absolute.append(new Array(b+1).join(this._templates[0])):b<0&&this._controls.$absolute.children().slice(b).remove(),this._controls.$absolute.find(".active").removeClass("active"),this._controls.$absolute.children().eq(a.inArray(this.current(),this._pages)).addClass("active"))},e.prototype.onTrigger=function(b){var c=this._core.settings;b.page={index:a.inArray(this.current(),this._pages),count:this._pages.length,size:c&&(c.center||c.autoWidth||c.dotsData?1:c.dotsEach||c.items)}},e.prototype.current=function(){var b=this._core.relative(this._core.current());return a.grep(this._pages,a.proxy(function(a,c){return a.start<=b&&a.end>=b},this)).pop()},e.prototype.getPosition=function(b){var c,d,e=this._core.settings;return"page"==e.slideBy?(c=a.inArray(this.current(),this._pages),d=this._pages.length,b?++c:--c,c=this._pages[(c%d+d)%d].start):(c=this._core.relative(this._core.current()),d=this._core.items().length,b?c+=e.slideBy:c-=e.slideBy),c},e.prototype.next=function(b){a.proxy(this._overrides.to,this._core)(this.getPosition(!0),b)},e.prototype.prev=function(b){a.proxy(this._overrides.to,this._core)(this.getPosition(!1),b)},e.prototype.to=function(b,c,d){var e;!d&&this._pages.length?(e=this._pages.length,a.proxy(this._overrides.to,this._core)(this._pages[(b%e+e)%e].start,c)):a.proxy(this._overrides.to,this._core)(b,c)},a.fn.owlCarousel.Constructor.Plugins.Navigation=e}(window.Zepto||window.jQuery,window,document),function(a,b,c,d){"use strict";var e=function(c){this._core=c,this._hashes={},this.$element=this._core.$element,this._handlers={"initialized.owl.carousel":a.proxy(function(c){c.namespace&&"URLHash"===this._core.settings.startPosition&&a(b).trigger("hashchange.owl.navigation")},this),"prepared.owl.carousel":a.proxy(function(b){if(b.namespace){var c=a(b.content).find("[data-hash]").addBack("[data-hash]").attr("data-hash");if(!c)return;this._hashes[c]=b.content}},this),"changed.owl.carousel":a.proxy(function(c){if(c.namespace&&"position"===c.property.name){var d=this._core.items(this._core.relative(this._core.current())),e=a.map(this._hashes,function(a,b){return a===d?b:null}).join();if(!e||b.location.hash.slice(1)===e)return;b.location.hash=e}},this)},this._core.options=a.extend({},e.Defaults,this._core.options),this.$element.on(this._handlers),a(b).on("hashchange.owl.navigation",a.proxy(function(a){var c=b.location.hash.substring(1),e=this._core.$stage.children(),f=this._hashes[c]&&e.index(this._hashes[c]);f!==d&&f!==this._core.current()&&this._core.to(this._core.relative(f),!1,!0)},this))};e.Defaults={URLhashListener:!1},e.prototype.destroy=function(){var c,d;a(b).off("hashchange.owl.navigation");for(c in this._handlers)this._core.$element.off(c,this._handlers[c]);for(d in Object.getOwnPropertyNames(this))"function"!=typeof this[d]&&(this[d]=null)},a.fn.owlCarousel.Constructor.Plugins.Hash=e}(window.Zepto||window.jQuery,window,document),function(a,b,c,d){function e(b,c){var e=!1,f=b.charAt(0).toUpperCase()+b.slice(1);return a.each((b+" "+h.join(f+" ")+f).split(" "),function(a,b){if(g[b]!==d)return e=!c||b,!1}),e}function f(a){return e(a,!0)}var g=a("").get(0).style,h="Webkit Moz O ms".split(" "),i={transition:{end:{WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd",transition:"transitionend"}},animation:{end:{WebkitAnimation:"webkitAnimationEnd",MozAnimation:"animationend",OAnimation:"oAnimationEnd",animation:"animationend"}}},j={csstransforms:function(){return!!e("transform")},csstransforms3d:function(){return!!e("perspective")},csstransitions:function(){return!!e("transition")},cssanimations:function(){return!!e("animation")}};j.csstransitions()&&(a.support.transition=new String(f("transition")),a.support.transition.end=i.transition.end[a.support.transition]),j.cssanimations()&&(a.support.animation=new String(f("animation")),a.support.animation.end=i.animation.end[a.support.animation]),j.csstransforms()&&(a.support.transform=new String(f("transform")),a.support.transform3d=j.csstransforms3d())}(window.Zepto||window.jQuery,window,document);
// source --> http://sofa21.ie/wp-content/themes/formula/assets/vendors/odometer/odometer.min.js?ver=6.0.3
/*! odometer 0.4.6 */
(function(){var a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G=[].slice;q='',n=''+q+"",d='8'+n+"",g='',c="(,ddd).dd",h=/^\(?([^)]*)\)?(?:(.)(d+))?$/,i=30,f=2e3,a=20,j=2,e=.5,k=1e3/i,b=1e3/a,o="transitionend webkitTransitionEnd oTransitionEnd otransitionend MSTransitionEnd",y=document.createElement("div").style,p=null!=y.transition||null!=y.webkitTransition||null!=y.mozTransition||null!=y.oTransition,w=window.requestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||window.msRequestAnimationFrame,l=window.MutationObserver||window.WebKitMutationObserver||window.MozMutationObserver,s=function(a){var b;return b=document.createElement("div"),b.innerHTML=a,b.children[0]},v=function(a,b){return a.className=a.className.replace(new RegExp("(^| )"+b.split(" ").join("|")+"( |$)","gi")," ")},r=function(a,b){return v(a,b),a.className+=" "+b},z=function(a,b){var c;return null!=document.createEvent?(c=document.createEvent("HTMLEvents"),c.initEvent(b,!0,!0),a.dispatchEvent(c)):void 0},u=function(){var a,b;return null!=(a=null!=(b=window.performance)?"function"==typeof b.now?b.now():void 0:void 0)?a:+new Date},x=function(a,b){return null==b&&(b=0),b?(a*=Math.pow(10,b),a+=.5,a=Math.floor(a),a/=Math.pow(10,b)):Math.round(a)},A=function(a){return 0>a?Math.ceil(a):Math.floor(a)},t=function(a){return a-x(a)},C=!1,(B=function(){var a,b,c,d,e;if(!C&&null!=window.jQuery){for(C=!0,d=["html","text"],e=[],b=0,c=d.length;c>b;b++)a=d[b],e.push(function(a){var b;return b=window.jQuery.fn[a],window.jQuery.fn[a]=function(a){var c;return null==a||null==(null!=(c=this[0])?c.odometer:void 0)?b.apply(this,arguments):this[0].odometer.update(a)}}(a));return e}})(),setTimeout(B,0),m=function(){function a(b){var c,d,e,g,h,i,l,m,n,o,p=this;if(this.options=b,this.el=this.options.el,null!=this.el.odometer)return this.el.odometer;this.el.odometer=this,m=a.options;for(d in m)g=m[d],null==this.options[d]&&(this.options[d]=g);null==(h=this.options).duration&&(h.duration=f),this.MAX_VALUES=this.options.duration/k/j|0,this.resetFormat(),this.value=this.cleanValue(null!=(n=this.options.value)?n:""),this.renderInside(),this.render();try{for(o=["innerHTML","innerText","textContent"],i=0,l=o.length;l>i;i++)e=o[i],null!=this.el[e]&&!function(a){return Object.defineProperty(p.el,a,{get:function(){var b;return"innerHTML"===a?p.inside.outerHTML:null!=(b=p.inside.innerText)?b:p.inside.textContent},set:function(a){return p.update(a)}})}(e)}catch(q){c=q,this.watchForMutations()}}return a.prototype.renderInside=function(){return this.inside=document.createElement("div"),this.inside.className="odometer-inside",this.el.innerHTML="",this.el.appendChild(this.inside)},a.prototype.watchForMutations=function(){var a,b=this;if(null!=l)try{return null==this.observer&&(this.observer=new l(function(){var a;return a=b.el.innerText,b.renderInside(),b.render(b.value),b.update(a)})),this.watchMutations=!0,this.startWatchingMutations()}catch(c){a=c}},a.prototype.startWatchingMutations=function(){return this.watchMutations?this.observer.observe(this.el,{childList:!0}):void 0},a.prototype.stopWatchingMutations=function(){var a;return null!=(a=this.observer)?a.disconnect():void 0},a.prototype.cleanValue=function(a){var b;return"string"==typeof a&&(a=a.replace(null!=(b=this.format.radix)?b:".",""),a=a.replace(/[.,]/g,""),a=a.replace("","."),a=parseFloat(a,10)||0),x(a,this.format.precision)},a.prototype.bindTransitionEnd=function(){var a,b,c,d,e,f,g=this;if(!this.transitionEndBound){for(this.transitionEndBound=!0,b=!1,e=o.split(" "),f=[],c=0,d=e.length;d>c;c++)a=e[c],f.push(this.el.addEventListener(a,function(){return b?!0:(b=!0,setTimeout(function(){return g.render(),b=!1,z(g.el,"odometerdone")},0),!0)},!1));return f}},a.prototype.resetFormat=function(){var a,b,d,e,f,g,i,j;if(a=null!=(i=this.options.format)?i:c,a||(a="d"),d=h.exec(a),!d)throw new Error("Odometer: Unparsable digit format");return j=d.slice(1,4),g=j[0],f=j[1],b=j[2],e=(null!=b?b.length:void 0)||0,this.format={repeating:g,radix:f,precision:e}},a.prototype.render=function(a){var b,c,d,e,f,g,h,i,j,k,l,m;for(null==a&&(a=this.value),this.stopWatchingMutations(),this.resetFormat(),this.inside.innerHTML="",g=this.options.theme,b=this.el.className.split(" "),f=[],i=0,k=b.length;k>i;i++)c=b[i],c.length&&((e=/^odometer-theme-(.+)$/.exec(c))?g=e[1]:/^odometer(-|$)/.test(c)||f.push(c));for(f.push("odometer"),p||f.push("odometer-no-transitions"),f.push(g?"odometer-theme-"+g:"odometer-auto-theme"),this.el.className=f.join(" "),this.ribbons={},this.digits=[],h=!this.format.precision||!t(a)||!1,m=a.toString().split("").reverse(),j=0,l=m.length;l>j;j++)d=m[j],"."===d&&(h=!0),this.addDigit(d,h);return this.startWatchingMutations()},a.prototype.update=function(a){var b,c=this;return a=this.cleanValue(a),(b=a-this.value)?(v(this.el,"odometer-animating-up odometer-animating-down odometer-animating"),b>0?r(this.el,"odometer-animating-up"):r(this.el,"odometer-animating-down"),this.stopWatchingMutations(),this.animate(a),this.startWatchingMutations(),setTimeout(function(){return c.el.offsetHeight,r(c.el,"odometer-animating")},0),this.value=a):void 0},a.prototype.renderDigit=function(){return s(d)},a.prototype.insertDigit=function(a,b){return null!=b?this.inside.insertBefore(a,b):this.inside.children.length?this.inside.insertBefore(a,this.inside.children[0]):this.inside.appendChild(a)},a.prototype.addSpacer=function(a,b,c){var d;return d=s(g),d.innerHTML=a,c&&r(d,c),this.insertDigit(d,b)},a.prototype.addDigit=function(a,b){var c,d,e,f;if(null==b&&(b=!0),"-"===a)return this.addSpacer(a,null,"odometer-negation-mark");if("."===a)return this.addSpacer(null!=(f=this.format.radix)?f:".",null,"odometer-radix-mark");if(b)for(e=!1;;){if(!this.format.repeating.length){if(e)throw new Error("Bad odometer format without digits");this.resetFormat(),e=!0}if(c=this.format.repeating[this.format.repeating.length-1],this.format.repeating=this.format.repeating.substring(0,this.format.repeating.length-1),"d"===c)break;this.addSpacer(c)}return d=this.renderDigit(),d.querySelector(".odometer-value").innerHTML=a,this.digits.push(d),this.insertDigit(d)},a.prototype.animate=function(a){return p&&"count"!==this.options.animation?this.animateSlide(a):this.animateCount(a)},a.prototype.animateCount=function(a){var c,d,e,f,g,h=this;if(d=+a-this.value)return f=e=u(),c=this.value,(g=function(){var i,j,k;return u()-f>h.options.duration?(h.value=a,h.render(),void z(h.el,"odometerdone")):(i=u()-e,i>b&&(e=u(),k=i/h.options.duration,j=d*k,c+=j,h.render(Math.round(c))),null!=w?w(g):setTimeout(g,b))})()},a.prototype.getDigitCount=function(){var a,b,c,d,e,f;for(d=1<=arguments.length?G.call(arguments,0):[],a=e=0,f=d.length;f>e;a=++e)c=d[a],d[a]=Math.abs(c);return b=Math.max.apply(Math,d),Math.ceil(Math.log(b+1)/Math.log(10))},a.prototype.getFractionalDigitCount=function(){var a,b,c,d,e,f,g;for(e=1<=arguments.length?G.call(arguments,0):[],b=/^\-?\d*\.(\d*?)0*$/,a=f=0,g=e.length;g>f;a=++f)d=e[a],e[a]=d.toString(),c=b.exec(e[a]),e[a]=null==c?0:c[1].length;return Math.max.apply(Math,e)},a.prototype.resetDigits=function(){return this.digits=[],this.ribbons=[],this.inside.innerHTML="",this.resetFormat()},a.prototype.animateSlide=function(a){var b,c,d,f,g,h,i,j,k,l,m,n,o,p,q,s,t,u,v,w,x,y,z,B,C,D,E;if(s=this.value,j=this.getFractionalDigitCount(s,a),j&&(a*=Math.pow(10,j),s*=Math.pow(10,j)),d=a-s){for(this.bindTransitionEnd(),f=this.getDigitCount(s,a),g=[],b=0,m=v=0;f>=0?f>v:v>f;m=f>=0?++v:--v){if(t=A(s/Math.pow(10,f-m-1)),i=A(a/Math.pow(10,f-m-1)),h=i-t,Math.abs(h)>this.MAX_VALUES){for(l=[],n=h/(this.MAX_VALUES+this.MAX_VALUES*b*e),c=t;h>0&&i>c||0>h&&c>i;)l.push(Math.round(c)),c+=n;l[l.length-1]!==i&&l.push(i),b++}else l=function(){E=[];for(var a=t;i>=t?i>=a:a>=i;i>=t?a++:a--)E.push(a);return E}.apply(this);for(m=w=0,y=l.length;y>w;m=++w)k=l[m],l[m]=Math.abs(k%10);g.push(l)}for(this.resetDigits(),D=g.reverse(),m=x=0,z=D.length;z>x;m=++x)for(l=D[m],this.digits[m]||this.addDigit(" ",m>=j),null==(u=this.ribbons)[m]&&(u[m]=this.digits[m].querySelector(".odometer-ribbon-inner")),this.ribbons[m].innerHTML="",0>d&&(l=l.reverse()),o=C=0,B=l.length;B>C;o=++C)k=l[o],q=document.createElement("div"),q.className="odometer-value",q.innerHTML=k,this.ribbons[m].appendChild(q),o===l.length-1&&r(q,"odometer-last-value"),0===o&&r(q,"odometer-first-value");return 0>t&&this.addDigit("-"),p=this.inside.querySelector(".odometer-radix-mark"),null!=p&&p.parent.removeChild(p),j?this.addSpacer(this.format.radix,this.digits[j-1],"odometer-radix-mark"):void 0}},a}(),m.options=null!=(E=window.odometerOptions)?E:{},setTimeout(function(){var a,b,c,d,e;if(window.odometerOptions){d=window.odometerOptions,e=[];for(a in d)b=d[a],e.push(null!=(c=m.options)[a]?(c=m.options)[a]:c[a]=b);return e}},0),m.init=function(){var a,b,c,d,e,f;if(null!=document.querySelectorAll){for(b=document.querySelectorAll(m.options.selector||".odometer"),f=[],c=0,d=b.length;d>c;c++)a=b[c],f.push(a.odometer=new m({el:a,value:null!=(e=a.innerText)?e:a.textContent}));return f}},null!=(null!=(F=document.documentElement)?F.doScroll:void 0)&&null!=document.createEventObject?(D=document.onreadystatechange,document.onreadystatechange=function(){return"complete"===document.readyState&&m.options.auto!==!1&&m.init(),null!=D?D.apply(this,arguments):void 0}):document.addEventListener("DOMContentLoaded",function(){return m.options.auto!==!1?m.init():void 0},!1),"function"==typeof define&&define.amd?define(["jquery"],function(){return m}):typeof exports===!1?module.exports=m:window.Odometer=m}).call(this);
// source --> http://sofa21.ie/wp-content/themes/formula/assets/js/formula.js?ver=6.0.3
/*My js*/
// Accodian Js
function toggleIcon(e) {
jQuery(e.target)
.prev('.panel-heading')
.find(".more-less")
.toggleClass('fa-plus-square-o fa-minus-square-o');
}
jQuery('.panel-group').on('hidden.bs.collapse', toggleIcon);
jQuery('.panel-group').on('shown.bs.collapse', toggleIcon);
const openedMenu = document.querySelector('.opened-menu');
const closedMenu = document.querySelector('.closed-menu');
const navbarMenu = document.querySelector('.navbar');
const menuOverlay = document.querySelector('.overlay');
jQuery(window).on("scroll", function () {
if (jQuery(".sticky-menu").length) {
var headerScrollPos = 100;
var sticky = jQuery(".sticky-menu");
if (jQuery(window).scrollTop() > headerScrollPos) {
sticky.addClass("sticky-fixed");
sticky.removeClass("not-sticky");
} else if (jQuery(this).scrollTop() <= headerScrollPos) {
sticky.removeClass("sticky-fixed");
sticky.addClass("not-sticky");
}
}
});
// Toggle Menu Function
function toggleMenu() {
navbarMenu.classList.toggle('active');
menuOverlay.classList.toggle('active');
document.body.classList.toggle('locked');
}
jQuery(document).ready(function() {
// WOW
new WOW().init();
//odometer
var odo = jQuery(".odometer");
odo.each(function() {
jQuery(this).appear(function() {
var countNumber = jQuery(this).attr("data-count");
jQuery(this).html(countNumber);
});
});
jQuery(".navbar").focus();
});
(function() {
var isIe = /(trident|msie)/i.test(navigator.userAgent);
if (isIe && document.getElementById && window.addEventListener) {
window.addEventListener('hashchange', function() {
var id = location.hash.substring(1),
element;
if (!(/^[A-z0-9_-]+$/.test(id))) {
return;
}
element = document.getElementById(id);
if (element) {
if (!(/^(?:a|select|input|button|textarea)$/i.test(element.tagName))) {
element.tabIndex = -1;
}
element.focus();
}
}, false);
}
}());
/* ---------------------------------------------- /*
* Scroll top
/* ---------------------------------------------- */
jQuery(window).scroll(function() {
if (jQuery(this).scrollTop() > 100) {
jQuery('.page-scroll-up').fadeIn();
} else {
jQuery('.page-scroll-up').fadeOut();
}
});
jQuery('.page-scroll-up').click(function() {
jQuery("html, body").animate({
scrollTop: 0
}, 700);
return false;
});
jQuery(document).ready(function() {
/* Loader */
if (jQuery(".page-loader").length) {
jQuery(".page-loader").fadeOut();
}
});
jQuery(document).ready(function() {
/* jQuery("#slider-demo").owlCarousel({
navigation: true, // Show next and prev buttons
autoplay: false,
animateOut: 'fadeOut', // fadeout
autoplayTimeout: 3000,
autoplayHoverPause: true,
smartSpeed: 800,
singleItem: true,
autoHeight: true,
loop: false, // loop is true up to 1199px screen.
nav: true, // is true across all sizes
margin: 0, // margin 10px till 960 breakpoint
responsiveClass: true, // Optional helper class. Add 'owl-reponsive-' + 'breakpoint' class to main element.
items: 1,
dots: false,
navText: ["PREV", "NEXT"]
});
jQuery("#testimonial-demo").owlCarousel({
navigation: true,
autoplay: false,
autoplayTimeout: 3000,
autoplayHoverPause: true,
smartSpeed: 1000,
loop: false,
nav: true,
margin: 30,
autoHeight: true,
responsiveClass: true,
dots: false,
navText: ["", ""],
responsive: {
200: { items: 1 },
480: { items: 1 },
768: { items: 2 },
1000: { items: 2 }
}
});
jQuery("#sponsors-demo").owlCarousel({
navigation: false,
autoplay: true,
autoplayTimeout: 3000,
autoplayHoverPause: true,
smartSpeed: 700,
loop: true,
nav: false,
margin: 30,
autoHeight: true,
responsiveClass: true,
dots: false,
responsive: {
200: { items: 1 },
480: { items: 1 },
768: { items: 3 },
1000: { items: 5 }
}
});
jQuery("#team-demo").owlCarousel({
navigation: false,
autoplay: false,
autoplayTimeout: 3000,
autoplayHoverPause: true,
smartSpeed: 700,
loop: true, // loop is true up to 1199px screen.
nav: false, // is true across all sizes
margin: 30, // margin 10px till 960 breakpoint
autoHeight: true,
responsiveClass: true,
dots: false,
navText: ["", ""],
responsive: {
100: { items: 1 },
480: { items: 1 },
768: { items: 2 },
1000: { items: 4 }
}
});
jQuery("#portfolio-demo").owlCarousel({
navigation: false,
autoplay: false,
autoplayTimeout: 3000,
autoplayHoverPause: true,
smartSpeed: 700,
loop: true, // loop is true up to 1199px screen.
nav: false, // is true across all sizes
margin: 30, // margin 10px till 960 breakpoint
autoHeight: true,
responsiveClass: true,
dots: false,
navText: ["", ""],
responsive: {
100: { items: 1 },
480: { items: 1 },
768: { items: 2 },
1000: { items: 3 }
}
}); */
/* add class to menu */
/* var ul_p = jQuery('.navbar ul > li').length;
var ul_c = jQuery('.sub-menu > li').length;
var ul_l = ul_p - ul_c;
if (ul_l > 8) {
jQuery('.header-top-info').removeClass('container');
jQuery('.header-top-info').addClass('container-fluid');
jQuery('.nav-wrap').removeClass('container');
jQuery('.nav-wrap').addClass('container-fluid');
} */
});
// source --> http://sofa21.ie/wp-content/themes/formula/assets/js/index.js?ver=0.0.5
/* -----------------------------------------------------------------------------------------------
Namespace
--------------------------------------------------------------------------------------------------- */
var formula = formula || {};
// Set a default value for scrolled.
formula.scrolled = 0;
// polyfill closest
// https://developer.mozilla.org/en-US/docs/Web/API/Element/closest#Polyfill
if ( ! Element.prototype.closest ) {
Element.prototype.closest = function( s ) {
var el = this;
do {
if ( el.matches( s ) ) {
return el;
}
el = el.parentElement || el.parentNode;
} while ( el !== null && el.nodeType === 1 );
return null;
};
}
// polyfill forEach
// https://developer.mozilla.org/en-US/docs/Web/API/NodeList/forEach#Polyfill
if ( window.NodeList && ! NodeList.prototype.forEach ) {
NodeList.prototype.forEach = function( callback, thisArg ) {
var i;
var len = this.length;
thisArg = thisArg || window;
for ( i = 0; i < len; i++ ) {
callback.call( thisArg, this[ i ], i, this );
}
};
}
// event "polyfill"
formula.createEvent = function( eventName ) {
var event;
if ( typeof window.Event === 'function' ) {
event = new Event( eventName );
} else {
event = document.createEvent( 'Event' );
event.initEvent( eventName, true, false );
}
return event;
};
// matches "polyfill"
// https://developer.mozilla.org/es/docs/Web/API/Element/matches
if ( ! Element.prototype.matches ) {
Element.prototype.matches =
Element.prototype.matchesSelector ||
Element.prototype.mozMatchesSelector ||
Element.prototype.msMatchesSelector ||
Element.prototype.oMatchesSelector ||
Element.prototype.webkitMatchesSelector ||
function( s ) {
var matches = ( this.document || this.ownerDocument ).querySelectorAll( s ),
i = matches.length;
while ( --i >= 0 && matches.item( i ) !== this ) {}
return i > -1;
};
}
// Add a class to the body for when touch is enabled for browsers that don't support media queries
// for interaction media features. Adapted from .
formula.touchEnabled = {
init: function() {
var matchMedia = function() {
// Include the 'heartz' as a way to have a non-matching MQ to help terminate the join. See .
var prefixes = [ '-webkit-', '-moz-', '-o-', '-ms-' ];
var query = [ '(', prefixes.join( 'touch-enabled),(' ), 'heartz', ')' ].join( '' );
return window.matchMedia && window.matchMedia( query ).matches;
};
if ( ( 'ontouchstart' in window ) || ( window.DocumentTouch && document instanceof window.DocumentTouch ) || matchMedia() ) {
document.body.classList.add( 'touch-enabled' );
}
}
}; // formula.touchEnabled
/* -----------------------------------------------------------------------------------------------
Cover Modals
--------------------------------------------------------------------------------------------------- */
formula.coverModals = {
init: function() {
if ( document.querySelector( '.cover-modal' ) ) {
// Handle cover modals when they're toggled.
this.onToggle();
// When toggled, untoggle if visitor clicks on the wrapping element of the modal.
this.outsideUntoggle();
// Close on escape key press.
this.closeOnEscape();
// Hide and show modals before and after their animations have played out.
this.hideAndShowModals();
}
},
// Handle cover modals when they're toggled.
onToggle: function() {
document.querySelectorAll( '.cover-modal' ).forEach( function( element ) {
element.addEventListener( 'toggled', function( event ) {
var modal = event.target,
body = document.body;
if ( modal.classList.contains( 'active' ) ) {
body.classList.add( 'showing-modal' );
} else {
body.classList.remove( 'showing-modal' );
body.classList.add( 'hiding-modal' );
// Remove the hiding class after a delay, when animations have been run.
setTimeout( function() {
body.classList.remove( 'hiding-modal' );
}, 500 );
}
} );
} );
},
// Close modal on outside click.
outsideUntoggle: function() {
document.addEventListener( 'click', function( event ) {
var target = event.target;
var modal = document.querySelector( '.cover-modal.active' );
// if target onclick is with # within the href attribute
if ( event.target.tagName.toLowerCase() === 'a' && event.target.hash.includes( '#' ) && modal !== null ) {
// untoggle the modal
this.untoggleModal( modal );
// wait 550 and scroll to the anchor
setTimeout( function() {
var anchor = document.getElementById( event.target.hash.slice( 1 ) );
anchor.scrollIntoView();
}, 550 );
}
if ( target === modal ) {
this.untoggleModal( target );
}
}.bind( this ) );
},
// Close modal on escape key press.
closeOnEscape: function() {
document.addEventListener( 'keydown', function( event ) {
if ( event.keyCode === 27 ) {
event.preventDefault();
document.querySelectorAll( '.cover-modal.active' ).forEach( function( element ) {
this.untoggleModal( element );
}.bind( this ) );
}
}.bind( this ) );
},
// Hide and show modals before and after their animations have played out.
hideAndShowModals: function() {
var _doc = document,
_win = window,
modals = _doc.querySelectorAll( '.cover-modal' ),
htmlStyle = _doc.documentElement.style,
adminBar = _doc.querySelector( '#wpadminbar' );
function getAdminBarHeight( negativeValue ) {
var height,
currentScroll = _win.pageYOffset;
if ( adminBar ) {
height = currentScroll + adminBar.getBoundingClientRect().height;
return negativeValue ? -height : height;
}
return currentScroll === 0 ? 0 : -currentScroll;
}
function htmlStyles() {
var overflow = _win.innerHeight > _doc.documentElement.getBoundingClientRect().height;
return {
'overflow-y': overflow ? 'hidden' : 'scroll',
position: 'fixed',
width: '100%',
top: getAdminBarHeight( true ) + 'px',
left: 0
};
}
// Show the modal.
modals.forEach( function( modal ) {
modal.addEventListener( 'toggle-target-before-inactive', function( event ) {
var styles = htmlStyles(),
offsetY = _win.pageYOffset,
paddingTop = ( Math.abs( getAdminBarHeight() ) - offsetY ) + 'px',
mQuery = _win.matchMedia( '(max-width: 600px)' );
if ( event.target !== modal ) {
return;
}
Object.keys( styles ).forEach( function( styleKey ) {
htmlStyle.setProperty( styleKey, styles[ styleKey ] );
} );
_win.formula.scrolled = parseInt( styles.top, 10 );
if ( adminBar ) {
_doc.body.style.setProperty( 'padding-top', paddingTop );
if ( mQuery.matches ) {
if ( offsetY >= getAdminBarHeight() ) {
modal.style.setProperty( 'top', 0 );
} else {
modal.style.setProperty( 'top', ( getAdminBarHeight() - offsetY ) + 'px' );
}
}
}
modal.classList.add( 'show-modal' );
} );
// Hide the modal after a delay, so animations have time to play out.
modal.addEventListener( 'toggle-target-after-inactive', function( event ) {
if ( event.target !== modal ) {
return;
}
setTimeout( function() {
var clickedEl = formula.toggles.clickedEl;
modal.classList.remove( 'show-modal' );
Object.keys( htmlStyles() ).forEach( function( styleKey ) {
htmlStyle.removeProperty( styleKey );
} );
if ( adminBar ) {
_doc.body.style.removeProperty( 'padding-top' );
modal.style.removeProperty( 'top' );
}
if ( clickedEl !== false ) {
clickedEl.focus();
clickedEl = false;
}
_win.scrollTo( 0, Math.abs( _win.formula.scrolled + getAdminBarHeight() ) );
_win.formula.scrolled = 0;
}, 500 );
} );
} );
},
// Untoggle a modal.
untoggleModal: function( modal ) {
var modalTargetClass,
modalToggle = false;
// If the modal has specified the string (ID or class) used by toggles to target it, untoggle the toggles with that target string.
// The modal-target-string must match the string toggles use to target the modal.
if ( modal.dataset.modalTargetString ) {
modalTargetClass = modal.dataset.modalTargetString;
modalToggle = document.querySelector( '*[data-toggle-target="' + modalTargetClass + '"]' );
}
// If a modal toggle exists, trigger it so all of the toggle options are included.
if ( modalToggle ) {
modalToggle.click();
// If one doesn't exist, just hide the modal.
} else {
modal.classList.remove( 'active' );
}
}
}; // formula.coverModals
/* -----------------------------------------------------------------------------------------------
Intrinsic Ratio Embeds
--------------------------------------------------------------------------------------------------- */
formula.intrinsicRatioVideos = {
init: function() {
this.makeFit();
window.addEventListener( 'resize', function() {
this.makeFit();
}.bind( this ) );
},
makeFit: function() {
document.querySelectorAll( 'iframe, object, video' ).forEach( function( video ) {
var ratio, iTargetWidth,
container = video.parentNode;
// Skip videos we want to ignore.
if ( video.classList.contains( 'intrinsic-ignore' ) || video.parentNode.classList.contains( 'intrinsic-ignore' ) ) {
return true;
}
if ( ! video.dataset.origwidth ) {
// Get the video element proportions.
video.setAttribute( 'data-origwidth', video.width );
video.setAttribute( 'data-origheight', video.height );
}
iTargetWidth = container.offsetWidth;
// Get ratio from proportions.
ratio = iTargetWidth / video.dataset.origwidth;
// Scale based on ratio, thus retaining proportions.
video.style.width = iTargetWidth + 'px';
video.style.height = ( video.dataset.origheight * ratio ) + 'px';
} );
}
}; // formula.instrinsicRatioVideos
/* -----------------------------------------------------------------------------------------------
Modal Menu
--------------------------------------------------------------------------------------------------- */
formula.modalMenu = {
init: function() {
// If the current menu item is in a sub level, expand all the levels higher up on load.
this.expandLevel();
this.keepFocusInModal();
},
expandLevel: function() {
var modalMenus = document.querySelectorAll( '.modal-menu' );
modalMenus.forEach( function( modalMenu ) {
var activeMenuItem = modalMenu.querySelector( '.current-menu-item' );
if ( activeMenuItem ) {
formulaFindParents( activeMenuItem, 'li' ).forEach( function( element ) {
var subMenuToggle = element.querySelector( '.sub-menu-toggle' );
if ( subMenuToggle ) {
formula.toggles.performToggle( subMenuToggle, true );
}
} );
}
} );
},
keepFocusInModal: function() {
var _doc = document;
_doc.addEventListener( 'keydown', function( event ) {
var toggleTarget, modal, selectors, elements, menuType, bottomMenu, activeEl, lastEl, firstEl, tabKey, shiftKey,
clickedEl = formula.toggles.clickedEl;
if ( clickedEl && _doc.body.classList.contains( 'showing-modal' ) ) {
toggleTarget = clickedEl.dataset.toggleTarget;
selectors = 'input, a, button';
modal = _doc.querySelector( toggleTarget );
elements = modal.querySelectorAll( selectors );
elements = Array.prototype.slice.call( elements );
if ( '.menu-modal' === toggleTarget ) {
menuType = window.matchMedia( '(min-width: 1000px)' ).matches;
menuType = menuType ? '.expanded-menu' : '.mobile-menu';
elements = elements.filter( function( element ) {
return null !== element.closest( menuType ) && null !== element.offsetParent;
} );
elements.unshift( _doc.querySelector( '.close-nav-toggle' ) );
bottomMenu = _doc.querySelector( '.menu-bottom > nav' );
if ( bottomMenu ) {
bottomMenu.querySelectorAll( selectors ).forEach( function( element ) {
elements.push( element );
} );
}
}
lastEl = elements[ elements.length - 1 ];
firstEl = elements[0];
activeEl = _doc.activeElement;
tabKey = event.keyCode === 9;
shiftKey = event.shiftKey;
if ( ! shiftKey && tabKey && lastEl === activeEl ) {
event.preventDefault();
firstEl.focus();
}
if ( shiftKey && tabKey && firstEl === activeEl ) {
event.preventDefault();
lastEl.focus();
}
}
} );
}
}; // formula.modalMenu
/* -----------------------------------------------------------------------------------------------
Primary Menu
--------------------------------------------------------------------------------------------------- */
formula.primaryMenu = {
init: function() {
this.focusMenuWithChildren();
},
// The focusMenuWithChildren() function implements Keyboard Navigation in the Primary Menu
// by adding the '.focus' class to all 'li.menu-item-has-children' when the focus is on the 'a' element.
focusMenuWithChildren: function() {
// Get all the link elements within the primary menu.
var links, i, len,
menu = document.querySelector( '.primary-menu-wrapper' );
if ( ! menu ) {
return false;
}
links = menu.getElementsByTagName( 'a' );
// Each time a menu link is focused or blurred, toggle focus.
for ( i = 0, len = links.length; i < len; i++ ) {
links[i].addEventListener( 'focus', toggleFocus, true );
links[i].addEventListener( 'blur', toggleFocus, true );
}
//Sets or removes the .focus class on an element.
function toggleFocus() {
var self = this;
// Move up through the ancestors of the current link until we hit .primary-menu.
while ( -1 === self.className.indexOf( 'primary-menu' ) ) {
// On li elements toggle the class .focus.
if ( 'li' === self.tagName.toLowerCase() ) {
if ( -1 !== self.className.indexOf( 'focus' ) ) {
self.className = self.className.replace( ' focus', '' );
} else {
self.className += ' focus';
}
}
self = self.parentElement;
}
}
}
}; // formula.primaryMenu
/* -----------------------------------------------------------------------------------------------
Toggles
--------------------------------------------------------------------------------------------------- */
formula.toggles = {
clickedEl: false,
init: function() {
// Do the toggle.
this.toggle();
// Check for toggle/untoggle on resize.
this.resizeCheck();
// Check for untoggle on escape key press.
this.untoggleOnEscapeKeyPress();
},
performToggle: function( element, instantly ) {
var target, timeOutTime, classToToggle,
self = this,
_doc = document,
// Get our targets.
toggle = element,
targetString = toggle.dataset.toggleTarget,
activeClass = 'active';
// Elements to focus after modals are closed.
if ( ! _doc.querySelectorAll( '.show-modal' ).length ) {
self.clickedEl = _doc.activeElement;
}
if ( targetString === 'next' ) {
target = toggle.nextSibling;
} else {
target = _doc.querySelector( targetString );
}
// Trigger events on the toggle targets before they are toggled.
if ( target.classList.contains( activeClass ) ) {
target.dispatchEvent( formula.createEvent( 'toggle-target-before-active' ) );
} else {
target.dispatchEvent( formula.createEvent( 'toggle-target-before-inactive' ) );
}
// Get the class to toggle, if specified.
classToToggle = toggle.dataset.classToToggle ? toggle.dataset.classToToggle : activeClass;
// For cover modals, set a short timeout duration so the class animations have time to play out.
timeOutTime = 0;
if ( target.classList.contains( 'cover-modal' ) ) {
timeOutTime = 10;
}
setTimeout( function() {
var focusElement,
subMenued = target.classList.contains( 'sub-menu' ),
newTarget = subMenued ? toggle.closest( '.menu-item' ).querySelector( '.sub-menu' ) : target,
duration = toggle.dataset.toggleDuration;
// Toggle the target of the clicked toggle.
if ( toggle.dataset.toggleType === 'slidetoggle' && ! instantly && duration !== '0' ) {
formulaMenuToggle( newTarget, duration );
} else {
newTarget.classList.toggle( classToToggle );
}
// If the toggle target is 'next', only give the clicked toggle the active class.
if ( targetString === 'next' ) {
toggle.classList.toggle( activeClass );
} else if ( target.classList.contains( 'sub-menu' ) ) {
toggle.classList.toggle( activeClass );
} else {
// If not, toggle all toggles with this toggle target.
_doc.querySelector( '*[data-toggle-target="' + targetString + '"]' ).classList.toggle( activeClass );
}
// Toggle aria-expanded on the toggle.
formulaToggleAttribute( toggle, 'aria-expanded', 'true', 'false' );
if ( self.clickedEl && -1 !== toggle.getAttribute( 'class' ).indexOf( 'close-' ) ) {
formulaToggleAttribute( self.clickedEl, 'aria-expanded', 'true', 'false' );
}
// Toggle body class.
if ( toggle.dataset.toggleBodyClass ) {
_doc.body.classList.toggle( toggle.dataset.toggleBodyClass );
}
// Check whether to set focus.
if ( toggle.dataset.setFocus ) {
focusElement = _doc.querySelector( toggle.dataset.setFocus );
if ( focusElement ) {
if ( target.classList.contains( activeClass ) ) {
focusElement.focus();
} else {
focusElement.blur();
}
}
}
// Trigger the toggled event on the toggle target.
target.dispatchEvent( formula.createEvent( 'toggled' ) );
// Trigger events on the toggle targets after they are toggled.
if ( target.classList.contains( activeClass ) ) {
target.dispatchEvent( formula.createEvent( 'toggle-target-after-active' ) );
} else {
target.dispatchEvent( formula.createEvent( 'toggle-target-after-inactive' ) );
}
}, timeOutTime );
},
// Do the toggle.
toggle: function() {
var self = this;
document.querySelectorAll( '*[data-toggle-target]' ).forEach( function( element ) {
element.addEventListener( 'click', function( event ) {
event.preventDefault();
self.performToggle( element );
} );
} );
},
// Check for toggle/untoggle on screen resize.
resizeCheck: function() {
if ( document.querySelectorAll( '*[data-untoggle-above], *[data-untoggle-below], *[data-toggle-above], *[data-toggle-below]' ).length ) {
window.addEventListener( 'resize', function() {
var winWidth = window.innerWidth,
toggles = document.querySelectorAll( '.toggle' );
toggles.forEach( function( toggle ) {
var unToggleAbove = toggle.dataset.untoggleAbove,
unToggleBelow = toggle.dataset.untoggleBelow,
toggleAbove = toggle.dataset.toggleAbove,
toggleBelow = toggle.dataset.toggleBelow;
// If no width comparison is set, continue.
if ( ! unToggleAbove && ! unToggleBelow && ! toggleAbove && ! toggleBelow ) {
return;
}
// If the toggle width comparison is true, toggle the toggle.
if (
( ( ( unToggleAbove && winWidth > unToggleAbove ) ||
( unToggleBelow && winWidth < unToggleBelow ) ) &&
toggle.classList.contains( 'active' ) ) ||
( ( ( toggleAbove && winWidth > toggleAbove ) ||
( toggleBelow && winWidth < toggleBelow ) ) &&
! toggle.classList.contains( 'active' ) )
) {
toggle.click();
}
} );
} );
}
},
// Close toggle on escape key press.
untoggleOnEscapeKeyPress: function() {
document.addEventListener( 'keyup', function( event ) {
if ( event.key === 'Escape' ) {
document.querySelectorAll( '*[data-untoggle-on-escape].active' ).forEach( function( element ) {
if ( element.classList.contains( 'active' ) ) {
element.click();
}
} );
}
} );
}
}; // formula.toggles
/**
* Is the DOM ready?
*
* This implementation is coming from https://gomakethings.com/a-native-javascript-equivalent-of-jquerys-ready-method/
*
* @param {Function} fn Callback function to run.
*/
function formulaDomReady( fn ) {
if ( typeof fn !== 'function' ) {
return;
}
if ( document.readyState === 'interactive' || document.readyState === 'complete' ) {
return fn();
}
document.addEventListener( 'DOMContentLoaded', fn, false );
}
formulaDomReady( function() {
formula.toggles.init(); // Handle toggles.
formula.coverModals.init(); // Handle cover modals.
formula.intrinsicRatioVideos.init(); // Retain aspect ratio of videos on window resize.
formula.modalMenu.init(); // Modal Menu.
formula.primaryMenu.init(); // Primary Menu.
formula.touchEnabled.init(); // Add class to body if device is touch-enabled.
} );
/* -----------------------------------------------------------------------------------------------
Helper functions
--------------------------------------------------------------------------------------------------- */
/* Toggle an attribute ----------------------- */
function formulaToggleAttribute( element, attribute, trueVal, falseVal ) {
if ( element.classList.contains( 'close-search-toggle' ) ) {
return;
}
if ( trueVal === undefined ) {
trueVal = true;
}
if ( falseVal === undefined ) {
falseVal = false;
}
if ( element.getAttribute( attribute ) !== trueVal ) {
element.setAttribute( attribute, trueVal );
} else {
element.setAttribute( attribute, falseVal );
}
}
/**
* Toggle a menu item on or off.
*
* @param {HTMLElement} target
* @param {number} duration
*/
function formulaMenuToggle( target, duration ) {
var initialParentHeight, finalParentHeight, menu, menuItems, transitionListener,
initialPositions = [],
finalPositions = [];
if ( ! target ) {
return;
}
menu = target.closest( '.menu-wrapper' );
// Step 1: look at the initial positions of every menu item.
menuItems = menu.querySelectorAll( '.menu-item' );
menuItems.forEach( function( menuItem, index ) {
initialPositions[ index ] = { x: menuItem.offsetLeft, y: menuItem.offsetTop };
} );
initialParentHeight = target.parentElement.offsetHeight;
target.classList.add( 'toggling-target' );
// Step 2: toggle target menu item and look at the final positions of every menu item.
target.classList.toggle( 'active' );
menuItems.forEach( function( menuItem, index ) {
finalPositions[ index ] = { x: menuItem.offsetLeft, y: menuItem.offsetTop };
} );
finalParentHeight = target.parentElement.offsetHeight;
// Step 3: close target menu item again.
// The whole process happens without giving the browser a chance to render, so it's invisible.
target.classList.toggle( 'active' );
/*
* Step 4: prepare animation.
* Position all the items with absolute offsets, at the same starting position.
* Shouldn't result in any visual changes if done right.
*/
menu.classList.add( 'is-toggling' );
target.classList.toggle( 'active' );
menuItems.forEach( function( menuItem, index ) {
var initialPosition = initialPositions[ index ];
if ( initialPosition.y === 0 && menuItem.parentElement === target ) {
initialPosition.y = initialParentHeight;
}
menuItem.style.transform = 'translate(' + initialPosition.x + 'px, ' + initialPosition.y + 'px)';
} );
/*
* The double rAF is unfortunately needed, since we're toggling CSS classes, and
* the only way to ensure layout completion here across browsers is to wait twice.
* This just delays the start of the animation by 2 frames and is thus not an issue.
*/
requestAnimationFrame( function() {
requestAnimationFrame( function() {
/*
* Step 5: start animation by moving everything to final position.
* All the layout work has already happened, while we were preparing for the animation.
* The animation now runs entirely in CSS, using cheap CSS properties (opacity and transform)
* that don't trigger the layout or paint stages.
*/
menu.classList.add( 'is-animating' );
menuItems.forEach( function( menuItem, index ) {
var finalPosition = finalPositions[ index ];
if ( finalPosition.y === 0 && menuItem.parentElement === target ) {
finalPosition.y = finalParentHeight;
}
if ( duration !== undefined ) {
menuItem.style.transitionDuration = duration + 'ms';
}
menuItem.style.transform = 'translate(' + finalPosition.x + 'px, ' + finalPosition.y + 'px)';
} );
if ( duration !== undefined ) {
target.style.transitionDuration = duration + 'ms';
}
} );
// Step 6: finish toggling.
// Remove all transient classes when the animation ends.
transitionListener = function() {
menu.classList.remove( 'is-animating' );
menu.classList.remove( 'is-toggling' );
target.classList.remove( 'toggling-target' );
menuItems.forEach( function( menuItem ) {
menuItem.style.transform = '';
menuItem.style.transitionDuration = '';
} );
target.style.transitionDuration = '';
target.removeEventListener( 'transitionend', transitionListener );
};
target.addEventListener( 'transitionend', transitionListener );
} );
}
/**
* Traverses the DOM up to find elements matching the query.
*
* @param {HTMLElement} target
* @param {string} query
* @return {NodeList} parents matching query
*/
function formulaFindParents( target, query ) {
var parents = [];
// Recursively go up the DOM adding matches to the parents array.
function traverse( item ) {
var parent = item.parentNode;
if ( parent instanceof HTMLElement ) {
if ( parent.matches( query ) ) {
parents.push( parent );
}
traverse( parent );
}
}
traverse( target );
return parents;
};