1/** 2 * Tiktok Feed Slider and Popup Functionality 3 * 4 * Handles: 5 * - Responsive slider/carousel initialization 6 * - Popup modal for post details 7 * - Masonry grid layout 8 * - Media type handling (images, videos, carousels) 9 * 10 * @since 1.0.0 11 * @package DiviSocialFeed 12 */ 13 14// Initialize Tiktok sliders with responsive settings 15jQuery(document).ready(function($) { 16 $('.dsf_vm_slider_wrapper').each(function() { 17 let $this = $(this); 18 /** 19 * Get spacing values from data attributes 20 * Default to 20px if not specified or invalid 21 */ 22 let spacingDesktop = parseInt($this.data('spacing-desktop')) || 20; 23 let spacingTablet = parseInt($this.data('spacing-tablet')) || 20; 24 let spacingMobile = parseInt($this.data('spacing-mobile')) || 20; 25 26 /** 27 * Get column count settings from data attributes 28 * These will be used in the responsive configuration 29 */ 30 let columnDesktop = $this.data('desktop-column'); 31 let columnTablet = $this.data('tablet-column'); 32 let columnPhone = $this.data('phone-column'); 33 34 /** 35 * Initialize Owl Carousel with responsive settings 36 */ 37 $this.find('.owl-carousel.dsf_vm_slider').owlCarousel({ 38 items: 1, // Default number of items 39 loop: true, // Infinite looping 40 nav: true, // Show navigation arrows 41 dots: true, // Show pagination dots 42 autoplay: false, // Disable auto-play by default 43 autoplayTimeout: 3000, // Auto-play interval if enabled 44 navText: ['<span class="prev-arrow">â¹</span>', '<span class="next-arrow">âº</span>'], // Custom arrow icons 45 46 /** 47 * Responsive breakpoint configuration 48 */ 49 responsive: { 50 // Phone viewport 51 0: { 52 items: columnPhone || 1, // Default to 1 item on phone 53 margin: spacingMobile // Use mobile spacing 54 }, 55 // Tablet viewport 56 768: { 57 items: columnTablet || 2, // Default to 2 items on tablet 58 margin: spacingTablet // Use tablet spacing 59 }, 60 // Desktop viewport 61 981: { 62 items: columnDesktop || 3, // Default to 3 items on desktop 63 margin: spacingDesktop // Use desktop spacing 64 } 65 } 66 }); 67 }); 68}); 69 70// Store the next page cursor per container 71// let nextCursor = {}; 72 73/** 74 * Tiktok Popup Modal Functionality 75 * 76 * Handles: 77 * - Post click events 78 * - Media type detection and rendering 79 * - Popup content population 80 * - Popup show/hide functionality 81 */ 82jQuery(document).ready(function ($) { 83 /** 84 * Event delegation for post clicks (works with dynamically added posts) 85 */ 86 $(document).on("click", ".dsf_vm_feed_item", function () { 87 // Get post identification data 88 let postId = $(this).data("id"); 89 let postObject = $(this).data("object"); 90 91 // Validate post data object exists 92 if (typeof window[postObject] === "undefined") { 93 console.error("Tiktok data object not found:", postObject); 94 return; 95 } 96 97 // Find the specific post data 98 let postData = window[postObject].media.find(post => String(post.video_id) === String(postId)); 99 100 if (!postData) { 101 console.error("Post data not found for ID:", postId); 102 return; 103 } 104 105 /** 106 * Cache DOM elements for popup 107 */ 108 let popupLeft = $(".dsf_vm_popup_left"); 109 let popupRight = $(".dsf_vm_popup_right"); 110 let popupVideoContainer = popupLeft.find(".dsf_popup_video_container"); 111 112 // Clear previous content 113 popupVideoContainer.empty().hide(); 114 // User information 115 popupRight.find(".dsf_vm_popup_video_title").text(postData.title || "Unknown Title"); 116 popupRight.find(".dsf_vm_popup_date").text(postData.published_at || ""); 117 118 let caption = postData.description || ""; 119 caption = caption.replace(/\n/g, "<br>"); 120 121 popupRight.find(".dsf_vm_popup_caption").html(caption); 122 123 // Engagement metrics 124 popupRight.find(".dsf_vm_like_count .like-count") 125 .text(postData.likes ?? "0"); 126 127 popupRight.find(".dsf_vm_comment_count .comment-count") 128 .text(postData.comments ?? "0"); 129 130 popupRight.find(".dsf_vm_views_count .views-count") 131 .text(postData.views ?? "0"); 132 133 if (postData.video_id) { 134 const vimeoId = postData.video_id; 135 136 const videoUrl = `https://player.vimeo.com/video/${vimeoId}?autoplay=1&muted=0&loop=1&title=0&byline=0&portrait=0`; 137 138 popupVideoContainer 139 .html(` 140 <div class="dsf-vimeo-embed"> 141 <iframe 142 src="${videoUrl}" 143 frameborder="0" 144 allow="autoplay; fullscreen; picture-in-picture" 145 allowfullscreen 146 ></iframe> 147 </div> 148 `) 149 .show(); 150 } 151 152 // Show the popup 153 $(".dsf_vm_popup").fadeIn(function () { 154 $("body").addClass("dsf-popup-open"); //Add class when popup opens 155 }); 156 });
157 158 /** 159 * Popup close handlers 160 */ 161 $(document).on("click", ".dsf_vm_popup_close", function () { 162 $(".dsf_vm_popup").fadeOut(function () { 163 stopVideoPlayback(); 164 $("body").removeClass("dsf-popup-open"); // Remove class when popup closes 165 }); 166 }); 167 168 $(document).on("click", function (e) { 169 if ($(e.target).hasClass("dsf_vm_popup")) { 170 stopVideoPlayback(); 171 $(".dsf_vm_popup").fadeOut(function () { 172 $("body").removeClass("dsf-popup-open"); // Remove class when popup closes 173 }); 174 } 175 }); 176 177 /** 178 * Helper function to stop video playback by removing the iframe 179 */ 180 function stopVideoPlayback() { 181 let popupVideoContainer = $(".dsf_popup_video_container"); 182 popupVideoContainer.empty(); 183 } 184}); 185 186 jQuery(document).ready(function ($) { 187 $(".dsf_vm_post_caption").each(function () { 188 let text = $(this).text(); 189 // Replace the literal <br /> (or <br>) text with actual line breaks 190 text = text.replace(/<br\s*\/?>/gi, "<br>"); 191 $(this).html(text); 192 }); 193}); 194 195/** 196 * Masonry Grid Layout Initialization 197 * 198 * Sets up the masonry layout for grid displays 199 */ 200 201jQuery(document).ready(function ($) { 202 var $grid = $('.dsf_vm_grid_masonry'); 203 204 // wait until images are loaded 205 $grid.imagesLoaded(function () { 206 $grid.masonry({ 207 itemSelector: '.dsf_vm_feed_item', 208 columnWidth: '.grid-sizer', 209 gutter: '.gutter-sizer', 210 percentPosition: true 211 }); 212 }); 213});
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.