1$(function () { 2 const $drpWhatsOn = $(".drpWhatsOn"); 3 4 if ($drpWhatsOn.length) { 5 dayjs.extend(window.dayjs_plugin_customParseFormat); 6 7 function initializeDateRangePicker() { 8 // Detect if the device is mobile 9 const isMobile = window.innerWidth <= 768; // Adjust this width as needed for mobile detection 10 11 // To set the minimum date to be today 12 const today = dayjs().subtract(1, "day").toDate(); 13 14 // Check if the HTML direction is RTL 15 const isRtl = $("html").attr("dir") === "rtl"; 16 17 const optionsDrpWhatsOn = { 18 locale: isRtl ? "ar-AE" : "en-US", // Set locale based on direction 19 minDate: today, 20 startName: "startDate", 21 endName: "endDate", 22 weekdayFormat: isRtl? "short" : 3, 23 inputReadOnly: true, 24 placeholder: isRtl? "Ù Ù , Ø¥ÙÙ" : "From, To", 25 showAdjacementDays: false, 26 calendars: isMobile ? 1 : 2, // Set calendars to 1 for mobile, 2 otherwise 27 inputDateFormat: (date) => 28 dayjs(date).locale("en").format("DD-MMM-YYYY"), 29 inputDateParse: (date) => dayjs(date, "DD-MMM-YYYY", "en").toDate(), 30 }; 31 32 // Initialize the Date Range Picker with the updated options 33 new coreui.DateRangePicker($drpWhatsOn[0], optionsDrpWhatsOn); 34 } 35 36 // Initialize Date Range Picker on page load 37 initializeDateRangePicker(); 38 } 39 40 // Helper function to get base URL up to /list/ 41 function getBaseUrl() { 42 var currentUrl = window.location.href; 43 if (currentUrl.indexOf('/list/') === -1) { 44 currentUrl = currentUrl.replace('/whats-on/', '/whats-on/list/'); 45 } 46 return currentUrl.split("/list/")[0] + "/list/"; 47 } 48 49 // Helper function to parse current filters from URL 50 function getCurrentFilters() { 51 var currentUrl = window.location.href; 52 var filters = { 53 eventType: null, 54 location: null, 55 learnType: null, 56 ageRange: null, 57 lang: null, 58 date: null 59 }; 60 61 // Check if we have the new filter structure 62 if (currentUrl.indexOf("/filter/") !== -1) { 63 var filterPart = currentUrl.split("/filter/")[1]; 64 if (filterPart) { 65 var filterValue = filterPart.split("/")[0]; 66 if (filterValue && filterValue !== "all") { 67 // Store the combined filter string - we'll parse individual values from DOM 68 filters.combined = filterValue; 69 } 70 } 71 } 72 73 // Check for date 74 if (currentUrl.indexOf("/date/") !== -1) { 75 var datePart = currentUrl.split("/date/")[1]; 76 if (datePart) { 77 var dateValue = datePart.split("/")[0]; 78 if (dateValue) { 79 filters.date = dateValue; 80 } 81 } 82 } 83 84 return filters; 85 } 86 87 // Helper function to get all selected filter IDs from dropdowns 88 function getSelectedFilterIds() { 89 var ids = []; 90 91 // Event type 92 var eventTypeVal = $("#event-type").val(); 93 if (eventTypeVal && eventTypeVal !== "all") { 94 ids.push(eventTypeVal); 95 } 96 97 // Location 98 var locationVal = $("#venue-city").val(); 99 if (locationVal && locationVal !== "all") { 100 ids.push(locationVal); 101 } 102 103 // Learning filters (only if learning is selected) 104 if (eventTypeVal === $("#event-type option[data-learning='true']").val() || 105 $(".learning-filters-row").hasClass("d-flex")) { 106 // Learn type 107 var learnTypeVal = $("#learn-type").val(); 108 if (learnTypeVal && learnTypeVal !== "all") { 109 ids.push(learnTypeVal); 110 } 111 112 // Age range 113 var ageRangeVal = $("#age-range").val(); 114 if (ageRangeVal && ageRangeVal !== "all") { 115 ids.push(ageRangeVal); 116 } 117 118 // Language 119 var langVal = $("#lang-filter").val(); 120 if (langVal && langVal !== "all") { 121 ids.push(langVal); 122 } 123 } 124 125 return ids; 126 } 127 128 // Helper function to build URL from filter IDs and date 129 function buildFilterUrl(filterIds, dateValue) { 130 var baseUrl = getBaseUrl(); 131 var url = baseUrl; 132 133 // Add filter segment - use '&' as separator (URL encoded as-is since it's in the path) 134 if (filterIds.length > 0) { 135 url += "filter/" + filterIds.join("&") + "/"; 136 } else { 137 url += "filter/all/"; 138 } 139 140 // Add date segment only if date is selected 141 if (dateValue && dateValue !== "all") { 142 url += "date/" + dateValue + "/"; 143 } 144 145 return url; 146 } 147 148 // Helper function to update URL with current filter state 149 function updateFiltersUrl(changedFilter, newValue) { 150 var filterIds = []; 151 var dateValue = null; 152 153 // Get current date from URL 154 var currentFilters = getCurrentFilters(); 155 dateValue = currentFilters.date; 156 157 // Event type 158 var eventTypeVal = changedFilter === "event-type" ? newValue : $("#event-type").val(); 159 if (eventTypeVal && eventTypeVal !== "all") { 160 filterIds.push(eventTypeVal); 161 } 162 163 // Location 164 var locationVal = changedFilter === "venue-city" ? newValue : $("#venue-city").val(); 165 if (locationVal && locationVal !== "all") { 166 filterIds.push(locationVal); 167 } 168 169 // Check if learning event type is selected (category ID for learning) 170 var learningCatId = $("#event-type option:contains('Learning')").val() || 171 $("#event-type").find("option").filter(function() { 172 return $(this).text().toLowerCase().indexOf("learning") !== -1 || 173 $(this).text().toLowerCase().indexOf("تعÙÙ ") !== -1; 174 }).val(); 175 176 var isLearning = eventTypeVal === learningCatId; 177 178 // Learning filters (only if learning is selected) 179 if (isLearning) { 180 // Learn type 181 var learnTypeVal = changedFilter === "learn-type" ? newValue : $("#learn-type").val(); 182 if (learnTypeVal && learnTypeVal !== "all") { 183 filterIds.push(learnTypeVal); 184 } 185 186 // Age range 187 var ageRangeVal = changedFilter === "age-range" ? newValue : $("#age-range").val(); 188 if (ageRangeVal && ageRangeVal !== "all") { 189 filterIds.push(ageRangeVal); 190 } 191 192 // Language 193 var langVal = changedFilter === "lang-filter" ? newValue : $("#lang-filter").val(); 194 if (langVal && langVal !== "all") { 195 filterIds.push(langVal); 196 } 197 } 198 199 return buildFilterUrl(filterIds, dateValue); 200 } 201 202 // Filter the entries based on the selected Event Type 203 $("#event-type").on("change", function () { 204 var selectedOption = $(this).find(":selected").val(); 205 var newUrl = updateFiltersUrl("event-type", selectedOption); 206 window.location.href = newUrl; 207 }); 208 209 // Filter the entries based on the selected Location 210 $("#venue-city").on("change", function () { 211 var selectedOption = $(this).find(":selected").val(); 212 var newUrl = updateFiltersUrl("venue-city", selectedOption); 213 window.location.href = newUrl; 214 }); 215 216 // Filter the entries based on the selected Learning Type 217 $("#learn-type").on("change", function () { 218 var selectedOption = $(this).find(":selected").val(); 219 var newUrl = updateFiltersUrl("learn-type", selectedOption); 220 window.location.href = newUrl; 221 }); 222 223 // Filter the entries based on the selected Age Range 224 $("#age-range").on("change", function () { 225 var selectedOption = $(this).find(":selected").val(); 226 var newUrl = updateFiltersUrl("age-range", selectedOption); 227 window.location.href = newUrl; 228 }); 229 230 // Filter the entries based on the selected Language 231 $("#lang-filter").on("change", function () { 232 var selectedOption = $(this).find(":selected").val(); 233 var newUrl = updateFiltersUrl("lang-filter", selectedOption); 234 window.location.href = newUrl; 235 }); 236 237 $drpWhatsOn.on("endDateChange.coreui.date-range-picker", function () { 238 var startDate = $('input[name="startDate"]').val(); 239 var endDate = $('input[name="endDate"]').val(); 240 241 if (startDate === null || startDate === "" || endDate === null || endDate === "") { 242 // Date range cleared - remove date from URL 243 var filterIds = getSelectedFilterIds(); 244 var newUrl = buildFilterUrl(filterIds, null); 245 window.location.href = newUrl; 246 } else { 247 var daterange = startDate + "--" + endDate; 248 249 // Convert to Unix timestamps 250 var dateArray = daterange.split("--"); 251 var fromDate = dateArray[0]; 252 var toDate = new Date(dateArray[1]); 253 254 // Round toDate to the last minute of the day 255 toDate.setHours(23, 59, 59); 256 257 // Convert to Unix timestamps (seconds) 258 var fromUnixTimestamp = Math.floor(new Date(fromDate).getTime() / 1000); 259 var toUnixTimestamp = Math.floor(toDate.getTime() / 1000); 260 var dateRangeUnixTimestamp = fromUnixTimestamp + "--" + toUnixTimestamp; 261 262 // Build URL with current filters and new date 263 var filterIds = getSelectedFilterIds(); 264 var newUrl = buildFilterUrl(filterIds, dateRangeUnixTimestamp); 265 window.location.href = newUrl; 266 } 267 }); 268 269 // Function to convert the Unix Timestamp to normal date format 270 function unixTimestampToDate(unixTimestamp) { 271 // Convert Unix timestamp to milliseconds 272 var milliseconds = unixTimestamp * 1000; 273 274 // Create a new Date object using the milliseconds 275 var dateObject = new Date(milliseconds); 276 277 // Get the day, month, and year from the date object 278 var day = dateObject.getDate(); 279 var monthIndex = dateObject.getMonth(); 280 var year = dateObject.getFullYear(); 281 282 // Array of month names 283 var monthNames = [ 284 "Jan", 285 "Feb", 286 "Mar", 287 "Apr", 288 "May", 289 "Jun", 290 "Jul", 291 "Aug", 292 "Sep", 293 "Oct", 294 "Nov", 295 "Dec", 296 ]; 297 298 // Get the month name using the month index 299 var monthName = monthNames[monthIndex]; 300 301 // Format the date string as 'DD-MMM-YYYY' 302 var formattedDate = day + "-" + monthName + "-" + year; 303 304 // Return the formatted date string 305 return formattedDate; 306 } 307 308 // Function to fill the daterangepicker input with the date range in the URL 309 function fillDateRange() { 310 var currentUrl = window.location.href; 311 312 if (currentUrl.indexOf("/date/") !== -1) { 313 var dateSegment = currentUrl.split("/date/")[1]; 314 if (dateSegment) { 315 dateSegment = dateSegment.split("/")[0]; 316 if (dateSegment && dateSegment !== "all" && dateSegment.indexOf("--") !== -1) { 317 var unixTimestampFrom = dateSegment.split("--")[0]; 318 var unixTimestampTo = dateSegment.split("--")[1]; 319 var formattedDateFrom = unixTimestampToDate(unixTimestampFrom); 320 var formattedDateTo = unixTimestampToDate(unixTimestampTo); 321 $('input[name="datefilter"]').val( 322 formattedDateFrom + "--" + formattedDateTo 323 ); 324 $('input[name="startDate"]').val(formattedDateFrom); 325 $('input[name="endDate"]').val(formattedDateTo); 326 } 327 } 328 } 329 } 330 331 // Initiate the fillDateRange Function 332 fillDateRange(); 333 334 // Function to show/hide learning filters row based on event-type selection 335 function updateLearningFiltersVisibility() { 336 var eventTypeVal = $("#event-type").val(); 337 338 // Find the learning category ID by checking the option text 339 var learningCatId = $("#event-type").find("option").filter(function() { 340 return $(this).text().toLowerCase().indexOf("learning") !== -1 || 341 $(this).text().toLowerCase().indexOf("تعÙÙ ") !== -1; 342 }).val(); 343 344 var $learningRow = $(".learning-filters-row"); 345 346 if (eventTypeVal === learningCatId) { 347 $learningRow.removeClass("d-none").addClass("d-flex"); 348 } else { 349 $learningRow.removeClass("d-flex").addClass("d-none"); 350 // Reset learning filter values when hiding 351 $("#learn-type").val("all"); 352 $("#age-range").val("all"); 353 $("#lang-filter").val("all"); 354 } 355 } 356 357 // Initialize learning filters visibility on page load 358 updateLearningFiltersVisibility(); 359 360 // ========================================== 361 // Filter Badges Functionality 362 // ========================================== 363 364 // Helper function to create badge HTML 365 function createBadgeHtml(text, filterId, filterType) { 366 return '<div class="filter-badge" data-filter-id="' + filterId + '" data-filter-type="' + filterType + '">' + 367 '<span class="badge-text">
367' + text + '</span>' + 368 '<span class="badge-remove">' + 369 '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor">' + 370 '<line x1="18" y1="6" x2="6" y2="18"></line>' + 371 '<line x1="6" y1="6" x2="18" y2="18"></line>' + 372 '</svg>' + 373 '</span>' + 374 '</div>'; 375 } 376 377 // Helper function to remove a filter ID from the combined filter string 378 function removeFilterId(combinedFilters, filterIdToRemove) { 379 if (!combinedFilters || combinedFilters === "all") return ""; 380 381 var filterIds = combinedFilters.split("&"); 382 var newFilterIds = filterIds.filter(function(id) { 383 return id !== filterIdToRemove; 384 }); 385 386 return newFilterIds.join("&"); 387 } 388 389 // Function to populate filter badges 390 function populateFilterBadges() { 391 var $badgesContainer = $("#filterBadges"); 392 if (!$badgesContainer.length) return; 393 394 $badgesContainer.empty(); 395 396 var currentFilters = getCurrentFilters(); 397 398 // Add category filter badges 399 if (currentFilters.combined) { 400 var filterIds = currentFilters.combined.split("&"); 401 402 filterIds.forEach(function(filterId) { 403 // Find the corresponding option text from dropdowns 404 var $option = null; 405 var filterType = ""; 406 407 // Check event-type dropdown 408 $option = $("#event-type option[value='" + filterId + "']"); 409 if ($option.length) { 410 filterType = "event-type"; 411 } 412 413 // Check venue-city dropdown 414 if (!$option.length || !$option.val()) { 415 $option = $("#venue-city option[value='" + filterId + "']"); 416 if ($option.length && $option.val()) { 417 filterType = "venue-city"; 418 } 419 } 420 421 // Check learn-type dropdown 422 if (!filterType) { 423 $option = $("#learn-type option[value='" + filterId + "']"); 424 if ($option.length && $option.val()) { 425 filterType = "learn-type"; 426 } 427 } 428 429 // Check age-range dropdown 430 if (!filterType) { 431 $option = $("#age-range option[value='" + filterId + "']"); 432 if ($option.length && $option.val()) { 433 filterType = "age-range"; 434 } 435 } 436 437 // Check lang-filter dropdown 438 if (!filterType) { 439 $option = $("#lang-filter option[value='" + filterId + "']"); 440 if ($option.length && $option.val()) { 441 filterType = "lang-filter"; 442 } 443 } 444 445 if ($option && $option.length && filterType) { 446 var badgeText = $option.text().trim(); 447 $badgesContainer.append(createBadgeHtml(badgeText, filterId, filterType)); 448 } 449 }); 450 } 451 452 // Add date badge if date filter is active 453 if (currentFilters.date && currentFilters.date.indexOf("--") !== -1) { 454 var dateParts = currentFilters.date.split("--"); 455 var fromDate = unixTimestampToDate(dateParts[0]); 456 var toDate = unixTimestampToDate(dateParts[1]); 457 var dateText = fromDate + " - " + toDate; 458 $badgesContainer.append(createBadgeHtml(dateText, currentFilters.date, "date")); 459 } 460 } 461 462 // Handle badge removal click 463 $(document).on("click", ".filter-badge", function() { 464 var $badge = $(this); 465 var filterId = $badge.data("filter-id"); 466 var filterType = $badge.data("filter-type"); 467 468 var currentFilters = getCurrentFilters(); 469 var newFilterIds = []; 470 var newDateValue = currentFilters.date; 471 472 if (filterType === "date") { 473 // Remove date filter 474 newDateValue = null; 475 // Keep existing category filters 476 if (currentFilters.combined) { 477 newFilterIds = currentFilters.combined.split("&"); 478 } 479 } else { 480 // Remove category filter 481 if (currentFilters.combined) { 482 var remainingFilters = removeFilterId(currentFilters.combined, String(filterId)); 483 if (remainingFilters) { 484 newFilterIds = remainingFilters.split("&"); 485 } 486 } 487 } 488 489 // Build new URL and navigate 490 var newUrl = buildFilterUrl(newFilterIds, newDateValue); 491 window.location.href = newUrl; 492 }); 493 494 // Initialize badges on page load 495 populateFilterBadges(); 496}); 497 498$(document).ready(function () { 499 var itemsPerPage = 8; 500 var loadedItems = itemsPerPage; 501 var isLoading = false;
502 503 // Check if the url has already a sorting or filters applied 504 var currentUrl = window.location.href; 505 var partUrl = currentUrl.split("/list/")[1]; 506 507 // Check the current language used 508 var lang; 509 if (currentUrl.indexOf("/ar/") === -1) { 510 lang = "/en"; 511 } else { 512 lang = "/ar"; 513 } 514 515 function loadMoreItems() { 516 if (isLoading) return; 517 isLoading = true; 518 519 // Simulate loading from server (replace this with actual loading mechanism) 520 $.ajax({ 521 url: lang + "/AJAX/whats-on-load-more/" + loadedItems + "/" + partUrl, 522 type: "GET", 523 //data: {offset: loadedItems}, 524 success: function (response) { 525 // Append loaded items to the list 526 $("#whatsOnList").append(response); 527 528 // Update loaded items count 529 loadedItems += itemsPerPage; 530 531 isLoading = false; 532 }, 533 error: function () { 534 isLoading = false; 535 }, 536 }); 537 } 538 539 // Load initial items 540 //loadMoreItems(); 541 542 // Detect scrolling to the bottom of the page 543 $(window).scroll(function () { 544 // Calculate 90% of the document height 545 var limitHeight = $(document).height() * 0.70; 546 547 // Check if scrollTop position is greater than or equal to 90% of the document height minus window height 548 if ($(window).scrollTop() >= limitHeight - $(window).height()) { 549 loadMoreItems(); 550 } 551 }); 552});
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.