added dynamic lloading for images

This commit is contained in:
partisan 2024-06-19 14:33:00 +02:00
parent d0c20bdc8f
commit 556309bac1
3 changed files with 211 additions and 133 deletions

View file

@ -1357,10 +1357,10 @@ p {
left: 50%;
transform: translateX(-50%);
padding: 10px;
background-color: var(--html-bg);
background-color: var(--search-bg);
border: 1px solid var(--border);
border-radius: 15px;
box-shadow: 0 0 10px rgba(0,0,0,0.1);
border-radius: 5px;
box-shadow: 0 0 10px var(--box-shadow);
z-index: 1000;
width: auto;
max-width: 80%;
@ -1370,9 +1370,9 @@ p {
/* Map container */
#map {
height: calc(100% - 60px); /* Adjust this value based on the header height */
height: calc(100% - 60px);
width: 100%;
top: 60px; /* Same value as in the results-search-container margin-top */
top: 60px;
}
/* Leaflet control buttons */
@ -1465,86 +1465,22 @@ p {
text-shadow: 1px 1px 2px var(--border) !important; /* Adjust text shadow */
}
/* Ensuring dark theme compliance */
@media (prefers-color-scheme: dark) {
.leaflet-control-locate,
.leaflet-control-layers-toggle,
.leaflet-bar a,
.leaflet-bar a:hover,
.leaflet-popup-content-wrapper,
.leaflet-popup-tip,
.leaflet-control-attribution,
.leaflet-control-scale,
.leaflet-control-scale-line {
background-color: var(--button) !important;
border: 1px solid var(--border) !important;
color: var(--fg) !important;
text-shadow: 1px 1px 2px var(--background-color) !important; /* Dark theme shadow adjustment */
}
.leaflet-control-attribution a {
color: var(--link) !important;
}
}
/* --- */
/* Variables for light theme */
:root {
--background-color: #ffffff;
--text-color: #000000;
--highlight: #007bff;
--border-color: #dddddd;
--search-bg: #f1f3f4;
--search-bg-input: #ffffff;
--search-bg-input-border: #dfe1e5;
--button: #f8f9fa;
--link: #1a0dab;
--fg: #202124;
--html-bg: #ffffff;
--snip-border: #dfe1e5;
--snip-background: #ffffff;
--image-view: #ffffff;
--image-view-titlebar: #f1f3f4;
--search-button: #5f6368;
--image-select: #e8f0fe;
--view-image-color: #f8f9fa;
--footer-bg: #f2f2f2;
--footer-font: #70757a;
--border: #e0e0e0;
--link-visited: #660099;
--publish-info: #70757a;
--green: #3c802c;
}
/* Styles for dark theme */
@media (prefers-color-scheme: dark) {
:root {
--background-color: #202124;
--text-color: #e8eaed;
--highlight: #8ab4f8;
--border-color: #5f6368;
--search-bg: #303134;
--search-bg-input: #202124;
--search-bg-input-border: #5f6368;
--button: #3c4043;
--link: #8ab4f8;
--fg: #e8eaed;
--html-bg: #202124;
--snip-border: #5f6368;
--snip-background: #303134;
--image-view: #202124;
--image-view-titlebar: #303134;
--search-button: #e8eaed;
--image-select: #5f6368;
--view-image-color: #202124;
--footer-bg: #303134;
--footer-font: #e8eaed;
--border: #5f6368;
--link-visited: #c79fff;
--publish-info: #e8eaed;
--green: #8ab4f8;
}
.message-bottom-left {
display: none;
align-items: center;
justify-content: center;
position: fixed;
bottom: 20px;
right: 20px;
background-color: var(--search-bg);
color: var(--text-color);
padding: 10px;
border-radius: 5px;
z-index: 1000;
text-align: center;
flex-direction: column;
border: 1px solid var(--border);
box-shadow: 0 0 10px var(--box-shadow);
}
body, h1, p, a, input, button {
@ -1889,3 +1825,87 @@ body, h1, p, a, input, button {
}
}
/* --- */
/* Ensuring dark theme compliance */
@media (prefers-color-scheme: dark) {
.leaflet-control-locate,
.leaflet-control-layers-toggle,
.leaflet-bar a,
.leaflet-bar a:hover,
.leaflet-popup-content-wrapper,
.leaflet-popup-tip,
.leaflet-control-attribution,
.leaflet-control-scale,
.leaflet-control-scale-line {
background-color: var(--button) !important;
border: 1px solid var(--border) !important;
color: var(--fg) !important;
text-shadow: 1px 1px 2px var(--background-color) !important; /* Dark theme shadow adjustment */
}
.leaflet-control-attribution a {
color: var(--link) !important;
}
}
/* Variables for light theme */
:root {
--background-color: #ffffff;
--text-color: #000000;
--highlight: #007bff;
--border-color: #dddddd;
--search-bg: #f1f3f4;
--search-bg-input: #ffffff;
--search-bg-input-border: #dfe1e5;
--button: #f8f9fa;
--link: #1a0dab;
--fg: #202124;
--html-bg: #ffffff;
--snip-border: #dfe1e5;
--snip-background: #ffffff;
--image-view: #ffffff;
--image-view-titlebar: #f1f3f4;
--search-button: #5f6368;
--image-select: #e8f0fe;
--view-image-color: #f8f9fa;
--footer-bg: #f2f2f2;
--footer-font: #70757a;
--border: #e0e0e0;
--link-visited: #660099;
--publish-info: #70757a;
--green: #3c802c;
--box-shadow: #00000020;
}
/* Styles for dark theme */
@media (prefers-color-scheme: dark) {
:root {
--background-color: #202124;
--text-color: #e8eaed;
--highlight: #8ab4f8;
--border-color: #5f6368;
--search-bg: #303134;
--search-bg-input: #202124;
--search-bg-input-border: #5f6368;
--button: #3c4043;
--link: #8ab4f8;
--fg: #e8eaed;
--html-bg: #202124;
--snip-border: #5f6368;
--snip-background: #303134;
--image-view: #202124;
--image-view-titlebar: #303134;
--search-button: #e8eaed;
--image-select: #5f6368;
--view-image-color: #202124;
--footer-bg: #303134;
--footer-font: #e8eaed;
--border: #5f6368;
--link-visited: #c79fff;
--publish-info: #e8eaed;
--green: #8ab4f8;
--box-shadow: #ffffff20;
}
}

View file

@ -11,15 +11,15 @@
<form action="/search" id="prev-next-form" class="results-search-container" method="GET" autocomplete="off">
<h1 class="logomobile"><a class="no-decoration" href="./">Ocásek</a></h1>
<div class="wrapper-results">
<input type="text" name="q" value="{{ .Query }}" id="search-input" placeholder="Type to search..." />
<button id="search-wrapper-ico" class="material-icons-round" name="t" value="image">search</button>
<input type="submit" class="hide" name="t" value="image" />
</div>
<input type="text" name="q" value="{{ .Query }}" id="search-input" placeholder="Type to search..." />
<button id="search-wrapper-ico" class="material-icons-round" name="t" value="image">search</button>
<input type="submit" class="hide" name="t" value="image" />
</div>
<div class="sub-search-button-wrapper">
<div class="search-container-results-btn">
<button id="sub-search-wrapper-ico" class="material-icons-round clickable" name="t" value="text">search</button>
<button name="t" value="text" class="clickable">Web</button>
</div>
</div>
<div class="search-container-results-btn">
<button id="sub-search-wrapper-ico" class="material-icons-round clickable search-active" name="t" value="image">image</button>
<button name="t" value="image" class="clickable search-active">Images</button>
@ -33,17 +33,16 @@
<button name="t" value="forum" class="clickable">Forums</button>
</div>
<div id="content" class="js-enabled">
<div class="search-container-results-btn">
<button id="sub-search-wrapper-ico" class="material-icons-round clickable" name="t" value="map">map</button>
<button name="t" value="map" class="clickable">Maps</button>
</div>
<div class="search-container-results-btn">
<button id="sub-search-wrapper-ico" class="material-icons-round clickable" name="t" value="map">map</button>
<button name="t" value="map" class="clickable">Maps</button>
</div>
</div>
<div class="search-container-results-btn">
<button id="sub-search-wrapper-ico" class="material-icons-round clickable" name="t" value="file">share</button>
<button name="t" value="file" class="clickable">Torrents</button>
</div>
</div>
</div>
</form>
<form class="results_settings" action="/search" method="get">
<input type="hidden" name="q" value="{{ .Query }}">
@ -58,27 +57,10 @@
</select>
<button class="results-save" name="t" value="image">Apply settings</button>
</form>
<div class="search-results">
<div class="search-results" id="results">
<!-- Results go here -->
{{ if .Results }}
<div class="images images_viewer_hidden">
<!-- Image Viewer Placeholder - Adapt as necessary -->
<div class="image_view image_hide">
<!-- Navigation and Close for the Image Viewer -->
<!-- Placeholder for dynamic interaction, adapt the onclick functionality as needed -->
<div class="image-view-close">
<button class="btn-nostyle"><div class="material-icons-round icon_visibility clickable">navigate_before</div></button>
<button class="btn-nostyle"><div class="material-icons-round icon_visibility clickable">navigate_next</div></button>
<button class="btn-nostyle"><div class="material-icons-round icon_visibility clickable">close</div></button>
</div>
<!-- Placeholder for selected image -->
<a class="image-viewer-link clickable" href="#">
<div class="view-image">
<img class="view-image-img" src="" alt="Selected Image"/>
</div>
</a>
<!-- Additional image details here -->
</div>
<!-- Images Grid -->
{{ range .Results }}
<div class="image">
@ -93,29 +75,90 @@
</div>
{{ end }}
</div>
<!-- Pagination -->
<div class="prev-next prev-img">
<form action="/search" method="get">
<input type="hidden" name="q" value="{{ .Query }}">
<input type="hidden" name="t" value="image">
{{ if .HasPrevPage }}
<!-- Subtract 1 from the current page for the Previous button -->
<button type="submit" name="p" value="{{ sub .Page 1 }}">Previous</button>
{{ end }}
{{ if .HasNextPage }}
<!-- Add 1 to the current page for the Next button -->
<button type="submit" name="p" value="{{ add .Page 1 }}">Next</button>
{{ end }}
</form>
</div>
{{ else }}
<noscript>
<div class="prev-next prev-img">
<form action="/search" method="get">
<input type="hidden" name="q" value="{{ .Query }}">
<input type="hidden" name="t" value="image">
{{ if .HasPrevPage }}
<!-- Subtract 1 from the current page for the Previous button -->
<button type="submit" name="p" value="{{ sub .Page 1 }}">Previous</button>
{{ end }}
{{ if .HasNextPage }}
<!-- Add 1 to the current page for the Next button -->
<button type="submit" name="p" value="{{ add .Page 1 }}">Next</button>
{{ end }}
</form>
</div>
</noscript>
{{ else if .NoResults }}
<div class="no-results">No results found for '{{ .Query }}'. Try different keywords.</div>
{{ else }}
<div class="no-more-results">Looks like this is the end of results.</div>
{{ end }}
</div>
<div class="message-bottom-left" id="message-bottom-left">
<span>Searching for new results...</span>
</div>
<script>
// Check if JavaScript is enabled and modify the DOM accordingly
document.getElementById('content').classList.remove('js-enabled');
document.addEventListener("DOMContentLoaded", function() {
let page = {{ .Page }};
const query = "{{ .Query }}";
let loading = false;
let hasMoreResults = true;
const loadingIndicator = document.getElementById('message-bottom-left');
let loadingTimeout;
function loadResults(newPage) {
if (loading || !hasMoreResults) return;
loading = true;
// Show loading indicator if taking more than 100ms
loadingTimeout = setTimeout(() => {
loadingIndicator.style.display = 'flex';
}, 100);
fetch(`/search?q=${encodeURIComponent(query)}&t=image&p=${newPage}`)
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.text();
})
.then(data => {
clearTimeout(loadingTimeout);
loadingIndicator.style.display = 'none';
const parser = new DOMParser();
const doc = parser.parseFromString(data, 'text/html');
const newResults = doc.getElementById('results').innerHTML;
const noResultsMessage = "No results found for '{{ .Query }}'. Try different keywords.";
const endOfResultsMessage = "Looks like this is the end of results.";
const serverError = "Internal Server Error";
if (newResults.includes(noResultsMessage) || newResults.includes(endOfResultsMessage) || newResults.includes(serverError)) {
document.getElementById('results').innerHTML += newResults;
hasMoreResults = false;
} else {
document.getElementById('results').innerHTML += newResults;
page = newPage;
}
loading = false;
})
.catch(error => {
clearTimeout(loadingTimeout);
loadingIndicator.style.display = 'none';
console.error('Error loading results:', error);
hasMoreResults = false; // Stop further attempts
loading = false;
});
}
window.addEventListener('scroll', () => {
if (window.innerHeight + window.scrollY >= document.body.offsetHeight) {
loadResults(page + 1);
}
});
});
</script>
</body>
</html>
</html>

View file

@ -73,6 +73,9 @@
<div class="no-more-results">Looks like this is the end of results.</div>
{{end}}
</div>
<div class="message-bottom-left" id="message-bottom-left">
<span>Searching for new results...</span>
</div>
<div class="prev-next prev-img" id="prev-next">
<form action="/search" method="get">
<input type="hidden" name="q" value="{{ .Query }}">
@ -94,13 +97,23 @@
const query = "{{ .Query }}";
let loading = false;
let hasMoreResults = true;
const loadingIndicator = document.getElementById('message-bottom-left');
let loadingTimeout;
function loadResults(newPage) {
if (loading || !hasMoreResults) return;
loading = true;
// Show loading indicator if taking more than 100ms
loadingTimeout = setTimeout(() => {
loadingIndicator.style.display = 'flex';
}, 100);
fetch(`/search?q=${encodeURIComponent(query)}&t=text&p=${newPage}`)
.then(response => response.text())
.then(data => {
clearTimeout(loadingTimeout);
loadingIndicator.style.display = 'none';
const parser = new DOMParser();
const doc = parser.parseFromString(data, 'text/html');
const newResults = doc.getElementById('results').innerHTML;
@ -116,6 +129,8 @@
loading = false;
})
.catch(error => {
clearTimeout(loadingTimeout);
loadingIndicator.style.display = 'none';
console.error('Error loading results:', error);
loading = false;
});