1/** 2 * @file 3 * bef_select_all_none.js 4 * 5 * Adds select all/none toggle functionality to an exposed filter. 6 */ 7 8(function ($, once) { 9 Drupal.behaviors.betterExposedFiltersSelectAllNone = { 10 attach: function () { 11 /* 12 * Add Select all/none links to specified checkboxes 13 */ 14 const selected = $('.form-checkboxes.bef-select-all-none:not(.bef-processed)'); 15 if (selected.length) { 16 const selAll = Drupal.t('Select All'); 17 const selNone = Drupal.t('Select None'); 18 19 // Set up a prototype link and event handlers. 20 const link = $('<a class="bef-toggle bef-toggle--select-all" href="#">' + selAll + '</a>'); 21 link.click(function (event) { 22 // Don't actually follow the link... 23 event.preventDefault(); 24 event.stopPropagation(); 25 26 if (selAll === $(this).text()) { 27 // Select all the checkboxes. 28 $(this) 29 .html(selNone) 30 .removeClass('bef-toggle--select-all') 31 .addClass('bef-toggle--deselect-all') 32 .siblings('.bef-select-all-none, .bef-tree') 33 .find('input:checkbox').each(function () { 34 $(this).prop('checked', true); 35 }) 36 .end() 37 38 // attr() doesn't trigger a change event, so we do it ourselves. But just on 39 // one checkbox otherwise we have many spinning cursors. 40 .find('input[type=checkbox]:first').change(); 41 } 42 else { 43 // Unselect all the checkboxes. 44 $(this) 45 .html(selAll) 46 .removeClass('bef-toggle--deselect-all') 47 .addClass('bef-toggle--select-all') 48 .siblings('.bef-select-all-none, .bef-tree') 49 .find('input:checkbox').each(function () { 50 $(this).prop('checked', false); 51 }) 52 .end() 53 54 // attr() doesn't trigger a change event, so we do it ourselves. But just on 55 // one checkbox otherwise we have many spinning cursors. 56 .find('input[type=checkbox]:first').change(); 57 } 58 }); 59 60 // Add link to the page for each set of checkboxes. 61 selected 62 .addClass('bef-processed') 63 .each(function () { 64 // Clone the link prototype and insert into the DOM. 65 const newLink = link.clone(true); 66 67 newLink.insertBefore($(this)); 68 69 // Show select all/none when single checkbox is checked/unchecked 70 $('input:checkbox', this).click(function() { 71 if ($(this).prop("checked") === true) { 72 newLink.text(selNone); 73 } 74 else if ($(this).prop("checked") === false) { 75 newLink.text(selAll); 76 } 77 }); 78 79 // If all checkboxes are already checked by default then switch to Select None. 80 if ($('input:checkbox:checked', this).length === $('input:checkbox', this).length) { 81 newLink.text(selNone).removeClass('bef-toggle--select-all').addClass('bef-toggle--deselect-all'); 82 } 83 }); 84 } 85 } 86 }; 87 88 Drupal.behaviors.betterExposedFiltersAllNoneNested = { 89 attach: function () { 90 $(once('bef-all-none-nested', '.bef-select-all-none-nested ul li')).each(function () { 91 const $this = $(this); 92 // Check/uncheck child terms along with their parent. 93 $this.find('input:checkbox:first').change(function () { 94 $(this).closest('li').find('ul li input:checkbox').prop('checked', this.checked); 95 }); 96 97 // When a child term is checked or unchecked, set the parent term's 98 // status as needed. 99 $this.find('ul input:checkbox').change(function () { 100 // Determine the number of unchecked sibling checkboxes. 101 const $this = $(this); 102 const uncheckedSiblings = $this.closest('li').siblings('li').find('> div input:checkbox:not(:checked)').length; 103 104 // If this term or any siblings are unchecked, uncheck the parent and 105 // all ancestors. 106 if (uncheckedSiblings || !this.checked) {
107 $this.parents('ul').siblings('div').find('input:checkbox').prop('checked', false); 108 } 109 110 // If this and all sibling terms are checked, check the parent. Then 111 // trigger the parent's change event to see if that change affects the 112 // grandparent's checked state. 113 if (this.checked && !uncheckedSiblings) { 114 $(this).closest('ul').closest('li').find('input:checkbox:first').prop('checked', true).change(); 115 } 116 }); 117 }); 118 } 119 }; 120 121})(jQuery, once);
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.