PageSourceSearch

https://fefc.biz/res/system/js/mwSelectInput.js

js fefc.biz collected 2026-10-08 16:14:47 UTC 24,798 bytes, 856 lines download raw bytes

1/** //** ----= CLASS mwSelectInput	=------------------------------------------------------------------------------\**//** \
2*
3*	Selector input JS model. Supports dropdowns, multiselects, custom item input, inline filtering and adding new items.	
4*
5* 	@package	morweb
6* 	@subpackage	system
7* 	@category	model
8*
9\**//** ---------------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/
10jQuery.fn.mwSelectInput = function ($options) {
11
12	if ( !this.length )
13		return;
14
15	// Retrieving or creating model
16	var $obj = this.data('mwSelectInput') || mwSelectInput(this);	//.set($options);
17	
18	// Storing in element
19	this.data('mwSelectInput', $obj);
20
21	// Done
22	return $obj;
23
24} //FUNC mwSelectInput
25
26function mwSelectInput ( $el, $options ) { return vEventObject(['onInit', 'onChange', 'onFilter', 'onAdd'], {
27
28	dom			: {			// Contains shortcuts to usable elements
29	
30		// Main
31		container		: false,		// mwInput element
32		input			: false, 		// Main input (hidden)
33
34		// Panels
35		face			: false,		// Face bar, wrapping around value input and dropdown button 
36		filter			: false, 		// Filter input, used to filter items in list
37		body			: false, 		// Main dropdown body (filter and items container)
38		list			: false, 		// Items wrapper
39
40		// Controls 		
41		iValue			: false,		// Value input, used to to display selected value or as custom input 
42		iSearch			: false, 		// Search input, used to filter items in list
43		btnDown			: false,		// Dropdown button subcontrol
44		btnAdd			: false,		// Button for adding custom values
45		btnClear		: false,		// Button for resetting search filter
46
47		// Misc		
48		items			: false, 		// Individual rendered option items
49
50		overlay			: false, 		// Overlay, when used
51		
52	}, //dom
53
54	multiselect		: false,			// Set TRUE to allow multiple values (checkList) 
55	multiline		: false,			// Set TRUE to use as multiline input 
56	filter			: false,			// Set TRUE to use inline filtering
57	custom			: false,			// Set TRUE to allow custom values (additinal input)
58	noMobile		: false,			// Set TRUE to skip init when used with mobile device (relies on native experience)
59
60	resizeDelay		: 5,				// Resize update delay
61	resizeTimout		: false,			// Stores timout during window resizing
62
63/* ==== SETUP =============================================================================================================== */
64
65	/** //** ----= set	=--------------------------------------------------------------------------------------\**//** \
66	*
67	*	Updates self properties with given values.
68	*
69	*	@param	MIXED	$option		- Option to set. Can be data object to setup several properties.
70	*	@param	MIXED	[$value]	- Value to set. Not used if object passes as first parameter.
71	*
72	*	@return SELF
73	*
74	\**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/
75	set		: function ($option, $value) {
76
77		var $this = this;
78
79		// Values can come as object, or single value
80		// Applying using object, for code unification below
81		// Any variable are accepted, to allow custom data storage
82		var $o = {};
83
84		if ( arguments.length === 1 )
85			$o = $option;
86		else
87			$o[$option] = $value;
88
89	// ==== Events ====
90
91		// Processing events, as those should be cleared before extending
92		for ( var $i in $o ) {
93
94			// Skipping non events and non funcitons
95			if ( !this.__events[$i] || !isFunction($o[$i]) )
96				continue;
97
98			// Setting up event, and removing it from opitons
99			this[$i]($o[$i]);
100			delete($o[$i]);
101
102		} //FOR each opiton
103
104	// ==== Self ====
105
106		jQuery.extend(this, $o);
107
108		return this;
109
110	}, //FUNC set
111
112/* ==== INIT ================================================================================================================ */ 
113
114	/** //** ----= init	=--------------------------------------------------------------------------------------\**//** \
115	*
116	*	Initiates payment form.
117	*
118	*	@return self
119	*
120	\**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/
121	init			: function () {
122
123		var $this = this;
124	
125	// ---- Main ----	
126		
127		// Saving main input and looking for wrapper
128		$this.dom.input		= $el;
129		$this.dom.container	= $el.closest('.mwInput');
130		
131		// Few shortcuts
132		var $container		= $this.dom.container;
133		var $input		= $this.dom.input;
134
135		// Adding required classes to wrapper
136		$this.dom.container.addClass('list');
137
138	// ---- Flags ----
139
140		// Reading flags from wrapper and input
141		// ToDo: improove flags management: classes should be guaranteed during render, for CSS. 
142		// Need to put back applied flags	
143		$this.set({
144			multiselect	: $input.is('[multiple]'),
145			multiline	: $container.is('.multiline'),
146			filter		: $container.is('.filter'),
147			custom		: $container.is('.custom'),
148			noMobile	: $container.is('.noMobile'),
149		}); //set
150
151	// ---- Mobile ----
152	
153		// If mobile is used - need to skip render optionally
154		if ( $this.noMobile && isTouchScreen() ) {
155			
156			// For mobile version - skipping render, but showing regular select instead
157			// Adding marker
158			$this.dom.container.addClass('isMobile');
159			
160			return;
161			
162		} //IF mobile
163
164	// ---- DOM ----	
165
166		// Hiding main select element
167		$this.dom.input.hide();
168
169		// Rendering face first
170		$this.renderFace();
171
172		// Then goes body, everything else would be inside
173		$this.renderBody();
174
175	// ---- Styles ----
176
177
178	// ---- Events ----
179
180		$this.initEvents();
181
182		// Initial update
183		$this.update();
184
185		return $this;
186		
187	}, //FUNC init
188
189	/** //** ----= initEvents	=------------------------------------------------------------------------------\**//** \
190	*
191	*	Initializes events. All in one place, for easier management.
192	*
193	*	@return SELF
194	*
195	\**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/
196	initEvents		: function ( ) {
197	
198		// Few shortucts
199		var $this	= this;
200		var $input	= $this.dom.input;
201		var $container	= $this.dom.container;
202		
203		// When select updates - it should update items and face
204		$this.dom.input.on('change.mwSelect', function () {
205			
206			$this.update();
207			
208		}); //FUNC input.onchange
209
210		// Adding item clicks, listening on body, in case reinit/changes happen in list or items 
211		$this.dom.body.on( 'click.mwSelect', '.item', function () {
212		
213			// Getting elements
214			var $item	= jQuery(this);
215			var $option	= $item.data('option');
216			
217			// No need to do anything if already selected option is clicked again
218			// Applicable only for non-multiselect
219			if ( !$this.multiselect && $option.prop('selected') )
220				return;
221		
222			// Updating property only. Attribute will be also updated by updateItems()
223			// Doing this way to ensure that correct attributes are updated on all items 
224			$option.prop( 'selected', !$option.prop('selected') );
225
226			// Triggering change on main input
227			$this.dom.input.trigger('change');
228		
229		}); //FUNC item.onclick	
230
231		// Filter executs on key presses, if input available
232		if ( $this.filter ) {
233			
234			$this.dom.iSearch.on('keyup.mwSelect', function () {
235
236				// Updating items, this will apply filter
237				$this.update();
238				
239			}); //FUNC input.onchange
240
241			$this.dom.btnClear.on('click.mwSelect', function () {
242
243				// Just clearing filter value and updating items
244				$this.dom.iSearch.val('');	
245
246				// Updating items, this will apply filter
247				$this.update();
248
249			}); //FUNC input.onchange
250			
251		} //IF filter enabled
252
253		// In inline mode - need to show/hide body
254		if ( !$this.multiline ) {
255
256			// Dropdown button always works
257			$this.dom.btnDown.on('click.mwSelect', function () {
258
259				// Showing/hiding depending on state
260				$this.toggleBody();
261				
262			}); //FUNC button.onclick
263
264			// For non-custom inputs - value also toggles body
265			if ( !$this.custom )
266				// Dropdown button always works
267				$this.dom.iValue.on('click.mwSelect', function () {
268	
269					// Showing/hiding depending on state
270					$this.toggleBody();
271					
272				}); //FUNC input.onclick
273
274			
275		} //IF inline mode
276		
277	}, //FUNC initEvents
278
279/* ==== Render ============================================================================================================== */ 
280
281	/** //** ----= renderBody	=------------------------------------------------------------------------------\**//** \
282	*
283	*	Renders main body element.
284	*
285	*	@return SELF
286	*
287	\**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/
288	renderBody		: function ( ) {
289
290		// Few shortucts
291		var $this	= this;
292		var $input	= $this.dom.input;
293		var $container	= $this.dom.container;
294		
295		// Marking body as inline if necessary for CSS
296		var $mode	= $this.multiline ? 'multiline absoluteFill' : 'mwInput oneline';
297		$this.dom.body	= jQuery('<div class="body '+$mode+'"></div>').appendTo($container);
298		
299		// Reset of css would be set on display
300	
301	// ---- Children ----	
302		
303		// Rendering filter, it goes inside body
304		$this.renderFilter();
305		
306		// Now can render items list
307		$this.renderList();
308		
309		return $this;
310		
311	}, //FUNC renderBody
312
313	/** //** ----= renderFace	=------------------------------------------------------------------------------\**//** \
314	*
315	*	Renders face panel. Used to display current value and entering custom value for inline mode. 
316	*
317	*	@return SELF
318	*
319	\**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/
320	renderFace		: function ( ) {
321
322		// Few shortucts
323		var $this	= this;
324		var $input	= $this.dom.input;
325		var $container	= $this.dom.container;
326
327		// Adding face controls only for inline input
328		if ( $this.multiline )
329			return $this;
330		
331		// Creating elements as one html chunk, then finding referrences afterwards
332		var $html	= '';
333		
334		// Subcontrol button goes first, as it's floating
335		$html		= '<div class="subcontrol right icon gray dropdown"></div>';
336		
337		// Input is wrapped in div to behave properly with floated element nearby
338		$html		= $html+'<div class="subInput value"><input type="text" class="mw" /></div>';
339		
340		// Finally - entire thing is wrapped into another element
341		$html		= '<div class="face">'+$html+'</div>';
342
343		// Appending entire thing to container
344		jQuery($html).appendTo($container);
345
346		// Looking for individual elements now
347		$this.dom.iValue	= $container.find('.subInput.value input');
348		$this.dom.btnDown	= $container.find('.subcontrol.dropdown');
349		$this.dom.face		= $container.find('.face');
350
351		// If custom input is not used - value is only for display, so making it readonly
352		if ( !$this.custom )
353			$this.dom.iValue.attr('readonly', 'readonly');
354
355		return $this;
356
357	}, //FUNC renderFace
358
359	/** //** ----= renderFilter	=------------------------------------------------------------------------------\**//** \
360	*
361	*	Renders filter panel. Used to filter items list, and adding custom values for multiselects.
362	*
363	*	@return SELF
364	*
365	\**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/
366	renderFilter		: function ( ) {
367		
368		// Few shortucts
369		var $this	= this;
370		var $input	= $this.dom.input;
371		var $container	= $this.dom.container;
372
373		// Adding filter only if it's allowed
374		if ( !$this.filter )
375			return $this;
376
377		// Filter is positioned inside body wrapper, to display and hide together with list
378		// Preparing html for filter bar
379		
380		// Subcontrols buttons go first, as they're floating
381		var $html	= '';
382		$html		+= '<div class="subcontrol left icon gray search"></div>';
383		$html		+= '<div class="subcontrol right button icon hi plus add"></div>';
384		$html		+= '<div class="subcontrol right icon delete clear gray"></div>';
385		
386		// Input is wrapped in div to behave properly with floated element nearby
387		$html		= $html+'<div class="subInput search"><input type="text" class="mw" /></div>';
388		
389		// Finally - entire thing is wrapped into another element
390		$html		= '<div class="filter">'+$html+'</div>';
391
392		// Appending entire thing to container
393		jQuery($html).appendTo($this.dom.body);
394
395		// Looking for individual elements now
396		$this.dom.filter	= $this.dom.body.find('.filter');
397		
398		$this.dom.iSearch	= $this.dom.filter.find('.subInput.search input');
399		$this.dom.btnAdd	= $this.dom.filter.find('.subcontrol.add');
400		$this.dom.btnClear	= $this.dom.filter.find('.subcontrol.clear');
401		
402		return $this;
403		
404	}, //FUNC renderFilter
405
406	/** //** ----= renderList	=------------------------------------------------------------------------------\**//** \
407	*
408	*	Renders items panel, including individual items.
409	*
410	*	@return SELF
411	*
412	\**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/
413	renderList		: function ( ) {
414		
415		// Few shortucts
416		var $this	= this;
417		var $input	= $this.dom.input;
418		var $container	= $this.dom.container;
419
420	// ---- Wrap ----
421		
422		// Clearing old wrapper if any happen
423		if ( $this.dom.list )
424			$this.dom.list.remove();
425
426	 	// Recreating items wrapper
427	 	$this.dom.list	= jQuery('<div class="list"></div>').appendTo( $this.dom.body );
428
429	// ---- Items ----
430
431		// Resetting items collection		
432		$this.dom.items	= jQuery([]);
433
434		// Looping through options and generating items
435		// ToDo: support grouping, custom icons, columns and more
436		$input.find('option').each( function () {
437			
438			var $option	= jQuery(this);
439			
440			// Rendering item into body
441			var $item	= $this.renderItem($option).appendTo( $this.dom.list );
442			
443			// And storing it in self for future reuse
444			$this.dom.items	= $this.dom.items.add($item); 
445			
446		}); //FOR each item
447	 
448		return $this;
449		
450	}, //FUNC renderList
451
452	/** //** ----= renderItem	=------------------------------------------------------------------------------\**//** \
453	*
454	*	Renders single item.
455	*
456	*	@return SELF
457	*
458	\**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/
459	renderItem		: function ( $option ) {
460
461		// Few shortucts
462		var $this	= this;
463
464	// ---- Text ----
465
466		var $text	= $option.html(); 
467	
468	// ---- Image ----
469		
470		// Preparing image if any
471		var $image	= $option.attr('data-image');
472		var $imageHtml	= '';
473		
474		if ( $image ) {
475			
476			$imageHtml = '<div class="image" style="background-image: url(\''+$image+'\')"></div>';
477			
478		} //IF image provided
479
480	// ---- Counter ----
481
482		// Adding counter
483		var $count	= $option.attr('data-count');
484		var $countHtml	= '';
485		
486		if ( $count ) {
487			
488			$countHtml = '<div class="count">'+$count+'</div>';
489			
490		} //IF count provided
491
492	// ---- Item ----
493		
494		// Creating item
495		var $item	= jQuery('<div class="item icon hi left">'+$imageHtml+$countHtml+$text+'</div>');
496		
497		// Setting up links
498		$option.data('item', $item);
499		$item.data('option', $option);
500			
501		return $item;
502		
503	}, //FUNC renderItem
504
505	/** //** ----= renderOverlay	=------------------------------------------------------------------------------\**//** \
506	*
507	*	Renders overlay.
508	*
509	*	@return SELF
510	*
511	\**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/
512	renderOverlay		: function ( ) {
513
514		// Few shortucts
515		var $this	= this;
516		
517		// Adding overlay to page
518		$this.dom.overlay	= jQuery('<div class="mwInputOverlay mwInput list"></div>').appendTo('body');
519		
520		// Marking body with class as flag 
521		// And Moving body inside overlay
522		$this.dom.body
523		//	.addClass('show')
524			.appendTo($this.dom.overlay);
525		
526		// Click on overlay hides stuff
527		$this.dom.overlay.on('click', function ($e) {
528			
529			$this.hideBody();
530
531			$e.stopPropagation();
532			
533		}); //FUNC overlay.click
534		
535		// Preventing click on body for closing (only for multiselects)
536
537		if ( $this.multiselect )
538			$this.dom.body.on('click', function ($e) {
539				
540				$e.stopPropagation();
541				
542			}); //FUNC body.click
543
544		// Filter never closes anyway
545		if ( $this.filter )
546			$this.dom.filter.on('click', function ($e) {
547				
548				$e.stopPropagation();
549				
550			}); //FUNC body.click
551
552	// ---- Resize ----
553
554		// If body resizes for some readon - need to update selector position
555		// Doing this only for inline mode
556		
557		// Initiating window resize after small delay
558		// to skip initial browser resizie events
559		setTimeout( function () {
560
561			// Updating dimensions on resize
562			jQuery(window).on('resize.mwSelect', function ($e) {
563	
564				// Using timeout during resize, to reduce updates count
565				if ( $this.resizeTimout )
566					clearTimeout($this.resizeTimout);
567								
568				$this.resizeTimout = setTimeout( function () {
569			
570					$this.updatePosition();
571			
572				}, $this.resizeDelay);
573				
574			}); //window.onResize
575			
576		}, 50);
577			
578		return $this;
579		
580	}, //FUNC renderOverlay
581
582/* ==== Display ============================================================================================================= */ 
583
584	/** //** ----= showBody	=--------------------------------------------------------------------------------------\**//** \
585	*
586	*	Displays body, recalculating positions.
587	*
588	*	@return SELF
589	*
590	\**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/
591	showBody		: function (  ) {
592
593		// Few shortucts
594		var $this	= this;
595		
596		// Creating overlay, this will also move body inside
597		$this.renderOverlay();
598
599		// Displaying overlay
600		$this.dom.overlay.show();
601		
602		setTimeout( function () {
603
604			// While it adjusts - can now reposition body
605			// At this point - everything is rendered and have dimensions
606			$this.updatePosition();
607
608			// Finally - executing fade/slide animation			
609			$this.dom.body.addClass('show')
610			$this.dom.overlay.addClass('show');
611
612		}, 1);
613		
614	}, //FUNC showBody
615
616	/** //** ----= hideBody	=--------------------------------------------------------------------------------------\**//** \
617	*
618	*	Hides body.
619	*
620	*	@return SELF
621	*
622	\**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/
623	hideBody		: function (  ) {
624
625		// Few shortucts
626		var $this	= this;
627
628		// Hiding overlay and unflagging body
629		$this.dom.overlay.removeClass('show');
630		$this.dom.body.removeClass('show');
631
632		// Allowing it to play animation with timeout
633		setTimeout( function () {
634
635			// Putting body back, where it belongs :)
636			// This will also hide it. Inline body is display:none outside overlay
637			$this.dom.body.appendTo( $this.dom.container );
638	
639			// Removing overlay from DOM now 
640			$this.dom.overlay.remove();
641
642			// Clearing resizing tracking
643			jQuery(window).off('resize.mwSelect');
644
645		}, 200);
646
647	}, //FUNC hideBody
648
649	/** //** ----= toggleBody	=------------------------------------------------------------------------------\**//** \
650	*
651	*	Toggles body visibility, depending on current state.
652	*
653	*	@return SELF
654	*
655	\**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/
656	toggleBody		: function (  ) {
657
658		// Few shortucts
659		var $this	= this;
660
661		// Just looking at body state
662		if ( $this.dom.body.is('.show') ) {
663			$this.hideBody();
664		} //IF visible
665		else {
666			$this.showBody();
667		} //IF hidden
668
669	}, //FUNC toggleBody
670	
671/* ==== HELPERS ============================================================================================================= */ 
672	
673	/** //** ----= getPosition	=-------------------------------------------------------------------------------\**//** \
674	*
675	* 	Returns panel position relative to screen.
676	* 
677	\**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/
678	getPosition		: function () {
679
680		var $this	= this;
681		var $el		= $this.dom.container;
682		 
683		var $offs	= $el.offset();
684		var $sTop	= jQuery(window).scrollTop();
685		var $sLeft	= jQuery(window).scrollLeft();
686		
687		// Recalculating coords based on scroll position
688		$offs.top	= $offs.top - $sTop;
689		$offs.left	= $offs.left - $sLeft;
690		
691		return $offs;
692		
693	}, //FUNC getPosition
694
695	/** //** ----= updatePosition	=-------------------------------------------------------------------------------\**//** \
696	*
697	* 	Updates body position against element
698	* 
699	\**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/
700	updatePosition		: function () {
701
702		var $this	= this;
703		
704		// Not doing anything for non-inline mode and if not visible
705		if ( $this.multiline )
706			return;
707
708		// Few shortcuts
709		var $input	= $this.dom.container;
710		var $body	= $this.dom.body;
711
712		// Getting input coordinates and screen size
713		var $pos	= $this.getPosition();
714		var $screen	= screenSize();
715
716		// Calculating margi as % of screen height
717		// Carrying only about height, since that's what is mostly positioned
718		var $margin	= $screen.height * 0.05;
719		
720		// Getting real body height and calculating max allowed
721		// For this - clearing height first
722		$this.dom.list.css('max-height', '');
723 
724		var $height	= $body.height();
725		var $limit	= $height; 
726		var $max	= $screen.height - ($margin * 2);
727
728		// Calculating real height limit (should be set on list inside body)
729		// Clearing if not necessary anymore (screen resize)
730		if ( $height > $max ) {
731			
732			$limit	= $max;
733			
734			// Accounting for filter if present
735			$this.dom.list.css('max-height', $limit - ($this.filter ? $this.dom.filter.outerHeight() : 0));
736			
737		} //IF too big 
738		
739		// Calculating new top based on real height and limits
740		// Starting from middle of input
741		var $top	= ($pos.top + ($this.dom.container.height() / 2)) - ($limit / 2);
742
743		// Correcting top: it should be lower than margin
744		if ( $top < $margin )
745			$top = $margin;
746
747		// But also can't be too low (top+height higher than margin)
748		if ( $top + $limit > $screen.height - $margin )
749			$top = $screen.height - $margin - $limit;
750		
751		// Adjusting body
752		// Slightly adjusting sizes, to do not mess with borders recalculations
753		// ToDo: read borders from skin			
754		$this.dom.body.css({
755			width		: $this.dom.container.width() - 2,
756			left		: $pos.left + 1,
757			top		: $top, //$pos.top + ($this.dom.container.height() / 2),
758		}); //$css
759		
760	}, //FUNC updatePosition
761	
762	/** //** ----= update	=--------------------------------------------------------------------------------------\**//** \
763	*
764	*	Updates item states based on current selector state. Uses filtering if available.
765	*	Additionally updats filter states, and face if available.
766	*
767	*	@return SELF
768	*
769	\**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/
770	update		: function (  ) {
771
772		// Few shortucts
773		var $this	= this;
774		
775		// Reading/updating filter
776		var $filter	= '';
777		
778		if ( $this.filter ) {
779
780			$filter	= $this.dom.iSearch.val();
781
782			// Showing/hiding clear button
783			if ( $filter )
784				$this.dom.btnClear.show();
785			else
786				$this.dom.btnClear.hide();
787			
788		} //IF filter used
789
790		// Updating face when applicable
791		// For this - collecting selected values, and concatenating them into lavel afterwards
792		var $val	= [];
793				
794		// Just looping through items list and setting selected class
795		$this.dom.items.each( function () {
796
797			var $item	= jQuery(this);
798			var $option	= $item.data('option');
799
800			// Checking if matching filter, or just showing them all
801			if ( $filter ) {
802				
803				// Using regex seaerch for case insensitivity
804				// ToDo: escape filter value
805				if ( $option.html().search( new RegExp($filter, 'i') ) == -1 )
806					$item.hide();
807				else
808					$item.show();
809				
810			} //If filter applied
811			else {
812
813				// Just showing, this makes sure we display all items if filter was just cleared
814				$item.show();
815
816			} //IF filter not applied or just cleared
817		
818			// Marking item as selected
819			if ( $option.prop('selected') )	
820				$item.addClass('selected');
821			else
822				$item.removeClass('selected');
823
824			// Collecting selected values for face update
825			if ( $option.prop('selected') )	{
826
827				$val.push( $option.text().trim() );
828
829			} //IF found selected
830		/*/ 			
831			// Additionally - setting selected atribute on option, for whoever needs this
832			// But this is supported only on multiselects
833			// This appears to be quite slow for obvious reasons, so skipping it for now as noone really needs it :) 
834			if ( !$this.dom.input.is('[multiple]')  )
835				return;
836
837			if ( $option.prop('selected') )	
838				$option.attr('selected', 'selected');
839			else
840				$option.removeAttr('selected', '');
841		/**/
842		}); //FOR each item
843
844		// If nothing found - using first option to display something (that's what would be submitted in the end)
845		// Only for non multiline selectors though
846		if ( !$this.multiselect && isEmpty($val) && $this.dom.items.length ) {
847			$val.push( $this.dom.items.first().data('option').text().trim() );
848		} //IF no values
849	
850		// Now can apply value
851		if ( !$this.multiline )
852			$this.dom.iValue.val( $val.join(', ') || '- Please select one or multiple -' );
853			
854	}, //FUNC update
855
856}).init()} //CONSTRUCTOR mwCodeInput

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.