Skip to content

Fix: Replace CSS :has() with closest() for browser compatibility#141

Merged
parhumm merged 2 commits intodevelopmentfrom
fix/issue-139-css-has-selector-crash
Mar 9, 2026
Merged

Fix: Replace CSS :has() with closest() for browser compatibility#141
parhumm merged 2 commits intodevelopmentfrom
fix/issue-139-css-has-selector-crash

Conversation

@ParhamTehrani
Copy link
Copy Markdown
Contributor

@ParhamTehrani ParhamTehrani commented Mar 9, 2026

Close #139 - Charts were crashing in older browsers (Firefox <121, older Chrome/Safari/Edge) because the :has() pseudo-class is not supported. Using querySelector with :has() throws errors in unsupported browsers, causing chart rendering failures.

Changes:

  • Replace querySelector(".inside:has(#chart)") with closest(".inside")
  • Replace querySelector(".chart-wrap:has(#chart)") with closest()
  • Add null checks before DOM manipulations to prevent TypeErrors

Describe your changes

...

Submission Review Guidelines:

  • I have performed a self-review of my code
  • If it is a core feature, I have added thorough tests.
  • Will this be part of a product update? If yes, please write one phrase about this update.
  • I have reviewed my code for security best practices.
  • Following the above guidelines will result in quick merges and clear and detailed feedback when appropriate.
  • My code follows the style guidelines of this project
  • I have updated the change-log in CHANGELOG.md.

Type of change

  • Fix - Fixes an existing bug
  • Add - Adds functionality
  • Update - Update existing functionality
  • Dev - Development related task
  • Tweak - A minor adjustment to the codebase
  • Performance - Address performance issues
  • Enhancement - Improvement to existing functionality

Summary by CodeRabbit

  • Bug Fixes
    • Improved chart rendering reliability: charts now consistently show or hide correctly, with better handling of missing chart containers and clearer diagnostic warnings when charts cannot be displayed; loading indicators reliably attach to the chart area during data fetches.

Resolves #139 - Charts were crashing in older browsers (Firefox <121,
older Chrome/Safari/Edge) because the :has() pseudo-class is not
supported. Using querySelector with :has() throws errors in
unsupported browsers, causing chart rendering failures.

Changes:
- Replace querySelector(".inside:has(#chart)") with closest(".inside")
- Replace querySelector(".chart-wrap:has(#chart)") with closest()
- Add null checks before DOM manipulations to prevent TypeErrors
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 9, 2026

📝 Walkthrough

Walkthrough

Replaced CSS :has() selectors with element lookups and closest() traversals in fetchChartData(), added null checks, and switched style.display manipulations to operate on resolved chart wrapper elements. Logs a warning and aborts when required DOM containers are not found.

Changes

Cohort / File(s) Summary
Chart DOM Navigation Fix
admin/assets/js/slimstat-chart.js
Replaced .querySelector(...:has(...)) usage with document.getElementById() + closest() for .inside and .slimstat-chart-wrap. Added guards to abort and console.warn() if elements are missing. Replaced selector-based show/hide with direct chartWrap.style.display updates and targeted loading indicator insertion/removal.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 A selector too new caused charts to fall,
:has() tripped up and couldn't answer the call.
I hopped in with closest() and checks so neat,
Now loading spinners land and charts can greet,
Hooray — dashboards hum and metrics stand tall! 📊✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The PR title accurately describes the main change: replacing CSS :has() selectors with closest() for better browser compatibility.
Linked Issues check ✅ Passed The PR addresses all requirements from issue #139: replaces :has()-based selectors with closest(), adds null checks before DOM operations, and prevents crashes in unsupported browsers.
Out of Scope Changes check ✅ Passed All changes in admin/assets/js/slimstat-chart.js are directly related to resolving issue #139; no unrelated modifications detected.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/issue-139-css-has-selector-crash

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.

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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@admin/assets/js/slimstat-chart.js`:
- Around line 88-90: Remove the browser console warning in slimstat-chart.js:
when the guard (if (!inside || !chartWrap)) triggers for chartId, delete the
console.warn(...) call and instead either call the project's logging utility
(use the existing project logger function if available) or wrap the message
behind a non-production / debug flag so no console output appears in shipped JS;
keep the early return behavior unchanged to preserve flow when inside or
chartWrap are missing.
- Around line 82-91: In fetchChartData(), guard the DOM lookup for the data node
before dereferencing it: check the result of
document.getElementById("slimstat_chart_data_" + chartId) (the variable element)
and bail out (console.warn and return) if it's null/undefined instead of calling
element.getAttribute and JSON.parse immediately; move the JSON.parse of
element.getAttribute("data-args") to after that null check and ensure subsequent
uses of chartCanvas/inside/chartWrap remain unchanged so a missing
`#slimstat_chart_data_`<chartId> fails gracefully.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b6ecd3af-bed8-483f-b3a4-0dc4a2ed9199

📥 Commits

Reviewing files that changed from the base of the PR and between a756e42 and 49782b7.

📒 Files selected for processing (1)
  • admin/assets/js/slimstat-chart.js

Comment on lines +88 to +90
if (!inside || !chartWrap) {
console.warn("SlimStat: Could not find chart container elements for chart " + chartId);
return;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Remove the new browser-console warning from shipped code.

If you want to keep this signal, route it through a project logger or a non-production-only path instead of writing to the browser console.

Suggested fix
         if (!inside || !chartWrap) {
-            console.warn("SlimStat: Could not find chart container elements for chart " + chartId);
             return;
         }

As per coding guidelines, **/*.js: Do not include var_dump(), console.log(), or debug code in shipped JavaScript; remove before release.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (!inside || !chartWrap) {
console.warn("SlimStat: Could not find chart container elements for chart " + chartId);
return;
if (!inside || !chartWrap) {
return;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@admin/assets/js/slimstat-chart.js` around lines 88 - 90, Remove the browser
console warning in slimstat-chart.js: when the guard (if (!inside ||
!chartWrap)) triggers for chartId, delete the console.warn(...) call and instead
either call the project's logging utility (use the existing project logger
function if available) or wrap the message behind a non-production / debug flag
so no console output appears in shipped JS; keep the early return behavior
unchanged to preserve flow when inside or chartWrap are missing.

@parhumm
Copy link
Copy Markdown
Contributor

parhumm commented Mar 9, 2026

Review note from manual pass:

  • Potential UI lock on failed requests (admin/assets/js/slimstat-chart.js, around lines 106-155): loadingIndicator is appended and chartWrap is hidden before XHR starts, but on !result.success and non-200 responses the function returns/logs without restoring the chart or removing the spinner.
  • This is likely pre-existing behavior, but still present in the updated path and user-visible when requests fail/intermittently timeout.

Suggestion: move hide/show + spinner cleanup into a shared helper (or a finally-style branch) so both success and failure paths restore UI state.

@parhumm
Copy link
Copy Markdown
Contributor

parhumm commented Mar 9, 2026

Human QA Checklist for PR #141 (:has() -> closest() compatibility fix)

Test Environment

  • WP Slimstat branch from this PR is installed and activated
  • Test data exists so charts render (Slimstat dashboard has chart widgets)
  • Browser matrix prepared:
    • Modern browser (latest Chrome/Firefox/Safari/Edge)
    • Older browser without :has() support (example: Firefox 120 or older)

Core Functional Checks

  • Open Slimstat dashboard with charts; confirm charts render on initial load
  • For each visible chart, change granularity (e.g. Daily -> Weekly -> Monthly)
  • Confirm chart updates successfully after each change
  • Confirm loading indicator appears during fetch and disappears after update
  • Confirm chart container is hidden while loading and shown again after update

Compatibility Checks (Main Purpose of PR)

  • In older browser, repeat granularity changes and confirm no JS crash
  • DevTools console has no selector syntax errors related to :has(
  • DevTools console has no TypeError from null DOM access (appendChild, removeChild, .style)

Regression Checks

  • Multi-chart screen: changing one chart updates only that chart area
  • Legend/labels/tooltips still render correctly after refresh
  • No visual regressions in chart wrapper layout after multiple refreshes
  • Rapidly toggle granularity 5-10 times; UI remains stable and responsive

Resilience / Failure Handling

  • Simulate request failure (offline mode or blocked admin-ajax.php) during refresh
  • Confirm behavior is acceptable and chart UI recovers (no permanently hidden chart/spinner)

Evidence to Attach in QA Result

  • Browser/version used for each run
  • Short video or screenshots for one successful refresh in old + modern browser
  • Console capture for old browser run (showing no :has()/null errors)
  • Pass/Fail per checklist item with reproduction notes for any failures

If helpful, I can also convert this into a compact QA report template for final sign-off.

@parhumm parhumm merged commit 181c47d into development Mar 9, 2026
1 check passed
@parhumm parhumm deleted the fix/issue-139-css-has-selector-crash branch March 9, 2026 10:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants