This commit is contained in:
rmeijer_huizehetoost committed 2025-10-06 11:19:59 +02:00
1 parent e33b5a2719
commit e7cf77e57e
5 files changed
+456 -15

No files matched your search

+224 -1
View File
@@ -106,6 +106,14 @@ body[style*="background-image"] {
font-size: 1.5rem; /* Increased font size for site title */
}
.navbar {
position: relative;
}
.navbar-collapse {
position: relative;
}
/* Class to force light text color when background is dark */
body.dark-background-active {
color: #f8f9fa !important;
@@ -185,5 +193,220 @@ body.dark-background-active .form-text,
/* Custom styles for transparent theme */
[data-bs-theme="transparent"] {
/* Transparent theme styles can be added here if needed */
}
/* New navbar layout */
.container-fluid {
display: flex;
align-items: center;
justify-content: space-between;
position: relative;
}
.navbar-left {
flex: 0 0 auto;
}
.navbar-right {
flex: 0 0 auto;
}
/* Search functionality styles */
.input-group.search {
margin-top: 16px;
}
/* Hide search bar on login page */
body.login-page .search-container-center {
display: none !important;
}
.search-container-center {
position: absolute;
left: 50%;
transform: translateX(-50%);
max-width: 600px;
width: 100%;
z-index: 10;
}
.search-container-center .form-control {
font-size: 1.1rem;
padding: 0.75rem 1rem;
height: auto;
}
.search-container-center .btn {
padding: 0.75rem 1rem;
font-size: 1.1rem;
}
.search-results {
position: absolute;
top: 100%;
left: 0;
right: 0;
background: var(--bs-body-bg);
border: 1px solid var(--bs-border-color);
border-top: none;
border-radius: 0 0 0.375rem 0.375rem;
max-height: 300px;
overflow-y: auto;
z-index: 1000;
display: none;
box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
}
.search-results.show {
display: block;
}
.search-result-item {
padding: 0.75rem 1rem;
border-bottom: 1px solid var(--bs-border-color);
cursor: pointer;
transition: background-color 0.15s ease-in-out;
display: flex;
align-items: center;
gap: 0.5rem;
}
.search-result-item:hover {
background-color: var(--bs-gray-100);
}
.search-result-item:last-child {
border-bottom: none;
}
.search-result-item .bookmark-icon {
width: 16px;
height: 16px;
flex-shrink: 0;
}
.search-result-item .bookmark-info {
flex: 1;
min-width: 0;
}
.search-result-item .bookmark-title {
font-weight: 500;
color: var(--bs-body-color);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
margin: 0;
}
.search-result-item .bookmark-url {
font-size: 0.875rem;
color: var(--bs-secondary);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
margin: 0;
}
.search-result-item .bookmark-category {
font-size: 0.75rem;
color: var(--bs-dark);
background: var(--bs-warning);
padding: 0.125rem 0.375rem;
border-radius: 0.25rem;
white-space: nowrap;
font-weight: 500;
}
.search-no-results {
padding: 1rem;
text-align: center;
color: var(--bs-muted);
font-style: italic;
}
.search-engine-results {
padding: 0.5rem;
background: var(--bs-info-bg-subtle);
border-bottom: 1px solid var(--bs-border-color);
}
.search-engine-results .search-engine-item {
padding: 0.5rem;
cursor: pointer;
border-radius: 0.25rem;
transition: background-color 0.15s ease-in-out;
}
.search-engine-item:hover {
background-color: var(--bs-info);
color: white;
}
/* Dark theme adjustments for search */
[data-bs-theme="dark"] .search-results {
background: var(--bs-dark);
border-color: var(--bs-gray-700);
}
[data-bs-theme="dark"] .search-result-item:hover {
background-color: var(--bs-gray-800);
}
[data-bs-theme="dark"] .search-result-item .bookmark-category {
color: var(--bs-dark);
background: var(--bs-warning);
}
[data-bs-theme="dark"] .search-engine-results {
background: var(--bs-dark);
}
[data-bs-theme="dark"] .search-engine-item:hover {
background-color: var(--bs-primary);
}
/* Responsive search bar */
@media (max-width: 768px) {
.container-fluid {
flex-direction: column;
align-items: stretch;
}
.search-container-center {
position: static;
transform: none;
max-width: 100%;
margin: 1rem auto;
order: -1;
}
.search-container-center .form-control {
font-size: 1rem;
padding: 0.6rem 0.8rem;
}
.search-container-center .btn {
padding: 0.6rem 0.8rem;
font-size: 1rem;
}
.search-results {
position: fixed;
top: auto;
left: 1rem;
right: 1rem;
max-height: 50vh;
}
.navbar-collapse {
flex-direction: column;
}
.navbar-nav {
margin-left: 0 !important;
margin-right: 0 !important;
}
}
+40 -14
View File
@@ -33,6 +33,11 @@ if ($theme !== 'dark' && intval($bg_brightness) < 70) {
$body_classes[] = 'dark-background-active';
}
// Add any additional body classes from globals
if (isset($GLOBALS['body_class'])) {
$body_classes[] = $GLOBALS['body_class'];
}
$navbar_classes = ['navbar', 'navbar-expand-lg', 'mb-4'];
if (in_array('dark-background-active', $body_classes) || $theme === 'dark') {
$navbar_classes[] = 'navbar-dark';
@@ -99,17 +104,37 @@ if ($theme === 'dark' || in_array('dark-background-active', $body_classes)) {
<header>
<nav class="navbar navbar-expand-lg">
<div class="container-fluid">
<a class="navbar-brand" href="index.php">
<img src="<?php echo htmlspecialchars($settings['site_logo'] ?? 'include/images/favicon.ico'); ?>" alt="<?php echo htmlspecialchars($settings['site_title'] ?? 'Bookmarkly'); ?> Logo" height="<?php echo htmlspecialchars($settings['logo_height'] ?? '50'); ?>">
<?php if (($settings['display_site_title'] ?? '1') === '1'): ?>
<?php echo htmlspecialchars($settings['site_title'] ?? 'Bookmarkly'); ?>
<?php endif; ?>
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav ms-auto mb-2 mb-lg-0">
<!-- Left side: Logo/Brand -->
<div class="navbar-left">
<a class="navbar-brand" href="index.php">
<img src="<?php echo htmlspecialchars($settings['site_logo'] ?? 'include/images/favicon.ico'); ?>" alt="<?php echo htmlspecialchars($settings['site_title'] ?? 'Bookmarkly'); ?> Logo" height="<?php echo htmlspecialchars($settings['logo_height'] ?? '50'); ?>">
<?php if (($settings['display_site_title'] ?? '1') === '1'): ?>
<?php echo htmlspecialchars($settings['site_title'] ?? 'Bookmarkly'); ?>
<?php endif; ?>
</a>
</div>
<!-- Center: Search Bar -->
<div class="search-container-center">
<div class="input-group search">
<input type="text" class="form-control" id="searchInput" placeholder="<?php echo translate('index_search_placeholder'); ?>" autocomplete="off">
<button class="btn btn-outline-secondary" type="button" id="searchButton">
<i class="bi bi-search"></i>
</button>
<button class="btn btn-outline-secondary" type="button" id="searchEngineButton" title="Zoek op internet">
<i class="bi bi-globe"></i>
</button>
</div>
<div id="searchResults" class="search-results"></div>
</div>
<!-- Right side: Navigation -->
<div class="navbar-right">
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav ms-auto mb-2 mb-lg-0">
<?php if (isset($_SESSION['user_id'])): ?>
<?php if (isAdmin() || isUser()): ?>
<li class="nav-item">
@@ -145,7 +170,8 @@ if ($theme === 'dark' || in_array('dark-background-active', $body_classes)) {
<a class="nav-link" href="login.php"><i class="bi bi-box-arrow-in-right"></i> <?php echo translate('login_button'); ?></a>
</li>
<?php endif; ?>
</ul>
</ul>
</div>
</div>
</div>
</div>
</nav>
</nav>
+183
View File
@@ -274,6 +274,9 @@ document.addEventListener('DOMContentLoaded', function() {
// Initialize SortableJS for drag-and-drop
initSortable();
// Initialize search functionality
initSearch();
// Add form submit handlers to format URLs before submission
// Use event delegation to handle dynamically created forms
document.addEventListener('submit', function(event) {
@@ -385,4 +388,184 @@ function optimizeImage(path) {
alert('A network error occurred: ' + error.message);
});
}
}
// Search functionality
function initSearch() {
const searchInput = document.getElementById('searchInput');
const searchButton = document.getElementById('searchButton');
const searchEngineButton = document.getElementById('searchEngineButton');
const searchResults = document.getElementById('searchResults');
if (!searchInput || !searchResults) return;
let searchTimeout;
let allBookmarks = [];
// Load all bookmarks on page load
loadAllBookmarks();
// Search input event
searchInput.addEventListener('input', function() {
clearTimeout(searchTimeout);
const query = this.value.trim();
if (query.length < 2) {
hideSearchResults();
return;
}
searchTimeout = setTimeout(() => {
performSearch(query);
}, 300);
});
// Search button click
if (searchButton) {
searchButton.addEventListener('click', function() {
const query = searchInput.value.trim();
if (query.length >= 2) {
performSearch(query);
}
});
}
// Search engine button click
if (searchEngineButton) {
searchEngineButton.addEventListener('click', function() {
const query = searchInput.value.trim();
if (query) {
searchOnWeb(query);
}
});
}
// Hide search results when clicking outside
document.addEventListener('click', function(event) {
if (!searchInput.contains(event.target) && !searchResults.contains(event.target)) {
hideSearchResults();
}
});
// Keyboard shortcuts
document.addEventListener('keydown', function(event) {
// Ctrl+K to focus search
if (event.ctrlKey && event.key === 'k') {
event.preventDefault();
searchInput.focus();
}
// Escape to hide results
if (event.key === 'Escape') {
hideSearchResults();
searchInput.blur();
}
});
function loadAllBookmarks() {
// Extract bookmarks from the current page
const bookmarkElements = document.querySelectorAll('.bookmark-link, .list-group-item a');
allBookmarks = [];
bookmarkElements.forEach(element => {
const title = element.textContent.trim();
const url = element.href;
const icon = element.querySelector('img')?.src || 'include/images/default-icon.png';
// Find category name
let categoryName = '';
const categoryElement = element.closest('.category-column');
if (categoryElement) {
const categoryTitle = categoryElement.querySelector('h5');
if (categoryTitle) {
categoryName = categoryTitle.textContent.trim();
}
}
allBookmarks.push({
title: title,
url: url,
icon: icon,
category: categoryName
});
});
}
function performSearch(query) {
const results = allBookmarks.filter(bookmark =>
bookmark.title.toLowerCase().includes(query.toLowerCase()) ||
bookmark.url.toLowerCase().includes(query.toLowerCase()) ||
bookmark.category.toLowerCase().includes(query.toLowerCase())
);
displaySearchResults(results, query);
}
function displaySearchResults(results, query) {
searchResults.innerHTML = '';
if (results.length === 0) {
searchResults.innerHTML = `
<div class="search-no-results">
Geen bladwijzers gevonden voor "${query}"
</div>
`;
} else {
// Add search engine options
searchResults.innerHTML = `
<div class="search-engine-results">
<div class="search-engine-item" onclick="searchOnWeb('${query}')">
<i class="bi bi-globe me-2"></i>
Zoek "${query}" op Google
</div>
<div class="search-engine-item" onclick="searchOnDuckDuckGo('${query}')">
<i class="bi bi-search me-2"></i>
Zoek "${query}" op DuckDuckGo
</div>
</div>
`;
// Add bookmark results
results.forEach(bookmark => {
const resultItem = document.createElement('div');
resultItem.className = 'search-result-item';
resultItem.onclick = () => {
window.open(bookmark.url, '_blank');
hideSearchResults();
};
resultItem.innerHTML = `
<img src="${bookmark.icon}" alt="" class="bookmark-icon" onerror="this.onerror=null;this.src='include/images/default-icon.png';">
<div class="bookmark-info">
<div class="bookmark-title">${bookmark.title}</div>
<div class="bookmark-url">${bookmark.url}</div>
</div>
${bookmark.category ? `<span class="bookmark-category">${bookmark.category}</span>` : ''}
`;
searchResults.appendChild(resultItem);
});
}
showSearchResults();
}
function showSearchResults() {
searchResults.classList.add('show');
}
function hideSearchResults() {
searchResults.classList.remove('show');
}
}
// Search engine functions
function searchOnWeb(query) {
const searchUrl = `https://www.google.com/search?q=${encodeURIComponent(query)}`;
window.open(searchUrl, '_blank');
}
function searchOnDuckDuckGo(query) {
const searchUrl = `https://duckduckgo.com/?q=${encodeURIComponent(query)}`;
window.open(searchUrl, '_blank');
}