Search
This commit is contained in:
1 parent
e33b5a2719
commit
e7cf77e57e
5 files changed
+456
-15
No files matched your search
+224
-1
@@ -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
@@ -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>
|
||||
@@ -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');
|
||||
}
|
||||
@@ -147,4 +147,11 @@ return [
|
||||
'tab_clear_token_confirm' => 'Weet je zeker dat je de inlog-token wilt wissen? De unieke URL werkt dan niet meer.',
|
||||
'tooltip_copy_to_clipboard' => 'Kopieer naar klembord',
|
||||
'tooltip_copied' => 'Gekopieerd!',
|
||||
|
||||
// Search functionality
|
||||
'search_placeholder' => 'Zoeken (Ctrl+K)',
|
||||
'search_no_results' => 'Geen bladwijzers gevonden voor',
|
||||
'search_google' => 'Zoek op Google',
|
||||
'search_duckduckgo' => 'Zoek op DuckDuckGo',
|
||||
'search_web' => 'Zoek op internet',
|
||||
];
|
||||
Reference in new issue
Block a user