Skip to content

fix: route WooCommerce order row clicks to separate windows. - #1030

Merged
epeicher merged 6 commits into
WordPress:trunkfrom
KarunyaChavan:fix/wc-orders-row-click-navigation
Nov 4, 2026
Merged

epeicher merged 6 commits into
WordPress:trunkfrom
KarunyaChavan:fix/wc-orders-row-click-navigation

Conversation

@KarunyaChavan

@KarunyaChavan KarunyaChavan commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

This PR fixes an issue where clicking anywhere on a WooCommerce order table row outside of the primary order number link (such as on the date, order status badge, order total, or empty cell whitespace) caused the order to open inside the current Orders list window instead of in a separate window.

See #1022

What was Happening ?

  • WooCommerce's wc-orders.js binds a row-level delegated click handler that assigns window.location = href, which previously bypassed OpenStation's anchor interceptor and wiped out the Orders list context in place.
  • This change intercepts row clicks on WooCommerce order tables in the capture phase, halts event bubbling to prevent in-page navigation, and routes the order URL through the parent shell so that orders consistently open in their own dedicated window beside the list.

What Changed ?

  • src/chromeless-bridge.js:

    • Added resolveOrderRowLink(): Introduced a helper that maps clicks on non-anchor order row cells to the row's primary order edit link (a.order-view, .column-order_number a).
    • Scoped strictly to WooCommerce order tables: Guarded row link resolution by verifying the click originates within WooCommerce HPOS or legacy CPT order tables (.woocommerce_page_wc-orders table, .post-type-shop_order table, or table.wc-orders-list-table), preventing false positives on unrelated admin list tables.
    • Excluded interactive controls and text selections: Explicitly ignores clicks on checkboxes, form controls, order preview modal toggles (.order-preview), the actions column (.wc_actions), and active user text selections.
    • Suppressed in-page row navigation: Added e.stopPropagation() and e.stopImmediatePropagation() alongside e.preventDefault() when claiming admin links so WooCommerce's bubble-phase handler cannot execute window.location = href.
  • tests/vitest/chromeless-bridge-links.test.ts:

    • Added unit tests asserting that clicks on non-anchor elements (<time>, <mark>, <span>) in an order row dispatch os-iframe-admin-link to open the order in a new window.
    • Verified that clicking row checkboxes, preview buttons, and action buttons does not trigger order navigation.
    • Added test cases for both HPOS tables and non-order tables (verifying tables with order-number-like columns are ignored).
    • Verified that claimed navigation halts event propagation to in-page DOM listeners.
  • docs/plugin-compat-layer.md:

    • Documented WooCommerce's row-click navigation quirk in wc-orders.js and how OpenStation resolves it in the compatibility layer.

3) Steps for Testing

Open OpenStation and launch the WooCommerce > Orders window:

  • Direct link click: Click on the order number/customer name (#1042 John Doe) - verify that the single order opens in a new window beside the list.
  • Row whitespace & text clicks: Click anywhere else on the row (the date text, the status badge, the total amount, or empty cell padding) - verify that the single order still opens in a new window rather than replacing the Orders list window in place.
  • Checkbox click: Click the bulk selection checkbox for an order row - verify that the checkbox toggles without opening any window.
  • Preview button click: Click the eye/preview icon inside the order number column - verify that the in-page order preview modal opens without triggering a new window.
  • Actions column: Click buttons in the actions column (if enabled) - verify that it performs the intended row action rather than opening the main order view.

Use of AI:

  • Tool Used: Antigravity
  • Model Used: Gemini 3.8 Flash
  • Used for: Confirming the root cause and adding automated tests for updated patch.
Open WordPress Playground Preview

- WooCommerce's `wc-orders.js` binds a row-level click handler on order list tables (`admin.php?page=wc-orders` and `edit.php?post_type=shop_order`) that assigns `window.location = href` when clicking non-anchor cells (date, status, total, whitespace). In OpenStation, that in-place navigation replaces the Orders list window with the single order view, losing the list context.
- Add `resolveOrderRowLink()` to intercept row clicks in the capture phase and route the destination through `os-iframe-admin-link` so the order opens in its own window beside the list. Explicitly exclude `.order-preview` when resolving the order link so the preceding modal preview button inside `.column-order_number` is not selected over `a.order-view`.
- Halt event bubbling and prevent competing document handlers with `preventDefault()`, `stopPropagation()`, and `stopImmediatePropagation()`.
Add test coverage for row-level click interception in WooCommerce order tables:
- Verify clicks on non-anchor cells (<time>, <mark>, <span>) resolve the order view link and dispatch `os-iframe-admin-link` with proper labels.
- Verify interactive controls (bulk checkboxes, preview modal buttons) are ignored by the row interceptor.
- Verify realistic HPOS table markup where `<a class="order-preview">` precedes `<a class="order-view">` in `.column-order_number`.
- Verify non-order list tables (such as posts) are not intercepted.
- Verify claimed navigation halts propagation to in-page listeners.
- Document the row-click navigation quirk in WooCommerce's `wc-orders.js` and how `resolveOrderRowLink()` in `src/chromeless-bridge.js` intercepts non-anchor clicks to open orders in separate windows beside the list.
@KarunyaChavan
KarunyaChavan marked this pull request as ready for review October 20, 2026 14:22
@epeicher

Copy link
Copy Markdown
Collaborator

Thanks a lot @KarunyaChavan, great digging into wc-orders.js to find why only some clicks escaped the window. I tested it with real orders: clicking a total now opens the order in its own window and the list stays put. 🙌

Two things before merging. First, clicking a header cell that isn't a link (e.g. "Status") now re-sorts the list. resolveOrderRowLink() uses closest( 'tr' ) without limiting it to tbody, so the header row resolves to the Order column's sort link (L1384-L1388). Using WooCommerce's own selector and target avoids it:

var cell = target.closest( '.post-type-shop_order .wp-list-table tbody td, .woocommerce_page_wc-orders .wp-list-table.orders tbody td' );
var view = cell && cell.closest( 'tr' ).querySelector( 'a.order-view' );

Second, the new stopPropagation() / stopImmediatePropagation() calls run for every admin and external link in every window (L1643, L1707, L1739). That would silence other plugins' click handlers on ordinary links. Could they apply only when the click came from an order row?

…gation

- Scope order row cell lookup to tbody (both td and th) across HPOS and
  legacy CPT tables so non-link header clicks (e.g. Status) do not match
  the header row or resolve the column sort link.
- Query strictly for `a.order-view`, matching WooCommerce's own handler.
- Support clicking whitespace and small-screen elements in the primary
  th (`th.column-order_number`), while ignoring the responsive `.toggle-row`
  button.
- Limit `stopPropagation()` and `stopImmediatePropagation()` strictly to
  claimed order row clicks (`isOrderRowClick`), allowing ordinary admin,
  other-admin, and external links to bubble to in-page listeners.
- Add test coverage for header clicks, primary th clicks, and event
  propagation isolation.
@KarunyaChavan

Copy link
Copy Markdown
Contributor Author

Thank you for the review @epeicher 🙇

I've updated the row lookup to target only tbody cells and WooCommerce's order-view link, preventing header clicks from triggering sorting. I've also limited event propagation blocking to actual order row clicks so other links behave normally.

…rks now

Quote WooCommerce's real selectors (body td and th on both list tables),
list every control the interceptor yields to, note that header cells are
never claimed and that only a claimed row click stops propagation, and
say that table.wc-orders-list-table also reaches other HPOS order types'
lists.

@epeicher epeicher left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks @KarunyaChavan for addressing the comments! I have added a small commit to update the docs and reviewed the changes. They LGTM!

@epeicher
epeicher merged commit ad84a05 into WordPress:trunk Nov 4, 2026
7 checks passed
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