|
23 | 23 |
|
24 | 24 | {% block content %} |
25 | 25 | <h3 style="margin: 0 0 8px 0;">{{ title }}</h3> |
26 | | -<form method="get" style="margin-bottom:10px; display:flex; gap:8px; align-items:center; flex-wrap: wrap;"> |
27 | | - {% if request.args.get('level') %} |
28 | | - <input type="hidden" name="level" value="{{ request.args.get('level') }}" /> |
29 | | - {% endif %} |
30 | | - <input name="q" class="input" type="text" placeholder="Search…" value="{{ q or '' }}" /> |
31 | | - <button class="btn" type="submit">Search</button> |
| 26 | +<div style="margin-bottom:10px; display:flex; gap:8px; align-items:center; flex-wrap: wrap; justify-content: space-between;"> |
| 27 | + <form method="get" style="display:flex; gap:8px; align-items:center; flex-wrap: wrap;"> |
| 28 | + {% if request.args.get('level') %} |
| 29 | + <input type="hidden" name="level" value="{{ request.args.get('level') }}" /> |
| 30 | + {% endif %} |
| 31 | + <input name="q" class="input" type="text" placeholder="Search…" value="{{ q or '' }}" /> |
| 32 | + <button class="btn" type="submit">Search</button> |
| 33 | + {% if current_tab == 'diffs' %} |
| 34 | + <label class="checkbox-label" style="display:flex;align-items:center;gap:6px;"> |
| 35 | + <input type="checkbox" name="smart" value="1" {% if smart_mode %}checked{% endif %} onchange="this.form.submit()" /> |
| 36 | + Smart Diff |
| 37 | + </label> |
| 38 | + {% endif %} |
| 39 | + {% if q %} |
| 40 | + <a class="btn secondary" href="{{ request.path }}">Clear</a> |
| 41 | + {% endif %} |
| 42 | + </form> |
32 | 43 | {% if current_tab == 'diffs' %} |
33 | | - <label class="checkbox-label" style="display:flex;align-items:center;gap:6px;"> |
34 | | - <input type="checkbox" name="smart" value="1" {% if smart_mode %}checked{% endif %} onchange="this.form.submit()" /> |
35 | | - Smart Diff |
| 44 | + <label style="display:flex;align-items:center;gap:6px;"> |
| 45 | + <span>Score Filter:</span> |
| 46 | + <input type="number" id="scoreFilterMin" class="input" placeholder="Min" step="0.001" min="0" max="1" style="width:80px;" oninput="filterByScore()" /> |
| 47 | + <span>to</span> |
| 48 | + <input type="number" id="scoreFilterMax" class="input" placeholder="Max" step="0.001" min="0" max="1" style="width:80px;" oninput="filterByScore()" /> |
36 | 49 | </label> |
37 | 50 | {% endif %} |
38 | | - {% if q %} |
39 | | - <a class="btn secondary" href="{{ request.path }}">Clear</a> |
40 | | - {% endif %} |
41 | | -</form> |
| 51 | +</div> |
42 | 52 | <table class="list-table" id="listTable"> |
43 | 53 | <thead> |
44 | 54 | <tr> |
@@ -238,6 +248,85 @@ <h3 style="margin: 0 0 8px 0;">{{ title }}</h3> |
238 | 248 | rows.sort((a,b)=> a.children[0].innerText.localeCompare(b.children[0].innerText)); |
239 | 249 | rows.forEach(r=>tbody.appendChild(r)); |
240 | 250 | } |
| 251 | + function filterByScore(){ |
| 252 | + const minInput = document.getElementById('scoreFilterMin'); |
| 253 | + const maxInput = document.getElementById('scoreFilterMax'); |
| 254 | + if (!minInput || !maxInput) return; // Filter inputs don't exist on this page |
| 255 | + |
| 256 | + const minValue = minInput.value === '' ? null : parseFloat(minInput.value); |
| 257 | + const maxValue = maxInput.value === '' ? null : parseFloat(maxInput.value); |
| 258 | + |
| 259 | + // Save filter values to localStorage |
| 260 | + const filterKey = 'diffrays_score_filter'; |
| 261 | + localStorage.setItem(filterKey, JSON.stringify({ |
| 262 | + min: minInput.value, |
| 263 | + max: maxInput.value |
| 264 | + })); |
| 265 | + |
| 266 | + const tbody = document.querySelector('#listTable tbody'); |
| 267 | + if (!tbody) return; |
| 268 | + |
| 269 | + const rows = Array.from(tbody.querySelectorAll('tr')); |
| 270 | + const theadCells = Array.from(document.querySelectorAll('#listTable thead th')); |
| 271 | + const scoreIdx = theadCells.findIndex(th => th.id === 'scoreHeader'); |
| 272 | + |
| 273 | + if (scoreIdx < 0) return; |
| 274 | + |
| 275 | + rows.forEach(row => { |
| 276 | + // Skip empty rows |
| 277 | + if (row.querySelector('.empty')) { |
| 278 | + row.style.display = ''; |
| 279 | + return; |
| 280 | + } |
| 281 | + |
| 282 | + const scoreCell = row.children[scoreIdx]; |
| 283 | + if (!scoreCell) { |
| 284 | + row.style.display = ''; |
| 285 | + return; |
| 286 | + } |
| 287 | + |
| 288 | + // Get the score value from data-score attribute |
| 289 | + const score = parseFloat(scoreCell.getAttribute('data-score')) || 0; |
| 290 | + |
| 291 | + // Check if it passes the filter |
| 292 | + let show = true; |
| 293 | + if (minValue !== null && score < minValue) { |
| 294 | + show = false; |
| 295 | + } |
| 296 | + if (maxValue !== null && score > maxValue) { |
| 297 | + show = false; |
| 298 | + } |
| 299 | + |
| 300 | + row.style.display = show ? '' : 'none'; |
| 301 | + }); |
| 302 | + } |
| 303 | + |
| 304 | + // Restore and apply filter on page load |
| 305 | + document.addEventListener('DOMContentLoaded', function() { |
| 306 | + const minInput = document.getElementById('scoreFilterMin'); |
| 307 | + const maxInput = document.getElementById('scoreFilterMax'); |
| 308 | + if (!minInput || !maxInput) return; |
| 309 | + |
| 310 | + // Restore filter values from localStorage |
| 311 | + const filterKey = 'diffrays_score_filter'; |
| 312 | + const saved = localStorage.getItem(filterKey); |
| 313 | + if (saved) { |
| 314 | + try { |
| 315 | + const filter = JSON.parse(saved); |
| 316 | + if (filter.min !== undefined && filter.min !== '') { |
| 317 | + minInput.value = filter.min; |
| 318 | + } |
| 319 | + if (filter.max !== undefined && filter.max !== '') { |
| 320 | + maxInput.value = filter.max; |
| 321 | + } |
| 322 | + } catch (e) { |
| 323 | + // Ignore parse errors |
| 324 | + } |
| 325 | + } |
| 326 | + |
| 327 | + // Apply the filter after restoring values |
| 328 | + filterByScore(); |
| 329 | + }); |
241 | 330 | </script> |
242 | 331 | {% endblock %} |
243 | 332 |
|
|
0 commit comments