jQuery( function ( $ ) { // The carousel widget $( '.sow-carousel-wrapper' ).each( function () { var $$ = $( this ), $postsContainer = $$.closest( '.sow-carousel-container' ), $container = $$.closest( '.sow-carousel-container' ).parent(), $itemsContainer = $$.find( '.sow-carousel-items' ), $items = $$.find( '.sow-carousel-item' ), $firstItem = $items.eq( 0 ); var position = 0, page = 1, fetching = false, numItems = $items.length, totalPosts = $$.data( 'found-posts' ), complete = numItems === totalPosts, itemWidth = ( $firstItem.width() + parseInt( $firstItem.css( 'margin-right' ) ) ), isRTL = $postsContainer.hasClass( 'js-rtl' ), updateProp = isRTL ? 'margin-right' : 'margin-left'; var updatePosition = function () { if ( position < 0 ) position = 0; if ( position >= $$.find( '.sow-carousel-item' ).length - 1 ) { position = $$.find( '.sow-carousel-item' ).length - 1; // Fetch the next batch if ( !fetching && !complete ) { fetching = true; page++; $itemsContainer.append( '' ); var instanceHash = $container.find( 'input[name="instance_hash"]' ).val(); $.get( $$.data( 'ajax-url' ), { query: $$.data( 'query' ), action: 'sow_carousel_load', paged: page, instance_hash: instanceHash, }, function ( data, status ) { var $items = $( data.html ); $items.appendTo( $itemsContainer ).hide().fadeIn(); $$.find( '.sow-carousel-loading' ).remove(); numItems = $$.find( '.sow-carousel-item' ).length; complete = numItems === totalPosts; fetching = false; } ) } } $itemsContainer.css( 'transition-duration', "0.45s" ); $itemsContainer.css( updateProp, -( itemWidth * position) + 'px' ); }; $container.on( 'click', 'a.sow-carousel-previous', function ( e ) { e.preventDefault(); position -= isRTL ? -1 : 1; updatePosition(); } ); $container.on( 'click', 'a.sow-carousel-next', function ( e ) { e.preventDefault(); position += isRTL ? -1 : 1; updatePosition(); } ); // Verify "swipe" method exists prior to invoking it. if ( 'function' === typeof $$.swipe ) { var validSwipe = false; var prevDistance = 0; var startPosition = 0; var velocity = 0; var prevTime = 0; var posInterval; var negativeDirection = isRTL ? 'right' : 'left'; var setNewPosition = function ( newPosition ) { if ( newPosition < 50 && newPosition > -( itemWidth * numItems ) ) { $itemsContainer.css( 'transition-duration', "0s" ); $itemsContainer.css( updateProp, newPosition + 'px' ); return true; } return false; }; var setFinalPosition = function () { var finalPosition = parseInt( $itemsContainer.css( updateProp ) ); position = Math.abs( Math.round( finalPosition / itemWidth ) ); updatePosition(); }; $$.on( 'click', '.sow-carousel-item a', function ( event ) { if ( validSwipe ) { event.preventDefault(); validSwipe = false; } } ); $$.swipe( { excludedElements: "", triggerOnTouchEnd: true, threshold: 75, swipeStatus: function ( event, phase, direction, distance, duration, fingerCount, fingerData ) { if ( direction === 'up' || direction === 'down' ) { return false; } if ( phase === "start" ) { startPosition = -( itemWidth * position); prevTime = new Date().getTime(); clearInterval( posInterval ); } else if ( phase === "move" ) { if ( direction === negativeDirection ) distance *= -1; setNewPosition( startPosition + distance ); var newTime = new Date().getTime(); var timeDelta = (newTime - prevTime) / 1000; velocity = (distance - prevDistance) / timeDelta; prevTime = newTime; prevDistance = distance; } else if ( phase === "end" ) { validSwipe = true; if ( direction === negativeDirection ) distance *= -1; if ( Math.abs( velocity ) > 400 ) { velocity *= 0.1; var startTime = new Date().getTime(); var cumulativeDistance = 0; posInterval = setInterval( function () { var time = (new Date().getTime() - startTime) / 1000; cumulativeDistance += velocity * time; var newPos = startPosition + distance + cumulativeDistance; var decel = 30; var end = (Math.abs( velocity ) - decel) < 0; if ( direction === negativeDirection ) { velocity += decel; } else { velocity -= decel; } if ( end || !setNewPosition( newPos ) ) { clearInterval( posInterval ); setFinalPosition(); } }, 20 ); } else { setFinalPosition(); } } else if ( phase === "cancel" ) { updatePosition(); } } } ); } } ); } );