Overview
Pokémon Explorer uses a pagination system to display search results in manageable chunks, showing 12 Pokémon per page by default.
Object.assign(this, {
currentPage: 1,
pokemonPerPage: 12,
allPokemon: [],
filteredPokemon: []
});
The default page size is 12 Pokémon, which creates a nice 3x4 or 4x3 grid depending on screen size.
Display Logic
The displayPokemon() method handles pagination:
displayPokemon() {
const { pokemonGrid, noResults } = this.elements;
const startIndex = (this.currentPage - 1) * this.pokemonPerPage;
const pokemonToShow = this.filteredPokemon.slice(startIndex, startIndex + this.pokemonPerPage);
pokemonGrid.style.display = pokemonToShow.length ? 'grid' : 'none';
noResults.style.display = pokemonToShow.length ? 'none' : 'block';
pokemonGrid.innerHTML = '';
pokemonToShow.forEach((pokemon, index) => {
const card = this.createPokemonCard(pokemon);
card.style.animationDelay = `${index * 0.1}s`;
pokemonGrid.appendChild(card);
});
}
Only the Pokémon for the current page are rendered to the DOM, improving performance for large result sets.
The updatePagination() method creates the navigation controls:
updatePagination() {
const { pagination } = this.elements;
const totalPages = Math.ceil(this.filteredPokemon.length / this.pokemonPerPage);
pagination.innerHTML = '';
if (totalPages <= 1) return;
const createBtn = (text, disabled, onClick) => {
const btn = document.createElement('button');
btn.textContent = text;
btn.disabled = disabled;
btn.addEventListener('click', onClick);
return btn;
};
// Previous button
pagination.appendChild(createBtn('← Anterior', this.currentPage === 1, () => {
if (this.currentPage > 1) {
this.currentPage--;
this.displayPokemon();
this.updatePagination();
}
}));
// Page number buttons
const startPage = Math.max(1, this.currentPage - 2);
const endPage = Math.min(totalPages, startPage + 4);
for (let i = startPage; i <= endPage; i++) {
const pageBtn = createBtn(i, false, () => {
this.currentPage = i;
this.displayPokemon();
this.updatePagination();
});
if (i === this.currentPage) {
pageBtn.classList.add('active');
}
pagination.appendChild(pageBtn);
}
// Next button
pagination.appendChild(createBtn('Siguiente →', this.currentPage === totalPages, () => {
if (this.currentPage < totalPages) {
this.currentPage++;
this.displayPokemon();
this.updatePagination();
}
}));
}
Previous/Next Buttons
Navigate to adjacent pages with ← Anterior and Siguiente → buttons
Page Numbers
Jump directly to a specific page by clicking its number
Smart Windowing
Shows up to 5 page numbers at a time, centered on current page
Active State
Current page is highlighted with the ‘active’ class
Auto-Hide
Pagination controls hide when there’s only one page
Disabled States
Previous/Next buttons disable at boundaries
Page Window Calculation
The pagination shows a sliding window of page numbers:
const startPage = Math.max(1, this.currentPage - 2);
const endPage = Math.min(totalPages, startPage + 4);
Calculate Start
Start at current page minus 2, but never below 1
Calculate End
Show 5 pages total (start + 4), but never exceed total pages
Render Buttons
Create buttons for each page in the window
Examples
Small Result Set (1 page)
Total Pokémon: 8
Pages: 1
Controls: [Hidden]
Medium Result Set (3 pages)
Total Pokémon: 30
Pages: 3
Controls: [← Anterior] [1] [2] [3] [Siguiente →]
Large Result Set (15 pages, on page 7)
Total Pokémon: 180
Pages: 15
Current Page: 7
Controls: [← Anterior] [5] [6] [7] [8] [9] [Siguiente →]
The window always tries to show 5 page numbers, centered around the current page.
Page Reset Behavior
The page resets to 1 when:
- New Search: User performs a search
- Filter Applied: Any filter is changed
- Smart Search: Multi-criteria search is executed
// In performNameSearch
this.filteredPokemon = found;
this.currentPage = 1;
this.displayPokemon();
this.updatePagination();
// In applyFilters
this.currentPage = 1;
this.clearError();
this.displayPokemon();
this.updatePagination();
Changing any filter or performing a new search will reset you to page 1.
Only 12 Pokémon cards are rendered at a time, regardless of total results. This keeps DOM size manageable and improves performance.
JavaScript’s slice() method is used to extract the current page’s Pokémon:const startIndex = (this.currentPage - 1) * this.pokemonPerPage;
const pokemonToShow = this.filteredPokemon.slice(startIndex, startIndex + this.pokemonPerPage);
This is an O(n) operation but n is always 12, making it constant time in practice.
Pagination buttons are recreated on each page change. For result sets with hundreds of pages, this could be optimized by maintaining a button pool.
User Experience Features
Visual Feedback
Active page is visually distinct with the ‘active’ class
Disabled States
Previous/Next buttons are disabled at boundaries to prevent invalid navigation
Keyboard Navigation
Buttons can be navigated with Tab and activated with Enter/Space
No Results Handling
When no Pokémon match filters, pagination hides and a “No results” message displays
For the best experience, keep your search criteria specific enough to avoid too many pages. Most users won’t navigate beyond page 3-4.
Integration with Other Features
Pagination works seamlessly with:
- Search: Results are paginated automatically
- Filters: Filtered results update pagination
- Smart Search: Multi-criteria searches respect pagination
- Loading States: Pagination updates after data loads
// Example: Filter application updates pagination
async applyFilters() {
// ... filter logic ...
this.currentPage = 1;
this.displayPokemon();
this.updatePagination();
}