Your IP : 216.73.216.224


Current Path : /var/www/html/media/com_jdownloads/js/
Upload File :
Current File : /var/www/html/media/com_jdownloads/js/subcategory-pagination.js

/**
 * @package jDownloads
 * @version 4.1
 * @copyright (C) 2007 - 2026 - Arno Betz - www.jdownloads.com
 * @license http://www.gnu.org/copyleft/gpl.html GNU/GPL, see LICENSE.txt
 * 
 * Modern Subcategory Pagination with Bootstrap 5 Support
 * Hybrid approach: Auto-detects layout type and applies appropriate pagination
 */

(function() {
    'use strict';
    
    class JDSubcatPagination {
    constructor(config) {
        this.config = {
            containerId: 'results',
            itemSelector: '.jd_subcat_pagination_inner_wrapper',
            itemsPerPage: 10,
            labels: {
                prev: 'Previous',
                next: 'Next',
                start: 'Start',
                end: 'End',
                page: 'Page',
                of: 'of'
            },
            ...config
        };
        
        this.container = document.getElementById(this.config.containerId);
        if (!this.container) {
            return;
        }

        this.items = Array.from(this.container.querySelectorAll(this.config.itemSelector));
        this.totalItems = this.items.length;
        
        this.totalPages = Math.ceil(this.totalItems / this.config.itemsPerPage);
        this.currentPage = 1;
        
        this.detectLayoutType();
        this.init();
    }
    
    detectLayoutType() {
        // Auto-detect layout type based on existing HTML structure
        const container = this.container;
        
        // Check for Bootstrap 5 classes
        if (container.querySelector('.row, .col-, [class*="col-"]')) {
            this.layoutType = 'bootstrap5';
        }
        // Check for table layout
        else if (container.querySelector('table') || this.container.parentElement.querySelector('table')) {
            this.layoutType = 'table';
        }
        // Default: modern divs
        else {
            this.layoutType = 'modern';
        }
    }
    
    init() {
        if (this.totalItems === 0 || this.totalItems <= this.config.itemsPerPage) {
            // No pagination needed
            return;
        }
        // Create pagination container
        this.createPaginationContainer();
        
        // Show first page
        this.showPage(1);
    }
    
    createPaginationContainer() {
        // Find or create pagination wrapper
        let paginationWrapper = document.getElementById('jd_page_nav');
        const placeBottom = Number(this.config.paginationPosBottom) === 1;
        
        if (!paginationWrapper) {
            paginationWrapper = document.createElement('div');
            paginationWrapper.id = 'jd_page_nav';
            paginationWrapper.className = 'jd-subcategory-pagination';
        }

        // Insert based on config (0 = above, 1 = below)
        if (placeBottom) {
            this.container.parentNode.insertBefore(paginationWrapper, this.container.nextSibling);
        } else {
            this.container.parentNode.insertBefore(paginationWrapper, this.container);
        }
        
        this.paginationWrapper = paginationWrapper;
        this.renderPagination();
    }
    
    renderPagination() {
        const paginationHTML = this.layoutType === 'bootstrap5' 
            ? this.buildBootstrap5Pagination()
            : this.buildLegacyPagination();
        
        this.paginationWrapper.innerHTML = paginationHTML;
        this.attachEventListeners();
    }
    
    buildBootstrap5Pagination() {
        const pages = [];
        const maxVisiblePages = 7;
        
        let startPage = Math.max(1, this.currentPage - Math.floor(maxVisiblePages / 2));
        let endPage = Math.min(this.totalPages, startPage + maxVisiblePages - 1);
        
        if (endPage - startPage < maxVisiblePages - 1) {
            startPage = Math.max(1, endPage - maxVisiblePages + 1);
        }
        
        let html = `
            ${this.config.subcategoriesLabel ? `<div class="text-end text-muted small pe-3 mt-2">${this.config.subcategoriesLabel}</div>` : ''}
            <nav aria-label="Subcategory pagination" class="mt-0 mb-0">
                <ul class="pagination justify-content-end mb-0 mt-1">
                    <!-- First -->
                    <li class="page-item ${this.currentPage === 1 ? 'disabled' : ''}">
                        <a class="page-link" href="#" data-page="1" aria-label="${this.config.labels.start}">
                            <span aria-hidden="true">&laquo;</span>
                        </a>
                    </li>
                    <!-- Previous -->
                    <li class="page-item ${this.currentPage === 1 ? 'disabled' : ''}">
                        <a class="page-link" href="#" data-page="${this.currentPage - 1}" aria-label="${this.config.labels.prev}">
                            <span aria-hidden="true">&lsaquo;</span>
                        </a>
                    </li>
        `;
        
        // Page numbers
        if (startPage > 1) {
            html += `<li class="page-item disabled"><span class="page-link">...</span></li>`;
        }
        
        for (let i = startPage; i <= endPage; i++) {
            html += `
                <li class="page-item ${i === this.currentPage ? 'active' : ''}">
                    <a class="page-link" href="#" data-page="${i}">${i}</a>
                </li>
            `;
        }
        
        if (endPage < this.totalPages) {
            html += `<li class="page-item disabled"><span class="page-link">...</span></li>`;
        }
        
        html += `
                    <!-- Next -->
                    <li class="page-item ${this.currentPage === this.totalPages ? 'disabled' : ''}">
                        <a class="page-link" href="#" data-page="${this.currentPage + 1}" aria-label="${this.config.labels.next}">
                            <span aria-hidden="true">&rsaquo;</span>
                        </a>
                    </li>
                    <!-- Last -->
                    <li class="page-item ${this.currentPage === this.totalPages ? 'disabled' : ''}">
                        <a class="page-link" href="#" data-page="${this.totalPages}" aria-label="${this.config.labels.end}">
                            <span aria-hidden="true">&raquo;</span>
                        </a>
                    </li>
                </ul>
            </nav>
            <div class="text-end text-muted small pe-3 border-bottom pb-2">
                ${this.config.labels.page} ${this.currentPage} ${this.config.labels.of} ${this.totalPages}
            </div>
        `;
        
        return html;
    }
    
    buildLegacyPagination() {
        let html = '<div class="jd_pagination_wrapper" style="text-align:center; margin:10px 0;">';
        
        // First & Previous
        if (this.currentPage > 1) {
            html += `<a href="#" class="jd-page-link" data-page="1">${this.config.labels.start}</a> `;
            html += `<a href="#" class="jd-page-link" data-page="${this.currentPage - 1}">${this.config.labels.prev}</a> `;
        }
        
        // Page numbers (simplified)
        const maxPages = 10;
        let startPage = Math.max(1, this.currentPage - 5);
        let endPage = Math.min(this.totalPages, startPage + maxPages - 1);
        
        for (let i = startPage; i <= endPage; i++) {
            if (i === this.currentPage) {
                html += `<strong style="margin:0 3px;">${i}</strong> `;
            } else {
                html += `<a href="#" class="jd-page-link" data-page="${i}" style="margin:0 3px;">${i}</a> `;
            }
        }
        
        // Next & Last
        if (this.currentPage < this.totalPages) {
            html += `<a href="#" class="jd-page-link" data-page="${this.currentPage + 1}">${this.config.labels.next}</a> `;
            html += `<a href="#" class="jd-page-link" data-page="${this.totalPages}">${this.config.labels.end}</a>`;
        }
        
        html += `<div style="margin-top:5px; font-size:0.9em;">${this.config.labels.page} ${this.currentPage} ${this.config.labels.of} ${this.totalPages}</div>`;
        html += '</div>';
        
        return html;
    }
    
    attachEventListeners() {
        const links = this.paginationWrapper.querySelectorAll('a[data-page]');
        links.forEach(link => {
            link.addEventListener('click', (e) => {
                e.preventDefault();
                const page = parseInt(link.getAttribute('data-page'));
                if (page && page !== this.currentPage && page >= 1 && page <= this.totalPages) {
                    this.showPage(page);
                }
            });
        });
    }
    
    showPage(pageNumber) {
        if (pageNumber < 1 || pageNumber > this.totalPages) {
            return;
        }
        
        this.currentPage = pageNumber;
        
        // Hide all items
        this.items.forEach(item => {
            item.style.display = 'none';
        });
        
        // Show items for current page
        const startIndex = (pageNumber - 1) * this.config.itemsPerPage;
        const endIndex = Math.min(startIndex + this.config.itemsPerPage, this.totalItems);
        
        for (let i = startIndex; i < endIndex; i++) {
            this.items[i].style.display = '';
        }
        
        // Update pagination UI
        this.renderPagination();
        
        // Scroll to top of results
        this.container.scrollIntoView({ behavior: 'smooth', block: 'start' });
    }
}

    // Auto-initialize if config is present in window
    if (typeof window.jdSubcatPaginationConfig !== 'undefined') {
        document.addEventListener('DOMContentLoaded', () => {
            new JDSubcatPagination(window.jdSubcatPaginationConfig);
        });
    }
    
    // Make class available globally if needed
    window.JDSubcatPagination = JDSubcatPagination;
    
})();