PageSourceSearch

https://www.agrofilm.sk/templates/charifund/js/main.js

js agrofilm.sk collected 2026-09-24 22:45:42 UTC 21,057 bytes, 749 lines download raw bytes

1/**
2 * @package Helix Ultimate Framework
3 * @author JoomShaper https://www.joomshaper.com
4 * @copyright Copyright (c) 2010 - 2023 JoomShaper
5 * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPLv2 or Later
6 */
7
8// Preloader
9jQuery(window).on('load', function () {
10	if (jQuery('.sp-loader-with-logo').length > 0) {
11
12		move();
13	}
14	jQuery('.sp-pre-loader').fadeOut(500, function () {
15		jQuery(this).remove();
16	});
17});
18
19/**
20 * Move the progress bar
21 */
22function move() {
23	var elem = document.getElementById('line-load');
24	var width = 1;
25	var id = setInterval(frame, 10);
26	function frame() {
27		if (width >= 100) {
28			clearInterval(id);
29		} else {
30			width++;
31			elem.style.width = width + '%';
32		}
33	}
34
35}
36
37jQuery(function ($) {
38
39	/**
40	 * Helix settings data
41	 *
42	 */
43	var settings = Joomla.getOptions('data') || {};
44
45	/**
46	 * sticky header
47	 *
48	 * @param {string} className the header className
49	 */
50	var handleStickiness = function (className, offsetTop) {
51		if ($('body:not(.layout-edit-iframe)').hasClass(className)) {
52			var $header = $('#sp-header');
53			var headerHeight = $header.outerHeight();
54			var $stickyHeaderPlaceholder = $('.sticky-header-placeholder');
55			let $stickyOffset = '100';
56
57			if (settings.header !== undefined && settings.header.stickyOffset !== undefined) {
58				$stickyOffset = settings.header.stickyOffset || '100';
59			}
60
61			var stickyHeader = function () {
62				var scrollTop = $(window).scrollTop();
63				if (scrollTop >= offsetTop + Number($stickyOffset)) {
64					$header.addClass('header-sticky');
65					$stickyHeaderPlaceholder.height(headerHeight);
66				} else {
67					if ($header.hasClass('header-sticky')) {
68						$header.removeClass('header-sticky');
69						$stickyHeaderPlaceholder.height('inherit');
70					}
71				}
72			};
73
74			stickyHeader();
75			$(window).scroll(function () {
76				stickyHeader();
77			});
78
79			if ($('body').hasClass('layout-boxed')) {
80				var windowWidth = $header.parent().outerWidth();
81				$header.css({ 'max-width': windowWidth, left: 'auto' });
82			}
83		} else {
84			var $header = $('#sp-header');
85			if ($header.hasClass('header-sticky')) {
86				$header.removeClass('header-sticky');
87			}
88			$(window).off('scroll');
89		}
90	};
91
92	/**
93	 * Calculate the header offset based on the
94	 * backend preview iframe site and real site.
95	 *
96	 * @return  integer The offset value
97	 */
98	function getHeaderOffset() {
99		/**
100		 * Real site header offset top
101		 *
102		 */
103		let $header = $('#sp-header');
104		let stickyHeaderTop = $header.offset().top;
105
106		/**
107		 * Backend edit preview iframe header offset top
108		 *
109		 */
110		let $backHeader = $('body.back-panel').find('#sp-header');
111		let backPanelStickyHeaderTop = null;
112
113		/**
114		 * If the class .back-panel exists,
115		 * that means this is from backend preview frame,
116		 * then get the offset top, as it varies with the original one.
117		 *
118		 */
119		if ($backHeader.length > 0) {
120			backPanelStickyHeaderTop = $backHeader.offset().top;
121		}
122
123		// By Default the header offset is the original header top
124		let headerOffset = stickyHeaderTop;
125
126		/**
127		 * If back panel sticky header top has value rather than null
128		 * that means the device type is changes from desktop to table or mobile or vice-versa.
129		 * If value found then subtract the settings topbar height from the offset top.
130		 *
131		 */
132		if (backPanelStickyHeaderTop !== null) {
133			headerOffset = backPanelStickyHeaderTop - settings.topbarHeight;
134			headerOffset = headerOffset < 0 ? stickyHeaderTop : headerOffset;
135		}
136
137		return headerOffset;
138	}
139
140	const headerExist = $('#sp-header');
141	if (headerExist.length > 0) {
142		handleStickiness('sticky-header', getHeaderOffset());
143	}
144
145	// go to top
146	$(window).scroll(function () {
147		if ($(this).scrollTop() > 100) {
148			$('.sp-scroll-up').fadeIn();
149		} else {
150			$('.sp-scroll-up').fadeOut(400);
151		}
152	});
153
154	$('.sp-scroll-up').click(function () {
155		$('html, body').animate(
156			{
157				scrollTop: -60,
158			},
159			600
160		);
161		return false;
162	});
163
164	//mega menu
165	$('.sp-megamenu-wrapper').parent().parent().css('position', 'static').parent().css('position', 'relative');
166	$('.sp-menu-full').each(function () {
167		$(this).parent().addClass('menu-justify');
168	});
169
170
171
172	$('#offcanvas-toggler, .offcanvas-toggler-secondary, .offcanvas-toggler-full').on('click', function (event) {
173		event.preventDefault();
174		openOffcanvas();
175	});
176
177	// Close handlers
178	$('.close-offcanvas, .offcanvas-overlay').on('click', function (event) {
179		event.preventDefault();
180		closeOffcanvas();
181	});
182
183	// Open function
184	function openOffcanvas() {
185		$('.offcanvas-init').addClass('offcanvas-active full-offcanvas');
186		$(document.body).css('overflow', 'hidden');
187
188		// Make offcanvas interactive
189		$('.offcanvas-menu')
190			.removeAttr('inert')
191			.attr('tabindex', '0');
192
193		// Set focus to close button (better for accessibility)
194		setTimeout(() => {
195			$('.close-offcanvas').focus();
196		}, 100);
197
198		// Add keyboard trap
199		$(document).on('keydown.offcanvas', handleOffcanvasKeyboard);
200	}
201
202	// Close function
203	function closeOffcanvas() {
204		$('.offcanvas-init').removeClass('offcanvas-active full-offcanvas');
205		$(document.body).css('overflow', '');
206
207		// Make offcanvas non-interactive
208		$('.offcanvas-menu')
209			.attr('inert', '')
210			.attr('tabindex', '-1');
211
212		// Return focus to the trigger
213		$('#offcanvas-toggler').focus();
214
215		// Remove keyboard trap
216		$(document).off('keydown.offcanvas');
217	}
218
219	// Keyboard trap handler on offcanvas
220	function handleOffcanvasKeyboard(e) {
221		if (!$('.offcanvas-init').hasClass('offcanvas-active')) return;
222
223		const $offcanvas = $('.offcanvas-menu');
224		const focusable = 'a[href], button, input, textarea, select, [tabindex="0"]';
225		const $focusable = $offcanvas.find(focusable).filter(':visible');
226
227		// Escape key closes
228		if (e.key === 'Escape') {
229			e.preventDefault();
230			closeOffcanvas();
231			return;
232		}
233
234		// Tab key containment
235		if (e.key === 'Tab') {
236			const $first = $focusable.first();
237			const $last = $focusable.last();
238
239			if (!$offcanvas[0].contains(document.activeElement)) {
240				e.preventDefault();
241				$first.focus();
242				return;
243			}
244
245			if (e.shiftKey && document.activeElement === $first[0]) {
246				e.preventDefault();
247				$last.focus();
248			} else if (!e.shiftKey && document.activeElement === $last[0]) {
249				e.preventDefault();
250				$first.focus();
251			}
252		}
253	}
254
255	// Prevent focus on inert elements
256	$(document).on('focusin', function (e) {
257		if ($(e.target).closest('[inert]').length) {
258			e.preventDefault();
259			$('#offcanvas-toggler').focus();
260		}
261	});
262
263	// Load inert polyfill if needed
264	if (!('inert' in document.createElement('div'))) {
265		const inertPolyfill = document.createElement('script');
266		inertPolyfill.src = 'https://cdn.jsdelivr.net/npm/[email protected]/inert.min.js';
267		document.head.appendChild(inertPolyfill);
268	}
269
270	// Modal Menu
271	if ($('#modal-menu').length > 0) {
272		let $modalToggler = $('#modal-menu-toggler');
273		let $modalMenu = $('#modal-menu');
274		let $body = $('body');
275
276		$modalToggler.on('click', function (e) {
277			e.preventDefault();
278			$modalMenu.toggleClass('active');
279			$body.toggleClass('modal-menu-active');
280			$(this).toggleClass('active');
281		});
282
283		// modal menu close with escape
284		$(document).keyup(function (e) {
285			if (e.key == 'Escape') {
286				$modalMenu.removeClass('active');
287				$modalToggler.removeClass('active');
288				$body.removeClass('modal-menu-active');
289			}
290		});
291	}
292
293	// Tooltip
294	const tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"], .hasTooltip'));
295	tooltipTriggerList.map(function (tooltipTriggerEl) {
296		return new bootstrap.Tooltip(tooltipTriggerEl, {
297			html: true
298		});
299	});
300
301	// Popover
302	const popoverTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="popover"], .hasPopover'));
303	popoverTriggerList.map(function (popoverTriggerEl) {
304		return new bootstrap.Popover(popoverTriggerEl);
305	});
306
307	// Article Ajax voting
308	$('.article-ratings .rating-star').on('click', function (event) {
309		event.preventDefault();
310		var $parent = $(this).closest('.article-ratings');
311
312		var request = {
313			option: 'com_ajax',
314			template: template,
315			action: 'rating',
316			rating: $(this).data('number'),
317			article_id: $parent.data('id'),
318			format: 'json',
319		};
320
321		$.ajax({
322			type: 'POST',
323			data: request,
324			beforeSend: function () {
325				$parent.find('.fa-spinner').show();
326			},
327			success: function (response) {
328				var data = $.parseJSON(response);
329				$parent.find('.ratings-count').text(data.message);
330				$parent.find('.fa-spinner').hide();
331
332				if (data.status) {
333					$parent.find('.rating-symbol').html(data.ratings);
334				}
335
336				setTimeout(function () {
337					$parent.find('.ratings-count').text('(' + data.rating_count + ')');
338				}, 3000);
339			},
340		});
341	});
342
343	//  Cookie consent
344	$('.sp-cookie-allow').on('click', function (event) {
345		event.preventDefault();
346
347		var date = new Date();
348		date.setTime(date.getTime() + 30 * 24 * 60 * 60 * 1000);
349		var expires = '; expires=' + date.toGMTString();
350		document.cookie = 'spcookie_status=ok' + expires + '; path=/';
351
352		$(this).closest('.sp-cookie-consent').fadeOut();
353	});
354
355	$('.btn-group label:not(.active)').click(function () {
356		var label = $(this);
357		var input = $('#' + label.attr('for'));
358
359		if (!input.prop('checked')) {
360			label.closest('.btn-group').find('label').removeClass('active btn-success btn-danger btn-primary');
361			if (input.val() === '') {
362				label.addClass('active btn-primary');
363			} else if (input.val() == 0) {
364				label.addClass('active btn-danger');
365			} else {
366				label.addClass('active btn-success');
367			}
368			input.prop('checked', true);
369			input.trigger('change');
370		}
371		var parent = $(this).parents('#attrib-helix_ultimate_blog_options');
372		if (parent) {
373			showCategoryItems(parent, input.val());
374		}
375	});
376	$('.btn-group input[checked=checked]').each(function () {
377		if ($(this).val() == '') {
378			$('label[for=' + $(this).attr('id') + ']').addClass('active btn btn-primary');
379		} else if ($(this).val() == 0) {
380			$('label[for=' + $(this).attr('id') + ']').addClass('active btn btn-danger');
381		} else {
382			$('label[for=' + $(this).attr('id') + ']').addClass('active btn btn-success');
383		}
384		var parent = $(this).parents('#attrib-helix_ultimate_blog_options');
385		if (parent) {
386			parent.find('*[data-showon]').each(function () {
387				$(this).hide();
388			});
389		}
390	});
391
392	function showCategoryItems(parent, value) {
393		var controlGroup = parent.find('*[data-showon]');
394
395		controlGroup.each(function () {
396			var data = $(this).attr('data-showon');
397			data = typeof data !== 'undefined' ? JSON.parse(data) : [];
398			if (data.length > 0) {
399				if (typeof data[0].values !== 'undefined' && data[0].values.includes(value)) {
400					$(this).slideDown();
401				} else {
402					$(this).hide();
403				}
404			}
405		});
406	}
407
408	$(window).on('scroll', function () {
409		var scrollBar = $('.sp-reading-progress-bar');
410		if (scrollBar.length > 0) {
411			var s = $(window).scrollTop(),
412				d = $(document).height(),
413				c = $(window).height();
414			var scrollPercent = (s / (d - c)) * 100;
415			const position = scrollBar.data('position');
416			if (position === 'top') {
417				// var sticky = $('.header-sticky');
418				// if( sticky.length > 0 ){
419				//     sticky.css({ top: scrollBar.height() })
420				// }else{
421				//     sticky.css({ top: 0 })
422				// }
423			}
424			scrollBar.css({ width: `${scrollPercent}%` });
425		}
426	});
427
428	// Error Alert close issue fix for Joomla 3
429	var observer = new MutationObserver(function (mutations) {
430		$('#system-message-container .alert .close').attr('data-bs-dismiss', 'alert');
431	});
432	var target = document.querySelector('#system-message-container');
433	observer.observe(target, {
434		attributes: true
435	});
436
437
438});
439
440
441// Handle accessibility on off-canvas dropdown menus
442jQuery(function ($) {
443	const menuSelector = '.menu-deeper.menu-parent';
444	const togglerSelector = '.menu-toggler';
445	const childSelector = '.menu-child';
446
447	// Toggle submenu open/close
448	function toggleSubmenu($item, open = null) {
449		const $submenu = $item.children(childSelector);
450		const isOpen = $item.hasClass('menu-parent-open');
451
452		if (open === null) open = !isOpen;
453
454		if (open) {
455			$item.addClass('menu-parent-open').attr('aria-expanded', 'true');
456			$submenu.slideDown(150);
457		} else {
458			$item.removeClass('menu-parent-open').attr('aria-expanded', 'false');
459			$submenu.slideUp(150);
460		}
461	}
462
463	// Prevent event bubbling from toggler to link
464	$(document).on('click', togglerSelector, function (event) {
465		event.preventDefault();
466		event.stopPropagation();
467		const $item = $(this).closest(menuSelector);
468		const isOpen = $item.hasClass('menu-parent-open');
469		toggleSubmenu($item, !isOpen);
470	});
471
472	// Handle menu link click or Enter/Space key
473	$(document).on('click keydown', `${menuSelector} > a`, function (event) {
474		const isToggleKey = event.type === 'click' || event.key === 'Enter' || event.key === ' ';
475		const isKeyboard = event.key === 'Enter' || event.key === ' ';
476
477		if (isToggleKey) {
478			const $item = $(this).closest(menuSelector);
479			const $submenu = $item.children(childSelector);
480
481			// If submenu exists
482			if ($submenu.length) {
483				// If it's Space key (prevent scrolling), toggle submenu only
484				if (event.key === ' ') {
485					event.preventDefault();
486					toggleSubmenu($item);
487				}
488				// If it's Enter or click — follow link (do not preventDefault)
489				// but also toggle submenu if desired
490				else if (event.key === 'Enter') {
491					toggleSubmenu($item, true);
492
493				} else if (event.type === 'click') {
494					toggleSubmenu($item, true);
495				}
496			}
497		}
498	});
499
500	// Handle arrow key navigation
501	$(document).on('keydown', `${menuSelector} > a`, function (event) {
502		const $currentItem = $(this).closest('li');
503		const $siblings = $currentItem.parent().children('li:visible');
504		const index = $siblings.index($currentItem);
505
506		if (event.key === 'ArrowDown') {
507			event.preventDefault();
508			// If submenu is open, focus first child link
509			const $submenu = $currentItem.children(childSelector);
510			if ($submenu.length && $currentItem.hasClass('menu-parent-open')) {
511				const $firstChildLink = $submenu.children('li:visible').find('a').first();
512				if ($firstChildLink.length) {
513					$firstChildLink.focus();
514					return;
515				}
516			}
517			// Otherwise, move to next sibling
518			$siblings.eq((index + 1) % $siblings.length).find('a').first().focus();
519		} else if (event.key === 'ArrowUp') {
520			event.preventDefault();
521			// Move to previous sibling
522			$siblings.eq((index - 1 + $siblings.length) % $siblings.length).find('a').first().focus();
523		} else if (event.key === 'ArrowRight') {
524			// Open nested submenu if present
525			const $submenu = $currentItem.children(childSelector);
526			if ($submenu.length) {
527				event.preventDefault();
528				toggleSubmenu($currentItem, true);
529				const $firstChildLink = $submenu.children('li:visible').find('a').first();
530				if ($firstChildLink.length) {
531					$firstChildLink.focus();
532				}
533			}
534		} else if (event.key === 'ArrowLeft' || event.key === 'Escape') {
535			event.preventDefault();
536			// Close only the current open dropdown
537			toggleSubmenu($currentItem, false);
538			$currentItem.children('a').first().focus();
539		}
540	});
541
542	// Handle arrow key navigation inside submenu
543	$(document).on('keydown', `${childSelector} > li > a`, function (event) {
544		const $currentItem = $(this).closest('li');
545		const $siblings = $currentItem.parent().children('li:visible');
546		const index = $siblings.index($currentItem);
547
548		if (event.key === 'ArrowDown') {
549			event.preventDefault();
550			$siblings.eq((index + 1) % $siblings.length).find('a').first().focus();
551		} else if (event.key === 'ArrowUp') {
552			event.preventDefault();
553			$siblings.eq((index - 1 + $siblings.length) % $siblings.length).find('a').first().focus();
554		} else if (event.key === 'ArrowRight') {
555			// Open nested submenu if present
556			const $submenu = $currentItem.children(childSelector);
557			if ($submenu.length) {
558				event.preventDefault();
559				toggleSubmenu($currentItem, true);
560				const $firstChildLink = $submenu.children('li:visible').find('a').first();
561				if ($firstChildLink.length) {
562					$firstChildLink.focus();
563				}
564			}
565		} else if (event.key === 'ArrowLeft' || event.key === 'Escape') {
566			event.preventDefault();
567			// Close submenu and focus parent
568			const $parentMenu = $currentItem.parents(menuSelector).first();
569			toggleSubmenu($parentMenu, false);
570			$parentMenu.children('a').first().focus();
571		}
572	});
573
574	// Close all menus when clicking outside
575	$(document).on('click', function (event) {
576		if (!$(event.target).closest('.menu-deeper').length) {
577			$(menuSelector).removeClass('menu-parent-open').attr('aria-expanded', 'false');
578			$(childSelector).slideUp(150);
579		}
580	});
581
582	//mark all menu-parents as aria-haspopup
583	$(menuSelector).attr('aria-haspopup', 'true').attr('aria-expanded', 'false');
584});
585
586// Handle accessibility on megamenu and profile dropdowns
587jQuery(function ($) {
588	const menuSelectors = '.sp-megamenu-parent > li, .sp-profile-wrapper';
589
590	$(menuSelectors).each(function () {
591		const $menuItem = $(this);
592		const $trigger = $menuItem.children('a, button');
593		const $dropdown = $menuItem.children('.sp-dropdown, .sp-profile-dropdown');
594
595		if ($dropdown.length) {
596			setupDropdownEvents($menuItem, $trigger, $dropdown);
597		}
598	});
599
600	bindNestedDropdowns('body');
601
602	function setupDropdownEvents($menuItem, $trigger, $dropdown) {
603		// Show on focus or mouseenter
604		$trigger.on('focus mouseenter', function () {
605			openMenu($menuItem, $dropdown);
606		});
607
608		$menuItem.on('mouseenter', function () {
609			openMenu($menuItem, $dropdown);
610		});
611
612		// Hide on focusout or mouseleave
613		$menuItem.on('mouseleave focusout', function () {
614			setTimeout(function () {
615				if (!$menuItem.find(':focus').length && !$menuItem.is(':hover')) {
616					closeMenu($menuItem, $dropdown);
617				}
618			}, 100);
619		});
620
621		// Keyboard trigger
622		$trigger.on('keydown', function (event) {
623			switch (event.key) {
624				case ' ':
625					event.preventDefault();
626					openMenu($menuItem, $dropdown);
627					break;
628				case 'ArrowDown':
629					event.preventDefault();
630					openMenu($menuItem, $dropdown);
631					focusFirstItem($dropdown);
632					break;
633				case 'Escape':
634					event.preventDefault();
635					closeMenu($menuItem, $dropdown);
636					$trigger.focus();
637					break;
638			}
639		});
640
641		// Prevent click from toggling menu
642		$trigger.on('click', function (event) {
643			if ($dropdown.length) {
644				openMenu($menuItem, $dropdown);
645			}
646		});
647
648	}
649
650	function bindNestedDropdowns(containerSelector) {
651		$(containerSelector).find(' .sp-has-child').each(function () {
652			const $subItem = $(this);
653			const $trigger = $subItem.children('a, button');
654			const $subDropdown = $subItem.children('.sp-dropdown');
655
656			if ($subDropdown.length) {
657				setupDropdownEvents($subItem, $trigger, $subDropdown);
658				bindNestedDropdowns($subDropdown);
659			}
660		});
661	}
662
663	function openMenu($item, $dropdown) {
664		$dropdown.show();
665		// Only force display for .sp-profile-dropdown
666		if ($dropdown.hasClass('sp-profile-dropdown')) {
667			$dropdown.attr('style', 'display: block !important');
668		}
669		bindKeyboardNavigation($dropdown);
670	}
671
672	function closeMenu($item, $dropdown) {
673		$dropdown.hide();
674		// Reset style for .sp-profile-dropdown
675		if ($dropdown.hasClass('sp-profile-dropdown')) {
676			$dropdown.removeAttr('style');
677		}
678	}
679
680	function focusFirstItem($dropdown) {
681		const $focusable = $dropdown.find('a, button').filter(':visible');
682		if ($focusable.length) {
683			$focusable.first().focus();
684		}
685	}
686
687	function bindKeyboardNavigation($dropdown) {
688		const $items = $dropdown.find('a, button').filter(':visible');
689
690		$items.off('keydown').on('keydown', function (event) {
691			const currentIndex = $items.index(this);
692			let newIndex = -1;
693
694			if (event.key === 'ArrowDown') {
695				event.preventDefault();
696				newIndex = (currentIndex + 1) % $items.length;
697			} else if (event.key === 'ArrowUp') {
698				event.preventDefault();
699				newIndex = (currentIndex - 1 + $items.length) % $items.length;
700			} else if (event.key === 'Escape') {
701				event.preventDefault();
702
703				// Reset style for .sp-profile-dropdown
704				if ($dropdown.hasClass('sp-profile-dropdown')) {
705					$dropdown.removeAttr('style');
706				}
707
708				const $currentDropdown = $(this).closest('.sp-dropdown');
709				const $parentItem = $currentDropdown.parent(' .sp-has-child, .sp-megamenu-parent > li');
710
711				// Check if this is the root-level dropdown
712				const isRoot = $parentItem.parent().is('.sp-megamenu-parent, .sp-megamenu-parent > ul, nav');
713
714				if (isRoot) {
715					// Close all menus
716					$(menuSelectors).each(function () {
717						const $item = $(this);
718						closeMenu($item, $item.children('.sp-dropdown'));
719					});
720				} else {
721					// Close only current submenu and focus its trigger
722					const $trigger = $parentItem.children('a, button');
723					closeMenu($parentItem, $currentDropdown);
724					if ($trigger.length) {
725						$trigger.focus();
726					}
727				}
728				return;
729			}
730
731			if (newIndex > -1) {
732				$items.eq(newIndex).focus();
733			}
734		});
735	}
736
737	// Close all menus on outside click
738	$(document).on('click', function (event) {
739		if (!$(event.target).closest(menuSelectors).length) {
740			$(menuSelectors).each(function () {
741				const $item = $(this);
742				closeMenu($item, $item.children('.sp-dropdown'));
743			});
744		}
745	});
746
747});
748
749

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.