/* Request ID: 6b2761eaa22c76193dc12a65faf80699 (05/19/2024 2:34pm) (minifier disabled) (tZFLbsMwDAWvkl0WKc0U3dSnCfRhbCa05IiUhdw+Qs9QbQlyBnwPD1ewtYaeJLNBpGMSPqitTmhKZLhXLxxuq22CN05LociUTNFW2khxkeydoIbCe59ewZOrxvcqYM4L6fTQrxP+v+fxqlTeQE77NnxPP6NE+uQdhNNz2Ctjg+ptyBj2LyxxL2PYM9xrCsY5DQpmnkEaqHAkXXPrQF+XMarQ71J0BUJVy9uf5Hxxl/MH) */ // ============================================================= // // Beautiful Data Tables // ------------------------------------------------------------ // Description: provides a beautiful layout for tables on mobile // Author: @nroyall @whitewhale // Docs: https://github.com/whitewhale/LWSkipLinks // Licensed under the MIT license // // USAGE: // Add headings to the top row or left column of the table. // On desktop, the headers receive special styling. // On mobile, each header appears above the appropriate table cell. // // ============================================================= ;(function($) { var initBeautifulTables = function() { var $table = $('table').addClass('data'); $table.each( function() { var $this = $(this); // find headers in or var $headers = $this.find('thead').length ? $this.find('thead').find('th, td') : $this.find('tbody').find('tr:first-child').find('th, td'); if ( $headers.length ) { // add class to tables with headers or bold text in the first table row if ( !$this.find('thead').length && $this.find('tbody').find('tr:first-child').has('th, h1, h2, h3, h4, h5, h6, strong').length ) { $this.addClass('has-header'); } // create table headers array for all header columns, even if empty var headers = $headers.map(function() { var header = $.trim($(this).text()); if ( header.length ) { header +=':'; // appeand colon non-empty headers } return header; }).get(); // add header data attribute each table cell for display on mobile $this.find('tbody').find('tr').children().attr('data-th', function() { var col = $(this).parent().children().index($(this)); return headers[col]; }); // if left column doesn't have a header, these become headers on mobile $this.find('tbody').find('tr').children(':first-child').filter(function(){ return !$(this).first().attr('data-th'); }).addClass('mobile-header'); } }); }; // Run on document ready initBeautifulTables(); // Run after LiveWhale page is edited and saved $('body').bind('stopEdit.lw', function(e) { initBeautifulTables(); }); })(livewhale.jQuery); /* * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/ * * Uses the built in easing capabilities added In jQuery 1.1 * to offer multiple easing options * * TERMS OF USE - jQuery Easing * * Open source under the BSD License. * * Copyright © 2008 George McGinley Smith * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * Neither the name of the author nor the names of contributors may be used to endorse * or promote products derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * */ // t: current time, b: begInnIng value, c: change In value, d: duration jQuery.easing['jswing'] = jQuery.easing['swing']; jQuery.extend( jQuery.easing, { def: 'easeOutQuad', swing: function (x, t, b, c, d) { //alert(jQuery.easing.default); return jQuery.easing[jQuery.easing.def](x, t, b, c, d); }, easeInQuad: function (x, t, b, c, d) { return c*(t/=d)*t + b; }, easeOutQuad: function (x, t, b, c, d) { return -c *(t/=d)*(t-2) + b; }, easeInOutQuad: function (x, t, b, c, d) { if ((t/=d/2) < 1) return c/2*t*t + b; return -c/2 * ((--t)*(t-2) - 1) + b; }, easeInCubic: function (x, t, b, c, d) { return c*(t/=d)*t*t + b; }, easeOutCubic: function (x, t, b, c, d) { return c*((t=t/d-1)*t*t + 1) + b; }, easeInOutCubic: function (x, t, b, c, d) { if ((t/=d/2) < 1) return c/2*t*t*t + b; return c/2*((t-=2)*t*t + 2) + b; }, easeInQuart: function (x, t, b, c, d) { return c*(t/=d)*t*t*t + b; }, easeOutQuart: function (x, t, b, c, d) { return -c * ((t=t/d-1)*t*t*t - 1) + b; }, easeInOutQuart: function (x, t, b, c, d) { if ((t/=d/2) < 1) return c/2*t*t*t*t + b; return -c/2 * ((t-=2)*t*t*t - 2) + b; }, easeInQuint: function (x, t, b, c, d) { return c*(t/=d)*t*t*t*t + b; }, easeOutQuint: function (x, t, b, c, d) { return c*((t=t/d-1)*t*t*t*t + 1) + b; }, easeInOutQuint: function (x, t, b, c, d) { if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b; return c/2*((t-=2)*t*t*t*t + 2) + b; }, easeInSine: function (x, t, b, c, d) { return -c * Math.cos(t/d * (Math.PI/2)) + c + b; }, easeOutSine: function (x, t, b, c, d) { return c * Math.sin(t/d * (Math.PI/2)) + b; }, easeInOutSine: function (x, t, b, c, d) { return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b; }, easeInExpo: function (x, t, b, c, d) { return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b; }, easeOutExpo: function (x, t, b, c, d) { return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b; }, easeInOutExpo: function (x, t, b, c, d) { if (t==0) return b; if (t==d) return b+c; if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b; return c/2 * (-Math.pow(2, -10 * --t) + 2) + b; }, easeInCirc: function (x, t, b, c, d) { return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b; }, easeOutCirc: function (x, t, b, c, d) { return c * Math.sqrt(1 - (t=t/d-1)*t) + b; }, easeInOutCirc: function (x, t, b, c, d) { if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b; return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b; }, easeInElastic: function (x, t, b, c, d) { var s=1.70158;var p=0;var a=c; if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3; if (a < Math.abs(c)) { a=c; var s=p/4; } else var s = p/(2*Math.PI) * Math.asin (c/a); return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; }, easeOutElastic: function (x, t, b, c, d) { var s=1.70158;var p=0;var a=c; if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3; if (a < Math.abs(c)) { a=c; var s=p/4; } else var s = p/(2*Math.PI) * Math.asin (c/a); return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b; }, easeInOutElastic: function (x, t, b, c, d) { var s=1.70158;var p=0;var a=c; if (t==0) return b; if ((t/=d/2)==2) return b+c; if (!p) p=d*(.3*1.5); if (a < Math.abs(c)) { a=c; var s=p/4; } else var s = p/(2*Math.PI) * Math.asin (c/a); if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b; }, easeInBack: function (x, t, b, c, d, s) { if (s == undefined) s = 1.70158; return c*(t/=d)*t*((s+1)*t - s) + b; }, easeOutBack: function (x, t, b, c, d, s) { if (s == undefined) s = 1.70158; return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b; }, easeInOutBack: function (x, t, b, c, d, s) { if (s == undefined) s = 1.70158; if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b; return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b; }, easeInBounce: function (x, t, b, c, d) { return c - jQuery.easing.easeOutBounce (x, d-t, 0, c, d) + b; }, easeOutBounce: function (x, t, b, c, d) { if ((t/=d) < (1/2.75)) { return c*(7.5625*t*t) + b; } else if (t < (2/2.75)) { return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b; } else if (t < (2.5/2.75)) { return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b; } else { return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b; } }, easeInOutBounce: function (x, t, b, c, d) { if (t < d/2) return jQuery.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b; return jQuery.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b; } }); /* * * TERMS OF USE - EASING EQUATIONS * * Open source under the BSD License. * * Copyright © 2001 Robert Penner * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * Neither the name of the author nor the names of contributors may be used to endorse * or promote products derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * */// ============================================================= // // Skip Links Plugin // ------------------------------------------------------------ // Description: Shows links on focus for screen readers/keyboard users. // Author: @nroyall @whitewhale // Docs: https://github.com/whitewhale/LWSkipLinks // Licensed under the MIT license // // USAGE: // Add classes .site-header and .site-footer to site header and footer. // Call the function on the elements you want to link to, passing the link id and the link name to display. // Make sure the site-header, site-footer and destination elements have relative, absolute or sticky positioning. // EXAMPLE: // $(window).on('load', function() { // run after load so all elements are already on the page // $('.news-page-title, .site-main-content').addSkipLink('#skip-to-main', 'Main Content'); // }); // // Remember to also include a "Back to Top" link in the site footer. // (no need to use the plugin for that since it's the same on every template). // // ============================================================= ;(function($) { $.fn.addSkipLink = function( linkID, linkName ) { // Get the ID without the hash var linkHash = linkID.replace(/^#/, ''); // Get the site header and footer var $header = $('.site-header'); var $footer = $('.site-footer'); // For each destination element $(this).each( function() { var $destination = $(this); // UNCOMMENT TO DEBUG ---------------------------------------------- // if ( !$('#'+linkHash).length && $destination.length ) { // console.log('Adding skip destination to '+$destination.attr('class')); // } // else if ( $('#'+linkHash).length && $destination.length ) { // console.log(linkName+' skip link was already added. Could not add another link to '+$destination.attr('class')); // } // else if ( !$destination.length ) { // console.log('Skip destination does not exist: '+$destination.attr('class')); // } // END DEBUG CODE -------------------------------------------------- // If this skip link hasn't already been added for another element // And if the destination elements exists if ( !$('#'+linkHash).length && $destination.length ) { // Add the skip destination element // (add a new element in case the destination already has an ID) $destination.prepend(''+linkName+''); // Then add a skip link to the page header and footer var skipLink = 'Skip to '+linkName+''; $header.prepend($(skipLink)); $footer.append($(skipLink)); } }); }; // After page load, add skip link pointing to start of main page content. // Different templates may require a different selector. $(window).on('load', function() { $('.site-main-content').addSkipLink('#skip-to-main', 'main content'); }); })(livewhale.jQuery); // ============================================================= // // Data Tables // ------------------------------------------------------------ // Description: provides a layout for tables on mobile // Author: @nroyall @whitewhale // Docs: https://github.com/whitewhale/LWSkipLinks // Licensed under the MIT license // // USAGE: // Add headings to the top row or left column of the table. // On desktop, the headers receive special styling. // On mobile, each header appears above the appropriate table cell. // // ============================================================= ;(function($) { var initScrollTables = function() { // filter tables that have the class "scroll" applied by the formats dropdown $('table').not('.data').not('.scroll-table').filter('.scroll').each(function() { // add the scroll-table class to the table to indicate it has been setup by JS $(this).addClass('scroll-table').wrap('
'); }); }; var initDataTables = function() { var $table = $('table').not('.scroll').addClass('data'); $table.each( function() { var $this = $(this); // find headers in or var $headers = $this.find('thead').length ? $this.find('thead').find('th, td') : $this.find('tbody').find('tr:first-child').find('th, td'); if ( $headers.length ) { // add class to tables with headers or bold text in the first table row if ( !$this.find('thead').length && $this.find('tbody').find('tr:first-child').has('th, h1, h2, h3, h4, h5, h6, strong').length ) { $this.addClass('has-header'); } // create table headers array for all header columns, even if empty var headers = $headers.map(function() { var header = $.trim($(this).text()); if ( header.length ) { header +=':'; // appeand colon non-empty headers } return header; }).get(); // add header data attribute each table cell for display on mobile $this.find('tbody').find('tr').children().attr('data-th', function() { var col = $(this).parent().children().index($(this)); return headers[col]; }); // if left column doesn't have a header, these become headers on mobile $this.find('tbody').find('tr').children(':first-child').filter(function(){ return !$(this).first().attr('data-th'); }).addClass('mobile-header'); } }); }; // Run on document ready initScrollTables(); initDataTables(); // Run again on load in case tables were not loaded yet $(window).on('load', function(){ initScrollTables(); }); // Run after LiveWhale page is edited and saved $('body').bind('stopEdit.lw', function(e) { initScrollTables(); initDataTables(); }); })(livewhale.jQuery); (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('jquery')) : typeof define === 'function' && define.amd ? define(['jquery'], factory) : (global.Util = factory(global.jQuery)); }(this, (function ($) { 'use strict'; $ = $ && $.hasOwnProperty('default') ? $['default'] : $; /** * -------------------------------------------------------------------------- * Bootstrap (v4.1.3): util.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * -------------------------------------------------------------------------- */ var Util = function ($$$1) { /** * ------------------------------------------------------------------------ * Private TransitionEnd Helpers * ------------------------------------------------------------------------ */ var TRANSITION_END = 'transitionend'; var MAX_UID = 1000000; var MILLISECONDS_MULTIPLIER = 1000; // Shoutout AngusCroll (https://goo.gl/pxwQGp) function toType(obj) { return {}.toString.call(obj).match(/\s([a-z]+)/i)[1].toLowerCase(); } function getSpecialTransitionEndEvent() { return { bindType: TRANSITION_END, delegateType: TRANSITION_END, handle: function handle(event) { if ($$$1(event.target).is(this)) { return event.handleObj.handler.apply(this, arguments); // eslint-disable-line prefer-rest-params } return undefined; // eslint-disable-line no-undefined } }; } function transitionEndEmulator(duration) { var _this = this; var called = false; $$$1(this).one(Util.TRANSITION_END, function () { called = true; }); setTimeout(function () { if (!called) { Util.triggerTransitionEnd(_this); } }, duration); return this; } function setTransitionEndSupport() { $$$1.fn.emulateTransitionEnd = transitionEndEmulator; $$$1.event.special[Util.TRANSITION_END] = getSpecialTransitionEndEvent(); } /** * -------------------------------------------------------------------------- * Public Util Api * -------------------------------------------------------------------------- */ var Util = { TRANSITION_END: 'bsTransitionEnd', getUID: function getUID(prefix) { do { // eslint-disable-next-line no-bitwise prefix += ~~(Math.random() * MAX_UID); // "~~" acts like a faster Math.floor() here } while (document.getElementById(prefix)); return prefix; }, getSelectorFromElement: function getSelectorFromElement(element) { var selector = element.getAttribute('data-target'); if (!selector || selector === '#') { selector = element.getAttribute('href') || ''; } try { return document.querySelector(selector) ? selector : null; } catch (err) { return null; } }, getTransitionDurationFromElement: function getTransitionDurationFromElement(element) { if (!element) { return 0; } // Get transition-duration of the element var transitionDuration = $$$1(element).css('transition-duration'); var floatTransitionDuration = parseFloat(transitionDuration); // Return 0 if element or transition duration is not found if (!floatTransitionDuration) { return 0; } // If multiple durations are defined, take the first transitionDuration = transitionDuration.split(',')[0]; return parseFloat(transitionDuration) * MILLISECONDS_MULTIPLIER; }, reflow: function reflow(element) { return element.offsetHeight; }, triggerTransitionEnd: function triggerTransitionEnd(element) { $$$1(element).trigger(TRANSITION_END); }, // TODO: Remove in v5 supportsTransitionEnd: function supportsTransitionEnd() { return Boolean(TRANSITION_END); }, isElement: function isElement(obj) { return (obj[0] || obj).nodeType; }, typeCheckConfig: function typeCheckConfig(componentName, config, configTypes) { for (var property in configTypes) { if (Object.prototype.hasOwnProperty.call(configTypes, property)) { var expectedTypes = configTypes[property]; var value = config[property]; var valueType = value && Util.isElement(value) ? 'element' : toType(value); if (!new RegExp(expectedTypes).test(valueType)) { throw new Error(componentName.toUpperCase() + ": " + ("Option \"" + property + "\" provided type \"" + valueType + "\" ") + ("but expected type \"" + expectedTypes + "\".")); } } } } }; setTransitionEndSupport(); return Util; }($); return Util; }))); //# sourceMappingURL=util.js.map ;(function($, window, document) { var $win = $(window); var $body = $('body'); if ($('#gdpr-notice').length) { // If notice is present var cookieName = "BELOIT-GDPR"; var gdpr_accepted=GetCookie(cookieName); if (gdpr_accepted===null || location.hash === "#gdpr-test"){ // not yet accepted or dismissed message $('#gdpr-notice').delay(3000).fadeIn(700); } $('#gdpr-notice').on('click', 'a.okay, a.exit', function(e){ e.preventDefault(); var expire=new Date(); var days=365; expire=new Date(expire.getTime()+(days*24*60*60*1000)); document.cookie= cookieName + "=here; path=/; expires="+expire; $('#gdpr-notice').fadeOut(300); }); } function GetCookie(name) { var arg=name+"="; var alen=arg.length; var clen=document.cookie.length; var i=0; while (iOpen Side Nav'); // Add expand/collapse behavior on mobile $sideNav.on('click', '.side-nav-title', function(e) { if ( mobileNavBreakpoint.matches === true && e.target.tagName !== 'A' ) { // target mobile screensize only, when clicking outside of group homepage link var $this = $(this); var $sideNav = $this.parents('.side-nav').toggleClass('show-nav'); $this.next('.lw_widget_navigation').slideToggle(340, 'easeInOutQuint'); // same speed and transition for sidebar arrow in sidebar.scss $sideNav.next('.related-links').slideToggle(340, 'easeInOutQuint'); } }); // Move side-nav on department homepages for mobile display // prevents image expanding when side-nav expands if ( $body.hasClass('department-homepage') && $sideNav.length ) { var moveDepartmentNav = function() { if ( mobileNavBreakpoint.matches === true ) { $sideNav.insertAfter('.hero-image-container'); // mobile location } else { $sideNav.insertAfter('.hero-header-panel'); // desktop location } }; // set department side-nav position on load moveDepartmentNav(); // keep an eye on the viewport size to see if department side-nav needs repositioning mobileNavBreakpoint.addListener(moveDepartmentNav); } //////////////////////////////////////////////////////////////////////// // // Text Slider (appears on Core landing page) // //////////////////////////////////////////////////////////////////////// var initTextSlider = function() { var $sliders = $('.text-slider'); // function to create slider with pagination dots // ----------------------------------------------- var createSliders = function() { $sliders.each(function(){ // run function on each gallery on the page var $thisSlider = $(this); // initialize this swiper if not already initialized if ( !$thisSlider.hasClass('.is-ready') ) { var timePerSlide = 4000, // time between image transitions transitionSpeed = 500; // duration of fade transition // initialize Swiper. Swiper container must be different from other swipers. var swiper = new Swiper($thisSlider.find('.text-slider-container').get(0), { observer: true, observeSlideChildren: true, // update Swiper after elements/images are added inside slides spaceBetween: 0, centeredSlides: true, // loop: true, speed: transitionSpeed, // duration of transition autoplay: { delay: timePerSlide, disableOnInteraction: false, // stop autoplay after changing slides with mouse or swipe }, pagination: { el: '.text-slider-dots', clickable: true, }, on: { init: function () { $thisSlider.addClass('is-ready'); // reveal all slides once fully loaded $thisSlider.addClass('is-visible'); // keeping this line to support old CSS }, } }); // swiper.updateSize(); $thisSlider.hover(function() { swiper.autoplay.stop(); // Pause autoplay on mouse hover }, function() { swiper.autoplay.start(); // resume autoplay after mousing away }); } }); }; // Call the createSlider function // -------------------------------- // First check whether Swiper plugin is loaded, then load it // Swiper is also loaded by vertical and hero galleries if ( !$body.hasClass('swiper-loaded') && !$body.hasClass('swiper-loading') ) { $body.addClass('swiper-loading'); // load the Swiper stylesheet $('head').append(''); // load the Swiper plugin script $.ajax({ url: '/_ingredients/plugins/swiper/swiper.js', dataType: 'script', cache: true }).done(function(){ // add body classes and trigger load event once Swiper is loaded $body.removeClass('swiper-loading').addClass('swiper-loaded').trigger('swiper-loaded'); }); } else if ( $body.hasClass('swiper-loaded') ) { createSliders(); // if plugin is already loaded, create sliders } $body.on('swiper-loaded', function(){ createSliders(); // otherwise create sliders when plugin loads (can be triggered by other galleries loading the plugin) }); }; //////////////////////////////////////////////////////////////////////// // // Faculty Profile Accordion (used in the profile sidebar) // //////////////////////////////////////////////////////////////////////// var initProfilesAccordion = function() { var $accordion = $('.profiles-accordion'), $accordionHeaders = $accordion.find('h4').attr('tabindex', '0'); $accordion.on('click keypress', 'h4', function(e){ e.stopImmediatePropagation(); e.preventDefault(); if(e.which == 13 || e.which == 1) { // for return key or mousedown var $thisHeader = $(this), $thisContent = $thisHeader.next('.profiles_content'), $otherSections = $thisHeader.parent('.profiles_field').siblings('.profiles_field'); //Hide the other panels $otherSections.find('h4').removeClass('active'); $otherSections.find('.profiles_content').slideUp('fast'); //Expand or collapse this panel $thisHeader.toggleClass('active'); $thisContent.slideToggle('fast'); } }); }; //////////////////////////////////////////////////////////////////////// // // Location Map Link (appears on office homepage) // //////////////////////////////////////////////////////////////////////// var initLocationMap = function() { var $map = $('.location-map'), $mapLink = $('.location-map-link'), $mapWidget = $('.location-map-overlay').find('.lw_widget_places'); $body.on('click', '.location-map-link', function(e){ e.preventDefault(); $(this).closest('.location-map').toggleClass('is-open'); }); $win.on('click touchstart', function(e) { // close map when clicking elsewhere if ( !$mapWidget.is(e.target) && $mapWidget.has(e.target).length === 0 && !$mapLink.is(e.target) && $mapLink.has(e.target).length === 0 ) { $map.removeClass('is-open'); } }); }; //////////////////////////////////////////////////////////////////////// // // YouTube Video Players // Used for story block videos and homepage video // //////////////////////////////////////////////////////////////////////// var YoutubeApiReady = false; // prevents the API loading twice var loadYoutubeVideos = function() { // check for the existance of a video before loading YouTube API script var youtubeVideos = document.querySelectorAll('.youtube-video'); // console.dir(youtubeVideos); if (typeof(youtubeVideos) != 'undefined' && youtubeVideos != null) { // This function creates a YouTube player for each video on the page // Assumes the video containers will never have the same id var createPlayers = function() { for(var i = 0; i < youtubeVideos.length;i++) { // loop through each video let youtubeVideo = youtubeVideos[i]; // local scope inside loop let videoIframe = youtubeVideo.querySelector('.youtube-video-iframe'); let iframeId = videoIframe.getAttribute('id'); // assume id is unique let youtubeId = videoIframe.getAttribute('data-youtube-id'); // console.log('youtube id: '+ youtubeId); videoPlayer = new YT.Player(iframeId, { host: 'https://www.youtube-nocookie.com', // prevents some cookies used for ads height: '480', // 16:9 aspect ratio, large quality width: '853', videoId: youtubeId, playerVars: { modestbranding: 1, // removes youtube logo from control bar controls: 0, // hides bottom control bar with playback controls rel: 0, // related videos will come from the same channel as the video that was just played (cannot disable related videos) }, events: { 'onStateChange': onPlayerStateChange, 'onReady': onPlayerReady, } }); // This function is called when the player state changes function onPlayerStateChange(event) { if ( event.data === 1 ) { // when video is playing // console.log(iframeId + ' is playing'); youtubeVideo.classList.add('is-playing'); } else if ( event.data === 2 ) { // when video is paused // console.log(iframeId + ' is paused'); youtubeVideo.classList.remove('is-playing'); } } // This function is called once the player is ready function onPlayerReady(event) { // Add play functionality to large play button var videoPlayBtnLarge = youtubeVideo.querySelector('.youtube-video-play-large'); if (typeof(videoPlayBtnLarge) != 'undefined' && videoPlayBtnLarge != null) { videoPlayBtnLarge.addEventListener('click', function (e) { event.target.playVideo(); // event.target applies to this specific video }, false); } // Add play functionality to small play button var videoPlayBtn = youtubeVideo.querySelector('.youtube-video-play'); if (typeof(videoPlayBtn) != 'undefined' && videoPlayBtn != null) { videoPlayBtn.addEventListener('click', function (e) { event.target.playVideo(); }, false); } // Add pause button functionality var videoPauseBtn = youtubeVideo.querySelector('.youtube-video-pause'); if (typeof(videoPauseBtn) != 'undefined' && videoPauseBtn != null) { videoPauseBtn.addEventListener('click', function (e) { event.target.pauseVideo(); }, false); } // Add close button functionality var videoCloseBtn = youtubeVideo.querySelector('.youtube-video-close'); if (typeof(videoCloseBtn) != 'undefined' && videoCloseBtn != null) { videoCloseBtn.addEventListener('click', function (e) { event.target.pauseVideo(); }, false); } // Add seek backwards button functionality var videoBackwardsBtn = youtubeVideo.querySelector('.youtube-video-backwards'); if (typeof(videoBackwardsBtn) != 'undefined' && videoBackwardsBtn != null) { videoBackwardsBtn.addEventListener('click', function (e) { var currentTime = event.target.getCurrentTime(); // console.log('current time: '+currentTime); event.target.seekTo(currentTime-10, true); event.target.playVideo(); }, false); } // Add seek forwards button functionality var videoForwardsBtn = youtubeVideo.querySelector('.youtube-video-forwards'); if (typeof(videoForwardsBtn) != 'undefined' && videoForwardsBtn != null) { videoForwardsBtn.addEventListener('click', function (e) { var currentTime = event.target.getCurrentTime(); // console.log('current time: '+currentTime); event.target.seekTo(currentTime+10, true); event.target.playVideo(); }, false); } // Add mute button functionality var videoMuteBtn = youtubeVideo.querySelector('.youtube-video-mute'); if (typeof(videoMuteBtn) != 'undefined' && videoMuteBtn != null) { videoMuteBtn.addEventListener('click', function (e) { youtubeVideo.classList.add('is-mute'); event.target.mute(); }, false); } // Add unmute button functionality var videoUnmuteBtn = youtubeVideo.querySelector('.youtube-video-unmute'); if (typeof(videoUnmuteBtn) != 'undefined' && videoUnmuteBtn != null) { videoUnmuteBtn.addEventListener('click', function (e) { youtubeVideo.classList.remove('is-mute'); event.target.unMute(); }, false); } // Pause video when switching to another tab window.addEventListener('blur', function(){ event.target.pauseVideo(); }); } } }; // Check whether the API script needs loading if ( !YoutubeApiReady ) { // Load the YouTube API script var YouTubeTag = document.createElement('script'); YouTubeTag.src = "https://www.youtube.com/iframe_api"; var firstScriptTag = document.getElementsByTagName('script')[0]; firstScriptTag.parentNode.insertBefore(YouTubeTag, firstScriptTag); // After the API code downloads (this function call must only occur once) window.onYouTubeIframeAPIReady = function() { // evoke globally YoutubeApiReady = true; createPlayers(youtubeVideos); // create players once the API is ready } } else { // if the API script has previously loaded eg: prior to widget pagination createPlayers(youtubeVideos); // create players without loading the API again } } }; //////////////////////////////////////////////////////////////////////// // // Hide Placeholder Text // //////////////////////////////////////////////////////////////////////// var hidePlaceholderText = function() { // Hide containers with unedited placeholder text in them, for logged-out visitors $('body:not(.has_pages_edit) #related-links p:contains("Add related links")').parent().parent().hide(); }; //////////////////////////////////////////////////////////////////////// // // Add functionality to Bootstrap tab behavior // When you navigate to the page with a #hash show the relevant tab // When you click a tab link, change the hash and scroll to top of tab // //////////////////////////////////////////////////////////////////////// $(function(){ var $tabs = $('.nav-tabs'); if ( $tabs.length ) { var tabsTop = $tabs.get(0).getBoundingClientRect().top + $(window)['scrollTop'](); // console.log("$(window)['scrollTop']()", $(window)['scrollTop']()); // console.log("$tabs.get(0).getBoundingClientRect().top", $tabs.get(0).getBoundingClientRect().top); // console.log('tabstop'+tabsTop); // show correct tab on load var hash = window.location.hash; if ( hash ) { $('.nav-tabs a[href="' + hash + '"]').tab('show'); $('html,body').scrollTop(tabsTop - 115 - 60 ); // scroll to top of tabs plus some padding for Beloit sticky header } // change URL hash when clicking tab button $('.nav-tabs a').click(function (e) { window.location.hash = this.hash; }); // show tab when clicking link inside one tab to another tab $body.on('click', '.tab-content a[href^="#"]', function(e) { var hash = $(this).attr('href'); var $tabLink = $('.nav-tabs a[href="' + hash + '"]'); // NR: added check to see if link goes to tab if ( $tabLink.length ) { e.preventDefault(); $tabLink.tab('show'); window.location.hash = hash; $('html,body').scrollTop(tabsTop - 115 - 36 - 10 ); // scroll to top, leave room for sticky header, announcement and gap } }) } }); //////////////////////////////////////////////////////////////////////// // // Core Landing Page Intro: Video Play Btn for images with videos // //////////////////////////////////////////////////////////////////////// var initCoreIntroVideo = function() { var $coreIntroVideo = $('.core-intro-video'); var $coreIntroVideoBtn = $('.core-intro-video-btn'); if ( $coreIntroVideo.length ) { $body.on('click', '.core-intro-video-btn', function(){ // open video $coreIntroVideo.addClass('is-visible'); $body.addClass('has-overlay'); }); $body.on('click', '.youtube-video-close', function(){ // close video $coreIntroVideo.removeClass('is-visible'); $body.removeClass('has-overlay'); }); $win.on('click touchstart', function(e) { // close video when clicking elsewhere if ( !$coreIntroVideo.is(e.target) && $coreIntroVideo.has(e.target).length === 0 && !$coreIntroVideoBtn.is(e.target) && $coreIntroVideoBtn.has(e.target).length === 0 ) { $coreIntroVideo.find('.youtube-video-close').trigger('click'); // trigger click on close button so video pauses } }); } }; //////////////////////////////////////////////////////////////////////// // // Append UTM Codes to links to external links - NM'14 // //////////////////////////////////////////////////////////////////////// /*var appendAdmissionsUTM = function() { return; // do not use $("a").each(function() { //check each link // if has href, contains "admissions.beloit.edu", and doesn't have "utm_" already if( !!$(this).attr('href') && ($(this).attr('href').indexOf('admissions.beloit.edu') > -1) && ($(this).attr('href').indexOf('utm_') == -1) ) { var link = $(this).attr('href'); link+= ($(this).attr('href').indexOf('?') > -1) ? "&" : "?"; link+= "utm_source=www.beloit.edu&utm_medium=referral"; //console.log( $(this) ); //console.log( link ); $(this).attr('href', link); } }); };*/ var appendExternalUTM = function() { $("a").each(function() { if( (!!$(this).attr('href')) && // has href (($(this).attr('href').indexOf('https://') > -1) || ($(this).attr('href').indexOf('http://') > -1)) && // has http or https ($(this).attr('href').indexOf('www.beloit.edu') == -1) && // doesn't have "www.beloit.edu" ($(this).attr('href').indexOf('admissions.beloit.edu') == -1) && // doesn't have "admissions.beloit.edu" ($(this).attr('href').indexOf('beloit-dev.livewhale.net') == -1) && // doesn't have "beloit-dev.livewhale.net" ($(this).attr('href').indexOf('npc.com') == -1) && // doesn't have "(college)npc.com" ($(this).attr('href').indexOf('NPC.com') == -1) && // doesn't have "(College)NPC.com" ($(this).attr('href').indexOf('utm_') == -1) // doesn't already have "utm_" parameters ) { var link = $(this).attr('href'); link+= ($(this).attr('href').indexOf('?') > -1) ? "&" : "?"; link+= "utm_source=www.beloit.edu&utm_medium=referral"; //console.log( $(this) ); //console.log( link ); $(this).attr('href', link); } }); }; //////////////////////////////////////////////////////////////////////// // // Function Calls: // //////////////////////////////////////////////////////////////////////// // Run these functions on document ready initMobileHeader(); initProfilesAccordion (); initLocationMap(); hidePlaceholderText(); initCoreIntroVideo(); initTextSlider(); // initialize text sliders BEFORE load, avoid waiting for heavy resources to load first appendExternalUTM(); // Run these functions on window resize $win.on('resize', function() { moveSidebarOnMobile(); }); // Run these functions on window load $win.on('load', function() { moveSidebarOnMobile(); loadYoutubeVideos(); // wait for videos in widgets to load initProfilesAccordion (); }); // Run these functions after widget pagination $body.bind('paginate.lw', function(e, el){ loadYoutubeVideos(); // for videos in the story block }); // Run these functions when LiveWhale page is edited then saved $body.bind('stopEdit.lw', function(e) { initProfilesAccordion (); }); }(livewhale.jQuery, window, document)); ;(function($, window, document) { var $win = $(window); var $body = $('body'); //////////////////////////////////////////////////////////////////////// // // Test lw-slideshow // //////////////////////////////////////////////////////////////////////// var initDebugSlideshow = function() { // var $lw_slideshow = $('.lw_slideshow'); // var $lw_slideshow_active = $('.lw_slideshow_active'); // if ( $lw_slideshow_active.length ) { // console.log('active slide found'); // ***** Repeat this function every 1.5 seconds function intervalTrigger() { return setInterval( function() { var $lw_slideshow = $('.lw_slideshow'); var $lw_slideshow_active = $('.lw_slideshow_active'); if ( $lw_slideshow_active.length ) { // console.log('active slide found'); // Check for slideshow size height = Math.round($lw_slideshow.height()); width = Math.round($lw_slideshow.width()); targetWidth = Math.round($lw_slideshow_active.outerWidth(true)); targetHeight = Math.round($lw_slideshow_active.outerHeight(true)); // console.log('Slideshow: ' + width + 'x' + height + ', active slide ' + targetWidth + 'x' + targetHeight); if ((width == targetWidth) && (width == 0)) { // debug, set 400px min width targetWidth = 400; } // Re-run the slideshow code to address the slideshow size if ((height !== targetHeight) || (width !== targetWidth)) { console.log('Slideshow: adjusting height/width'); $lw_slideshow.animate({ 'height': targetHeight, 'width': targetWidth } , 300); console.log('Slideshow: animated to ' + width + 'x' + height + ', active slide ' + targetWidth + 'x' + targetHeight); } } // end of check for slideshow existence }, 750 ); }; // console.log('Starting interval'); // ***** After 20 seconds, clear the repeating function var id = intervalTrigger(); setTimeout(function() { // console.log('Clearing interval'); clearInterval(id); }, 12000); // } }; //////////////////////////////////////////////////////////////////////// // // Function Calls: // //////////////////////////////////////////////////////////////////////// // Run these functions on window load $win.on('load', function() { initDebugSlideshow(); }); }(livewhale.jQuery, window, document)); (function($, LW) { var $body = $('body'), $win = $(window); // FILTER DROPDOWNS -- prepared for Nick after LWDC // ---------------------------------------------------------------- var initFilters = function() { var $filters = $('.filter'); if ( $filters.length ) { var $dropdowns = $filters.find('.filter-dropdown'); // toggle filter dropdowns on click or keypress $body.on('click keydown', '.filter .filter-label', function(e) { // e.preventDefault(); var $this = $(this), $thisFilter = $this.closest('.filter'), $thisDropdown = $thisFilter.find('.filter-dropdown'); // if clicking or pressing return key if ( e.type == 'click' || e.type == 'keydown' && e.which == 13 ) { // when the dropdown is collapsed if ( !$thisDropdown.is(':visible') ) { // close other dropdowns $filters.not($thisFilter).removeClass('is-active'); $dropdowns.not($thisDropdown).slideUp(0); // open this dropdown if closed $thisDropdown.slideDown(200); $thisFilter.addClass('is-active'); // move focus to the first selected option, otherwise to the first option var $selectedOptions = $thisDropdown.find('.filter-option').find('input:checked'); var $focusedOption = $selectedOptions.length ? $selectedOptions.first() : $thisDropdown.find('.filter-option').find('input, a').first(); // $focusedOption.focus(); } else { // when the dropdown is expanded, close it $thisDropdown.slideUp(100); $thisFilter.removeClass('is-active') } } }); $body.on('click touchstart keydown', function(e) { // close all dropdowns if clicking/keypressing elsewhere if ( !$filters.is(e.target) && $filters.has(e.target).length === 0 ) { $filters.removeClass('is-active'); $dropdowns.slideUp(0); } // close all dropdowns if pressing escape while focused inside dropdown if ( ( $filters.is(e.target) || $filters.has(e.target).length ) && e.which == 27 ) { $filters.removeClass('is-active'); $dropdowns.slideUp(0); $(e.target).closest('.filter').find('.filter-label').focus(); // move focus back to label } }); // when tabbing on a collapsed dropdown, close expanded dropdowns $body.on('keyup', '.filter .filter-label', function(e) { var $this = $(this), $thisFilter = $this.closest('.filter'), $thisDropdown = $thisFilter.find('.filter-dropdown'); if ( !$thisDropdown.is(':visible') && e.which == 9 ) { $filters.removeClass('is-active'); $dropdowns.slideUp(0); } }); } // add custom function to support the calendar filter // the core calendar function only supports a