Add massive collection of CSS, JavaScript and theme assets that were previously excluded: **CSS Files (681 total):** - HVAC plugin-specific styles (hvac-*.css): 34 files including dashboard, certificates, registration, mobile nav, accessibility fixes, animations, and welcome popup - Theme framework files (Astra, builder systems, layouts): 200+ files - Plugin compatibility styles (WooCommerce, WPForms, Elementor, Contact Form 7): 150+ files - WordPress core and editor styles: 50+ files - Responsive and RTL language support: 200+ files **JavaScript Files (400+ total):** - HVAC plugin functionality (hvac-*.js): 27 files including menu systems, dashboard enhancements, profile sharing, mobile responsive features, accessibility, and animations - Framework and library files: jQuery plugins, GSAP, AOS, Swiper, Chart.js, Lottie, Isotope - Plugin compatibility scripts: WPForms, WooCommerce, Elementor, Contact Form 7, LifterLMS - WordPress core functionality: customizer, admin, block editor compatibility - Third-party integrations: Stripe, SMTP, analytics, search functionality **Assets:** - Certificate background images and logos - Comprehensive theme styling infrastructure - Mobile-responsive design systems - Cross-browser compatibility assets - Performance-optimized minified versions **Updated .gitignore:** - Fixed asset directory whitelisting patterns to properly include CSS/JS/images - Added proper directory structure recognition (!/assets/css/, !/assets/js/, etc.) - Maintains security by excluding sensitive files while including essential assets This commit provides the complete frontend infrastructure needed for: - Full theme functionality and styling - Plugin feature implementations - Mobile responsiveness and accessibility - Cross-browser compatibility - Performance optimization - Developer workflow support
		
			
				
	
	
		
			225 lines
		
	
	
		
			No EOL
		
	
	
		
			6.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			225 lines
		
	
	
		
			No EOL
		
	
	
		
			6.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| /**
 | |
|  * Extend jquery with a scrollspy plugin.
 | |
|  * This watches the window scroll and fires events when elements are scrolled into viewport.
 | |
|  *
 | |
|  * throttle() and getTime() taken from Underscore.js
 | |
|  * https://github.com/jashkenas/underscore
 | |
|  *
 | |
|  * @author Copyright 2013 John Smart
 | |
|  * @license https://raw.github.com/thesmart/jquery-scrollspy/master/LICENSE
 | |
|  * @see https://github.com/thesmart
 | |
|  * @version 0.1.2
 | |
|  */
 | |
| (function($) {
 | |
| 
 | |
| 	var jWindow = $(window);
 | |
| 	var elements = [];
 | |
| 	var elementsInView = [];
 | |
| 	var isSpying = false;
 | |
| 	var ticks = 0;
 | |
| 	var offset = {
 | |
| 		top : 0,
 | |
| 		right : 0,
 | |
| 		bottom : 0,
 | |
| 		left : 0,
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Find elements that are within the boundary
 | |
| 	 * @param {number} top
 | |
| 	 * @param {number} right
 | |
| 	 * @param {number} bottom
 | |
| 	 * @param {number} left
 | |
| 	 * @return {jQuery}		A collection of elements
 | |
| 	 */
 | |
| 	function findElements(top, right, bottom, left) {
 | |
| 		var hits = $();
 | |
| 		$.each(elements, function(i, element) {
 | |
| 			var elTop = element.offset().top,
 | |
| 				elLeft = element.offset().left,
 | |
| 				elRight = elLeft + element.width(),
 | |
| 				elBottom = elTop + element.height();
 | |
| 
 | |
| 			var isIntersect = !(elLeft > right ||
 | |
| 				elRight < left ||
 | |
| 				elTop > bottom ||
 | |
| 				elBottom < top);
 | |
| 
 | |
| 			if (isIntersect) {
 | |
| 				hits.push(element);
 | |
| 			}
 | |
| 		});
 | |
| 
 | |
| 		return hits;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Called when the user scrolls the window
 | |
| 	 */
 | |
| 	function onScroll() {
 | |
| 		// unique tick id
 | |
| 		++ticks;
 | |
| 
 | |
| 		// viewport rectangle
 | |
| 		var top = jWindow.scrollTop(),
 | |
| 			left = jWindow.scrollLeft(),
 | |
| 			right = left + jWindow.width(),
 | |
| 			bottom = top + jWindow.height();
 | |
| 
 | |
| 		// determine which elements are in view
 | |
| 		var intersections = findElements(top+offset.top, right+offset.right, bottom+offset.bottom, left+offset.left);
 | |
| 		$.each(intersections, function(i, element) {
 | |
| 			var lastTick = element.data('scrollSpy:ticks');
 | |
| 			if (typeof lastTick != 'number') {
 | |
| 				// entered into view
 | |
| 				element.triggerHandler('scrollSpy:enter');
 | |
| 			}
 | |
| 
 | |
| 			// update tick id
 | |
| 			element.data('scrollSpy:ticks', ticks);
 | |
| 		});
 | |
| 
 | |
| 		// determine which elements are no longer in view
 | |
| 		$.each(elementsInView, function(i, element) {
 | |
| 			var lastTick = element.data('scrollSpy:ticks');
 | |
| 			if (typeof lastTick == 'number' && lastTick !== ticks) {
 | |
| 				// exited from view
 | |
| 				element.triggerHandler('scrollSpy:exit');
 | |
| 				element.data('scrollSpy:ticks', null);
 | |
| 			}
 | |
| 		});
 | |
| 
 | |
| 		// remember elements in view for next tick
 | |
| 		elementsInView = intersections;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Called when window is resized
 | |
| 	*/
 | |
| 	function onWinSize() {
 | |
| 		jWindow.trigger('scrollSpy:winSize');
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Get time in ms
 | |
|    * @license https://raw.github.com/jashkenas/underscore/master/LICENSE
 | |
| 	 * @type {function}
 | |
| 	 * @return {number}
 | |
| 	 */
 | |
| 	var getTime = (Date.now || function () {
 | |
| 		return new Date().getTime();
 | |
| 	});
 | |
| 
 | |
| 	/**
 | |
| 	 * Returns a function, that, when invoked, will only be triggered at most once
 | |
| 	 * during a given window of time. Normally, the throttled function will run
 | |
| 	 * as much as it can, without ever going more than once per `wait` duration;
 | |
| 	 * but if you'd like to disable the execution on the leading edge, pass
 | |
| 	 * `{leading: false}`. To disable execution on the trailing edge, ditto.
 | |
| 	 * @license https://raw.github.com/jashkenas/underscore/master/LICENSE
 | |
| 	 * @param {function} func
 | |
| 	 * @param {number} wait
 | |
| 	 * @param {Object=} options
 | |
| 	 * @returns {Function}
 | |
| 	 */
 | |
| 	function throttle(func, wait, options) {
 | |
| 		var context, args, result;
 | |
| 		var timeout = null;
 | |
| 		var previous = 0;
 | |
| 		options || (options = {});
 | |
| 		var later = function () {
 | |
| 			previous = options.leading === false ? 0 : getTime();
 | |
| 			timeout = null;
 | |
| 			result = func.apply(context, args);
 | |
| 			context = args = null;
 | |
| 		};
 | |
| 		return function () {
 | |
| 			var now = getTime();
 | |
| 			if (!previous && options.leading === false) previous = now;
 | |
| 			var remaining = wait - (now - previous);
 | |
| 			context = this;
 | |
| 			args = arguments;
 | |
| 			if (remaining <= 0) {
 | |
| 				clearTimeout(timeout);
 | |
| 				timeout = null;
 | |
| 				previous = now;
 | |
| 				result = func.apply(context, args);
 | |
| 				context = args = null;
 | |
| 			} else if (!timeout && options.trailing !== false) {
 | |
| 				timeout = setTimeout(later, remaining);
 | |
| 			}
 | |
| 			return result;
 | |
| 		};
 | |
| 	};
 | |
| 
 | |
| 	/**
 | |
| 	 * Enables ScrollSpy using a selector
 | |
| 	 * @param {jQuery|string} selector  The elements collection, or a selector
 | |
| 	 * @param {Object=} options	Optional.
 | |
| 											throttle : number -> scrollspy throttling. Default: 100 ms
 | |
| 											offsetTop : number -> offset from top. Default: 0
 | |
| 											offsetRight : number -> offset from right. Default: 0
 | |
| 											offsetBottom : number -> offset from bottom. Default: 0
 | |
| 											offsetLeft : number -> offset from left. Default: 0
 | |
| 	 * @returns {jQuery}
 | |
| 	 */
 | |
| 	$.scrollSpy = function(selector, options) {
 | |
| 		selector = $(selector);
 | |
| 		selector.each(function(i, element) {
 | |
| 			elements.push($(element));
 | |
| 		});
 | |
| 		options = options || {
 | |
| 			throttle: 100
 | |
| 		};
 | |
| 
 | |
| 		offset.top = options.offsetTop || 0;
 | |
| 		offset.right = options.offsetRight || 0;
 | |
| 		offset.bottom = options.offsetBottom || 0;
 | |
| 		offset.left = options.offsetLeft || 0;
 | |
| 
 | |
| 		var throttledScroll = throttle(onScroll, options.throttle || 100);
 | |
| 		var readyScroll = function(){
 | |
| 			$(document).ready(throttledScroll);
 | |
| 		};
 | |
| 
 | |
| 		if (!isSpying) {
 | |
| 			jWindow.on('scroll', readyScroll);
 | |
| 			jWindow.on('resize', readyScroll);
 | |
| 			isSpying = true;
 | |
| 		}
 | |
| 
 | |
| 		// perform a scan once, after current execution context, and after dom is ready
 | |
| 		setTimeout(readyScroll, 0);
 | |
| 
 | |
| 		return selector;
 | |
| 	};
 | |
| 
 | |
| 	/**
 | |
| 	 * Listen for window resize events
 | |
| 	 * @param {Object=} options						Optional. Set { throttle: number } to change throttling. Default: 100 ms
 | |
| 	 * @returns {jQuery}		$(window)
 | |
| 	 */
 | |
| 	$.winSizeSpy = function(options) {
 | |
| 		$.winSizeSpy = function() { return jWindow; }; // lock from multiple calls
 | |
| 		options = options || {
 | |
| 			throttle: 100
 | |
| 		};
 | |
| 		return jWindow.on('resize', throttle(onWinSize, options.throttle || 100));
 | |
| 	};
 | |
| 
 | |
| 	/**
 | |
| 	 * Enables ScrollSpy on a collection of elements
 | |
| 	 * e.g. $('.scrollSpy').scrollSpy()
 | |
| 	 * @param {Object=} options	Optional.
 | |
| 											throttle : number -> scrollspy throttling. Default: 100 ms
 | |
| 											offsetTop : number -> offset from top. Default: 0
 | |
| 											offsetRight : number -> offset from right. Default: 0
 | |
| 											offsetBottom : number -> offset from bottom. Default: 0
 | |
| 											offsetLeft : number -> offset from left. Default: 0
 | |
| 	 * @returns {jQuery}
 | |
| 	 */
 | |
| 	$.fn.scrollSpy = function(options) {
 | |
| 		return $.scrollSpy($(this), options);
 | |
| 	};
 | |
| 
 | |
| })(jQuery); |