1jQuery(document).ready(function($) { 2 var $track = $('.kraken-timeline-track'); 3 var $items = $('.kraken-timeline-item'); 4 var $progress = $('.timeline-progress'); // The progress bar element 5 var $border = $('.timeline-border'); // The border element 6 var itemWidth = $items.outerWidth(true); 7 var totalItems = $items.length; 8 var currentPosition = 0; 9 var touchStartX = 0; 10 var touchEndX = 0; 11 12 // Set the width of the kraken-timeline-track and timeline-border based on the number of items 13 var trackWidth = itemWidth * totalItems; 14 $track.css('width', trackWidth + 'px'); 15 $border.css('width', trackWidth + 'px'); 16 17 // Add CSS for smooth transition 18 $track.css({ 19 'transition': 'transform 0.6s ease' 20 }); 21 $border.css({ 22 'transition': 'transform 0.6s ease' 23 }); 24 25 $progress.css({ 26 'transition': 'width 0.6s ease' 27 }); 28 29 function updateControls() { 30 $('#kraken-prev-button').prop('disabled', currentPosition === 0); 31 $('#kraken-next-button').prop('disabled', currentPosition === totalItems - 1); 32 } 33 34 function updateProgressBar() { 35 var activeItem = $items.eq(currentPosition); 36 var progressWidth = activeItem.position().left + (activeItem.outerWidth(true) / 2); 37 $progress.css('width', progressWidth + 'px'); 38 } 39 40 function loadTimelineContent(postId) { 41 $.ajax({ 42 url: KrakenTimelineAjax.ajaxurl, 43 type: 'POST', 44 data: { 45 action: 'load_timeline_content', 46 post_id: postId, 47 }, 48 success: function(response) { 49 $('.kraken-timeline-content').html(response); 50 $items.removeClass('active'); 51 $('[data-post-id="' + postId + '"]').addClass('active'); 52 updateProgressBar(); // Update the progress bar when content is loaded 53 } 54 }); 55 } 56 57 function moveToPosition(newPosition) { 58 if (newPosition >= 0 && newPosition < totalItems) { 59 currentPosition = newPosition; 60 61 var activeItem = $items.eq(newPosition); 62 $items.attr('aria-selected', 'false'); // Deselect all items 63 activeItem.attr('aria-selected', 'true'); // Select the current item 64 65 var activeItemLeft = activeItem.position().left; 66 var activeItemRight = activeItemLeft + activeItem.outerWidth(true); 67 68 var trackScrollLeft = Math.abs(parseInt($track.css('transform').split(',')[4]) || 0); // Get the current scroll position 69 70 // Check if the new item is out of view 71 if (activeItemLeft < trackScrollLeft || activeItemRight > trackScrollLeft + $('.kraken-timeline-container').width()) { 72 var offset = -(newPosition * itemWidth); 73 $track.css('transform', 'translateX(' + offset + 'px)'); 74 $border.css('transform', 'translateX(' + offset + 'px)'); // Sync border with track 75 } 76 77 updateProgressBar(); // Update the progress bar after moving 78 79 var postId = $items.eq(currentPosition).data('post-id'); 80 loadTimelineContent(postId); 81 82 updateControls(); 83 $items.eq(currentPosition).focus(); // Set focus to the new item 84 } 85 } 86 87 $items.click(function() { 88 var postId = $(this).data('post-id'); 89 var newPosition = $(this).index(); 90 91 // If the clicked position is not the same as the current one, update the timeline 92 if (newPosition !== currentPosition) { 93 moveToPosition(newPosition); 94 } else { 95 // Even if it's the same, ensure the timeline content is updated 96 loadTimelineContent(postId); 97 } 98 }); 99 100 $('#kraken-prev-button').click(function() { 101 if (currentPosition > 0) { 102 moveToPosition(currentPosition - 1); 103 } 104 }); 105 106 $('#kraken-next-button').click(function() { 107 if (currentPosition < totalItems - 1) { 108 moveToPosition(currentPosition + 1); 109 } 110 }); 111 112 // Swipe handling 113 $('.kraken-timeline-content').on('touchstart', function(event) { 114 touchStartX = event.originalEvent.touches[0].clientX; 115 }); 116 117 $('.kraken-timeline-content').on('touchmove', function(event) { 118 touchEndX = event.originalEvent.touches[0].clientX; 119 }); 120 121 $('.kraken-timeline-content').on('touchend', function() { 122 if (touchEndX < touchStartX) { 123 // Swipe left 124 if (currentPosition < totalItems - 1) { 125 moveToPosition(currentPosition + 1); 126 } 127 } else if (touchEndX > touchStartX) { 128 // Swipe right 129 if (currentPosition > 0) { 130 moveToPosition(currentPosition - 1); 131 } 132 } 133 }); 134 135 // Keyboard navigation for accessibility 136 $items.attr('tabindex', '0'); // Make each item tabbable 137 138 $(document).on('keydown', function(e) { 139 if (e.key === 'ArrowRight' || e.key === 'Tab' && !e.shiftKey) { 140 // Move to the next item 141 if (currentPosition < totalItems - 1) { 142 moveToPosition(currentPosition + 1); 143 e.preventDefault(); // Prevent default behavior of the Tab and Arrow key 144 } 145 } else if (e.key === 'ArrowLeft' || e.key === 'Tab' && e.shiftKey) { 146 // Move to the previous item 147 if (currentPosition > 0) { 148 moveToPosition(currentPosition - 1); 149 e.preventDefault(); // Prevent default behavior of the Shift+Tab and Arrow key 150 } 151 } 152 }); 153 154 // Ensure initial state is set correctly 155 var initialPostId = $('.kraken-timeline-content').data('initial-post-id'); 156 if (initialPostId) { 157 loadTimelineContent(initialPostId); 158 } 159 160 // Initialize controls and progress bar 161 updateProgressBar(); 162 updateControls(); 163});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.