PageSourceSearch

https://www.burghotel-lech.com/(cms)/module/static/default/content/libs/js/vac/vac.js?v=4

js burghotel-lech.com collected 2026-09-28 08:19:17 UTC 26,893 bytes, 1,064 lines download raw bytes

1/*
2 * vac - Vioma AutoCompleter
3 * 
4 */
5
6if ( typeof vac == 'undefined' ) {
7	var vac = {
8		version: '0.1.3',
9		ready: false,
10		insts: [],
11		inst: {},
12		item: {},
13		countries: null,
14		events: 0,
15		eventIgnored: '',
16		timer: false,
17		interval: false,
18		ios: navigator.userAgent.match(/like Mac OS X/i) == 'like Mac OS X',
19		log: false
20	};
21	(function(jQuery) {
22		if ( 'console' in window ) {
23			var log = false;
24
25			if ( 'log' in window.console ) {
26				log = function( name, args ){
27					console.log( name, args )
28				};
29				//log( 'Vioma AutoCompleter ' + vac.version );
30			}
31
32			if ( vac.log ) {
33				vac.log = log;
34			}
35		}
36
37		// enter triggert teilweise ein click event, dieses hat jedoch (u.a.) keine screen(Y|X) angaben, woran wir es erkennen und ignorieren koennen
38		vac.isFakeClick = function( event ){
39			return event.type == 'click' && !event.screenX && !event.screenY;
40		};
41
42		// chrome's autocomplete triggers focus, keydown, keyup. we need to handle those a bit different to make autocomplete work for countries
43		vac.isFakeEvent = function( event ){
44			if (event.type === 'keyup' || event.type === 'keydown') {
45				return event.view === undefined && event.keyCode === undefined;
46			}
47
48			return false;
49		};
50
51		vac.init = function(){
52			if ( this.log ) this.log( 'vac.init()', arguments );
53
54			this.container = jQuery( document.createElement( 'div' ) )
55				.attr( 'class', 'vac' )
56				.bind( 'click', function( event ){
57					if ( vac.isFakeClick( event ) ) {
58						return;
59					}
60
61					var element = jQuery( event.target );
62
63					// vac.inst.element.is( element ) gibt manchmal false zurueck, obwohl es das selbe element ist
64					// von daher comparen wir einfach die im vac-attribute hinterlegte instanz-id..
65					if ( vac.inst.element.attr( 'vac' ) == element.attr( 'vac' ) ) {
66						return;
67					}
68
69					// vac.container.find( element ) gibt teilweise false zurueck, von daher pruefen wir einfach die class der parent node
70					if ( !element.parent().hasClass( 'vac' ) ) {
71						vac.close();
72						event.preventDefault()
73					}
74				});
75
76			jQuery( 'body' )
77				.bind( 'click', function () {
78					vac.close();
79				})
80				.append( this.container )
81
82			jQuery( window ).bind( 'resize.vac', this.containerMove.bind( this ) );
83		};
84
85		vac.defaults = function(){
86			return {
87				className: '',
88				fieldName: '',
89				fieldSelector: '',
90				callbacks: {},
91				width: 250,
92				height: 300,
93				openInstant: true,
94				dataOrder: true,
95				dataValue: 'value',
96				dataSource: 'data',
97				resultsMax: 30,
98				resultsMore: true,
99				resultsMorePattern: 'Weitere $count Übereinstimmungen anzeigen.',
100				resultsOrder: true,
101				resultsEmptyMsg: true,
102				resultPosition: false,
103				resultPositionPattern: '$pos.',
104				searchMode: 'contains',
105				allowNonSelect: false,
106				allowNonMatch: false,
107				strings: {
108					searchFailed: 'Keine Übereinstimmungen gefunden'
109				}
110			}
111		};
112
113		vac.instsPreInit = function( instId ){
114			if ( this.log ) this.log( 'vac.instsPreInit()', arguments );
115
116			for( var i in vac.insts ) {
117				if ( !vac.insts.hasOwnProperty( i ) ) {
118					continue;
119				}
120
121				var inst = vac.insts[i];
122
123				if ( inst.preinited ) {
124					continue;
125				}
126
127				inst.preinited = true;
128				var options = inst.options;
129
130				if ( options.dataSource != 'data' ) {
131					vac.instReady( inst.id );
132					continue;
133				}
134
135				if ( !options.url ) {
136					vac.instReady( inst.id );
137				}
138				else {
139					if ( vac.countries != null && options.url.indexOf( 'json.php?get=countries' ) != -1 ) {
140						inst.options.data = vac.countries;
141						vac.instReady( inst.id );
142					}
143					else {
144						jQuery.ajax({
145							url: options.url,
146							dataType: 'jsonp',
147							success: function( result ){
148								this.options.data = result;
149
150								if ( options.url.indexOf( 'json.php?get=countries' ) != -1 ) {
151									vac.countries = result;
152								}
153
154								vac.instReady( this.id );
155							}.bind(inst),
156							error: function(){
157								clearInterval( this.interval )
158							}.bind( inst )
159						});
160					}
161				}
162			}
163		};
164
165		vac.instInit = function(){
166			if ( this.log ) this.log( 'vac.instInit()', arguments );
167
168			var inst = this.inst,
169				options = inst.options,
170				form = inst.element.parents( 'form' );
171
172			if ( !form.length ) {
173				form = inst.element.parent();
174			}
175
176			inst.inited = true;
177
178			if (!inst.element.attr( 'autocomplete' )) {
179				inst.element.attr( 'autocomplete', 'off' );
180			}
181
182			if ( this.ios ) {
183				inst.element
184					.attr( 'autocorrect', 'off' )
185					.attr( 'autocapitalize', 'off' );
186			}
187
188			// fieldSelector: das dort angegebene node wird ohne aenderungen als target genommen
189			if ( options.fieldSelector.length ) {
190				inst.target = jQuery( options.fieldSelector );
191			}
192			// das node mit diesem namen, innerhalb der selben form, wird als target genommen
193			else if ( options.fieldName.length ) {
194				form.find('input,select,textarea').each(function(){
195					var element = jQuery( this );
196
197					if ( element.attr( 'name' ) == options.fieldName ) {
198						inst.target = element;
199					}
200				});
201				if ( typeof inst.target == 'undefined' ) {
202					inst.target = jQuery( document.createElement( 'input' ) )
203						.attr( 'type', 'hidden' )
204						.attr( 'name', options.fieldName )
205						.appendTo( form );
206				}
207			}
208			// wird nichts angegeben, wird ein hidden-field erstellt und diesem der name des fields gegeben, welchem der vac gebinded ist
209			else {
210				inst.target = jQuery( document.createElement( 'input' ) )
211					.attr( 'type', 'hidden' )
212					.attr( 'name', inst.element.attr( 'name' ) )
213					.appendTo( form );
214
215				inst.element.removeAttr( 'name' );
216			}
217
218			form.bind( 'submit', function(){
219				if ( vac.container.is( ':visible' ) ) {
220					return false;
221				}
222
223				if ( !inst.itemSelected ) {
224					vac.itemSelect();
225				}
226			});
227
228			return true;
229		};
230
231		vac.instReady = function( instId ) {
232			if ( this.log ) this.log( 'vac.instReady()', arguments );
233
234			var inst = this.inst = this.insts[ instId ];
235
236			this.order( 'priority' );
237			inst.ready = true;
238		};
239
240		vac.instCallback = function( name, args ){
241			//if ( this.log ) this.log( 'vac.instCallback()', arguments );
242
243			var options = this.inst.options;
244
245			if ( name in options.callbacks ) {
246				return options.callbacks[ name ].call( this, args );
247			}
248		};
249
250		vac.instChange = function( instId ){
251			if ( this.log ) this.log( 'vac.instChange()', arguments );
252
253			var inst = this.inst;
254
255			if ( inst && inst.id != instId ) {
256				this.close();
257				this.eventIgnored = false;
258				this.inst = inst = this.insts[ instId ];
259			}
260
261			if ( !inst.inited ) {
262				this.instInit();
263			}
264		};
265
266		vac.containerMove = function(){
267			if ( this.log ) this.log( 'vac.containerMove()', arguments );
268
269			var inst = this.inst,
270				options = inst.options,
271				element = inst.element,
272				offset = element.offset(),
273				scrollOffset = {
274					scrollX: window.scrollX || window.pageXOffset,
275					scrollY: window.scrollY || window.pageYOffset
276				},
277				dimensions = {
278					height: element.outerHeight(),
279					width: element.outerWidth()
280				},
281				position = {
282					left: offset.left + dimensions.width,
283					top: offset.top + dimensions.height - (document.body.getBoundingClientRect().top + scrollOffset.scrollY)
284				},
285				cssProps = {
286					top: position['top'],
287					left: offset['left'],
288					width: options.width,
289					maxHeight: options.height
290				};
291
292			this.container
293				.attr( 'class', 'vac ' + options.className )
294				.css( cssProps );
295		};
296
297		vac.instReset = function(){
298			if ( this.log ) this.log( 'vac.instReset()', arguments );
299
300			var inst = this.inst;
301			inst.itemSelected = -1;
302			inst.element.data( 'result', '' );
303
304			if ( 'target' in inst ) {
305				inst.target.val( '' );
306			}
307		};
308
309		vac.register = function( element, options ){
310			if ( this.log ) this.log( 'vac.register()', arguments );
311
312			var instId = this.insts.length;
313
314			element = jQuery( element )
315				.attr( 'vac', vac.insts.length )
316				.unbind( 'click focus keyup keydown' )
317				.bind( 'click focus keyup keydown', function( event ){
318					var instId = jQuery( this ).attr( 'vac' );
319
320					if ( !vac.event( instId, event ) ) {
321	//					event.stopPropagation();
322	//					return false;
323					}
324				});
325
326			options = jQuery.extend( {}, this.defaults(), options );
327
328			vac.insts.push({
329				id: instId,
330				ready: false,
331				inited: false,
332				preinited: false,
333				itemIndex: -1,
334				itemIndexLast: -1,
335				string: '',
336				stringLast: '',
337				data: {},
338				data_cached: [],
339				element: element,
340				options: options,
341				result: []
342			});
343
344			vac.timer = setTimeout(function(){
345				vac.instsPreInit();
346
347				// in case that the input field was focused before vac was listening we open ourself automatically
348				if (element.is(':focus')) {
349					element.trigger( 'click' );
350				}
351			}, 200 );
352		};
353
354		vac.event = function( instId, event ){
355			if ( this.log ) this.log( 'vac.event()', arguments );
356
357			if ( !this.container ) {
358				this.init();
359			}
360
361			if ( this.instChange( instId ) ) {
362				this.eventIgnore( this.eventIgnored )
363			}
364			else if ( this.eventIgnore( event.type ) ) {
365				return false;
366			}
367
368			var inst = this.inst;
369			var eventAccept = true;
370
371			if ( !inst.inited ) {
372				this.instInit();
373			}
374
375			// the user can only trigger specific events (KeyboardEvent, FocusEvent, ...), a pure "Event" is only triggert bei autocomplete or javascript (hopefully.)
376			if ( this.isFakeEvent( event) ) {
377				if ( inst.options.data && inst.options.data.length ) {
378					let elementValue = ( inst.element.val() || '' ).toLowerCase();
379
380					for( var i in inst.options.data ) {
381						var dataItem = inst.options.data[i];
382
383						if ( dataItem.alias.toLowerCase() == elementValue ) {
384							this.instCallback( 'onSelectBefore' );
385							this.itemSelectByIndex(i);
386
387							setTimeout(function() {
388								this.instCallback( 'onSelectAfter' );
389							}.bind(this), 500); // chrome does also autofill input fields if there getting replaced within ~400ms
390							break;
391						}
392					}
393				}
394			}
395
396			// ignored events
397			if ( 'keyCode' in event ) {
398				if ( event.keyCode == 38 || event.keyCode == 40 ) {
399					/* */
400				}
401				else if ( ( event.ctrlKey || event.altkey || event.metaKey ) && ( event.keyCode == 0 || ( event.keyCode >= 65 && event.keyCode <= 90 ) || ( event.keyCode >= 48 && event.keyCode <= 57 ) ) ) {
402					eventAccept = false;
403				}
404			}
405
406			if ( eventAccept ) {
407				inst.event = event;
408				event.stopPropagation();
409				return this.eventAccept();
410			}
411		};
412
413		vac.eventAccept = function(){
414			if ( this.log ) this.log( 'vac.eventAccept()', arguments );
415
416			if ( this.inst.ready ) {
417				return this.eventProcess();
418			}
419			else {
420				var eventAcceptCounter = 0;
421
422				vac.timer = setTimeout(function(){
423					if ( eventAcceptCounter++ == 50 ) {
424						clearTimeout( vac.timer );
425					}
426
427					vac.eventAccept();
428				}, 100 );
429			}
430		};
431
432		vac.eventProcess = function(){
433			if ( this.log ) this.log( 'vac.eventProcess()', arguments );
434
435			var inst = this.inst,
436				event = inst.event,
437				element = inst.element,
438				returnValue = true;
439
440			this.instCallback( 'onEventBefore' );
441
442			// ignore this damn pseudo-events..are they fired from jquery?
443			if ( !( 'type' in event ) ) {
444				event.type = undefined;
445			}
446
447			switch( event.type ) {
448				case 'focus':
449					this.resultsReload();
450					this.containerMove();
451
452					if ( inst.itemSelected ) {
453						break;
454					}
455
456				case ( this.ios ? 'touchend' : 'click' ):
457					if ( inst.options.openInstant ) {
458						this.resultsShow();
459					}
460					break;
461
462				case 'keydown':
463					switch( event.keyCode ) {
464						case 9:// tab
465							if ( !( event.ctrlKey || event.altkey || event.metaKey ) ) {
466								this.itemSelect();
467								this.close();
468							}
469							break;
470
471						case 13:// enter
472							returnValue = !vac.container.is( ':visible' ) || inst.options.allowNonMatch;
473							break;
474
475						case 38:// arrow up
476							this.itemPrev();
477							break;
478
479						case 40:// arrow done
480							this.itemNext();
481							break;
482					}
483					break;
484
485				case 'keyup':
486					switch( event.keyCode ) {
487						case 38:// arrow up
488						case 40:// arrow done
489							break;
490
491						case 13:// enter
492							returnValue = !vac.container.is( ':visible' );
493
494							this.itemSelect();
495							break;
496
497						default:
498							var value = element.val(),
499								search = element.data( 'search' ),
500								result = element.data( 'result' );
501
502							if ( !value || !search || value != search && search != result ) {
503								element
504									.data( 'result', '' )
505									.data( 'search', value );
506
507								clearTimeout( this.searchTimer );
508								this.searchTimer = setTimeout( 'vac.search()', 150 );
509							}
510							else if ( event.keyCode == 8 || !( event.ctrlKey || event.altkey || event.metaKey ) && ( event.keyCode == 0 || ( event.keyCode >= 65 && event.keyCode <= 90 ) || ( event.keyCode >= 48 && event.keyCode <= 57 ) ) ) {
511								this.resultsShow();
512							}
513							break;
514					}
515					break;
516
517				case 'submit':
518					returnValue = !vac.container.is( ':visible' );
519					this.itemSelect();
520					break;
521			}
522
523			this.instCallback( 'onEventAfter' );
524
525			return returnValue;
526		};
527
528		// da wir nach dem seletieren eines items den focus wieder in das input element setzen,
529		// triggern wir gleichzeitig ein focus event - dieses muessen wir ignorieren, da es keine user eingabe ist
530		vac.eventIgnore = function( eventType ){
531			if ( this.log ) this.log( 'vac.eventIgnore()', arguments );
532
533			if ( this.eventIgnored == eventType ) {
534				this.eventIgnored = '';
535				return true;
536			}
537
538			return false;
539		};
540
541		vac.eventIgnoreNext = function( eventType ){
542			if ( this.log ) this.log( 'vac.eventIgnoreNext()', arguments );
543
544			this.eventIgnored = eventType;
545		};
546
547		vac.itemPrev = function(){
548			if ( this.log ) this.log( 'vac.itemPrev()', arguments );
549
550			var inst = this.inst,
551				container = this.container,
552				itemPrev = container.children( '.focused' ).prevAll( '[item]:first' );
553
554			if ( itemPrev.size() ) {
555				this.itemScrollTo( itemPrev.attr( 'item' ) );
556			}
557			else if ( inst.itemIndex > 0 ) {
558				this.itemScrollTo( parseInt( inst.itemIndex, 10 ) - 1 );
559			}
560		};
561
562		vac.itemNext = function(){
563			if ( this.log ) this.log( 'vac.itemNext()', arguments );
564
565			var inst = this.inst;
566
567			if ( inst.itemIndex < this.container.children( ':not(.hidden)' ).size() - 1 ) {
568				this.itemScrollTo( parseInt( inst.itemIndex, 10 ) + 1 );
569			}
570		};
571
572		vac.itemFocus = function( element ){
573			if ( this.log ) this.log( 'vac.itemFocus()', arguments );
574
575			element = jQuery( element );
576			var inst = this.inst,
577				container = this.container;
578
579			this.instCallback( 'onItemFocusBefore' );
580
581			if ( !this.ios ) {
582				container
583					.children( '.focused' )
584					.removeClass( 'focused' );
585			}
586
587			if ( element.is( '[item]' ) ) {
588				inst.itemIndexLast = inst.itemIndex;
589				inst.itemIndex = element.attr( 'item' ) * 1;
590				inst.containerScrollTop = container.scrollTop();
591			}
592
593			if ( !this.ios ) {
594				element.addClass( 'focused' );
595			}
596
597			this.instCallback( 'onItemFocusAfter' );
598		};
599
600		vac.itemSelect = function(){
601			if ( this.log ) this.log( 'vac.itemSelect()', arguments );
602
603			this.instCallback( 'onSelectBefore' );
604
605			var inst = this.inst;
606			var container = this.container;
607			var item = container.children( '[item="' + inst.itemIndex + '"]' );
608
609			if ( item.is( '.more' ) ) {
610				this.resultsShowAll();
611				item = item.next();
612				this.itemFocus( item );
613			}
614			else if ( inst.itemIndex === -1 ) {
615				this.instReset();
616				this.eventIgnoreNext( 'focus' );
617				this.close();
618			}
619			else if ( item.is( '[item]' ) ) {
620				this.itemSelectByIndex( item.attr( 'item' ) );
621			}
622
623			this.instCallback( 'onSelectAfter' );
624		};
625
626		vac.itemSelectByIndex = function( itemIndex ){
627			if ( this.log ) this.log( 'vac.itemSelectByIndex()', arguments );
628
629			var inst = this.inst;
630			var data = inst.data_cached;
631
632			if ( !data.length ) {
633				data = inst.options.data;
634			}
635
636			inst.itemIndexLast = inst.itemIndex;
637			inst.itemIndex = itemIndex;
638
639			if ( !( itemIndex in data ) ) {
640				return;
641			}
642
643			var dataItem = data[ itemIndex ];
644
645			inst.itemSelected = itemIndex;
646			inst.item = dataItem
647
648			if ( inst.target && inst.target.length ) {
649				inst.target.val( dataItem[ inst.options.dataValue ] );
650
651				if (inst.container) {
652					inst.container.children( '.selected' ).removeClass( 'selected' );
653					inst.container.children( '[item="' + inst.itemIndex + '"]' ).addClass( 'selected' );
654					inst.containerScrollTop = inst.container.scrollTop();
655				}
656
657				if (inst.element) {
658					inst.element
659						.data( 'result', dataItem.name )
660						.val( dataItem.name )
661						.get( 0 )
662						.select();
663				}
664
665				this.eventIgnoreNext( 'focus' );
666				this.close();
667			}
668		};
669
670		vac.itemScrollTo = function( index ){
671			if ( this.log ) this.log( 'vac.itemScrollTo()', arguments );
672
673			var inst = this.inst,
674				container = this.container,
675				containerOffset = inst.containerOffset || container.offset(),
676				item = container.children( ':not(.hidden)' ).eq( index ),
677				itemOffset = item.offset(),
678				containerScrollTop = container.scrollTop(),
679				scrollTop = itemOffset.top - ( containerOffset.top - containerScrollTop ),
680				scrollTopItem = container.height() - item.outerHeight();
681
682			inst.containerOffset = containerOffset;
683
684				this.itemFocus( item );
685			if ( !inst.options.allowNonSelect ) {
686			}
687
688			// scroll down
689			if ( inst.itemIndexLast < inst.itemIndex && scrollTop > ( containerScrollTop + scrollTopItem ) ) {
690				container.scrollTop( scrollTop - scrollTopItem );
691			}
692			// scroll up
693			else if ( scrollTop < container.scrollTop() ) {
694				container.scrollTop( scrollTop );
695			}
696
697			container.show();
698		};
699
700		vac.close = function( blur = true ){
701			if ( this.log ) this.log( 'vac.close()', arguments );
702
703			this.instCallback( 'onCloseBefore' );
704			this.inst.containerScrollTop = this.container.scrollTop();
705			this.container.fadeOut('fast').hide(); // .fadeOut('fast') ie11 fix
706
707			if ( blur && this.inst.element.hasClass('vac_active') ) {
708				this.inst.element.trigger( 'blur' );
709			}
710			this.instCallback( 'onCloseAfter' );
711		};
712
713		vac.search = function(){
714			if ( this.log ) this.log( 'vac.search()', arguments );
715
716			var inst = this.inst,
717				element = inst.element,
718				elementResult = ( inst.element.data( 'result' ) || '' ).toLowerCase(),
719				string = ( element.data( 'search' ) || '' ).toLowerCase();
720
721			if ( elementResult && string == elementResult ) {
722				this.resultsShow();
723				return;
724			}
725
726			if ( inst.options.dataSource == 'url' ) {
727				var self = this;
728				var url = inst.options.url;
729				var data = this.instCallback( 'onSearchParamsGet', string );
730
731				jQuery.ajax({
732					url: url.replace( /value/, string ),
733					dataType: 'json',
734					data: data,
735					success: function (data) {
736						var result = self.instCallback( 'onDataFetch', data );
737
738						if ( result === false ) {
739							inst.options.data = [];
740						}
741						else {
742							inst.options.data = result || data;
743						}
744
745						inst.data_cached = [];
746
747						self.searchRun();
748					}
749				});
750			}
751			else {
752				this.searchRun();
753			}
754		};
755
756		vac.searchRun = function(){
757			var inst = this.inst,
758				element = inst.element,
759				elementResult = ( inst.element.data( 'result' ) || '' ).toLowerCase(),
760				string = ( element.data( 'search' ) || '' ).toLowerCase();
761
762			var options = inst.options,
763				data = options.data,
764				data_cached = [],
765				dataOrder = string.length;
766
767			if ( inst.data_cached.length && string.substr( 0, inst.string.length ) == inst.string ) {
768				data = inst.data_cached;
769			}
770
771			inst.string = string;
772
773			this.instReset();
774			this.instCallback( 'onSearchBefore' );
775
776			for( var i in data ) {
777				var entry = data[i],
778					multiplier = 1,
779					texts = [ entry.name, entry.alias ];
780
781				texts.push.apply( texts, entry.alternatives );
782				entry.score = -1;
783
784				if ( !string.length ) {
785					entry.score = entry.priority;
786				}
787				else {
788					for( var j in texts ) {
789						if ( !texts.hasOwnProperty( j ) || typeof texts[j] != 'string' ) {
790							continue;
791						}
792
793						var text = texts[j].toLowerCase(),
794							pos = text.indexOf( string );
795
796						if ( inst.searchMode == 'beginsWith' && pos != 0 ) continue;
797						if ( pos == -1 ) continue;
798						if ( pos != 0 ) multiplier = 3;
799						if ( text == string ) multiplier = 5;
800
801						var score = ( ( pos + 1 ) * multiplier ) * ( j == 0 ? 1 : 2 );
802
803						if ( entry.score == -1 || score < entry.score ) {
804							entry.score = score;
805
806							if ( j != 0 ) {
807								entry.match = texts[j];
808							}
809						}
810					}
811				}
812
813				if ( entry.score != -1 ) {
814					data_cached.push( entry );
815				}
816			}
817
818			inst.data_cached = data_cached;
819			inst.itemIndexLast = inst.itemIndex;
820			inst.itemIndex = inst.options.allowNonSelect ? -1 : 0;
821
822			this.instCallback( 'onSearchAfter' );
823
824			if ( inst.data_cached.length ) {
825				if ( dataOrder && options.resultsOrder ) {
826					this.order( 'results' );
827				}
828
829				this.resultsReload();
830			}
831			else {
832				this.searchFailed();
833			}
834		};
835
836		vac.searchFailed = function(){
837			if ( this.log ) this.log( 'vac.searchFailed()', arguments );
838
839			var string = this.inst.options.strings['searchFailed'];
840
841			if ( this.inst.options.resultsEmptyMsg && string ) {
842				this.inst.result = this.container.html( '<div class="row noresult">' + string + '</div>' );
843			}
844			else {
845				this.close(false);
846			}
847		};
848
849		vac.resultsReload = function(){
850			if ( this.log ) this.log( 'vac.resultsReload()', arguments );
851
852			var rows = [],
853				row = '',
854				inst = this.inst,
855				options = inst.options,
856				data = inst.data_cached.length ? inst.data_cached : jQuery.makeArray( options.data ),
857				pattern = inst.string.length ? eval( '/(' + inst.string + ')/gi' ) : null,
858				length = data.length,
859				resultsMoreDone = false;
860
861			for( var i in data ) {
862
863				if( !data.hasOwnProperty( i ) ) {
864					continue;
865				}
866
867				var className = 'row item',
868					style = '';
869
870				if ( i % 2 == 0 ) className += ' even';
871				if ( i >= options.resultsMax ) className += ' hidden';
872				if ( !inst.options.allowNonSelect && inst.itemSelected == -1 && i == 0 ) {
873					if ( !this.ios ) {
874						className += ' focused';
875					}
876				}
877				else if ( i == inst.itemSelected ) className += ' selected';
878
879				row = '<div class="' + className + '" onclick="vac.itemSelect()" onmouseover="vac.itemFocus( this )" item="' + i + '">';
880
881				if ( options.resultPosition ) {
882					row += '<span class="position">' + options.resultPositionPattern.replace( '$pos', ( +i + 1 ) ) + '</span>';
883				}
884
885				if ( pattern ) {
886					row += data[i].name.replace( pattern, '<span class="match">$1</span>' );
887
888					if ( data[i].match && data[i].match.match( pattern ) ) {
889						row += '<span class="alternative">';
890						row += data[i].match.replace( pattern, '<span class="match">$1</span>' );
891						row += '</span>';
892					}
893				}
894				else {
895					row += data[i].name;
896				}
897
898				row += '</div>';
899				rows.push( row );
900
901				if ( i == options.resultsMax - 1 ) {
902					if ( options.resultsMore ) {
903						className += ' hidden';
904
905						if ( !resultsMoreDone ) {
906							resultsMoreDone = true;
907
908							var row = '<div class="row more" onclick="vac.resultsShowAll()" onmouseover="vac.itemFocus( this )" item="' + i + '">';
909							row += options.resultsMorePattern.replace( '$count', ( length - 1 ) - i );
910							row += '</div>';
911
912							rows.push( row );
913						}
914					}
915					else break;
916				}
917			}
918
919			inst.element.addClass( 'vac_active' );
920			this.container.html( rows.join('') ).show();
921			inst.containerScrollTop = 0;
922			this.container.scrollTop(0);
923			inst.result = this.container.children( '.item' );
924		};
925
926		vac.resultsShow = function(){
927			if ( this.log ) this.log( 'vac.resultsShow()', arguments );
928
929			var inst = this.inst;
930
931			this.instCallback( 'onShowBefore' );
932
933			inst.element.addClass( 'vac_active' );
934
935			if ( this.container.children( '[item]' ).length == 0 ) {
936				this.resultsReload();
937			}
938
939			if ( !inst.options.data || !inst.options.data.length ) {
940				this.searchFailed();
941			}
942			else if ( false && inst.itemIndex ) {
943				this.itemScrollTo( inst.itemIndex )
944			}
945			else {
946				this.container.show().scrollTop( inst.containerScrollTop );
947			}
948
949			this.instCallback( 'onShowAfter' );
950		};
951
952		vac.resultsShowAll = function(){
953			if ( this.log ) this.log( 'vac.resultsShowAll()', arguments );
954
955			// div.more darf nicht geloescht werden, da wir erst danach pruefen in wie fern wir das click event abfangen muessen
956			this.container
957				.children( '.more' )
958				.addClass( 'hidden' )
959				.nextAll()
960				.removeClass( 'hidden' );
961		};
962
963		vac.order = function( type, compare ){
964			if ( this.log ) this.log( 'vac.order()', arguments );
965
966			if ( type in vacOrder ) {
967				vacOrder[ type ].run( compare );
968			}
969		};
970
971		var vacOrder = function( type, data ){
972			if ( type in vacOrder ) {
973				vacOrder[ type ].run( data );
974			}
975		};
976
977		vacOrder._new = function(){
978			return {
979				data: {},
980				run: function(){}
981			}
982		};
983
984		vacOrder.results = new vacOrder._new;
985		vacOrder.results.run = function(){
986			if ( vac.log ) vac.log( 'vacOrder.results()', arguments );
987
988			if ( vac.instCallback( 'onOrderBefore' ) !== false ) {
989				vac.inst.data_cached.sort(function(a,b){
990					var result = a.score - b.score;
991
992					if ( result == 0 ) return 0;
993					if( result > 0 ) return 1;
994					return -1;
995				});
996			}
997			vac.instCallback( 'onOrderAfter' );
998		};
999
1000		vacOrder.priority = new vacOrder._new;
1001		vacOrder.priority.run = function(){
1002			if ( vac.log ) vac.log( 'vacOrder.priority()', arguments );
1003
1004			if ( 'data' in vac.inst.options ) {
1005				vac.inst.options.data.sort(function(a,b){
1006					if ( a.priority == b.priority ) return 0;
1007					if ( a.priority > b.priority ) return -1;
1008					return 1;
1009				});
1010			}
1011		};
1012
1013		vacOrder.countries = new vacOrder._new;
1014		vacOrder.countries.run = function( data ){
1015			if ( vac.log ) vac.log( 'vacOrder.countries()', arguments );
1016
1017			if ( data ) {
1018				this.data = data;
1019			}
1020
1021			if ( 'country' in this.data && 'geo_country_code_iso_2' in this.data.country ) {
1022				var inst = vac.inst,
1023					options = inst.options,
1024					data = jQuery.extend( {}, options.data ),
1025					dataOrdered = [],
1026					firstItem;
1027
1028				for( var i in data ) {
1029					if ( data[i].alias == this.data.country.geo_country_code_iso_2 ) {
1030						firstItem = data[i];
1031					}
1032					else {
1033						dataOrdered.push( data[i] );
1034					}
1035				}
1036
1037				if ( firstItem ) {
1038					dataOrdered.unshift( firstItem );
1039				}
1040
1041				options.data = dataOrdered;
1042			}
1043		}
1044
1045		jQuery.fn.vac = function( options ) {
1046			this.each(function() {
1047				vac.register( this, options );
1048			});
1049
1050			return this;
1051		};
1052
1053		// damit wir den seitenaufbau nicht unnoetig mit irgendwelchen ajax requests verlangsamen
1054		// fangen wir erst nach dem onload event an die daten zu laden
1055		jQuery(function(){
1056			vac.timer = setTimeout(function(){
1057				vac.instsPreInit();
1058			}, 200 );
1059		});
1060	})( typeof vQuery != 'undefined' ? vQuery : jQuery );
1061}
1062else if ( typeof jQuery !== 'undefined' && typeof vQuery !== 'undefined' && 'vac' in jQuery.fn && !( 'vac' in vQuery.fn ) ){
1063	vQuery.fn.vac = jQuery.fn.vac;
1064}

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.