diff --git a/index.html b/index.html
index d01f9c5..33e2900 100644
--- a/index.html
+++ b/index.html
@@ -47,7 +47,7 @@
padding: 20px;
position: relative;
}
- h1 {
+ h1, h2 {
text-align: center;
}
#pattern {
@@ -154,11 +154,56 @@
border-radius: 4px;
padding: 10px;
opacity: 0;
- transition: opacity 0.3s ease;
+ transition: opacity 0.2s ease;
}
.copy-notification.show {
opacity: 1;
}
+
+ .controls-container {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 10px;
+ }
+ .options, .pagination {
+ display: flex;
+ align-items: center;
+ margin-bottom: 0;
+ }
+ .options label {
+ margin-right: 5px;
+ }
+ .options select {
+ padding: 5px;
+ }
+ .pagination button {
+ margin: 0 5px;
+ padding: 5px 10px;
+ background-color: var(--box-background-color);
+ color: var(--text-color);
+ border: 1px solid var(--box-border-color);
+ border-radius: 4px;
+ cursor: pointer;
+ }
+ .pagination button:disabled {
+ opacity: 0.5;
+ cursor: not-allowed;
+ }
+ .pagination input {
+ width: 50px;
+ text-align: center;
+ padding: 5px;
+ margin: 0 5px;
+ background-color: var(--box-background-color);
+ color: var(--text-color);
+ border: 1px solid var(--box-border-color);
+ border-radius: 4px;
+ }
+ .pagination span {
+ font-size: 14px;
+ }
@@ -177,6 +222,26 @@
Statistics
Possible Patterns
+
+
+
+
+
+
+
+
+
diff --git a/js/resultProcessor.js b/js/resultProcessor.js
index 9cc40d0..2021567 100644
--- a/js/resultProcessor.js
+++ b/js/resultProcessor.js
@@ -5,12 +5,7 @@ export default class ResultProcessor {
let shortestPattern = Infinity;
let totalLength = 0;
const parseTagsSet = new Set();
-
- const MAX_RESULTS = 100; // should this be a configurable option?
- if (results.length > MAX_RESULTS) {
- results = results.slice(0, MAX_RESULTS);
- }
-
+
for (const result of results) {
const length = result.text.length;
totalLength += length;
diff --git a/script.js b/script.js
index dbbf000..58fdad5 100644
--- a/script.js
+++ b/script.js
@@ -5,18 +5,56 @@ import ResultProcessor from './js/resultProcessor.js';
let tooltip;
let copyNotification;
+let allData = null;
+let allResults = [];
+let currentPage = 1;
+let totalPages = 1;
+let resultsPerPage = 100;
+let patternsContent;
+let prevPageButton;
+let nextPageButton;
+let currentPageInput;
+let totalPagesSpan;
+let displayCount;
document.addEventListener('DOMContentLoaded', () => {
const patternInput = document.getElementById('pattern');
+ const themeToggleButton = document.getElementById('theme-toggle');
+ patternsContent = document.getElementById('patternsContent');
+ prevPageButton = document.getElementById('prev-page');
+ nextPageButton = document.getElementById('next-page');
+ currentPageInput = document.getElementById('current-page');
+ totalPagesSpan = document.getElementById('total-pages');
+ displayCount = document.getElementById('display-count');
+
+ displayCount.value = '100';
+
+ // pattern input listener
patternInput.addEventListener('input', debounce(parsePattern, 5));
+ // possible pattern related stuff
tooltip = document.getElementById('tooltip');
-
copyNotification = document.getElementById('copy-notification');
+ // theme stuff
initializeTheme();
- const themeToggleButton = document.getElementById('theme-toggle');
themeToggleButton.addEventListener('click', toggleTheme);
+
+ // pagination listeners
+ prevPageButton.addEventListener('click', () => changePage(currentPage - 1));
+ nextPageButton.addEventListener('click', () => changePage(currentPage + 1));
+ currentPageInput.addEventListener('change', (e) => {
+ let page = parseInt(e.target.value);
+ if (isNaN(page) || page < 1) page = 1;
+ if (page > totalPages) page = totalPages;
+ changePage(page);
+ });
+ displayCount.addEventListener('change', () => {
+ updateResultsPerPage();
+ currentPage = 1;
+ updatePagination();
+ showPage(currentPage);
+ });
});
// this is basically a limit on how often parsePattern should be called
@@ -31,12 +69,12 @@ function debounce(func, delay) {
function parsePattern() {
const pattern = document.getElementById('pattern').value;
const statsContent = document.getElementById('statsContent');
- const patternsContent = document.getElementById('patternsContent');
// no pattern :(
if (!pattern.trim()) {
patternsContent.innerText = 'Enter a pattern to get started.';
statsContent.innerHTML = '';
+ resetPagination();
return;
}
@@ -54,6 +92,7 @@ function parsePattern() {
if (estimatedCombinations > MAX_COMBINATIONS) {
displayError('Too many combinations!');
+ resetPagination();
return;
}
@@ -62,30 +101,72 @@ function parsePattern() {
const processor = new ResultProcessor();
const data = processor.process(variants);
- displayResults(data);
+ // sort by length, looks nicer imo
+ data.results.sort((a, b) => a.text.length - b.text.length);
+
+ allData = data;
+ allResults = data.results;
+ currentPage = 1;
+
+ updateResultsPerPage();
+ updatePagination();
+ displayStatistics();
+ showPage(currentPage);
} catch (error) {
displayError('Invalid syntax pattern!');
+ resetPagination();
}
}
-function displayResults(data) {
+function updateResultsPerPage() {
+ const displayValue = displayCount.value;
+ if (displayValue === 'all') {
+ resultsPerPage = allResults.length;
+ } else {
+ const parsedValue = parseInt(displayValue);
+ if (!isNaN(parsedValue) && parsedValue > 0) {
+ resultsPerPage = parsedValue;
+ } else {
+ resultsPerPage = 10; // fallback - should never get here tho
+ }
+ }
+}
+
+function updatePagination() {
+ totalPages = Math.ceil(allResults.length / resultsPerPage);
+ if (totalPages === 0)
+ totalPages = 1;
+ currentPage = Math.min(currentPage, totalPages);
+ updatePaginationControls();
+}
+
+function updatePaginationControls() {
+ totalPagesSpan.textContent = `/ ${totalPages}`;
+ currentPageInput.value = currentPage;
+
+ prevPageButton.disabled = currentPage <= 1;
+ nextPageButton.disabled = currentPage >= totalPages;
+
+ const paginationDiv = document.querySelector('.pagination');
+ if (allResults && allResults.length > 0) {
+ paginationDiv.style.display = 'flex';
+ } else {
+ paginationDiv.style.display = 'none';
+ }
+}
+
+function displayStatistics() {
const {
- results,
totalPatterns,
longestPattern,
shortestPattern,
averagePattern,
uniqueParseTags,
- } = data;
+ } = allData;
const statsContent = document.getElementById('statsContent');
- const patternsContent = document.getElementById('patternsContent');
-
- patternsContent.innerHTML = '';
statsContent.innerHTML = '';
- // update the stats part
-
const stats = [
{ label: 'Total Patterns', value: totalPatterns },
{ label: 'Longest Pattern Length', value: `${longestPattern} characters` },
@@ -96,28 +177,29 @@ function displayResults(data) {
if (uniqueParseTags.length > 0)
stats.push({ label: 'Unique Parse Tags', value: uniqueParseTags.join(', ') });
- if (totalPatterns > results.length) {
- stats.push({
- label: 'Note',
- value: `Displaying first ${results.length} of ${totalPatterns} patterns.`,
- });
- }
-
stats.forEach((stat) => {
const statItem = document.createElement('div');
statItem.className = 'stat-item';
statItem.innerHTML = `${stat.label}:
${stat.value}`;
statsContent.appendChild(statItem);
});
+}
- // sort by length ascending, looks nicer imo
- results.sort((a, b) => a.text.length - b.text.length);
+function showPage(page) {
+ patternsContent.innerHTML = '';
+ currentPage = page;
+ updatePaginationControls();
+
+ const startIndex = (currentPage - 1) * resultsPerPage;
+ const endIndex = startIndex + resultsPerPage;
+ if (endIndex > allResults.length)
+ endIndex = allResults.length;
+ const pageResults = allResults.slice(startIndex, endIndex);
const ul = document.createElement('ul');
patternsContent.appendChild(ul);
- for (let i = 0; i < results.length; i++) {
- const result = results[i];
+ pageResults.forEach((result) => {
const li = document.createElement('li');
li.className = 'result';
@@ -133,21 +215,30 @@ function displayResults(data) {
positionTooltip(e);
}
});
+ li.addEventListener('mousemove', (e) => { positionTooltip(e); });
+ li.addEventListener('mouseleave', () => { tooltip.style.display = 'none'; });
+ li.addEventListener('click', () => { copyToClipboard(patternText); });
- li.addEventListener('mousemove', (e) => {
- positionTooltip(e);
- });
-
- li.addEventListener('mouseleave', () => {
- tooltip.style.display = 'none';
- });
+ ul.appendChild(li);
+ });
+}
- li.addEventListener('click', () => {
- copyToClipboard(patternText);
- });
+function changePage(page) {
+ if (page < 1)
+ page = 1;
+ if (page > totalPages)
+ page = totalPages;
+ currentPage = page;
+ showPage(currentPage);
+}
- ul.appendChild(li);
- }
+function resetPagination() {
+ allData = null;
+ allResults = [];
+ currentPage = 1;
+ totalPages = 1;
+ patternsContent.innerHTML = '';
+ updatePaginationControls();
}
function positionTooltip(e) {
@@ -175,6 +266,8 @@ function displayError(message) {
patternsContent.innerHTML = `${message}
`;
statsContent.innerHTML = '';
+
+ resetPagination();
}
function initializeTheme() {