PageSourceSearch

https://redesurftank.com.br/themes/wc_surf/wc_js/redesign.js?v=1782621374

js redesurftank.com.br collected 2026-10-02 01:18:37 UTC 12,517 bytes, 293 lines download raw bytes

1/**
2 * SurfTank Redesign — Visual Effects & Interactions
3 * Auto-loaded by framework (scans wc_js/)
4 */
5(function () {
6    'use strict';
7
8    // Wait for DOM
9    document.addEventListener('DOMContentLoaded', init);
10
11    function init() {
12        smoothScroll();
13        scrollReveal();
14        tiltCards();
15        buttonEffects();
16        parallaxHero();
17        glowOnHover();
18        animateCounters();
19        navbarShrink();
20        podiumLoader();
21    }
22
23    /* ===== 1. SMOOTH SCROLL ===== */
24    function smoothScroll() {
25        document.documentElement.style.scrollBehavior = 'smooth';
26        // Anchor links smooth scroll with offset for sticky header
27        document.querySelectorAll('a[href^="#"]').forEach(function (a) {
28            a.addEventListener('click', function (e) {
29                var target = document.querySelector(this.getAttribute('href'));
30                if (target) {
31                    e.preventDefault();
32                    var offset = 80; // header height
33                    var top = target.getBoundingClientRect().top + window.pageYOffset - offset;
34                    window.scrollTo({ top: top, behavior: 'smooth' });
35                }
36            });
37        });
38    }
39
40    /* ===== 2. SCROLL REVEAL (fade-in on scroll) ===== */
41    function scrollReveal() {
42        // Only animate small, repeatable elements — NOT large content containers
43        var reveals = document.querySelectorAll(
44            '.st-feature-card, .st-download-btn, ' +
45            '.st-section-title, .st-section-sub'
46        );
47
48        if (!reveals.length) return;
49
50        reveals.forEach(function (el) {
51            el.style.opacity = '0';
52            el.style.transform = 'translateY(24px)';
53            el.style.transition = 'opacity 0.5s ease, transform 0.5s ease';
54        });
55
56        var observer = new IntersectionObserver(function (entries) {
57            entries.forEach(function (entry) {
58                if (entry.isIntersecting) {
59                    var delay = entry.target.dataset.delay || 0;
60                    setTimeout(function () {
61                        entry.target.style.opacity = '1';
62                        entry.target.style.transform = 'translateY(0)';
63                    }, delay);
64                    observer.unobserve(entry.target);
65                }
66            });
67        }, { threshold: 0.05, rootMargin: '0px 0px -30px 0px' });
68
69        // Stagger delays for sibling groups
70        var groups = {};
71        reveals.forEach(function (el) {
72            var parent = el.parentElement;
73            var key = parent ? (parent.className || 'root') : 'root';
74            if (!groups[key]) groups[key] = [];
75            groups[key].push(el);
76        });
77        Object.values(groups).forEach(function (group) {
78            group.forEach(function (el, i) {
79                el.dataset.delay = i * 120;
80            });
81        });
82
83        reveals.forEach(function (el) { observer.observe(el); });
84    }
85
86    /* ===== 3. TILT 3D EFFECT ON CARDS ===== */
87    function tiltCards() {
88        var cards = document.querySelectorAll('.server-card-inner, .st-feature-card, .st-download-btn');
89        cards.forEach(function (card) {
90            card.addEventListener('mousemove', function (e) {
91                var rect = card.getBoundingClientRect();
92                var x = e.clientX - rect.left;
93                var y = e.clientY - rect.top;
94                var centerX = rect.width / 2;
95                var centerY = rect.height / 2;
96                var rotateX = ((y - centerY) / centerY) * -6;
97                var rotateY = ((x - centerX) / centerX) * 6;
98                card.style.transform = 'perspective(600px) rotateX(' + rotateX + 'deg) rotateY(' + rotateY + 'deg) scale(1.02)';
99            });
100            card.addEventListener('mouseleave', function () {
101                card.style.transform = 'perspective(600px) rotateX(0) rotateY(0) scale(1)';
102            });
103        });
104    }
105
106    /* ===== 4. BUTTON SHINE EFFECT ===== */
107    function buttonEffects() {
108        var btns = document.querySelectorAll(
109            '.btn-st-blue, .btn-st-orange, .btn-st-green, .btn-st-purple, ' +
110            '.btn-header-login, .btn-header-register, .btn-header-play, ' +
111            '.st-quick-action, .btn_green, .btn_blue'
112        );
113        btns.forEach(function (btn) {
114            btn.style.position = 'relative';
115            btn.style.overflow = 'hidden';
116            btn.addEventListener('mouseenter', function (e) {
117                var shine = document.createElement('span');
118                shine.className = 'btn-shine';
119                shine.style.cssText =
120                    'position:absolute;top:0;left:-100%;width:100%;height:100%;' +
121                    'background:linear-gradient(90deg,transparent,rgba(255,255,255,0.2),transparent);' +
122                    'animation:btnShine 0.6s ease-out forwards;pointer-events:none;';
123                btn.appendChild(shine);
124                setTimeout(function () { shine.remove(); }, 700);
125            });
126        });
127
128        // Add keyframe
129        if (!document.getElementById('st-btn-shine-style')) {
130            var style = document.createElement('style');
131            style.id = 'st-btn-shine-style';
132            style.textContent = '@keyframes btnShine{0%{left:-100%}100%{left:100%}}';
133            document.head.appendChild(style);
134        }
135    }
136
137    /* ===== 5. PARALLAX ON HERO ===== */
138    function parallaxHero() {
139        var hero = document.querySelector('.st-hero');
140        if (!hero) return;
141        var content = hero.querySelector('.st-hero-content');
142
143        function update() {
144            var scrolled = window.pageYOffset;
145            if (scrolled < window.innerHeight) {
146                hero.style.backgroundPositionY = (scrolled * 0.4) + 'px';
147                if (content) {
148                    content.style.transform = 'translateY(' + (scrolled * 0.15) + 'px)';
149                    content.style.opacity = 1 - (scrolled / (window.innerHeight * 0.8));
150                }
151            }
152        }
153
154        // Aplica o estado inicial (scroll = 0) já na carga, para que a posição do
155        // background coincida com a do parallax. Sem isso a imagem fica no "center"
156        // do CSS e "pula" para o topo no primeiro scroll.
157        update();
158        window.addEventListener('scroll', update);
159    }
160
161    /* ===== 6. GLOW ON HOVER ===== */
162    function glowOnHover() {
163        var glowEls = document.querySelectorAll('.st-quick-action, .server-card-inner, .ann-link');
164        glowEls.forEach(function (el) {
165            el.addEventListener('mousemove', function (e) {
166                var rect = el.getBoundingClientRect();
167                var x = e.clientX - rect.left;
168                var y = e.clientY - rect.top;
169                el.style.setProperty('--glow-x', x + 'px');
170                el.style.setProperty('--glow-y', y + 'px');
171            });
172        });
173
174        // Add glow style
175        if (!document.getElementById('st-glow-style')) {
176            var style = document.createElement('style');
177            style.id = 'st-glow-style';
178            style.textContent =
179                '.st-quick-action:hover,.server-card-inner:hover,.ann-link:hover{' +
180                'background-image:radial-gradient(circle 120px at var(--glow-x,50%) var(--glow-y,50%),rgba(255,255,255,0.08),transparent) !important;}';
181            document.head.appendChild(style);
182        }
183    }
184
185    /* ===== 7. ANIMATED COUNTERS ===== */
186    function animateCounters() {
187        var counters = document.querySelectorAll('[data-counter]');
188        if (!counters.length) return;
189        var observer = new IntersectionObserver(function (entries) {
190            entries.forEach(function (entry) {
191                if (entry.isIntersecting) {
192                    var el = entry.target;
193                    var target = parseInt(el.dataset.counter);
194                    if (isNaN(target)) { observer.unobserve(el); return; }
195                    var start = parseInt((el.textContent || '0').replace(/\D/g, '')) || 0;
196                    observer.unobserve(el);
197                    if (start === target) return; // numero ja renderizado server-side: mantem (sem flash, bom p/ SEO/no-JS)
198                    var duration = target > 1000 ? 2000 : 1500;
199                    var startTime = null;
200                    function step(timestamp) {
201                        if (!startTime) startTime = timestamp;
202                        var progress = Math.min((timestamp - startTime) / duration, 1);
203                        var eased = 1 - Math.pow(1 - progress, 3);
204                        var current = Math.floor(start + eased * (target - start));
205                        el.textContent = target >= 1000 ? current.toLocaleString('pt-BR') : current;
206                        if (progress < 1) requestAnimationFrame(step);
207                    }
208                    requestAnimationFrame(step);
209                }
210            });
211        }, { threshold: 0.5 });
212        counters.forEach(function (c) { observer.observe(c); });
213    }
214
215    /* ===== 8. PODIUM CHARACTER LOADER ===== */
216    function podiumLoader() {
217        if (typeof CharacterPreview === 'undefined') return;
218        var BASE = document.querySelector("link[rel='base']");
219        if (!BASE) return;
220        BASE = BASE.getAttribute('href');
221
222        var loaded = {};
223
224        function loadPodiumSlots(container) {
225            var slots = container.querySelectorAll('.podium-slot');
226            slots.forEach(function (slot) {
227                var dataEl = slot.querySelector('.podium-data');
228                var canvas = slot.querySelector('.podium-canvas');
229                if (!dataEl || !canvas || !canvas.id) return;
230                if (loaded[canvas.id]) return;
231
232                var userid = dataEl.dataset.userid;
233                var server = dataEl.dataset.server;
234                if (!userid || !server) return;
235
236                loaded[canvas.id] = true;
237                var preview = new CharacterPreview(canvas.id);
238
239                var xhr = new XMLHttpRequest();
240                xhr.open('POST', BASE + '/_cdn/widgets/accddtankeiros/users/player.ajax.php');
241                xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
242                xhr.onload = function () {
243                    try {
244                        var resp = JSON.parse(xhr.responseText);
245                        if (resp.success && resp.data && resp.data.style) {
246                            preview.render(resp.data.style, resp.data.sex, resp.data.resourceUrl, resp.data.hide, resp.data.styleSex);
247                        }
248                    } catch (e) {}
249                };
250                xhr.send('userid=' + userid + '&server=' + server);
251            });
252        }
253
254        // Load visible podiums
255        setTimeout(function () {
256            document.querySelectorAll('.podium').forEach(function (p) {
257                var pane = p.closest('.tab-pane');
258                if (!pane || pane.classList.contains('active')) {
259                    loadPodiumSlots(p);
260                }
261            });
262        }, 600);
263
264        // Load on tab change
265        if (window.jQuery) {
266            jQuery(document).on('shown.bs.tab', '[data-toggle="tab"]', function (e) {
267                var target = jQuery(e.target).attr('href');
268                var podium = document.querySelector(target + ' .podium');
269                if (podium) loadPodiumSlots(podium);
270            });
271        }
272    }
273
274    /* ===== 9. NAVBAR SHRINK ON SCROLL ===== */
275    function navbarShrink() {
276        var header = document.querySelector('.header-modern');
277        if (!header) return;
278        window.addEventListener('scroll', function () {
279            if (window.pageYOffset > 50) {
280                header.style.padding = '0';
281                header.style.boxShadow = '0 4px 30px rgba(0,0,0,0.4)';
282                var logo = header.querySelector('.header-logo');
283                if (logo) logo.style.height = '36px';
284            } else {
285                header.style.padding = '';
286                header.style.boxShadow = '';
287                var logo = header.querySelector('.header-logo');
288                if (logo) logo.style.height = '';
289            }
290        });
291    }
292
293})();

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.