PageSourceSearch

https://www.knkv.nl/app/themes/saas-theme/assets/js/bootstrap-multiselect-scripts.js?ver=5.1.3

js knkv.nl collected 2026-09-24 21:31:34 UTC 8,407 bytes, 220 lines download raw bytes

1
2function saas_init_bs_multiselect() {
3    jQuery( 'select[multiple], .filterable select, select.multiselect' ).not( '.multiselect-initialized' ).each( function( i ) {
4
5		const select = this;
6		const $select = jQuery( this );
7		const field_classes_to_copy = $select.attr( 'data-field-classes-to-copy' ) || 'border theme-rounded-input';
8		const popup_classes_to_copy = $select.attr( 'data-popup-classes-to-copy' ) || 'border theme-rounded-input-limited';
9
10		const args = {
11
12            templates: {
13                button: '<button type="button" class="multiselect dropdown-toggle ' + field_classes_to_copy + '" data-bs-toggle="dropdown"><span class="multiselect-selected-text"></span></button>',
14                popupContainer: '<div class="multiselect-container dropdown-menu ' + popup_classes_to_copy + '"></div>',
15                filter: '<div class="multiselect-filter d-flex align-items-center"><i class="fas fa-sm fa-search text-muted"></i><input type="search" class="multiselect-search form-control" /></div>',
16                buttonGroup: '<div class="multiselect-buttons btn-group dropdown d-flex"></div>',
17                buttonGroupReset: '<button type="button" class="multiselect-reset btn btn-secondary btn-block"></button>',
18                option: '<button type="button" class="multiselect-option dropdown-item"></button>',
19                divider: '<div class="dropdown-divider"></div>',
20                optionGroup: '<button type="button" class="multiselect-group dropdown-item"></button>',
21                resetButton: '<div class="multiselect-reset text-center p-2"><button type="button" class="btn btn-sm btn-block btn-outline-secondary"></button></div>'
22            },
23            includeSelectAllOption: true,
24            enableFiltering: false,
25            includeFilterClearBtn: true,
26            enableCaseInsensitiveFiltering: true,
27			onInitialized: function( select, container ) {
28
29				// Custom event
30				// $select.trigger( 'multiselect-initialized' );
31				$select.get( 0 ).dispatchEvent( new CustomEvent( 'multiselect-initialized' ) );
32
33				$select.addClass( 'multiselect-initialized' );
34
35				// Re-init icons in newly rendered dropdown (search)
36				if ( typeof window.FontAwesome !== 'undefined' ) {
37					window.FontAwesome.dom.i2svg( { node: select.parentElement } );
38				}
39				else {
40					setTimeout( function() {
41						if ( typeof window.FontAwesome !== 'undefined' ) {
42							window.FontAwesome.dom.i2svg( { node: select.parentElement } );
43						}
44					}, 1000 );
45				}
46
47			},
48			onDropdownShow: function( event ) {
49
50				// Custom event
51				select.dispatchEvent( new CustomEvent( 'multiselect-open' ) );
52
53				// Global flag
54				// window.moddse_multiselect_is_open = true;
55
56				// Temporarily disable the fontawesome dom change listener for performance while text searching in the list.
57				// Reenabled on onDropdownHide
58				// if ( typeof window.FontAwesome !== 'undefined' ) {
59				// 	window.FontAwesome.dom.unwatch();
60				// }
61
62			},
63			onDropdownHide: function( event ) {
64
65				// Global flag
66				// window.moddse_multiselect_is_open = false;
67
68				// Reenable the fontawesome dom change listener.
69				// if ( typeof window.FontAwesome !== 'undefined' ) {
70				// 	window.FontAwesome.dom.watch();
71				// }
72
73			},
74			onChange: function( option, checked, select ) {
75
76				// Trigger a native 'change' event on the actual select element
77				this.$select[0].dispatchEvent( new Event( 'change', { bubbles: true } ) );
78				$select.trigger( 'multiselect-change', option );
79
80				// Apply selection limit when applicable
81				if ( $select.data( 'max' ) ) {
82
83					const $options = $select.children( 'option' );
84					const selected_options = $select.children( 'option:selected' );
85					const max = $select.data( 'max' );
86
87					// Disable all other checkboxes
88					if ( selected_options.length >= max ) {
89						const non_selected_options = $options.filter( function() {
90							return ! jQuery( this ).is( ':selected' );
91						} );
92						non_selected_options.each( function() {
93							const checkbox = jQuery( 'input[value="' + jQuery( this ).val() + '"]' );
94							checkbox.prop( 'disabled', true );
95							checkbox.closest( '.multiselect-option' ).addClass( 'disabled' );
96						} );
97					}
98
99					// Enable all checkboxes
100					else {
101						$options.each( function() {
102							const checkbox = jQuery( 'input[value="' + jQuery( this ).val() + '"]' );
103							checkbox.prop( 'disabled', false );
104							checkbox.closest( '.multiselect-option' ).removeClass( 'disabled' );
105						} );
106					}
107
108				}
109
110			},
111			onSelectAll: function( options ) {
112				select.dispatchEvent( new Event( 'change', { bubbles: true } ) );
113				$select.trigger( 'multiselect-change', options );
114			},
115			onDeselectAll: function(options) {
116				select.dispatchEvent( new Event( 'change', { bubbles: true } ) );
117				$select.trigger( 'multiselect-change', options );
118			},
119
120			// Translations
121			allSelectedText: multiselect_ajax_object.translations.allSelectedText,
122			filterPlaceholder: multiselect_ajax_object.translations.filterPlaceholder,
123			nonSelectedText: multiselect_ajax_object.translations.nonSelectedText,
124			nSelectedText: multiselect_ajax_object.translations.nSelectedText,
125			resetText: multiselect_ajax_object.translations.resetText,
126			selectAllText: multiselect_ajax_object.translations.selectAllText
127
128		};
129
130		if ( select.classList.contains( '-nosearch' ) ) {
131			args.enableFiltering = false;
132			args.enableCaseInsensitiveFiltering = false;
133		}
134
135		if ( $select.attr( 'data-nonSelectedText' ) ) {
136			args.nonSelectedText = $select.attr( 'data-nonSelectedText' );
137		}
138
139		if ( $select.attr( 'data-allSelectedText' ) ) {
140			args.allSelectedText = $select.attr( 'data-allSelectedText' );
141		}
142
143		if ( $select.attr( 'data-includeSelectAllOption' ) ) {
144			args.includeSelectAllOption = parseInt( $select.attr( 'data-includeSelectAllOption' ), 10 );
145		}
146
147		// Customize the dropdown text relevant to the selections
148		if ( $select.attr( 'data-show-selected-number' ) && args.nonSelectedText ) {
149			args.buttonText = function( options, select ) {
150				const nonselectedtext = select[0].getAttribute( 'data-nonselectedtext' );
151				const selected = options.length === 1 ? ' (' + options[0].label + ')' : options.length ? ' (' + options.length + ')' : '';
152				return nonselectedtext + selected;
153			};
154		}
155
156		// Add the multiple attr if it doesn't exist yet
157		if ( ! $select.attr( 'multiple' ) && ! $select.hasClass( '-single' ) ) {
158			$select.attr( 'multiple', 'multiple' );
159			$select.find( 'option' ).prop( 'selected', false ); // Native non-multiple select has first option selected by default
160		}
161
162		// Keep a copy of the original element in memory, for when we need to re-initialize it after cloning.
163		const uid = '_' + Date.now() + '_' + i;
164		window['multiselect_originals'] = window['multiselect_originals'] || {};
165		window['multiselect_originals'][ uid ] = $select.clone();
166		$select.attr( 'data-uid', uid );
167
168		// Init
169		$select.multiselect( args );
170
171    });
172}
173
174// Load the Bootstrap Multiselect library (once) when a multiselect is present, then init.
175// Runs on page load and again for content arriving via ajax template parts (e.g. the conditional-page swap),
176// where the first select may only appear after the initial load.
177function saas_ensure_bs_multiselect() {
178
179	if ( ! document.querySelector( 'select[multiple], .filterable select, .multiselect' ) ) {
180		return;
181	}
182
183	saas_load_jquery( function() {
184
185		const script_id = 'bootstrap-multiselect-lib-js';
186		const existing = document.getElementById( script_id );
187
188		// Library present and executed: init straight away.
189		if ( existing && typeof jQuery.fn.multiselect === 'function' ) {
190			saas_init_bs_multiselect();
191			return;
192		}
193
194		// Library still loading (a previous call injected it): init once it lands.
195		if ( existing ) {
196			existing.addEventListener( 'load', saas_init_bs_multiselect );
197			return;
198		}
199
200		const script = document.createElement( 'script' );
201		document.body.appendChild( script );
202		script.id = script_id;
203		script.onload = function() {
204
205			// Init on pageload
206			saas_init_bs_multiselect();
207
208			// Reinit on GF validation error
209			jQuery( document ).bind( 'gform_post_render', saas_init_bs_multiselect );
210
211		}
212		script.async = false;
213		script.src = multiselect_ajax_object.bootstrap_multiselect_lib;
214
215	} );
216
217}
218
219saas_ensure_bs_multiselect();
220document.body.addEventListener( 'ajax-template-loaded', saas_ensure_bs_multiselect );

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.