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%; left: 50%;
transform: translateX(-50%); transform: translateX(-50%);
padding: 10px; padding: 10px;
background-color: var(--html-bg); background-color: var(--search-bg);
border: 1px solid var(--border); border: 1px solid var(--border);
border-radius: 15px; border-radius: 5px;
box-shadow: 0 0 10px rgba(0,0,0,0.1); box-shadow: 0 0 10px var(--box-shadow);
z-index: 1000; z-index: 1000;
width: auto; width: auto;
max-width: 80%; max-width: 80%;
@ -1370,9 +1370,9 @@ p {
/* Map container */ /* Map container */
#map { #map {
height: calc(100% - 60px); /* Adjust this value based on the header height */ height: calc(100% - 60px);
width: 100%; width: 100%;
top: 60px; /* Same value as in the results-search-container margin-top */ top: 60px;
} }
/* Leaflet control buttons */ /* Leaflet control buttons */
@ -1465,86 +1465,22 @@ p {
text-shadow: 1px 1px 2px var(--border) !important; /* Adjust text shadow */ text-shadow: 1px 1px 2px var(--border) !important; /* Adjust text shadow */
} }
/* Ensuring dark theme compliance */ .message-bottom-left {
@media (prefers-color-scheme: dark) { display: none;
.leaflet-control-locate, align-items: center;
.leaflet-control-layers-toggle, justify-content: center;
.leaflet-bar a, position: fixed;
.leaflet-bar a:hover, bottom: 20px;
.leaflet-popup-content-wrapper, right: 20px;
.leaflet-popup-tip, background-color: var(--search-bg);
.leaflet-control-attribution, color: var(--text-color);
.leaflet-control-scale, padding: 10px;
.leaflet-control-scale-line { border-radius: 5px;
background-color: var(--button) !important; z-index: 1000;
border: 1px solid var(--border) !important; text-align: center;
color: var(--fg) !important; flex-direction: column;
text-shadow: 1px 1px 2px var(--background-color) !important; /* Dark theme shadow adjustment */ border: 1px solid var(--border);
} box-shadow: 0 0 10px var(--box-shadow);
.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;
}
} }
body, h1, p, a, input, button { 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,10 +11,10 @@
<form action="/search" id="prev-next-form" class="results-search-container" method="GET" autocomplete="off"> <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> <h1 class="logomobile"><a class="no-decoration" href="./">Ocásek</a></h1>
<div class="wrapper-results"> <div class="wrapper-results">
<input type="text" name="q" value="{{ .Query }}" id="search-input" placeholder="Type to search..." /> <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> <button id="search-wrapper-ico" class="material-icons-round" name="t" value="image">search</button>
<input type="submit" class="hide" name="t" value="image" /> <input type="submit" class="hide" name="t" value="image" />
</div> </div>
<div class="sub-search-button-wrapper"> <div class="sub-search-button-wrapper">
<div class="search-container-results-btn"> <div class="search-container-results-btn">
<button id="sub-search-wrapper-ico" class="material-icons-round clickable" name="t" value="text">search</button> <button id="sub-search-wrapper-ico" class="material-icons-round clickable" name="t" value="text">search</button>
@ -33,17 +33,16 @@
<button name="t" value="forum" class="clickable">Forums</button> <button name="t" value="forum" class="clickable">Forums</button>
</div> </div>
<div id="content" class="js-enabled"> <div id="content" class="js-enabled">
<div class="search-container-results-btn"> <div class="search-container-results-btn">
<button id="sub-search-wrapper-ico" class="material-icons-round clickable" name="t" value="map">map</button> <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> <button name="t" value="map" class="clickable">Maps</button>
</div> </div>
</div> </div>
<div class="search-container-results-btn"> <div class="search-container-results-btn">
<button id="sub-search-wrapper-ico" class="material-icons-round clickable" name="t" value="file">share</button> <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> <button name="t" value="file" class="clickable">Torrents</button>
</div> </div>
</div> </div>
</div>
</form> </form>
<form class="results_settings" action="/search" method="get"> <form class="results_settings" action="/search" method="get">
<input type="hidden" name="q" value="{{ .Query }}"> <input type="hidden" name="q" value="{{ .Query }}">
@ -58,27 +57,10 @@
</select> </select>
<button class="results-save" name="t" value="image">Apply settings</button> <button class="results-save" name="t" value="image">Apply settings</button>
</form> </form>
<div class="search-results"> <div class="search-results" id="results">
<!-- Results go here --> <!-- Results go here -->
{{ if .Results }} {{ if .Results }}
<div class="images images_viewer_hidden"> <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 --> <!-- Images Grid -->
{{ range .Results }} {{ range .Results }}
<div class="image"> <div class="image">
@ -93,29 +75,90 @@
</div> </div>
{{ end }} {{ end }}
</div> </div>
<!-- Pagination --> <noscript>
<div class="prev-next prev-img"> <div class="prev-next prev-img">
<form action="/search" method="get"> <form action="/search" method="get">
<input type="hidden" name="q" value="{{ .Query }}"> <input type="hidden" name="q" value="{{ .Query }}">
<input type="hidden" name="t" value="image"> <input type="hidden" name="t" value="image">
{{ if .HasPrevPage }} {{ if .HasPrevPage }}
<!-- Subtract 1 from the current page for the Previous button --> <!-- Subtract 1 from the current page for the Previous button -->
<button type="submit" name="p" value="{{ sub .Page 1 }}">Previous</button> <button type="submit" name="p" value="{{ sub .Page 1 }}">Previous</button>
{{ end }} {{ end }}
{{ if .HasNextPage }} {{ if .HasNextPage }}
<!-- Add 1 to the current page for the Next button --> <!-- Add 1 to the current page for the Next button -->
<button type="submit" name="p" value="{{ add .Page 1 }}">Next</button> <button type="submit" name="p" value="{{ add .Page 1 }}">Next</button>
{{ end }} {{ end }}
</form> </form>
</div> </div>
{{ else }} </noscript>
{{ else if .NoResults }}
<div class="no-results">No results found for '{{ .Query }}'. Try different keywords.</div> <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 }} {{ end }}
</div> </div>
<div class="message-bottom-left" id="message-bottom-left">
<span>Searching for new results...</span>
</div>
<script> <script>
// Check if JavaScript is enabled and modify the DOM accordingly document.addEventListener("DOMContentLoaded", function() {
document.getElementById('content').classList.remove('js-enabled'); 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> </script>
</body> </body>
</html> </html>

View file

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