PageSourceSearch

https://www.centa-star.com/wp-content/plugins/greyd-plugin/src/features/multiselects/public.js?ver=2.22.2

js centa-star.com collected 2026-10-04 20:52:40 UTC 17,896 bytes, 549 lines download raw bytes

1/**
2 * Custom Input Scripts
3 * - multiselect
4 * - select
5 * - checkbox
6 * - radio
7 * 
8 * Moved from classic greyd default.js
9 * was global default.js variable 'custom_inputs'
10 */
11
12var greyd = greyd || {};
13
14( function() {
15	jQuery( function() {
16		if ( typeof $ === 'undefined' ) $ = jQuery;
17
18		// do not init if classic theme is detected
19		if ( typeof theme !== 'undefined' ) return;
20
21		greyd.input.init();
22
23		console.log( "Input Scripts: loaded" );
24	} );
25} )( jQuery );
26
27
28/**
29 * init greyd.input var
30 */
31greyd.input = greyd.input || {};
32
33/**
34 * init all inputs
35 * multiselects, selects, checkboxes, radios
36 */
37greyd.input.init = function() {
38	greyd.input.multiselects.init();
39	greyd.input.selects.init();
40	greyd.input.boxes.init();
41}
42
43/**
44 * close all multiselect and select boxes in the document
45 * except the current select box
46 */
47greyd.input.closeAll = function( current ) {
48	greyd.input.multiselects.closeAll();
49	greyd.input.selects.closeAll(current);
50}
51
52
53/**
54 * Multiselect
55 */
56greyd.input.multiselects = new function() {
57
58	/**
59	 * Custom multiselects
60	 */
61	this.init = function() {
62
63		if ( typeof $ === 'undefined' ) $ = jQuery;
64
65		// console.log( "greyd.input.multiselects init" );
66
67		$( ".greyd_form select[multiple]" ).each( function() {
68			greyd.input.multiselects.render( this );
69		} );
70
71		$( ".greyd_multiselect" ).each( function() {
72			var wrap = $( this );
73			var input = wrap.find( ".input" );
74
75			// open the dropdown
76			input.off( "click" ).on( "click", function( e ) {
77				e.stopPropagation();
78				var open = wrap.hasClass( "open" ) ? false : true;
79				$( ".greyd_multiselect" ).each( function() { $( this ).removeClass( "open" ); } );
80				greyd.input.closeAll(null);
81				if ( open ) {
82					wrap.addClass( "open" );
83					$( document ).one( "click", function() {
84						wrap.removeClass( "open" );
85					} );
86				}
87			} );
88
89			// toggle tag
90			var option = wrap.find( ".option" );
91			option.off( "click" ).on( "click", function( e ) {
92				greyd.input.multiselects.toggleValue( this, e );
93			} );
94
95		} );
96
97		// control multiselects and multiradio with keyboard
98		document.addEventListener( "keydown", e => {
99
100			const multiselectWrapper = e.target?.closest( ".greyd_multiselect" );
101			if ( multiselectWrapper && multiselectWrapper?.querySelector( "input" ) ) {
102
103				if ( multiselectWrapper?.classList?.contains( "open" ) ) {
104					if ( e.key == "ArrowUp" || e.key == "ArrowDown" ) {
105						e.preventDefault();
106						greyd.input.multiselects.focusNextItem( e );
107					}
108					else if ( e.key == " " && e.target.classList.contains( "option" ) ) {
109						const option = e.target;
110						e.preventDefault();
111						greyd.input.multiselects.toggleValue( option, e );
112					}
113					else if (
114						e.key == "Escape" ||
115						e.key == " " && e.target.classList.contains( "input" )
116					) {
117						e.preventDefault();
118						greyd.input.closeAll(null);
119					}
120					else if ( e.key == "Tab" ) {
121						const activeElement = document.activeElement;
122						if (
123							( e.shiftKey && e.target.classList.contains( "input" ) ) ||
124							( !e.shiftKey && !activeElement.nextElementSibling )
125						) {
126							greyd.input.closeAll(null);
127						}
128					}
129				}
130				else {
131					if (
132						e.key == "Enter" ||
133						e.key == " " && e.target.classList.contains( "input" )
134					) {
135						e.preventDefault();
136						multiselectWrapper.classList.add( "open" );
137					}
138				}
139			
140			}
141			else if ( e.target?.closest( ".greyd_multiradio" ) ) {
142
143				if ( e.key == "ArrowUp" || e.key == "ArrowDown" ) {
144					// console.log(e);
145					e.preventDefault();
146					const activeElement = document.activeElement;
147					if ( activeElement.nextElementSibling && e.key == "ArrowDown" ) {
148						activeElement.nextElementSibling.focus();
149					}
150					else if ( activeElement.previousElementSibling && e.key == "ArrowUp" ) {
151						activeElement.previousElementSibling.focus();
152					}
153				}
154				else if ( e.key == " " && e.target.classList.contains( "option" ) ) {
155					e.preventDefault();
156					e.target.onclick();
157				}
158			}
159
160		} );
161
162	};
163
164	/**
165	 * Events
166	 */
167	this.toggleValue = function( elem, e ) {
168		e.stopPropagation();
169		elem = $( elem );
170		if ( elem.hasClass( 'selected' ) )
171			this.removeValue( elem, e );
172		else
173			this.addValue( elem, e );
174	};
175
176	this.removeValue = function( elem, e ) {
177		e.stopPropagation();
178		elem = $( elem );
179		var val = elem.data( 'value' );
180		var wrap = elem.closest( '.greyd_multiselect' );
181
182		// reset option
183		wrap.find( '.dropdown .option[data-value="' + val + '"]' ).removeClass( 'selected' );
184
185		// remove tag
186		wrap.find( '.input .tag[data-value="' + val + '"]' ).remove();
187
188		// remove value
189		var field = wrap.find( 'input' );
190		var values = field.val().split( ',' );
191		values = values.filter( function( v, i ) {
192			if ( v != "" && v != val && values.indexOf( v ) == i ) return true;
193		} );
194		greyd.input.multiselects.setValue( field, values.join( ',' ) );
195		// greyd.input.multiselects.setValue( field, field.val().replace(val, "") );
196	};
197
198	this.addValue = function( elem, e ) {
199		e.stopPropagation();
200		elem = $( elem );
201		var val = elem.data( 'value' );
202		var name = elem.text();
203		var wrap = elem.closest( '.greyd_multiselect' );
204		var input = wrap.find( '.input' );
205
206		// highlight option
207		wrap.find( '.dropdown .option[data-value="' + val + '"]' ).addClass( 'selected' );
208
209		// append tag
210		// var tag     = input.data('tag');
211		var tag = decodeURIComponent( input.data( 'tag' ) );
212		tag = tag.replace( "{value}", val ).replace( "{name}", name );
213		input.find( '.tags' ).append( tag );
214
215		// add value
216		var field = wrap.find( 'input' );
217		var values = field.val().split( ',' );
218		values.push( val );
219		values = values.filter( function( v, i ) {
220			if ( v != "" && values.indexOf( v ) == i ) return true;
221		} );
222		greyd.input.multiselects.setValue( field, values.join( ',' ) );
223		// greyd.input.multiselects.setValue( field, field.val()+","+val );
224	};
225
226	this.setValue = function( field, value ) {
227		// cleanup double commas or commas at the end or beginning of the string
228		// field.val( value.replace(/,+/, ",").replace(/^,|,$/, "") );
229		field.val( value );
230		field.trigger( "change" );
231	};
232
233	this.render = function( select ) {
234		var placeholder = '';
235		var options = {};
236		var values = [];
237		var name = select.getAttribute( 'name' );
238		var className = select.getAttribute( 'class' );
239		var required = select.hasAttribute( 'required' );
240		var tag_code = "<span class=\"tag\" data-value=\"{value}\" onclick=\"greyd.input.multiselects.removeValue(this, event);\">{name}<span class=\"icon_close\"></span></span>";
241
242		$( select ).children( 'option' ).each( function() {
243			var txt = this.textContent;
244			var val = this.hasAttribute( 'value' ) ? this.getAttribute( 'value' ) : '';
245			if ( val == '' && placeholder == '' ) {
246				placeholder = txt;
247			} else {
248				val = val == '' ? txt : val;
249				options[ val ] = txt;
250				if ( this.hasAttribute( 'selected' ) )
251					values.push( val );
252			}
253		} );
254
255		// create wrapper
256		var wrap = document.createElement( "div" );
257		wrap.setAttribute( "class", "greyd_multiselect" );
258		select.after( wrap );
259
260		// remove original select
261		select.parentNode.removeChild( select );
262
263		// create input
264		var input = document.createElement( "input" );
265		input.setAttribute( "type", "text" );
266		input.setAttribute( "name", name );
267		input.setAttribute( "id", name );
268		input.setAttribute( "value", values.join( ',' ) );
269		input.setAttribute( "tabindex", -1 );
270		if ( required ) input.setAttribute( "required", "required" );
271		wrap.appendChild( input );
272
273		// create div.input
274		var div = document.createElement( "div" );
275		div.setAttribute( "class", "input" + ( className ? ' ' + className : '' ) );
276
277		// make it tabbable
278		div.setAttribute( "role", "listbox" );
279		div.setAttribute( "tabindex", 0 );
280		div.setAttribute( "aria-multiselectable", "true" );
281		div.setAttribute( "data-tag", encodeURIComponent( tag_code ) );
282		wrap.appendChild( div );
283
284		// create tags
285		var tags = document.createElement( "span" );
286		tags.setAttribute( "class", "tags" );
287		tags.setAttribute( "data-placeholder", placeholder );
288		div.appendChild( tags );
289		if ( values.length > 0 ) {
290			values.forEach( function( value, i ) {
291				var tag = $.parseHTML( tag_code.replace( /{value}/, value ).replace( /{name}/, options[ value ] ) );
292				$( tags ).append( tag );
293			} );
294		}
295
296		// create dropdown
297		var dropdown = document.createElement( "div" );
298		dropdown.setAttribute( "class", "dropdown" );
299		wrap.appendChild( dropdown );
300		for ( var val in options ) {
301
302			// create option
303			var option = document.createElement( "div" );
304			option.setAttribute( "class", "option" + ( values.indexOf( val ) >= 0 ? " selected" : "" ) );
305			option.setAttribute( "data-value", val );
306
307			// declare it as listbox child
308			option.setAttribute( "role", "option" );
309			option.setAttribute( "tabindex", 0 );
310			dropdown.appendChild( option );
311
312			var icon = document.createElement( "span" );
313			icon.setAttribute( "class", "icn" );
314			option.appendChild( icon );
315
316			option.innerHTML += options[ val ];
317		}
318	};
319
320	/**
321	 * Helper function for multiselects to switch between options with ArrowUp & Arrow Down
322	 * @param {event}
323	 */
324	this.focusNextItem = ( e ) => {
325		const key = e.key;
326		const target = e.target;
327		const activeElement = document.activeElement;
328
329		const selectWrapper = target.closest( ".greyd_multiselect" );
330		const selectGroup = selectWrapper.querySelector( ".dropdown" );
331		const items = selectGroup.children;
332
333		if ( activeElement.classList.contains( "input" ) && selectWrapper.classList.contains( "open" ) && key == "ArrowDown" ) {
334			items[ 0 ].focus();
335		} else if ( activeElement.nextSibling && key == "ArrowDown" ) {
336			activeElement.nextSibling.focus();
337		} else if ( activeElement.previousSibling && key == "ArrowUp" ) {
338			activeElement.previousSibling.focus();
339		} else return;
340	};
341	
342	/**
343	 * close all multiselect boxes in the document
344	 */
345	this.closeAll = function() {
346		var elements = document.getElementsByClassName("greyd_multiselect");
347		for (var i = 0; i < elements.length; i++) {
348			elements[i].classList.remove("open");
349		}
350	}
351};
352
353/**
354 * normal Select
355 */
356greyd.input.selects = new function() {
357	
358	/**
359	 * Custom selects
360	 */
361	this.init = function() {
362		var x, i, j, selElmnt, a, b, c;
363		// look for any elements with the class "custom-select":
364		x = document.getElementsByClassName("custom-select");
365		// console.log(x);
366		// x = document.getElementsByTagName("select");
367		for (i = 0; i < x.length; i++) {
368			// console.log(x[i]);
369			selElmnt = x[i].getElementsByTagName("select")[0];
370			if (typeof selElmnt === 'undefined') continue;
371			var t = x[i].getElementsByClassName("select-selected")[0];
372			if (typeof t !== 'undefined') continue;
373			// selElmnt = x[i];
374			// for each element, create a new DIV that will act as the selected item:
375			a = document.createElement("DIV");
376			a.setAttribute("class", "select-selected");
377			if (selElmnt.hasAttribute("style")) a.setAttribute("style", selElmnt.getAttribute("style"));
378			if (selElmnt.hasAttribute("title")) a.setAttribute("title", selElmnt.getAttribute("title"));
379			a.setAttribute("onmouseover", selElmnt.getAttribute("onmouseover"));
380			a.setAttribute("onmouseout", selElmnt.getAttribute("onmouseout"));
381			a.innerHTML = "<span>" + selElmnt.options[selElmnt.selectedIndex].innerHTML + "</span>";
382			// x[i].appendChild(a);
383			selElmnt.parentNode.insertBefore(a, selElmnt.nextSibling);
384			a.innerHTML += "<span class=\"select-icon\" aria-hidden=\"true\"></span>";
385			// x[i].parentElement.appendChild(a);
386			// for each element, create a new DIV that will contain the option list:
387			b = document.createElement("DIV");
388			b.setAttribute("class", "select-items select-hide");
389			b.style.marginTop = '-'+selElmnt.style.marginBottom;
390			b.style.fontSize = selElmnt.style.fontSize;
391			b.style.fontWeight = selElmnt.style.fontWeight;
392			b.style.color = selElmnt.style.color;
393			b.style.background = selElmnt.style.background;
394			b.style.borderRadius = selElmnt.style.borderRadius;
395			b.style.borderColor = selElmnt.style.borderColor;
396			b.style.borderWidth = selElmnt.style.borderWidth;
397			b.style.borderLeftStyle = selElmnt.style.borderLeftStyle;
398			b.style.borderRightStyle = selElmnt.style.borderRightStyle;
399			b.style.borderTopStyle = selElmnt.style.borderTopStyle;
400			b.style.borderBottomStyle = selElmnt.style.borderBottomStyle;
401
402			// for each option in the original select element...
403			for (j = 0; j < selElmnt.length; j++) {
404				// create a new DIV that will act as an option item:
405				c = document.createElement("DIV");
406				c.innerHTML = selElmnt.options[j].innerHTML;
407				c.dataset.value = selElmnt.options[j].getAttribute('value');
408
409				// custom css and hover
410				if (selElmnt.getAttribute("onmouseover") && selElmnt.getAttribute("onmouseout")) {
411					c.style.color = selElmnt.style.color;
412					c.style.background = selElmnt.style.background;
413					c.style.paddingLeft = selElmnt.style.paddingLeft;
414					c.style.paddingRight = selElmnt.style.paddingRight;
415					c.style.paddingTop = "5px";
416					c.style.paddingBottom = "5px";
417					// make onmouseover
418					var t = selElmnt.getAttribute("onmouseover");
419					t = t.split(' !important').join('');
420					if (t.indexOf('color: ') > -1) {
421						t = t.split('color: ');
422						var color = t[1].split(';');
423						var jscolor = "$(this).css('color','"+color[0]+"');";
424						t = t[1];
425					}
426					if (t.indexOf('background: ') > -1) {
427						t = t.split('background: ');
428						var background = t[1].split(';');
429						var jsbackground = "$(this).css('background','"+background[0]+"');";
430					}
431					// c.setAttribute("onmouseover", "$(this).css('color','"+color[0]+"');$(this).css('background','"+background[0]+"');");
432					c.setAttribute("onmouseover", jscolor+jsbackground);
433					// make onmouseout
434					var t = selElmnt.getAttribute("onmouseout");
435					t = t.split(' !important').join('');
436					if (t.indexOf('color: ') > -1) {
437						t = t.split('color: ');
438						var color = t[1].split(';');
439						var jscolor = "$(this).css('color','"+color[0]+"');";
440						t = t[1];
441					}
442					if (t.indexOf('background: ') > -1) {
443						t = t.split('background: ');
444						var background = t[1].split(';');
445						var jsbackground = "$(this).css('background','"+background[0]+"');";
446					}
447					// c.setAttribute("onmouseout", "$(this).css('color','"+color[0]+"');$(this).css('background','"+background[0]+"');");
448					c.setAttribute("onmouseout", jscolor+jsbackground);
449				}
450
451				// when an item is clicked, update the original select box
452				c.addEventListener("click", function(e) {
453					const select = this.parentNode.parentNode.getElementsByTagName("select")[0];
454					const index = [...this.parentElement.children].indexOf( this );
455					select.selectedIndex = index;
456					select.dispatchEvent(new Event('change'));
457					// close the dropdown
458					this.parentNode.classList.add("select-hide");
459					this.parentNode.previousSibling.classList.remove("select-arrow-active");
460				});
461				b.appendChild(c);
462			}
463			selElmnt.parentNode.insertBefore(b, a.nextSibling);
464
465			// when the select box is clicked, close any other select boxes,
466			a.addEventListener("click", function(e) {
467				// and open/close the current select box:
468				e.stopPropagation();
469				greyd.input.closeAll(this);
470				// this.nextSibling.classList.toggle("select-hide");
471				this.classList.toggle("select-arrow-active");
472				$(this.nextSibling).toggleClass("select-hide");
473			});
474
475			// change the fake select when changing the real select
476			selElmnt.addEventListener("change", function(e) {
477				const select = this;
478				const fakeSelect = select.parentNode.getElementsByClassName('select-selected')[0];
479				fakeSelect.innerHTML = "<span>" + select.options[select.selectedIndex].innerHTML + "</span>";
480				fakeSelect.innerHTML += "<span class=\"select-icon\" aria-hidden=\"true\"></span>";
481				const fakeOptions = select.parentNode.getElementsByClassName('select-items')[0];
482				const selectedOptions = fakeOptions.getElementsByClassName("same-as-selected");
483				selectedOptions.length && selectedOptions[0].classList.remove("same-as-selected");
484				fakeOptions.children[ select.selectedIndex ].classList.add("same-as-selected");
485			})
486		}
487		// if the user clicks anywhere outside the select box,
488		// then close all select boxes:
489		document.addEventListener("click", greyd.input.closeAll);
490	}
491	
492	/**
493	 * close all select boxes in the document
494	 * except the current select box
495	 */
496	this.closeAll = function( current ) {
497		var except = [];
498		var elements = document.getElementsByClassName("select-items");
499		var selected = document.getElementsByClassName("select-selected");
500		for ( var i=0; i<selected.length; i++ ) {
501			if ( selected[i] == current ) {
502				except.push(i);
503			}
504			else {
505				selected[i].classList.remove("select-arrow-active");
506			}
507		}
508		for ( var i=0; i<elements.length; i++ ) {
509			if ( except.indexOf(i) ) {
510				elements[i].classList.add("select-hide");
511			}
512		}
513	}
514
515};
516
517/**
518 * radio buttons & checkboxes
519 */
520greyd.input.boxes = new function() {
521
522	/**
523	 * Custom radio buttons & checkboxes
524	 */
525	this.init = function() {
526		let inputs = document.getElementsByTagName("input");
527		for ( var i=0; i<inputs.length; i++ ) {
528			// console.log(inputs[i]);
529			const input = inputs[i];
530
531			// check if next sibling already is an empty span
532			const nextSibling = input.nextSibling;
533			if (nextSibling && nextSibling.tagName == "SPAN") continue;
534
535			const isCustomCheckbox = input.type == "checkbox" && input.closest('form.greyd_form') !== null;
536			const isCustomRadio = input.type == "radio" && ( input.closest('form.greyd_form') !== null || input.closest('form.greyd-search-form ') !== null );
537
538			if ( isCustomCheckbox || isCustomRadio ) {
539				// console.log(input);
540				var lbl = document.createElement("span");
541				if ( input.hasAttribute("title") ) {
542					lbl.setAttribute("title", input.getAttribute("title"));
543				}
544				input.parentNode.insertBefore( lbl, input.nextSibling );
545			}
546		}
547	}
548
549};

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.