PageSourceSearch

https://www.criticalmetalscorp.com/wp-content/themes/critical-metals/js/rotating-glow.js?ver=1790110934

js criticalmetalscorp.com collected 2026-09-25 03:57:24 UTC 6,127 bytes, 195 lines download raw bytes

1/**
2 * Rotating Glow Border Effect
3 * Creates smooth rotating glow borders similar to modern web designs
4 */
5
6(function() {
7    'use strict';
8
9    let animationId = null;
10    const glowElements = [];
11
12    /**
13     * Initialize rotating glow elements
14     */
15    function initRotatingGlow() {
16        // Find all elements that need JS-controlled rotating glow
17        const elements = document.querySelectorAll('.js-rotating-glow');
18        
19        elements.forEach(element => {
20            // Create glow structure if it doesn't exist
21            let glowWrapper = element.querySelector('.glow-wrapper');
22            if (!glowWrapper) {
23                glowWrapper = document.createElement('div');
24                glowWrapper.className = 'glow-wrapper pointer-event-off';
25                
26                const glowItem = document.createElement('div');
27                glowItem.className = 'glow-item-2';
28                
29                glowWrapper.appendChild(glowItem);
30                element.appendChild(glowWrapper);
31                
32                // Wrap existing content
33                const content = Array.from(element.childNodes).filter(node => 
34                    node !== glowWrapper && node.nodeType === Node.ELEMENT_NODE
35                );
36                
37                if (content.length > 0 && !element.querySelector('.js-rotating-glow-content')) {
38                    const contentWrapper = document.createElement('div');
39                    contentWrapper.className = 'js-rotating-glow-content';
40                    
41                    content.forEach(node => {
42                        contentWrapper.appendChild(node);
43                    });
44                    
45                    element.appendChild(contentWrapper);
46                }
47            }
48            
49            // Store element data for animation
50            const glowItem = glowWrapper.querySelector('.glow-item-2');
51            if (glowItem) {
52                glowElements.push({
53                    element: glowItem,
54                    rotation: Math.random() * 360, // Start at random rotation
55                    speed: parseFloat(element.dataset.glowSpeed || '1'), // Rotation speed multiplier
56                    wrapper: glowWrapper
57                });
58            }
59        });
60        
61        // Start animation if we have elements
62        if (glowElements.length > 0) {
63            startAnimation();
64        }
65    }
66
67    /**
68     * Start the animation loop
69     */
70    function startAnimation() {
71        if (animationId) return; // Already running
72        
73        function animate() {
74            glowElements.forEach(item => {
75                // Increment rotation
76                item.rotation += item.speed * 0.8; // Adjust speed here
77                
78                // Keep rotation within 0-360
79                if (item.rotation >= 360) {
80                    item.rotation -= 360;
81                }
82                
83                // Apply transform
84                item.element.style.transform = `translate3d(0px, 0px, 0px) scale3d(1, 1, 1) rotateX(0deg) rotateY(0deg) rotateZ(${item.rotation}deg) skew(0deg, 0deg)`;
85                item.element.style.transformStyle = 'preserve-3d';
86                item.element.style.willChange = 'transform';
87            });
88            
89            animationId = requestAnimationFrame(animate);
90        }
91        
92        animate();
93    }
94
95    /**
96     * Stop the animation
97     */
98    function stopAnimation() {
99        if (animationId) {
100            cancelAnimationFrame(animationId);
101            animationId = null;
102        }
103    }
104
105    /**
106     * Handle visibility change to pause/resume animation
107     */
108    function handleVisibilityChange() {
109        if (document.hidden) {
110            stopAnimation();
111        } else if (glowElements.length > 0) {
112            startAnimation();
113        }
114    }
115
116    /**
117     * Add rotating glow to an element programmatically
118     */
119    function addRotatingGlow(element, options = {}) {
120        if (!element) return;
121        
122        element.classList.add('js-rotating-glow');
123        
124        if (options.speed) {
125            element.dataset.glowSpeed = options.speed;
126        }
127        
128        // Re-initialize to pick up new element
129        initRotatingGlow();
130    }
131
132    /**
133     * Remove rotating glow from an element
134     */
135    function removeRotatingGlow(element) {
136        if (!element) return;
137        
138        element.classList.remove('js-rotating-glow');
139        const glowWrapper = element.querySelector('.glow-wrapper');
140        if (glowWrapper) {
141            glowWrapper.remove();
142        }
143        
144        // Remove from animation array
145        for (let i = glowElements.length - 1; i >= 0; i--) {
146            if (glowElements[i].wrapper.parentElement === element) {
147                glowElements.splice(i, 1);
148            }
149        }
150        
151        // Stop animation if no elements left
152        if (glowElements.length === 0) {
153            stopAnimation();
154        }
155    }
156
157    /**
158     * Initialize when DOM is ready
159     */
160    function init() {
161        if (document.readyState === 'loading') {
162            document.addEventListener('DOMContentLoaded', init);
163            return;
164        }
165        
166        // Initialize all rotating glow elements
167        initRotatingGlow();
168        
169        // Handle visibility changes for performance
170        document.addEventListener('visibilitychange', handleVisibilityChange);
171        
172        // Handle reduced motion preference
173        if (window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
174            stopAnimation();
175        }
176        
177        // Debug info
178        if (window.location.hostname === 'localhost' || window.location.hostname.includes('.local')) {
179            console.log('Rotating Glow initialized:', glowElements.length, 'elements');
180        }
181    }
182
183    // Expose public API
184    window.RotatingGlow = {
185        init: initRotatingGlow,
186        start: startAnimation,
187        stop: stopAnimation,
188        add: addRotatingGlow,
189        remove: removeRotatingGlow
190    };
191
192    // Auto-initialize
193    init();
194
195})();

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.