Skip to content

Commit 9aa973a

Browse files
committed
Fix #71
1 parent 2de19a5 commit 9aa973a

File tree

2 files changed

+97
-117
lines changed

2 files changed

+97
-117
lines changed

src/py_semantic_taxonomy/adapters/routers/templates/base.html

Lines changed: 97 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,14 @@
2828
placeholder="Search concepts..."
2929
class="w-full px-4 py-2 pl-10 pr-20 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary focus:border-transparent"
3030
autocomplete="off"
31+
value="{{ query }}"
3132
/>
3233
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
3334
<i class="fas fa-search text-gray-400"></i>
3435
</div>
3536
<div class="absolute inset-y-0 right-0 pr-3 flex items-center">
3637
<kbd class="hidden md:inline-flex items-center px-2 py-1.5 text-xs font-semibold border rounded shadow-sm" style="color: var(--text-secondary); background-color: var(--nav-bg); border-color: var(--border-color)">
37-
<span id="shortcut-key">Ctrl</span><span class="mx-0.5">+</span>K
38+
<span id="shortcut-key">Esc</span>
3839
</kbd>
3940
</div>
4041
<input type="hidden" name="semantic" value="true" />
@@ -95,128 +96,118 @@
9596
</div>
9697
</footer>
9798
<script>
99+
// Theme handling
100+
const themeToggle = document.getElementById('theme-toggle');
101+
const themeIcon = themeToggle.querySelector('i');
102+
103+
// Check for saved theme preference
104+
const savedTheme = localStorage.getItem('theme') || 'light';
105+
document.documentElement.setAttribute('data-theme', savedTheme);
106+
updateThemeIcon(savedTheme);
107+
108+
themeToggle.addEventListener('click', () => {
109+
const currentTheme = document.documentElement.getAttribute('data-theme');
110+
const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
111+
document.documentElement.setAttribute('data-theme', newTheme);
112+
localStorage.setItem('theme', newTheme);
113+
updateThemeIcon(newTheme);
114+
});
115+
116+
function updateThemeIcon(theme) {
117+
themeIcon.className = theme === 'dark' ? 'fas fa-sun' : 'fas fa-moon';
118+
}
119+
120+
// Prevent clicks on disabled links
121+
document.querySelectorAll('a[aria-disabled="true"]').forEach(link => {
122+
link.addEventListener('click', (e) => {
123+
e.preventDefault();
124+
e.stopPropagation();
125+
});
126+
});
127+
128+
// Search functionality
98129
document.addEventListener('DOMContentLoaded', function() {
99130
document.getElementById('language').addEventListener('change', function(e) {
100131
window.location.href = e.target.value;
101132
});
102133

103-
// Theme handling
104-
const themeToggle = document.getElementById('theme-toggle');
105-
const themeIcon = themeToggle.querySelector('i');
106-
107-
// Check for saved theme preference
108-
const savedTheme = localStorage.getItem('theme') || 'light';
109-
document.documentElement.setAttribute('data-theme', savedTheme);
110-
updateThemeIcon(savedTheme);
111-
112-
themeToggle.addEventListener('click', () => {
113-
const currentTheme = document.documentElement.getAttribute('data-theme');
114-
const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
115-
document.documentElement.setAttribute('data-theme', newTheme);
116-
localStorage.setItem('theme', newTheme);
117-
updateThemeIcon(newTheme);
118-
});
119-
120-
function updateThemeIcon(theme) {
121-
themeIcon.className = theme === 'dark' ? 'fas fa-sun' : 'fas fa-moon';
122-
}
134+
const searchInput = document.querySelector('input[name="query"]');
135+
const suggestionsDiv = document.getElementById('suggestions');
136+
let debounceTimer;
123137

124-
// Prevent clicks on disabled links
125-
document.querySelectorAll('a[aria-disabled="true"]').forEach(link => {
126-
link.addEventListener('click', (e) => {
127-
e.preventDefault();
128-
e.stopPropagation();
129-
});
138+
document.addEventListener('keydown', function(e) {
139+
if (e.key === 'Escape') {
140+
if (searchInput) {
141+
searchInput.focus();
142+
searchInput.select();
143+
}
144+
}
130145
});
131146

132-
// Detect OS and update shortcut key
133-
const isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0;
134-
if (isMac) {
135-
document.getElementById('shortcut-key').textContent = '⌘';
136-
} else {
137-
document.getElementById('shortcut-key').textContent = 'Ctrl';
147+
// Debounce function
148+
function debounce(func, delay) {
149+
return function() {
150+
const context = this;
151+
const args = arguments;
152+
clearTimeout(debounceTimer);
153+
debounceTimer = setTimeout(() => func.apply(context, args), delay);
154+
};
138155
}
139156

140-
// Search functionality
141-
document.addEventListener('DOMContentLoaded', function() {
142-
const searchInput = document.querySelector('input[name="query"]');
143-
const suggestionsDiv = document.getElementById('suggestions');
144-
let debounceTimer;
145-
146-
// Handle keyboard shortcut
147-
document.addEventListener('keydown', function(e) {
148-
// Check for Cmd+K (Mac) or Ctrl+K (Windows/Linux)
149-
if ((e.metaKey || e.ctrlKey) && e.key === 'k') {
150-
e.preventDefault();
151-
searchInput.focus();
152-
}
153-
});
154-
155-
// Debounce function
156-
function debounce(func, delay) {
157-
return function() {
158-
const context = this;
159-
const args = arguments;
160-
clearTimeout(debounceTimer);
161-
debounceTimer = setTimeout(() => func.apply(context, args), delay);
162-
};
157+
// Fetch suggestions
158+
async function fetchSuggestions(query) {
159+
if (!query) {
160+
suggestionsDiv.classList.add('hidden');
161+
return;
163162
}
164163

165-
// Fetch suggestions
166-
async function fetchSuggestions(query) {
167-
if (!query) {
168-
suggestionsDiv.classList.add('hidden');
169-
return;
170-
}
171-
172-
try {
173-
const response = await fetch(`{{ suggest_api_url }}?query=${encodeURIComponent(query)}&language={{ language }}`);
174-
const suggestions = await response.json();
175-
176-
if (suggestions.length > 0) {
177-
const limitedSuggestions = suggestions.slice(0, 5);
178-
const hasMore = suggestions.length > 5;
179-
180-
suggestionsDiv.innerHTML = `
181-
${limitedSuggestions.map(suggestion => `
182-
<div class="p-2 cursor-pointer transition-colors duration-150 hover-row" onclick="selectSuggestion('${suggestion.label}')" style="color: var(--text-color)">
183-
${suggestion.label}
184-
</div>
185-
`).join('')}
186-
${hasMore ? `
187-
<div class="p-2 text-sm text-center border-t" style="color: var(--text-secondary); border-color: var(--border-color)">
188-
+${suggestions.length - 5} more results
189-
</div>
190-
` : ''}
191-
`;
192-
suggestionsDiv.classList.remove('hidden');
193-
} else {
194-
suggestionsDiv.classList.add('hidden');
195-
}
196-
} catch (error) {
197-
console.error('Error fetching suggestions:', error);
164+
try {
165+
const response = await fetch(`{{ suggest_api_url }}?query=${encodeURIComponent(query)}&language={{ language }}`);
166+
const suggestions = await response.json();
167+
168+
if (suggestions.length > 0) {
169+
const limitedSuggestions = suggestions.slice(0, 5);
170+
const hasMore = suggestions.length > 5;
171+
172+
suggestionsDiv.innerHTML = `
173+
${limitedSuggestions.map(suggestion => `
174+
<div class="p-2 cursor-pointer transition-colors duration-150 hover-row" onclick="selectSuggestion('${suggestion.label}')" style="color: var(--text-color)">
175+
${suggestion.label}
176+
</div>
177+
`).join('')}
178+
${hasMore ? `
179+
<div class="p-2 text-sm text-center border-t" style="color: var(--text-secondary); border-color: var(--border-color)">
180+
+${suggestions.length - 5} more results
181+
</div>
182+
` : ''}
183+
`;
184+
suggestionsDiv.classList.remove('hidden');
185+
} else {
198186
suggestionsDiv.classList.add('hidden');
199187
}
188+
} catch (error) {
189+
console.error('Error fetching suggestions:', error);
190+
suggestionsDiv.classList.add('hidden');
200191
}
192+
}
201193

202-
// Handle input with debounce
203-
searchInput.addEventListener('input', debounce(function(e) {
204-
fetchSuggestions(e.target.value);
205-
}, 300));
206-
207-
// Handle suggestion selection
208-
window.selectSuggestion = function(suggestion) {
209-
searchInput.value = suggestion;
194+
// Handle input with debounce
195+
searchInput.addEventListener('input', debounce(function(e) {
196+
fetchSuggestions(e.target.value);
197+
}, 300));
198+
199+
// Handle suggestion selection
200+
window.selectSuggestion = function(suggestion) {
201+
searchInput.value = suggestion;
202+
suggestionsDiv.classList.add('hidden');
203+
document.getElementById('searchForm').submit();
204+
};
205+
206+
// Close suggestions when clicking outside
207+
document.addEventListener('click', function(e) {
208+
if (!searchInput.contains(e.target) && !suggestionsDiv.contains(e.target)) {
210209
suggestionsDiv.classList.add('hidden');
211-
document.getElementById('searchForm').submit();
212-
};
213-
214-
// Close suggestions when clicking outside
215-
document.addEventListener('click', function(e) {
216-
if (!searchInput.contains(e.target) && !suggestionsDiv.contains(e.target)) {
217-
suggestionsDiv.classList.add('hidden');
218-
}
219-
});
210+
}
220211
});
221212
});
222213
</script>

src/py_semantic_taxonomy/adapters/routers/templates/search.html

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -91,17 +91,6 @@ <h3 class="text-lg font-medium mb-2" style="color: var(--text-color)">Start sear
9191
fetchConceptDetails(iri, element.id);
9292
});
9393

94-
// Handle escape key to clear search
95-
document.addEventListener('keydown', function(e) {
96-
if (e.key === 'Escape') {
97-
const searchInput = document.querySelector('input[name="query"]');
98-
if (searchInput) {
99-
searchInput.value = '';
100-
searchInput.focus();
101-
}
102-
}
103-
});
104-
10594
// Fetch concept details
10695
async function fetchConceptDetails(iri, elementId) {
10796
try {

0 commit comments

Comments
 (0)