PATH:
var
/
www
/
clients
/
client1
/
web1
/
web
/
wp-content
/
plugins
/
so-widgets-bundle
/
js
/* globals jQuery, sowb */ var sowb = window.sowb || {}; jQuery( function ( $ ) { // We remove animations if the user has motion disabled. const reduceMotion = window.matchMedia( '(prefers-reduced-motion: reduce)' ).matches; /** * Fix container height to prevent layout shifts * * Calculates and sets optimal container height based on the tallest * carousel item: * - Stores current height to compare with calculated height. * - Efficiently measures all items to find maximum height. * - Adds margin-bottom to final height calculation. * - Only updates DOM if height difference exceeds 1px threshold. * - Prevents unnecessary reflows by checking height before setting. */ $.fn.fixContainerHeight = function() { const $$ = $( this ); const currentHeight = $$.height(); const $items = $$.find( '.sow-carousel-item' ); if ( ! $items.length ) { return; } // Find the tallest item let maxHeight = 0; $items.each( function() { const $item = $( this ); const height = $item.outerHeight(); if ( height > maxHeight ) { maxHeight = height; } } ); const margin_height = parseFloat( $items.first().css( 'margin-bottom' ) ); const newHeight = maxHeight + margin_height; // Only change height if necessary and avoid unnecessary reflows. if ( Math.abs( currentHeight - newHeight ) > 1 ) { $$.css( 'height', newHeight ); } }; /** * Navigate to a specific slide in the carousel, and then * (optionally) adapts the height of the carousel. */ $.fn.navigateToSlide = function( newSlide ) { const $$ = $( this ); if ( newSlide !== null ) { if ( typeof newSlide === 'string' ) { $$.slick( newSlide ); } else { $$.slick( 'slickGoTo', newSlide - 1 ); } } $$.adaptiveHeight(); }; let carouselLoading = true; /** * Adjust carousel height to fit tallest visible slide. * * Extends jQuery with an adaptive height function that: * - Measures all visible slides (not just active one like Slick does). * - Adjusts container height to match tallest slide. * - Handles initial loading state differently to avoid navigation jump. * - Adds smooth transition animation for subsequent height changes. * - Accounts for margin-bottom spacing between slides. * - Sets consistent height for all visible slides. */ $.fn.adaptiveHeight = function() { const $$ = $( this ); if ( ! $$.data( 'adaptive_height' ) ) { return; } // We're using a custom solution for adaptive height as Slick's // adaptive height only factors in the "active" item, not all // visible items. const visibleSlides = $$.find( '.slick-active' ); visibleSlides.css( 'height', 'fit-content' ); let maxHeight = 0; visibleSlides.each( function() { const $item = $( this ); const slideHeight = $item.outerHeight(); if ( slideHeight > maxHeight ) { maxHeight = slideHeight; } } ); // It's possible that the slides will have a margin-bottom set, // and we need to account for that in the sizing. const marginBottom = parseFloat( visibleSlides.first().css( 'margin-bottom' ) ); $slickList = $$.find( '.slick-list' ); // Check if the carousel has been loaded before. if ( $slickList.hasClass( 'sow-loaded' ) ) { $slickList.animate( { height: maxHeight + marginBottom, }, $$.data( 'adaptive_height' ) || 150 ); } else { // Prevent the navigation from moving on load. $slickList.css( 'height', maxHeight + marginBottom ); if ( carouselLoading ) { setTimeout( function() { $slickList.addClass( 'sow-loaded' ) carouselLoading = false; }, 150 ); } } visibleSlides.css( 'height', maxHeight ); } $.fn.carouselDotNavigation = function( e ) { const $$ = $( this ); const $items = $$.find( '.sow-carousel-items' ); const slidesToScroll = $items.slick( 'slickGetOption', 'slidesToScroll' ); const numItems = $items.find( '.sow-carousel-item' ).length; const numVisibleItems = Math.ceil( $items.outerWidth() / $items.find( '.sow-carousel-item' ).outerWidth( true ) ); const lastPosition = numItems - numVisibleItems; let targetItem = $( e.currentTarget ).index(); // Check if navigating to the selected item would result in a blank space. if ( targetItem + numVisibleItems >= numItems ) { // Blank spacing would occur, let's go to the last possible item // make it appear as though we navigated to the selected item. $items.navigateToSlide( lastPosition ); $dots = $$.parent(); $dots.find( '.slick-active' ).removeClass( 'slick-active' ); $dots.children().eq( targetItem ).addClass( 'slick-active' ); } else { if ( $$.data( 'widget' ) == 'post' ) { // We need to account for an empty item. targetItem = Math.ceil( targetItem + 1 * slidesToScroll ); } $items.navigateToSlide( targetItem ); } // Is this a Post Carousel? If so, let's check if we need to load more posts. if ( $$.data( 'widget' ) == 'post' ) { const complete = numItems >= $$.data( 'item_count' ); // Check if all items are displayed if ( ! complete ) { if ( $items.slick( 'slickCurrentSlide' ) + numVisibleItems >= numItems - 1 || $items.slick( 'slickCurrentSlide' ) + slidesToScroll > lastPosition ) { $( sowb ).trigger( 'carousel_load_new_items', [ $$, $items, false ] ); } } } triggerResize( $items, $$.data( 'carousel_settings' ) ); }; /** * Trigger resize adjustments for carousel items. * * Handles adaptive height adjustments and container height fixes. * for carousel items. Only applies height adjustments if: * - Adaptive height is enabled. * - Theme is 'cards'. * - Dynamic navigation is disabled. * * @param {jQuery} $items Carousel items jQuery element. * @param {Object} settings Carousel settings object. */ const triggerResize = ( $items, settings ) => { if ( ! $items.data( 'adaptive_height' ) ) { return; } $items.adaptiveHeight(); if ( settings.theme !== 'cards' || settings.dynamic_navigation ) { return; } $items.fixContainerHeight(); } sowb.setupCarousel = function () { $.fn.setSlideTo = function( slide ) { $items = $( this ); // We need to reset the Slick slide settings to avoid https://github.com/kenwheeler/slick/issues/1006. const slidesToShow = $items.slick( 'slickGetOption', 'slidesToShow' ); const slidesToScroll = $items.slick( 'slickGetOption', 'slidesToScroll' ); $items.slick( 'slickSetOption', 'slidesToShow', 1 ); $items.slick( 'slickSetOption', 'slidesToScroll', 1 ); $items.navigateToSlide( slide ); $items.slick( 'slickSetOption', 'slidesToShow', slidesToShow ); $items.slick( 'slickSetOption', 'slidesToScroll', slidesToScroll ); }; // The carousel widget $( '.sow-carousel-wrapper' ).each( function () { var $$ = $( this ), $items = $$.find( '.sow-carousel-items' ), responsiveSettings = $$.data( 'responsive' ), carouselSettings = $$.data( 'carousel_settings' ); // Remove animations if needed. if ( reduceMotion ) { carouselSettings.animation_speed = 0; } // Store reference to Adaptive height and speed for later use. $items.data( 'adaptive_height', carouselSettings.adaptive_height ); $items.data( 'animation_speed', carouselSettings.animation_speed ); const isBlockEditor = $( 'body' ).hasClass( 'block-editor-page' ); const isContinuous = carouselSettings.autoplay === 'continuous'; $items.on( 'init', function(e, slick) { const $wrapper = $(this).closest('.sow-carousel-wrapper'); setTimeout( function() { if ( carouselSettings.theme === 'cards' && ! carouselSettings.dynamic_navigation && ! $wrapper.hasClass( 'fixed-navigation' ) ) { $wrapper.addClass( 'fixed-navigation' ); $items.fixContainerHeight(); } $items.adaptiveHeight(); $wrapper.css( 'opacity', 1 ); }, 50 ); } ); if ( carouselSettings.theme === 'cards' ) { // To prevent a sizing issue, we need to check if the Cards Carousel // is inside of a Layout Builder, and if so, set the parent container // to overflow hidden. if ( $$.closest( '.widget_siteorigin-panels-builder' ).length ) { const $cell = $$.closest( '.so-panel' ).parent().css( 'overflow', 'hidden' ); } } $items.not( '.slick-initialized' ).slick( { arrows: false, dots: carouselSettings.dots, appendDots: carouselSettings.appendDots ? $$.find( '.sow-carousel-nav' ) : $$, rows: 0, rtl: $$.data( 'dir' ) == 'rtl', touchThreshold: 20, infinite: carouselSettings.loop && ( ! $$.data( 'ajax-url' ) || ( $$.data( 'ajax-url' ) && isContinuous ) ), variableWidth: $$.data( 'variable_width' ), accessibility: false, cssEase: carouselSettings.animation, speed: carouselSettings.animation_speed, slidesToScroll: responsiveSettings.desktop_slides_to_scroll, slidesToShow: typeof responsiveSettings.desktop_slides_to_show == 'undefined' ? responsiveSettings.desktop_slides_to_scroll : responsiveSettings.desktop_slides_to_show, responsive: [ { breakpoint: responsiveSettings.tablet_portrait_breakpoint, settings: { slidesToScroll: responsiveSettings.tablet_portrait_slides_to_scroll, slidesToShow: typeof responsiveSettings.tablet_portrait_slides_to_show == 'undefined' ? responsiveSettings.tablet_portrait_slides_to_scroll : responsiveSettings.tablet_portrait_slides_to_show, } }, { breakpoint: responsiveSettings.mobile_breakpoint, settings: { slidesToScroll: responsiveSettings.mobile_slides_to_scroll, slidesToShow: typeof responsiveSettings.mobile_slides_to_show == 'undefined' ? responsiveSettings.mobile_slides_to_scroll : responsiveSettings.mobile_slides_to_show, } }, ], autoplay: ! isBlockEditor && isContinuous, autoplaySpeed: 0, } ); // Clear the pre-fill width if one is set. if ( carouselSettings.item_overflow ) { $items.css( 'width', '' ); $items.css( 'opacity', '' ); } // Trigger navigation click on swipe $items.on( 'swipe', function( e, slick, direction ) { $$.parent().parent().find( '.sow-carousel-' + ( direction == 'left' ? 'next' : 'prev' ) ).trigger( 'touchend' ); } ); // Set up Autoplay. We use a custom autoplay rather than the Slick // autoplay to account for the (sometimes) non-standard nature // of our navigation that Slick has trouble accounting for. if ( carouselSettings.autoplay && carouselSettings.autoplay !== 'off' ) { var interrupted = false; // Check if this is a Block Editor preview or continuous autoplay is enabled. // If either are true, don't setup (this) autoplay. if ( isBlockEditor || isContinuous ) { return; } setInterval( function() { if ( ! interrupted ) { handleCarouselNavigation( true, false ); } }, carouselSettings.autoplaySpeed ); if ( carouselSettings.pauseOnHover ) { $items.on('mouseenter.slick', function() { interrupted = true; } ); $items.on( 'mouseleave.slick', function() { interrupted = false; } ); } } var handleCarouselNavigation = function( nextSlide, refocus ) { const $items = $$.find( '.sow-carousel-items' ); const navigationContainer = $$.parent().parent(); const currentSlide = $items.slick( 'slickCurrentSlide' ); const numItems = $items.find( '.sow-carousel-item' ).length; const complete = numItems >= $$.data( 'item_count' ); const numVisibleItems = Math.floor( $items.outerWidth() / $items.find( '.sow-carousel-item' ).outerWidth( true ) ); let slidesToScroll = $items.slick( 'slickGetOption', 'slidesToScroll' ); let lastPosition = numItems - numVisibleItems; let loading = $$.data( 'fetching' ); let preloaded = $$.data( 'preloaded' ); let loadMorePosts = false; if ( ! complete && ! preloaded && ( currentSlide + numVisibleItems >= numItems - 1 || currentSlide + ( slidesToScroll * 2 ) > lastPosition ) ) { // For Ajax Carousels, check if we need to fetch the next batch of items. loadMorePosts = true; } // Enable/disable navigation buttons as needed. if ( ! $$.data( 'carousel_settings' ).loop ) { const direction = $$.data( 'dir' ) == 'ltr' ? 'previous' : 'next'; if ( currentSlide == 0 ) { navigationContainer.find( `.sow-carousel-${ direction }` ) .removeClass( 'sow-carousel-disabled' ) .removeAttr( 'aria-disabled' ); } else if ( ! nextSlide && currentSlide - slidesToScroll == 0 ) { navigationContainer.find( `.sow-carousel-${ direction }` ) .addClass( 'sow-carousel-disabled' ) .attr( 'aria-disabled', 'true' ); } } // A custom navigation is used due to a Slick limitation that prevents the slide from stopping // the slide from changing and wanting to remain consistent with the previous carousel. // https://github.com/kenwheeler/slick/pull/2104 // // The Slick Infinite setting has a positioning bug that can result in the first item // being hidden so we need to manually handle that // https://github.com/kenwheeler/slick/issues/3567 if ( nextSlide ) { // If we're already loading posts, don't do anything. if ( loading && ! preloaded ) { return; } // Check if this is the last slide, and we need to loop if ( complete && currentSlide >= lastPosition ) { if ( $$.data( 'carousel_settings' ).loop ) { $items.navigateToSlide( 0 ); } // If slidesToScroll is higher than the the number of visible items, go to the last item. } else if ( $$.data( 'widget' ) == 'post' && $$.data( 'carousel_settings' ).theme == 'undefined' && slidesToScroll >= numVisibleItems ) { // There's more slides than items, update Slick settings to allow for scrolling of partially visible items. $items.slick( 'slickSetOption', 'slidesToShow', numVisibleItems ); $items.slick( 'slickSetOption', 'slidesToScroll', numVisibleItems ); $items.navigateToSlide( 'slickNext' ); // Check if the number of slides to scroll exceeds lastPosition, go to the last slide, or } else if ( currentSlide + slidesToScroll > lastPosition ) { $items.setSlideTo( lastPosition ); $items.navigateToSlide( null ); // Is the current slide a non-standard slideToScroll? } else if ( currentSlide % slidesToScroll !== 0 ) { // We need to increase the slidesToScroll temporarily to // bring it back line with the slidesToScroll. $items.slick( 'slickSetOption', 'slidesToScroll', slidesToScroll + 1 ); $items.navigateToSlide( 'slickNext' ); $items.slick( 'slickSetOption', 'slidesToScroll', slidesToScroll ); } else { $items.navigateToSlide( 'slickNext' ); } // Have we just scrolled to the last slide, and is looping disabled?. // If so, disable the next button. if ( currentSlide == lastPosition && ! $$.data( 'carousel_settings' ).loop ) { navigationContainer.find( '.sow-carousel-next' ) .addClass( 'sow-carousel-disabled' ) .attr( 'aria-disabled', 'true' ); } } else { let slickPrev = false; if ( $$.data( 'widget' ) === 'post' ) { if ( $$.data( 'carousel_settings' ).loop && currentSlide === 0 ) { // Determine lastPosition based on the 'complete' flag lastPosition = complete ? numItems : lastPosition; loadMorePosts = ! complete; $items.navigateToSlide( lastPosition ); } else if ( currentSlide <= slidesToScroll ) { $items.navigateToSlide( 0 ); } else { slickPrev = true; } } else { slickPrev = true; } if ( slickPrev ) { $items.navigateToSlide( 'slickPrev' ); const next = navigationContainer.find( '.sow-carousel-next' ); if ( next.hasClass( 'sow-carousel-disabled' ) ) { next.removeClass( 'sow-carousel-disabled' ) .removeAttr( 'aria-disabled' ); } } } // Post Carousel update dot navigation active item. if ( carouselSettings.dots && $$.data( 'widget' ) == 'post' ) { $$.find( 'li.slick-active' ).removeClass( 'slick-active' ); $$.find( '.slick-dots li' ).eq( Math.ceil( $$.find( '.sow-carousel-items' ).slick( 'slickCurrentSlide' ) / slidesToScroll ) ).addClass( 'slick-active' ); } // Do we need to load more posts? if ( loadMorePosts ) { $( sowb ).trigger( 'carousel_load_new_items', [ $$, $items, refocus ] ); } } if ( ! carouselSettings.loop && $items.slick( 'slickCurrentSlide' ) == 0 ) { const direction = $$.data( 'dir' ) == 'ltr' ? 'previous' : 'next'; $$.parent().parent().find( `.sow-carousel-${ direction }` ) .addClass( 'sow-carousel-disabled' ) .attr( 'aria-disabled', 'true' ); } // Click is used instead of Slick's beforeChange or afterChange events // due to the inability to stop a slide from changing. $$.parent().parent().find( '.sow-carousel-previous, .sow-carousel-next' ).on( 'click touchend', function( e, refocus ) { e.preventDefault(); if ( ! $( this ).hasClass( 'sow-carousel-disabled' ) ) { handleCarouselNavigation( $( this ).hasClass( 'sow-carousel-next' ), refocus ) } } ); if ( carouselSettings.dots && ( $$.data( 'variable_width' ) || $$.data( 'carousel_settings' ).theme ) ) { // Unbind base Slick Dot Navigation as we use a custom event to prevent blank spaces. $$.find( '.slick-dots li' ).off( 'click.slick' ); $$.find( '.slick-dots li' ).on( 'click touchend', function( e ) { $$.carouselDotNavigation( e ); } ); // Setup Slick Dot Navigation again when new posts are added. $( sowb ).on( 'carousel_posts_added', function( e, carousel) { const $$ = $( carousel ); const $dots = $$.find( '.slick-dots li' ); if ( $dots ) { $dots .off( 'click touchend' ) .on( 'click touchend', function( e ) { $$.carouselDotNavigation( e ); } ); } triggerResize( $$.find( '.sow-carousel-items.slick-initialized' ), $$.data( 'carousel_settings' ) ); } ); } } ); $( sowb ).trigger( 'carousel_setup' ); // Keyboard Navigation of carousel navigation. $( document ).on( 'keydown', '.sow-carousel-navigation a', function( e ) { if ( e.keyCode != 13 && e.keyCode != 32 ) { return; } e.preventDefault(); $( this ).trigger( 'click' ); } ); // Keyboard Navigation of carousel items. $( document ).on( 'keyup', '.sow-carousel-item', function( e ) { // Was enter pressed? if ( e.keyCode == 13 ) { $( this ).find( 'h3 a' )[0].click(); } // Ensure left/right key was pressed if ( e.keyCode != 37 && e.keyCode != 39 ) { return; } var $wrapper = $( this ).parents( '.sow-carousel-wrapper' ), $items = $wrapper.find( '.sow-carousel-items' ), numItems = $items.find( '.sow-carousel-item' ).length, itemIndex = $( this ).data( 'slick-index' ), lastPosition = numItems - ( numItems === $wrapper.data( 'item_count' ) ? 0 : 1 ); if ( e.keyCode == 37 ) { itemIndex--; if ( itemIndex < 0 ) { itemIndex = lastPosition; } } else if ( e.keyCode == 39 ) { itemIndex++; if ( itemIndex >= lastPosition ) { if ( $wrapper.data( 'fetching' ) ) { return; // Currently loading new items. } $wrapper.parent().find( '.sow-carousel-next' ).trigger( 'click', true ); } } $items.navigateToSlide( itemIndex ); $wrapper.find( '.sow-carousel-item' ).prop( 'tabindex', -1 ); $wrapper.find( '.sow-carousel-item[data-slick-index="' + itemIndex + '"]' ) .trigger( 'focus' ) .prop( 'tabindex', 0 ); } ); /** * Updates Slick carousel based on current resolution, and * conditionally triggers a fixed container height refresh if needed. * * @this {jQuery} The current carousel wrapper. */ const handleCarouselResize = function() { const $$ = $( this ); const $items = $$.find( '.sow-carousel-items.slick-initialized' ); if ( ! $items.length ) { return; } const responsive = $$.data( 'responsive' ); const settings = $$.data( 'carousel_settings' ); const breakpoints = [ { query: `(min-width: ${ responsive.tablet_landscape_breakpoint }px)`, show: responsive.desktop_slides_to_show, scroll: responsive.desktop_slides_to_scroll }, { query: `(min-width: ${ responsive.tablet_portrait_breakpoint }px) and (max-width: ${ responsive.tablet_landscape_breakpoint }px) and (orientation: landscape)`, show: responsive.tablet_landscape_slides_to_show, scroll: responsive.tablet_landscape_slides_to_scroll }, { query: `(min-width: ${ responsive.mobile_breakpoint }px) and (max-width: ${responsive.tablet_portrait_breakpoint}px)`, show: responsive.tablet_portrait_slides_to_show, scroll: responsive.tablet_portrait_slides_to_scroll }, { query: `(max-width: ${ responsive.mobile_breakpoint }px)`, show: responsive.mobile_slides_to_show, scroll: responsive.mobile_slides_to_scroll } ]; // Conditionally update Slick settings based on current resolution. breakpoints.some( breakpoint => { if ( window.matchMedia( breakpoint.query ).matches ) { $items.slick( 'slickSetOption', 'slidesToShow', breakpoint.show ); $items.slick( 'slickSetOption', 'slidesToScroll', breakpoint.scroll ); return true; } return false; } ); if ( $items.data( 'adaptive_height' ) ) { window.requestAnimationFrame(() => { $items.adaptiveHeight(); if ( settings.theme === 'cards' && ! settings.dynamic_navigation ) { $items.fixContainerHeight(); } } ); } }; let resizeTimeout; $( window ).on( 'resize load', () => { clearTimeout( resizeTimeout ); resizeTimeout = setTimeout( () => { $( '.sow-carousel-wrapper' ).each( handleCarouselResize ); }, 100 ); $( '.sow-carousel-item:first-of-type' ).prop( 'tabindex', 0 ); } ).trigger( 'resize' ); }; sowb.setupCarousel(); $( sowb ).on( 'setup_widgets', sowb.setupCarousel ); } ); window.sowb = sowb;
[-] jquery.cycle.min.js
[edit]
[-] sow.jquery.fittext.js
[edit]
[-] jquery.cycle.swipe.js
[edit]
[-] jquery.touchSwipe.js
[edit]
[+]
lib
[+]
slider
[-] sow.jquery.fittext.min.js
[edit]
[-] jquery.cycle.js
[edit]
[-] sow.google-map.js
[edit]
[-] sow.google-map.min.js
[edit]
[-] carousel.min.js
[edit]
[+]
..
[-] jquery.touchSwipe.min.js
[edit]
[-] carousel.js
[edit]
[-] jquery.cycle.swipe.min.js
[edit]