PageSourceSearch

https://www.gamevgames.com/assets/js/pagination.js?v=1782717952

js gamevgames.com collected 2026-09-24 11:01:02 UTC 9,329 bytes, 210 lines download raw bytes

1/**
2 * 🎮 GameScript - Dynamic Grid Pagination & Infinite Horizontal Slider
3 */
4document.addEventListener('DOMContentLoaded', function() {
5    
6    // ==========================================
7    // 1. DİNAMİK GRID PAGINATION LİMİT AYARI
8    // ==========================================
9    function calculateOptimalGridLimit() {
10        const gamesGrid = document.querySelector('.games-grid');
11        if (!gamesGrid) return 48; // Varsayılan
12
13        // Grid'in kaç sütunlu olduğunu hesapla
14        const gridComputedStyle = window.getComputedStyle(gamesGrid);
15        const gridTemplateColumns = gridComputedStyle.getPropertyValue('grid-template-columns');
16        const columns = gridTemplateColumns.split(' ').length;
17        
18        // Ekran genişliğine göre 4-6 satırlık tam doluluk hedefle
19        let rows = 6;
20        if (window.innerWidth < 480) rows = 6;
21        else if (window.innerWidth < 1024) rows = 5;
22
23        let optimalLimit = columns * rows;
24        if (optimalLimit < 12) optimalLimit = 12;
25        
26        return optimalLimit;
27    }
28
29    // Ekran sütun sayısına göre cookie değerini güncelle (Backend'in okuması için)
30    const optimalLimit = calculateOptimalGridLimit();
31    document.cookie = "grid_per_page=" + optimalLimit + "; path=/; max-age=31536000; SameSite=Lax";
32
33    // "Daha Fazla Yükle" Butonu İşlemleri
34    const loadMoreBtn = document.getElementById('load-more-btn');
35    const gamesGrid = document.querySelector('.standard-grid') || document.querySelector('.games-grid');
36    
37    if (loadMoreBtn && gamesGrid) {
38        loadMoreBtn.addEventListener('click', function() {
39            const btn = this;
40            const nextPage = parseInt(btn.getAttribute('data-page'));
41            const totalPages = parseInt(btn.getAttribute('data-total'));
42            const btnText = btn.querySelector('.btn-text');
43            const btnLoader = btn.querySelector('.btn-loader');
44            
45            const reqUrl = new URL(window.location.href);
46            reqUrl.searchParams.set('page', nextPage);
47            // Limit parametresini URL barına yansıtmadan sadece AJAX isteğinde gönderelim
48            reqUrl.searchParams.set('limit', optimalLimit);
49            
50            btn.disabled = true;
51            if (btnText) btnText.style.opacity = '0';
52            if (btnLoader) btnLoader.style.display = 'inline-block';
53            
54            fetch(reqUrl.toString(), {
55                headers: { 'X-Requested-With': 'XMLHttpRequest' }
56            })
57            .then(response => response.text())
58            .then(html => {
59                const parser = new DOMParser();
60                const doc = parser.parseFromString(html, 'text/html');
61                
62                const gridSelector = doc.querySelector('.standard-grid') ? '.standard-grid' : '.games-grid';
63                const newGames = doc.querySelectorAll(`${gridSelector} .game-card`);
64                
65                if (newGames.length > 0) {
66                    newGames.forEach(game => {
67                        game.style.opacity = '0';
68                        game.style.transform = 'translateY(10px)';
69                        game.style.transition = 'all 0.4s ease';
70                        gamesGrid.appendChild(game);
71                        setTimeout(() => {
72                            game.style.opacity = '1';
73                            game.style.transform = 'translateY(0)';
74                        }, 50);
75                    });
76                    
77                    // URL'den limit ve page parametrelerini temizleyelim (refresh yapıldığında en baştan başlanması için)
78                    const cleanUrl = new URL(window.location.href);
79                    cleanUrl.searchParams.delete('page');
80                    cleanUrl.searchParams.delete('limit');
81                    window.history.replaceState({ page: nextPage }, '', cleanUrl.toString());
82                    
83                    if (nextPage < totalPages) {
84                        btn.setAttribute('data-page', nextPage + 1);
85                        btn.disabled = false;
86                        if (btnText) btnText.style.opacity = '1';
87                        if (btnLoader) btnLoader.style.display = 'none';
88                    } else {
89                        btn.parentElement.remove();
90                    }
91                }
92            })
93            .catch(error => {
94                console.error('Pagination Error:', error);
95                btn.disabled = false;
96                if (btnText) btnText.style.opacity = '1';
97                if (btnLoader) btnLoader.style.display = 'none';
98            });
99        });
100    }
101
102    // ==========================================
103    // 2. DİNAMİK INFINITE CATEGORY LATEST SLIDER
104    // ==========================================
105    const sliderTrack = document.querySelector('.slider-track');
106    const prevBtn = document.querySelector('.slider-nav-btn.prev');
107    const nextBtn = document.querySelector('.slider-nav-btn.next');
108
109    if (sliderTrack) {
110        let isFetching = false;
111        let hasMore = true;
112        let loadedOffset = sliderTrack.querySelectorAll('.slider-card').length;
113        const categorySlug = sliderTrack.getAttribute('data-category');
114
115        // Sağa ve Sola Buton Kontrolleri
116        if (prevBtn && nextBtn) {
117            prevBtn.addEventListener('click', () => {
118                sliderTrack.scrollBy({ left: -400, behavior: 'smooth' });
119            });
120
121            nextBtn.addEventListener('click', () => {
122                sliderTrack.scrollBy({ left: 400, behavior: 'smooth' });
123            });
124        }
125
126        // Sonsuz Kaydırma / Ajax Ek Oyun Yükleme Dinamiği
127        sliderTrack.addEventListener('scroll', function() {
128            // Sağ uca 200px kala yeni veriyi çek
129            const scrollLeft = sliderTrack.scrollLeft;
130            const scrollWidth = sliderTrack.scrollWidth;
131            const clientWidth = sliderTrack.clientWidth;
132
133            if (scrollLeft + clientWidth >= scrollWidth - 200) {
134                fetchMoreSliderGames();
135            }
136        });
137
138        function fetchMoreSliderGames() {
139            if (isFetching || !hasMore) return;
140            isFetching = true;
141
142            const limit = 10;
143            const fetchUrl = `${window.location.origin}/api/category-latest/${categorySlug}?offset=${loadedOffset}&limit=${limit}`;
144
145            fetch(fetchUrl)
146            .then(res => res.json())
147            .then(data => {
148                if (data.success && data.games && data.games.length > 0) {
149                    data.games.forEach(game => {
150                        const wrapper = document.createElement('div');
151                        wrapper.className = 'slider-game-item';
152                        wrapper.style.cssText = 'flex: 0 0 auto; width: 220px; opacity: 0; transform: translateY(10px); transition: all 0.4s ease;';
153
154                        // Badge logic
155                        let badgeHtml = '';
156                        if (game.is_featured) {
157                            badgeHtml = '<span class="game-badge badge-featured">ÖNE ÇIKAN</span>';
158                        } else if (game.is_new) {
159                            badgeHtml = '<span class="game-badge badge-new">YENİ</span>';
160                        } else if (game.is_hot) {
161                            badgeHtml = '<span class="game-badge badge-hot">POPÜLER</span>';
162                        }
163
164                        wrapper.innerHTML = `
165                            <a href="${game.url}" class="game-card glass-card">
166                                <div class="game-card-wrapper">
167                                    <div class="game-thumb">
168                                        <img src="${game.thumbnail}" alt="${escapeHtml(game.title)}" width="240" height="180" class="card-image" loading="lazy">
169                                        <div class="card-overlay">
170                                            <div class="game-hover-info">
171                                                <h4 class="hover-title">${escapeHtml(game.title)}</h4>
172                                            </div>
173                                        </div>
174                                    </div>
175                                    ${badgeHtml}
176                                </div>
177                            </a>
178                        `;
179
180                        sliderTrack.appendChild(wrapper);
181                        loadedOffset++;
182
183                        setTimeout(() => {
184                            wrapper.style.opacity = '1';
185                            wrapper.style.transform = 'translateY(0)';
186                        }, 50);
187                    });
188
189                    hasMore = data.has_more;
190                } else {
191                    hasMore = false;
192                }
193                isFetching = false;
194            })
195            .catch(err => {
196                console.error('Error fetching slider games:', err);
197                isFetching = false;
198            });
199        }
200
201        function escapeHtml(text) {
202            return text
203                .replace(/&/g, "&amp;")
204                .replace(/</g, "&lt;")
205                .replace(/>/g, "&gt;")
206                .replace(/"/g, "&quot;")
207                .replace(/'/g, "&#039;");
208        }
209    }
210});

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.