(function ($) { 'use strict' /* Masonry --------------------- */ function masonrySetup () { var $container = $('.obb-masonry-container'); // Ensure Masonry initializes after images have loaded $container.imagesLoaded(function() { $container.masonry({ gutter: '.obb-grid-spacer', itemSelector: '.obb-masonry-wrapper' }); }); } /* Isotope --------------------- */ function isotopeSetup () { $('.obb-portfolio, .obb-posts').each(function (index, obj) { var filterID = obj.getAttribute('data-id') var $grid = $('#' + filterID + ' .obb-masonry-container.obb-isotope') // Quick search regex var qsRegex // Initialize Isotope after images have loaded $grid.imagesLoaded(function () { $grid.isotope({ itemSelector: '.obb-masonry-wrapper', percentPosition: true, masonry: { gutter: '.obb-grid-spacer' } }) }); // use value of search field to filter $('#' + filterID + ' .obb-filter-search').on('click', 'input', function () { $('.obb-filter-buttons button').off('click') var $quicksearch = $('.quicksearch').keyup(debounce(function () { qsRegex = new RegExp($quicksearch.val(), 'gi') $grid.isotope({ filter: function () { return qsRegex ? $(this).text().match(qsRegex) : true } }) }, 200)) }) $('#' + filterID + ' .obb-filter-buttons').on('click', 'button', function () { var filterValue = $(this).attr('data-filter') $grid.isotope({ filter: filterValue }) }) // debounce so filtering doesn't happen every millisecond function debounce (fn, threshold) { var timeout threshold = threshold || 100 return function debounced () { clearTimeout(timeout) var args = arguments var _this = this function delayed () { fn.apply(_this, args) } timeout = setTimeout(delayed, threshold) } } }) } // Recalculate layout on scroll to ensure items are in the correct positions function recalculateLayoutOnScroll() { $(window).on('scroll', function() { $('.obb-masonry-container').each(function() { var $this = $(this); if ($this.is(':visible')) { $this.masonry('layout'); } }); }); } $(document).ready(() => { isotopeSetup(); masonrySetup(); recalculateLayoutOnScroll(); }); $(window).on('resize', () => { isotopeSetup(); masonrySetup(); }); })(jQuery); ; /** * Observe how the user enters content into the comment form in order to determine whether it's a bot or not. * * Note that no actual input is being saved here, only counts and timings between events. */ ( function() { // Passive event listeners are guaranteed to never call e.preventDefault(), // but they're not supported in all browsers. Use this feature detection // to determine whether they're available for use. var supportsPassive = false; try { var opts = Object.defineProperty( {}, 'passive', { get : function() { supportsPassive = true; } } ); window.addEventListener( 'testPassive', null, opts ); window.removeEventListener( 'testPassive', null, opts ); } catch ( e ) {} function init() { var input_begin = ''; var keydowns = {}; var lastKeyup = null; var lastKeydown = null; var keypresses = []; var modifierKeys = []; var correctionKeys = []; var lastMouseup = null; var lastMousedown = null; var mouseclicks = []; var mousemoveTimer = null; var lastMousemoveX = null; var lastMousemoveY = null; var mousemoveStart = null; var mousemoves = []; var touchmoveCountTimer = null; var touchmoveCount = 0; var lastTouchEnd = null; var lastTouchStart = null; var touchEvents = []; var scrollCountTimer = null; var scrollCount = 0; var correctionKeyCodes = [ 'Backspace', 'Delete', 'ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'Home', 'End', 'PageUp', 'PageDown' ]; var modifierKeyCodes = [ 'Shift', 'CapsLock' ]; var forms = document.querySelectorAll( 'form[method=post]' ); for ( var i = 0; i < forms.length; i++ ) { var form = forms[i]; var formAction = form.getAttribute( 'action' ); // Ignore forms that POST directly to other domains; these could be things like payment forms. if ( formAction ) { // Check that the form is posting to an external URL, not a path. if ( formAction.indexOf( 'http://' ) == 0 || formAction.indexOf( 'https://' ) == 0 ) { if ( formAction.indexOf( 'http://' + window.location.hostname + '/' ) != 0 && formAction.indexOf( 'https://' + window.location.hostname + '/' ) != 0 ) { continue; } } } form.addEventListener( 'submit', function () { var ak_bkp = prepare_timestamp_array_for_request( keypresses ); var ak_bmc = prepare_timestamp_array_for_request( mouseclicks ); var ak_bte = prepare_timestamp_array_for_request( touchEvents ); var ak_bmm = prepare_timestamp_array_for_request( mousemoves ); var input_fields = { // When did the user begin entering any input? 'bib': input_begin, // When was the form submitted? 'bfs': Date.now(), // How many keypresses did they make? 'bkpc': keypresses.length, // How quickly did they press a sample of keys, and how long between them? 'bkp': ak_bkp, // How quickly did they click the mouse, and how long between clicks? 'bmc': ak_bmc, // How many mouseclicks did they make? 'bmcc': mouseclicks.length, // When did they press modifier keys (like Shift or Capslock)? 'bmk': modifierKeys.join( ';' ), // When did they correct themselves? e.g., press Backspace, or use the arrow keys to move the cursor back 'bck': correctionKeys.join( ';' ), // How many times did they move the mouse? 'bmmc': mousemoves.length, // How many times did they move around using a touchscreen? 'btmc': touchmoveCount, // How many times did they scroll? 'bsc': scrollCount, // How quickly did they perform touch events, and how long between them? 'bte': ak_bte, // How many touch events were there? 'btec' : touchEvents.length, // How quickly did they move the mouse, and how long between moves? 'bmm' : ak_bmm }; var akismet_field_prefix = 'ak_'; if ( this.getElementsByClassName ) { // Check to see if we've used an alternate field name prefix. We store this as an attribute of the container around some of the Akismet fields. var possible_akismet_containers = this.getElementsByClassName( 'akismet-fields-container' ); for ( var containerIndex = 0; containerIndex < possible_akismet_containers.length; containerIndex++ ) { var container = possible_akismet_containers.item( containerIndex ); if ( container.getAttribute( 'data-prefix' ) ) { akismet_field_prefix = container.getAttribute( 'data-prefix' ); break; } } } for ( var field_name in input_fields ) { var field = document.createElement( 'input' ); field.setAttribute( 'type', 'hidden' ); field.setAttribute( 'name', akismet_field_prefix + field_name ); field.setAttribute( 'value', input_fields[ field_name ] ); this.appendChild( field ); } }, supportsPassive ? { passive: true } : false ); form.addEventListener( 'keydown', function ( e ) { // If you hold a key down, some browsers send multiple keydown events in a row. // Ignore any keydown events for a key that hasn't come back up yet. if ( e.key in keydowns ) { return; } var keydownTime = ( new Date() ).getTime(); keydowns[ e.key ] = [ keydownTime ]; if ( ! input_begin ) { input_begin = keydownTime; } // In some situations, we don't want to record an interval since the last keypress -- for example, // on the first keypress, or on a keypress after focus has changed to another element. Normally, // we want to record the time between the last keyup and this keydown. But if they press a // key while already pressing a key, we want to record the time between the two keydowns. var lastKeyEvent = Math.max( lastKeydown, lastKeyup ); if ( lastKeyEvent ) { keydowns[ e.key ].push( keydownTime - lastKeyEvent ); } lastKeydown = keydownTime; }, supportsPassive ? { passive: true } : false ); form.addEventListener( 'keyup', function ( e ) { if ( ! ( e.key in keydowns ) ) { // This key was pressed before this script was loaded, or a mouseclick happened during the keypress, or... return; } var keyupTime = ( new Date() ).getTime(); if ( 'TEXTAREA' === e.target.nodeName || 'INPUT' === e.target.nodeName ) { if ( -1 !== modifierKeyCodes.indexOf( e.key ) ) { modifierKeys.push( keypresses.length - 1 ); } else if ( -1 !== correctionKeyCodes.indexOf( e.key ) ) { correctionKeys.push( keypresses.length - 1 ); } else { // ^ Don't record timings for keys like Shift or backspace, since they // typically get held down for longer than regular typing. var keydownTime = keydowns[ e.key ][0]; var keypress = []; // Keypress duration. keypress.push( keyupTime - keydownTime ); // Amount of time between this keypress and the previous keypress. if ( keydowns[ e.key ].length > 1 ) { keypress.push( keydowns[ e.key ][1] ); } keypresses.push( keypress ); } } delete keydowns[ e.key ]; lastKeyup = keyupTime; }, supportsPassive ? { passive: true } : false ); form.addEventListener( "focusin", function ( e ) { lastKeydown = null; lastKeyup = null; keydowns = {}; }, supportsPassive ? { passive: true } : false ); form.addEventListener( "focusout", function ( e ) { lastKeydown = null; lastKeyup = null; keydowns = {}; }, supportsPassive ? { passive: true } : false ); } document.addEventListener( 'mousedown', function ( e ) { lastMousedown = ( new Date() ).getTime(); }, supportsPassive ? { passive: true } : false ); document.addEventListener( 'mouseup', function ( e ) { if ( ! lastMousedown ) { // If the mousedown happened before this script was loaded, but the mouseup happened after... return; } var now = ( new Date() ).getTime(); var mouseclick = []; mouseclick.push( now - lastMousedown ); if ( lastMouseup ) { mouseclick.push( lastMousedown - lastMouseup ); } mouseclicks.push( mouseclick ); lastMouseup = now; // If the mouse has been clicked, don't record this time as an interval between keypresses. lastKeydown = null; lastKeyup = null; keydowns = {}; }, supportsPassive ? { passive: true } : false ); document.addEventListener( 'mousemove', function ( e ) { if ( mousemoveTimer ) { clearTimeout( mousemoveTimer ); mousemoveTimer = null; } else { mousemoveStart = ( new Date() ).getTime(); lastMousemoveX = e.offsetX; lastMousemoveY = e.offsetY; } mousemoveTimer = setTimeout( function ( theEvent, originalMousemoveStart ) { var now = ( new Date() ).getTime() - 500; // To account for the timer delay. var mousemove = []; mousemove.push( now - originalMousemoveStart ); mousemove.push( Math.round( Math.sqrt( Math.pow( theEvent.offsetX - lastMousemoveX, 2 ) + Math.pow( theEvent.offsetY - lastMousemoveY, 2 ) ) ) ); if ( mousemove[1] > 0 ) { // If there was no measurable distance, then it wasn't really a move. mousemoves.push( mousemove ); } mousemoveStart = null; mousemoveTimer = null; }, 500, e, mousemoveStart ); }, supportsPassive ? { passive: true } : false ); document.addEventListener( 'touchmove', function ( e ) { if ( touchmoveCountTimer ) { clearTimeout( touchmoveCountTimer ); } touchmoveCountTimer = setTimeout( function () { touchmoveCount++; }, 500 ); }, supportsPassive ? { passive: true } : false ); document.addEventListener( 'touchstart', function ( e ) { lastTouchStart = ( new Date() ).getTime(); }, supportsPassive ? { passive: true } : false ); document.addEventListener( 'touchend', function ( e ) { if ( ! lastTouchStart ) { // If the touchstart happened before this script was loaded, but the touchend happened after... return; } var now = ( new Date() ).getTime(); var touchEvent = []; touchEvent.push( now - lastTouchStart ); if ( lastTouchEnd ) { touchEvent.push( lastTouchStart - lastTouchEnd ); } touchEvents.push( touchEvent ); lastTouchEnd = now; // Don't record this time as an interval between keypresses. lastKeydown = null; lastKeyup = null; keydowns = {}; }, supportsPassive ? { passive: true } : false ); document.addEventListener( 'scroll', function ( e ) { if ( scrollCountTimer ) { clearTimeout( scrollCountTimer ); } scrollCountTimer = setTimeout( function () { scrollCount++; }, 500 ); }, supportsPassive ? { passive: true } : false ); } /** * For the timestamp data that is collected, don't send more than `limit` data points in the request. * Choose a random slice and send those. */ function prepare_timestamp_array_for_request( a, limit ) { if ( ! limit ) { limit = 100; } var rv = ''; if ( a.length > 0 ) { var random_starting_point = Math.max( 0, Math.floor( Math.random() * a.length - limit ) ); for ( var i = 0; i < limit && i < a.length; i++ ) { rv += a[ random_starting_point + i ][0]; if ( a[ random_starting_point + i ].length >= 2 ) { rv += "," + a[ random_starting_point + i ][1]; } rv += ";"; } } return rv; } if ( document.readyState !== 'loading' ) { init(); } else { document.addEventListener( 'DOMContentLoaded', init ); } })();; /*! This file is auto-generated */ window.addComment=function(v){var I,C,h,E=v.document,b={commentReplyClass:"comment-reply-link",commentReplyTitleId:"reply-title",cancelReplyId:"cancel-comment-reply-link",commentFormId:"commentform",temporaryFormId:"wp-temp-form-div",parentIdFieldId:"comment_parent",postIdFieldId:"comment_post_ID"},e=v.MutationObserver||v.WebKitMutationObserver||v.MozMutationObserver,r="querySelector"in E&&"addEventListener"in v,n=!!E.documentElement.dataset;function t(){d(),e&&new e(o).observe(E.body,{childList:!0,subtree:!0})}function d(e){if(r&&(I=g(b.cancelReplyId),C=g(b.commentFormId),I)){I.addEventListener("touchstart",l),I.addEventListener("click",l);function t(e){if((e.metaKey||e.ctrlKey)&&13===e.keyCode&&"a"!==E.activeElement.tagName.toLowerCase())return C.removeEventListener("keydown",t),e.preventDefault(),C.submit.click(),!1}C&&C.addEventListener("keydown",t);for(var n,d=function(e){var t=b.commentReplyClass;e&&e.childNodes||(e=E);e=E.getElementsByClassName?e.getElementsByClassName(t):e.querySelectorAll("."+t);return e}(e),o=0,i=d.length;o 0) { var subMenuWidth = $(this).find('.sub-menu').width() var subMenuOffset = $(this).find('.sub-menu').parent().offset().left + subMenuWidth // If sub menu is off screen, give new position if ((subMenuOffset + subMenuWidth) > mainWindowWidth) { var newSubMenuPosition = subMenuWidth $(this).find('.sub-menu').css({ left: 'auto', right: '0' }) $(this).find('.sub-menu .sub-menu').css({ left: -newSubMenuPosition - 32, right: '0' }) } } }) } /* Header Block Position --------------------- */ function headerSetup () { if ($('.obb-header').hasClass('position-fixed')) { $('.site-header').attr('data-position', 'position-fixed') } if ($('.obb-header').hasClass('position-absolute')) { $('.site-header').attr('data-position', 'position-absolute') } if ($(this).scrollTop() > 80) { $('.header-transparent-scroll').addClass('scrolling') $('.obb-mobile-menu-container').addClass('scrolling') } else { $('.header-transparent-scroll').removeClass('scrolling') $('.obb-mobile-menu-container').removeClass('scrolling') } } /* Header Block Mobile Submenus --------------------- */ function subMenuSetup() { if ($(window).width() <= 768) { if ($('.obb-mobile-menus #mobile-nav-large ul.obb-menu ul.sub-menu').css('display') == 'none') { // Toggle submenus var subMenuToggle = $('.obb-menu li.menu-item-has-children > .dropdown').unbind(); subMenuToggle.on('click', function(e) { e.preventDefault(); var submenu = $(this).parent().children('.obb-mobile-menus ul.obb-menu ul.sub-menu'); if ($(submenu).is(':hidden')) { $(submenu).slideDown(200); } else { $(submenu).slideUp(200); } }) subMenuToggle.on('dblclick', function (e) { window.location.replace($(this).attr('href')) }) } } } function generalFunctions () { /* Add Mobile Menu Dropdown Arrows --------------------- */ $(".obb-mobile-menus #mobile-nav-large ul.obb-menu li.menu-item-has-children").append(""); /* Toggle Mobile Menu --------------------- */ $('.obb-mobile-menu-container').each(function (index, obj) { var mobileMenuID = obj.getAttribute('data-mobile-id') $('#' + mobileMenuID + ' .obb-menu-toggle.open').on('click touchstart', function () { $('.' + mobileMenuID + '.obb-mobile-menu-container').addClass('revealed') $('body').addClass('mobile-menu-open') }) $('.' + mobileMenuID + ' .obb-menu-toggle.close, .' + mobileMenuID + ' .obb-mobile-menus li a').on('click swipeleft', function () { $('.' + mobileMenuID + '.obb-mobile-menu-container').removeClass('revealed') $('body').removeClass('mobile-menu-open') }) }) /* Scroll To Top Button --------------------- */ $('button.obb-footer-return').click(function () { window.scroll({ top: 0, left: 0, behavior: 'smooth' }) }) /* Animate Page Scroll --------------------- */ $('.scroll-link a').on('click', function (event) { event.preventDefault() var dest = $(this).attr('href') // console.log(dest) if (dest.length) { $('html,body').animate({ scrollTop: $(dest).offset().top }, 500) } }) /* Remove Links From Link Container Content --------------------- */ $('.obb-link-content a').removeAttr('href') /* Modal Button -------------------- */ $('.obb-modal-open[rel~="modal:open"]').click(function (event) { $(this).modal() return false }) } $(document) .ready(generalFunctions) .ready(menuOffset) .ready(headerSetup) $(window) .on('scroll', headerSetup) .on('load', subMenuSetup) .on('resize', subMenuSetup) })(jQuery) ;