Search/templates/images.html

262 lines
12 KiB
HTML
Executable file
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
{{ if .IsThemeDark }}
<meta name="darkreader-lock">
{{ end }}
<title>{{.Query}} - Ocásek</title>
<link rel="stylesheet" href="/static/css/style.css">
<link rel="stylesheet" href="/static/css/style-fixedwidth.css">
<link rel="stylesheet" href="/static/css/{{.Theme}}.css">
<link rel="search" type="application/opensearchdescription+xml" title="Ocásek" href="/opensearch.xml">
</head>
<body>
<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"/>
<button id="search-wrapper-ico" class="material-icons-round" name="t" value="image">search</button>
<div class="autocomplete">
<ul>
</ul>
</div>
<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 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>
</div>
<div class="search-container-results-btn">
<button id="sub-search-wrapper-ico" class="material-icons-round clickable" name="t" value="video">movie</button>
<button name="t" value="video" class="clickable">Videos</button>
</div>
<div class="search-container-results-btn">
<button id="sub-search-wrapper-ico" class="material-icons-round clickable" name="t" value="forum">forum</button>
<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>
<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>
</form>
<form class="results_settings" action="/search" method="get">
<input type="hidden" name="q" value="{{ .Query }}">
<select class="results-settings" name="safe" id="safeSearchSelect">
<option value="disabled" {{if eq .Safe "disabled"}}selected{{end}}>Safe Search Off</option>
<option value="active" {{if eq .Safe "active"}}selected{{end}}>Safe Search On</option>
</select>
<select class="results-settings" name="lang" id="languageSelect">
{{range .LanguageOptions}}
<option value="{{.Code}}" {{if eq .Code $.CurrentLang}}selected{{end}}>{{.Name}}</option>
{{end}}
</select>
<button class="results-save" name="t" value="image">Apply settings</button>
</form>
<div class="search-results" id="results">
<!-- Results go here -->
{{ if .Results }}
<div class="images images_viewer_hidden">
<!-- Images Grid -->
{{ range $index, $result := .Results }}
<div class="image">
<img src="{{ .ThumbProxy }}" alt="{{ .Title }}" data-media="{{ .Media }}" class="clickable">
<div class="resolution">{{ .Width }} × {{ .Height }}</div>
<div class="details">
<span class="img_title clickable">{{ .Title }}</span>
<a href="{{ .Source }}" target="_blank" class="img_source">Source</a>
</div>
</div>
{{ end }}
</div>
<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>
<div id="image-viewer-overlay" style="display: none;"></div>
<div id="template-data" data-page="{{ .Page }}" data-query="{{ .Query }}" data-type="image"></div>
<script defer src="/static/js/dynamicscrolling.js"></script>
<script defer src="/static/js/autocomplete.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
let viewerOpen = false;
const viewerOverlay = document.getElementById('image-viewer-overlay');
viewerOverlay.innerHTML = `
<div id="image-viewer">
<span id="viewer-close-button" class="material-icons">close</span>
<span id="viewer-prev-button" class="material-icons">arrow_back</span>
<span id="viewer-next-button" class="material-icons">arrow_forward</span>
<div id="viewer-image-container">
<img id="viewer-image" src="" alt="">
</div>
<div id="viewer-info">
<div id="viewer-title"></div>
<a id="viewer-source-button" href="" target="_blank">Visit Page</a>
</div>
</div>
`;
function openImageViewer(element) {
const parentImageDiv = element.closest('.image');
if (!parentImageDiv) return;
const imgElement = parentImageDiv.querySelector('img.clickable');
const mediaUrl = imgElement.dataset.media;
const title = imgElement.alt;
const sourceUrl = parentImageDiv.querySelector('.img_source').href;
if (!mediaUrl || viewerOpen) {
return; // Don't open if data is missing or viewer is already open
}
viewerOpen = true;
const viewerImage = document.getElementById('viewer-image');
const viewerTitle = document.getElementById('viewer-title');
const viewerSourceButton = document.getElementById('viewer-source-button');
viewerImage.src = mediaUrl;
viewerTitle.textContent = title;
viewerSourceButton.href = sourceUrl;
viewerOverlay.style.display = 'flex';
}
// Attach event listener to the document body
document.body.addEventListener('click', function(e) {
let target = e.target;
let clickableElement = target.closest('img.clickable, .img_title.clickable');
if (clickableElement) {
e.preventDefault();
openImageViewer(clickableElement);
}
});
function closeImageViewer() {
viewerOverlay.style.display = 'none';
viewerOpen = false;
}
// Close viewer on overlay or button click
document.getElementById('viewer-close-button').addEventListener('click', closeImageViewer);
viewerOverlay.addEventListener('click', function(e) {
if (e.target === viewerOverlay) {
closeImageViewer();
}
});
// Handle keyboard events for closing and navigation
document.addEventListener('keydown', function(e) {
if (viewerOverlay.style.display === 'flex') {
if (e.key === 'Escape') {
closeImageViewer();
}
}
});
});
</script>
<script>
document.addEventListener('DOMContentLoaded', function() {
let imagesContainer = document.querySelector('.images');
let observer;
// Function to trim image titles based on the image width
function trimTitles() {
const images = document.querySelectorAll('.images .image');
images.forEach((element) => {
const imgElement = element.querySelector('img.clickable');
const titleElement = element.querySelector('.img_title.clickable');
const detailsElement = element.querySelector('.details');
if (imgElement.complete && imgElement.naturalWidth) {
const imageWidth = imgElement.clientWidth;
// Set the width of the details div and title to match the image width
detailsElement.style.width = imageWidth + 'px';
titleElement.style.maxWidth = imageWidth + 'px';
}
// // Add load event listener in case images load dynamically
// imgElement.addEventListener('load', function() {
// const imageWidth = imgElement.clientWidth;
// detailsElement.style.width = imageWidth + 'px';
// titleElement.style.maxWidth = imageWidth + 'px';
// });
});
}
// Call trimTitles periodically to account for dynamic loading, not happy about this one
setInterval(() => {
trimTitles();
}, 10);
// Observe for dynamically added images
function observeNewImages() {
observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
mutation.addedNodes.forEach(function(node) {
if (node.nodeType === 1 && node.classList.contains('image')) {
trimTitles();
}
});
});
});
// Observe the images container for changes
observer.observe(imagesContainer, { childList: true, subtree: true });
}
// Run initial title trimming after page load
trimTitles();
// Start observing for dynamic image loading
observeNewImages();
});
</script>
<script>
// Check if JavaScript is enabled and modify the DOM accordingly
document.getElementById('content').classList.remove('js-enabled');
</script>
</body>
</html>