PageSourceSearch

https://brasilmetropole.com.br/wp-content/themes/smart-mag/js/theme.js?ver=8.0.5

js brasilmetropole.com.br collected 2026-10-02 13:50:27 UTC 52,292 bytes, 2,204 lines download raw bytes

1/**
2 * SmartMag Theme Frontend JS.
3 * 
4 * @copyright 2021 ThemeSphere.
5 */
6"use strict";
7
8if (!Bunyad) {
9	var Bunyad = {};
10}
11
12Bunyad.theme = (function($) {
13	
14	var hasTouch = false,
15		responsiveMenu = false,
16		isIframe = window.BunyadIsIframe || false,
17		schemeKey = window.BunyadSchemeKey || 'bunyad-scheme';
18		
19	if (!window.requestIdleCallback) {
20		window.requestIdleCallback = requestAnimationFrame;
21	}
22	
23	// module
24	var self = {
25		init: function() {
26
27			// Detect touch capability dynamically.
28			$(window).on('touchstart', function() {
29				// First touch.
30				if (!hasTouch) {
31					$('body').addClass('touch');
32					self.touchNav();
33				}
34
35				hasTouch = true;
36			});
37
38			this.imageEffects();
39			
40			// Setup all sliders
41			this.sliders();
42			this.contentSlideshow();
43			
44			// Setup mobile header and navigation
45			this.header();
46			this.responsiveNav();
47			this.megaMenus();
48			
49			// Start the news ticker
50			this.newsTicker();
51			
52			// Setup the lightbox
53			requestIdleCallback(this.lightbox);
54
55			// Search modal
56			this.searchModal();
57			
58			// Use sticky sidebar if enabled
59			this.initStickySidebar();
60			
61			// User ratings
62			this.userRatings();
63
64			this.tabWidget();
65
66			/**
67			 * Woocommerce
68			 */ 
69			$('.woocommerce-ordering .drop li a').on('click', function(e) {
70				var form = $(this).closest('form');
71				form.find('[name=orderby]').val($(this).parent().data('value'));
72				form.trigger('submit');
73				
74				e.preventDefault();
75			});
76
77			$(document).on('ts-ajax-pagination', e => {
78				$(document).trigger('scroll.TSS');
79				Bunyad.sliders();
80			});
81
82			// Lower priority.
83			requestIdleCallback(() => {
84				self.contextualBinds(document);
85
86				// Nav icons class if missing
87				$('.navigation i.only-icon').each(function() {	
88					var el = $(this).closest('li');
89					if (!el.hasClass('only-icon')) {
90						el.addClass('only-icon');
91					}
92				});
93
94				// Single show comments.
95				$(document).on('click', '.ts-comments-show', function() {
96					$(this).hide()
97						.closest('.comments')
98						.find('.ts-comments-hidden').show();
99					return false;
100				});
101	
102			}, {timeout: 1000});
103		},
104
105		/**
106		 * @param {HTMLDocument|HTMLElement} document
107		 */
108		contextualBinds: function(document)
109		{
110			// Fit videos to container.
111			requestAnimationFrame(() => {
112				$('.featured-vid, .post-content', document).fitVids();
113			});
114
115			// Ratings
116			$('.review-number', document).each(function() {
117				var raw = $(this).find('span:not(.progress)').html(),
118					progress = parseFloat(raw);
119				
120				$(this).find('.progress').css('width', (raw.search('%') === -1 ? (Math.round(progress / 10 * 100)) + '%' : progress));
121			});
122
123			$('.review-box ul li .bar', document).each(function() {
124				$(this).data('width', $(this)[0].style.width).css('width', 0);
125			});
126		
127			new Bunyad_InView(
128				document.querySelectorAll('.review-box ul li', document),
129				entry => {
130					const bar = $(entry.target).find('.bar');
131					bar.addClass('appear').css('width', bar.data('width'));
132				},
133				{once: true}
134			);
135
136			// Single top social sharing view all buttons
137			$('.post-share-b .show-more', document).on('click', function() {
138				$(this).parent().addClass('all');
139				return false;
140			});
141
142			// Go back handler for 404.
143			$('.go-back').on('click', function() { 
144				window.history.back();
145				return false;
146			});
147		},
148
149		/**
150		 * Reinit common theme functionality, in a context, usually ALP feature.
151		 * 
152		 * @param {HTMLDocument|HTMLElement} context
153		 */
154		reInit: function(context) {
155
156			// Only for elements.
157			if (context !== document) {
158				this.imageEffects(context.querySelectorAll('img'));
159			}
160
161			this.contextualBinds(context);
162			this.lightbox();
163			this.contentSlideshow();
164			this.userRatings();
165
166			setTimeout(this.stickySidebar, 50);
167
168			Bunyad.sliders();
169		},
170
171		/**
172		 * Image scroll animations.
173		 */
174		imageEffects: function(elements) {
175
176			// Image effects - remove temp CSS when loaded.
177			if (!$('body').hasClass('img-effects')) {
178				return;
179			}
180
181			if (!elements) {
182				elements = document.querySelectorAll('.main-wrap .wp-post-image, .post-content img');
183			}
184
185			elements.forEach(e => e.classList.add('no-display'));
186			$('.bunyad-img-effects-css').remove();
187
188			new Bunyad_InView(
189				elements,
190				entry => entry.target.classList.add('appear'),
191				{once: true},
192				() => $(elements).addClass('appear')
193			);
194		},
195		
196		newsTicker: function() {
197
198			$('.trending-ticker').each(function() {
199
200				if (!$(this).find('li.active').length) {
201					$(this).find('li:first').addClass('active');
202				}
203				
204				let ticker   = $(this);
205				let interval = false;
206				const delay  = parseInt(ticker.data('delay') || 5) * 1000;
207				
208				const setTick = () => {
209					var active = ticker.find('li.active');
210					active.fadeOut(function() {
211
212						var next = active.next();
213						if (!next.length) {
214							next = ticker.find('li:first');
215						}
216						
217						next.addClass('active').fadeIn();
218						active.removeClass('active');
219					});
220				}
221				
222				const startTicker = () => {
223					if (interval) {
224						return;
225					}
226
227					interval = window.setInterval(setTick, delay);
228				}
229
230				startTicker();
231
232				ticker.on('mouseenter', 'li', () => {
233					clearInterval(interval);
234					interval = false;
235				});
236
237				ticker.on('mouseleave', 'li', startTicker);
238			});
239		},
240		
241		header: function() {
242			
243			const toggleDarkMode = (scheme) => {
244				const prevScheme = (scheme == 'dark' ? 'light' : 'dark');
245
246				// Set initial scheme.
247				const htmlClass = $('html').data('origClass');
248				let initialScheme;
249				if (htmlClass) {
250					initialScheme = htmlClass.includes('s-dark') ? 'dark' : 'light';
251				}
252
253				if (scheme !== initialScheme) {
254					localStorage.setItem(schemeKey, scheme);
255				}
256				else {
257					localStorage.removeItem(schemeKey);
258				}
259				
260				$('html')
261					.removeClass(`s-${prevScheme} site-s-${prevScheme}`)
262					.addClass(`s-${scheme} site-s-${scheme}`);
263			};
264			
265			$('.scheme-switcher .toggle').on('click', function() {
266				const ele  = $(this);
267				let scheme = ele.hasClass('toggle-dark') ? 'dark' : 'light';
268
269				toggleDarkMode(scheme);
270
271				// Notify auto-loaded posts.
272				document.querySelectorAll('iframe.spc-auto-load-post').forEach(element => {
273					element.contentWindow.postMessage({
274						action: 'toggle-dark-mode',
275						scheme
276					}, '*');
277				});
278
279				return false;
280			});
281
282			// Listen and change in auto-loaded posts.
283			if (isIframe) {
284				window.addEventListener('message', e => {
285					if (!e.data || e.data.action !== 'toggle-dark-mode') {
286						return;
287					}
288
289					toggleDarkMode(e.data.scheme);
290				});
291			}
292		},
293		
294		/**
295		 * Setup the responsive nav events and markup
296		 */
297		responsiveNav: function() {
298			this.initResponsiveNav();
299		},
300
301		initResponsiveNav: function() {
302			
303			if (responsiveMenu || !$('.off-canvas').length) {
304				responsiveMenu = true;
305				return;
306			}
307			
308			// Set responsive initialized
309			responsiveMenu = true;
310
311			// Test for overlay/non-obstrusive scrollbar (MacOS).
312			const hasOverlayScroll = () => {
313				const ele = document.createElement("div");
314				ele.setAttribute("style", "width:30px;height:30px;overflow:scroll;opacity:0");
315				document.body.appendChild(ele);
316
317				const result = ele.offsetWidth === ele.clientWidth;
318				document.body.removeChild(ele);
319				
320				return result;
321			}
322
323			const setupScroll = () => {
324				if (!hasTouch && !hasOverlayScroll()) {
325					document.body.classList.add("has-scrollbar");
326	
327					// Reflow to fix scrollbars.
328					const ele = $('.off-canvas-content');
329					ele.css('display', 'block');
330	
331					requestAnimationFrame(function() {
332						ele.css('display', 'flex');
333					});
334				}
335			}
336
337			const setupMenuHandlers = () => {
338				// Setup mobile menu click handlers
339				$('.mobile-menu li > a').each(function() {
340					
341					if ($(this).parent().children('ul').length) {
342						$('<span class="chevron"><i class="tsi tsi-chevron-down"></i></span>').insertAfter($(this));
343					}
344				});
345				
346				$('.mobile-menu li .chevron').on('click', function() {
347					$(this).closest('li').find('ul')
348						.first()
349						.parent()
350						.toggleClass('active item-active');
351
352					return false;
353				});
354			}
355
356			const setupMobileMenu = () => {
357				var container = $('.mobile-menu-container');
358
359				// No items for mobile menu? Grab from others
360				if (!container.find('.mobile-menu').children().length) {
361					
362					// Merge existing menus
363					var mobileMenu = container.find('.mobile-menu'),
364						mainMenu = $('.navigation-main .menu');
365						
366					if (!mainMenu.length) {
367						return;
368					}
369
370					var menu = mainMenu.children().clone();
371					
372					// add category mega menu links
373					menu.find('.mega-menu .sub-cats').each(function() {
374						var container = $(this).closest('.menu-item');
375						
376						container.append($(this).find('.sub-nav'));
377						container.find('.sub-nav').replaceWith(function() {
378							return $('<ul />', {html: $(this).html()});
379						});
380						
381						$(this).remove();
382					});
383					
384					mobileMenu.append(menu);
385				}
386			}
387
388			// Delayed setup.
389			let isMenuSetup = false;
390			const initSetup = () => {
391				setupScroll();
392				setupMobileMenu();
393				setupMenuHandlers();
394				
395				isMenuSetup = true;
396			};
397
398			// Bunyad.util.onLoad(() => requestIdleCallback(initSetup, {timeout: 1000}));
399			const showMenu = () => {
400				if (!isMenuSetup) {
401					initSetup();
402				}
403				
404				$('html').toggleClass('off-canvas-active');
405			}
406		
407			$('.mobile-head .menu-icon a, .smart-head .offcanvas-toggle')
408				.on('click', function() {
409					$(document).trigger('ts-sticky-bar-remove');
410					showMenu();
411				});
412
413			// Off-canvas close
414			$('.off-canvas .close').on('click', function() {
415				showMenu();
416				return false;
417			});
418
419			$('.off-canvas-backdrop').on('click', function() {
420				$('.off-canvas .close').click();
421				return false;
422			})
423		},
424
425		megaMenus: function() {
426			const media = window.matchMedia('(min-width: 940px)');
427			const init  = e => {
428				if (e.matches) {
429					this.initMegaMenus();
430				}
431				media.removeListener(init);
432			};
433
434			init(media);
435			media.addListener(init);
436		},
437
438		initMegaMenus: function() {
439			// Bind events for mega menus
440			$('.navigation .mega-menu-a').each(function() {
441				
442				var menu = $(this),
443				    number = menu.find('.recent-posts').data('columns');
444				
445				// Init mega menus
446				var default_mega_menu = function f() {
447					menu.find('.posts').last().addClass('active');
448					return f;
449				}();
450
451				// Mega-menu sub-cats handling.
452				menu.find('.menu-item').on('mouseenter', function() {
453
454					var id = parseInt( $(this).attr('class').match(/menu-cat-(\d+)/)[1] || 0 ),
455					    menu = $(this).parents('.mega-menu'),
456					    view_all = $(this).hasClass('view-all');
457				
458					if (!view_all && !id) {
459						return;
460					}
461					
462					// Remove other actives
463					menu.find('.active, .current-menu-item').removeClass('active current-menu-item');
464
465					// Activate current
466					$(this).addClass('current-menu-item');
467					var posts = menu.find('[data-id=' + id + ']').addClass('active');
468					
469					return false;
470				});
471				
472				// Reset mega menu state on fresh hover
473				menu.parent().on('mouseenter', function() {
474					
475					var menu = $(this).find('.mega-menu');
476					
477					// reset at beginning
478					menu.find('.active, .current-menu-item')
479						.removeClass('active current-menu-item');
480
481					$(this)[0].offsetWidth; // reflow
482					default_mega_menu();
483				});
484				
485			});
486		},
487		
488		/**
489		 * Setup touch navigation for larger touch devices.
490		 */
491		touchNav: function() {
492			
493			var targets = $('.menu:not(.mobile-menu) a'),
494				open_class = 'item-active',
495				child_tag = 'ul, .mega-menu';
496			
497			targets.each(function() {
498				
499				var $this = $(this),
500					$parent = $this.parent('li'),
501					$siblings = $parent.siblings().find('a');
502				
503				$this.on('click', function(e) {
504
505					var $this = $(this);
506					e.stopPropagation();
507					
508					$siblings.parent('li').removeClass(open_class);
509					
510					// has a child? open the menu on tap
511					if (!$this.parent().hasClass(open_class) && $this.next(child_tag).length > 0 && !$this.parents('.mega-menu.links').length) {
512						e.preventDefault();
513						$this.parent().addClass(open_class);
514					}
515				});
516			});
517			
518			// close all menus
519			$(document).on('click', function(e) {
520				if (!$(e.target).is('.menu') && !$(e.target).parents('.menu').length) {
521					targets.parent('li').removeClass(open_class);
522				}
523			});
524		},
525
526		initStickySidebar: function() {
527
528			let hasInit  = false;
529			const events = 'resize orientationchange scroll';
530			const init = () => {
531				if (hasInit) {
532					return;
533				}
534
535				if (document.documentElement.clientWidth >= 940) {
536					self.stickySidebar();
537					hasInit = true;
538					$(window).off(events, init);
539				}
540			}
541
542			$(window).on(events, init);
543			Bunyad.util.onLoad(init);
544		},
545		
546		/**
547		 * Setup sticky sidebar
548		 */
549		stickySidebar: function() {
550
551			const stickyHeaderHeight = () => {
552				const stickyHead = $('.smart-head-sticky');
553				let addHeight = 0;
554				if (stickyHead.length) {
555					let height = window.getComputedStyle(stickyHead[0]).getPropertyValue('--head-h');
556					addHeight = parseInt(height) || 0;
557				}
558
559				return addHeight;
560			}
561
562			const initNative = () => {
563				if (!$('.ts-sticky-native').length) {
564					return;
565				}
566
567				let baseTop = 20;
568				if ($('.admin-bar').length) {
569					baseTop += $('#wpadminbar').height();
570				}
571				
572				const setTop = top => $('body').css('--ts-sticky-top', top + 'px');				
573
574				$(document).on('sticky-bar-show', () => setTop(baseTop + stickyHeaderHeight()));
575				$(document).on('sticky-bar-hide', () => setTop(baseTop));
576			}
577
578			const init = (addExtra) => {
579
580				const sticky = $('.ts-sticky-col, .main-sidebar[data-sticky=1]');
581				if (!sticky.length) {
582					return;
583				}
584				
585				let add = 20;
586				if ($('.admin-bar').length) {
587					add += $('#wpadminbar').height();
588				}
589				add += addExtra || 0;
590
591				sticky.each(function() {
592
593					var stickyCol = $(this);
594					if (stickyCol.data('init') || stickyCol.hasClass('.ts-sticky-native')) {
595						return;
596					}
597
598					stickyCol.data('init', 1);
599					
600					// Add wrapper class if missing
601					if (!stickyCol.find('.theiaStickySidebar').length) {
602						stickyCol.find('.elementor-widget-wrap').first().addClass('theiaStickySidebar');
603						stickyCol.css({display: 'block'});
604					}
605
606					stickyCol.theiaStickySidebar({
607						minWidth: 940, 
608						updateSidebarHeight: false,
609						additionalMarginTop: add,
610						additionalMarginBottom: 20,
611						disableOnResponsiveLayouts: false
612					});
613					
614					// Update TSS internal options on sticky header on / off.
615					const options = stickyCol.data('tss-options');
616
617					if (!options) {
618						return;
619					}
620
621					const stickyInner       = stickyCol.find('.theiaStickySidebar');
622					const stickyColHeight   = stickyCol.outerHeight();
623					const stickyInnerHeight = stickyInner.outerHeight();
624
625					$(document).on('sticky-bar-show', () => {
626						const newMarginTop = add + stickyHeaderHeight();
627
628						// Do nothing if the height will exceed. This would cause a bug at bottom of sticky turning static.
629						if (stickyInnerHeight + newMarginTop >= stickyColHeight) {
630							return;
631						}
632
633						if (newMarginTop !== options.additionalMarginTop) {
634							// Ignore unexpected negative transform of scrolling down.
635							if (!sticky.css('transform').includes('-')) {
636								options.additionalMarginTop = newMarginTop;
637								setTimeout(() => $(window).trigger('scroll.TSS'), 300);
638							}
639						}
640					});
641
642					// Reset margins on sticky bar hide.
643					$(document).on('sticky-bar-hide', () => {
644						options.additionalMarginTop = add;
645						setTimeout(() => $(window).trigger('scroll.TSS'), 300);
646					});
647				});
648			};
649
650			init();
651			initNative();
652			
653			// for iframe loads in sidebar
654			Bunyad.util.onLoad(() => setTimeout(() => {
655				$(window).trigger('resize.TSS');
656			}, 3500));
657		},
658		
659		/**
660		 * Setup legacy slider and slideshow.
661		 */
662		sliders: function() {
663
664			if (!$.fn.flexslider) {
665				return;
666			}
667			
668			var is_rtl = ($('html').attr('dir') == 'rtl' ? true : false);
669			
670			// Classic / Legacy slider.
671			var slider = $('.classic-slider');
672
673			if (!slider.length) {
674				return;
675			}
676			
677			slider.find('.flexslider').flexslider({
678				controlNav: true,
679				animationSpeed: slider.data('animation-speed'),
680				animation: slider.data('animation'),
681				slideshowSpeed: slider.data('slide-delay'),
682				manualControls: '.main-featured .flexslider .pages a',
683				pauseOnHover: true,
684				start: function() {
685					$('.main-featured .slider').css('opacity', 1);
686				},
687				rtl: is_rtl
688			});
689			
690			// Dynamic pagination - if not at default of 5
691			var pages  = slider.find('.pages'),
692				number = parseInt(pages.data('number'));
693			
694			if (number && number !== 5) {
695				var width = (100 - ((number + 1) * 0.284900285)) / number;
695  // 100 - (slides + 1 * margin-left) / slides
696				pages.find('a').css('width', width + '%');
697			}
698		},
699
700		/**
701		 * Post Content Slideshow: AJAX
702		 */
703		contentSlideshow: function() {
704
705			var slideshow_cache = {},
706				slideshow_wrap  = '.post-slideshow .post-pagination-large';
707			
708			if ($(slideshow_wrap).length && !$(slideshow_wrap).data('init') && $(slideshow_wrap).data('type') == 'ajax') {
709			
710				var processing;
711				$(slideshow_wrap).data('init', true);
712
713				$('.main-content').on('click', '.post-slideshow .post-pagination-large .links a', function() {
714					
715						// showing on home-page?
716						if ($('body').hasClass('page')) {
717							return;
718						}
719						
720						// bottom links, scroll top
721						var scroll;
722						if ($(this).parents('.bottom').length) {
723							scroll = true;
724						}
725						
726						// abort existing request
727						if (processing && processing.hasOwnProperty('abort')) {
728							processing.abort();
729						}
730					
731						var parent = $(this).closest('.post-slideshow'),
732							url    = $(this).attr('href');
733						
734						parent.find('.content-page').removeClass('active').addClass('hidden previous');
735					
736						var show_slide = function(data) {
737							
738							// change browser url
739							if (history.pushState) {
740								history.pushState({}, '', url);
741							}
742							
743							var page = $(data).find('.post-slideshow');
744							
745							if (page.length) {
746								parent.find('.post-pagination-large').html(page.find('.post-pagination-large').html());
747								parent.find('.content-page').after(page.find('.content-page').addClass('hidden loading'));
748								
749								setTimeout(function() {
750
751									if (scroll) {
752										$('html, body').animate({scrollTop: parent.offset().top - 50}, 200);
753									}
754									
755									parent.find('.content-page.previous').remove();
756									parent.find('.content-page.loading')
757										.removeClass('previous hidden loading')
758										.find('img').addClass('appear');
759								}, 1);
760							}
761							
762							processing = null;
763							
764						};
765						
766						// in cache?
767						if (slideshow_cache[url]) {
768							show_slide(slideshow_cache[url]);
769						}
770						else {
771							
772							// get via ajax
773							processing = $.get(url, function(data) {
774								slideshow_cache[url] = data;
775								show_slide(data);
776								
777							});
778						}
779						
780						return false;
781				});
782				
783				// keyboard nav
784				$(document).on('keyup', function(e) {				
785						if (e.which == 37) {
786							$(slideshow_wrap).find('.prev').parent().click();
787						}
788						else if (e.which == 39) {
789							$(slideshow_wrap).find('.next').parent().click();
790						}
791				});
792				
793			}
794		},
795				
796		/**
797		 * User Ratings handling
798		 */
799		userRatings: function() {
800			
801			var compute_percent = function(e) {
802				
803				var offset = $(this).offset(),
804				    position, percent;
805				
806				// count from right for RTL
807				if ($('html').attr('dir') == 'rtl')  {
808					offset.left = offset.left + $(this).outerWidth();
809				}
810				
811				position = Math.abs(e.pageX - Math.max(0, offset.left));
812				percent  = Math.min(100, Math.round(position / $(this).width() * 100));
813				
814				return percent;
815			};
816
817			// percent or points?
818			var is_points = true,
819				scale = parseInt($('.review-box .value-title').text()) || 10;
820			
821			if ($('.review-box .overall .percent').length) {
822				is_points = false;
823			}
824			
825			// update the bar and percent/points on hover
826			$('.user-ratings .main-stars, .user-ratings .rating-bar').on('mousemove mouseenter mouseleave', 
827				function(e) {
828				
829					// set main variables
830					var bar = $(this).find('span'),
831						user_ratings = $(this).closest('.user-ratings');
832				
833					bar.css('transition', 'none');
834					
835					if (user_ratings.hasClass('voted')) {
836						return;
837					}
838				
839					// hover over?
840					if (e.type == 'mouseleave') {
841						bar.css('width', bar.data('orig-width'));
842						user_ratings.find('.hover-number').hide();
843						user_ratings.find('.rating').show();
844						return;
845					}
846					
847					var percent = compute_percent.call(this, e);
848					
849					if (!bar.data('orig-width')) {
850						bar.data('orig-width', bar[0].style.width);
851					}
852					
853					bar.css('width', percent + '%');
854					user_ratings.find('.rating').hide();
855					user_ratings.find('.hover-number').show().text((is_points ? +parseFloat(percent / 100 * scale).toFixed(1) : percent + '%'));
856				}
857			);
858			
859			// add the rating
860			$('.user-ratings .main-stars, .user-ratings .rating-bar').on('click', function(e) {
861				
862				// set main variables
863				var bar = $(this).find('span'),
864					user_ratings = $(this).closest('.user-ratings');
865				
866				if (user_ratings.hasClass('voted')) {
867					return;
868				}
869				
870				// setup ajax post data
871				var post_data = {
872						'action': 'bunyad_rate', 
873						'id': user_ratings.data('post-id'), 
874						'rating': compute_percent.call(this, e)
875				};
876				
877				// get current votes
878				var votes = user_ratings.find('.number'),
879					cur_votes = parseInt(votes.text()) || 0;
880				
881				user_ratings.css('opacity', '0.3');
882				bar.data('orig-width', bar[0].style.width);
883				
884				// add to votes and disable further voting 
885				votes.text((cur_votes + 1).toString());
886				
887				$(this).trigger('mouseleave');
888				user_ratings.addClass('voted');
889				
890				$.post(Bunyad.ajaxurl, post_data, function(data) {
891					
892					// update data
893					if (data === Object(data)) {
894
895						// change rating
896						var cur_rating = user_ratings.find('.rating').text();
897						user_ratings.find('.rating').text( cur_rating.search('%') !== -1 ? data.percent + ' %' : data.decimal );
898						
899						bar.css('width', data.percent + '%');
900						bar.data('orig-width', data.percent);
901					}
902					
903					user_ratings.hide().css('opacity', 1).fadeIn('slow');			
904				}, 'json');
905			});
906		},
907		
908		tabWidget: function() {
909			$(document).on('click', '.widget-tabbed .heading a', function() {
910				
911				var tab = $(this).data('tab'),
912					tabs_data = $(this).closest('.widget-tabbed').find('.tabs-data'),
913					parent = $(this).parent().parent(),
914					active = parent.find('.active');
915				
916				if (!active.length) {
917					active = parent.find('li:first-child');
918				}
919
920				active.removeClass('active').addClass('inactive');
921				$(this).parent().addClass('active').removeClass('inactive');
922				
923				// hide current and show the clicked one
924				var active_data = tabs_data.find('.tab-posts.active');
925				if (!active_data.length) {
926					active_data = tabs_data.find('.tab-posts:first-child');
927				}
928				
929				active_data.hide();
930				tabs_data.find('#recent-tab-' + tab).fadeIn().addClass('active').removeClass('inactive');
931
932				return false;
933			});
934		},
935
936		searchModal: function() {
937			let isSetup = false;
938			const target = $('.smart-head .search-icon');
939
940			const setup = () => {
941				if (isSetup || !$.fn.magnificPopup) {
942					return;
943				}
944
945				isSetup = true;
946				const scheme = $('.search-modal-wrap').data('scheme') == 'dark' ? ' s-dark' : '';
947
948				// Search modal
949				target.magnificPopup({
950					items: {
951						src: '.search-modal-wrap',
952						type: 'inline'
953					},
954					removalDelay: 400,
955					focus: 'input',
956					closeBtnInside: false,
957					closeOnBgClick: false,
958					mainClass: 'search-modal' + scheme,
959					midClick: true,
960					fixedContentPos: true,
961					autoFocusLast: false
962				}); 
963			};
964
965			target.on('mouseover', setup);
966			setTimeout(setup, 400);
967		},
968
969		/**
970		 * Setup prettyPhoto
971		 */
972		lightbox: function() {
973			
974			// Can be disabled overall, or on mobile.
975			if (
976				!$.fn.magnificPopup 
977				|| !$('body').hasClass('has-lb') 
978				|| (!$('body').hasClass('has-lb-sm') && $(window).width() < 768)
979			) {
980				return;
981			}
982
983			if (isIframe) {
984				return;
985			}
986			
987			var mfpInit = {
988				type: 'image',
989				tLoading: '',
990				mainClass: 'mfp-fade mfp-img-mobile',
991				removalDelay: 300,
992				callbacks: {
993					afterClose: function() {
994						if (this._lastFocusedEl) {
995							$(this._lastFocusedEl).addClass('blur');
996						}
997					}
998				}
999			};
1000
1001			/**
1002			 * Filter to handle valid images only.
1003			 */
1004			var filterImages = function() {
1005				
1006				if (!$(this).attr('href')) {
1007					return false;
1008				}
1009				
1010				return $(this).attr('href').match(/\.(jpe?g|webp|png|bmp|gif)($|\?.+?)/); 
1011			};
1012			
1013			/**
1014			 * Handle Galleries in post.
1015			 * 
1016			 * @param {HTMLElement} context
1017			 */
1018			var addGalleryLightbox = function(context) {
1019				var gal_selectors = '.gallery-slider, .post-content .gallery, .post-content .blocks-gallery-item, .post-content .tiled-gallery';
1020		
1021				// Filter to only tie valid images.
1022				$(gal_selectors, context)
1023					.find('a')
1024					.has('img')
1025					.filter(filterImages)
1026					.addClass('lightbox-gallery-img');
1027
1028				// Add WooCommerce support
1029				$('.woocommerce a[data-rel^="prettyPhoto"], a.zoom').addClass('lightbox-gallery-img');
1030				gal_selectors += ', .woocommerce .images';
1031
1032				// Attach the lightbox as gallery
1033				$(gal_selectors, context).magnificPopup($.extend({}, mfpInit, {
1034					delegate: '.lightbox-gallery-img',
1035					gallery: {enabled: true},
1036					image: {
1037						titleSrc: function(item) {
1038							var image   = item.el.find('img'), 
1039								caption = item.el.find('.caption').html();
1040							
1041							return (caption || image.attr('title') || ' ');
1042						}
1043					}
1044				}));
1045			};
1046			
1047			/**
1048			 * Non-gallery images in posts.
1049			 * 
1050			 * @param {HTMLElement} context 
1051			 */
1052			var addLightboxImages = function(context) {
1053
1054				var selector = 
1055					$('.post-content, .main .featured, .single-creative .featured', context)
1056						.find('a:not(.lightbox-gallery-img)')
1057						.has('img, .img');
1058
1059				selector.add('.lightbox-img')
1060					.filter(filterImages)
1061					.magnificPopup(mfpInit);
1062
1063			};
1064
1065			addGalleryLightbox();
1066			addLightboxImages();
1067
1068			$('iframe.spc-auto-load-post').each(function() {
1069				const iframe = $(this).get(0).contentDocument;
1070				addGalleryLightbox(iframe);
1071				addLightboxImages(iframe);
1072			});
1073			
1074		}
1075	};
1076
1077	self.stickyBarPause = false;
1078
1079	return self;
1080	
1081})(jQuery);
1082/**
1083 * Utility methods.
1084 */
1085Bunyad.util = {
1086	
1087	throttle(fn, delay = 150, trails = true) {
1088
1089		let pause = false;
1090		let trail;
1091		let timeout = function() {
1092			if (trail) {
1093				fn.apply(trail[0], trail[1]);
1094				trail = null;
1095				setTimeout(timeout, delay);
1096			} else {
1097				pause = false;
1098			}
1099		};
1100
1101		return function(...args) {
1102			if (!pause) {
1103				fn.apply(this, args);
1104				pause = true;
1105				setTimeout(timeout, delay);
1106			} else if (trails) {
1107				trail = [this, args];
1108			}
1109		};
1110	},
1111
1112	writeRaf(fn, options) {
1113		var running, 
1114		    args, 
1115		    that;
1116
1117		var run = function() {
1118			running = false;
1119			fn.apply(that, args);
1120		};
1121
1122		if (!options) {
1123			options = {};
1124		}
1125
1126		return function() {
1127			args = arguments;
1128			that = options.that || this;
1129
1130			if (!running) {
1131				running = true;
1132				requestAnimationFrame(run);
1133			}
1134		};
1135	},
1136
1137	onLoad(cb) {
1138		document.readyState === 'complete' ? cb() : window.addEventListener('load', cb);
1139	}
1140};
1141
1142/**
1143 * Authentication modal.
1144 */
1145(function($) {
1146
1147	/** @type {Boolean} */
1148	let isInitialized = false;
1149
1150	function init() {
1151
1152		if (!$('#auth-modal').length) {
1153			return;
1154		}
1155
1156		$(document).on('click', 'a', e => {
1157			if (e.currentTarget.hash === '#auth-modal') {
1158				if (!window.MicroModal) {
1159					return;
1160				}
1161		
1162				initModal();
1163				MicroModal.show('auth-modal', {
1164					awaitCloseAnimation: true
1165				});
1166
1167				e.preventDefault();
1168			}
1169		});
1170	}
1171
1172	function initModal(e) {
1173
1174		if (isInitialized) {
1175			return;
1176		}
1177
1178		const modal  = $('#auth-modal');
1179		const toggle = e => {
1180			modal.find('.auth-modal-login, .auth-modal-register').toggle();
1181			e.preventDefault();
1182		}
1183		
1184		modal.on('click', '.register-link, .login-link', toggle);
1185		isInitialized = true;
1186	}
1187
1188	Bunyad.authModal = init;
1189
1190})(jQuery);
1191(function($) {
1192
1193	const cache = [];
1194
1195	function init() {
1196		$('.section-head .subcats a, .block-head .filters a').on('click', e => {
1197			doFilter(e.currentTarget);
1198			return false;
1199		});
1200	}
1201
1202	function doFilter(ele) {
1203
1204		if ($(this).hasClass('active')) {
1205			return false;
1206		}
1207
1208		ele = $(ele);
1209
1210		const block   = ele.closest('.block-wrap');
1211		const blockId = block.data('id');
1212		const termId  = ele.data('id');
1213		const content = block.find('.block-content');
1214		const curActive = ele.parents('.filters').find('a.active');
1215		
1216		// Store "All" in cache.
1217		if (!curActive.data('id')) {
1218			cache[`${blockId}-0`] = block[0].outerHTML;
1219		}
1220
1221		// Filter links active
1222		ele.addClass('active');
1223		curActive.removeClass('active');
1224		
1225		const cacheId = `${blockId}-${termId}`;
1226		content.removeClass('fade-in-up-lg')
1227			.addClass('loading');
1228
1229		if (!cache[cacheId]) {
1230
1231			const blockData = block.data('block') || {};
1232			blockData.props.filter = termId;
1233
1234			// AJAX params
1235			const params =  {
1236				action: 'bunyad_block',
1237				block: blockData
1238			};
1239
1240			$.post(
1241				Bunyad.ajaxurl,
1242				params,
1243				data => {
1244					cache[cacheId] = data;
1245					replaceContent(cache[cacheId], block, content);
1246				}
1247			);
1248		}
1249		else {
1250			replaceContent(cache[cacheId], block, content);
1251		}
1252	}
1253
1254	function replaceContent(data, block, content) {
1255		const newHtml    = $(data);
1256		const newContent = newHtml.find('.block-content')
1257		newContent.find('img').addClass('no-display appear');
1258
1259		// Race condition.
1260		newContent.find('.lazyloading').removeClass('lazyloading').addClass('lazyload');
1261		content.removeClass('fade-in-up-lg');
1262
1263		requestAnimationFrame(() => {
1264			content.html(newContent.html())
1265				.removeClass('loading')
1266				.addClass('fade-in-up-lg')
1267				.addClass('ready');
1268		});
1269		
1270		// Set new block data.
1271		block.data('block', newHtml.data('block'));
1272	}
1273
1274	Bunyad.blocksFilters = init;
1275
1276})(jQuery);
1277
1278(function($) {
1279	Bunyad.stickyHeader = function(header, options = {}) {
1280		var nav,
1281			isSmart = false,
1282			isSticky = false,
1283			stickyIsStatic = false,
1284			prevScroll = 0,
1285			curScroll  = 0,
1286			extraTop   = 0,
1287			stickyTop,
1288			hideAt,
1289			head,
1290			headHeight;
1291
1292		let stickyBar;
1293		let stickyIsActive = false;
1294		let hasInitialized = false;
1295		
1296		/**
1297		 * Calculate header size.
1298		 */
1299		const calcHeadSize = Bunyad.util.writeRaf(() => {
1300
1301			// Don't reset if it's stuck
1302			if (stickyIsActive) {
1303				return;
1304			}
1305
1306			var new_height = head.css('min-height', 0).height();
1307			head.css('min-height', new_height);
1308			headHeight = new_height;
1309		});
1310
1311		function setSize(skipCalc) {
1312
1313			// Skip calculation if asked to and head height has been prev set
1314			if (skipCalc && headHeight) {
1315				return;
1316			}
1317
1318			calcHeadSize();
1319		}
1320
1321		/**
1322		 * Remove / disable sticky.
1323		 */
1324		function removeSticky(simpleHide) {
1325		
1326			// Check before dom modification 
1327			if (isSticky) {
1328				
1329				stickyIsActive = false;
1330				let visualHide = false;
1331
1332				// Mainly for smart sticky. Simple hide by not unfixing completely.
1333				if (simpleHide) {
1334					if (!nav.hasClass('off')) {
1335						nav.addClass('off');
1336						visualHide = true;
1337					}
1338				}
1339				else {
1340					// isSticky already checks for presence of smart-head-sticky.
1341					nav.removeClass('smart-head-sticky off');
1342					visualHide = true;
1343				}
1344				
1345				if (visualHide) {
1346					setSize(true);
1347					$(document).trigger('sticky-bar-hide');
1348				}
1349			}
1350		}
1351
1352		/**
1353		 * Make the bar sticky and setup handlers.
1354		 */
1355		function toggleSticky() {
1356
1357			if (stickyIsStatic) {
1358				return;
1359			}
1360
1361			curScroll = $(window).scrollTop();
1362			isSticky  = nav.hasClass('smart-head-sticky');
1363
1364			// Check and apply sticky - separated writes
1365			const stickyWrites = Bunyad.util.writeRaf(() => {
1366				
1367				// Make it sticky when viewport is scrolled beyond the sticky bar.
1368				if (curScroll > stickyTop) {
1369
1370					// For smart sticky, test for scroll change
1371					if (isSmart && (!prevScroll || curScroll > prevScroll)) {
1372						removeSticky(true);
1373					}
1374					else {
1375						stickyIsActive = true;
1376						
1377						if (!isSmart || curScroll < prevScroll-4 && !Bunyad.theme.stickyBarPause) {
1378							if (!nav.hasClass('smart-head-sticky') || nav.hasClass('off')) {
1379								nav.removeClass('off');
1380								nav.addClass('smart-head-sticky');
1381
1382								$(document).trigger('sticky-bar-show');
1383							}
1384						}
1385					}
1386					
1387					prevScroll = curScroll;
1388					
1389				} else {
1390					
1391					// hide at a certain point
1392					if (curScroll <= hideAt) {
1393						prevScroll = 0;
1394						removeSticky();
1395					}
1396				}
1397			});
1398			
1399			stickyWrites();
1400		}
1401
1402		/**
1403		 * Check if smart sticky is enabled.
1404		 */
1405		function checkSmart() {
1406			if (head.data('sticky-type') == 'smart') {
1407				isSmart = true;
1408			}
1409			
1410			if (isSmart && nav.length) {
1411				nav.addClass('is-smart');
1412			}
1413		}
1414
1415		/**
1416		 * Setup calculations and DOM targets.
1417		 */
1418		function setup() {
1419
1420			// Reset vars - might be a re-init
1421			stickyIsStatic = false;
1422			
1423			if ($('.admin-bar').length) {
1424				extraTop = $('#wpadminbar').height();
1425			}
1426
1427			stickyBar = head.data('sticky');
1428			if (!stickyBar) {
1429				return;
1430			}
1431
1432			// Auto detect.
1433			if (stickyBar === 'auto') {
1434				const menu = head.find('.navigation-main .menu');
1435				if (menu.length) {
1436					const match = menu.eq(0).closest('.smart-head-row').attr('class')
1437						.match(/smart-head-(top|mid|bot)/);
1438
1439					if (!match || !match[1]) {
1440						return;
1441					}
1442					
1443					stickyBar = match[1];
1444				}
1445			}
1446		
1447			stickyBar = head.find('.smart-head-' + stickyBar);
1448			nav = stickyBar;
1449
1450			if (!stickyBar.length) {
1451				return;
1452			}
1453
1454			if (head.data('sticky-full')) {
1455				stickyBar.addClass('sticky-is-full');
1456			}
1457			
1458			stickyTop = nav.offset().top - extraTop;
1459			hideAt = stickyTop + 1;
1460
1461			const isLast = head.find('.smart-head-row:last-child').is(stickyBar);
1462			
1463			// If not the last row, show late and hide early to prevent jumps for bottom row.
1464			if (!isLast) {
1465				stickyTop = head.offset().top + head.height();
1466				hideAt = stickyTop + 1;
1467				nav.addClass('animate');
1468			}
1469				
1470			checkSmart();
1471
1472			// For smart, always animate.
1473			if (isSmart) {
1474				nav.addClass('animate');
1475			}
1476
1477			// Android fix on addr bar hide
1478			if (isSmart && !stickyIsActive) {
1479				prevScroll = 0;
1480			}
1481		}
1482
1483		/**
1484		 * Init it - called multiple times to test for init based on width.
1485		 */
1486		function initHandler() {
1487
1488			if (hasInitialized) {
1489				return false;
1490			}
1491	
1492			if (
1493				(options.mobile && $(window).width() > 940)
1494				|| (!options.mobile && $(window).width() <= 940)
1495			) {
1496				return;
1497			}
1498	
1499			setup();
1500			if (!nav || !nav.length) {
1501				return;
1502			}
1503	
1504			// Setup sticky handler 
1505			toggleSticky();
1506	
1507			Bunyad.util.onLoad(calcHeadSize);
1508			$(window).on('scroll', toggleSticky);
1509			
1510			// Re-initialize on resize.
1511			$(window).on('resize orientationchange', () => {
1512				removeSticky();
1513				calcHeadSize();
1514				setup();
1515				toggleSticky();
1516			});
1517
1518			hasInitialized = true;
1519
1520			// Hooks.
1521			$(document).on('ts-sticky-bar-remove', removeSticky);
1522		}
1523
1524		function init(header) {
1525			hasInitialized = false;
1526			head = $(header);
1527
1528			if (!head.length) {
1529				return;
1530			}
1531
1532			initHandler();
1533			$(window).on('resize orientationchange', initHandler);
1534		}
1535
1536		init(header);
1537
1538		return {
1539			init,
1540			getSticky: () => stickyBar,
1541		};
1542	};
1543})(jQuery);
1544/**
1545 * Minimal Element in-viewport handler.
1546 */
1547class Bunyad_InView {
1548	
1549	/**
1550	 * @param {NodeList} elements 
1551	 * @param {CallableFunction} callback 
1552	 * @param {Object} options 
1553	 * @param {CallableFunction} fallback
1554	 */
1555	constructor(elements = [], callback, options = {}, fallback) {
1556
1557		this.elements = elements;
1558		this.callback = callback;
1559		this.options  = Object.assign({
1560			intersectOnly: true,
1561			observeOptions: {},
1562			once: false
1563		}, options);
1564
1565		if (!this.callback) {
1566			return false;
1567		}
1568
1569		if (!window.IntersectionObserver) {
1570			console.warn('Intersection observer missing.');
1571			fallback();
1572			return false;
1573		}
1574
1575		// eslint-disable-next-line compat/compat
1576		this.observer = new IntersectionObserver(
1577			this.handleIntersection.bind(this), 
1578			this.options.observeOptions
1579		);
1580
1581		elements.forEach(element => {
1582			this.observer.observe(element);
1583		});
1584	}
1585
1586	handleIntersection(entries) {
1587
1588		entries.forEach(entry => {
1589			if (this.options.intersectOnly && !entry.isIntersecting) {
1590				return;
1591			}
1592
1593			this.callback.call(this, entry);
1594
1595			if (this.options.once) {
1596				this.observer.unobserve(entry.target);
1597			}
1598		});
1599	}
1600}
1601(function($) {
1602
1603	const cache = [];
1604
1605	/**
1606	 * Setup pagination for blocks.
1607	 */
1608	function init() {
1609
1610		// AJAX pagination handlers
1611		$('.main-wrap')
1612			.on('click', '.main-pagination .load-button, .pagination-numbers[data-type=numbers-ajax] a', e => {
1613				const target = e.currentTarget;
1614
1615				if (target.dataset.processing) {
1616					return;
1617				}
1618
1619				target.dataset.processing = true;
1620
1621				ajaxPagination(target, () => {
1622					target.dataset.processing = false;
1623				});
1624
1625				return false;
1626			});
1627
1628		$('.main-pagination[data-type=infinite]').each(function() {
1629			infiniteLoad($(this).get(0));
1630		});
1631	}
1632
1633	/**
1634	 * Infinite load handler.
1635	 * 
1636	 * @param {Element} pageEle Pagination element container.
1637	 * @param {Object} options 
1638	 */
1639	function infiniteLoad(pageEle, options) {
1640		const block = pageEle.closest('.block-wrap');
1641		pageEle._loads = 1;
1642		options = Object.assign({bottomDeduct: 30}, options);
1643
1644		if (!block) {
1645			return;
1646		}
1647
1648		const offset = {top: 0, bottom: 0};
1649		const compute = () => {
1650			const rect    = block.getBoundingClientRect();
1651			offset.top    = rect.top + window.scrollY;
1652			offset.bottom = offset.top + block.clientHeight - window.innerHeight;
1653
1654			// Page element's height shouldn't be counted + extra deduction.
1655			offset.bottom -= pageEle.clientHeight + options.bottomDeduct;
1656		}
1657
1658		compute();
1659		
1660		let isLoading = false;	
1661		const loadOnScroll = (e) => {
1662
1663			if (isLoading || pageEle._loads > 5) {
1664				return;
1665			}
1666
1667			if (window.scrollY > offset.bottom) {
1668				isLoading = true;
1669				pageEle._loads++;
1670
1671				ajaxPagination(pageEle.querySelector('.load-button'), () => {
1672					compute();
1673					isLoading = false;
1674				});
1675			}
1676		};
1677
1678		$(window).on('scroll', Bunyad.util.throttle(loadOnScroll, 150, false));
1679		$(window).on('resize', Bunyad.util.throttle(compute));
1680	}
1681
1682	function ajaxPagination(ele, callback) {
1683		
1684		ele = $(ele);
1685			
1686		let block    = ele.closest('.block-wrap');
1687		let isBlock = true;
1688		let process  = processLoadMore;
1689		
1690		// Not a block, archives
1691		if (!block.length) {
1692			isBlock = false;
1693			block = ele.closest('.main-content');
1694		}
1695
1696		// AJAX params
1697		const params =  {
1698			action: 'bunyad_block',
1699			block: block.data('block') || {},
1700			paged: (ele.data('page') || 0) + 1
1701		};
1702
1703		// Type of pagination
1704		const type = ele.closest('.main-pagination').data('type');
1705		
1706		switch(type) {
1707		
1708			// Type: Load More
1709			case 'load-more':
1710			case 'infinite':
1711				ele.addClass('loading').find('.tsi').addClass('tsi-spin');
1712				process = processLoadMore;
1713
1714				break;
1715
1716			// Type: Numbered
1717			case 'numbers-ajax':
1718
1719				block.find('.block-content').addClass('loading');
1720				
1721				// Change page number
1722				const permalink = ele.attr('href').match(/\/page\/(\d+)\//);
1723				if (permalink !== null) {
1724					params.paged = permalink[1];
1725				}
1726				else {
1727					// Plain links
1728					const src = ele.attr('href').match(/(\?|&)paged?=(\d+)/);
1729					params.paged = src ? src[2] : 1;
1730				}
1731				
1732				// Set height
1733				block.css('height', block.height());
1734				process = processNumbered;
1735
1736				break;
1737		}
1738
1739		// Process block.
1740		if (isBlock) {
1741			
1742			// Home blocks AJAX
1743			const ajaxUrl = Bunyad.ajaxurl;
1744
1745			const blockId = block.data('id');
1746			const cacheId = `${blockId}-${params.paged}`;
1747
1748			if (!cache[cacheId]) {
1749				$.post(
1750					ajaxUrl,
1751					params,
1752					data => {
1753						requestAnimationFrame(() => {
1754							process(data, block, ele);
1755							cache[cacheId] = data;
1756							!callback || callback();
1757						});
1758					}
1759				);
1760			}
1761			else {
1762				requestAnimationFrame(() => {
1763					process(cache[cacheId], block, ele);
1764					!callback || callback();
1765				});
1766			}
1767		}
1768	}
1769
1770	/**
1771	 * Numbered Ajax callback.
1772	 */
1773	function processNumbered(data, block) {
1774		const blockContent = block.find('.block-content');
1775		
1776		blockContent
1777			.removeClass('fade-in-down-lg')
1778			.html($(data).find('.block-content').html());
1779		
1780		block.css('height', 'auto');
1781		blockContent.addClass('fade-in-down-lg').removeClass('loading');
1782		blockContent.on('animationend', e => blockContent.removeClass('fade-in-down-lg'));
1783
1784		// Scroll to top, temporarily pausing sticky bar.
1785		Bunyad.theme.stickyBarPause = true;
1786		setTimeout(() => { Bunyad.theme.stickyBarPause = false; }, 300);
1787		$('html, body').animate({scrollTop: block.offset().top - 50}, 200);
1788		
1789		$(document).trigger('ts-ajax-pagination');		
1790	}
1791
1792	/**
1793	 * Load More Ajax callback method.
1794	 */
1795	function processLoadMore(data, block, ele) {
1796		
1797		var content = $(data),
1798			posts;
1799
1800		const wrap = block.find('.loop');
1801
1802		posts = content.find('.loop').children().addClass('fade-in-up-lg');
1803		posts.each(function() {
1804			$(this).on('animationend', () => $(this).removeClass('fade-in-up-lg'));
1805		});
1806		
1807		wrap.append(posts);
1808		
1809		// Masonry reload
1810		if (wrap.hasClass('masonry')) {
1811			// posts.removeClass('fade-in-up-lg');
1812			// Bunyad.theme.masonry(true, posts, wrap.find('.posts-wrap'));
1813		}
1814		
1815		$(document).trigger('ts-ajax-pagination');
1816
1817		const pagination = block.find('.main-pagination');
1818		const newPagination = content.find('.main-pagination');
1819
1820		if (newPagination.length) {
1821			pagination.html(newPagination.html());
1822		}
1823		else {
1824			pagination.remove();
1825		}
1826		
1827		ele.removeClass('loading')
1828			.find('.tsi').removeClass('tsi-spin');
1829	}
1830
1831	Bunyad.pagination = init;
1832})(jQuery);
1833
1834/**
1835 * Live Search Handler
1836 */
1837(function($) {
1838	"use strict";
1839	
1840	var cache = {}, timer, element;
1841	
1842	const self = {
1843		
1844		init: function() {
1845			
1846			var search = $('.live-search-query');
1847
1848			if (!search.length) {
1849				return;
1850			}
1851			
1852			// Turn off browser's own auto-complete
1853			$('.live-search-query').attr('autocomplete', 'off');
1854			
1855			// setup the live search on key press
1856			$('.live-search-query').on('keyup focus', function() {
1857				
1858				element = $(this).parent();
1859			
1860				var query = $(this).val(), result;
1861
1862				// clear existing debounce
1863				clearTimeout(timer);
1864				
1865				// minimum of 1 character
1866				if (query.length < 1) {
1867					self.add_result('');
1868					return;
1869				}
1870				
1871				// debounce to prevent excessive ajax queries
1872				timer = setTimeout(function() {
1873					self.process(query);
1874				}, 250);
1875			});
1876			
1877			// setup hide 
1878			$(document).on('click', function(e) {
1879				
1880				var results = $('.live-search-results');
1881				
1882				if (results.is(':visible') && !$(e.target).closest('.search-form').length) {
1883					results.removeClass('fade-in');
1884					results.closest('form').removeClass('has-live-results');
1885				}
1886			});
1887		},
1888		
1889		/**
1890		 * Process the search query
1891		 */
1892		process: function(query) {
1893
1894			// have it in cache?
1895			if (query in cache) {
1896				self.add_result(cache[query]);
1897			}
1898			else {
1899				$.get(Bunyad.ajaxurl, {action: 'bunyad_live_search', 'query': query}, function(data) {
1900					
1901					// add to cache and add results
1902					cache[query] = data;
1903					self.add_result(data);
1904				});
1905			}
1906		},
1907		
1908		/**
1909		 * Add live results to the container
1910		 */
1911		add_result: function(result) {
1912			
1913			if (!element.find('.live-search-results').length) {
1914				element.append($('<div class="live-search-results"></div>'));
1915			}
1916			
1917			var container = element.find('.live-search-results');
1918
1919			if (!result) {
1920				container.removeClass('fade-in');
1921				return;
1922			}
1923			
1924			// add the html result
1925			container.html(result);
1926			
1927			requestAnimationFrame(function() {
1928				container.addClass('fade-in');
1929				container.closest('form').addClass('has-live-results');
1930			});
1931			
1932		}
1933	};
1934
1935	Bunyad.liveSearch = self.init;
1936	
1937})(jQuery);
1938
1939(function($) {
1940	/**
1941	 * Setup sliders.
1942	 */
1943	function init() {
1944
1945		if (!$.fn.slick) {
1946			return;
1947		}
1948
1949		// Setup all sliders
1950		$('.common-slider .slides:not(.loaded), .loop-carousel:not(.loaded), .gallery-slider:not(.loaded)').each(function() {
1951
1952			const slider = $(this);
1953			if (slider.hasClass('loaded')) {
1954				return;
1955			}
1956
1957			slider.one('init', function() {
1958				$(this).addClass('loaded');
1959			});
1960		
1961			// Common setting
1962			var vars = {
1963				rows: 0,
1964				prevArrow: '<a href="#" class="prev-arrow"><i class="tsi tsi-angle-left"></i></a>',
1965				nextArrow: '<a href="#" class="next-arrow"><i class="tsi tsi-angle-right"></i></a>',
1966				autoplay: slider.data('autoplay') ? true : false,
1967				autoplaySpeed: slider.data('speed') || 5000,
1968				fade: slider.data('animation') == 'fade' ? true : false,
1969				rtl: $('html').prop('dir') === 'rtl'
1970			};
1971				
1972			const sliderType = slider.data('slider');
1973
1974			// First image load.
1975			if (vars.autoplay) {
1976
1977				slider.on('init afterChange', function(e, slick) {				
1978					var ele     = $(this),
1979						current = ele.find('[data-slick-index="' + slick.currentSlide + '"]');
1980
1981					var img = current.find('.wp-post-image').first();
1982					if (!img.length) {
1983						return;
1984					}					
1985
1986					var loaded = img.hasClass('lazyloaded') || (img.is('img:not(.lazyload)') && img.prop('complete'));
1987
1988					if (!loaded) {
1989						img.on('lazyloaded load', function(e) {
1990							slick.slickPlay();
1991						});
1992						
1993						slick.slickPause();
1994					}
1995				});
1996			}
1997			
1998			switch (sliderType) {
1999				case 'feat-grid':
2000					setupFeatGrid(slider, vars);
2001					break;
2002					
2003				case 'carousel':
2004					setupCarousel(slider, vars);
2005					break;
2006
2007				case 'gallery':
2008					setupGallery(slider, vars);
2009					break;
2010			}
2011
2012		});
2013
2014		// Disable anchor jump on arrows
2015		$('.common-slider').on('click', '.slick-arrow', function(e) {
2016			e.preventDefault();
2017		});
2018	}
2019
2020	/**
2021	 * For posts carousels.
2022	 */
2023	function setupCarousel(slider, vars) {
2024
2025		const slidesNum = slider.data('slides') || 1;
2026
2027		// If not defined, use columns - 1, min 2, max 4.
2028		const slidesNumMd = slider.data('slides-md') || (
2029			Math.min(4, Math.max(2, slidesNum - 1))
2030		);
2031
2032		const slidesNumSm = slider.data('slides-sm') || 1;
2033
2034		if (slider.data('arrows')) {
2035			// Set correct top for arrows on init.
2036			slider.on('init', (ele) => {
2037				const height = slider.find('.l-post:first-child .media-ratio').outerHeight();
2038				if (height) {
2039					slider[0].style.setProperty('--arrow-top', (height/2) + 'px');
2040				}
2041			});
2042		}
2043
2044		slider.slick($.extend(vars, {
2045			arrows: slider.data('arrows') ? true : false,
2046			infinite: true,
2047			cssEase: 'ease-out',
2048			speed: 400,
2049			dots: slider.data('dots') ? true : false,
2050			dotsClass: 'nav-dots',
2051			adaptiveHeight: true,
2052			slidesToShow: slidesNum,
2053			slidesToScroll: slidesNum, 
2054			responsive: [
2055				{
2056					breakpoint: 940,
2057					settings: {slidesToShow: slidesNumMd, slidesToScroll: slidesNumMd}
2058				},
2059				{
2060					breakpoint: 540,
2061					settings: {slidesToShow: slidesNumSm, slidesToScroll: slidesNumSm}
2062				}
2063			]
2064		}));
2065	}
2066
2067	/**
2068	 * Setup slider for featured grid.
2069	 */
2070	function setupFeatGrid(slider, vars) {
2071
2072		const scrollNum = slider.data('scroll-num') || 1;
2073		let scrollNumMd = slider.data('scroll-num-md');
2074			
2075		if (!scrollNumMd) {
2076			scrollNumMd = Math.min(2, Math.max(1, scrollNum - 1));
2077		}
2078
2079		slider.slick($.extend(vars, {
2080			arrows: true,
2081			infinite: true,
2082			cssEase: 'ease-out',
2083			speed: 500,
2084			slidesToShow: scrollNum,
2085			slidesToScroll: scrollNumMd, 
2086			responsive: [
2087				{
2088					breakpoint: 940,
2089					settings: {slidesToShow: scrollNumMd, slidesToScroll: scrollNumMd}
2090				},
2091				{
2092					breakpoint: 540,
2093					settings: {slidesToShow: 1, slidesToScroll: 1}
2094				}
2095			]
2096		}));
2097	}
2098
2099	/**
2100	 * Setup gallery slider.
2101	 */
2102	function setupGallery(slider, vars) {
2103			
2104		vars = Object.assign(vars, {
2105			infinite: true,
2106			slidesToShow: 1,
2107			slidesToScroll: 1,
2108			adaptiveHeight: true
2109		});
2110		
2111		const init = () => {
2112			slider.slick(vars);
2113		};
2114
2115		// slider.find('img').eq(0).imagesLoaded(init);
2116		init();
2117	}
2118
2119	Bunyad.sliders = init;
2120})(jQuery);
2121
2122// load when ready
2123jQuery(function($) {
2124		
2125	Bunyad.theme.init();
2126	Bunyad.pagination();
2127	Bunyad.sliders();
2128	Bunyad.blocksFilters();
2129
2130	// Setup sticky headers as applicable.
2131	Bunyad.stickyHeaders = {
2132		main: Bunyad.stickyHeader('.smart-head-main', {mobile: false}),
2133		mobile: Bunyad.stickyHeader('.smart-head-mobile', {mobile: true})
2134	};
2135
2136	Bunyad.liveSearch();
2137	Bunyad.authModal();
2138});
2139/**
2140 * Plugins and 3rd Party Libraries
2141 */
2142
2143/*!
2144* FitVids 1.1
2145*
2146* Copyright 2013, Chris Coyier - http://css-tricks.com + Dave Rupert - http://daverupert.com
2147* Credit to Thierry Koblentz - http://www.alistapart.com/articles/creating-intrinsic-ratios-for-video/
2148* Released under the WTFPL license - http://sam.zoy.org/wtfpl/
2149*
2150*/
2151;(function($){$.fn.fitVids=function(options){var settings={customSelector:null,ignore:null};if(!document.getElementById("fit-vids-style")){var head=document.head||document.getElementsByTagName("head")[0];var css=".fluid-width-video-wrapper{width:100%;position:relative;padding:0;}.fluid-width-video-wrapper iframe,.fluid-width-video-wrapper object,.fluid-width-video-wrapper embed {position:absolute;top:0;left:0;width:100%;height:100%;}";var div=document.createElement("div");div.innerHTML='<p>x</p><style id="fit-vids-style">'+css+"</style>";head.appendChild(div.childNodes[1])}if(options){$.extend(settings,options)}return this.each(function(){var selectors=['iframe[src*="player.vimeo.com"]','iframe[src*="youtube.com"]','iframe[src*="youtube-nocookie.com"]','iframe[src*="kickstarter.com"][src*="video.html"]',"object","embed"];if(settings.customSelector){selectors.push(settings.customSelector)}var ignoreList=".fitvidsignore";if(settings.ignore){ignoreList=ignoreList+", "+settings.ignore}var $allVideos=$(this).find(selectors.join(","));$allVideos=$allVideos.not("object object");$allVideos=$allVideos.not(ignoreList);$allVideos.each(function(){var $this=$(this);if($this.parents(ignoreList).length>0){return}if(this.tagName.toLowerCase()==="embed"&&$this.parent("object").length||$this.parent(".fluid-width-video-wrapper").length){return}if((!$this.css("height")&&!$this.css("width"))&&(isNaN($this.attr("height"))||isNaN($this.attr("width")))){$this.attr("height",9);$this.attr("width",16)}var height=(this.tagName.toLowerCase()==="object"||($this.attr("height")&&!isNaN(parseInt($this.attr("height"),10))))?parseInt($this.attr("height"),10):$this.height(),width=!isNaN(parseInt($this.attr("width"),10))?parseInt($this.attr("width"),10):$this.width(),aspectRatio=height/width;if(!$this.attr("id")){var videoID="fitvid"+Math.floor(Math.random()*999999);$this.attr("id",videoID)}$this.wrap('<div class="fluid-width-video-wrapper"></div>').parent(".fluid-width-video-wrapper").css("padding-top",(aspectRatio*100)+"%");$this.removeAttr("height").removeAttr("width")})})}})(window.jQuery||window.Zepto);
2152
2153/**
2154 * Plus/minus polyfill for numbers - used in WooCommerce
2155 * 
2156 * Author Bryce Adams
2157 */
2158jQuery( function( $ ) {
2159
2160	// Quantity buttons
2161	$( 'div.quantity:not(.buttons_added), td.quantity:not(.buttons_added)' )
2162		.addClass( 'buttons_added' )
2163		.append( '<div class="vertical-buttons"><input type="button" value="+" class="plus" /><input type="button" value="-" class="minus" /></div>' );
2164
2165	$( document ).on( 'click', '.plus, .minus', function() {
2166
2167		// Get values
2168		var $qty		= $( this ).closest( '.quantity' ).find( '.qty' ),
2169			currentVal	= parseFloat( $qty.val() ),
2170			max			= parseFloat( $qty.attr( 'max' ) ),
2171			min			= parseFloat( $qty.attr( 'min' ) ),
2172			step		= $qty.attr( 'step' );
2173
2174		// Format values
2175		if ( ! currentVal || currentVal === '' || currentVal === 'NaN' ) currentVal = 0;
2176		if ( max === '' || max === 'NaN' ) max = '';
2177		if ( min === '' || min === 'NaN' ) min = 0;
2178		if ( step === 'any' || step === '' || step === undefined || parseFloat( step ) === 'NaN' ) step = 1;
2179
2180		// Change the value
2181		if ( $( this ).is( '.plus' ) ) {
2182
2183			if ( max && ( max == currentVal || currentVal > max ) ) {
2184				$qty.val( max );
2185			} else {
2186				$qty.val( currentVal + parseFloat( step ) );
2187			}
2188
2189		} else {
2190
2191			if ( min && ( min == currentVal || currentVal < min ) ) {
2192				$qty.val( min );
2193			} else if ( currentVal > 0 ) {
2194				$qty.val( currentVal - parseFloat( step ) );
2195			}
2196
2197		}
2198
2199		// Trigger change event
2200		$qty.trigger( 'change' );
2201
2202	});
2203
2204});

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.