PageSourceSearch

https://eoipsocommunications.com/wp-content/plugins/greyd-plugin/s…/query/assets/js/post-slider.js?ver=2.15.0

js eoipsocommunications.com collected 2026-10-04 20:18:01 UTC 26,267 bytes, 857 lines download raw bytes

1/**
2 * Query Loop Scripts
3 * - post-slider
4 * - sorting
5 * - table sorting
6 * 
7 * Moved from classic greyd default.js
8 */
9
10var greyd = greyd || {};
11
12( function() {
13	jQuery( function() {
14		if ( typeof $ === 'undefined' ) $ = jQuery;
15
16		greyd.query.init();
17
18		console.log( "Query Scripts: loaded" );
19	} );
20} )( jQuery );
21
22
23/**
24 * init greyd.query var
25 */
26greyd.query = greyd.query || {};
27
28/**
29 * init all query features
30 */
31greyd.query.init = function() {
32	greyd.query.slider.init();
33	greyd.query.sorting.init();
34	greyd.query.table.init();
35}
36
37
38/**
39 * slider features
40 * 
41 * was global default.js variable 'post'
42 */
43greyd.query.slider = new function() {
44	
45	this.loaded = false;
46	
47	this.init = function() {
48		this.addEvents();
49		// console.log('Posts Pagination Script: loaded');
50	}
51	
52	this.addEvents = function() {
53		var wrapper = $(".greyd-posts-slider.js:not([data-init])");
54		if (wrapper.length > 0) {
55
56			wrapper.each(function() {
57				if ($(this).hasClass('autoplay')) {
58					var time = $(this).data('interval')*1000;
59					var that = this;
60					$(this).timer = setInterval(function() {
61						if (!$(that).hasClass('pause') && !$(that).hasClass('forcePause')) {
62							greyd.query.slider.paginateNext($(that));
63						}
64					}, time);
65					// $(this).on('mouseenter', function() {
66					//     if ( !$(that).hasClass('pause') ) {
67					//         $(that).addClass('pause');
68					//         $(this).on('mouseleave', function() {
69					//             $(that).removeClass('pause');
70					//         });
71					//     }
72					// });
73				}
74				
75				$(this).off('next').on('next', function() {
76					greyd.query.slider.paginateNext(this);
77				});
78				$(this).off('prev').on('prev', function() {
79					greyd.query.slider.paginatePrevious(this);
80				});
81				$(this).off('first').on('first', function() {
82					greyd.query.slider.paginate(this, 1);
83				});
84				$(this).off('last').on('last', function() {
85					var pages = $(this).children('.query-pages-wrapper').children('.query-page');
86					greyd.query.slider.paginate(this, pages.length);
87				});
88				$(this).off('stop').on('stop', function() {
89					$(this).addClass('forcePause pause');
90				});
91				$(this).off('start').on('start', function() {
92					$(this).removeClass('forcePause pause');
93				});
94
95				/**
96				 * We insert the event listeners using PHP for more reliability.
97				 * @since 2.7.0
98				 */
99				// // next/previous
100				// $(this).find('.pagination > a, a.pgn_arrows, .pgn_arrows a').off('click').on("click", function(e) {
101				// 	var wrapper = $(this).closest('.greyd-posts-slider');
102				// 	wrapper.trigger( $(this).data('pagelink') );
103				// 	wrapper.trigger('stop');
104				// });
105				// console.log(
106				// 	$(this).find('.pagination > a, a.pgn_arrows, .pgn_arrows a'),
107				// 	$(this).find('.pagination > .pgn_numbers > a')
108				// );
109				
110				// // numbers
111				// $(this).find('.pagination > .pgn_numbers > a').off('click').on("click", function(e) {
112				// 	var wrapper = $(this).closest('.greyd-posts-slider');
113				// 	greyd.query.slider.paginate( wrapper, $(this).data('pagelink') );
114				// 	wrapper.trigger('stop');
115				// });
116
117				// core pagination
118				$(this).closest('.wp-block-query').find('.wp-block-query-pagination').each(function() {
119					greyd.query.slider.addCorePagination(this);
120
121				});
122	
123				// touch support
124				$(this).off('touchstart').on('touchstart', function(e) { 
125					greyd.query.slider.touchStart(this, e);
126					$(this).trigger('stop');
127				});
128				$(this).off('touchmove').on('touchmove', function(e) {
129					greyd.query.slider.touchMove(this, e);
130					$(this).trigger('stop');
131				});
132
133				// add onload event to images inside slider to re-calculate height
134				$(this).find('img').each(function() {
135					// console.log(this);
136					$(this).off('load').on('load', function(e) { 
137						// console.log("img loaded");
138						if ( greyd.query.slider.loaded ) greyd.query.slider.calc();
139					});
140				});
141
142				$(this).attr('data-init', 'true');
143			});
144
145			// size wrapper
146			window.addEventListener("resize", function() { 
147				greyd.query.slider.calc()
148			});
149			setTimeout(function(){
150				greyd.query.slider.calc()
151			}, 100);
152			
153			$(document).keydown(function(e){
154				// arrow left
155				if (e.keyCode == 37) {
156					var wrapper = $(".greyd-posts-slider.js:hover");
157					if ( wrapper.length > 0 ) {
158						wrapper.trigger('prev');
159						wrapper.trigger('stop');
160					}
161					return false;
162				}
163				// arrow right
164				if (e.keyCode == 39) {
165					var wrapper = $(".greyd-posts-slider.js:hover");
166					if ( wrapper.length > 0 ) {
167						wrapper.trigger('next');
168						wrapper.trigger('stop');
169					}
170					return false;
171				}
172			});
173		}
174	}
175
176	this.calc = function() {
177		$('.greyd-posts-slider.js > .query-pages-wrapper').each(function(e) {
178			var pages   = $(this).children('.query-page');
179			var wrapper = $(this).closest('.greyd-posts-slider');
180			var current = wrapper.data('currentpage');
181
182			// console.log(offset);
183			// $(this).finish().animate({ scrollLeft: offset }, 0);
184			
185			// get slider height
186			var height = $(this)[0].offsetHeight;
187			var newHeight = null;
188
189			/**
190			 * Adjust the slider height.
191			 * 
192			 * The naming of the options are misleading:
193			 * (1) 'auto'   =>  'as high as highest slide'
194			 *                  This is called auto, because the height of the slider
195			 *                  is automatically this way due to 'display: flex'. We
196			 *                  do not need to do anything in JS.
197			 * (2) 'max'    =>  'adjust automatically'
198			 *                  We need to adjust the slider's height to the height
199			 *                  of the current slide each step.
200			 * (3) 'custom' =>  'manual height'
201			 *                  Set the height to a manual input.
202			 */
203			if ( wrapper.data('height') == 'auto' ) {
204				// (1)
205			}
206			else if ( wrapper.data('height') === 'max') {
207				// (2)
208				newHeight = pages.length > 1 ? pages[current-1].offsetHeight+"px" : null;
209			}
210			else {
211				// (3)
212				newHeight = wrapper.data('height');
213				if ( screen.width <= 767 && typeof wrapper.data('height_mobile') != 'undefined' && wrapper.data('height_mobile') != 'max' ) {
214					newHeight = wrapper.data('height_mobile');
215				}
216			}
217
218			// set height for new slider
219			if ( newHeight && newHeight != height ) {
220				$(this).css('height', newHeight);
221			}
222		});
223		
224		// set loaded state to only re-calculate height after initial calc is done
225		greyd.query.slider.loaded = true;
226	}
227
228	/**
229	 * When a pagination link is clicked, this function is called to paginate.
230	 * @since 2.7.0
231	 * 
232	 * @param {object} e        The event object.
233	 * @param {object} el       The element that was clicked.
234	 * @param {number} pagelink The page number to paginate to.
235	 */
236	this.onPaginateClick = function(e, el, pagelink) {
237		// console.log("paginate click", e, el, pagelink);
238		var wrapper = $(el).closest('.greyd-posts-slider');
239		greyd.query.slider.paginate( wrapper, pagelink );
240		wrapper.trigger('stop');
241	}
242	this.paginateNext = function(wrapper) {
243		// console.log("next page");
244		var newpage = parseInt($(wrapper).data('currentpage')) + 1;
245		this.paginate(wrapper, newpage);
246	}
247	this.paginatePrevious = function(wrapper) {
248		// console.log("previous page");
249		var newpage = parseInt($(wrapper).data('currentpage')) - 1;
250		this.paginate(wrapper, newpage);
251	}
252	this.paginate = function(wrapper, newpage) {
253
254		// function to check is a string is numeric
255		const isNumeric = (str) => {
256			if (typeof str != "string") return false;
257			return !isNaN(str) && !isNaN(parseFloat(str));
258		}
259
260		// get the new page number
261		if ( isNumeric(newpage) ) {
262			newpage = parseInt(newpage);
263		}
264		// if not numeric, like 'next' or 'prev', calculate the new page number
265		else {
266			if ( newpage == 'next' ) {
267				newpage = parseInt($(wrapper).data('currentpage')) + 1;
268			} else if ( newpage == 'prev' ) {
269				newpage = parseInt($(wrapper).data('currentpage')) - 1;
270			} else if ( newpage == 'first' ) {
271				newpage = 1;
272			} else if ( newpage == 'last' ) {
273				newpage = $(wrapper).children('.query-pages-wrapper').children('.query-page').length;
274			}
275		}
276
277		var current = $(wrapper).data('currentpage');
278		var pages   = $(wrapper).children('.query-pages-wrapper').children('.query-page');
279
280		// return if no need to go to the next page
281		if (current == newpage) return;
282		if ( $(wrapper).hasClass('loop') ) {
283			if (newpage < 1) newpage = pages.length;
284			if (newpage > pages.length) newpage = 1;
285		}
286		else {
287			if (newpage < 1) return;
288			if (newpage > pages.length) return;
289		}
290
291		// get html elements
292		const resultsWrapper = $(wrapper).children('.query-pages-wrapper');
293		const activeStep = pages[newpage-1];
294		const prev = $(wrapper).find('.pgn_previous');
295		const next = $(wrapper).find('.pgn_next');
296
297		// get animation settings
298		const config = {
299			animation: $(wrapper).data('animation'),
300			height: $(wrapper).data('height'),
301			heightMobile: $(wrapper).data('height_mobile'),
302			offsetLeft: activeStep.offsetLeft,
303			scrollToTop: $(wrapper).hasClass('slider_scroll_top'),
304			/**
305			 * Speed of the animation.
306			 * 
307			 * @since 2.3.0 Added the global variable 'greydSliderSpeed' to enable
308			 *              users to set the speed of the slider in the global scope.
309			 */ 
310			speed: $(wrapper).data('duration') ?? ( typeof greydSliderSpeed !== "undefined" ? greydSliderSpeed : 200 )
311		};
312
313		if ( config.animation == 'none' ) {
314			config.speed = 0;
315		}
316		
317		// update html attributes and classes
318		$(wrapper).data('currentpage', newpage);
319		pages.removeClass('is-current is-prev is-next');
320		$(pages[newpage-2]).addClass('is-prev');
321		$(activeStep).addClass('is-current');
322		$(pages[newpage]).addClass('is-next');
323		
324		/**
325		 * Adjust the slider height.
326		 * 
327		 * The naming of the options are misleading:
328		 * (1) 'auto'   =>  'as high as highest slide'
329		 *                  This is called auto, because the height of the slider
330		 *                  is automatically this way due to 'display: flex'. We
331		 *                  do not need to do anything in JS.
332		 * (2) 'max'    =>  'adjust automatically'
333		 *                  We need to adjust the slider's height to the height
334		 *                  of the current slide each step.
335		 * (3) 'custom' =>  'manual height'
336		 *                  Set the height to a manual input.
337		 */
338		let newHeight;
339		if ( config.height == 'auto' ) {
340			// (1)
341		}
342		else if ( config.height === 'max') {
343			// (2)
344			newHeight = activeStep.offsetHeight;
345		}
346		else {
347			// (3)
348			newHeight = config.height;
349			if (
350				screen.width <= 767
351				&& typeof config.heightMobile != 'undefined'
352				&& config.heightMobile != 'max'
353			) {
354				newHeight = config.heightMobile;
355			}
356		}
357
358		// animate slider
359		if ( config.animation == 'fade' ) {
360
361			// fade out
362			$(resultsWrapper).finish().animate({ opacity: 0 }, config.speed);
363			setTimeout( () => {
364
365				/**
366				 * @since 2.7.0 set the height directly and only animate the
367				 * scroll x position.
368				 * This is necessary to prevent the slider from jumping around
369				 * which leads to errors scrolling to top, especially on mobile
370				 * and safari browsers.
371				 */
372				if ( config.scrollToTop && newHeight ) {
373					resultsWrapper.css('height', newHeight);
374				}
375				
376				// scroll to new position
377				$(resultsWrapper).finish().animate({ scrollLeft: config.offsetLeft }, 0);
378				
379				// fade in
380				$(resultsWrapper).finish().animate({
381					opacity: 1,
382					...( !config.scrollToTop )  && newHeight ? { height: newHeight } : {}
383				}, config.speed);
384			}, config.speed );
385		}
386		else if ( config.animation == 'cover' ) {
387			/**
388			 * @since 2.7.0 set the height directly and only animate the
389			 * scroll x position.
390			 * This is necessary to prevent the slider from jumping around
391			 * which leads to errors scrolling to top, especially on mobile
392			 * and safari browsers.
393			 */
394			if ( config.scrollToTop && newHeight ) {
395				resultsWrapper.css('height', newHeight);
396			} else if ( newHeight )  {
397				$(resultsWrapper).finish().animate({ height: newHeight }, config.speed, 'swing');
398			}
399			// ...the rest of cover-flow animation is entirely handled by CSS
400		}
401		else {
402			/**
403			 * @since 2.7.0 set the height directly and only animate the
404			 * scroll x position.
405			 * This is necessary to prevent the slider from jumping around
406			 * which leads to errors scrolling to top, especially on mobile
407			 * and safari browsers.
408			 */
409			if ( config.scrollToTop && newHeight ) {
410				resultsWrapper.css('height', newHeight);
411			}
412			$(resultsWrapper).finish().animate({
413				scrollLeft: config.offsetLeft,
414				...( !config.scrollToTop ) && newHeight ? { height: newHeight } : {}
415			}, config.speed, 'swing');
416		}
417
418		// scroll to top
419		if ( config.scrollToTop ) {
420			const offsetTop = $(wrapper).offset().top - 100;
421			if ( $(document).scrollTop() > offsetTop ) {
422
423				// backward compatibility with classic theme
424				if ( typeof nav !== 'undefined' ) {
425					console.log( "scroll to top with nav", nav );
426					nav.scrollTo( offsetTop );
427				}
428				else {
429					window.scrollTo( { top: offsetTop, behavior: 'auto' } );
430				}
431			}
432		}
433		else {
434			// trigger 'scroll' event manually
435			// eg. to perform animations for now visible elements
436			setTimeout( () => {
437				document.dispatchEvent( new Event('scroll') );
438			}, config.speed );
439		}
440		
441		// update the pagination
442		var pg_wrapper = $(wrapper).find('.pagination');
443		if ( pg_wrapper.length ) {
444			var pg_pages = $(pg_wrapper).find('.pgn_numbers').children();
445			var iconnormal = $(pg_wrapper).data('iconnormal') ?? $(pg_wrapper).find('.pgn_numbers').data('iconnormal');
446			var iconactive = $(pg_wrapper).data('iconactive') ?? $(pg_wrapper).find('.pgn_numbers').data('iconactive');
447			var imgnormal = $(pg_wrapper).data('imgnormal') ?? $(pg_wrapper).find('.pgn_numbers').data('imgnormal');
448			var imgactive = $(pg_wrapper).data('imgactive') ?? $(pg_wrapper).find('.pgn_numbers').data('imgactive');
449	
450			for (var i=0; i<pg_pages.length; i++) {
451				// console.log( "pagination", $(pg_pages[i]) );
452				var p = $(pg_pages[i]);
453				if (!$(p).hasClass('pgn_number')) p = $(p).find('.pgn_number');
454				if ($(pg_pages[i]).data('pagelink') == current) {
455					$(p).removeClass('pgn_current');
456					if (typeof iconactive !== 'undefined') $(p).removeClass(iconactive);
457					if (typeof iconnormal !== 'undefined') $(p).addClass(iconnormal);
458					if (typeof imgnormal !== 'undefined') $(p).children().attr('src', imgnormal);
459				}
460				if ($(pg_pages[i]).data('pagelink') == newpage) {
461					$(p).addClass('pgn_current');
462					if (typeof iconnormal !== 'undefined') $(p).removeClass(iconnormal);
463					if (typeof iconactive !== 'undefined') $(p).addClass(iconactive);
464					if (typeof imgactive !== 'undefined') $(p).children().attr('src', imgactive);
465				}
466			}
467		}
468
469		// update the arrows
470		$(prev).removeClass('pgn_current');
471		if (newpage == 1) $(prev).addClass('pgn_current');
472		$(next).removeClass('pgn_current');
473		if (newpage == pages.length) $(next).addClass('pgn_current');
474
475		// trigger custom JS event
476		$(wrapper).trigger("greyd_slider_paginate", [newpage] );
477	}
478	 
479	this.xDown = null; 
480	this.touchStart = function(el, evt) {
481		greyd.query.slider.xDown = evt.originalEvent.touches[0].clientX;
482	}
483	this.touchMove = function(el, evt) {
484		if (!greyd.query.slider.xDown) {
485			return;
486		}
487		var xUp = evt.originalEvent.touches[0].clientX;    
488		var xDiff = greyd.query.slider.xDown - xUp;    
489		if (xDiff > 50) {
490			// console.log("scroll right");
491			$(el).trigger('next');
492			$(el).trigger('stop');
493			greyd.query.slider.xDown = null; 
494		}
495		else if (xDiff < -50)  {
496			// console.log("scroll left");
497			$(el).trigger('prev');
498			$(el).trigger('stop');
499			greyd.query.slider.xDown = null; 
500		}
501	}
502	
503	this.triggerNext = function(el) {
504		// console.log(el);
505		$(el).closest('.wp-block-query').children('.greyd-posts-slider.js').trigger('next');
506	}
507	this.triggerPrevious = function(el) {
508		// console.log(el);
509		$(el).closest('.wp-block-query').children('.greyd-posts-slider.js').trigger('prev');
510	}
511	this.triggerIndex = function(el, index) {
512		// console.log(el);
513		$(el).closest('.wp-block-query').children('.greyd-posts-slider.js').each(function() {
514			greyd.query.slider.paginate(this, index);
515		});
516	}
517	
518	this.addCorePagination = function(el) {
519
520		let allPages = $(el).closest('.wp-block-query').children('.greyd-posts-slider.js').find('.query-page');
521
522		if ( ! allPages || allPages.length < 2 ) return;
523		
524
525		// trigger function - also handles 'current' attributes on links
526		const trigger = ( mode, element, index = false ) => {
527			var wrapper = $(el).closest('.wp-block-query').children('.greyd-posts-slider.js');
528			var current = $(wrapper).data('currentpage');
529			var pages   = $(wrapper).find('.query-page');
530			var isLoop  = $(wrapper).hasClass('loop');
531			if (mode == 'previous') {
532				current--;
533				greyd.query.slider.triggerPrevious(element);
534				if (current < 1) {
535					if (isLoop) current = pages.length;
536					else return;
537				}
538			}
539			if (mode == 'next') {
540				current++;
541				greyd.query.slider.triggerNext(element);
542				if (current > pages.length) {
543					if (isLoop) current = 1;
544					else return;
545				}
546			}
547			if (mode == 'index') {
548				current = index;
549				greyd.query.slider.triggerIndex(element, index);
550			}
551			// set 'current' attributes
552			$(el).find('.wp-block-query-pagination-numbers .page-numbers:not
552(.dots)').each( (j, number) => {
553				$(number).removeClass('current');
554				$(number).removeAttr('aria-current');
555				if ($(number).data('page') == current) {
556					$(number).addClass('current');
557					$(number).attr('aria-current', 'page');
558				}
559			})
560		};
561
562		// previous
563		var previous = $(el).find('.wp-block-query-pagination-previous');
564		previous.removeAttr("href");
565		previous.off('click').on('click', function(e) { trigger('previous', this) } );
566
567		// next
568		var next = $(el).find('.wp-block-query-pagination-next');
569		next.removeAttr("href");
570		next.off('click').on('click', function(e) { trigger('next', this) } );
571
572		// numbers
573		var numbers = $(el).find('.wp-block-query-pagination-numbers .page-numbers:not(.dots)');
574		numbers.each( (i, num) => {
575
576			// get all elements attributes
577			var attrs = {};
578			$.each($(num)[0].attributes, function(idx, attr) {
579				attrs[attr.nodeName] = attr.nodeValue;
580			});
581			// get index
582			let index = i+1;
583			if ( attrs['href'] ) {
584				// var params = Object.fromEntries((new URLSearchParams(attrs['href'])).entries())
585				// Object.keys(params).forEach( (key) => {
586				// 	if ( key.indexOf('query-') == 0 && key.indexOf('-page') > 0 )
587				// 		index = parseInt(params[key]);
588				// });
589				delete attrs['href'];
590			}
591			// make onclick event
592			attrs['data-page'] = index;
593			// attrs['click'] = function(e) { trigger('index', this, index) };
594			attrs['onclick'] = "greyd.query.slider.triggerIndex(this, "+index+")";
595
596			// make new link with attributes
597			$(num).replaceWith(function() {
598				const text = $(this).contents();
599				return $("<a />", attrs).append( text );
600			});
601		});
602
603	}
604
605}
606
607/**
608 * sort posts in frontend via dropdown
609 * 
610 * was global default.js variable 'sorting'
611 */
612greyd.query.sorting = new function() {
613
614	this.init = function() {
615		// return if not needed
616		if ($(".greyd-posts-slider").length === 0) return false;
617		
618		// normal pages
619		if (!($(".greyd-posts-slider.js").length === 0)) {
620			this.addEvents();
621		}
622		// search page
623		else {
624			if ($('.greyd-posts-slider').attr("live-search") == "true") {
625				return false
626			} else {
627				this.startQuery();
628			}
629		}
630	}
631
632	this.addEvents = function() {
633		const sortingDropdown = $('.greyd-posts-slider').find('.sorting');
634		sortingDropdown.each(function() {
635			var wrapper = $(this);
636			var select  = wrapper.find("select");
637			var slider  = wrapper.parent();
638			var results = slider.find($(".query-post"));
639
640			// sort and redistribute search results
641			select.off("change").on("change", function() {
642				console.log(slider);
643				console.log(results);
644				var sorted_elements = greyd.query.sorting.sortElements($(this).val(), results);
645				// console.log(sorted_elements);
646				greyd.query.sorting.distributeElements(sorted_elements, slider);
647			});
648		});
649		
650		$('[id^="filter_"]').each(function() {
651			var results = $(this).siblings('[id^="slider_"]').find($(".query-post"));
652			if (results) {
653				var select = $(this).find("select");
654				var filter = select.val();
655				$(results).each(function() {
656					greyd.query.sorting.filterElements(this, filter);
657				});
658				select.off("change").on("change", function() {
659					var filter = $(this).val();
660					$(results).each(function() {
661						greyd.query.sorting.filterElements(this, filter);
662					});
663				});
664			}
665		});
666	}
667
668	this.filterElements = function(el, filter) {
669		var vals = JSON.parse(decodeURIComponent($(el).data('filter')));
670		filter = parseInt(filter);
671		if (filter == null || filter == -1 || vals.indexOf(filter) != -1)
672			$(el).css('display', 'block');
673		else
674			$(el).css('display', 'none');
675	}
676
677	this.sortElements = function(mode, search_results) {
678
679		search_results.sort(function (a, b) {
680
681			if (~mode.indexOf("title")) {
682				// propably do that via php...
683				// var compA = a.dataset.title.toLowerCase().replace(/[^a-zA-Z0-9 ]/g, "");
684				// var compB = b.dataset.title.toLowerCase().replace(/[^a-zA-Z0-9 ]/g, "");
685				var compA = a.dataset.title;
686				var compB = b.dataset.title;
687			}
688			else if (~mode.indexOf("date")) {
689				var compA = a.dataset.date;
690				var compB = b.dataset.date;
691			}
692			else if (~mode.indexOf("views")) {
693				// propably do that via php...
694				// var compA = (a.dataset.postviews != 0) ? parseInt(a.dataset.postviews) : 0; 
695				// var compB = (b.dataset.postviews != 0) ? parseInt(b.dataset.postviews) : 0;
696				var compA = parseInt(a.dataset.postviews); 
697				var compB = parseInt(b.dataset.postviews);
698			}
699			//compare
700			if (~mode.indexOf("ASC")) {
701				return ((compA < compB) ? -1 : ((compA > compB) ? 1 : 0));
702			}
703			else if (~mode.indexOf("DESC")) {
704				return ((compA > compB) ? -1 : ((compA < compB) ? 1 : 0));
705			}
706		});  
707		return search_results;
708	}
709	this.distributeElements = function(sorted_elements, parent) {
710		var posts_per_page = $(".query-pages-wrapper").data("ppp");
711		var pages  = $(".query-page").length;
712		var i = 0;
713
714		for (var x = 1; x <= pages; x++) {
715			var limit_per_page = 1;
716			for (; i < sorted_elements.length;) {
717				
718				parent.find($('.query-page[data-page="' + x + '"]')).append(sorted_elements[i]);
719				i++;
720				if (limit_per_page == posts_per_page) {
721					break;
722				}
723				limit_per_page++;
724			}                
725		} 
726	}
727	this.startQuery = function() {
728		const sortingDropdown = $('.greyd-posts-slider').find('.sorting');
729		sortingDropdown.find("select").off("change").on('change', function () {
730			var url = $(this).val(); // get selected value
731			if (url) { // require a URL
732				window.location = url; // redirect
733			}
734			return false;
735		});
736	}
737	
738}
739
740/*
741 * jq.TableSort -- jQuery Table sorter Plug-in
742 * Copyright (c) 2017 Dmitry Zavodnikov
743 * Licensed under the MIT License
744 * 
745 * was global default.js variable 'tablesort'
746 */
747greyd.query.table = new function() {
748	
749	this.init = function() {
750		
751		// do not init if classic theme is detected
752		if ( typeof tablesort !== 'undefined' ) return;
753
754		// return if not needed
755		if ( $(".posts_table").length === 0 ) return false;
756
757		this.config  = {
758			styles: {
759				'sort':     'sortable', 
760				'asc':      'ascending', 
761				'desc':     'descending', 
762				'unsort':   'unsorted'
763			},
764			defaultColumn: 0,
765			defaultOrder: 'asc',
766			selector: function(tbody, column) {
767				var groups = [];
768				$.each($(tbody).find('tr'), function(index, tr) {
769					var td = $(tr).find('td')[column];
770					groups.push({
771						'elem': [tr], 
772						'text': $(td).text()
773					});
774				});
775				return groups;
776			},
777			comparator: function(a, b) {
778				function convertToNum(x) { return parseFloat( x.replace(',','.') ); }
779				var regex = /^[0-9\s.,]+$/;
780				a = a.text, b = b.text;
781				if ( a.match(regex) && b.match(regex) ) return convertToNum(b) - convertToNum(a);
782				return a.localeCompare(b);
783			}
784		};
785		
786		$(".posts_table").each( function(i, wrapper) {
787			// Add click listener to the header.
788			$.each(greyd.query.table.getSortableTableHeaders(wrapper), function(j, th) {
789				$(th).off("click").on("click", function(event) {
790					var clickColumn = $.inArray(event.currentTarget, greyd.query.table.getAllTableHeaders( $(this).closest("table") ));
791					
792					greyd.query.table.changeOrder(wrapper, clickColumn);
793				});
794				// $(th).append("<span class='icon'><span></span><span></span></span>"); // already added via php
795			});
796			// Table sort on load
797			//greyd.query.table.changeOrder(table, greyd.query.table.config.defaultColumn);
798		});
799	}
800	
801	this.getAllTableHeaders = function(wrapper) {
802		return $(wrapper).find('thead > tr > th');
803	}
804	
805	this.getNthTableHeaders = function(wrapper, n) {
806		return $(wrapper).find('thead > tr > th:nth-child('+(n+1)+')');
807	}
808
809	this.getSortableTableHeaders = function(wrapper) {
810		return greyd.query.table.getAllTableHeaders(wrapper).filter(function(index){
811			return $(this).hasClass(greyd.query.table.config.styles['sort']);
812		});
813	}
814
815	this.changeOrder = function(wrapper, column) {
816		var th = greyd.query.table.getNthTableHeaders(wrapper, column);
817		
818		// Order
819		var sortOrder = greyd.query.table.config.defaultOrder;
820		if (th.hasClass(greyd.query.table.config.styles['asc'])) {
821			sortOrder = 'desc';
822		}
823		if (th.hasClass(greyd.query.table.config.styles['desc'])) {
824			sortOrder = 'asc';
825		}
826		
827		// Reset
828		var headers = greyd.query.table.getSortableTableHeaders(wrapper);
829		headers.removeClass( greyd.query.table.config.styles['asc']+" "+greyd.query.table.config.styles['desc'] );
830		headers.addClass( greyd.query.table.config.styles['unsort'] );
831		
832		// Set classes
833		th.removeClass(greyd.query.table.config.styles['unsort']);
834		th.addClass(greyd.query.table.config.styles[sortOrder]);
835		
836		// Group
837		var tbody = $(wrapper).find('tbody');
838		var groups = greyd.query.table.config.selector(tbody, column);
839
840		// Sorting
841		groups.sort(function(a, b){
842			var res = greyd.query.table.config.comparator(a, b);
843			return sortOrder == 'asc' ? res : -1 * res;
844		});
845
846		// Change order
847		var rows = parseInt( $(wrapper).data('rows') ), i = 0, k = 0;
848		$.each(groups, function(i, trList) {
849			if ( i === rows * ( k+1 ) ) k++;
850			$.each(trList.elem, function(j, tr) {
851				tbody[k].append(tr);
852			});
853			i++;
854		});
855	}
856
857};

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.