1(function ($) { 2 var $page = $('.applied-research-projects-page').first(); 3 var config = window.HCTAppliedResearchProjects || {}; 4 var labels = config.labels || {}; 5 var lang = config.lang || 'en'; 6 var $form; 7 var $search; 8 var $campus; 9 var $dateFrom; 10 var $dateTo; 11 var $researchArea; 12 var $listing; 13 var $status; 14 var $paginationWrap; 15 var $desktopPages; 16 var $mobilePages; 17 var page = 1; 18 var totalPages = 1; 19 var perPage = 10; 20 var activeRequest = null; 21 var searchDebounce = null; 22 23 if (!$page.length) { 24 return; 25 } 26 27 $form = $('#projects-search-form'); 28 $search = $('#project-keyword'); 29 $campus = $('#project-campus'); 30 $dateFrom = $('#project-date-from'); 31 $dateTo = $('#project-date-to'); 32 $researchArea = $('#project-research-area'); 33 $listing = $('#projects-listing'); 34 $status = $('#projects-status'); 35 $paginationWrap = $('#projects-pagination-wrap'); 36 $desktopPages = $('#projects-pagination-pages'); 37 $mobilePages = $('#projects-mobile-pages'); 38 39 if (!$form.length || !$listing.length) { 40 return; 41 } 42 43 function escapeHtml(value) { 44 return $('<div/>').text(value == null ? '' : String(value)).html(); 45 } 46 47 function decodeHtml(value) { 48 return $('<div/>').html(value == null ? '' : String(value)).text(); 49 } 50 51 function isNonEmpty(value) { 52 return typeof value !== 'undefined' && value !== null && String(value).trim() !== ''; 53 } 54 55 function acfValue(item, key) { 56 var value = item && item.acf ? item.acf[key] : ''; 57 58 return isNonEmpty(value) ? String(value) : '-'; 59 } 60 61 function setStatus(message) { 62 if (!message) { 63 $status.addClass('hidden').text(''); 64 return; 65 } 66 67 $status.removeClass('hidden').text(message); 68 } 69 70 function setDisabled($elements, disabled) { 71 $elements 72 .toggleClass('pointer-events-none opacity-50', !!disabled) 73 .attr('aria-disabled', disabled ? 'true' : 'false') 74 .attr('tabindex', disabled ? '-1' : '0'); 75 } 76 77 function buildPageList(current, total) { 78 var pages = []; 79 var start; 80 var end; 81 var i; 82 83 if (total <= 7) { 84 for (i = 1; i <= total; i += 1) { 85 pages.push(i); 86 } 87 88 return pages; 89 } 90 91 pages.push(1); 92 start = Math.max(2, current - 1); 93 end = Math.min(total - 1, current + 1); 94 95 if (current <= 3) { 96 end = 4; 97 } 98 99 if (current >= total - 2) { 100 start = total - 3; 101 } 102 103 if (start > 2) { 104 pages.push('ellipsis-start'); 105 } 106 107 for (i = start; i <= end; i += 1) { 108 pages.push(i); 109 } 110 111 if (end < total - 1) { 112 pages.push('ellipsis-end'); 113 } 114 115 pages.push(total); 116 117 return pages; 118 } 119 120 function renderRows(items) { 121 var html = ''; 122 123 $.each(items, function (index, item) { 124 var title = item && item.title && item.title.rendered ? decodeHtml(item.title.rendered) : '-'; 125 126 html += '<tr>'; 127 html += '<td data-title="' + escapeHtml(labels.project_title || 'Project Title') + '">' + escapeHtml(title) + '</td>'; 128 html += '<td data-title="' + escapeHtml(labels.start_date || 'Start Date') + '">' + escapeHtml(acfValue(item, 'project_start_date')) + '</td>'; 129 html += '<td data-title="' + escapeHtml(labels.end_date || 'End Date') + '">' + escapeHtml(acfValue(item, 'project_end_date')) + '</td>'; 130 html += '<td data-title="' + escapeHtml(labels.duration || 'Duration') + '">' + escapeHtml(acfValue(item, 'duration_project')) + '</td>'; 131 html += '<td data-title="' + escapeHtml(labels.grant_type || 'Grant Type') + '">' + escapeHtml(acfValue(item, 'project_grant_type')) + '</td>'; 132 html += '<td data-title="' + escapeHtml(labels.principal_investigator || 'Principal Investigator') + '">' + escapeHtml(acfValue(item, 'project_principal_investigator')) + '</td>'; 133 html += '<td data-title="' + escapeHtml(labels.division || 'Division') + '">' + escapeHtml(acfValue(item, 'project_division')) + '</td>'; 134 html += '<td data-title="' + escapeHtml(labels.campus || 'Campus') + '">' + escapeHtml(acfValue(item, 'project_campus')) + '</td>'; 135 html += '<td data-title="' + escapeHtml(labels.research_area || 'Research Area') + '">' + escapeHtml(acfValue(item, 'project_research_area')) + '</td>'; 136 html += '</tr>'; 137 }); 138 139 $listing.html(html); 140 } 141 142 function renderMessage(message) { 143 $listing.html('<tr><td colspan="9" class="text-center">' + escapeHtml(message) + '</td></tr>'); 144 $paginationWrap.addClass('hidden'); 145 } 146 147 function renderPagination() { 148 var pages; 149 var html = ''; 150 var isFirst = page <= 1; 151 var isLast = page >= totalPages; 152 153 if (totalPages <= 1) { 154 $paginationWrap.addClass('hidden'); 155 return; 156 } 157 158 $paginationWrap.removeClass('hidden'); 159 $mobilePages.text((labels.page || 'Page') + ' ' + page + ' ' + (labels.of || 'of') + ' ' + totalPages); 160 pages = buildPageList(page, totalPages); 161 162 $.each(pages, function (index, item) { 163 if (typeof item === 'string') { 164 html += '<span class="aegov-pagination-extend">...</span>'; 165 return; 166 } 167 168 if (item === page) { 169 html += '<span aria-current="page" class="aegov-pagination-current">' + escapeHtml(item) + '</span>'; 170 return; 171 } 172 173 html += '<a href="#" class="aegov-pagination-page ' + (item < page ? 'aegov-pagination-smaller' : 'aegov-pagination-larger') + ' js-projects-page-number" title="' + escapeHtml((labels.page || 'Page') + ' ' + item) + '" data-page="' + item + '">' + escapeHtml(item) + '</a>'; 174 }); 175 176 $desktopPages.html(html); 177 178 setDisabled($('.js-projects-page-first, .js-projects-page-prev, .js-projects-page-prev-mobile'), isFirst); 179 setDisabled($('.js-projects-page-next, .js-projects-page-last, .
179js-projects-page-next-mobile'), isLast); 180 } 181 182 function getListing(shouldScroll) { 183 var params = new URLSearchParams(); 184 var request; 185 186 params.set('_embed', '1'); 187 params.set('orderby', 'date'); 188 params.set('order', 'desc'); 189 params.set('per_page', String(perPage)); 190 params.set('page', String(page)); 191 params.append('_fields[]', 'title'); 192 params.append('_fields[]', 'acf.project_start_date'); 193 params.append('_fields[]', 'acf.project_end_date'); 194 params.append('_fields[]', 'acf.duration_project'); 195 params.append('_fields[]', 'acf.project_grant_type'); 196 params.append('_fields[]', 'acf.project_principal_investigator'); 197 params.append('_fields[]', 'acf.project_division'); 198 params.append('_fields[]', 'acf.project_campus'); 199 params.append('_fields[]', 'acf.project_research_area'); 200 201 if (isNonEmpty($search.val())) { 202 params.set('search', $.trim($search.val())); 203 } 204 205 if (isNonEmpty($campus.val())) { 206 params.set('campus', $.trim($campus.val())); 207 } 208 209 if (isNonEmpty($researchArea.val())) { 210 params.set('research_area', $.trim($researchArea.val())); 211 } 212 213 if (isNonEmpty($dateFrom.val())) { 214 params.set('after', $.trim($dateFrom.val()) + 'T00:00:00'); 215 } 216 217 if (isNonEmpty($dateTo.val())) { 218 params.set('before', $.trim($dateTo.val()) + 'T00:00:00'); 219 } 220 221 if (isNonEmpty(lang)) { 222 params.set('lang', lang); 223 } 224 225 if (activeRequest && typeof activeRequest.abort === 'function') { 226 activeRequest.abort(); 227 } 228 229 setStatus(''); 230 231 request = $.ajax({ 232 url: '/wp-json/wp/v2/project?' + params.toString(), 233 method: 'GET', 234 dataType: 'json' 235 }); 236 activeRequest = request; 237 238 request.done(function (data, textStatus, jqXHR) { 239 if (Array.isArray(data) && data.length) { 240 totalPages = Math.max(parseInt(jqXHR.getResponseHeader('X-WP-TotalPages') || '1', 10) || 1, 1); 241 renderRows(data); 242 renderPagination(); 243 244 if (shouldScroll) { 245 $('html, body').animate({ scrollTop: $listing.offset().top - 120 }, 300); 246 } 247 248 return; 249 } 250 251 renderMessage(labels.no_results || 'No results found.'); 252 }); 253 254 request.fail(function (jqXHR, textStatus) { 255 if (textStatus === 'abort') { 256 return; 257 } 258 259 if (jqXHR && jqXHR.status === 400 && page > 1) { 260 page = 1; 261 getListing(false); 262 return; 263 } 264 265 renderMessage(labels.request_failed || 'Unable to load projects.'); 266 }); 267 268 request.always(function () { 269 if (activeRequest === request) { 270 activeRequest = null; 271 } 272 }); 273 } 274 275 function runSearch() { 276 page = 1; 277 getListing(false); 278 } 279 280 $form.on('submit', function (event) { 281 event.preventDefault(); 282 runSearch(); 283 }); 284 285 $search.on('input', function () { 286 clearTimeout(searchDebounce); 287 searchDebounce = setTimeout(runSearch, 300); 288 }); 289 290 $campus.add($researchArea).add($dateFrom).add($dateTo).on('change', runSearch); 291 292 $(document).on('click', '.js-projects-page-number', function (event) { 293 var targetPage = parseInt($(this).data('page'), 10); 294 295 event.preventDefault(); 296 297 if (!targetPage || targetPage === page) { 298 return; 299 } 300 301 page = targetPage; 302 getListing(true); 303 }); 304 305 $('.js-projects-page-first').on('click', function (event) { 306 event.preventDefault(); 307 308 if (page <= 1) { 309 return; 310 } 311 312 page = 1; 313 getListing(true); 314 }); 315 316 $('.js-projects-page-prev, .js-projects-page-prev-mobile').on('click', function (event) { 317 event.preventDefault(); 318 319 if (page <= 1) { 320 return; 321 } 322 323 page -= 1; 324 getListing(true); 325 }); 326 327 $('.js-projects-page-next, .js-projects-page-next-mobile').on('click', function (event) { 328 event.preventDefault(); 329 330 if (page >= totalPages) { 331 return; 332 } 333 334 page += 1; 335 getListing(true); 336 }); 337 338 $('.js-projects-page-last').on('click', function (event) { 339 event.preventDefault(); 340 341 if (page >= totalPages) { 342 return; 343 } 344 345 page = totalPages; 346 getListing(true); 347 }); 348 349 getListing(false); 350})(jQuery);
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.