diff --git a/index.html b/index.html
index 1a12cf4..b7adadc 100644
--- a/index.html
+++ b/index.html
@@ -10,6 +10,9 @@
@@ -33,7 +36,10 @@
// Fetch services.xml and render the service cards with logos.
(async function(){
const grid = document.getElementById('services-grid');
+ const searchInput = document.getElementById('search-input');
const host = window.location.hostname;
+ let allServices = []; // Store all service elements for filtering
+
try{
const res = await fetch('/services.xml', {cache: 'no-cache'});
if(!res.ok){ throw new Error('Failed to load services.xml'); }
@@ -81,6 +87,7 @@
a.href = href;
a.target = '_blank';
a.rel = 'noreferrer';
+ a.dataset.serviceName = name.toLowerCase(); // For search filtering
const img = document.createElement('img');
img.className = 'logo';
@@ -93,8 +100,59 @@
a.appendChild(img);
a.appendChild(span);
+
+ // Add info button if both hostname and port are available
+ if((hostAttr || host) && port){
+ const infoBtn = document.createElement('button');
+ infoBtn.className = 'info-btn';
+ infoBtn.title = 'Connection details';
+ infoBtn.innerHTML = 'ⓘ';
+ infoBtn.onclick = (e) => {
+ e.preventDefault();
+ e.stopPropagation();
+ const displayHost = hostAttr || host;
+ const details = `Service: ${name}\nHost: ${displayHost}\nPort: ${port}\nProtocol: ${proto}`;
+ alert(details);
+ };
+ a.appendChild(infoBtn);
+ }
+
grid.appendChild(a);
+ allServices.push(a);
});
+
+ // Search functionality
+ searchInput.addEventListener('input', (e) => {
+ const searchTerm = e.target.value.toLowerCase().trim();
+ let visibleCount = 0;
+ allServices.forEach(card => {
+ const serviceName = card.dataset.serviceName;
+ if(serviceName.includes(searchTerm)){
+ card.style.display = '';
+ visibleCount++;
+ } else {
+ card.style.display = 'none';
+ }
+ });
+ // Show message if no results
+ const existingMsg = grid.querySelector('.no-results');
+ if(existingMsg) existingMsg.remove();
+ if(visibleCount === 0 && searchTerm !== ''){
+ const msg = document.createElement('p');
+ msg.className = 'notes no-results';
+ msg.textContent = `No services found matching "${e.target.value}"`;
+ grid.appendChild(msg);
+ }
+ });
+
+ // Focus search on '/' key
+ document.addEventListener('keydown', (e) => {
+ if(e.key === '/' && document.activeElement !== searchInput){
+ e.preventDefault();
+ searchInput.focus();
+ }
+ });
+
}catch(err){
console.error(err);
grid.innerHTML = 'Error loading services.xml — see console for details.
';