MediaWiki:CRT Search.js: Difference between revisions
No edit summary |
No edit summary |
||
| Line 237: | Line 237: | ||
function buildHTML() { | function buildHTML() { | ||
var html = '<div class="crt-search-wrapper">'; | var html = '<div class="crt-search-wrapper">'; | ||
// Notification area for warnings/errors | |||
html += '<div class="crt-notifications" id="notifications"></div>'; | |||
// Mobile filter toggle | // Mobile filter toggle | ||
| Line 374: | Line 377: | ||
html += '</div>'; | html += '</div>'; | ||
return html; | return html; | ||
} | |||
/** | |||
* Show a notification message to the user | |||
* @param {string} message - The message to display | |||
* @param {string} type - 'error', 'warning', or 'info' | |||
* @param {number} duration - How long to show (0 = permanent until dismissed) | |||
*/ | |||
function showNotification(message, type, duration) { | |||
var container = document.getElementById('notifications'); | |||
if (!container) return; | |||
type = type || 'info'; | |||
duration = duration !== undefined ? duration : 8000; | |||
var notification = document.createElement('div'); | |||
notification.className = 'crt-notification crt-notification-' + type; | |||
var icon = type === 'error' ? '⚠️' : type === 'warning' ? '⚠️' : 'ℹ️'; | |||
notification.innerHTML = '<span class="crt-notification-icon">' + icon + '</span>' + | |||
'<span class="crt-notification-message">' + escapeHtml(message) + '</span>' + | |||
'<button class="crt-notification-close" title="Dismiss">×</button>'; | |||
notification.querySelector('.crt-notification-close').addEventListener('click', function() { | |||
notification.remove(); | |||
}); | |||
container.appendChild(notification); | |||
if (duration > 0) { | |||
setTimeout(function() { | |||
if (notification.parentNode) { | |||
notification.remove(); | |||
} | |||
}, duration); | |||
} | |||
} | |||
/** | |||
* Clear all notifications | |||
*/ | |||
function clearNotifications() { | |||
var container = document.getElementById('notifications'); | |||
if (container) { | |||
container.innerHTML = ''; | |||
} | |||
} | } | ||
| Line 697: | Line 746: | ||
*/ | */ | ||
function resetFilters() { | function resetFilters() { | ||
clearNotifications(); | |||
document.querySelectorAll('.crt-filter-select, .crt-filter-number').forEach(function(input) { | document.querySelectorAll('.crt-filter-select, .crt-filter-number').forEach(function(input) { | ||
input.value = ''; | input.value = ''; | ||
| Line 1,469: | Line 1,520: | ||
function parseURLParams() { | function parseURLParams() { | ||
var params = new URLSearchParams(window.location.search); | var params = new URLSearchParams(window.location.search); | ||
var invalidFilters = []; | |||
// No URL params to process (other than possibly 'title') | // No URL params to process (other than possibly 'title') | ||
| Line 1,504: | Line 1,556: | ||
} | } | ||
if (!filterConfig) return; | if (!filterConfig) { | ||
// Unknown filter parameter | |||
invalidFilters.push({ | |||
key: key, | |||
value: value, | |||
reason: 'Unknown filter "' + key + '"' | |||
}); | |||
return; | |||
} | |||
switch (filterConfig.type) { | switch (filterConfig.type) { | ||
| Line 1,517: | Line 1,577: | ||
select.value = value; | select.value = value; | ||
} else { | } else { | ||
invalidFilters.push({ | |||
key: key, | |||
value: value, | |||
reason: '"' + value + '" is not a valid option for ' + filterConfig.label | |||
}); | |||
} | } | ||
} | } | ||
| Line 1,557: | Line 1,621: | ||
} | } | ||
}); | }); | ||
// Show warnings for any invalid filters | |||
if (invalidFilters.length > 0) { | |||
invalidFilters.forEach(function(invalid) { | |||
showNotification(invalid.reason + '. This filter was ignored.', 'warning', 10000); | |||
}); | |||
} | |||
} | } | ||