Skip to content

fix: handle null activeElement in _spaceCatcher AND fix: guard _moveManual and _ariaChecked against dom-repeat race AND MORE#51

Merged
paodb merged 6 commits intomasterfrom
fix-49-50
May 7, 2026
Merged

fix: handle null activeElement in _spaceCatcher AND fix: guard _moveManual and _ariaChecked against dom-repeat race AND MORE#51
paodb merged 6 commits intomasterfrom
fix-49-50

Conversation

@javier-godoy
Copy link
Copy Markdown
Member

@javier-godoy javier-godoy commented May 6, 2026

Close #49
Close #50

Summary by CodeRabbit

  • Bug Fixes

    • Dot navigation now follows the actually rendered dots to prevent off-by-one and out-of-bounds navigation.
    • Click handling consolidated to a single delegated listener and cleaned up on detach to avoid duplicate handlers or leaks.
    • Dot-related styles are only initialized when dots exist.
  • Accessibility

    • Dot controls expose accurate aria-checked states and per-dot aria-labels.
    • Keyboard/focus detection for advancing slides improved.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 6, 2026

Review Change Stack

Walkthrough

Iterate and initialize slider dots using actual rendered dot elements; replace per-dot click handlers with a single delegated listener stored on the component; use shadowRoot.activeElement safely for keyboard activation, and remove the delegated listener on detach.

Changes

Dot navigation & keyboard handling

Layer / File(s) Summary
Data Shape / DOM discovery
src/.../paper-slider/l2t-paper-slider.js
Switch iteration bounds to use actual dotElems.length (querySelectorAll result) instead of this.totalSlides.
Core Wiring / Click handlers
src/.../paper-slider/l2t-paper-slider.js
Set per-dot aria-label by iterating rendered dots; install a single delegated click listener stored on this._dotClickListener; initialize _dotStyles only when dots exist.
Keyboard / Focus routing
src/.../paper-slider/l2t-paper-slider.js
Use this.shadowRoot.activeElement directly to read aria-posinset and call movePos when present; otherwise advance using (position + 1) % this.totalSlides.
Teardown / Cleanup
src/.../paper-slider/l2t-paper-slider.js
Remove the delegated dot click listener on detached and clear the stored listener reference.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • paodb
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title is overly long and uses 'AND MORE' which is vague, making it unclear what the primary change is despite referencing specific issue fixes. Shorten the title to focus on the main fix (e.g., 'fix: handle null activeElement and dom-repeat race conditions in slider'). Avoid vague terms like 'AND MORE'.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed The code changes address the null-access guards in _spaceCatcher and dom-repeat race conditions in _moveManual and _ariaChecked as required by issues #49 and #50.
Out of Scope Changes check ✅ Passed All changes focus on fixing null-access and race condition issues in the slider component's _spaceCatcher, _moveManual, and _ariaChecked methods, directly aligned with issues #49 and #50.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix-49-50

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@javier-godoy
Copy link
Copy Markdown
Member Author

@coderabbitai full review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 6, 2026

✅ Actions performed

Full review triggered.

@paodb
Copy link
Copy Markdown
Member

paodb commented May 6, 2026

@coderabbitai full review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 6, 2026

✅ Actions performed

Full review triggered.

@javier-godoy
Copy link
Copy Markdown
Member Author

@coderabbitai full review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 7, 2026

✅ Actions performed

Full review triggered.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/main/resources/META-INF/resources/frontend/paper-slider/l2t-paper-slider.js (1)

372-380: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

_ariaChecked: out-of-bounds access when this.position >= dotElems.length

The guard if (dotElems.length > 0) only ensures at least one dot exists, but Line 378 still unconditionally accesses dotElems[this.position]. During a dom-repeat race (which is exactly what this PR aims to fix), this.position can be greater than the number of rendered dots, causing an uncaught TypeError: Cannot read properties of undefined.

🛡️ Proposed fix
  _ariaChecked: function () {
    var dotElems = this.$.container.querySelectorAll('.slider__dot');
-   if (dotElems.length > 0) {
+   if (dotElems.length > 0 && this.position < dotElems.length) {
      for (var i = 0; i < dotElems.length; i++) {
        dotElems[i].setAttribute("aria-checked", "false");
      };
      dotElems[this.position].setAttribute("aria-checked", "true");
    }
  },
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/main/resources/META-INF/resources/frontend/paper-slider/l2t-paper-slider.js`
around lines 372 - 380, The _ariaChecked method can access
dotElems[this.position] out of bounds if this.position >= dotElems.length;
update _ariaChecked to verify bounds before accessing or setting the "true"
attribute (e.g., check this.position !== undefined && this.position >= 0 &&
this.position < dotElems.length or clamp this.position to dotElems.length - 1)
after you clear all dots; specifically modify the _ariaChecked function to only
call dotElems[this.position].setAttribute when the index is valid to avoid the
TypeError during dom-repeat races.
🧹 Nitpick comments (1)
src/main/resources/META-INF/resources/frontend/paper-slider/l2t-paper-slider.js (1)

375-377: 💤 Low value

SonarCloud warning: prefer for…of over index-based for loop

SonarCloud flags Lines 375-377 for using a for loop with a simple sequential iteration where for…of is idiomatic.

♻️ Proposed refactor
-     for (var i = 0; i < dotElems.length; i++) {
-       dotElems[i].setAttribute("aria-checked", "false");
-     };
-     dotElems[this.position].setAttribute("aria-checked", "true");
+     for (const dot of dotElems) {
+       dot.setAttribute("aria-checked", "false");
+     }
+     dotElems[this.position].setAttribute("aria-checked", "true");
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/main/resources/META-INF/resources/frontend/paper-slider/l2t-paper-slider.js`
around lines 375 - 377, Replace the index-based loop that clears aria-checked on
dotElems with a for...of iteration: locate the loop iterating over dotElems (the
block starting with "for (var i = 0; i < dotElems.length; i++)" in
l2t-paper-slider.js) and change it to use "for (const dotElem of dotElems) {
dotElem.setAttribute('aria-checked', 'false'); }" so the code uses the idiomatic
for…of construct while preserving the same behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@src/main/resources/META-INF/resources/frontend/paper-slider/l2t-paper-slider.js`:
- Around line 541-550: The _spaceCatcher function uses a legacy var and a raw
parseInt which SonarCloud flags; update the function to declare nextPos with
const or let (prefer const when not reassigned) and call parseInt with an
explicit radix (e.g., parseInt(nextPos, 10)) or use Number(nextPos) to convert,
and keep the existing logic that calls this.movePos(parseInt(nextPos, 10) - 1)
when shadowRoot.activeElement has an aria-posinset, otherwise
this.movePos((this.position + 1) % this.totalSlides); ensure you only change the
declaration and numeric conversion (nextPos, _spaceCatcher, movePos, position,
totalSlides) to satisfy SonarCloud.
- Around line 478-490: _moveManual currently adds anonymous click handlers to
each .slider__dot on every call, causing duplicate listeners; change it to
attach a single delegated click handler on this.$.container (or use a named
bound handler stored as this._dotClickHandler) that checks
event.target.classList.contains('slider__dot') (or aria-posinset) and calls
this.movePos(pos - 1); before adding the handler remove any existing one
(removeEventListener using this._dotClickHandler) or only add it once, and keep
setting aria-labels and this._dotStyles for the dots but do not attach per-dot
listeners.

---

Outside diff comments:
In
`@src/main/resources/META-INF/resources/frontend/paper-slider/l2t-paper-slider.js`:
- Around line 372-380: The _ariaChecked method can access
dotElems[this.position] out of bounds if this.position >= dotElems.length;
update _ariaChecked to verify bounds before accessing or setting the "true"
attribute (e.g., check this.position !== undefined && this.position >= 0 &&
this.position < dotElems.length or clamp this.position to dotElems.length - 1)
after you clear all dots; specifically modify the _ariaChecked function to only
call dotElems[this.position].setAttribute when the index is valid to avoid the
TypeError during dom-repeat races.

---

Nitpick comments:
In
`@src/main/resources/META-INF/resources/frontend/paper-slider/l2t-paper-slider.js`:
- Around line 375-377: Replace the index-based loop that clears aria-checked on
dotElems with a for...of iteration: locate the loop iterating over dotElems (the
block starting with "for (var i = 0; i < dotElems.length; i++)" in
l2t-paper-slider.js) and change it to use "for (const dotElem of dotElems) {
dotElem.setAttribute('aria-checked', 'false'); }" so the code uses the idiomatic
for…of construct while preserving the same behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: eeded5f8-7a76-48bf-aa86-9de6c59927be

📥 Commits

Reviewing files that changed from the base of the PR and between 47b7456 and 6893f6d.

📒 Files selected for processing (1)
  • src/main/resources/META-INF/resources/frontend/paper-slider/l2t-paper-slider.js

@javier-godoy javier-godoy changed the title fix: handle null activeElement in _spaceCatcher AND fix: guard _moveManual and _ariaChecked against dom-repeat race fix: handle null activeElement in _spaceCatcher AND fix: guard _moveManual and _ariaChecked against dom-repeat race AND MORE May 7, 2026
@javier-godoy
Copy link
Copy Markdown
Member Author

@coderabbitai full review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 7, 2026

✅ Actions performed

Full review triggered.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@src/main/resources/META-INF/resources/frontend/paper-slider/l2t-paper-slider.js`:
- Around line 487-490: Replace the use of "var dot" and the unsafe arithmetic
coercion in the delegated click handler _dotClickListener: declare the found
element with const (or let) instead of var, read the aria-posinset attribute
with Number.parseInt(dot.getAttribute('aria-posinset'), 10), check that the
parsed value is a finite number (not NaN) and only then call this.movePos(parsed
- 1); keep using e.target.closest('.slider__dot') and the existing movePos
method name to locate the fix.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c8c8f3bb-5cdd-4a76-8135-f2d47fc74198

📥 Commits

Reviewing files that changed from the base of the PR and between 47b7456 and d952872.

📒 Files selected for processing (1)
  • src/main/resources/META-INF/resources/frontend/paper-slider/l2t-paper-slider.js

@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented May 7, 2026

@paodb
Copy link
Copy Markdown
Member

paodb commented May 7, 2026

@coderabbitai full review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 7, 2026

✅ Actions performed

Full review triggered.

@javier-godoy
Copy link
Copy Markdown
Member Author

@coderabbitai full review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 7, 2026

✅ Actions performed

Full review triggered.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
src/main/resources/META-INF/resources/frontend/paper-slider/l2t-paper-slider.js (1)

487-490: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

_dotClickListener: isNaN guard still missing after partial fix.

Number.parseInt(dot.getAttribute('aria-posinset'), 10) - 1 passes NaN to movePos if the attribute is absent or non-numeric. The current code degrades gracefully (_moveInd(undefined) exits early), but the explicit isNaN guard from the proposed fix was not applied.

🛡️ Proposed fix
-        if (dot) this$.movePos(Number.parseInt(dot.getAttribute('aria-posinset'), 10) - 1);
+        if (dot) {
+          const pos = Number.parseInt(dot.getAttribute('aria-posinset'), 10);
+          if (!isNaN(pos)) this$.movePos(pos - 1);
+        }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/main/resources/META-INF/resources/frontend/paper-slider/l2t-paper-slider.js`
around lines 487 - 490, The click handler _dotClickListener currently passes NaN
to movePos when aria-posinset is missing or non-numeric; change it to parse the
attribute into a numeric index (use Number.parseInt or Number.parseInt(...,
10)), check with Number.isNaN (or !Number.isNaN) before computing "- 1" and only
call this$.movePos when the parsed index is a valid number; reference
_dotClickListener, the '.slider__dot' element, its 'aria-posinset' attribute,
and the movePos(...) call so the guard is applied before invoking movePos.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Duplicate comments:
In
`@src/main/resources/META-INF/resources/frontend/paper-slider/l2t-paper-slider.js`:
- Around line 487-490: The click handler _dotClickListener currently passes NaN
to movePos when aria-posinset is missing or non-numeric; change it to parse the
attribute into a numeric index (use Number.parseInt or Number.parseInt(...,
10)), check with Number.isNaN (or !Number.isNaN) before computing "- 1" and only
call this$.movePos when the parsed index is a valid number; reference
_dotClickListener, the '.slider__dot' element, its 'aria-posinset' attribute,
and the movePos(...) call so the guard is applied before invoking movePos.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 22729320-9e40-4337-8693-a38caa71f859

📥 Commits

Reviewing files that changed from the base of the PR and between 47b7456 and c2c9602.

📒 Files selected for processing (1)
  • src/main/resources/META-INF/resources/frontend/paper-slider/l2t-paper-slider.js

@javier-godoy javier-godoy marked this pull request as ready for review May 7, 2026 18:02
@paodb paodb merged commit bf44af2 into master May 7, 2026
5 checks passed
@paodb paodb deleted the fix-49-50 branch May 7, 2026 18:17
@github-project-automation github-project-automation Bot moved this from To Do to Pending release in Flowing Code Addons May 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Pending release

Development

Successfully merging this pull request may close these issues.

moveManual causes undefined setAttribute spaceCatcher causes null-access

2 participants