1function haveCommonItems(arr1, arr2) { 2 // Check if both arrays are defined 3 if (!arr1 || !arr2) { 4 return false; 5 } 6 7 // Use the some method to check if any element in arr1 exists in arr2 8 return arr1.some(item => arr2.includes(item)); 9} 10 11function removeItem(arr, itemToRemove) { 12 // Check if the array is undefined or null 13 if (arr === undefined || arr === null) { 14 console.log("Array is undefined or null."); 15 return arr; 16 } 17 18 // Check if the array is empty 19 if (arr.length === 0) { 20 console.log("Array is empty."); 21 return arr; 22 } 23 24 // Use filter to create a new array without the specified item 25 return arr.filter(item => item !== itemToRemove); 26} 27 28jQuery(document).ready(function($) { 29 $('.paneldeltager-container .description-container').expander({ 30 slicePoint: 150, // default is 100 31 expandText: 'Læs mere â', // default is 'read more' 32 userCollapseText: 'Luk ⤫' // default is 'read less' 33 }); 34 35 var Shuffle = window.Shuffle; 36 37 // Only initialize Shuffle if the container exists 38 if ($('.shuffle-container').length > 0) { 39 var myShuffle = new Shuffle(document.querySelector('.shuffle-container'), { 40 itemSelector: '.shuffle-item', 41 sizer: '.shuffle-item', 42 delimiter: ',', 43 buffer: 1, 44 }); 45 46 $('.filterizr-filter li').on('click', function(evt) { 47 var filter = $(this).attr("data-filter"); 48 49 if (filter) { 50 myShuffle.filter(filter); 51 } 52 }); 53 54 let selections = { 55 themes: [], 56 roles: [], 57 ages: [], 58 }; 59 60 function isAgeInRange(age, range) { 61 if (range === 'all') return true; 62 63 const ageNum = parseInt(age); 64 if (range === '15-35') return ageNum >= 15 && ageNum <= 35; 65 if (range === '36-49') return ageNum >= 36 && ageNum <= 49; 66 if (range === '50+') return ageNum >= 50; 67 68 return false; 69 } 70 71 function custom_filter() { 72 myShuffle.filter(element => { 73 if (selections.themes.length == 0 && selections.roles.length == 0 && selections.ages.length == 0) { 74 return true; 75 } 76 77 var themes = JSON.parse(element.getAttribute("data-themes")); 78 var roles = JSON.parse(element.getAttribute("data-roles")); 79 var age = element.getAttribute("data-age"); 80 81 var hasTheme = selections.themes.length == 0 ? true : haveCommonItems(themes, selections.themes); 82 var hasRole = selections.roles.length == 0 ? true : haveCommonItems(roles, selections.roles); 83 var hasAge = selections.ages.length == 0 ? true : selections.ages.some(range => isAgeInRange(age, range)); 84 85 return (hasTheme && hasRole && hasAge); 86 }); 87 } 88 89 custom_filter(); 90 91 $("li.fltr-controls").on("click", function() { 92 var checkbox = $(this).find("input[type=checkbox]"); 93 checkbox.prop("checked", !checkbox.prop("checked")); 94 }); 95 96 $("input[name^=themes]").on("change", function() { 97 var filter = $(this).attr("data-filter"); 98 var label = $(this).closest("label"); 99 var active = $(this).is(":checked"); 100 101 if (filter == "all") { 102 selections.themes = []; 103 $(this).closest(".filterizr-filter").find("label").removeClass("filtr-active"); 104 custom_filter(); 105 return; 106 } 107 108 if (active) { 109 selections.themes.push(filter); 110 label.addClass("filtr-active"); 111 } else { 112 selections.themes = removeItem(selections.themes, filter); 113 label.removeClass("filtr-active"); 114 } 115 116 custom_filter(); 117 }); 118 119 // Age filter handler 120 $("input[name=age]").on("change", function() { 121 var filter = $(this).attr("data-filter"); 122 var label = $(this).closest("label"); 123 124 $(".age-filter-container").find("label").removeClass("filtr-active"); 125 126 if (filter === "all") { 127 selections.ages = []; 128 // No addClass for "all" 129 } else { 130 selections.ages = [filter]; 131 label.addClass("filtr-active"); 132 } 133 custom_filter(); 134 }); 135 136 // Roles filter handler 137 $(".roles-filter-container input[type=radio]").on("change", function() { 138 var filter = $(this).attr("data-filter"); 139 var label = $(this).closest("label"); 140 141 // Force radio button state reset 142 $(".roles-filter-container input[type=radio]").prop("checked", false); 143 $(this).prop("checked", true); 144 145 // Reset visual states 146 $(".roles-filter-container").find("label").removeClass("filtr-active"); 147 148 if ($(this).attr("name") === "all") { 149 selections.roles = []; 150 // No addClass for "all" 151 } else { 152 selections.roles = [filter]; 153 label.addClass("filtr-active"); 154 } 155 156 custom_filter(); 157 }); 158 } 159 160 /** 161 * Character limit for form fields with submission prevention 162 * Simplified approach: Allow typing beyond limit but prevent submission 163 * Only for tcode_event post type 164 */ 165 jQuery(document).ready(function($) { 166 // Constants 167 const CHAR_LIMIT_TITLE = 40; 168 const CHAR_LIMIT_CONTENT = 400; 169 170 // Track fields with excess text 171 let fieldsWithExcess = []; 172 173 // Helper function to check if we're on an event form 174 function isEventForm($element) { 175 // Check if we're on an event edit page or form 176 return ( 177 $element.closest('.e-loop-item.tcode_event').length > 0 || 178 $element.closest('.acf-form[data-post-type="tcode_event"]').length > 0 || 179 $element.closest('form.frontend-form').length > 0 || // Added this line 180 $element.closest('.fea-modal.edit-modal').length > 0 || // Added this line
181 $('body').hasClass('post-type-tcode_event') || 182 // Check for event form by looking for specific event fields 183 $element.closest('form').find('[data-name="event_tema"], [data-name="arrangementstype"]').length > 0 184 ); 185 } 186 187 // Helper function to check if we're on a bod form - to explicitly exclude 188 function isBoderForm($element) { 189 return ( 190 $element.closest('.e-loop-item.bod').length > 0 || 191 $element.closest('.acf-form[data-post-type="bod"]').length > 0 || 192 $('body').hasClass('post-type-bod') 193 ); 194 } 195 196 // Function to initialize character counter for regular inputs 197 function initInputCharCounter() { 198 // Title field 199 $('.acf-field[data-name="fea_post_title"] input[type="text"]').each(function() { 200 const $field = $(this); 201 202 // Skip if already initialized 203 if ($field.data('char-counter-init')) return; 204 205 // Skip if on a bod form 206 if (isBoderForm($field)) return; 207 208 // Skip if not in an event form 209 if (!isEventForm($field)) return; 210 211 $field.data('char-counter-init', true); 212 213 // Remove any existing counters to avoid duplicates 214 $field.next('.char-counter-container').remove(); 215
216 const $counterContainer = $('<div class="char-counter-container"></div>'); 217 const $counter = $('<div class="char-counter"></div>'); 218 $counterContainer.append($counter); 219 $field.after($counterContainer); 220 221 $field.on('input change keyup', function() { 222 const text = $(this).val(); 223 const currentLength = text.length; 224 225 // Update counter 226 $counter.text(currentLength + '/' + CHAR_LIMIT_TITLE); 227 228 // Update styling and track excess 229 const fieldId = 'title-' + ($(this).attr('id') || $(this).attr('name') || Math.random().toString(36).substring(2, 9)); 230 231 if (currentLength > CHAR_LIMIT_TITLE) { 232 $counter.removeClass('normal warning').addClass('exceeded'); 233 $field.addClass('field-with-excess'); 234 235 // Add to excess tracking 236 if (!fieldsWithExcess.includes(fieldId)) { 237 fieldsWithExcess.push(fieldId); 238 } 239 } else if (currentLength >= CHAR_LIMIT_TITLE * 0.9) { 240 $counter.removeClass('normal exceeded').addClass('warning'); 241 $field.removeClass('field-with-excess'); 242 243 // Remove from excess tracking 244 fieldsWithExcess = fieldsWithExcess.filter(id => id !== fieldId); 245 } else { 246 $counter.removeClass('warning exceeded').addClass('normal'); 247 $field.removeClass('field-with-excess'); 248 249 // Remove from excess tracking 250 fieldsWithExcess = fieldsWithExcess.filter(id => id !== fieldId); 251 } 252 253 // Update form submission state 254 updateFormSubmissionState(); 255 }); 256 257 // Initial update 258 $field.trigger('input'); 259 }); 260 } 261 262 // Function to initialize TinyMCE character counter 263 function initTinyMCECharCounter() { 264 if (typeof tinyMCE === 'undefined' || !tinyMCE.editors || !tinyMCE.editors.length) { 265 return; 266 } 267 268 // Loop through all TinyMCE editors 269 tinyMCE.editors.forEach(function(editor) { 270 // Skip if already initialized 271 if (editor.hasCharCounter) return; 272 273 const $editorElement = $('#' + editor.id); 274 275 // Skip if on a bod form 276 if (isBoderForm($editorElement)) return; 277 278 // Skip if not in an event form 279 if (!isEventForm($editorElement)) return; 280 281 const $editorContainer = $editorElement.closest('.wp-editor-container'); 282 283 // Remove any existing counters to avoid duplicates 284 $editorContainer.next('.char-counter-container').remove(); 285 $editorContainer.find('.char-counter-container').remove(); 286 287 // Create counter element
288 const $counterContainer = $('<div class="char-counter-container"></div>'); 289 const $counter = $('<div class="char-counter"></div>'); 290 $counterContainer.append($counter); 291 $editorContainer.after($counterContainer); 292 293 editor.hasCharCounter = true; 294 295 // Function to count characters and update counter 296 function updateCounter() { 297 // Get plain text content (strips HTML tags) 298 const content = editor.getContent({format: 'text'}); 299 const length = content.length; 300 301 // Always update counter text - ensure it's visible initially 302 $counter.text(length + '/' + CHAR_LIMIT_CONTENT); 303 304 // Update styling and track excess 305 const fieldId = 'editor-' + editor.id; 306 307 if (length > CHAR_LIMIT_CONTENT) { 308 $counter.removeClass('normal warning').addClass('exceeded'); 309 $editorContainer.addClass('field-with-excess'); 310 311 // Add to excess tracking 312 if (!fieldsWithExcess.includes(fieldId)) { 313 fieldsWithExcess.push(fieldId); 314 } 315 } else if (length >= CHAR_LIMIT_CONTENT * 0.9) { 316 $counter.removeClass('normal exceeded').addClass('warning'); 317 $editorContainer.removeClass('field-with-excess'); 318 319 // Remove from excess tracking 320 fieldsWithExcess = fieldsWithExcess.filter(id => id !== fieldId); 321 } else { 322 $counter.removeClass('warning exceeded').addClass('normal'); 323 $editorContainer.removeClass('field-with-excess'); 324 325 // Remove from excess tracking 326 fieldsWithExcess = fieldsWithExcess.filter(id => id !== fieldId); 327 } 328 329 // Update form submission state 330 updateFormSubmissionState(); 331 } 332 333 // Add event listeners 334 editor.on('keyup change SetContent', function() { 335 setTimeout(updateCounter, 100); 336 }); 337 338 // Initial update - make sure it runs 339 editor.on('init', function() { 340 setTimeout(updateCounter, 500); 341 }); 342 343 // If editor is already initialized, run the counter immediately 344 if (editor.initialized) { 345 setTimeout(updateCounter, 100); 346 } 347 }); 348 } 349 350 // Returns true if THIS form's own title/content fields exceed the limits. 351 // Computed fresh from the form's current fields so that one form (or a 352 // legacy over-limit event elsewhere on the page) can never lock another. 353 function formHasExcessText($form) { 354 let hasExcess = false; 355 356 // Title fields in this form 357 $form.find('.acf-field[data-name="fea_post_title"] input[type="text"]').each(function() { 358 if (($(this).val() || '').length > CHAR_LIMIT_TITLE) { 359 hasExcess = true; 360 } 361 }); 362 363 // WYSIWYG/content fields in this form 364 $form.find('.acf-field-wysiwyg textarea.wp-editor-area, textarea.wp-editor-area').each(function() { 365 const id = $(this).attr('id'); 366 let len; 367 if (id && typeof tinyMCE !== 'undefined' && tinyMCE.get(id) && !tinyMCE.get(id).isHidden()) { 368 // Visual mode: live content lives in the TinyMCE instance, not the textarea 369 len = tinyMCE.get(id).getContent({format: 'text'}).length; 370 } else { 371 // Text mode or no editor: fall back to the raw textarea value 372 len = ($(this).val() || '').length; 373 } 374 if (len > CHAR_LIMIT_CONTENT) { 375 hasExcess = true; 376 } 377 }); 378 379 return hasExcess; 380 } 381 382 // Function to update form submission state 383 function updateFormSubmissionState() { 384 // Find only event forms - explicitly exclude bod forms 385 const $forms = $('.acf-form, form.frontend-form').filter(function() { 386 return isEventForm($(this)) && !isBoderForm($(this)); 387 }); 388 389 $forms.each(function() { 390 const $form = $(this); 391 392 // Target the specific button class from your co
392debase - UPDATED SELECTOR 393 const $submitBtn = $form.find('.fea-submit-button, button[type="submit"], input[type="submit"], button[data-state="publish"]'); 394 395 // Remove any existing warning message 396 $form.find('.excess-text-warning').remove(); 397 398 // Evaluate ONLY this form's own fields - never a shared global array 399 if (formHasExcessText($form)) { 400 // Disable submit button - use both prop and attr for maximum compatibility 401 $submitBtn.prop('disabled', true).attr('disabled', 'disabled').addClass('disabled'); 402 403 // Add warning message before the submit button 404 const $warningMsg = $('<div class="excess-text-warning">Tilpas mængden af tekst i felterne øverst for at kunne gemme</div>'); 405 406 // Find the submit button container 407 const $submitContainer = $submitBtn.closest('.fea-submit-buttons, .acf-form-submit'); 408 if ($submitContainer.length) { 409 $submitContainer.before($warningMsg); 410 } else { 411 $submitBtn.before($warningMsg); 412 } 413 414 // Also prevent form submission via click handler - re-check at click time 415 $submitBtn.off('click.charLimit').on('click.charLimit', function(e) { 416 if (formHasExcessText($form)) { 417 e.preventDefault(); 418 e.stopPropagation(); 419 420 // Scroll to the first field with excess within this form 421 const $firstExcessField = $form.find('.field-with-excess').first(); 422 if ($firstExcessField.length) { 423 $('html, body').animate({ 424 scrollTop: $firstExcessField.offset().top - 100 425 }, 500); 426 } 427 428 return false; 429 } 430 }); 431 } else { 432 // Enable submit button - remove both prop and attr 433 $submitBtn.prop('disabled', false).removeAttr('disabled').removeClass('disabled'); 434 435 // Remove click handler 436 $submitBtn.off('click.charLimit'); 437 } 438 }); 439 } 440 441 // Initialize on page load 442 initInputCharCounter(); 443 initTinyMCECharCounter(); 444 445 // Initialize after AJAX completions 446 $(document).ajaxComplete(function() { 447 setTimeout(function() { 448 initInputCharCounter(); 449 initTinyMCECharCounter(); 450 }, 300); 451 }); 452 453 // For Elementor frontend 454 if (typeof elementorFrontend !== 'undefined') { 455 elementorFrontend.hooks.addAction('frontend/element_ready/global', function() { 456 setTimeout(function() { 457 initInputCharCounter(); 458 initTinyMCECharCounter(); 459 }, 300); 460 }); 461 } 462 463 // Monitor DOM changes for dynamically added fields 464 if (typeof MutationObserver !== 'undefined') { 465 const observer = new MutationObserver(function(mutations) { 466 let shouldInit = false; 467 468 mutations.forEach(function(mutation) { 469 if (mutation.addedNodes.length) { 470 for (let i = 0; i < mutation.addedNodes.length; i++) { 471 const node = mutation.addedNodes[i]; 472 if (node.nodeType === 1 && ( 473 $(node).hasClass('acf-field-wysiwyg') || 474 $(node).find('.acf-field-wysiwyg').length || 475 $(node).hasClass('wp-editor-container') || 476 $(node).find('.wp-editor-container').length || 477 $(node).is('input') || 478 $(node).find('input').length || 479 $(node).hasClass('fea-submit-button') || 480 $(node).find('.fea-submit-button').length 481 )) { 482 shouldInit = true; 483 break; 484 } 485 } 486 } 487 }); 488 489 if (shouldInit) { 490 setTimeout(function() { 491 initInputCharCounter(); 492 initTinyMCECharCounter(); 493 }, 300); 494 } 495 }); 496 497 observer.observe(document.body, { childList: true, subtree: true }); 498 } 499 500 // Also add form submit handler to catch any submissions that might b
500ypass button disabling 501 $(document).on('submit', function(e) { 502 const $form = $(e.target); 503 // Only apply to event forms 504 if (!isEventForm($form) || isBoderForm($form)) { 505 return; 506 } 507 508 // Evaluate ONLY the submitted form's own fields 509 if (formHasExcessText($form)) { 510 e.preventDefault(); 511 e.stopPropagation(); 512 513 // Scroll to the first field with excess within this form 514 const $firstExcessField = $form.find('.field-with-excess').first(); 515 if ($firstExcessField.length) { 516 $('html, body').animate({ 517 scrollTop: $firstExcessField.offset().top - 100 518 }, 500); 519 } 520 521 return false; 522 } 523 }); 524 525 // Add a specific handler for modal buttons 526 $(document).on('click', '.fea-modal button.fea-submit-button', function(e) { 527 const $form = $(this).closest('.acf-form, form.frontend-form, form'); 528 // Only apply to event forms - bod forms are not limited 529 if (!isEventForm($form) || isBoderForm($form)) { 530 return; 531 } 532 533 // Evaluate ONLY this button's own form fields 534 if (formHasExcessText($form)) { 535 e.preventDefault(); 536 e.stopPropagation(); 537 538 // Scroll to the first field with excess within this form 539 const $firstExcessField = $form.find('.field-with-excess').first(); 540 if ($firstExcessField.length) { 541 $('html, body').animate({ 542 scrollTop: $firstExcessField.offset().top - 100 543 }, 500); 544 } 545 546 return false; 547 } 548 }); 549 550 // Clean up any existing counters on bod forms 551 function removeCountersFromBoderForms() { 552 $('.acf-form').each(function() { 553 if (isBoderForm($(this))) { 554 $(this).find('.char-counter-container').remove(); 555 $(this).find('.field-with-excess').removeClass('field-with-excess'); 556 $(this).find('.excess-text-warning').remove(); 557 } 558 }); 559 } 560 561 // Run cleanup on page load and after AJAX 562 removeCountersFromBoderForms(); 563 $(document).ajaxComplete(removeCountersFromBoderForms); 564 }); 565 566 /** 567 * Event search functionality 568 */ 569 if ($('.tcode-event-schedule').length > 0) { 570 // Initialize search state 571 var isSearchActive = false; 572 573 // Store original click handlers 574 var originalDayClickHandler; 575 var originalLocationClickHandler; 576 577 // Search functionality 578 $('#event-search').on('keyup', function() { 579 var searchText = $(this).val().toLowerCase(); 580 581 if (searchText.length > 0) { 582 // Enter search mode 583 if (!isSearchActive) { 584 isSearchActive = true; 585 586 // Disable date and location click handlers by adding a search-active class 587 $('.scheduled-days, .scheduled-locations').addClass('search-active'); 588 589 // Add a temporary click handler to prevent default behavior 590 $('.scheduled-day, .scheduled-location').on('click.searchMode', function(e) { 591 if (isSearchActive) { 592 e.preventDefault(); 593 e.stopPropagation(); 594 return false; 595 } 596 }); 597 } 598 599 // Make all events visible 600 $('.scheduled-event').show().removeClass('event-hidden').addClass('event-visible'); 601 $('.scheduled-events').removeClass('hidden'); 602 603 // Filter events based on search text 604 var matchCount = 0; 605 $('.scheduled-event').each(function() { 606 var $event = $(this); 607 var eventTitle = $event.find('.event-title').text().toLowerCase(); 608 var eventContent = $event.find('.event-content').text().toLowerCase(); 609 var eventArtists = $event.find('.tcode-es-artist-title').text().toLowerCase(); 610 var panelists = $event.find('.paneldeltagere').text().toLowerCase(); 611 var moderator = $event.find('.moderator').text().toLowerCase(); 612 var organisation = $event.find('.organisation').text().toLowerCase(); 613 // Add theme search - look for the alt attribute in the theme image 614 var eventTheme = $event.find('.imgContainer img').attr('alt') || ''; 615 eventTheme = eventTheme.toLowerCase(); 616 617 if (eventTitle.indexOf(searchText) > -1 || 618 eventContent.indexOf(searchText) > -1 || 619 eventArtists.indexOf(searchText) > -1 || 620 panelists.indexOf(searchText) > -1 || 621 moderator.indexOf(searchText) > -1 || 622 organisation.indexOf(searchText) > -1 || 623 eventTheme.indexOf(searchText) > -1) { 624 $event.show(); 625 matchCount++; 626 } else { 627 $event.hide(); 628 } 629 }); 630 631 // Show "no results" message if needed 632 $('.no-search-results').remove(); 633 if (matchCount === 0) {ª 634 $('.scheduled-events.desktop').append('<div class="no-search-results">Ingen resultater fundet. Prøv en anden søgning.</div>'); 635 } 636 } else { 637 // Exit search mode 638 isSearchActive = false;
639 640 // Remove search results message 641 $('.no-search-results').remove(); 642 643 // Re-enable date and location click handlers 644 $('.scheduled-days, .scheduled-locations').removeClass('search-active'); 645 $('.scheduled-day, .scheduled-location').off('click.searchMode'); 646 647 // Reset to default view by triggering a click on the first day 648 $('.scheduled-day').first().trigger('click'); 649 } 650 }); 651 // Make search button functional 652 $('.promagnifier').on('click', function() { 653 $('#event-search').trigger('keyup'); 654 }); 655 656 } 657 658 /** 659 * Show/hide description for bod elements 660 */ 661 // Function to initialize bod elements 662 function initBodElements() { 663 // Hide all bod-desc elements initially 664 $('.bod-desc').hide(); 665 666 // Reset all buttons to their default state 667 $('.bod-showdesc').removeClass('active'); 668 $('.bod-showdesc .htmega_button_txt').text(''); 669 $('.bod-showdesc .htmega_button_icon i').removeClass('fa-chevron-up').addClass('fa-chevron-down'); 670 } 671 672 // Call the function when the document is ready 673 initBodElements(); 674 675 // Use event delegation for the click handler to work with dynamically loaded content 676 $(document).on('click', '.bod-showdesc', function(e) { 677 e.preventDefault(); 678 679 // Find the common parent container - going up to the main widget-wrap that contains everything 680 var $mainContainer = $(this).closest('.elementor-widget-wrap').parent().parent().parent().parent(); 681 682 // Find the bod-desc within this main container 683 var $desc = $mainContainer.find('.bod-desc'); 684 685 // Toggle the description with a slide animation 686 if ($desc.is(':visible')) { 687 $desc.slideUp(300); 688 $(this).removeClass('active'); 689 // Update the button text 690 $(this).find('.htmega_button_txt').text(''); 691 $(this).find('.htmega_button_icon i').removeClass('fa-chevron-up').addClass('fa-chevron-down'); 692 } else { 693 $desc.slideDown(300); 694 $(this).addClass('active'); 695 // Update the button text 696 $(this).find('.htmega_button_txt').text(''); 697 $(this).find('.htmega_button_icon i').removeClass('fa-chevron-down').addClass('fa-chevron-up'); 698 } 699 }); 700 701 // Listen for various events that might indicate content has been updated 702 $(document).ajaxComplete(function(event, xhr, settings) { 703 setTimeout(initBodElements, 100); // Slight delay to ensure DOM is updated 704 }); 705 706 // For Elementor-specific events 707 jQuery(window).on('elementor/frontend/init', function() { 708 elementorFrontend.hooks.addAction('frontend/element_ready/global', function() { 709 setTimeout(initBodElements, 100); 710 }); 711 }); 712 713 // Also run on document ready as a fallback 714 jQuery(document).ready(function() { 715 setTimeout(initBodElements, 100); 716 }); 717 718 // Monitor DOM changes to detect when new content is added 719 // This is a more aggressive approach but should catch all dynamic content updates 720 if (typeof MutationObserver !== 'undefined') { 721 var observer = new MutationObserver(function(mutations) { 722 var shouldInit = false; 723 724 mutations.forEach(function(mutation) { 725 // Check if new nodes were added 726 if (mutation.addedNodes.length) { 727 // Check if any of the added nodes contain our target elements 728 for (var i = 0; i < mutation.addedNodes.length; i++) { 729 var node = mutation.addedNodes[i]; 730 if (node.nodeType === 1 && ( 731 $(node).hasClass('bod-desc') || 732 $(node).find('.bod-desc').length || 733 $(node).hasClass('bod-showdesc') || 734 $(node).find('.bod-showdesc').length)) { 735 shouldInit = true; 736 break; 737 } 738 } 739 } 740 }); 741 742 if (shouldInit) { 743 setTimeout(initBodElements, 100); 744 } 745 }); 746 747 // Start observing the document with the configured parameters 748 observer.observe(document.body, { childList: true, subtree: true }); 749 } 750 751 // Additional event listeners for common filter/pagination events 752 $(document).on('click', '.filterizr-filter li, .fltr-control
752s, input[name^=themes], input[name=age], .roles-filter-container input[type=radio]', function() { 753 // Wait for the filter to complete 754 setTimeout(initBodElements, 300); 755 }); 756});
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.