1/** 2 * Vimeo Feed Load More Functionality 3 * 4 * Handles dynamic loading of additional Vimeo posts with: 5 * - AJAX loading of additional posts 6 * - Masonry layout support 7 * - Clone-based template system 8 * - Individual module state management 9 * - Comprehensive error handling 10 * 11 * @since 1.0.0 12 * @package DiviSocialFeed 13 */ 14 15jQuery(document).ready(function ($) { 16 // Initialize load more functionality for each instance 17 $(".dsf_vm_load_more").each(function () { 18 let button = $(this); 19 let blockId = button.data("object"); 20 let feedContainer = $("#" + blockId); 21 22 // Validate container existence 23 if (!feedContainer.length) { 24 console.warn(`Feed container with ID '${blockId}' not found.`); 25 return; 26 } 27 28 // Store nextCursor individually for each module 29 feedContainer.data("nextCursor", ""); 30 31 // Click handler for load more button 32 button.on("click", function () { 33 // Get configuration parameters 34 let perPage = button.data("per-page"); 35 let captionLength = button.data("caption-length"); 36 let originalText = button.text(); 37 let nextCursor = feedContainer.data("nextCursor"); // Get stored cursor 38 39 // AJAX request to load more posts 40 $.ajax({
41 url: dsf_vm_ajax.ajax_url, 42 type: "POST", 43 data: { 44 action: "dsf_vm_load_more", 45 nonce: dsf_vm_ajax.nonce, 46 block_id: blockId, 47 perpage: perPage, 48 next_cursor: nextCursor, 49 }, 50 51 /** 52 * Before sending the request 53 */ 54 beforeSend: function () { 55 console.log(`Loading more posts for ${blockId}...`); 56 button.prop("disabled", true).text("Loading..."); 57 }, 58 59 /** 60 * Successful response handler 61 * @param {object} response AJAX response containing new posts 62 */ 63 success: function (response) { 64 if (response.success && response.data.media.length > 0) { 65 // Initialize media array if it doesn't exist 66 if (!window[blockId]) { 67 window[blockId] = { media: [] }; 68 } 69 70 // Append new media to existing array 71 window[blockId].media = window[blockId].media.concat(response.data.media); 72 73 // Update the next cursor for pagination 74 feedContainer.data("nextCursor", response.data.next_cursor); 75 76 // Get the first article as template for cloning 77 let existingArticle = feedContainer.find(".dsf_vm_feed_item").first(); 78 79 if (existingArticle.length) { 80 // Process each new post 81 $.each(response.data.media, function (index, post) { 82 let newArticle = existingArticle.clone(); 83 84 // Important: remove inline styles from the clone 85 newArticle.removeAttr("style"); 86 87 // Set custom attributes 88 newArticle.attr("data-id", post.video_id); 89 newArticle.attr("data-link", post.video_url); 90 newArticle.attr("data-object", blockId); 91 92 // Update media source (handles both images and videos) 93 let img = newArticle.find("img.vimeo-feed__media"); 94 if (img.length) { 95 img.attr("src", post.thumbnails || ""); 96 } 97 98 // Update Vimeo iframe video 99 let iframeWrapper = newArticle.find(".dsf_vm_post_iframe"); 100 101 if (iframeWrapper.length && post.video_id) { 102 const vimeoId = post.video_id; 103 const videoUrl = `https://player.vimeo.com/video/${vimeoId}?autoplay=0&muted=1&loop=1&title=0&byline=0&portrait=0`; 104 105 iframeWrapper.html(` 106 <iframe 107 src="${videoUrl}" 108 class="vimeo-feed__media" 109 frameborder="0" 110 allow="autoplay; fullscreen; picture-in-picture" 111 allowfullscreen 112 loading="lazy" 113 ></iframe> 114 `); 115 } 116 117 // Update like count display 118 let likeCountElement = newArticle.find(".dsf_vm_like_count .like-count"); 119 if (likeCountElement.length) { 120 likeCountElement.text(post.likes || "0"); 121 } 122 123 // Update comment count display 124 let commentCountElement = newArticle.find(".dsf_vm_comment_count .comment-count"); 125 if (commentCountElement.length) { 126 commentCountElement.text(post.comments || "0"); 127 } 128 129 // Update Views count display 130 let viewsCountElement = newArticle.find(".dsf_vm_views_count .views-count"); 131 if (viewsCountElement.length) { 132 viewsCountElement.text(post.views || "0"); 133 } 134 135 // Update Post Date 136 let postDateDisplay = newArticle.find(".dsf_vm_post_date"); 137 if (postDateDisplay.length) { 138 postDateDisplay.text(post.published_at || "Unknown date"); 139 } 140 141 // Update Post Title 142 let postTitleDisplay = newArticle.find(".dsf_vm_video_title"); 143 if (postTitleDisplay.length) { 144 postTitleDisplay.text(post.title || ""); 145 } 146 147 // Duration Update 148 149 let postDurationDisplay = newArticle.find(".dsf_vm_post_duration"); 150 if (postDurationDisplay.length) { 151 postDurationDisplay.text(post.duration || "0 sec"); 152 } 153 154 155 let captionElement = newArticle.find(".dsf_vm_post_caption"); 156 if (captionElement.length) { 157 captionElement.empty(); // clear old caption 158 159 let fullCaption = post.description || ""; 160 let trimmedCaption = fullCaption.length > captionLength 161 ? fullCaption.substring(0, captionLength) + "â¦" 162 : fullCaption; 163 164 let formattedCaption = trimmedCaption.replace(/\n/g, "<br>"); 165 captionElement.html(formattedCaption); 166 } 167 168 // Append the new post to the container 169 feedContainer.append(newArticle); 170 171 // Trigger Isotope/Masonry layout update only if it's masonry layout 172 if (feedContainer.hasClass("dsf_vm_grid_masonry")) { 173 feedContainer.imagesLoaded(function () { 174 feedContainer.masonry("appended", newArticle); 175 }); 176 } 177 }); 178 179 } else { 180 console.warn(`No existing article found to clone for ${blockId}.`); 181 } 182 // Hide the button if no more data is available 183 if (!response.data.next_cursor) { 184 console.log(`No more posts for ${blockId}.`); 185 button.hide(); 186 } else { 187 button.text(originalText); 188 } 189 } else { 190 console.warn(`No data received for ${blockId}.`); 191 button.text(originalText); 192 button.hide(); 193 } 194 }, 195 196 /** 197 * Error handler 198 * @param {object} error Error object from AJAX request 199 */ 200 error: function (error) { 201 console.error(`Error loading posts for ${blockId}:`, error); 202 button.text(originalText); 203 }, 204 205 /** 206 * Always execute after request completes 207 */ 208 complete: function () { 209 button.prop("disabled", false); 210 }, 211 }); 212 }); 213 });
vendor: 3 bytes, line 214
214});
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.