diff --git a/.jules/bolt.md b/.jules/bolt.md index 341c7c9..78b53ea 100644 --- a/.jules/bolt.md +++ b/.jules/bolt.md @@ -67,3 +67,6 @@ ## 2025-02-12 - [Fast Path Execution in Directory Traversal and Log Parsing] **Learning:** Checking for string existence (`if "silence_" not in stderr`) before invoking regex matchers provides significant speed improvements when parsing large blocks of text. Similarly, moving expensive I/O operations like `os.path.realpath` inside conditional blocks prevents redundant disk access when configuration (like path exclusions) isn't utilized. **Action:** When working on large text processing or disk operations, verify if early exit conditions or conditional execution can bypass the expensive system or library calls. +## 2026-06-25 - [DOM Query and Parsing Optimization in Event Listeners] +**Learning:** Querying the DOM (e.g., `document.querySelectorAll`) and parsing attributes (e.g., `Number.parseInt(btn.dataset.bytes)`) inside frequent event listeners like `input` introduces unnecessary repeated processing overhead on every keystroke. +**Action:** Always precompute static values and cache NodeLists/Elements outside of frequent event handlers to improve client-side UI responsiveness. diff --git a/saas_web.py b/saas_web.py index 3a7b035..87d6aac 100644 --- a/saas_web.py +++ b/saas_web.py @@ -239,19 +239,25 @@ async def add_security_headers(request: Request, call_next): preview.innerText = 'Selected file size: ' + text; } + // Optimize: Cache DOM references and precompute button values outside the input event listener. + // This prevents repeating O(N) DOM traversal and string parsing on every keystroke. + const targetBytesPreview = document.getElementById('target_bytes_preview'); + const targetBytesButtons = Array.from(document.querySelectorAll('#preset_buttons_container .preset-btn')).map(btn => ({ + el: btn, + val: Number.parseInt(btn.dataset.bytes, 10) + })); + document.getElementById('target_bytes').addEventListener('input', function(e) { const val = parseInt(this.value, 10); - const preview = document.getElementById('target_bytes_preview'); + const preview = targetBytesPreview; this.setCustomValidity(''); this.removeAttribute('aria-invalid'); preview.style.color = '#1e7e34'; - const buttons = document.querySelectorAll('#preset_buttons_container .preset-btn'); - buttons.forEach(btn => { - const presetValue = Number.parseInt(btn.dataset.bytes, 10); - btn.setAttribute( + targetBytesButtons.forEach(btn => { + btn.el.setAttribute( 'aria-pressed', - !e.isTrusted && presetValue === val ? 'true' : 'false' + !e.isTrusted && btn.val === val ? 'true' : 'false' ); }); @@ -266,19 +272,25 @@ async def add_security_headers(request: Request, call_next): }); + // Optimize: Cache DOM references and precompute button values outside the input event listener. + // This prevents repeating O(N) DOM traversal and string parsing on every keystroke. + const batchTargetBytesPreview = document.getElementById('batch_target_bytes_preview'); + const batchTargetBytesButtons = Array.from(document.querySelectorAll('#batch_preset_buttons_container .preset-btn')).map(btn => ({ + el: btn, + val: Number.parseInt(btn.dataset.bytes, 10) + })); + document.getElementById('batch_target_bytes').addEventListener('input', function(e) { const val = parseInt(this.value, 10); - const preview = document.getElementById('batch_target_bytes_preview'); + const preview = batchTargetBytesPreview; this.setCustomValidity(''); this.removeAttribute('aria-invalid'); preview.style.color = '#1e7e34'; - const buttons = document.querySelectorAll('#batch_preset_buttons_container .preset-btn'); - buttons.forEach(btn => { - const presetValue = Number.parseInt(btn.dataset.bytes, 10); - btn.setAttribute( + batchTargetBytesButtons.forEach(btn => { + btn.el.setAttribute( 'aria-pressed', - !e.isTrusted && presetValue === val ? 'true' : 'false' + !e.isTrusted && btn.val === val ? 'true' : 'false' ); }); diff --git a/tests/test_saas_web.py b/tests/test_saas_web.py index 57b879d..ef92bc1 100644 --- a/tests/test_saas_web.py +++ b/tests/test_saas_web.py @@ -331,8 +331,8 @@ def test_get_ui_includes_preset_buttons(self): self.assertIn('aria-pressed="false"', html) self.assertIn('role="group" aria-label="Preset target sizes"', html) self.assertNotIn('onclick="setTargetBytes(', html) - self.assertIn("const presetValue = Number.parseInt(btn.dataset.bytes, 10);", html) - self.assertIn("!e.isTrusted && presetValue === val", html) + self.assertIn("val: Number.parseInt(btn.dataset.bytes, 10)", html) + self.assertIn("!e.isTrusted && btn.val === val", html) self.assertNotIn("btn.dataset.bytes === this.value", html)