| 1 |
// Both Woo product loops, block and classic [products], mark tiles this way. |
| 2 |
const TILE = 'li.product[class*="post-"]'; |
| 3 |
const TITLE = '.wp-block-post-title, .woocommerce-loop-product__title'; |
| 4 |
const MAX_PRODUCTS = 50; |
| 5 |
|
| 6 |
const productId = (tile) => Number(tile.className.match(/\bpost-(\d+)\b/)?.[1]); |
| 7 |
|
| 8 |
const productTitle = (tile) => |
| 9 |
(tile.querySelector(TITLE) ?? tile.querySelector('a'))?.textContent?.trim() ?? |
| 10 |
''; |
| 11 |
|
| 12 |
const readPageProducts = () => { |
| 13 |
const byId = new Map(); |
| 14 |
for (const tile of document.querySelectorAll(TILE)) { |
| 15 |
const id = productId(tile); |
| 16 |
if (!id || byId.has(id)) continue; |
| 17 |
const title = productTitle(tile); |
| 18 |
// The model matches on the title, so an untitled id is unusable. |
| 19 |
if (!title) continue; |
| 20 |
byId.set(id, { id, title }); |
| 21 |
} |
| 22 |
return [...byId.values()].slice(0, MAX_PRODUCTS); |
| 23 |
}; |
| 24 |
|
| 25 |
export default { |
| 26 |
id: 'wp-ability:woocommerce', |
| 27 |
onStarted: () => { |
| 28 |
const products = readPageProducts(); |
| 29 |
// An earlier run's list must not outlive the grid it was read from. |
| 30 |
if (!products.length) { |
| 31 |
delete window.extAgentData.agentContext.pageProducts; |
| 32 |
return; |
| 33 |
} |
| 34 |
window.extAgentData.agentContext.pageProducts = products; |
| 35 |
}, |
| 36 |
}; |
| 37 |
|