!function(n,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):n.anime=e()}(this,function(){"use strict";var n={update:null,begin:null,loopBegin:null,changeBegin:null,change:null,changeComplete:null,loopComplete:null,complete:null,loop:1,direction:"normal",autoplay:!0,timelineOffset:0},e={duration:1e3,delay:0,endDelay:0,easing:"easeOutElastic(1, .5)",round:0},t=["translateX","translateY","translateZ","rotate","rotateX","rotateY","rotateZ","scale","scaleX","scaleY","scaleZ","skew","skewX","skewY","perspective","matrix","matrix3d"],r={CSS:{},springs:{}};function a(n,e,t){return Math.min(Math.max(n,e),t)}function o(n,e){return n.indexOf(e)>-1}function u(n,e){return n.apply(null,e)}var i={arr:function(n){return Array.isArray(n)},obj:function(n){return o(Object.prototype.toString.call(n),"Object")},pth:function(n){return i.obj(n)&&n.hasOwnProperty("totalLength")},svg:function(n){return n instanceof SVGElement},inp:function(n){return n instanceof HTMLInputElement},dom:function(n){return n.nodeType||i.svg(n)},str:function(n){return"string"==typeof n},fnc:function(n){return"function"==typeof n},und:function(n){return void 0===n},nil:function(n){return i.und(n)||null===n},hex:function(n){return/(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(n)},rgb:function(n){return/^rgb/.test(n)},hsl:function(n){return/^hsl/.test(n)},col:function(n){return i.hex(n)||i.rgb(n)||i.hsl(n)},key:function(t){return!n.hasOwnProperty(t)&&!e.hasOwnProperty(t)&&"targets"!==t&&"keyframes"!==t}};function c(n){var e=/\(([^)]+)\)/.exec(n);return e?e[1].split(",").map(function(n){return parseFloat(n)}):[]}function s(n,e){var t=c(n),o=a(i.und(t[0])?1:t[0],.1,100),u=a(i.und(t[1])?100:t[1],.1,100),s=a(i.und(t[2])?10:t[2],.1,100),f=a(i.und(t[3])?0:t[3],.1,100),l=Math.sqrt(u/o),d=s/(2*Math.sqrt(u*o)),p=d<1?l*Math.sqrt(1-d*d):0,v=1,h=d<1?(d*l-f)/p:-f+l;function g(n){var t=e?e*n/1e3:n;return t=d<1?Math.exp(-t*d*l)*(v*Math.cos(p*t)+h*Math.sin(p*t)):(v+h*t)*Math.exp(-t*l),0===n||1===n?n:1-t}return e?g:function(){var e=r.springs[n];if(e)return e;for(var t=0,a=0;;)if(1===g(t+=1/6)){if(++a>=16)break}else a=0;var o=t*(1/6)*1e3;return r.springs[n]=o,o}}function f(n){return void 0===n&&(n=10),function(e){return Math.ceil(a(e,1e-6,1)*n)*(1/n)}}var l,d,p=function(){var n=11,e=1/(n-1);function t(n,e){return 1-3*e+3*n}function r(n,e){return 3*e-6*n}function a(n){return 3*n}function o(n,e,o){return((t(e,o)*n+r(e,o))*n+a(e))*n}function u(n,e,o){return 3*t(e,o)*n*n+2*r(e,o)*n+a(e)}return function(t,r,a,i){if(0<=t&&t<=1&&0<=a&&a<=1){var c=new Float32Array(n);if(t!==r||a!==i)for(var s=0;s=.001?function(n,e,t,r){for(var a=0;a<4;++a){var i=u(e,t,r);if(0===i)return e;e-=(o(e,t,r)-n)/i}return e}(r,l,t,a):0===d?l:function(n,e,t,r,a){for(var u,i,c=0;(u=o(i=e+(t-e)/2,r,a)-n)>0?t=i:e=i,Math.abs(u)>1e-7&&++c<10;);return i}(r,i,i+e,t,a)}}}(),v=(l={linear:function(){return function(n){return n}}},d={Sine:function(){return function(n){return 1-Math.cos(n*Math.PI/2)}},Circ:function(){return function(n){return 1-Math.sqrt(1-n*n)}},Back:function(){return function(n){return n*n*(3*n-2)}},Bounce:function(){return function(n){for(var e,t=4;n<((e=Math.pow(2,--t))-1)/11;);return 1/Math.pow(4,3-t)-7.5625*Math.pow((3*e-2)/22-n,2)}},Elastic:function(n,e){void 0===n&&(n=1),void 0===e&&(e=.5);var t=a(n,1,10),r=a(e,.1,2);return function(n){return 0===n||1===n?n:-t*Math.pow(2,10*(n-1))*Math.sin((n-1-r/(2*Math.PI)*Math.asin(1/t))*(2*Math.PI)/r)}}},["Quad","Cubic","Quart","Quint","Expo"].forEach(function(n,e){d[n]=function(){return function(n){return Math.pow(n,e+2)}}}),Object.keys(d).forEach(function(n){var e=d[n];l["easeIn"+n]=e,l["easeOut"+n]=function(n,t){return function(r){return 1-e(n,t)(1-r)}},l["easeInOut"+n]=function(n,t){return function(r){return r<.5?e(n,t)(2*r)/2:1-e(n,t)(-2*r+2)/2}},l["easeOutIn"+n]=function(n,t){return function(r){return r<.5?(1-e(n,t)(1-2*r))/2:(e(n,t)(2*r-1)+1)/2}}}),l);function h(n,e){if(i.fnc(n))return n;var t=n.split("(")[0],r=v[t],a=c(n);switch(t){case"spring":return s(n,e);case"cubicBezier":return u(p,a);case"steps":return u(f,a);default:return u(r,a)}}function g(n){try{return document.querySelectorAll(n)}catch(n){return}}function m(n,e){for(var t=n.length,r=arguments.length>=2?arguments[1]:void 0,a=[],o=0;o1&&(t-=1),t<1/6?n+6*(e-n)*t:t<.5?e:t<2/3?n+(e-n)*(2/3-t)*6:n}if(0==u)e=t=r=i;else{var f=i<.5?i*(1+u):i+u-i*u,l=2*i-f;e=s(l,f,o+1/3),t=s(l,f,o),r=s(l,f,o-1/3)}return"rgba("+255*e+","+255*t+","+255*r+","+c+")"}(n):void 0;var e,t,r,a}function C(n){var e=/[+-]?\d*\.?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?(%|px|pt|em|rem|in|cm|mm|ex|ch|pc|vw|vh|vmin|vmax|deg|rad|turn)?$/.exec(n);if(e)return e[1]}function P(n,e){return i.fnc(n)?n(e.target,e.id,e.total):n}function I(n,e){return n.getAttribute(e)}function D(n,e,t){if(M([t,"deg","rad","turn"],C(e)))return e;var a=r.CSS[e+t];if(!i.und(a))return a;var o=document.createElement(n.tagName),u=n.parentNode&&n.parentNode!==document?n.parentNode:document.body;u.appendChild(o),o.style.position="absolute",o.style.width=100+t;var c=100/o.offsetWidth;u.removeChild(o);var s=c*parseFloat(e);return r.CSS[e+t]=s,s}function B(n,e,t){if(e in n.style){var r=e.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase(),a=n.style[e]||getComputedStyle(n).getPropertyValue(r)||"0";return t?D(n,a,t):a}}function T(n,e){return i.dom(n)&&!i.inp(n)&&(!i.nil(I(n,e))||i.svg(n)&&n[e])?"attribute":i.dom(n)&&M(t,e)?"transform":i.dom(n)&&"transform"!==e&&B(n,e)?"css":null!=n[e]?"object":void 0}function E(n){if(i.dom(n)){for(var e,t=n.style.transform||"",r=/(\w+)\(([^)]*)\)/g,a=new Map;e=r.exec(t);)a.set(e[1],e[2]);return a}}function F(n,e,t,r){var a,u=o(e,"scale")?1:0+(o(a=e,"translate")||"perspective"===a?"px":o(a,"rotate")||o(a,"skew")?"deg":void 0),i=E(n).get(e)||u;return t&&(t.transforms.list.set(e,i),t.transforms.last=e),r?D(n,i,r):i}function A(n,e,t,r){switch(T(n,e)){case"transform":return F(n,e,r,t);case"css":return B(n,e,t);case"attribute":return I(n,e);default:return n[e]||0}}function N(n,e){var t=/^(\*=|\+=|-=)/.exec(n);if(!t)return n;var r=C(n)||0,a=parseFloat(e),o=parseFloat(n.replace(t[0],""));switch(t[0][0]){case"+":return a+o+r;case"-":return a-o+r;case"*":return a*o+r}}function S(n,e){if(i.col(n))return O(n);if(/\s/g.test(n))return n;var t=C(n),r=t?n.substr(0,n.length-t.length):n;return e?r+e:r}function L(n,e){return Math.sqrt(Math.pow(e.x-n.x,2)+Math.pow(e.y-n.y,2))}function j(n){for(var e,t=n.points,r=0,a=0;a0&&(r+=L(e,o)),e=o}return r}function q(n){if(n.getTotalLength)return n.getTotalLength();switch(n.tagName.toLowerCase()){case"circle":return o=n,2*Math.PI*I(o,"r");case"rect":return 2*I(a=n,"width")+2*I(a,"height");case"line":return L({x:I(r=n,"x1"),y:I(r,"y1")},{x:I(r,"x2"),y:I(r,"y2")});case"polyline":return j(n);case"polygon":return t=(e=n).points,j(e)+L(t.getItem(t.numberOfItems-1),t.getItem(0))}var e,t,r,a,o}function H(n,e){var t=e||{},r=t.el||function(n){for(var e=n.parentNode;i.svg(e)&&i.svg(e.parentNode);)e=e.parentNode;return e}(n),a=r.getBoundingClientRect(),o=I(r,"viewBox"),u=a.width,c=a.height,s=t.viewBox||(o?o.split(" "):[0,0,u,c]);return{el:r,viewBox:s,x:s[0]/1,y:s[1]/1,w:u,h:c,vW:s[2],vH:s[3]}}function V(n,e,t){function r(t){void 0===t&&(t=0);var r=e+t>=1?e+t:0;return n.el.getPointAtLength(r)}var a=H(n.el,n.svg),o=r(),u=r(-1),i=r(1),c=t?1:a.w/a.vW,s=t?1:a.h/a.vH;switch(n.property){case"x":return(o.x-a.x)*c;case"y":return(o.y-a.y)*s;case"angle":return 180*Math.atan2(i.y-u.y,i.x-u.x)/Math.PI}}function $(n,e){var t=/[+-]?\d*\.?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?/g,r=S(i.pth(n)?n.totalLength:n,e)+"";return{original:r,numbers:r.match(t)?r.match(t).map(Number):[0],strings:i.str(n)||e?r.split(t):[]}}function W(n){return m(n?y(i.arr(n)?n.map(b):b(n)):[],function(n,e,t){return t.indexOf(n)===e})}function X(n){var e=W(n);return e.map(function(n,t){return{target:n,id:t,total:e.length,transforms:{list:E(n)}}})}function Y(n,e){var t=x(e);if(/^spring/.test(t.easing)&&(t.duration=s(t.easing)),i.arr(n)){var r=n.length;2===r&&!i.obj(n[0])?n={value:n}:i.fnc(e.duration)||(t.duration=e.duration/r)}var a=i.arr(n)?n:[n];return a.map(function(n,t){var r=i.obj(n)&&!i.pth(n)?n:{value:n};return i.und(r.delay)&&(r.delay=t?0:e.delay),i.und(r.endDelay)&&(r.endDelay=t===a.length-1?e.endDelay:0),r}).map(function(n){return k(n,t)})}function Z(n,e){var t=[],r=e.keyframes;for(var a in r&&(e=k(function(n){for(var e=m(y(n.map(function(n){return Object.keys(n)})),function(n){return i.key(n)}).reduce(function(n,e){return n.indexOf(e)<0&&n.push(e),n},[]),t={},r=function(r){var a=e[r];t[a]=n.map(function(n){var e={};for(var t in n)i.key(t)?t==a&&(e.value=n[t]):e[t]=n[t];return e})},a=0;a0?requestAnimationFrame(e):void 0}return"undefined"!=typeof document&&document.addEventListener("visibilitychange",function(){en.suspendWhenDocumentHidden&&(nn()?n=cancelAnimationFrame(n):(K.forEach(function(n){return n._onDocumentVisibility()}),U()))}),function(){n||nn()&&en.suspendWhenDocumentHidden||!(K.length>0)||(n=requestAnimationFrame(e))}}();function nn(){return!!document&&document.hidden}function en(t){void 0===t&&(t={});var r,o=0,u=0,i=0,c=0,s=null;function f(n){var e=window.Promise&&new Promise(function(n){return s=n});return n.finished=e,e}var l,d,p,v,h,g,y,b,M=(d=w(n,l=t),p=w(e,l),v=Z(p,l),h=X(l.targets),g=_(h,v),y=R(g,p),b=J,J++,k(d,{id:b,children:[],animatables:h,animations:g,duration:y.duration,delay:y.delay,endDelay:y.endDelay}));f(M);function x(){var n=M.direction;"alternate"!==n&&(M.direction="normal"!==n?"normal":"reverse"),M.reversed=!M.reversed,r.forEach(function(n){return n.reversed=M.reversed})}function O(n){return M.reversed?M.duration-n:n}function C(){o=0,u=O(M.currentTime)*(1/en.speed)}function P(n,e){e&&e.seek(n-e.timelineOffset)}function I(n){for(var e=0,t=M.animations,r=t.length;e2||(b=Math.round(b*p)/p)),v.push(b)}var k=d.length;if(k){g=d[0];for(var O=0;O0&&(M.began=!0,D("begin")),!M.loopBegan&&M.currentTime>0&&(M.loopBegan=!0,D("loopBegin")),d<=t&&0!==M.currentTime&&I(0),(d>=l&&M.currentTime!==e||!e)&&I(e),d>t&&d=e&&(u=0,M.remaining&&!0!==M.remaining&&M.remaining--,M.remaining?(o=i,D("loopComplete"),M.loopBegan=!1,"alternate"===M.direction&&x()):(M.paused=!0,M.completed||(M.completed=!0,D("loopComplete"),D("complete"),!M.passThrough&&"Promise"in window&&(s(),f(M)))))}return M.reset=function(){var n=M.direction;M.passThrough=!1,M.currentTime=0,M.progress=0,M.paused=!0,M.began=!1,M.loopBegan=!1,M.changeBegan=!1,M.completed=!1,M.changeCompleted=!1,M.reversePlayback=!1,M.reversed="reverse"===n,M.remaining=M.loop,r=M.children;for(var e=c=r.length;e--;)M.children[e].reset();(M.reversed&&!0!==M.loop||"alternate"===n&&1===M.loop)&&M.remaining++,I(M.reversed?M.duration:0)},M._onDocumentVisibility=C,M.set=function(n,e){return z(n,e),M},M.tick=function(n){i=n,o||(o=i),B((i+(u-o))*en.speed)},M.seek=function(n){B(O(n))},M.pause=function(){M.paused=!0,C()},M.play=function(){M.paused&&(M.completed&&M.reset(),M.paused=!1,K.push(M),C(),U())},M.reverse=function(){x(),M.completed=!M.reversed,C()},M.restart=function(){M.reset(),M.play()},M.remove=function(n){rn(W(n),M)},M.reset(),M.autoplay&&M.play(),M}function tn(n,e){for(var t=e.length;t--;)M(n,e[t].animatable.target)&&e.splice(t,1)}function rn(n,e){var t=e.animations,r=e.children;tn(n,t);for(var a=r.length;a--;){var o=r[a],u=o.animations;tn(n,u),u.length||o.children.length||r.splice(a,1)}t.length||r.length||e.pause()}return en.version="3.2.1",en.speed=1,en.suspendWhenDocumentHidden=!0,en.running=K,en.remove=function(n){for(var e=W(n),t=K.length;t--;)rn(e,K[t])},en.get=A,en.set=z,en.convertPx=D,en.path=function(n,e){var t=i.str(n)?g(n)[0]:n,r=e||100;return function(n){return{property:n,el:t,svg:H(t),totalLength:q(t)*(r/100)}}},en.setDashoffset=function(n){var e=q(n);return n.setAttribute("stroke-dasharray",e),e},en.stagger=function(n,e){void 0===e&&(e={});var t=e.direction||"normal",r=e.easing?h(e.easing):null,a=e.grid,o=e.axis,u=e.from||0,c="first"===u,s="center"===u,f="last"===u,l=i.arr(n),d=l?parseFloat(n[0]):parseFloat(n),p=l?parseFloat(n[1]):0,v=C(l?n[1]:n)||0,g=e.start||0+(l?d:0),m=[],y=0;return function(n,e,i){if(c&&(u=0),s&&(u=(i-1)/2),f&&(u=i-1),!m.length){for(var h=0;h-1&&K.splice(o,1);for(var s=0;s 1) Util.addClass(el, classList.slice(1).join(" ")); }; Util.removeClass = function (el, className) { var classList = className.split(" "); el.classList.remove(classList[0]); if (classList.length > 1) Util.removeClass(el, classList.slice(1).join(" ")); }; Util.toggleClass = function (el, className, bool) { if (bool) Util.addClass(el, className); else Util.removeClass(el, className); }; Util.getIndexInArray = function (array, el) { return Array.prototype.indexOf.call(array, el); }; Util.osHasReducedMotion = function () { if (!window.matchMedia) return false; var matchMediaObj = window.matchMedia("(prefers-reduced-motion: reduce)"); if (matchMediaObj) return matchMediaObj.matches; return false; }; Util.setAttributes = function(el, attrs) { for(var key in attrs) { el.setAttribute(key, attrs[key]); } }; Util.scrollTo = function(final, duration, cb, scrollEl) { var element = scrollEl || window; var start = element.scrollTop || document.documentElement.scrollTop, currentTime = null; if(!scrollEl) start = window.scrollY || document.documentElement.scrollTop; var animateScroll = function(timestamp){ if (!currentTime) currentTime = timestamp; var progress = timestamp - currentTime; if(progress > duration) progress = duration; var val = Math.easeInOutQuad(progress, start, final-start, duration); element.scrollTo(0, val); if(progress < duration) { window.requestAnimationFrame(animateScroll); } else { cb && cb(); } }; window.requestAnimationFrame(animateScroll); }; Util.moveFocus = function (element) { if( !element ) element = document.getElementsByTagName('body')[0]; element.focus(); if (document.activeElement !== element) { element.setAttribute('tabindex','-1'); element.focus(); } }; Util.cssSupports = function(property, value) { return CSS.supports(property, value); }; Math.easeInOutQuad = function (t, b, c, d) { t /= d/2; if (t < 1) return c/2*t*t + b; t--; return -c/2 * (t*(t-2) - 1) + b; }; Util.getChildrenByClassName = function(el, className) { var children = el.children, childrenByClass = []; for (var i = 0; i < children.length; i++) { if (Util.hasClass(children[i], className)) childrenByClass.push(children[i]); } return childrenByClass; }; Util.extend = function() { var extended = {}; var deep = false; var i = 0; var length = arguments.length; if ( Object.prototype.toString.call( arguments[0] ) === '[object Boolean]' ) { deep = arguments[0]; i++; } var merge = function (obj) { for ( var prop in obj ) { if ( Object.prototype.hasOwnProperty.call( obj, prop ) ) { if ( deep && Object.prototype.toString.call(obj[prop]) === '[object Object]' ) { extended[prop] = extend( true, extended[prop], obj[prop] ); } else { extended[prop] = obj[prop]; } } } }; for ( ; i < length; i++ ) { var obj = arguments[i]; merge(obj); } return extended; }; Util.osHasReducedMotion = function() { if(!window.matchMedia) return false; var matchMediaObj = window.matchMedia('(prefers-reduced-motion: reduce)'); if(matchMediaObj) return matchMediaObj.matches; return false; }; (function () { var SlidingPanels = function (element) { this.element = element; this.itemsList = this.element.getElementsByClassName("js-s-panels__projects-list"); this.items = this.itemsList[0].getElementsByClassName("js-s-panels__project-preview"); this.navigationToggle = this.element.getElementsByClassName("js-s-panels__nav-control"); this.navigation = this.element.getElementsByClassName("js-s-panels__nav-wrapper"); this.transitionLayer = this.element.getElementsByClassName("js-s-panels__overlay-layer"); this.selectedSection = false; this.animating = false; this.toggleAriaLabels = ["Toggle navigation", "Close Project"]; initSlidingPanels(this); }; function initSlidingPanels(element) { if (element.navigationToggle.length > 0 && element.navigation.length > 0) { element.navigationToggle[0].addEventListener("click", function (event) { if (element.animating) return; if (closeProjectIfVisible(element)) return; var openNav = Util.hasClass(element.navigation[0], "sn3-hide"); toggleNavigation(element, openNav); }); } // open project element.element.addEventListener("click", function (event) { if (element.animating) return; var link = event.target.closest(".js-s-panels__project-control"); if (!link) return; event.preventDefault(); openProject(element, event.target.closest(".js-s-panels__project-preview"), link.getAttribute("href").replace("#", "")); }); } // check if there's a visible project to close and close it function closeProjectIfVisible(element) { var visibleProject = element.element.getElementsByClassName("s-panels__project-preview--selected"); if (visibleProject.length > 0) { element.animating = true; closeProject(element); return true; } return false; } function toggleNavigation(element, openNavigation) { element.animating = true; if (openNavigation) Util.removeClass(element.navigation[0], "sn3-hide"); slideProjects(element, openNavigation, false, function () { element.animating = false; if (!openNavigation) Util.addClass(element.navigation[0], "sn3-hide"); }); Util.toggleClass(element.navigationToggle[0], "s-panels__nav-control--arrow-down", openNavigation); } function openProject(element, project, id) { element.animating = true; var projectIndex = Util.getIndexInArray(element.items, project); Util.removeClass(element.itemsList[0], "sn3-bg-opacity-0"); Util.addClass(project, "s-panels__project-preview--selected"); slideProjects(element, true, projectIndex, function () { element.selectedSection = document.getElementById(id); if (element.selectedSection) Util.removeClass(element.selectedSection, "sn3-hide"); element.animating = false; element.element.dispatchEvent(new CustomEvent("slidingPanelOpen", { detail: projectIndex })); }); Util.addClass(element.navigationToggle[0], "s-panels__nav-control--close"); element.navigationToggle[0].setAttribute("aria-label", element.toggleAriaLabels[1]); } function closeProject(element) { toggleTransitionProjects(element, true); Util.removeClass(element.itemsList[0], "sn3-bg-opacity-0"); Util.addClass(element.transitionLayer[0], "s-panels__overlay-layer--visible"); element.transitionLayer[0].addEventListener("transitionend", function cb(event) { if (event.propertyName != "opacity") return; element.transitionLayer[0].removeEventListener("transitionend", cb); resetProjects(element); setTimeout(function () { Util.removeClass(element.transitionLayer[0], "s-panels__overlay-layer--visible"); slideProjects(element, false, false, function () { Util.addClass(element.itemsList[0], "sn3-bg-opacity-0"); element.animating = false; }); }, 200); }); Util.removeClass(element.navigationToggle[0], "s-panels__nav-control--close"); element.navigationToggle[0].setAttribute("aria-label", element.toggleAriaLabels[0]); } function slideProjects(element, openNav, exclude, cb) { var randomList = getRandomList(element.items.length, exclude); for (var i = 0; i < randomList.length; i++) { (function (i) { setTimeout(function () { Util.toggleClass(element.items[randomList[i]], "s-panels__project-preview--hide", openNav); toggleProjectAccessibility(element.items[randomList[i]], openNav); if (cb && i == randomList.length - 1) { element.items[randomList[i]].addEventListener("transitionend", function cbt() { if (event.propertyName != "transform") return; if (cb) cb(); element.items[randomList[i]].removeEventListener("transitionend", cbt); }); } }, i * 100); })(i); } } function toggleTransitionProjects(element, bool) { for (var i = 0; i < element.items.length; i++) { Util.toggleClass(element.items[i], "s-panels__project-preview--no-transition", bool); } } function resetProjects(element) { for (var i = 0; i < element.items.length; i++) { Util.removeClass(element.items[i], "s-panels__project-preview--selected s-panels__project-preview--no-transition"); Util.addClass(element.items[i], "s-panels__project-preview--hide"); } if (element.selectedSection) Util.addClass(element.selectedSection, "sn3-hide"); element.selectedSection = false; } function getRandomList(maxVal, exclude) { var uniqueRandoms = []; var randomArray = []; function makeUniqueRandom() { if (!uniqueRandoms.length) { for (var i = 0; i < maxVal; i++) { if (exclude === false || i != exclude) uniqueRandoms.push(i); } } var index = Math.floor(Math.random() * uniqueRandoms.length); var val = uniqueRandoms[index]; uniqueRandoms.splice(index, 1); return val; } for (var j = 0; j < maxVal; j++) { randomArray.push(makeUniqueRandom()); } return randomArray; } function toggleProjectAccessibility(project, bool) { bool ? project.setAttribute("aria-hidden", "true") : project.removeAttribute("aria-hidden"); var link = project.getElementsByClassName("js-s-panels__project-control"); if (link.length > 0) { bool ? link[0].setAttribute("tabindex", "-1") : link[0].removeAttribute("tabindex"); } } var slidingPanels = document.getElementsByClassName("js-s-panels"); if (slidingPanels.length > 0) { for (var i = 0; i < slidingPanels.length; i++) { (function (i) { new SlidingPanels(slidingPanels[i]); })(i); } } })(); // drawer (function () { var TdDrawer = function (element) { this.element = element; this.mianContent = document.getElementsByClassName("js-td-drawer-main"); this.content = document.getElementsByClassName("js-td-drawer__body"); this.triggers = document.querySelectorAll('[aria-controls="' + this.element.getAttribute("id") + '"]'); this.firstFocusable = null; this.lastFocusable = null; this.selectedTrigger = null; this.showClass = "td-drawer--is-visible"; this.showMainClass = "td-drawer-main--drawer-is-visible"; initDrawer(this); }; function initDrawer(drawer) { for (var i = 0; i < drawer.triggers.length; i++) { drawer.triggers[i].addEventListener("click", function (event) { event.preventDefault(); if (drawer.element.classList.contains(drawer.showClass)) { closeDrawer(drawer); return; } drawer.selectedTrigger = event.target; showDrawer(drawer); initDrawerEvents(drawer); }); } if (drawer.element.classList.contains(drawer.showClass)) initDrawerEvents(drawer); } function showDrawer(drawer) { if (drawer.content.length > 0) drawer.content[0].scrollTop = 0; if (drawer.mianContent.length > 0) drawer.mianContent[0].classList.add(drawer.showMainClass); drawer.element.classList.add(drawer.showClass); getFocusableElements(drawer); focusDrawer(drawer); drawer.element.addEventListener("transitionend", function cb(event) { focusDrawer(drawer); drawer.element.removeEventListener("transitionend", cb); }); emitDrawerEvents(drawer, "drawerIsOpen"); } function focusDrawer(drawer) { drawer.element.setAttribute("tabindex", "-1"); drawer.element.focus(); } function closeDrawer(drawer) { if (drawer.mianContent.length > 0) drawer.mianContent[0].classList.remove(drawer.showMainClass); drawer.element.classList.remove(drawer.showClass); drawer.firstFocusable = null; drawer.lastFocusable = null; if (drawer.selectedTrigger) drawer.selectedTrigger.focus(); cancelDrawerEvents(drawer); emitDrawerEvents(drawer, "drawerIsClose"); } function initDrawerEvents(drawer) { drawer.element.addEventListener("keydown", handleEvent.bind(drawer)); drawer.element.addEventListener("click", handleEvent.bind(drawer)); } function cancelDrawerEvents(drawer) { drawer.element.removeEventListener("keydown", handleEvent.bind(drawer)); drawer.element.removeEventListener("click", handleEvent.bind(drawer)); } function handleEvent(event) { switch (event.type) { case "click": { initClick(this, event); } case "keydown": { initKeyDown(this, event); } } } function initKeyDown(drawer, event) { if ((event.keyCode && event.keyCode == 27) || (event.key && event.key == "Escape")) { closeDrawer(drawer); } else if ((event.keyCode && event.keyCode == 9) || (event.key && event.key == "Tab")) { trapFocus(drawer, event); } } function initClick(drawer, event) { if (!event.target.closest(".js-td-drawer__close") && !event.target.classList.contains("js-td-drawer")) return; event.preventDefault(); closeDrawer(drawer); } function trapFocus(drawer, event) { if (drawer.firstFocusable == document.activeElement && event.shiftKey) { event.preventDefault(); drawer.lastFocusable.focus(); } if (drawer.lastFocusable == document.activeElement && !event.shiftKey) { event.preventDefault(); drawer.firstFocusable.focus(); } } function getFocusableElements(drawer) { var allFocusable = drawer.element.querySelectorAll('[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, [tabindex]:not([tabindex="-1"]), [contenteditable], audio[controls], video[controls], summary'); getFirstVisible(drawer, allFocusable); getLastVisible(drawer, allFocusable); } function getFirstVisible(drawer, elements) { for (var i = 0; i < elements.length; i++) { if (elements[i].offsetWidth || elements[i].offsetHeight || elements[i].getClientRects().length) { drawer.firstFocusable = elements[i]; return true; } } } function getLastVisible(drawer, elements) { for (var i = elements.length - 1; i >= 0; i--) { if (elements[i].offsetWidth || elements[i].offsetHeight || elements[i].getClientRects().length) { drawer.lastFocusable = elements[i]; return true; } } } function emitDrawerEvents(drawer, eventName) { var event = new CustomEvent(eventName, { detail: drawer.selectedTrigger }); drawer.element.dispatchEvent(event); } var drawer = document.getElementsByClassName("js-td-drawer"); if (drawer.length > 0) { for (var i = 0; i < drawer.length; i++) { (function (i) { new TdDrawer(drawer[i]); })(i); } } })(); // scroll fx (function () { var ScrollFx = function (element, scrollableSelector) { this.element = element; this.options = []; this.boundingRect = this.element.getBoundingClientRect(); this.windowHeight = window.innerHeight; this.scrollingFx = []; this.animating = []; this.deltaScrolling = []; this.observer = []; this.scrollableSelector = scrollableSelector; this.scrollableElement = false; initScrollFx(this); }; function initScrollFx(element) { if (Util.osHasReducedMotion()) return; setScrollableElement(element); var animation = element.element.getAttribute("data-scroll-fx"); if (animation) { element.options.push(extractAnimation(animation)); } else { getAnimations(element, 1); } initObserver(element); initResize(element); } function setScrollableElement(element) { if (element.scrollableSelector) element.scrollableElement = document.querySelector(element.scrollableSelector); } function initObserver(element) { for (var i = 0; i < element.options.length; i++) { (function (i) { element.scrollingFx[i] = false; element.deltaScrolling[i] = getDeltaScrolling(element, i); element.animating[i] = false; element.observer[i] = new IntersectionObserver( function (entries, observer) { scrollFxCallback(element, i, entries, observer); }, { rootMargin: element.options[i][5] - 100 + "% 0px " + (0 - element.options[i][4]) + "% 0px", } ); element.observer[i].observe(element.element); setTimeout(function () { animateScrollFx.bind(element, i)(); }); })(i); } } function scrollFxCallback(element, index, entries, observer) { if (entries[0].isIntersecting) { if (element.scrollingFx[index]) return; resetDeltaBeforeAnim(element, index); triggerAnimateScrollFx(element, index); } else { if (!element.scrollingFx[index]) return; window.removeEventListener("scroll", element.scrollingFx[index]); element.scrollingFx[index] = false; } } function triggerAnimateScrollFx(element, index) { element.scrollingFx[index] = animateScrollFx.bind(element, index); element.scrollableElement ? element.scrollableElement.addEventListener("scroll", element.scrollingFx[index]) : window.addEventListener("scroll", element.scrollingFx[index]); } function animateScrollFx(index) { if (getScrollY(this) < this.deltaScrolling[index][0]) { setCSSProperty(this, index, this.options[index][1]); return; } if (getScrollY(this) > this.deltaScrolling[index][1]) { setCSSProperty(this, index, this.options[index][2]); return; } if (this.animating[index]) return; this.animating[index] = true; window.requestAnimationFrame(updatePropertyScroll.bind(this, index)); } function updatePropertyScroll(index) { if (isNaN(this.options[index][1])) { getScrollY(this) >= this.deltaScrolling[index][1] ? setCSSProperty(this, index, this.options[index][2]) : setCSSProperty(this, index, this.options[index][1]); } else { var value = this.options[index][1] + ((this.options[index][2] - this.options[index][1]) * (getScrollY(this) - this.deltaScrolling[index][0])) / (this.deltaScrolling[index][1] - this.deltaScrolling[index][0]); setCSSProperty(this, index, value); } this.animating[index] = false; } function setCSSProperty(element, index, value) { if (isNaN(value)) { setThemeValue(element, value); return; } if (element.options[index][0] == "--scroll-fx-skew" || element.options[index][0] == "--scroll-fx-scale") { element.element.style.setProperty(element.options[index][0] + "-x", value + element.options[index][3]); element.element.style.setProperty(element.options[index][0] + "-y", value + element.options[index][3]); } else { element.element.style.setProperty(element.options[index][0], value + element.options[index][3]); } } function setThemeValue(element, value) { if (element.element.getAttribute("data-theme") != value) { Util.addClass(element.element, "scroll-fx--theme-transition"); element.element.offsetWidth; element.element.setAttribute("data-theme", value); element.element.addEventListener("transitionend", function cb() { element.element.removeEventListener("transitionend", cb); Util.removeClass(element.element, "scroll-fx--theme-transition"); }); } } function getAnimations(element, index) { var option = element.element.getAttribute("data-scroll-fx-" + index); if (option) { element.options.push(extractAnimation(option)); getAnimations(element, index + 1); } return; } function extractAnimation(option) { var array = option.split(",").map(function (item) { return item.trim(); }); var propertyOptions = getPropertyValues(array[1], array[2]); var animation = [getPropertyLabel(array[0]), propertyOptions[0], propertyOptions[1], propertyOptions[2], parseInt(array[3]), parseInt(array[4])]; return animation; } function getPropertyLabel(property) { var propertyCss = "--scroll-fx-"; for (var i = 0; i < property.length; i++) { propertyCss = property[i] == property[i].toUpperCase() ? propertyCss + "-" + property[i].toLowerCase() : propertyCss + property[i]; } if (propertyCss == "--scroll-fx-rotate") { propertyCss = "--scroll-fx-rotate-z"; } else if (propertyCss == "--scroll-fx-translate") { propertyCss = "--scroll-fx-translate-x"; } return propertyCss; } function getPropertyValues(val1, val2) { var nbVal1 = parseFloat(val1), nbVal2 = parseFloat(val2), unit = val1.replace(nbVal1, ""); if (isNaN(nbVal1)) { nbVal1 = val1; nbVal2 = val2; unit = ""; } return [nbVal1, nbVal2, unit]; } function getDeltaScrolling(element, index) { var topDelta = getScrollY(element) - (element.windowHeight - ((element.windowHeight + element.boundingRect.height) * element.options[index][4]) / 100) + element.boundingRect.top, bottomDelta = getScrollY(element) - (element.windowHeight - ((element.windowHeight + element.boundingRect.height) * element.options[index][5]) / 100) + element.boundingRect.top; return [topDelta, bottomDelta]; } function initResize(element) { var resizingId = false; window.addEventListener("resize", function () { clearTimeout(resizingId); resizingId = setTimeout(resetResize.bind(element), 500); }); var event = new CustomEvent("scrollFxReady"); element.element.dispatchEvent(event); } function resetResize() { this.boundingRect = this.element.getBoundingClientRect(); this.windowHeight = window.innerHeight; for (var i = 0; i < this.deltaScrolling.length; i++) { this.deltaScrolling[i] = getDeltaScrolling(this, i); animateScrollFx.bind(this, i)(); } var event = new CustomEvent("scrollFxResized"); this.element.dispatchEvent(event); } function resetDeltaBeforeAnim(element, index) { element.boundingRect = element.element.getBoundingClientRect(); element.windowHeight = window.innerHeight; element.deltaScrolling[index] = getDeltaScrolling(element, index); } function getScrollY(element) { if (!element.scrollableElement) return window.scrollY; return element.scrollableElement.scrollTop; } window.ScrollFx = ScrollFx; var scrollFx = document.getElementsByClassName("js-scroll-fx"); for (var i = 0; i < scrollFx.length; i++) { (function (i) { var scrollableElement = scrollFx[i].getAttribute("data-scrollable-element"); new ScrollFx(scrollFx[i], scrollableElement); })(i); } })(); // sticky hero (function () { var StickyBackground = function (element) { this.element = element; this.scrollingElement = this.element.getElementsByClassName("sticky-hero__content")[0]; this.nextElement = this.element.nextElementSibling; this.scrollingTreshold = 0; this.nextTreshold = 0; initStickyEffect(this); }; function initStickyEffect(element) { var observer = new IntersectionObserver(stickyCallback.bind(element), { threshold: [0, 0.1, 1] }); observer.observe(element.scrollingElement); if (element.nextElement) observer.observe(element.nextElement); } function stickyCallback(entries, observer) { var threshold = entries[0].intersectionRatio.toFixed(1); entries[0].target == this.scrollingElement ? (this.scrollingTreshold = threshold) : (this.nextTreshold = threshold); Util.toggleClass(this.element, "sticky-hero--media-is-fixed", this.nextTreshold > 0 || this.scrollingTreshold > 0); } var stickyBackground = document.getElementsByClassName("js-sticky-hero"), intersectionObserverSupported = "IntersectionObserver" in window && "IntersectionObserverEntry" in window && "intersectionRatio" in window.IntersectionObserverEntry.prototype; if (stickyBackground.length > 0 && intersectionObserverSupported) { for (var i = 0; i < stickyBackground.length; i++) { (function (i) { if (Util.hasClass(stickyBackground[i], "sticky-hero--overlay-layer") || Util.hasClass(stickyBackground[i], "sticky-hero--scale")) new StickyBackground(stickyBackground[i]); })(i); } } })(); // modal window (function () { var Modal = function (element) { this.element = element; this.triggers = document.querySelectorAll('[aria-controls="' + this.element.getAttribute("id") + '"]'); this.firstFocusable = null; this.lastFocusable = null; this.moveFocusEl = null; this.modalFocus = this.element.getAttribute("data-modal-first-focus") ? this.element.querySelector(this.element.getAttribute("data-modal-first-focus")) : null; this.selectedTrigger = null; this.preventScrollEl = this.getPreventScrollEl(); this.showClass = "modal--is-visible"; this.initModal(); }; Modal.prototype.getPreventScrollEl = function () { var scrollEl = false; var querySelector = this.element.getAttribute("data-modal-prevent-scroll"); if (querySelector) scrollEl = document.querySelector(querySelector); return scrollEl; }; Modal.prototype.initModal = function () { var self = this; if (this.triggers) { for (var i = 0; i < this.triggers.length; i++) { this.triggers[i].addEventListener("click", function (event) { event.preventDefault(); if (Util.hasClass(self.element, self.showClass)) { self.closeModal(); return; } self.selectedTrigger = event.currentTarget; self.showModal(); self.initModalEvents(); }); } } this.element.addEventListener("openModal", function (event) { if (event.detail) self.selectedTrigger = event.detail; self.showModal(); self.initModalEvents(); }); this.element.addEventListener("closeModal", function (event) { if (event.detail) self.selectedTrigger = event.detail; self.closeModal(); }); if (Util.hasClass(this.element, this.showClass)) this.initModalEvents(); }; Modal.prototype.showModal = function () { var self = this; Util.addClass(this.element, this.showClass); this.getFocusableElements(); if (this.moveFocusEl) { this.moveFocusEl.focus(); this.element.addEventListener("transitionend", function cb(event) { self.moveFocusEl.focus(); self.element.removeEventListener("transitionend", cb); }); } this.emitModalEvents("modalIsOpen"); if (this.preventScrollEl) this.preventScrollEl.style.overflow = "hidden"; }; Modal.prototype.closeModal = function () { if (!Util.hasClass(this.element, this.showClass)) return; Util.removeClass(this.element, this.showClass); this.firstFocusable = null; this.lastFocusable = null; this.moveFocusEl = null; if (this.selectedTrigger) this.selectedTrigger.focus(); this.cancelModalEvents(); this.emitModalEvents("modalIsClose"); if (this.preventScrollEl) this.preventScrollEl.style.overflow = ""; }; Modal.prototype.initModalEvents = function () { this.element.addEventListener("keydown", this); this.element.addEventListener("click", this); }; Modal.prototype.cancelModalEvents = function () { this.element.removeEventListener("keydown", this); this.element.removeEventListener("click", this); }; Modal.prototype.handleEvent = function (event) { switch (event.type) { case "click": { this.initClick(event); } case "keydown": { this.initKeyDown(event); } } }; Modal.prototype.initKeyDown = function (event) { if ((event.keyCode && event.keyCode == 9) || (event.key && event.key == "Tab")) { this.trapFocus(event); } else if (((event.keyCode && event.keyCode == 13) || (event.key && event.key == "Enter")) && event.target.closest(".js-modal__close")) { event.preventDefault(); this.closeModal(); } }; Modal.prototype.initClick = function (event) { if (!event.target.closest(".js-modal__close") && !Util.hasClass(event.target, "js-modal")) return; event.preventDefault(); this.closeModal(); }; Modal.prototype.trapFocus = function (event) { if (this.firstFocusable == document.activeElement && event.shiftKey) { event.preventDefault(); this.lastFocusable.focus(); } if (this.lastFocusable == document.activeElement && !event.shiftKey) { event.preventDefault(); this.firstFocusable.focus(); } }; Modal.prototype.getFocusableElements = function () { var allFocusable = this.element.querySelectorAll(focusableElString); this.getFirstVisible(allFocusable); this.getLastVisible(allFocusable); this.getFirstFocusable(); }; Modal.prototype.getFirstVisible = function (elements) { for (var i = 0; i < elements.length; i++) { if (isVisible(elements[i])) { this.firstFocusable = elements[i]; break; } } }; Modal.prototype.getLastVisible = function (elements) { for (var i = elements.length - 1; i >= 0; i--) { if (isVisible(elements[i])) { this.lastFocusable = elements[i]; break; } } }; Modal.prototype.getFirstFocusable = function () { if (!this.modalFocus || !Element.prototype.matches) { this.moveFocusEl = this.firstFocusable; return; } var containerIsFocusable = this.modalFocus.matches(focusableElString); if (containerIsFocusable) { this.moveFocusEl = this.modalFocus; } else { this.moveFocusEl = false; var elements = this.modalFocus.querySelectorAll(focusableElString); for (var i = 0; i < elements.length; i++) { if (isVisible(elements[i])) { this.moveFocusEl = elements[i]; break; } } if (!this.moveFocusEl) this.moveFocusEl = this.firstFocusable; } }; Modal.prototype.emitModalEvents = function (eventName) { var event = new CustomEvent(eventName, { detail: this.selectedTrigger }); this.element.dispatchEvent(event); }; function isVisible(element) { return element.offsetWidth || element.offsetHeight || element.getClientRects().length; } window.Modal = Modal; var modals = document.getElementsByClassName("js-modal"); var focusableElString = '[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, [tabindex]:not([tabindex="-1"]), [contenteditable], audio[controls], video[controls], summary'; if (modals.length > 0) { var modalArrays = []; for (var i = 0; i < modals.length; i++) { (function (i) { modalArrays.push(new Modal(modals[i])); })(i); } window.addEventListener("keydown", function (event) { if ((event.keyCode && event.keyCode == 27) || (event.key && event.key.toLowerCase() == "escape")) { for (var i = 0; i < modalArrays.length; i++) { (function (i) { modalArrays[i].closeModal(); })(i); } } }); } })(); // tooltips (function() { var Tooltip = function(element) { this.element = element; this.tooltip = false; this.tooltipIntervalId = false; this.tooltipContent = this.element.getAttribute('title'); this.tooltipPosition = (this.element.getAttribute('data-tooltip-position')) ? this.element.getAttribute('data-tooltip-position') : 'top'; this.tooltipClasses = (this.element.getAttribute('data-tooltip-class')) ? this.element.getAttribute('data-tooltip-class') : false; this.tooltipId = 'js-tooltip-element'; this.tooltipDescription = (this.element.getAttribute('data-tooltip-describedby') && this.element.getAttribute('data-tooltip-describedby') == 'false') ? false : true; this.tooltipDelay = this.element.getAttribute('data-tooltip-delay'); if(!this.tooltipDelay) this.tooltipDelay = 100; this.tooltipDelta = parseInt(this.element.getAttribute('data-tooltip-gap')); if(isNaN(this.tooltipDelta)) this.tooltipDelta = 10; this.tooltipTriggerHover = false; this.tooltipSticky = (this.tooltipClasses && this.tooltipClasses.indexOf('tooltip--sticky') > -1); this.tooltipHover = false; if(this.tooltipSticky) { this.tooltipHoverInterval = false; } this.tooltipTriangleVar = '--tooltip-triangle-translate'; resetTooltipContent(this); initTooltip(this); }; function resetTooltipContent(tooltip) { var htmlContent = tooltip.element.getAttribute('data-tooltip-title'); if(htmlContent) { tooltip.tooltipContent = htmlContent; } }; function initTooltip(tooltipObj) { tooltipObj.element.removeAttribute('title'); tooltipObj.element.setAttribute('tabindex', '0'); tooltipObj.element.addEventListener('mouseenter', handleEvent.bind(tooltipObj)); tooltipObj.element.addEventListener('focus', handleEvent.bind(tooltipObj)); }; function removeTooltipEvents(tooltipObj) { tooltipObj.element.removeEventListener('mouseleave', handleEvent.bind(tooltipObj)); tooltipObj.element.removeEventListener('blur', handleEvent.bind(tooltipObj)); }; function handleEvent(event) { switch(event.type) { case 'mouseenter': case 'focus': showTooltip(this, event); break; case 'mouseleave': case 'blur': checkTooltip(this); break; case 'newContent': changeTooltipContent(this, event); break; } }; function showTooltip(tooltipObj, event) { if(tooltipObj.tooltipIntervalId) return; tooltipObj.tooltipTriggerHover = true; tooltipObj.element.addEventListener('mouseleave', handleEvent.bind(tooltipObj)); tooltipObj.element.addEventListener('blur', handleEvent.bind(tooltipObj)); tooltipObj.element.addEventListener('newContent', handleEvent.bind(tooltipObj)); tooltipObj.tooltipIntervalId = setTimeout(function(){ createTooltip(tooltipObj); }, tooltipObj.tooltipDelay); }; function createTooltip(tooltipObj) { tooltipObj.tooltip = document.getElementById(tooltipObj.tooltipId); if( !tooltipObj.tooltip ) { tooltipObj.tooltip = document.createElement('div'); document.body.appendChild(tooltipObj.tooltip); } tooltipObj.tooltip.removeAttribute('data-reset'); Util.setAttributes(tooltipObj.tooltip, {'id': tooltipObj.tooltipId, 'class': 'tooltip tooltip--is-hidden js-tooltip', 'role': 'tooltip'}); tooltipObj.tooltip.innerHTML = tooltipObj.tooltipContent; if(tooltipObj.tooltipDescription) tooltipObj.element.setAttribute('aria-describedby', tooltipObj.tooltipId); if(tooltipObj.tooltipClasses) Util.addClass(tooltipObj.tooltip, tooltipObj.tooltipClasses); if(tooltipObj.tooltipSticky) Util.addClass(tooltipObj.tooltip, 'tooltip--sticky'); placeTooltip(tooltipObj); Util.removeClass(tooltipObj.tooltip, 'tooltip--is-hidden'); if(!tooltipObj.tooltipSticky) return; tooltipObj.tooltip.addEventListener('mouseenter', function cb(){ tooltipObj.tooltipHover = true; if(tooltipObj.tooltipHoverInterval) { clearInterval(tooltipObj.tooltipHoverInterval); tooltipObj.tooltipHoverInterval = false; } tooltipObj.tooltip.removeEventListener('mouseenter', cb); tooltipLeaveEvent(tooltipObj); }); }; function tooltipLeaveEvent(tooltipObj) { tooltipObj.tooltip.addEventListener('mouseleave', function cb(){ tooltipObj.tooltipHover = false; tooltipObj.tooltip.removeEventListener('mouseleave', cb); hideTooltip(tooltipObj); }); }; function placeTooltip(tooltipObj) { var dimention = [tooltipObj.tooltip.offsetHeight, tooltipObj.tooltip.offsetWidth], positionTrigger = tooltipObj.element.getBoundingClientRect(), position = [], scrollY = window.scrollY || window.pageYOffset; position['top'] = [ (positionTrigger.top - dimention[0] - tooltipObj.tooltipDelta + scrollY), (positionTrigger.right/2 + positionTrigger.left/2 - dimention[1]/2)]; position['bottom'] = [ (positionTrigger.bottom + tooltipObj.tooltipDelta + scrollY), (positionTrigger.right/2 + positionTrigger.left/2 - dimention[1]/2)]; position['left'] = [(positionTrigger.top/2 + positionTrigger.bottom/2 - dimention[0]/2 + scrollY), positionTrigger.left - dimention[1] - tooltipObj.tooltipDelta]; position['right'] = [(positionTrigger.top/2 + positionTrigger.bottom/2 - dimention[0]/2 + scrollY), positionTrigger.right + tooltipObj.tooltipDelta]; var direction = tooltipObj.tooltipPosition; if( direction == 'top' && position['top'][0] < scrollY) direction = 'bottom'; else if( direction == 'bottom' && position['bottom'][0] + tooltipObj.tooltipDelta + dimention[0] > scrollY + window.innerHeight) direction = 'top'; else if( direction == 'left' && position['left'][1] < 0 ) direction = 'right'; else if( direction == 'right' && position['right'][1] + dimention[1] > window.innerWidth ) direction = 'left'; tooltipObj.tooltip.style.setProperty(tooltipObj.tooltipTriangleVar, '0px'); if(direction == 'top' || direction == 'bottom') { var deltaMarg = 5; if(position[direction][1] < 0 ) { position[direction][1] = deltaMarg; tooltipObj.tooltip.style.setProperty(tooltipObj.tooltipTriangleVar, (positionTrigger.left + 0.5*positionTrigger.width - 0.5*dimention[1] - deltaMarg)+'px'); } if(position[direction][1] + dimention[1] > window.innerWidth ) { position[direction][1] = window.innerWidth - dimention[1] - deltaMarg; tooltipObj.tooltip.style.setProperty(tooltipObj.tooltipTriangleVar, (0.5*dimention[1] - (window.innerWidth - positionTrigger.right) - 0.5*positionTrigger.width + deltaMarg)+'px'); } } tooltipObj.tooltip.style.top = position[direction][0]+'px'; tooltipObj.tooltip.style.left = position[direction][1]+'px'; Util.addClass(tooltipObj.tooltip, 'tooltip--'+direction); }; function checkTooltip(tooltipObj) { tooltipObj.tooltipTriggerHover = false; if(!tooltipObj.tooltipSticky) hideTooltip(tooltipObj); else { if(tooltipObj.tooltipHover) return; if(tooltipObj.tooltipHoverInterval) return; tooltipObj.tooltipHoverInterval = setTimeout(function(){ hideTooltip(tooltipObj); tooltipObj.tooltipHoverInterval = false; }, 300); } }; function hideTooltip(tooltipObj) { if(tooltipObj.tooltipHover || tooltipObj.tooltipTriggerHover) return; clearInterval(tooltipObj.tooltipIntervalId); if(tooltipObj.tooltipHoverInterval) { clearInterval(tooltipObj.tooltipHoverInterval); tooltipObj.tooltipHoverInterval = false; } tooltipObj.tooltipIntervalId = false; if(!tooltipObj.tooltip) return; removeTooltip(tooltipObj); removeTooltipEvents(tooltipObj); }; function removeTooltip(tooltipObj) { if(tooltipObj.tooltipContent == tooltipObj.tooltip.innerHTML || tooltipObj.tooltip.getAttribute('data-reset') == 'on') { Util.addClass(tooltipObj.tooltip, 'tooltip--is-hidden'); tooltipObj.tooltip.removeAttribute('data-reset'); } if(tooltipObj.tooltipDescription) tooltipObj.element.removeAttribute('aria-describedby'); }; function changeTooltipContent(tooltipObj, event) { if(tooltipObj.tooltip && tooltipObj.tooltipTriggerHover && event.detail) { tooltipObj.tooltip.innerHTML = event.detail; tooltipObj.tooltip.setAttribute('data-reset', 'on'); placeTooltip(tooltipObj); } }; window.Tooltip = Tooltip; var tooltips = document.getElementsByClassName('js-tooltip-trigger'); if( tooltips.length > 0 ) { for( var i = 0; i < tooltips.length; i++) { (function(i){new Tooltip(tooltips[i]);})(i); } } }()); // smooth scroll (function() { var SmoothScroll = function(element) { if(!('CSS' in window) || !CSS.supports('color', 'var(--color-var)')) return; this.element = element; this.scrollDuration = parseInt(this.element.getAttribute('data-duration')) || 300; this.dataElementY = this.element.getAttribute('data-scrollable-element-y') || this.element.getAttribute('data-scrollable-element') || this.element.getAttribute('data-element'); this.scrollElementY = this.dataElementY ? document.querySelector(this.dataElementY) : window; this.dataElementX = this.element.getAttribute('data-scrollable-element-x'); this.scrollElementX = this.dataElementY ? document.querySelector(this.dataElementX) : window; this.initScroll(); }; SmoothScroll.prototype.initScroll = function() { var self = this; this.element.addEventListener('click', function(event){ event.preventDefault(); var targetId = event.target.closest('.js-smooth-scroll').getAttribute('href').replace('#', ''), target = document.getElementById(targetId), targetTabIndex = target.getAttribute('tabindex'), windowScrollTop = self.scrollElementY.scrollTop || document.documentElement.scrollTop; if(!self.dataElementY) windowScrollTop = window.scrollY || document.documentElement.scrollTop; var scrollElementY = self.dataElementY ? self.scrollElementY : false; var fixedHeight = self.getFixedElementHeight(); Util.scrollTo(target.getBoundingClientRect().top + windowScrollTop - fixedHeight, self.scrollDuration, function() { self.scrollHorizontally(target, fixedHeight); Util.moveFocus(target); history.pushState(false, false, '#'+targetId); self.resetTarget(target, targetTabIndex); }, scrollElementY); }); }; SmoothScroll.prototype.scrollHorizontally = function(target, delta) { var scrollEl = this.dataElementX ? this.scrollElementX : false; var windowScrollLeft = this.scrollElementX ? this.scrollElementX.scrollLeft : document.documentElement.scrollLeft; var final = target.getBoundingClientRect().left + windowScrollLeft - delta, duration = this.scrollDuration; var element = scrollEl || window; var start = element.scrollLeft || document.documentElement.scrollLeft, currentTime = null; if(!scrollEl) start = window.scrollX || document.documentElement.scrollLeft; if(Math.abs(start - final) < 5) return; var animateScroll = function(timestamp){ if (!currentTime) currentTime = timestamp; var progress = timestamp - currentTime; if(progress > duration) progress = duration; var val = Math.easeInOutQuad(progress, start, final-start, duration); element.scrollTo({ left: val, }); if(progress < duration) { window.requestAnimationFrame(animateScroll); } }; window.requestAnimationFrame(animateScroll); }; SmoothScroll.prototype.resetTarget = function(target, tabindex) { if( parseInt(target.getAttribute('tabindex')) < 0) { target.style.outline = 'none'; !tabindex && target.removeAttribute('tabindex'); } }; SmoothScroll.prototype.getFixedElementHeight = function() { var scrollElementY = this.dataElementY ? this.scrollElementY : document.documentElement; var fixedElementDelta = parseInt(getComputedStyle(scrollElementY).getPropertyValue('scroll-padding')); if(isNaN(fixedElementDelta) ) { fixedElementDelta = 0; var fixedElement = document.querySelector(this.element.getAttribute('data-fixed-element')); if(fixedElement) fixedElementDelta = parseInt(fixedElement.getBoundingClientRect().height); } return fixedElementDelta; }; var smoothScrollLinks = document.getElementsByClassName('js-smooth-scroll'); if( smoothScrollLinks.length > 0 && !Util.cssSupports('scroll-behavior', 'smooth') && window.requestAnimationFrame) { for( var i = 0; i < smoothScrollLinks.length; i++) { (function(i){new SmoothScroll(smoothScrollLinks[i]);})(i); } } }()); // animated menu (function() { var menuBtns = document.getElementsByClassName('js-anim-menu-btn'); if( menuBtns.length > 0 ) { for(var i = 0; i < menuBtns.length; i++) {(function(i){ initMenuBtn(menuBtns[i]); })(i);} function initMenuBtn(btn) { btn.addEventListener('click', function(event){ event.preventDefault(); var status = !Util.hasClass(btn, 'anim-menu-btn--state-b'); Util.toggleClass(btn, 'anim-menu-btn--state-b', status); // emit custom event var event = new CustomEvent('anim-menu-btn-clicked', {detail: status}); btn.dispatchEvent(event); }); }; } }()); // social shares (function() { function initSocialShare(button) { button.addEventListener('click', function(event){ event.preventDefault(); var social = button.getAttribute('data-social'); var url = getSocialUrl(button, social); (social == 'mail') ? window.location.href = url : window.open(url, social+'-share-dialog', 'width=626,height=436'); }); }; function getSocialUrl(button, social) { var params = getSocialParams(social); var newUrl = ''; for(var i = 0; i < params.length; i++) { var paramValue = button.getAttribute('data-'+params[i]); if(params[i] == 'hashtags') paramValue = encodeURI(paramValue.replace(/\#| /g, '')); if(paramValue) { (social == 'facebook') ? newUrl = newUrl + 'u='+encodeURIComponent(paramValue)+'&' : newUrl = newUrl + params[i]+'='+encodeURIComponent(paramValue)+'&'; } } if(social == 'linkedin') newUrl = 'mini=true&'+newUrl; return button.getAttribute('href')+'?'+newUrl; }; function getSocialParams(social) { var params = []; switch (social) { case 'twitter': params = ['text', 'hashtags']; break; case 'facebook': case 'linkedin': params = ['url']; break; case 'pinterest': params = ['url', 'media', 'description']; break; case 'mail': params = ['subject', 'body']; break; } return params; }; var socialShare = document.getElementsByClassName('js-social-share'); if(socialShare.length > 0) { for( var i = 0; i < socialShare.length; i++) { (function(i){initSocialShare(socialShare[i])})(i); } } }()); // countdown (function() { var CountDown = function(element) { this.element = element; this.labels = this.element.getAttribute('data-labels') ? this.element.getAttribute('data-labels').split(',') : []; this.intervalId; // set visible labels this.setVisibleLabels(); //create countdown HTML this.createCountDown(); //store time elements this.days = this.element.getElementsByClassName('js-countdown__value--0')[0]; this.hours = this.element.getElementsByClassName('js-countdown__value--1')[0]; this.mins = this.element.getElementsByClassName('js-countdown__value--2')[0]; this.secs = this.element.getElementsByClassName('js-countdown__value--3')[0]; this.endTime = this.getEndTime(); //init counter this.initCountDown(); }; CountDown.prototype.setVisibleLabels = function() { this.visibleLabels = this.element.getAttribute('data-visible-labels') ? this.element.getAttribute('data-visible-labels').split(',') : []; this.visibleLabels = this.visibleLabels.map(function(label){ return label.trim(); }); }; CountDown.prototype.createCountDown = function() { var wrapper = document.createElement("div"); Util.setAttributes(wrapper, {'aria-hidden': 'true', 'class': 'countdown__timer'}); for(var i = 0; i < 4; i++) { var timeItem = document.createElement("span"), timeValue = document.createElement("span"), timeLabel = document.createElement('span'); timeItem.setAttribute('class', 'countdown__item'); timeValue.setAttribute('class', 'countdown__value countdown__value--'+i+' js-countdown__value--'+i); timeItem.appendChild(timeValue); if( this.labels && this.labels.length > 0 ) { timeLabel.textContent = this.labels[i].trim(); timeLabel.setAttribute('class', 'countdown__label'); timeItem.appendChild(timeLabel); } wrapper.appendChild(timeItem); } this.element.insertBefore(wrapper, this.element.firstChild); }; CountDown.prototype.getEndTime = function() { if(this.element.getAttribute('data-timer')) return Number(this.element.getAttribute('data-timer'))*1000 + new Date().getTime(); else if(this.element.getAttribute('data-countdown')) return Number(new Date(this.element.getAttribute('data-countdown')).getTime()); }; CountDown.prototype.initCountDown = function() { var self = this; this.intervalId = setInterval(function(){ self.updateCountDown(false); }, 1000); this.updateCountDown(true); }; CountDown.prototype.updateCountDown = function(bool) { var time = parseInt( (this.endTime - new Date().getTime())/1000 ), days = 0, hours = 0, mins = 0, seconds = 0; if(isNaN(time) || time < 0) { clearInterval(this.intervalId); this.emitEndEvent(); } else { days = parseInt(time / 86400); time = (time % 86400); hours = parseInt(time / 3600); time = (time % 3600); mins = parseInt(time / 60); time = (time % 60); seconds = parseInt(time); } if(bool && days == 0 && this.visibleLabels.indexOf('d') < 0) this.days.parentElement.style.display = "none"; if(bool && days == 0 && hours == 0 && this.visibleLabels.indexOf('h') < 0) this.hours.parentElement.style.display = "none"; if(bool && days == 0 && hours == 0 && mins == 0 && this.visibleLabels.indexOf('m') < 0) this.mins.parentElement.style.display = "none"; this.days.textContent = days; this.hours.textContent = this.getTimeFormat(hours); this.mins.textContent = this.getTimeFormat(mins); this.secs.textContent = this.getTimeFormat(seconds); }; CountDown.prototype.getTimeFormat = function(time) { return ('0'+ time).slice(-2); }; CountDown.prototype.emitEndEvent = function(time) { var event = new CustomEvent('countDownFinished'); this.element.dispatchEvent(event); }; var countDown = document.getElementsByClassName('js-countdown'); if( countDown.length > 0 ) { for( var i = 0; i < countDown.length; i++) { (function(i){new CountDown(countDown[i]);})(i); } } }()); // notice bar (function() { function initNoticeEvents(notice) { notice.addEventListener('click', function(event){ if(event.target.closest('.js-notice__hide-control')) { event.preventDefault(); Util.addClass(notice, 'notice--hide'); } }); }; var noticeElements = document.getElementsByClassName('js-notice'); if(noticeElements.length > 0) { for(var i=0; i < noticeElements.length; i++) {(function(i){ initNoticeEvents(noticeElements[i]); })(i);} } }()); // back to top button (function() { var backTop = document.getElementsByClassName('js-back-to-top')[0]; if( backTop ) { var dataElement = backTop.getAttribute('data-element'); var scrollElement = dataElement ? document.querySelector(dataElement) : window; var scrollOffsetInit = parseInt(backTop.getAttribute('data-offset-in')) || parseInt(backTop.getAttribute('data-offset')) || 0, //show back-to-top if scrolling > scrollOffset scrollOffsetOutInit = parseInt(backTop.getAttribute('data-offset-out')) || 0, scrollOffset = 0, scrollOffsetOut = 0, scrolling = false; // check if target-in/target-out have been set var targetIn = backTop.getAttribute('data-target-in') ? document.querySelector(backTop.getAttribute('data-target-in')) : false, targetOut = backTop.getAttribute('data-target-out') ? document.querySelector(backTop.getAttribute('data-target-out')) : false; updateOffsets(); //detect click on back-to-top link backTop.addEventListener('click', function(event) { event.preventDefault(); if(!window.requestAnimationFrame) { scrollElement.scrollTo(0, 0); } else { dataElement ? scrollElement.scrollTo({top: 0, behavior: 'smooth'}) : window.scrollTo({top: 0, behavior: 'smooth'}); } //move the focus to the #top-element - don't break keyboard navigation moveFocus(document.getElementById(backTop.getAttribute('href').replace('#', ''))); }); //listen to the window scroll and update back-to-top visibility checkBackToTop(); if (scrollOffset > 0 || scrollOffsetOut > 0) { scrollElement.addEventListener("scroll", function(event) { if( !scrolling ) { scrolling = true; (!window.requestAnimationFrame) ? setTimeout(function(){checkBackToTop();}, 250) : window.requestAnimationFrame(checkBackToTop); } }); } function checkBackToTop() { updateOffsets(); var windowTop = scrollElement.scrollTop || document.documentElement.scrollTop; if(!dataElement) windowTop = window.scrollY || document.documentElement.scrollTop; var condition = windowTop >= scrollOffset; if(scrollOffsetOut > 0) { condition = (windowTop >= scrollOffset) && (window.innerHeight + windowTop < scrollOffsetOut); } backTop.classList.toggle('back-to-top--is-visible', condition); scrolling = false; } function updateOffsets() { scrollOffset = getOffset(targetIn, scrollOffsetInit, true); scrollOffsetOut = getOffset(targetOut, scrollOffsetOutInit); } function getOffset(target, startOffset, bool) { var offset = 0; if(target) { var windowTop = scrollElement.scrollTop || document.documentElement.scrollTop; if(!dataElement) windowTop = window.scrollY || document.documentElement.scrollTop; var boundingClientRect = target.getBoundingClientRect(); offset = bool ? boundingClientRect.bottom : boundingClientRect.top; offset = offset + windowTop; } if(startOffset && startOffset) { offset = offset + parseInt(startOffset); } return offset; } function moveFocus(element) { if( !element ) element = document.getElementsByTagName("body")[0]; element.focus(); if (document.activeElement !== element) { element.setAttribute('tabindex','-1'); element.focus(); } }; } }()); (function() { var Masonry = function(element) { this.element = element; this.list = this.element.getElementsByClassName('js-masonry__list')[0]; this.items = this.element.getElementsByClassName('js-masonry__item'); this.activeColumns = 0; this.colStartWidth = 0; // col min-width (defined in CSS using --masonry-col-auto-size variable) this.colWidth = 0; // effective column width this.colGap = 0; // store col heights and items this.colHeights = []; this.colItems = []; // flex full support this.flexSupported = checkFlexSupported(this.items[0]); getGridLayout(this); // get initial grid params setGridLayout(this); // set grid params (width of elements) initMasonryLayout(this); // init gallery layout }; function checkFlexSupported(item) { var itemStyle = window.getComputedStyle(item); return itemStyle.getPropertyValue('flex-basis') != 'auto'; }; function getGridLayout(grid) { // this is used to get initial grid details (width/grid gap) var itemStyle = window.getComputedStyle(grid.items[0]); if( grid.colStartWidth == 0) { grid.colStartWidth = parseFloat(itemStyle.getPropertyValue('width')); } grid.colGap = parseFloat(itemStyle.getPropertyValue('margin-right')); }; function setGridLayout(grid) { // set width of items in the grid var containerWidth = parseFloat(window.getComputedStyle(grid.element).getPropertyValue('width')); grid.activeColumns = parseInt((containerWidth + grid.colGap)/(grid.colStartWidth+grid.colGap)); if(grid.activeColumns == 0) grid.activeColumns = 1; grid.colWidth = parseFloat((containerWidth - (grid.activeColumns - 1)*grid.colGap)/grid.activeColumns); for(var i = 0; i < grid.items.length; i++) { grid.items[i].style.width = grid.colWidth+'px'; // reset items width } }; function initMasonryLayout(grid) { if(grid.flexSupported) { checkImgLoaded(grid); // reset layout when images are loaded } else { Util.addClass(grid.element, 'masonry--loaded'); // make sure the gallery is visible } grid.element.addEventListener('masonry-resize', function(){ // window has been resized -> reset masonry layout getGridLayout(grid); setGridLayout(grid); if(grid.flexSupported) layItems(grid); }); grid.element.addEventListener('masonry-reset', function(event){ // reset layout (e.g., new items added to the gallery) if(grid.flexSupported) checkImgLoaded(grid); }); // if there are fonts to be loaded -> reset masonry if(document.fonts) { document.fonts.onloadingdone = function (fontFaceSetEvent) { if(!grid.masonryLaid) return; getGridLayout(grid); setGridLayout(grid); if(grid.flexSupported) layItems(grid); }; } }; function layItems(grid) { Util.addClass(grid.element, 'masonry--loaded'); // make sure the gallery is visible grid.colHeights = []; grid.colItems = []; // grid layout has already been set -> update container height and order of items for(var j = 0; j < grid.activeColumns; j++) { grid.colHeights.push(0); // reset col heights grid.colItems[j] = []; // reset items order } for(var i = 0; i < grid.items.length; i++) { var minHeight = Math.min.apply( Math, grid.colHeights ), index = grid.colHeights.indexOf(minHeight); if(grid.colItems[index]) grid.colItems[index].push(i); grid.items[i].style.flexBasis = 0; // reset flex basis before getting height var itemHeight = grid.items[i].getBoundingClientRect().height || grid.items[i].offsetHeight || 1; grid.colHeights[index] = grid.colHeights[index] + grid.colGap + itemHeight; } // reset height of container var masonryHeight = Math.max.apply( Math, grid.colHeights ) + 5; grid.list.style.cssText = 'height: '+ masonryHeight + 'px;'; // go through elements and set flex order var order = 0; for(var i = 0; i < grid.colItems.length; i++) { for(var j = 0; j < grid.colItems[i].length; j++) { grid.items[grid.colItems[i][j]].style.order = order; order = order + 1; } // change flex-basis of last element of each column, so that next element shifts to next col var lastItemCol = grid.items[grid.colItems[i][grid.colItems[i].length - 1]]; if(lastItemCol) lastItemCol.style.flexBasis = masonryHeight - grid.colHeights[i] + lastItemCol.getBoundingClientRect().height - 5 + 'px'; } grid.masonryLaid = true; // emit custom event when grid has been reset grid.element.dispatchEvent(new CustomEvent('masonry-laid')); }; function checkImgLoaded(grid) { var imgs = grid.list.getElementsByTagName('img'); function countLoaded() { var setTimeoutOn = false; for(var i = 0; i < imgs.length; i++) { if(imgs[i].complete && imgs[i].naturalHeight == 0) { continue; // broken image -> skip } if(!imgs[i].complete) { setTimeoutOn = true; break; } else if (typeof imgs[i].naturalHeight !== "undefined" && imgs[i].naturalHeight == 0) { setTimeoutOn = true; break; } } if(!setTimeoutOn) { layItems(grid); } else { setTimeout(function(){ countLoaded(); }, 100); } }; if(imgs.length == 0) { layItems(grid); // no need to wait -> no img available } else { countLoaded(); } }; //initialize the Masonry objects var masonries = document.getElementsByClassName('js-masonry'), flexSupported = Util.cssSupports('flex-basis', 'auto'), masonriesArray = []; if( masonries.length > 0) { for( var i = 0; i < masonries.length; i++) { if(!flexSupported) { Util.addClass(masonries[i], 'masonry--loaded'); // reveal gallery } else { (function(i){masonriesArray.push(new Masonry(masonries[i]));})(i); // init Masonry Layout } } if(!flexSupported) return; // listen to window resize -> reorganize items in gallery var resizingId = false, customEvent = new CustomEvent('masonry-resize'); window.addEventListener('resize', function() { clearTimeout(resizingId); resizingId = setTimeout(doneResizing, 500); }); function doneResizing() { for( var i = 0; i < masonriesArray.length; i++) { (function(i){masonriesArray[i].element.dispatchEvent(customEvent)})(i); }; }; }; }()); (function() { var fxElements = document.getElementsByClassName('reveal-fx'); var intersectionObserverSupported = ('IntersectionObserver' in window && 'IntersectionObserverEntry' in window && 'intersectionRatio' in window.IntersectionObserverEntry.prototype); if(fxElements.length > 0) { // deactivate effect if Reduced Motion is enabled if (Util.osHasReducedMotion() || !intersectionObserverSupported) { fxRemoveClasses(); return; } //on small devices, do not animate elements -> reveal all if( fxDisabled(fxElements[0]) ) { fxRevealAll(); return; } var fxRevealDelta = 120; // amount (in pixel) the element needs to enter the viewport to be revealed - if not custom value (data-reveal-fx-delta) var viewportHeight = window.innerHeight, fxChecking = false, fxRevealedItems = [], fxElementDelays = fxGetDelays(), //elements animation delay fxElementDeltas = fxGetDeltas(); // amount (in px) the element needs enter the viewport to be revealed (default value is fxRevealDelta) // add event listeners window.addEventListener('load', fxReveal); window.addEventListener('resize', fxResize); window.addEventListener('restartAll', fxRestart); // observe reveal elements var observer = []; initObserver(); function initObserver() { for(var i = 0; i < fxElements.length; i++) { observer[i] = new IntersectionObserver( function(entries, observer) { if(entries[0].isIntersecting) { fxRevealItemObserver(entries[0].target); observer.unobserve(entries[0].target); } }, {rootMargin: "0px 0px -"+fxElementDeltas[i]+"px 0px"} ); observer[i].observe(fxElements[i]); } }; function fxRevealAll() { // reveal all elements - small devices for(var i = 0; i < fxElements.length; i++) { Util.addClass(fxElements[i], 'reveal-fx--is-visible'); } }; function fxResize() { // on resize - check new window height and reveal visible elements if(fxChecking) return; fxChecking = true; (!window.requestAnimationFrame) ? setTimeout(function(){fxReset();}, 250) : window.requestAnimationFrame(fxReset); }; function fxReset() { viewportHeight = window.innerHeight; fxReveal(); }; function fxReveal() { // reveal visible elements for(var i = 0; i < fxElements.length; i++) {(function(i){ if(fxRevealedItems.indexOf(i) != -1 ) return; //element has already been revelead if(fxElementIsVisible(fxElements[i], i)) { fxRevealItem(i); fxRevealedItems.push(i); }})(i); } fxResetEvents(); fxChecking = false; }; function fxRevealItem(index) { if(fxElementDelays[index] && fxElementDelays[index] != 0) { // wait before revealing element if a delay was added setTimeout(function(){ Util.addClass(fxElements[index], 'reveal-fx--is-visible'); }, fxElementDelays[index]); } else { Util.addClass(fxElements[index], 'reveal-fx--is-visible'); } }; function fxRevealItemObserver(item) { var index = Util.getIndexInArray(fxElements, item); if(fxRevealedItems.indexOf(index) != -1 ) return; //element has already been revelead fxRevealItem(index); fxRevealedItems.push(index); fxResetEvents(); fxChecking = false; }; function fxGetDelays() { // get anmation delays var delays = []; for(var i = 0; i < fxElements.length; i++) { delays.push( fxElements[i].getAttribute('data-reveal-fx-delay') ? parseInt(fxElements[i].getAttribute('data-reveal-fx-delay')) : 0); } return delays; }; function fxGetDeltas() { // get reveal delta var deltas = []; for(var i = 0; i < fxElements.length; i++) { deltas.push( fxElements[i].getAttribute('data-reveal-fx-delta') ? parseInt(fxElements[i].getAttribute('data-reveal-fx-delta')) : fxRevealDelta); } return deltas; }; function fxDisabled(element) { // check if elements need to be animated - no animation on small devices return !(window.getComputedStyle(element, '::before').getPropertyValue('content').replace(/'|"/g, "") == 'reveal-fx'); }; function fxElementIsVisible(element, i) { // element is inside viewport return (fxGetElementPosition(element) <= viewportHeight - fxElementDeltas[i]); }; function fxGetElementPosition(element) { // get top position of element return element.getBoundingClientRect().top; }; function fxResetEvents() { if(fxElements.length > fxRevealedItems.length) return; // remove event listeners if all elements have been revealed window.removeEventListener('load', fxReveal); window.removeEventListener('resize', fxResize); }; function fxRemoveClasses() { // Reduced Motion on or Intersection Observer not supported while(fxElements[0]) { // remove all classes starting with 'reveal-fx--' var classes = fxElements[0].getAttribute('class').split(" ").filter(function(c) { return c.lastIndexOf('reveal-fx--', 0) !== 0; }); fxElements[0].setAttribute('class', classes.join(" ").trim()); Util.removeClass(fxElements[0], 'reveal-fx'); } }; function fxRestart() { // restart the reveal effect -> hide all elements and re-init the observer if (Util.osHasReducedMotion() || !intersectionObserverSupported || fxDisabled(fxElements[0])) { return; } // check if we need to add the event listensers back if(fxElements.length <= fxRevealedItems.length) { window.addEventListener('load', fxReveal); window.addEventListener('resize', fxResize); } // remove observer and reset the observer array for(var i = 0; i < observer.length; i++) { if(observer[i]) observer[i].disconnect(); } observer = []; // remove visible class for(var i = 0; i < fxElements.length; i++) { Util.removeClass(fxElements[i], 'reveal-fx--is-visible'); } // reset fxRevealedItems array fxRevealedItems = []; // restart observer initObserver(); }; } }()); (function() { var SwipeContent = function(element) { this.element = element; this.delta = [false, false]; this.dragging = false; this.intervalId = false; initSwipeContent(this); }; function initSwipeContent(content) { content.element.addEventListener('mousedown', handleEvent.bind(content)); content.element.addEventListener('touchstart', handleEvent.bind(content), {passive: true}); }; function initDragging(content) { //add event listeners content.element.addEventListener('mousemove', handleEvent.bind(content)); content.element.addEventListener('touchmove', handleEvent.bind(content), {passive: true}); content.element.addEventListener('mouseup', handleEvent.bind(content)); content.element.addEventListener('mouseleave', handleEvent.bind(content)); content.element.addEventListener('touchend', handleEvent.bind(content)); }; function cancelDragging(content) { //remove event listeners if(content.intervalId) { (!window.requestAnimationFrame) ? clearInterval(content.intervalId) : window.cancelAnimationFrame(content.intervalId); content.intervalId = false; } content.element.removeEventListener('mousemove', handleEvent.bind(content)); content.element.removeEventListener('touchmove', handleEvent.bind(content)); content.element.removeEventListener('mouseup', handleEvent.bind(content)); content.element.removeEventListener('mouseleave', handleEvent.bind(content)); content.element.removeEventListener('touchend', handleEvent.bind(content)); }; function handleEvent(event) { switch(event.type) { case 'mousedown': case 'touchstart': startDrag(this, event); break; case 'mousemove': case 'touchmove': drag(this, event); break; case 'mouseup': case 'mouseleave': case 'touchend': endDrag(this, event); break; } }; function startDrag(content, event) { content.dragging = true; // listen to drag movements initDragging(content); content.delta = [parseInt(unify(event).clientX), parseInt(unify(event).clientY)]; // emit drag start event emitSwipeEvents(content, 'dragStart', content.delta, event.target); }; function endDrag(content, event) { cancelDragging(content); var dx = parseInt(unify(event).clientX), dy = parseInt(unify(event).clientY); // check if there was a left/right swipe if(content.delta && (content.delta[0] || content.delta[0] === 0)) { var s = getSign(dx - content.delta[0]); if(Math.abs(dx - content.delta[0]) > 30) { (s < 0) ? emitSwipeEvents(content, 'swipeLeft', [dx, dy]) : emitSwipeEvents(content, 'swipeRight', [dx, dy]); } content.delta[0] = false; } // check if there was a top/bottom swipe if(content.delta && (content.delta[1] || content.delta[1] === 0)) { var y = getSign(dy - content.delta[1]); if(Math.abs(dy - content.delta[1]) > 30) { (y < 0) ? emitSwipeEvents(content, 'swipeUp', [dx, dy]) : emitSwipeEvents(content, 'swipeDown', [dx, dy]); } content.delta[1] = false; } // emit drag end event emitSwipeEvents(content, 'dragEnd', [dx, dy]); content.dragging = false; }; function drag(content, event) { if(!content.dragging) return; // emit dragging event with coordinates (!window.requestAnimationFrame) ? content.intervalId = setTimeout(function(){emitDrag.bind(content, event);}, 250) : content.intervalId = window.requestAnimationFrame(emitDrag.bind(content, event)); }; function emitDrag(event) { emitSwipeEvents(this, 'dragging', [parseInt(unify(event).clientX), parseInt(unify(event).clientY)]); }; function unify(event) { // unify mouse and touch events return event.changedTouches ? event.changedTouches[0] : event; }; function emitSwipeEvents(content, eventName, detail, el) { var trigger = false; if(el) trigger = el; // emit event with coordinates var event = new CustomEvent(eventName, {detail: {x: detail[0], y: detail[1], origin: trigger}}); content.element.dispatchEvent(event); }; function getSign(x) { if(!Math.sign) { return ((x > 0) - (x < 0)) || +x; } else { return Math.sign(x); } }; window.SwipeContent = SwipeContent; //initialize the SwipeContent objects var swipe = document.getElementsByClassName('js-swipe-content'); if( swipe.length > 0 ) { for( var i = 0; i < swipe.length; i++) { (function(i){new SwipeContent(swipe[i]);})(i); } } }()); // tab gallery (function() { var LoopTab = function(opts) { this.options = Util.extend(LoopTab.defaults , opts); this.element = this.options.element; this.tabList = this.element.getElementsByClassName('js-loop-tabs__controls')[0]; this.listItems = this.tabList.getElementsByTagName('li'); this.triggers = this.tabList.getElementsByTagName('a'); this.panelsList = this.element.getElementsByClassName('js-loop-tabs__panels')[0]; this.panels = Util.getChildrenByClassName(this.panelsList, 'js-loop-tabs__panel'); this.assetsList = this.element.getElementsByClassName('js-loop-tabs__assets')[0]; this.assets = this.assetsList.getElementsByTagName('li'); this.videos = getVideoElements(this); this.panelShowClass = 'loop-tabs__panel--selected'; this.assetShowClass = 'loop-tabs__asset--selected'; this.assetExitClass = 'loop-tabs__asset--exit'; this.controlActiveClass = 'loop-tabs__control--selected'; // autoplay this.autoplayPaused = false; this.loopTabAutoId = false; this.loopFillAutoId = false; this.loopFill = 0; initLoopTab(this); }; function getVideoElements(tab) { var videos = []; for(var i = 0; i < tab.assets.length; i++) { var video = tab.assets[i].getElementsByTagName('video'); videos[i] = video.length > 0 ? video[0] : false; } return videos; }; function initLoopTab(tab) { //set initial aria attributes tab.tabList.setAttribute('role', 'tablist'); for( var i = 0; i < tab.triggers.length; i++) { var bool = Util.hasClass(tab.triggers[i], tab.controlActiveClass), panelId = tab.panels[i].getAttribute('id'); tab.listItems[i].setAttribute('role', 'presentation'); Util.setAttributes(tab.triggers[i], {'role': 'tab', 'aria-selected': bool, 'aria-controls': panelId, 'id': 'tab-'+panelId}); Util.addClass(tab.triggers[i], 'js-loop-tabs__trigger'); Util.setAttributes(tab.panels[i], {'role': 'tabpanel', 'aria-labelledby': 'tab-'+panelId}); Util.toggleClass(tab.panels[i], tab.panelShowClass, bool); Util.toggleClass(tab.assets[i], tab.assetShowClass, bool); resetVideo(tab, i, bool); // play/pause video if available if(!bool) tab.triggers[i].setAttribute('tabindex', '-1'); } // add autoplay-off class if needed !tab.options.autoplay && Util.addClass(tab.element, 'loop-tabs--autoplay-off'); //listen for Tab events initLoopTabEvents(tab); }; function initLoopTabEvents(tab) { if(tab.options.autoplay) { initLoopTabAutoplay(tab); // init autoplay // pause autoplay if user is interacting with the tabs tab.element.addEventListener('focusin', function(event){ pauseLoopTabAutoplay(tab); tab.autoplayPaused = true; }); tab.element.addEventListener('focusout', function(event){ tab.autoplayPaused = false; initLoopTabAutoplay(tab); }); } //click on a new tab -> select content tab.tabList.addEventListener('click', function(event) { if( event.target.closest('.js-loop-tabs__trigger') ) triggerLoopTab(tab, event.target.closest('.js-loop-tabs__trigger'), event); }); //arrow keys to navigate through tabs tab.tabList.addEventListener('keydown', function(event) { if( !event.target.closest('.js-loop-tabs__trigger') ) return; if( event.keyCode && event.keyCode == 39 || event.key && event.key.toLowerCase() == 'arrowright' ) { pauseLoopTabAutoplay(tab); selectNewLoopTab(tab, 'next', true); } else if( event.keyCode && event.keyCode == 37 || event.key && event.key.toLowerCase() == 'arrowleft' ) { pauseLoopTabAutoplay(tab); selectNewLoopTab(tab, 'prev', true); } }); }; function initLoopTabAutoplay(tab) { if(!tab.options.autoplay || tab.autoplayPaused) return; tab.loopFill = 0; var selectedTab = tab.tabList.getElementsByClassName(tab.controlActiveClass)[0]; // reset css variables for(var i = 0; i < tab.triggers.length; i++) { if(cssVariableSupport) tab.triggers[i].style.setProperty('--loop-tabs-filling', 0); } tab.loopTabAutoId = setTimeout(function(){ selectNewLoopTab(tab, 'next', false); }, tab.options.autoplayInterval); if(cssVariableSupport) { // tab fill effect tab.loopFillAutoId = setInterval(function(){ tab.loopFill = tab.loopFill + 0.005; selectedTab.style.setProperty('--loop-tabs-filling', tab.loopFill); }, tab.options.autoplayInterval/200); } }; function pauseLoopTabAutoplay(tab) { // pause autoplay if(tab.loopTabAutoId) { clearTimeout(tab.loopTabAutoId); tab.loopTabAutoId = false; clearInterval(tab.loopFillAutoId); tab.loopFillAutoId = false; // make sure the filling line is scaled up var selectedTab = tab.tabList.getElementsByClassName(tab.controlActiveClass); if(selectedTab.length > 0) selectedTab[0].style.setProperty('--loop-tabs-filling', 1); } }; function selectNewLoopTab(tab, direction, bool) { var selectedTab = tab.tabList.getElementsByClassName(tab.controlActiveClass)[0], index = Util.getIndexInArray(tab.triggers, selectedTab); index = (direction == 'next') ? index + 1 : index - 1; //make sure index is in the correct interval //-> from last element go to first using the right arrow, from first element go to last using the left arrow if(index < 0) index = tab.listItems.length - 1; if(index >= tab.listItems.length) index = 0; triggerLoopTab(tab, tab.triggers[index]); bool && tab.triggers[index].focus(); }; function triggerLoopTab(tab, tabTrigger, event) { pauseLoopTabAutoplay(tab); event && event.preventDefault(); var index = Util.getIndexInArray(tab.triggers, tabTrigger); //no need to do anything if tab was already selected if(Util.hasClass(tab.triggers[index], tab.controlActiveClass)) return; for( var i = 0; i < tab.triggers.length; i++) { var bool = (i == index), exit = Util.hasClass(tab.triggers[i], tab.controlActiveClass); Util.toggleClass(tab.triggers[i], tab.controlActiveClass, bool); Util.toggleClass(tab.panels[i], tab.panelShowClass, bool); Util.toggleClass(tab.assets[i], tab.assetShowClass, bool); Util.toggleClass(tab.assets[i], tab.assetExitClass, exit); tab.triggers[i].setAttribute('aria-selected', bool); bool ? tab.triggers[i].setAttribute('tabindex', '0') : tab.triggers[i].setAttribute('tabindex', '-1'); resetVideo(tab, i, bool); // play/pause video if available // listen for the end of animation on asset element and remove exit class if(exit) {(function(i){ tab.assets[i].addEventListener('transitionend', function cb(event){ tab.assets[i].removeEventListener('transitionend', cb); Util.removeClass(tab.assets[i], tab.assetExitClass); }); })(i);} } // restart tab autoplay initLoopTabAutoplay(tab); }; function resetVideo(tab, i, bool) { if(tab.videos[i]) { if(bool) { tab.videos[i].play(); } else { tab.videos[i].pause(); tab.videos[i].currentTime = 0; } } }; LoopTab.defaults = { element : '', autoplay : true, autoplayInterval: 5000 }; //initialize the Tab objects var loopTabs = document.getElementsByClassName('js-loop-tabs'); if( loopTabs.length > 0 ) { var reducedMotion = Util.osHasReducedMotion(), cssVariableSupport = ('CSS' in window) && Util.cssSupports('color', 'var(--var)'); for( var i = 0; i < loopTabs.length; i++) { (function(i){ var autoplay = (loopTabs[i].getAttribute('data-autoplay') && loopTabs[i].getAttribute('data-autoplay') == 'off' || reducedMotion) ? false : true, autoplayInterval = (loopTabs[i].getAttribute('data-autoplay-interval')) ? loopTabs[i].getAttribute('data-autoplay-interval') : 5000; new LoopTab({element: loopTabs[i], autoplay : autoplay, autoplayInterval : autoplayInterval}); })(i); } } }()); (function() { var flexHeader = document.getElementsByClassName('js-f-header'); if(flexHeader.length > 0) { var menuTrigger = flexHeader[0].getElementsByClassName('js-anim-menu-btn')[0], firstFocusableElement = getMenuFirstFocusable(); // we'll use these to store the node that needs to receive focus when the mobile menu is closed var focusMenu = false; resetFlexHeaderOffset(); setAriaButtons(); menuTrigger.addEventListener('anim-menu-btn-clicked', function(event){ toggleMenuNavigation(event.detail); }); // listen for key events window.addEventListener('keyup', function(event){ // listen for esc key if( (event.keyCode && event.keyCode == 27) || (event.key && event.key.toLowerCase() == 'escape' )) { // close navigation on mobile if open if(menuTrigger.getAttribute('aria-expanded') == 'true' && isVisible(menuTrigger)) { focusMenu = menuTrigger; // move focus to menu trigger when menu is close menuTrigger.click(); } } // listen for tab key if( (event.keyCode && event.keyCode == 9) || (event.key && event.key.toLowerCase() == 'tab' )) { // close navigation on mobile if open when nav loses focus if(menuTrigger.getAttribute('aria-expanded') == 'true' && isVisible(menuTrigger) && !document.activeElement.closest('.js-f-header')) menuTrigger.click(); } }); // detect click on a dropdown control button - expand-on-mobile only flexHeader[0].addEventListener('click', function(event){ var btnLink = event.target.closest('.js-f-header__dropdown-control'); if(!btnLink) return; !btnLink.getAttribute('aria-expanded') ? btnLink.setAttribute('aria-expanded', 'true') : btnLink.removeAttribute('aria-expanded'); }); // detect mouseout from a dropdown control button - expand-on-mobile only flexHeader[0].addEventListener('mouseout', function(event){ var btnLink = event.target.closest('.js-f-header__dropdown-control'); if(!btnLink) return; // check layout type if(getLayout() == 'mobile') return; btnLink.removeAttribute('aria-expanded'); }); // close dropdown on focusout - expand-on-mobile only flexHeader[0].addEventListener('focusin', function(event){ var btnLink = event.target.closest('.js-f-header__dropdown-control'), dropdown = event.target.closest('.f-header__dropdown'); if(dropdown) return; if(btnLink && btnLink.hasAttribute('aria-expanded')) return; // check layout type if(getLayout() == 'mobile') return; var openDropdown = flexHeader[0].querySelector('.js-f-header__dropdown-control[aria-expanded="true"]'); if(openDropdown) openDropdown.removeAttribute('aria-expanded'); }); // listen for resize var resizingId = false; window.addEventListener('resize', function() { clearTimeout(resizingId); resizingId = setTimeout(doneResizing, 500); }); function getMenuFirstFocusable() { var focusableEle = flexHeader[0].getElementsByClassName('f-header__nav')[0].querySelectorAll('[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, [tabindex]:not([tabindex="-1"]), [contenteditable], audio[controls], video[controls], summary'), firstFocusable = false; for(var i = 0; i < focusableEle.length; i++) { if( focusableEle[i].offsetWidth || focusableEle[i].offsetHeight || focusableEle[i].getClientRects().length ) { firstFocusable = focusableEle[i]; break; } } return firstFocusable; }; function isVisible(element) { return (element.offsetWidth || element.offsetHeight || element.getClientRects().length); }; function doneResizing() { if( !isVisible(menuTrigger) && Util.hasClass(flexHeader[0], 'f-header--expanded')) { menuTrigger.click(); } resetFlexHeaderOffset(); }; function toggleMenuNavigation(bool) { // toggle menu visibility on small devices Util.toggleClass(document.getElementsByClassName('f-header__nav')[0], 'f-header__nav--is-visible', bool); Util.toggleClass(flexHeader[0], 'f-header--expanded', bool); menuTrigger.setAttribute('aria-expanded', bool); if(bool) firstFocusableElement.focus(); // move focus to first focusable element else if(focusMenu) { focusMenu.focus(); focusMenu = false; } }; function resetFlexHeaderOffset() { // on mobile -> update max height of the flexi header based on its offset value (e.g., if there's a fixed pre-header element) document.documentElement.style.setProperty('--f-header-offset', flexHeader[0].getBoundingClientRect().top+'px'); }; function setAriaButtons() { var btnDropdown = flexHeader[0].getElementsByClassName('js-f-header__dropdown-control'); for(var i = 0; i < btnDropdown.length; i++) { var id = 'f-header-dropdown-'+i, dropdown = btnDropdown[i].nextElementSibling; if(dropdown.hasAttribute('id')) { id = dropdown.getAttribute('id'); } else { dropdown.setAttribute('id', id); } btnDropdown[i].setAttribute('aria-controls', id); } }; function getLayout() { return getComputedStyle(flexHeader[0], ':before').getPropertyValue('content').replace(/\'|"/g, ''); }; } }()); // social sticky (function() { var StickyShareBar = function(element) { this.element = element; this.contentTarget = document.getElementsByClassName('js-sticky-sharebar-target'); this.contentTargetOut = document.getElementsByClassName('js-sticky-sharebar-target-out'); this.showClass = 'sticky-sharebar--on-target'; this.threshold = '50%'; // Share Bar will be revealed when .js-sticky-sharebar-target element reaches 50% of the viewport initShareBar(this); initTargetOut(this); }; function initShareBar(shareBar) { if(shareBar.contentTarget.length < 1) { shareBar.showSharebar = true; Util.addClass(shareBar.element, shareBar.showClass); return; } if(intersectionObserverSupported) { shareBar.showSharebar = false; initObserver(shareBar); // update anchor appearance on scroll } else { Util.addClass(shareBar.element, shareBar.showClass); } }; function initObserver(shareBar) { // target of Sharebar var observer = new IntersectionObserver( function(entries, observer) { shareBar.showSharebar = entries[0].isIntersecting; toggleSharebar(shareBar); }, {rootMargin: "0px 0px -"+shareBar.threshold+" 0px"} ); observer.observe(shareBar.contentTarget[0]); }; function initTargetOut(shareBar) { // target out of Sharebar shareBar.hideSharebar = false; if(shareBar.contentTargetOut.length < 1) { return; } var observer = new IntersectionObserver( function(entries, observer) { shareBar.hideSharebar = entries[0].isIntersecting; toggleSharebar(shareBar); } ); observer.observe(shareBar.contentTargetOut[0]); }; function toggleSharebar(shareBar) { Util.toggleClass(shareBar.element, shareBar.showClass, shareBar.showSharebar && !shareBar.hideSharebar); }; //initialize the StickyShareBar objects var stickyShareBar = document.getElementsByClassName('js-sticky-sharebar'), intersectionObserverSupported = ('IntersectionObserver' in window && 'IntersectionObserverEntry' in window && 'intersectionRatio' in window.IntersectionObserverEntry.prototype); if( stickyShareBar.length > 0 ) { for( var i = 0; i < stickyShareBar.length; i++) { (function(i){ new StickyShareBar(stickyShareBar[i]); })(i); } } }()); // video modal (function() { var ModalVideo = function(element) { this.element = element; this.modalContent = this.element.getElementsByClassName('js-modal-video__content')[0]; this.media = this.element.getElementsByClassName('js-modal-video__media')[0]; this.contentIsIframe = this.media.tagName.toLowerCase() == 'iframe'; this.modalIsOpen = false; this.initModalVideo(); }; ModalVideo.prototype.initModalVideo = function() { var self = this; // reveal modal content when iframe is ready this.addLoadListener(); // listen for the modal element to be open -> set new iframe src attribute this.element.addEventListener('modalIsOpen', function(event){ self.modalIsOpen = true; self.media.setAttribute('src', event.detail.closest('[aria-controls]').getAttribute('data-url')); }); // listen for the modal element to be close -> reset iframe and hide modal content this.element.addEventListener('modalIsClose', function(event){ self.modalIsOpen = false; Util.addClass(self.element, 'modal--is-loading'); self.media.setAttribute('src', ''); }); }; ModalVideo.prototype.addLoadListener = function() { var self = this; if(this.contentIsIframe) { this.media.onload = function () { self.revealContent(); }; } else { this.media.addEventListener('loadedmetadata', function(){ self.revealContent(); }); } }; ModalVideo.prototype.revealContent = function() { if( !this.modalIsOpen ) return; Util.removeClass(this.element, 'modal--is-loading'); if(this.element.getAttribute('data-modal-first-focus')) return; // user selected a specific element to focus this.contentIsIframe ? this.media.contentWindow.focus() : this.media.focus(); }; //initialize the ModalVideo objects var modalVideos = document.getElementsByClassName('js-modal-video__media'); if( modalVideos.length > 0 ) { for( var i = 0; i < modalVideos.length; i++) { (function(i){new ModalVideo(modalVideos[i].closest('.js-modal'));})(i); } } }()); (function() { var ImageZoom = function(element, index) { this.element = element; this.lightBoxId = 'img-zoom-lightbox--'+index; this.imgPreview = this.element.getElementsByClassName('js-image-zoom__preview')[0]; initImageZoomHtml(this); // init markup this.lightbox = document.getElementById(this.lightBoxId); this.imgEnlg = this.lightbox.getElementsByClassName('js-image-zoom__fw')[0]; this.input = this.element.getElementsByClassName('js-image-zoom__input')[0]; this.animate = this.element.getAttribute('data-morph') != 'off'; initImageZoomEvents(this); //init events }; function initImageZoomHtml(imageZoom) { // get zoomed image url var url = imageZoom.element.getAttribute('data-img'); if(!url) url = imageZoom.imgPreview.getAttribute('src'); var lightBox = document.createElement('div'); Util.setAttributes(lightBox, {class: 'image-zoom__lightbox js-image-zoom__lightbox', id: imageZoom.lightBoxId, 'aria-hidden': 'true'}); lightBox.innerHTML = ''; document.body.appendChild(lightBox); var keyboardInput = ''; imageZoom.element.insertAdjacentHTML('afterbegin', keyboardInput); }; function initImageZoomEvents(imageZoom) { // toggle lightbox on click imageZoom.imgPreview.addEventListener('click', function(event){ toggleFullWidth(imageZoom, true); imageZoom.input.checked = true; }); imageZoom.lightbox.addEventListener('click', function(event){ toggleFullWidth(imageZoom, false); imageZoom.input.checked = false; }); // detect swipe down to close lightbox new SwipeContent(imageZoom.lightbox); imageZoom.lightbox.addEventListener('swipeDown', function(event){ toggleFullWidth(imageZoom, false); imageZoom.input.checked = false; }); // keyboard accessibility imageZoom.input.addEventListener('change', function(event){ toggleFullWidth(imageZoom, imageZoom.input.checked); }); imageZoom.input.addEventListener('keydown', function(event){ if( (event.keyCode && event.keyCode == 13) || (event.key && event.key.toLowerCase() == 'enter') ) { imageZoom.input.checked = !imageZoom.input.checked; toggleFullWidth(imageZoom, imageZoom.input.checked); } }); }; function toggleFullWidth(imageZoom, bool) { if(animationSupported && imageZoom.animate) { // start expanding animation window.requestAnimationFrame(function(){ animateZoomImage(imageZoom, bool); }); } else { // show lightbox without animation Util.toggleClass(imageZoom.lightbox, 'image-zoom__lightbox--is-visible', bool); } }; function animateZoomImage(imageZoom, bool) { // get img preview position and dimension for the morphing effect var rect = imageZoom.imgPreview.getBoundingClientRect(), finalWidth = imageZoom.lightbox.getBoundingClientRect().width; var init = (bool) ? [rect.top, rect.left, rect.width] : [0, 0, finalWidth], final = (bool) ? [-rect.top, -rect.left, parseFloat(finalWidth/rect.width)] : [rect.top + imageZoom.lightbox.scrollTop, rect.left, parseFloat(rect.width/finalWidth)]; if(bool) { imageZoom.imgEnlg.setAttribute('style', 'top: '+init[0]+'px; left:'+init[1]+'px; width:'+init[2]+'px;'); } // show modal Util.removeClass(imageZoom.lightbox, 'image-zoom__lightbox--no-transition'); Util.addClass(imageZoom.lightbox, 'image-zoom__lightbox--is-visible'); imageZoom.imgEnlg.addEventListener('transitionend', function cb(event){ // reset elements once animation is over if(!bool) Util.removeClass(imageZoom.lightbox, 'image-zoom__lightbox--is-visible'); Util.addClass(imageZoom.lightbox, 'image-zoom__lightbox--no-transition'); imageZoom.imgEnlg.removeAttribute('style'); imageZoom.imgEnlg.removeEventListener('transitionend', cb); }); // animate image and bg imageZoom.imgEnlg.style.transform = 'translateX('+final[1]+'px) translateY('+final[0]+'px) scale('+final[2]+')'; Util.toggleClass(imageZoom.lightbox, 'image-zoom__lightbox--animate-bg', bool); }; // init ImageZoom object var imageZoom = document.getElementsByClassName('js-image-zoom'), animationSupported = window.requestAnimationFrame && !Util.osHasReducedMotion(); if( imageZoom.length > 0 ) { var imageZoomArray = []; for( var i = 0; i < imageZoom.length; i++) { imageZoomArray.push(new ImageZoom(imageZoom[i], i)); } // close Zoom Image lightbox on Esc window.addEventListener('keydown', function(event){ if((event.keyCode && event.keyCode == 27) || (event.key && event.key.toLowerCase() == 'esc')) { for( var i = 0; i < imageZoomArray.length; i++) { imageZoomArray[i].input.checked = false; if(Util.hasClass(imageZoomArray[i].lightbox, 'image-zoom__lightbox--is-visible')) toggleFullWidth(imageZoomArray[i], false); } } }); } }()); (function() { var hidingNav = document.getElementsByClassName('js-hide-nav'); if(hidingNav.length > 0 && window.requestAnimationFrame) { var mainNav = Array.prototype.filter.call(hidingNav, function(element) { return Util.hasClass(element, 'js-hide-nav--main'); }), subNav = Array.prototype.filter.call(hidingNav, function(element) { return Util.hasClass(element, 'js-hide-nav--sub'); }); var scrolling = false, previousTop = window.scrollY, currentTop = window.scrollY, scrollDelta = 10, scrollOffset = 350, // scrollY needs to be bigger than scrollOffset to hide navigation headerHeight = 0; var navIsFixed = false; // check if main navigation is fixed if(mainNav.length > 0 && Util.hasClass(mainNav[0], 'hide-nav--fixed')) navIsFixed = true; // store button that triggers navigation on mobile var triggerMobile = getTriggerMobileMenu(); var prevElement = createPrevElement(); var mainNavTop = 0; // list of classes the hide-nav has when it is expanded -> do not hide if it has those classes var navOpenClasses = hidingNav[0].getAttribute('data-nav-target-class'), navOpenArrayClasses = []; if(navOpenClasses) navOpenArrayClasses = navOpenClasses.split(' '); getMainNavTop(); if(mainNavTop > 0) { scrollOffset = scrollOffset + mainNavTop; } // init navigation and listen to window scroll event getHeaderHeight(); initSecondaryNav(); // initFixedNav(); resetHideNav(); window.addEventListener('scroll', function(event){ if(scrolling) return; scrolling = true; window.requestAnimationFrame(resetHideNav); }); window.addEventListener('resize', function(event){ if(scrolling) return; scrolling = true; window.requestAnimationFrame(function(){ if(headerHeight > 0) { getMainNavTop(); getHeaderHeight(); initSecondaryNav(); // initFixedNav(); } // reset both navigation hideNavScrollUp(); scrolling = false; }); }); function getHeaderHeight() { headerHeight = mainNav[0].offsetHeight; }; function initSecondaryNav() { // if there's a secondary nav, set its top equal to the header height if(subNav.length < 1 || mainNav.length < 1) return; subNav[0].style.top = (headerHeight - 1)+'px'; }; // function initFixedNav() { // if(!navIsFixed || mainNav.length < 1) return; // mainNav[0].style.marginBottom = '-'+headerHeight+'px'; // }; function resetHideNav() { // check if navs need to be hidden/revealed currentTop = window.scrollY; if(currentTop - previousTop > scrollDelta && currentTop > scrollOffset) { hideNavScrollDown(); } else if( previousTop - currentTop > scrollDelta || (previousTop - currentTop > 0 && currentTop < scrollOffset) ) { hideNavScrollUp(); } else if( previousTop - currentTop > 0 && subNav.length > 0 && subNav[0].getBoundingClientRect().top > 0) { setTranslate(subNav[0], '0%'); } // if primary nav is fixed -> toggle bg class if(navIsFixed) { var scrollTop = window.scrollY || window.pageYOffset; Util.toggleClass(mainNav[0], 'hide-nav--has-bg', (scrollTop > headerHeight + mainNavTop)); } previousTop = currentTop; scrolling = false; }; function hideNavScrollDown() { // if there's a secondary nav -> it has to reach the top before hiding nav if( subNav.length > 0 && subNav[0].getBoundingClientRect().top > headerHeight) return; // on mobile -> hide navigation only if dropdown is not open if(triggerMobile && triggerMobile.getAttribute('aria-expanded') == "true") return; // check if main nav has one of the following classes if( mainNav.length > 0 && (!navOpenClasses || !checkNavExpanded())) { setTranslate(mainNav[0], '-100%'); mainNav[0].addEventListener('transitionend', addOffCanvasClass); } if( subNav.length > 0 ) setTranslate(subNav[0], '-'+headerHeight+'px'); }; function hideNavScrollUp() { if( mainNav.length > 0 ) {setTranslate(mainNav[0], '0%'); Util.removeClass(mainNav[0], 'hide-nav--off-canvas');mainNav[0].removeEventListener('transitionend', addOffCanvasClass);} if( subNav.length > 0 ) setTranslate(subNav[0], '0%'); }; function addOffCanvasClass() { mainNav[0].removeEventListener('transitionend', addOffCanvasClass); Util.addClass(mainNav[0], 'hide-nav--off-canvas'); }; function setTranslate(element, val) { element.style.transform = 'translateY('+val+')'; }; function getTriggerMobileMenu() { // store trigger that toggle mobile navigation dropdown var triggerMobileClass = hidingNav[0].getAttribute('data-mobile-trigger'); if(!triggerMobileClass) return false; if(triggerMobileClass.indexOf('#') == 0) { // get trigger by ID var trigger = document.getElementById(triggerMobileClass.replace('#', '')); if(trigger) return trigger; } else { // get trigger by class name var trigger = hidingNav[0].getElementsByClassName(triggerMobileClass); if(trigger.length > 0) return trigger[0]; } return false; }; function createPrevElement() { // create element to be inserted right before the mainNav to get its top value if( mainNav.length < 1) return false; var newElement = document.createElement("div"); newElement.setAttribute('aria-hidden', 'true'); mainNav[0].parentElement.insertBefore(newElement, mainNav[0]); var prevElement = mainNav[0].previousElementSibling; prevElement.style.opacity = '0'; return prevElement; }; function getMainNavTop() { if(!prevElement) return; mainNavTop = prevElement.getBoundingClientRect().top + window.scrollY; }; function checkNavExpanded() { var navIsOpen = false; for(var i = 0; i < navOpenArrayClasses.length; i++){ if(Util.hasClass(mainNav[0], navOpenArrayClasses[i].trim())) { navIsOpen = true; break; } } return navIsOpen; }; } else { // if window requestAnimationFrame is not supported -> add bg class to fixed header var mainNav = document.getElementsByClassName('js-hide-nav--main'); if(mainNav.length < 1) return; if(Util.hasClass(mainNav[0], 'hide-nav--fixed')) Util.addClass(mainNav[0], 'hide-nav--has-bg'); } }()); $("button.s-panels__nav-control").click(function () { if ($("button.s-panels__nav-control").attr('class').split(' ').length > 3) { // console.log("true"); $(this).siblings(".notification").addClass("hide-notification"); } else { // console.log("false"); $(this).siblings(".notification").removeClass("hide-notification"); } }); $(".s-panels__project-control").click(function () { if ($("button.s-panels__nav-control").attr('class').split(' ').length > 2) { // console.log("true"); $("button.s-panels__nav-control").siblings(".notification").addClass("hide-notification"); } else { // console.log("false"); $("button.s-panels__nav-control").siblings(".notification").removeClass("hide-notification"); } }); setTimeout(function () { $(".js-f-header").removeClass('animate__animated', 'animate__slideInDown', 'animate__delay-1s'); }, 2000); $(function () { const pagelogo = ''; const pagelogo_rev = ''; const subpage = "body.sub-page header" const menu_btn = "button.anim-menu-btn" var logo_change = function () { $(document).scroll(function () { if ($(subpage).hasClass("hide-nav--has-bg")) { $(subpage).find(".logo-white").replaceWith(pagelogo); } else { $(subpage).find(".logo-black").replaceWith(pagelogo_rev); }; }); } logo_change(); $(menu_btn).click(function () { if ($("header").hasClass("f-header--expanded") || $("header").hasClass("hide-nav--off-canvas") || $("header").hasClass("hide-nav--has-bg")) { $(".logo-white").replaceWith(pagelogo); } else { $(subpage).find(".logo-black").replaceWith(pagelogo_rev); }; $(document).scroll(function () { if ($("header").hasClass("f-header--expanded")) { $(subpage).find(".logo-white").replaceWith(pagelogo); }; }); }); if ($("header").hasClass("hide-nav--has-bg")) { $(".logo-white").replaceWith(pagelogo); }; }); // colour change on scroll $(window).scroll(function () { // selectors var $window = $(window), $body = $('body'), $panel = $('.panel'); var scroll = $window.scrollTop() + ($window.height() / 3); $panel.each(function () { var $this = $(this); if ($this.position().top <= scroll && $this.position().top + $this.height() > scroll) { $body.removeClass(function (index, css) { return (css.match(/(^|\s)bg-color-\S+/g) || []).join(' '); }); $body.addClass('bg-color-' + $(this).data('color')); } }); }).scroll(); // loading screen window.addEventListener('load', function () { var loadingScreen = document.getElementById('loading-screen'); loadingScreen.classList.add('loading-screen-visible'); // Wait for the transition to complete before hiding the loading screen setTimeout(function () { loadingScreen.style.display = 'none'; }, 500); }); // lazyload document.addEventListener("DOMContentLoaded", function () { var images = document.querySelectorAll("img"); var videos = document.querySelectorAll("video"); var elements = document.querySelectorAll(".lazy-bg"); var options = { root: null, rootMargin: "0px", threshold: 0.1 }; var observer = new IntersectionObserver(function (entries, observer) { entries.forEach(function (entry) { if (entry.isIntersecting) { var element = entry.target; if (element.tagName === "IMG") { // Lazy load image // Apply lazy loading to the element (e.g., update the src attribute) // ... } else if (element.tagName === "VIDEO") { // Lazy load video // Apply lazy loading to the element (e.g., load the video source) // ... } else if (element.classList.contains("lazy-bg")) { // Lazy load background image var backgroundImage = getComputedStyle(element).getPropertyValue("background-image"); var imageUrl = backgroundImage.replace(/url\(['"]?(.*?)['"]?\)/i, "$1"); element.style.backgroundImage = "url('" + imageUrl + "')"; } observer.unobserve(element); } }); }, options); images.forEach(function (image) { observer.observe(image); }); videos.forEach(function (video) { observer.observe(video); }); elements.forEach(function (element) { observer.observe(element); }); }); // animate on timing const elements = document.querySelectorAll('.ani[data-repeat-animate]'); const observer = new IntersectionObserver((entries) => { entries.forEach((entry) => { const animation = entry.target.getAttribute('data-animation'); if (window.innerWidth >= 1200) { if (entry.isIntersecting) { entry.target.style.visibility = 'visible'; // Show the element entry.target.classList.add('animate__animated', animation); } else { entry.target.style.visibility = 'hidden'; // Hide the element entry.target.classList.remove('animate__animated', animation); } } else { entry.target.style.visibility = 'visible'; // Show the element entry.target.classList.remove('animate__animated', animation); } }); }, { threshold: 0.05 }); elements.forEach((element) => { element.style.visibility = 'hidden'; // Initially hide the element observer.observe(element); }); // floating dots const dots = document.querySelectorAll('.dot'); const sections = document.querySelectorAll('.scroll-section'); dots.forEach((dot, index) => { dot.addEventListener('click', () => { scrollToSection(index); }); }); window.addEventListener('scroll', () => { const currentSectionIndex = getCurrentSectionIndex(); dots.forEach((dot, index) => { if (index === currentSectionIndex) { dot.classList.add('active'); } else { dot.classList.remove('active'); } }); }); function scrollToSection(index) { const section = sections[index]; section.scrollIntoView({ behavior: 'smooth' }); } function getCurrentSectionIndex() { let currentIndex = 0; let maxSectionBottom = 0; sections.forEach((section, index) => { const rect = section.getBoundingClientRect(); if (rect.top < window.innerHeight && rect.bottom > maxSectionBottom) { maxSectionBottom = rect.bottom; currentIndex = index; } }); return currentIndex; } // Trigger the scroll event on page load to highlight the initial section window.dispatchEvent(new Event('scroll')); // parallax bg window.addEventListener('scroll', function () { var scrolled = window.pageYOffset; var layers = document.getElementsByClassName('parallax-background'); for (var i = 0; i < layers.length; i++) { var layer = layers[i]; var speed = 0.3; // Adjust the parallax speed as needed var yPos = -(scrolled * speed); layer.style.transform = 'translate3d(0px, ' + yPos + 'px, 0px)'; } }); // remove anchor tag in address bar // Get all the anchor tags const anchorTags = document.querySelectorAll('a'); // Add click event listener to each anchor tag anchorTags.forEach((anchor) => { anchor.addEventListener('click', (event) => { // Get the href value of the anchor tag const href = anchor.getAttribute('href'); // Check if the href starts with a "#" indicating it targets an ID if (href && href.startsWith('#')) { // Prevent the default behavior of the link event.preventDefault(); // Get the target element's ID from the href attribute const targetId = href.substring(1); // Get the target element const targetElement = document.getElementById(targetId); // Scroll to the target element using smooth behavior targetElement.scrollIntoView({ behavior: 'smooth' }); } }); }); // animated hero image // if (window.location.pathname === '/' || window.location.pathname === '/preview13/') { // const html = document.documentElement; // const canvas = document.getElementById("hero-cloncurry"); // const context = canvas.getContext("2d"); // const frameCount = 220; // const currentFrame = index => ( // `assets/img/v-sequence/cloncurry_${index.toString().padStart(3, '0')}.jpg` // ) // const preloadImages = () => { // for (let i = 1; i < frameCount; i++) { // const img = new Image(); // img.src = currentFrame(i); // } // }; // const img = new Image() // img.src = currentFrame(1); // canvas.width=1920; // canvas.height=1080; // img.onload=function(){ // context.drawImage(img, 0, 0); // } // const updateImage = index => { // img.src = currentFrame(index); // context.drawImage(img, 0, 0); // } // window.addEventListener('scroll', () => { // const scrollTop = html.scrollTop; // const maxScrollTop = html.scrollHeight - window.innerHeight; // const scrollFraction = scrollTop / maxScrollTop; // const frameIndex = Math.min( // frameCount - 1, // Math.ceil(scrollFraction * frameCount) // ); // requestAnimationFrame(() => updateImage(frameIndex + 1)) // }); // preloadImages() /* Homepage Popup */ // if (window.location.pathname === '/' || window.location.pathname === '/preview13/') { // document.addEventListener('DOMContentLoaded', function () { // var modal = document.getElementsByClassName('home-popup'); // function openModal(element) { // var event = new CustomEvent('openModal'); // element.dispatchEvent(event); // } // setTimeout(function () { // openModal(modal[0]); // }, 2000); // }); // }