1/** 2 * Zollu Star Module 3 * Handles all user library and article starring functionality. 4 */ 5const ZolluStar = (function () { 6 // Private variables 7 8 let cache = {}; 9 10 /** 11 * Initialize the star functionality 12 */ 13 function init() { 14 15 // Initialize only if the user is logged in 16 if (isUserLoggedIn()) { 17 initUserLibrary(); 18 } 19 } 20 21 /** 22 * Cache DOM elements 23 */ 24 function cacheDOMElements() { 25 cache = { 26 $userProjectProcessModal: $('#user_project_process_modal'), 27 $userProjectModalContent: $('#user_project_modal_content'), 28 $userProjectModalFavoriteContent: $('#user_project_modal_favorite_content'), 29 $body: $("body") 30 }; 31 } 32 33 /** 34 * Initialize user library functionality 35 */ 36 function initUserLibrary() { 37 // Cache frequently used DOM elements 38 cacheDOMElements(); 39 40 // Show library stars 41 $('.library-star-o').removeClass("d-none"); 42 $('.add-item-block').removeClass("d-none"); 43 44 // Attach event handlers 45 initEventHandlers(); 46 47 // Update initial article states 48 updateArticleStates(); 49 50 // Handle mobile view for project creation 51 handleMobileProjectCreation(); 52 } 53 54 /** 55 * Initialize all event handlers 56 */ 57 function initEventHandlers() { 58 cache.$body.on('click', '.fetch-user-projects', function () { 59 handleFetchUserProjects($(this)); 60 }); 61 62 cache.$body.on('click', '.add-article-item', function () { 63 handleAddArticleItem($(this)); 64 }); 65 66 cache.$body.on('click', '.favorite-process', function () { 67 handleFavoriteProcess($(this)); 68 }); 69 70 $(window).on('resize', handleMobileProjectCreation); 71 } 72 73 /** 74 * Handle fetching user projects 75 * @param {jQuery} $button - The clicked button element 76 */ 77 function handleFetchUserProjects($button) { 78 $('#favorite-star, #favorite-star-o').addClass('kt-hidden'); 79 $('#favorite-spinner').removeClass('kt-hidden'); 80 81 if (canUseFollowerFeature(getUserInfo().username) && getUserInfo().verification === 1) { 82 $.ajax({ 83 type: "GET", 84 url: $button.attr('data-url'), 85 success: function (data) { 86 cache.$userProjectModalContent.html(data.html); 87 } 88 }); 89 90 $('.modal-create-resarch').removeClass('d-none'); 91 $('#modal-favorite-action').addClass('upl-modal__favorites-wrap--bordered'); 92 } else { 93 $('#kt-scroll-area').remove(); 94 cache.$userProjectModalFavoriteContent.removeClass('modal-custom-padding'); 95 } 96 97 $.ajax({ 98 type: "GET", 99 url: $button.attr('data-href'), 100 success: function (data) { 101 cache.$userProjectModalFavoriteContent.html(data.html); 102 cache.$userProjectProcessModal.modal('show'); 103 } 104 }); 105 } 106 107 /** 108 * Handle adding an article item to the library 109 * @param {jQuery} $button - The clicked button element 110 */ 111 function handleAddArticleItem($button) { 112 $.ajax({ 113 type: "GET", 114 url: $button.attr('data-href'), 115 success: function (data) { 116 cache.$userProjectModalContent.html(data.html); 117 updateArticleStates(); 118 } 119 }); 120 } 121 122 /** 123 * Handle the favorite/unfavorite process 124 * @param {jQuery} $button - The clicked button element 125 */ 126 function handleFavoriteProcess($button) { 127 $('#favorite-star, #favorite-star-o').addClass('kt-hidden'); 128 $('#favorite-spinner').removeClass('kt-hidden'); 129 130 const url = $button.attr('data-href'); 131 $.ajax({ 132 type: "GET", 133 url: url, 134 success: function (data) { 135 cache.$userProjectModalFavoriteContent.html(data.html); 136 $('#favorite-star, #favorite-star-o').removeClass('kt-hidden'); 137 $('#favorite-spinner').addClass('kt-hidden'); 138 updateArticleStates(); 139 } 140 }); 141 } 142 143 /** 144 * Update the visual state of articles (starred/unstarred) 145 */ 146 function updateArticleStates() { 147 const $projectActions = $('.article-project-actions'); 148 let article_ids = []; 149 150 $.each($projectActions, function (k, v) { 151 article_ids.push($(v).data('id')); 152 }); 153 154 const distinct = (value, index, self) => { 155 return self.indexOf(value) === index; 156 }; 157 158 const tmpIds = article_ids.filter(distinct); 159 const uniqueIds = tmpIds.filter(el => el != null); 160 161 if (uniqueIds.length > 0) { 162 const url = Routing.generate('app_project_userproject_checkadduserproject', {'article_ids': uniqueIds}); 163 $.post(url, {article_ids: uniqueIds}, function (result) { 164 $.each($projectActions, function (k, v) { 165 const $projectActionsItem = $(v); 166 const articleId = parseInt($projectActionsItem.data('id')); 167 168 if (result['is_added_project'].includes(articleId)) { 169 $projectActionsItem.find('.library-star-o').addClass('d-none'); 170 $projectActionsItem.find('.library-star').removeClass('d-none'); 171 $projectActionsItem.find('.fetch-user-projects').attr({ 172 'title': '', 173 'data-original-title': Translator.trans('title.remove.item.user.library') 174 }); 175 } else { 176 $projectActionsItem.find('.library-star').addClass('d-none'); 177 $projectActionsItem.find('.library-star-o').removeClass('d-none'); 178 $projectActionsItem.find('.fetch-user-projects').attr({ 179 'title': '', 180 'data-original-title': Translator.trans('title.adding.item.user.library') 181 }); 182 } 183 }); 184 }); 185 } 186 } 187 188 /**
189 * Handle responsive adjustments for the project creation modal 190 */ 191 function handleMobileProjectCreation() { 192 const $createProjectButton = $('#modal-create-project'); 193 if (window.innerWidth < 1024) { 194 $createProjectButton.removeAttr('target'); 195 } else { 196 $createProjectButton.attr('target', '_blank'); // Assuming it should have a target on larger screens 197 } 198 } 199 200 // Public API 201 return { 202 init: init 203 }; 204})(); 205 206// Initialize the ZolluStar module when the document is ready 207$(document).ready(function () { 208 ZolluStar.init(); 209});
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.