mirror of
https://github.com/obsqrbtz/goose-highlighter.git
synced 2026-04-08 20:19:06 +03:00
added pagination to popup
This commit is contained in:
@@ -645,6 +645,72 @@ body {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* Pagination (Words tab) */
|
||||
.pagination-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
padding: 6px 8px;
|
||||
background: var(--section-bg);
|
||||
border: 1px solid var(--input-border);
|
||||
border-radius: 8px;
|
||||
flex-shrink: 0;
|
||||
flex-wrap: wrap;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.pagination-info {
|
||||
font-size: 11px;
|
||||
opacity: 0.8;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.pagination-controls {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.pagination-btn {
|
||||
background: var(--input-bg);
|
||||
border: 1px solid var(--input-border);
|
||||
color: var(--text-color);
|
||||
border-radius: 6px;
|
||||
padding: 3px 5px;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-width: 24px;
|
||||
min-height: 24px;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.pagination-btn:hover:not(:disabled) {
|
||||
background: var(--section-bg);
|
||||
border-color: var(--accent);
|
||||
}
|
||||
|
||||
.pagination-btn:disabled {
|
||||
opacity: 0.4;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.pagination-pages {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 4px;
|
||||
}
|
||||
|
||||
.pagination-pages .page-info {
|
||||
font-size: 11px;
|
||||
opacity: 0.9;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* Word item 3-dot menu dropdown */
|
||||
.word-item-menu-dropdown {
|
||||
display: none;
|
||||
|
||||
@@ -195,6 +195,7 @@
|
||||
|
||||
<!-- Word List -->
|
||||
<div id="wordList" class="word-list-container"></div>
|
||||
<div id="paginationControls" class="pagination-container"></div>
|
||||
|
||||
<!-- Word item 3-dot menu dropdown (positioned by JS) -->
|
||||
<div id="wordItemMenuDropdown" class="word-item-menu-dropdown" role="menu" aria-hidden="true"></div>
|
||||
|
||||
@@ -9,6 +9,9 @@ export class PopupController {
|
||||
private selectedCheckboxes = new Set<number>();
|
||||
private globalHighlightEnabled = true;
|
||||
private wordSearchQuery = '';
|
||||
private currentPage = 1;
|
||||
private pageSize = 100;
|
||||
private totalWords = 0;
|
||||
private matchCaseEnabled = false;
|
||||
private matchWholeEnabled = false;
|
||||
private exceptionsList: string[] = [];
|
||||
@@ -271,6 +274,7 @@ export class PopupController {
|
||||
|
||||
wordSearch.addEventListener('input', (e) => {
|
||||
this.wordSearchQuery = (e.target as HTMLInputElement).value;
|
||||
this.currentPage = 1;
|
||||
this.renderWords();
|
||||
});
|
||||
}
|
||||
@@ -1023,6 +1027,7 @@ export class PopupController {
|
||||
if (!Number.isNaN(index)) {
|
||||
this.selectedCheckboxes.clear();
|
||||
this.currentListIndex = index;
|
||||
this.currentPage = 1;
|
||||
this.renderWords();
|
||||
this.updateListForm();
|
||||
this.renderLists();
|
||||
@@ -1063,14 +1068,25 @@ export class PopupController {
|
||||
filteredWords = list.words.filter(w => w.wordStr.toLowerCase().includes(q));
|
||||
}
|
||||
|
||||
this.totalWords = filteredWords.length;
|
||||
|
||||
if (filteredWords.length === 0) {
|
||||
wordList.innerHTML = '<div class="word-list-empty">No words found</div>';
|
||||
const wordCount = document.getElementById('wordCount');
|
||||
if (wordCount) wordCount.textContent = '0';
|
||||
this.renderPaginationControls();
|
||||
return;
|
||||
}
|
||||
|
||||
wordList.innerHTML = filteredWords.map(w => {
|
||||
const totalPages = Math.ceil(this.totalWords / this.pageSize);
|
||||
if (this.currentPage > totalPages) {
|
||||
this.currentPage = Math.max(1, totalPages);
|
||||
}
|
||||
const startIndex = (this.currentPage - 1) * this.pageSize;
|
||||
const endIndex = Math.min(startIndex + this.pageSize, this.totalWords);
|
||||
const paginatedWords = filteredWords.slice(startIndex, endIndex);
|
||||
|
||||
wordList.innerHTML = paginatedWords.map(w => {
|
||||
const realIndex = list.words.indexOf(w);
|
||||
const isSelected = this.selectedCheckboxes.has(realIndex);
|
||||
return this.createWordItemHTML(w, realIndex, isSelected);
|
||||
@@ -1078,8 +1094,94 @@ export class PopupController {
|
||||
|
||||
const wordCount = document.getElementById('wordCount');
|
||||
if (wordCount) {
|
||||
wordCount.textContent = filteredWords.length.toString();
|
||||
wordCount.textContent = this.totalWords.toString();
|
||||
}
|
||||
|
||||
this.renderPaginationControls();
|
||||
}
|
||||
|
||||
private renderPaginationControls(): void {
|
||||
const paginationContainer = document.getElementById('paginationControls');
|
||||
if (!paginationContainer) return;
|
||||
|
||||
const totalPages = Math.ceil(this.totalWords / this.pageSize);
|
||||
|
||||
if (totalPages <= 1) {
|
||||
paginationContainer.style.display = 'none';
|
||||
return;
|
||||
}
|
||||
|
||||
const startItem = (this.currentPage - 1) * this.pageSize + 1;
|
||||
const endItem = Math.min(this.currentPage * this.pageSize, this.totalWords);
|
||||
|
||||
const showingText = chrome.i18n.getMessage('showing_items')
|
||||
?.replace('{start}', String(startItem))
|
||||
.replace('{end}', String(endItem))
|
||||
.replace('{total}', String(this.totalWords))
|
||||
|| `Showing ${startItem}-${endItem} of ${this.totalWords} words`;
|
||||
|
||||
const pageInfoText = chrome.i18n.getMessage('page_info')
|
||||
?.replace('{current}', String(this.currentPage))
|
||||
.replace('{total}', String(totalPages))
|
||||
|| `Page ${this.currentPage} of ${totalPages}`;
|
||||
|
||||
const firstPageTitle = chrome.i18n.getMessage('first_page') || 'First page';
|
||||
const prevPageTitle = chrome.i18n.getMessage('previous_page') || 'Previous page';
|
||||
const nextPageTitle = chrome.i18n.getMessage('next_page') || 'Next page';
|
||||
const lastPageTitle = chrome.i18n.getMessage('last_page') || 'Last page';
|
||||
|
||||
paginationContainer.style.display = 'flex';
|
||||
paginationContainer.innerHTML = `
|
||||
<div class="pagination-info">
|
||||
${showingText}
|
||||
</div>
|
||||
<div class="pagination-controls">
|
||||
<button class="pagination-btn" id="firstPageBtn" ${this.currentPage === 1 ? 'disabled' : ''} title="${firstPageTitle}">
|
||||
<i class="fa-solid fa-angles-left"></i>
|
||||
</button>
|
||||
<button class="pagination-btn" id="prevPageBtn" ${this.currentPage === 1 ? 'disabled' : ''} title="${prevPageTitle}">
|
||||
<i class="fa-solid fa-angle-left"></i>
|
||||
</button>
|
||||
<div class="pagination-pages">
|
||||
<span class="page-info">${pageInfoText}</span>
|
||||
</div>
|
||||
<button class="pagination-btn" id="nextPageBtn" ${this.currentPage === totalPages ? 'disabled' : ''} title="${nextPageTitle}">
|
||||
<i class="fa-solid fa-angle-right"></i>
|
||||
</button>
|
||||
<button class="pagination-btn" id="lastPageBtn" ${this.currentPage === totalPages ? 'disabled' : ''} title="${lastPageTitle}">
|
||||
<i class="fa-solid fa-angles-right"></i>
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
|
||||
this.setupPaginationEventListeners();
|
||||
}
|
||||
|
||||
private setupPaginationEventListeners(): void {
|
||||
document.getElementById('firstPageBtn')?.addEventListener('click', () => {
|
||||
this.goToPage(1);
|
||||
});
|
||||
|
||||
document.getElementById('prevPageBtn')?.addEventListener('click', () => {
|
||||
this.goToPage(this.currentPage - 1);
|
||||
});
|
||||
|
||||
document.getElementById('nextPageBtn')?.addEventListener('click', () => {
|
||||
this.goToPage(this.currentPage + 1);
|
||||
});
|
||||
|
||||
document.getElementById('lastPageBtn')?.addEventListener('click', () => {
|
||||
const totalPages = Math.ceil(this.totalWords / this.pageSize);
|
||||
this.goToPage(totalPages);
|
||||
});
|
||||
}
|
||||
|
||||
private goToPage(page: number): void {
|
||||
const totalPages = Math.ceil(this.totalWords / this.pageSize);
|
||||
if (page < 1 || page > totalPages) return;
|
||||
|
||||
this.currentPage = page;
|
||||
this.renderWords();
|
||||
}
|
||||
|
||||
private createWordItemHTML(word: HighlightWord, realIndex: number, isSelected: boolean): string {
|
||||
|
||||
Reference in New Issue
Block a user