PageSourceSearch

https://support.rometheme.net/wp-content/plugins/eazydocs/assets/js/frontend/docs-single.js?ver=2.14.0

js rometheme.net collected 2026-09-24 19:35:58 UTC 31,813 bytes, 1,036 lines download raw bytes

1(function ($) {
2	'use strict';
3
4	$(document).ready(function () {
5		const applyFadeGradient = () => {
6			/**
7			 * Match Fade gradient Shadow color
8			 * Used it for the fade gradient shadow on the Read More button
9			 * @type {string}
10			 */
11			let bgColor = window
12				.getComputedStyle(document.querySelector('.doc_documentation_area'), null)
13				.getPropertyValue('background-color'),
14				bgColorRGBA = bgColor.replace(')', ', 0)').replace('rgb', 'rgba');
15
16			if (bgColor) {
17				$('.fadeGradient').css(
18					'background',
19					'-webkit-linear-gradient(bottom, ' +
20					bgColor +
21					' 15%, ' +
22					bgColorRGBA +
23					' 100%)'
24				);
25			}
26		}
27
28		// Apply fade gradient initially
29		applyFadeGradient();
30
31		/**
32		 * Watch for body background-color changes and reapply fade gradient
33		 * This handles dark/light mode switches and any other background color changes
34		 */
35		(function () {
36			let lastBgColor = window.getComputedStyle(document.body, null).getPropertyValue('background-color');
37
38			// Create a MutationObserver to watch for changes on the body element
39			const observer = new MutationObserver(function (mutations) {
40				// Get the current background color
41				const currentBgColor = window.getComputedStyle(document.body, null).getPropertyValue('background-color');
42
43				// Only call applyFadeGradient if the background color actually changed
44				if (currentBgColor !== lastBgColor) {
45					lastBgColor = currentBgColor;
46					applyFadeGradient();
47				}
48			});
49
50			// Start observing the body element for attribute and style changes
51			observer.observe(document.body, {
52				attributes: true,        // Watch for attribute changes (like class changes)
53				attributeFilter: ['class', 'style'], // Only watch class and style attributes
54				childList: false,        // Don't watch for child additions/removals
55				subtree: false          // Don't watch descendants
56			});
57		})();
58
59		/**
60		 * Social Share options
61		 * Copy the current page link to clipboard
62		 */
63		if ($('.share-this-doc').length) {
64			$('.share-this-doc').on('click', function (e) {
65				e.preventDefault();
66				let success_message = $(this).data('success-message');
67				let $temp = $('<input>');
68				$('body').append($temp);
69				$temp.val($(location).attr('href')).select();
70				document.execCommand('copy');
71				$temp.remove();
72
73				setTimeout(function () {
74					$('.ezd-link-copied-wrap')
75						.text(success_message)
76						.addClass('copied');
77				}, 500);
78
79				setTimeout(function () {
80					$('.ezd-link-copied-wrap').removeClass('copied');
81				}, 3500);
82			});
83		}
84
85		$('.ezd-link-copied-wrap').click(function () {
86			$(this).removeClass('copied');
87		});
88
89		$.fn.ezd_social_popup = function (
90			e,
91			intWidth,
92			intHeight,
93			strResize,
94			blnResize
95		) {
96			// Prevent default anchor event
97			e.preventDefault();
98
99			// Set values for window
100			intWidth = intWidth || '500';
101			intHeight = intHeight || '400';
102			strResize = blnResize ? 'yes' : 'no';
103
104			// Set title and open popup with focus on it
105			var strTitle =
106				typeof this.attr('title') !== 'undefined'
107					? this.attr('title')
108					: 'Social Share',
109				strParam =
110					'width=' +
111					intWidth +
112					',height=' +
113					intHeight +
114					',resizable=' +
115					strResize,
116				objWindow = window
117					.open(this.attr('href'), strTitle, strParam)
118					.focus();
119		};
120		$('.social-links a:not(:first)').on('click', function (e) {
121			$(this).ezd_social_popup(e);
122		});
123
124		// Add scroll spy attributes to body
125		$('body').attr({
126			// 'data-bs-spy': 'scroll',
127			'data-bs-target': '#eazydocs-toc',
128		});
129
130		// Sanitize URL hash on page load
131		if (window.location.hash) {
132			try {
133				// Decode the percent-encoded hash
134				const decoded = decodeURIComponent(window.location.hash.substring(1));
135				const safe = decoded.normalize('NFD').replace(/[\u0300-\u036f]/g, '').replace(/[^\w\-]/g, '');
136
137				// If sanitized differs, rewrite it before any plugin runs
138				if (safe && safe !== window.location.hash.substring(1)) {
139					// Update the URL fragment instantly (no reload)
140					history.replaceState(null, '', '#' + safe);
141				}
142			} catch (e) {
143				console.warn('Invalid hash encoding:', e);
144			}
145		}
146
147		/**
148		 * Make the Titles clickable with anchor js
149		 * If no selector is provided, it falls back to a default selector of:
150		 * 'h2, h3, h4, h5, h6'
151		*/
152		const ezdHeadingSelector = '.doc-scrollable h2, .doc-scrollable h3, .doc-scrollable h4';
153		function ezdSetupHeadingAnchors() {
154			const $headings = $(ezdHeadingSelector);
155			$headings.each(function () {
156				const text = $(this).text();
157				const clean = text.toLowerCase().normalize('NFD').replace(/[\u0300-\u036f]/g, '').replace(/[^a-z0-9\s\-_\/]/g, '').trim().replace(/\s+/g, '-').replace(/-+/g, '-').replace(/^-+|-+$/g, '');
158				if (clean) {
159					$(this).attr('id', clean);
160				}
161			});
162			$headings.find('.anchorjs-link').remove();
163			anchors.add(ezdHeadingSelector);
164		}
165
166		window.ezd_heading_anchors = ezdSetupHeadingAnchors;
167		ezdSetupHeadingAnchors();
168
169		// Anchor JS scroll — use getElementById so IDs with / or _ don't break jQuery CSS selectors
170		var urlHash = window.location.href.split('#')[1];
171		if (urlHash) {
172			var hashTarget = document.getElementById(decodeURIComponent(urlHash));
173			if (hashTarget) {
174				$('html,body').animate({
175					scrollTop: $(hashTarget).offset().top
176				}, 30);
177			}
178		}
179
180		/**
181		 * Feedback Contact Form Ajax Handler
182		 */
183		$('form#edocs-contact-form').on('submit', function (e) {
184			e.preventDefault();
185			let that = $(this),
186				url = that.attr('action'),
187				type = that.attr('method');
188			let name = $('#name').val();
189			let email = $('#email').val();
190			let subject = $('#subject').val();
191			let doc_id = $('#doc_id').val();
192			let message = $('#massage').val();
193
194			if (nameDisallowedCharacters(name)) {
195				$('.form-name-field').append('<span class="ezd-input-warning-text">Special characters not allowed</span>');
196				$('.ezd-input-warning-text:not(:last)').remove();
197				// remove the error message after 3 seconds
198				setTimeout(function () {
199					$('.ezd-input-warning-text').remove();
200				}, 3000);
201
202			} else if (emailDisallowedCharacters(email)) {
203				$('.form-email-field').append('<span class="ezd-input-warning-text">Invalid email format.</span>');
204				$('.ezd-input-warning-text:not(:last)').remove();
205				// remove the error message after 3 seconds
206				setTimeout(function () {
207					$('.ezd-input-warning-text').remove();
208				}, 3000);
209
210			} else {
211
212				$.ajax({
213					url: eazydocs_local_object.ajaxurl,
214					type: 'post',
215					dataType: 'json',
216					data: {
217						action: 'eazydocs_feedback_email',
218						name: name,
219						email: email,
220						subject: subject,
221						doc_id: doc_id,
222						message: message,
223						security: eazydocs_local_object.nonce,
224					},
225					beforeSend: function () {
226						$('.eazydocs-form-result').html(
227							'<div class="spinner-border spinner-border-sm" role="status">\n' +
228							'<span class="visually-hidden">Loading...</span>\n' +
229							'</div>'
230						);
231					},
232					success: function (response) {
233						if (response.success) {
234							$('.eazydocs-form-result').html(response.data);
235						} else {
236							$('.eazydocs-form-result').html('Something went wrong.');
237						}
238						setTimeout(function () {
239							$('.eazydocs-form-result').html('');
240						}, 3000);
241					},
242
243					error: function () {
244						$('.eazydocs-form-result').html(
245							'Oops! Something wrong, try again!'
246						);
247					},
248				});
249				$('form#edocs-contact-form')[0].reset();
250			}
251
252			// Check for disallowed characters in the name field
253			function nameDisallowedCharacters(str) {
254				// Regular expression to check for disallowed characters
255				var pattern = /[#$%^&*()+={}\[\];:'",<>\/?@]/;
256				return pattern.test(str);
257			}
258
259			// Check for disallowed characters in the email field
260			function emailDisallowedCharacters(email) {
261				// Regular expression to check for disallowed characters
262				var mailPattern = /[#$%^&*()+={}\[\];:'",<>\/?]/;
263				// Check if there is more than one "@" symbol
264				var atSymbolCount = (email.match(/@/g) || []).length;
265				return atSymbolCount !== 1 || mailPattern.test(email);
266			}
267		});
268
269		/**
270		 * Feedback voting Handler
271		 */
272		$(document).on('click', '.vote-link-wrap a.h_btn', function (e) {
273			e.preventDefault();
274			let self = $(this);
275			$.ajax({
276				url: eazydocs_local_object.ajaxurl,
277				method: 'post',
278				data: {
279					action: 'eazydocs_handle_feedback',
280					post_id: self.data('id'),
281					type: self.data('type'),
282					security: eazydocs_local_object.nonce,
283				},
284				beforeSend: function () {
285					$('.eazydocs-feedback-wrap .vote-link-wrap').html(
286						'<div class="spinner-border spinner-border-sm" role="status">\n' +
287						'  <span class="visually-hidden">Loading...</span>\n' +
288						'</div>'
289					);
290				},
291				success: function (response) {
292					$('.eazydocs-feedback-wrap').html(response.data);
293				},
294				error: function () {
295					console.log('Oops! Something wrong, try again!');
296				},
297			});
298		});
299
300		/**
301		 * Expand and collapse the sidebar menu on clicking on the arrow icon
302		 */
303		if ($('.nav-sidebar > li').hasClass('active')) {
304			$('.nav-sidebar > li.active').find('ul').slideDown(700);
305		}
306
307		// Handle click event for all .icon elements inside .nav-sidebar
308		$('.nav-sidebar').on('click', '.doc-link .icon', function (e) {
309			// Prevent default action
310			e.preventDefault();
311
312			// Find the closest parent li element and toggle its active class
313			let parentLi = $(this).closest('li.nav-item');
314			parentLi.toggleClass('active');
315
316			// Toggle the display of the immediate child ul element
317			parentLi.children('ul.dropdown_nav').toggle(300);
318
319			// Hide sibling submenus
320			parentLi.siblings().find('ul.dropdown_nav').hide(300);
321			parentLi.siblings().removeClass('active');
322		});
323
324		/**
325		 * Print doc
326		 *
327		 * Builds a clean, self-contained printout via printThis: sets a proper
328		 * document title (so "Save as PDF" yields a meaningful filename), prepends
329		 * a source header (title + URL + date), shows a busy state on the button,
330		 * and guards against repeat clicks spawning multiple print dialogs.
331		 */
332		let ezdIsPrinting = false;
333
334		// HTML-escape helper to keep injected title/URL safe.
335		function ezdEscapeHtml(value) {
336			return $('<div>').text(value == null ? '' : value).html();
337		}
338
339		$('.pageSideSection .print').on('click', function (e) {
340			e.preventDefault();
341
342			if (ezdIsPrinting) {
343				return;
344			}
345
346			const $btn = $(this);
347			const $content = $(
348				'.doc-middle-content .doc-post-content, body.single-onepage-docs .documentation_info'
349			);
350
351			if (!$content.length) {
352				return;
353			}
354
355			// Prefer the doc heading for the title; fall back to the page title.
356			const docTitle = ($content.find('h1').first().text() || document.title || '').trim();
357			const printDate = new Date().toLocaleDateString(undefined, {
358				year: 'numeric',
359				month: 'long',
360				day: 'numeric',
361			});
362
363			const printHeader =
364				'<div class="ezd-print-header">' +
365				'<span class="ezd-print-header__title">' + ezdEscapeHtml(docTitle) + '</span>' +
366				'<span class="ezd-print-header__meta">' +
367				'<span class="ezd-print-header__url">' + ezdEscapeHtml(window.location.href) + '</span>' +
368				'<span class="ezd-print-header__date">' + ezdEscapeHtml(printDate) + '</span>' +
369				'</span>' +
370				'</div>';
371
372			ezdIsPrinting = true;
373			$btn.addClass('is-printing').attr('aria-busy', 'true');
374
375			function ezdRestorePrintButton() {
376				ezdIsPrinting = false;
377				$btn.removeClass('is-printing').removeAttr('aria-busy');
378			}
379
380			// Append the plugin version so the print stylesheet busts cache on release.
381			const printCssVer = eazydocs_local_object.EZD_VERSION
382				? '?ver=' + encodeURIComponent(eazydocs_local_object.EZD_VERSION)
383				: '';
384
385			$content.printThis({
386				loadCSS: eazydocs_local_object.EZD_STYLES + 'print.css' + printCssVer,
387				pageTitle: docTitle,
388				header: printHeader,
389				afterPrint: ezdRestorePrintButton,
390			});
391
392			// Safety net if afterPrint never fires (e.g. dialog dismissed instantly).
393			setTimeout(ezdRestorePrintButton, 5000);
394		});
395
396		/**
397		 * ============================
398		 * Navbar Show / Hide Script
399		 * ============================
400		 * This script handles dynamic adjustments of the navbar's top margin based on user interactions:
401		 * - Clicking internal page anchor links (.doc_menu and .ezd-note-indicator)
402		 * - Clicking outside the anchor links
403		 * - Scrolling the page
404		 * ============================
405		 */
406
407		// Function to handle navbar margin adjustments
408		function ezdSetNavbarMarginTop(active) {
409			let height = $('.navbar.navbar_fixed').outerHeight(); // Get navbar height
410			let adminBarOffset = $('body').hasClass('admin-bar') ? 32 : 0; // Check for admin bar
411			let marginTop = active ? `-${height}px` : `${adminBarOffset}px`;
412
413			// Apply the appropriate margin and toggle active class
414			$('.navbar.navbar_fixed').toggleClass('doc_menu_active', active).css('margin-top', marginTop);
415		}
416
417		/**
418		 * Handle link click for internal page navigation
419		 * Applies to both .doc_menu and .ezd-note-indicator mean footnote elements.
420		 */
421		function normalize(str) {
422			return str
423				.replace(/–/g, '-')                // EN DASH → dash
424				.normalize('NFD')                  // normalize accents
425				.replace(/[\u0300-\u036f]/g, '')   // remove accents
426				.replace(/[^a-z0-9\s-]/gi, '')     // clean symbols
427				.replace(/\s+/g, ' ')              // normalize spaces
428				.trim()
429				.toLowerCase();
430		}
431
432		/**
433		 * Build a map from normalized heading TEXT → real ID
434		 */
435		const headingTextMap = {};
436		document.querySelectorAll('h1[id], h2[id], h3[id]').forEach(h => {
437			headingTextMap[normalize(h.textContent)] = h.id;
438		});
439
440		/**
441		 * Docs menu click handler
442		 */
443		$('.doc_menu a[href^="#"]:not([href="#"]), .ezd-note-indicator').on('click', function (event) {
444			event.preventDefault();
445			ezdSetNavbarMarginTop(true);
446
447			const linkText = normalize($(this).text());
448
449			// Find matching heading by text
450			const realId = Object.keys(headingTextMap).find(key =>
451				key.includes(linkText) || linkText.includes(key)
452			);
453
454			if (!realId) {
455				// Parent menu or grouping item → do nothing
456				return;
457			}
458
459			const $el = $('#' + CSS.escape(headingTextMap[realId]));
460			if (!$el.length) return;
461
462			$('html, body').stop().animate({
463				scrollTop: $el.offset().top
464			}, 900);
465		});
466
467		/**
468		 * Handle scroll events
469		 * Reset navbar margin when scrolled near the top.
470		 */
471		$(window).on('scroll', function () {
472			if ($(this).scrollTop() <= $('.navbar.navbar_fixed').outerHeight()) {
473				ezdSetNavbarMarginTop(false);
474			}
475		});
476
477		/**
478		 * ============================
479		 * End of Navbar Show / Hide Script
480		 * ============================
481		 */
482
483		// Ensure sidebars are sticky and toggle logic works properly
484		if ($('.doc_documentation_area').length > 0) {
485			var leftOpen = false;
486			var rightOpen = false;
487
488			// Right sidebar toggle
489			$(document).on('click', '#mobile-right-toggle, .doc_rightsidebar.opened .doc_menu a', function (e) {
490				e.preventDefault();
491				e.stopPropagation();
492				if (leftOpen) closeLeftSidebar();
493
494				if (!rightOpen) {
495					$('.doc_documentation_area').addClass('overlay');
496					$('.doc_rightsidebar').addClass('opened').animate({ right: '0px' }, 100);
497					rightOpen = true;
498				} else {
499					closeRightSidebar();
500				}
501			});
502
503			// Left sidebar toggle
504			$(document).on('click', '#mobile-left-toggle', function (e) {
505				e.preventDefault();
506				e.stopPropagation();
507				if (rightOpen) closeRightSidebar();
508
509				if (!leftOpen) {
510					$('.doc_documentation_area').addClass('overlay');
511					$('.left-column .doc_left_sidebarlist')
512						.addClass('opened')
513						.animate({ left: '0px' }, 300);
514					leftOpen = true;
515				} else {
516					closeLeftSidebar();
517				}
518			});
519
520			// Close sidebars when clicking outside
521			$(document).on('click', function (e) {
522				if (
523					!$(e.target).closest('.doc_rightsidebar, .doc_rightsidebar.opened .doc_menu a, .left-column, #mobile-right-toggle, #mobile-left-toggle').length
524				) {
525					if (leftOpen) closeLeftSidebar();
526					if (rightOpen) closeRightSidebar();
527				}
528			});
529
530			function closeLeftSidebar() {
531				var screenWidth = $(window).width(); // Get current window width
532				var animationDistance = (screenWidth < 360) ? '-280px' : '-330px'; // Set distance based on screen width
533
534				$('.doc_documentation_area').removeClass('overlay');
535				$('.left-column .doc_left_sidebarlist')
536					.removeClass('opened')
537					.animate({ left: animationDistance }, 300);
538
539				leftOpen = false;
540			}
541
542			function closeRightSidebar() {
543				$('.doc_documentation_area').removeClass('overlay');
544				$('.doc_rightsidebar').removeClass('opened').animate({ right: '-290px' }, 100);
545				rightOpen = false;
546			}
547		}
548
549		// Mobile menu on the Doc single page
550		$(document).on('click', '.single-docs .mobile_menu_btn', function () {
551			$('body').removeClass('menu-is-closed').addClass('menu-is-opened');
552		});
553
554		$(document).on('click', '.single-docs .close_nav', function (e) {
555			if ($('.side_menu').hasClass('menu-opened')) {
556				$('.side_menu').removeClass('menu-opened');
557				$('body').removeClass('menu-is-opened');
558			} else {
559				$('.side_menu').addClass('menu-opened');
560			}
561		});
562
563		/**
564		 * Filter doc menu items on the left sidebar
565		 **/
566		if ($('#doc_filter').length) {
567			$('#doc_filter').keyup(function () {
568				var value = $(this).val().toLowerCase();
569				$('.nav-sidebar .page_item').each(function () {
570					var lcval = $(this).text().toLowerCase();
571					if (lcval.indexOf(value) > -1) {
572						$(this).show(500);
573					} else {
574						$(this).hide(500);
575					}
576					if (value.length > 0) {
577						$('.left-sidebar-results')
578							.find('li')
579							.addClass('active');
580						$('.left-sidebar-results').find('li > ul').show(500);
581					} else {
582						$('.left-sidebar-results')
583							.find('li')
584							.removeClass('active');
585						$('.left-sidebar-results').find('li > ul').hide(500);
586					}
587				});
588			});
589
590			document
591				.getElementById('doc_filter')
592				.addEventListener('search', function (event) {
593					$('.nav-sidebar .page_item').show(300);
594					$('.left-sidebar-results').find('li').removeClass('active');
595					$('.left-sidebar-results').find('li > ul').hide(500);
596				});
597		}
598
599		/**
600		 * Collapse left sidebar
601		 **/
602		function docLeftSidebarToggle() {
603			let left_column = $('.doc_mobile_menu');
604			let middle_column = $('.doc-middle-content');
605			$(document).on(
606				'click',
607				'.left-sidebar-toggle .left-arrow',
608				function () {
609					$('.doc_mobile_menu').hide(500);
610
611					if (middle_column.hasClass('ezd-xl-col-7')) {
612						$('.doc-middle-content')
613							.removeClass('ezd-xl-col-7')
614							.addClass('ezd-xl-col-10 ezd-col-extended');
615					} else if (middle_column.hasClass('ezd-xl-col-8')) {
616						$('.doc-middle-content')
617							.removeClass('ezd-xl-col-8')
618							.addClass('ezd-xl-col-10');
619					}
620
621					$('.left-sidebar-toggle .left-arrow').hide(500);
622					$('.left-sidebar-toggle .right-arrow').show(500);
623				}
624			);
625
626			$(document).on(
627				'click',
628				'.left-sidebar-toggle .right-arrow',
629				function () {
630					$('.doc_mobile_menu').show(500);
631
632					if (middle_column.hasClass('ezd-xl-col-10')) {
633						$('.doc-middle-content')
634							.removeClass('ezd-xl-col-10 ezd-col-extended')
635							.addClass('ezd-xl-col-7');
636					} else if (middle_column.hasClass('ezd-xl-col-8')) {
637						$('.doc-middle-content')
638							.removeClass('ezd-xl-col-10 ezd-col-extended')
639							.addClass('ezd-xl-col-8');
640					}
641
642					$('.left-sidebar-toggle .left-arrow').show(500);
643					$('.left-sidebar-toggle .right-arrow').hide(500);
644				}
645			);
646		}
647
648		docLeftSidebarToggle();
649
650		//  page scroll
651		function bodyFixed() {
652			let windowWidth = $(window).width();
653			let middle_column = $('.doc-middle-content');
654
655			if ($('#sticky_doc').length) {
656				if (windowWidth > 576) {
657					let tops = $('#sticky_doc');
658					let leftOffset = tops.offset().top;
659
660					$(window).on('scroll', function () {
661						let scroll = $(window).scrollTop();
662						if (scroll >= leftOffset) {
663							tops.addClass('body_fixed');
664						} else {
665							tops.removeClass('body_fixed');
666						}
667					});
668				}
669			}
670		}
671
672		bodyFixed();
673
674		// TOC area
675		function bodyFixed2() {
676			var windowWidth = $(window).width();
677
678			if ($('#sticky_doc2').length) {
679				if (windowWidth > 576) {
680					var tops = $('#sticky_doc2');
681					var topOffset = tops.offset().top;
682					var blogForm = $('.blog_comment_box');
683					var blogFormTop = blogForm.offset().top - 300;
684
685					$(window).on('scroll', function () {
686						var scrolls = $(window).scrollTop();
687						if (scrolls >= topOffset) {
688							tops.addClass('stick');
689						} else {
690							tops.removeClass('stick');
691						}
692					});
693
694					var $hackers = $('#hackers');
695					var hackersPaddingActive = false;
696
697					$('a[href="#hackers"]').click(function () {
698						$hackers.css('padding-top', '100px');
699						hackersPaddingActive = true;
700					});
701
702					$(window).on('scroll', function () {
703						if (!hackersPaddingActive) {
704							return;
705						}
706						var hackersOffset = $hackers.offset().top;
707						var scrolls = $(window).scrollTop();
708						if (scrolls < hackersOffset) {
709							$hackers.css('padding-top', '0px');
710							hackersPaddingActive = false;
711						}
712					});
713				}
714			}
715		}
716
717		bodyFixed2();
718
719		function tocSidebarScrollHeight() {
720			var leftSidebarScrollElement = $('.doc_left_sidebarlist  .ezd-scroll');
721			if (leftSidebarScrollElement.length) {
722				var leftSidebarScrollOffset = leftSidebarScrollElement.position().top;
723				var maxHeightLeftSidebar = `calc(100vh - ${leftSidebarScrollOffset}px)`;
724				leftSidebarScrollElement.css('max-height', maxHeightLeftSidebar);
725			}
726
727			var rightSidebarScrollElement = $('.single-docs .doc_rightsidebar .toc_right');
728			if (rightSidebarScrollElement.length) {
729				var rightSidebarScrollOffset = rightSidebarScrollElement.position().top;
730				var maxHeightRightSidebar = `calc(100vh - ${rightSidebarScrollOffset + 70}px)`;
731				rightSidebarScrollElement.css('max-height', maxHeightRightSidebar);
732			}
733		}
734		tocSidebarScrollHeight();
735
736		/*  Menu Click js  */
737		if ($('.submenu').length) {
738			$('.submenu > .dropdown-toggle').click(function () {
739				var location = $(this).attr('href');
740				window.location.href = location;
741				return false;
742			});
743		}
744
745		/*------------ Cookie functions and color js ------------*/
746		function createCookie(name, value, days) {
747			var expires = '';
748			if (days) {
749				var date = new Date();
750				date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000);
751				expires = '; expires=' + date.toUTCString();
752			}
753			document.cookie = name + '=' + value + expires + '; path=/';
754		}
755
756		function readCookie(name) {
757			var nameEQ = name + '=';
758			var ca = document.cookie.split(';');
759			for (var i = 0; i < ca.length; i++) {
760				var c = ca[i];
761				while (c.charAt(0) == ' ') c = c.substring(1, c.length);
762				if (c.indexOf(nameEQ) == 0)
763					return c.substring(nameEQ.length, c.length);
764			}
765			return null;
766		}
767
768		function eraseCookie(name) {
769			createCookie(name, '', -1);
770		}
771
772		/**
773		 * Dark mode switcher.
774		 *
775		 * The server already paints the correct theme before this runs (the
776		 * `body_dark` class is added server-side from the cookie / admin default,
777		 * and the first-visit "follow system" case is handled by an inline script
778		 * on wp_body_open). So here we only mirror that state onto the toggle UI,
779		 * persist the visitor's choice on change, and — while no explicit choice
780		 * exists and the default is "follow system" — track live OS changes.
781		 * Keeping the body class as the single source of truth removes the old
782		 * flicker and the competing active-state logic.
783		 */
784		if (eazydocs_local_object.ezd_dark_switcher === '1') {
785			var $darkSwitch = $('#ezd_dark_switch');
786
787			function syncDarkUI(isDark) {
788				$darkSwitch.prop('checked', isDark);
789				$('.light-mode').toggleClass('active', !isDark);
790				$('.dark-mode').toggleClass('active', isDark);
791			}
792
793			function setDarkMode(isDark) {
794				$('body').toggleClass('body_dark', isDark);
795				syncDarkUI(isDark);
796			}
797
798			// Reflect whatever the server decided.
799			syncDarkUI($('body').hasClass('body_dark'));
800
801			$darkSwitch.on('change', function () {
802				var isDark = $(this).is(':checked');
803				setDarkMode(isDark);
804				createCookie('body_dark', isDark ? 'true' : 'false', 999);
805			});
806
807			// Live-follow the OS preference until the visitor makes a choice.
808			if (
809				window.matchMedia &&
810				readCookie('body_dark') === null &&
811				eazydocs_local_object.ezd_dark_default === 'system'
812			) {
813				var darkScheme = window.matchMedia('(prefers-color-scheme: dark)');
814				var onSchemeChange = function (e) {
815					if (readCookie('body_dark') !== null) return; // a choice was made meanwhile
816					setDarkMode(e.matches);
817				};
818				if (darkScheme.addEventListener) {
819					darkScheme.addEventListener('change', onSchemeChange);
820				} else if (darkScheme.addListener) {
821					darkScheme.addListener(onSchemeChange);
822				}
823			}
824		}
825
826		// CONTRIBUTOR SEARCH
827		$('#ezd-contributor-search').on('input', function () {
828			let value = $(this).val().toLowerCase();
829
830			if (value === '') {
831				// Show all users when input is cleared
832				$('.users_wrap_item').show();
833			} else {
834				// Filter the users based on input
835				$('.users_wrap_item').filter(function () {
836					$(this).toggle(
837						$(this).text().toLowerCase().indexOf(value) > -1
838					);
839				});
840			}
841		});
842
843		/*
844		* Font size switcher
845		* Check if there are buttons for font size switcher
846		*/
847
848		if ($('#rvfs-controllers button').length) {
849			var $speech = $('#post p, #post ul li:not(.process_tab_shortcode ul li), #post h1, #post h2, #post h3, #post h4, #post h5, #post h6, #post ol li, #post table:not(.basic_table_info,.table-dark), #post table tr td, #post .tab-content');
850			var originalSizes = {};
851
852			// Function to check if cookie exists and apply font size
853			function checkFontSize() {
854				var cookieFontSize = readCookie("fontSize");
855				if (cookieFontSize) {
856					var sizeFactor = parseFloat(cookieFontSize);
857					$speech.each(function () {
858						var tagName = $(this).prop('tagName').toLowerCase();
859						var originalSize = originalSizes[tagName];
860						$(this).css('fontSize', originalSize * sizeFactor + 'px');
861					});
862				}
863			}
864			// Store the original font sizes
865			$speech.each(function () {
866				var tagName = $(this).prop('tagName').toLowerCase();
867				if (!originalSizes[tagName]) {
868					originalSizes[tagName] = parseFloat($(this).css('fontSize'));
869				}
870			});
871
872			// Apply font size when page loads
873			checkFontSize();
874
875			// Event handler for font size buttons
876			$(document).on('click', '#rvfs-controllers button', function () {
877				var sizeFactor;
878				var currentFactor = parseFloat(readCookie("fontSize")) || 1;
879
880				switch (this.id) {
881					case 'switcher-large':
882						sizeFactor = currentFactor * 1.1;
883						break;
884					case 'switcher-small':
885						sizeFactor = currentFactor / 1.1;
886						break;
887					case 'switcher-default':
888						sizeFactor = 1;
889						break;
890					default:
891						sizeFactor = 1;
892				}
893
894				if (sizeFactor === 1) {
895					$speech.each(function () {
896						var tagName = $(this).prop('tagName').toLowerCase();
897						$(this).css('fontSize', originalSizes[tagName] + 'px');
898					});
899					eraseCookie("fontSize");
900				} else {
901					$speech.each(function () {
902						var tagName = $(this).prop('tagName').toLowerCase();
903						var originalSize = originalSizes[tagName];
904						$(this).css('fontSize', originalSize * sizeFactor + 'px');
905					});
906					createCookie("fontSize", sizeFactor, 30);
907				}
908			});
909		}
910
911		/**
912		 * Enables sticky behavior for the sidebar when it reaches the top of the viewport.
913		 * This applies to both the left sidebar and mobile right sidebar in smaller screens.
914		 */
915		function ezd_sidebar_enable_sticky() {
916			// One-page layouts manage sidebar stickiness via CSS (.ezd-sticky-lg-top)
917			// and the off-canvas drawer. The JS `.sticky` toggle below applies
918			// `position: fixed`, which detaches the one-page drawer/aside from its
919			// column — so restrict this to the single-doc layout only.
920			var $stickyElements = $('.left-column .doc_left_sidebarlist, .doc_right_mobile_menu .doc_rightsidebar')
921				.filter(function () {
922					return $(this).closest('.onepage_doc_area').length === 0;
923				}); // Select single-doc sidebar elements
924
925			if ($stickyElements.length === 0) return; // Exit if no target elements found
926
927			var stickyOffset = $stickyElements.offset().top; // Get initial top position
928
929			$(window).on('scroll', function () {
930				var scrollTop = $(window).scrollTop(); // Current scroll position
931
932				if (scrollTop >= stickyOffset) {
933					$stickyElements.addClass('sticky');
934				} else {
935					$stickyElements.removeClass('sticky');
936				}
937			});
938		}
939
940		// Initialize the sticky sidebar function 
941		ezd_sidebar_enable_sticky();
942
943		// Google Login script
944		$(".ezd-google-login-btn").on("click", function (e) {
945			e.preventDefault();
946			var $btn = $(this);
947			var googleUrl = $btn.data("href");
948
949			// Open popup
950			var width = 600;
951			var height = 600;
952			var left = (screen.width / 2) - (width / 2);
953			var top = (screen.height / 2) - (height / 2);
954			var popup = window.open(googleUrl, "GoogleLogin", "width=" + width + ",height=" + height + ",top=" + top + ",left=" + left);
955
956			// Loading feedback
957			var originalText = $btn.find("span").text();
958			$btn.find("span").text("Connecting...");
959			$btn.css("opacity", "0.7");
960
961			// Reset after 10s
962			setTimeout(function () {
963				$btn.find("span").text(originalText);
964				$btn.css("opacity", "1");
965			}, 10000);
966		});
967
968		/**
969		 * EazyDocs Accordion Functionality
970		 * Sync with updated markup: .ezd-doc-attached-files-accordion
971		 * Maintains ARIA states and toggle icons.
972		 */
973		function ezdDocAttachedFile() {
974			const $accordion = $('.ezd-doc-attached-files-accordion');
975
976			// Set initial collapsed state
977			$accordion.find('.accordion__content').addClass('is-collapsed').hide();
978			$accordion.find('.accordion__header').attr('aria-expanded', 'false');
979			$accordion.find('.accordion__toggle i')
980				.removeClass('arrow_carrot-up')
981				.addClass('arrow_carrot-down');
982
983			// Click on header or toggle button
984			$accordion.on('click', '.accordion__header, .accordion__toggle', function (e) {
985				e.preventDefault();
986				const $wrapper = $(this).closest('.ezd-doc-attached-files-accordion');
987				const $content = $wrapper.find('.accordion__content');
988				const $header = $wrapper.find('.accordion__header');
989				const $icon = $wrapper.find('.accordion__toggle i');
990				const expanded = $header.attr('aria-expanded') === 'true';
991
992				if (expanded) {
993					$content.slideUp(250).addClass('is-collapsed');
994					$header.attr('aria-expanded', 'false');
995					$icon.removeClass('arrow_carrot-up').addClass('arrow_carrot-down');
996				} else {
997					$content.slideDown(250).removeClass('is-collapsed');
998					$header.attr('aria-expanded', 'true');
999					$icon.removeClass('arrow_carrot-down').addClass('arrow_carrot-up');
1000				}
1001			});
1002		}
1003		// Initialize accordion functionality
1004		ezdDocAttachedFile();
1005	});
1006})(jQuery);
1007
1008// Listen for messages from the Google login popup window.
1009// Hardened against cross-origin open redirect / javascript: URL injection:
1010// only same-origin senders and same-origin http(s) redirect targets are honored.
1011window.addEventListener("message", function (event) {
1012	// Reject messages from any origin other than this site.
1013	if (event.origin !== window.location.origin) {
1014		return;
1015	}
1016
1017	var data = event.data;
1018	if (!data || data.type !== "google_login_success" || !data.redirect) {
1019		return;
1020	}
1021
1022	// Resolve and validate the redirect target before navigating.
1023	var target;
1024	try {
1025		target = new URL(data.redirect, window.location.origin);
1026	} catch (err) {
1027		return;
1028	}
1029
1030	if (
1031		(target.protocol === "http:" || target.protocol === "https:") &&
1032		target.origin === window.location.origin
1033	) {
1034		window.location.href = target.href;
1035	}
1036});

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.