This is a subpage

This subpage can be used as a base for adding more pages. You can duplicate this page in your page manager to maintain this basic structure of header-reference, footer-reference and this editable section. Referenced elements are copies of their original element and cannot be edited. But they change according to their original element, so you only have to make changes once and they apply to all related references.

/* JS for preset "Menu V2" */ (function() { $(function() { $('.menu-wrapper').each(function() { initMenu($(this)) }); }); // Make :active pseudo classes work on iOS document.addEventListener("touchstart", function() {}, false); var initMenu = function($menuWrapper) { var $body = $('body'); var $menu = $('.ed-menu', $menuWrapper); var $menuLinks = $('a', $menu); var $menuTrigger = $('.menu-trigger', $menuWrapper); var $banner = $('.banner').first(); var menuWrapperHeight = $menuWrapper.outerHeight(); var bannerHeight = $banner.length ? $banner.outerHeight() : 0; var smoothScrollOffset = 20; toggleClassOnClick($body.add($menu), $menuTrigger, null, 'open open-menu'); // Keep open on $menu for backward compatibility activateSmoothScroll($menuLinks.add($('.scroll a')), smoothScrollOffset); addClassOnVisibleLinkTargets($menuLinks, 'active', 2 / 3); handleSticky($menuWrapper, 'sticky', $banner); }; /** * Observe element's height changes and reload the initMenu() function * * @param {HTMLElement} elm Element to observe * @param {function} callback to call when elmement's height changed */ var observeHeightChange = function(elm, callback) { if (!('ResizeObserver' in window) || elm == null) return; var ro = new ResizeObserver(callback); ro.observe(elm); } /** * Toggles class on a target when a trigger is clicked * * @param {jQuery} $target The target to apply the CSS class to * @param {jQuery} $trigger The Trigger * @param {jQuery} $closeTrigger Optional close trigger * @param {string} cssClass CSS Class to toggle on the target */ var toggleClassOnClick = function($target, $trigger, $closeTrigger, cssClass) { // Reset in case class "open" was saved accidentally $target.removeClass(cssClass); $trigger.removeClass(cssClass); // Click on trigger toggles class "open" $trigger.off('.toggle').on('click.toggle', function() { $(this).toggleClass(cssClass); $target.toggleClass(cssClass); }); // Close target when link inside is clicked $target.find('a').click(function() { $target.removeClass(cssClass); $trigger.removeClass(cssClass); }); if (!$closeTrigger || !$closeTrigger.length) { return; } $closeTrigger.click(function() { $target.removeClass(cssClass); $trigger.removeClass(cssClass); }); }; /** * Smooth scroll to link targets * * @param {jQuery} $scrollLinks The links * @param {jQuery} scrollOffset Offset to subtract from the scroll target position (e.g. for fixed positioned elements like a menu) */ var activateSmoothScroll = function($scrollLinks, scrollOffset) { if (typeof scrollOffset === 'undefined') { scrollOffset = 0; } var determineTarget = function($trigger, hash) { if (hash == '#!next') { return $trigger.closest('.ed-element').next(); } return $(hash); } $scrollLinks.click(function(e) { var $target = determineTarget($(this), this.hash); if (!$target.length) return; e.preventDefault(); viewport.scrollTo($target, 'top', 500, 0); }); }; /** * We are using the fill property on an element to pass user's choices from CSS to JavaScript * * @param {jQuery} $element */ var getStickyMode = function($element) { var fillValue = getComputedStyle($element[0]).fill; return fillValue === 'rgb(255, 0, 0)' ? 'sticky_banner' : fillValue === 'rgb(0, 255, 0)' ? 'sticky_menu' : fillValue === 'rgb(0, 0, 255)' ? 'sticky_instant' : fillValue === 'rgb(255, 255, 255)' ? 'sticky_reverse' : 'sticky_none'; }; /** * Adds a class to an element when not currently visible * * @param {jQuery} $element The element to handle stickyness for * @param {string} cssClass The actual CSS class to be applied to the element when it's above a certain scroll position * @param {jQuery} $banner A banner to reference the scroll position to */ var handleSticky = function($element, cssClass, $banner) { var triggerPos = 0, offset = 0; var menuWrapperHeight = $element.outerHeight(); var mode; var prevScroll = 0; $element.removeClass(cssClass); var toggleSpacer = function(toggle) { document.body.style.setProperty('--spacer-height', toggle ? menuWrapperHeight + 'px' : ''); }; var handleScroll = function() { if (!$element.length || mode === 'sticky_none') return; var isReverse = mode === 'sticky_reverse', curScroll = viewport.getScrollTop(); if (triggerPos <= curScroll && (!isReverse || prevScroll > curScroll)) { $element.addClass(cssClass); toggleSpacer(true); } else { $element.removeClass(cssClass); toggleSpacer(false); } prevScroll = curScroll; }; var updateOffset = function() { mode = getStickyMode($element); menuWrapperHeight = $element.outerHeight(); if (!$element.hasClass(cssClass)) { offset = $element.offset().top; } if (mode === 'sticky_banner' && !$banner.length) { mode = 'sticky_menu'; } if (mode === 'sticky_banner') { triggerPos = $banner.offset().top + ($banner.length ? $banner.outerHeight() : $element.outerHeight()); } if (mode === 'sticky_menu' || mode === 'sticky_reverse') { triggerPos = offset + $element.outerHeight(); } if (mode === 'sticky_instant') { triggerPos = offset; } handleScroll(); } viewport.observe('resize', updateOffset); viewport.observe('animation.end', updateOffset); observeHeightChange($element[0], updateOffset); updateOffset(); viewport.observe('scroll', handleScroll); handleScroll(); }; /** * Adds a class to links whose target is currently inside the viewport * * @param {jQuery} $links Link(s) to be observed * @param {string} cssClass CSS Class to be applied * @param {float} sectionViewportRatio Ratio by which the target should be within the viewport */ var addClassOnVisibleLinkTargets = function($links, cssClass, sectionViewportRatio) { if (typeof sectionViewportRatio === 'undefined') { sectionViewportRatio = 1 / 2; } var menuTargets = []; var activeLink = $links.filter('.active:not(.wv-link-elm)').eq(0); var links = $links.filter(function() { var $target = $(this.hash); if (!$target.length) { return false; } // Cache offset position to improve performance (update on resize) var updateOffset = function() { $target.data('offset', $target.offset().top); }; viewport.observe('resize', updateOffset); viewport.observe('animation.end', updateOffset); updateOffset(); menuTargets.push($target); return true; }); // No hash links found, so don't handle it at all if (!links.length) { return; } var checkVisibility = function() { $links.removeClass('active'); // Check section position reversely for (var i = menuTargets.length - 1; i >= 0; i--) { var desiredScrollPosition = menuTargets[i].data('offset') - viewport.getHeight() * (1 - sectionViewportRatio); if (viewport.getScrollTop() >= desiredScrollPosition && menuTargets[i][0].offsetParent !== null) { links.eq(i).addClass(cssClass); return; } } // Fallback to originally active item activeLink.addClass(cssClass); }; viewport.observe('scroll', checkVisibility); checkVisibility(); }; })(); /* End JS for preset "Menu V2" */ /* JS for preset QUOTES "Content Slider" */ $(function() { if (document.body.classList.contains('edit')) { return; } viewport.promise('api.slick.ready', function() { viewport.jQuery('.preset-content-slider-quotes > .inner').slick({ autoplay: true, arrows: true, prevArrow: '', nextArrow: '', speed: 600, autoplaySpeed: 4000, dots: true, adaptiveHeight: true, fade: false }); }).requireSlick(); }); /* JS for preset TEACHER "Content Slider" */ $(function() { if (document.body.classList.contains('edit')) { return; } viewport.promise('api.slick.ready', function() { viewport.jQuery('.ed-element.preset-content-slider-teacher > .inner').slick({ autoplay: true, arrows: true, prevArrow: '', nextArrow: '', speed: 600, autoplaySpeed: 4000, dots: false, adaptiveHeight: true, fade: false, slidesToShow: 3, slidesToScroll: 1, responsive: [{ breakpoint: 976, settings: { slidesToShow: 2 } }, { breakpoint: 768, settings: { slidesToShow: 1 } }] }); }).requireSlick(); }); /* JS for preset "Countdown" */ (function() { var isIE11 = !!window.MSInputMethodContext && !!document.documentMode, isSafari = navigator.userAgent.toLowerCase().indexOf('safari') > -1 && navigator.userAgent.toLowerCase().indexOf('chrome') === -1; var slice = Array.prototype.slice; var ready = function(callback) { var fn = function() { if (document.body.classList.contains('edit')) { return; } callback(); }; if (window.readyState !== 'loading') { fn(); return; } document.addEventListener('DOMContentLoaded', fn); } var countdown = function(date, tick) { var now = new Date().getTime(), running = false, days = 0, hours = 0, minutes = 0, seconds, interval; var updateCounter = function() { if (!running) return; now = new Date().getTime(); seconds = Math.round((date - now) / 1000); if (seconds > 86400) { days = Math.floor(seconds / 86400); seconds %= 86400; } if (seconds > 3600) { hours = Math.floor(seconds / 3600); seconds %= 3600; } if (seconds > 60) { minutes = Math.floor(seconds / 60); seconds %= 60; } tick(days, hours, minutes, seconds); }; if (isIE11 || isSafari) { date = date.replace(/\s/, 'T'); } date = new Date(date).getTime(); if (now >= date) { throw new Error('Date cannot be in the past.'); } tick = tick || (function() {}); return { start: function() { interval = window.setInterval(updateCounter, 1000); running = true; updateCounter(); }, stop: function() { if (interval) window.clearInterval(interval); interval = undefined; running = false; } } }; var writeCountdown = function(element, days, hours, minutes, seconds) { var daysElm = element.querySelector(".countdown-days"), hoursElm = element.querySelector('.countdown-hours'), minutesElm = element.querySelector('.countdown-minutes'), secondsElm = element.querySelector('.countdown-seconds'); if (daysElm) daysElm.innerHTML = days; if (hoursElm) hoursElm.innerHTML = hours; if (minutesElm) minutesElm.innerHTML = minutes; if (secondsElm) secondsElm.innerHTML = seconds; } var buildCountdown = function(e) { var instances = slice.call(document.querySelectorAll('.countdown-instance')), len = instances.length, i = 0, element; for (; i < len; i++) { element = instances[i]; var date = element.querySelector('.countdown-data p').innerHTML; element.countdown = countdown(date, function(days, hours, minutes, seconds) { writeCountdown( element, parseInt(days), ("0" + parseInt(hours)).slice(-2), ("0" + parseInt(minutes)).slice(-2), ("0" + parseInt(seconds)).slice(-2) ); }); element.countdown.start(); } }; var destroyCountdown = function(e) { var instances = slice.call(document.querySelectorAll('.countdown-instance')), len = instances.length, i = 0, element; for (; i < len; i++) { element = instances[i]; writeCountdown(element, "0", "0", "0", "0"); element.countdown.stop(); } } var preview = false; var listener = function() { if (!preview && document.body.classList.contains('preview')) { console.log("entering preview") buildCountdown(); preview = true; } else if (preview && !document.body.classList.contains('preview')) { console.log("edit again"); destroyCountdown(); preview = false; } requestAnimationFrame(listener); }; requestAnimationFrame(listener); ready(function() { buildCountdown(); }); })(); /* End JS for preset "Countdown" */ /* Show Captcha */ $(function() { if (!$('body').is('.edit')) { $('.preset-contact-form-sign-up .ed-form-container').each(function() { $(this).click(function() { $('.ed-form-captcha', this).addClass('show'); }); }); } });