# Sale price events

> The DOM events the AndOr sale price widget dispatches, with payload fields and a listener example, plus its data attributes and states.

Source: https://backtrackhq.com/docs/widgets/sale-price/events/

This page is for theme developers. The sale price host,
`<andor-price>`, dispatches three DOM events with `widgetType: "price"`.
Use them to react when a sale starts, ends or changes.

All events are `CustomEvent`s that bubble, so you can listen on
`document`.

## Events

| Event | Dispatched on | When |
|---|---|---|
| `andor:widget:mount` | the host | The first time the events script sees the widget |
| `andor:widget:unmount` | the host and `document` | The first check after the widget left the page |
| `andor:display:change` | the host | The widget's state changed since the last check |

Rules worth knowing:

- **No event on first paint.** The first check sends
  `andor:widget:mount` and stores the state silently. A change event is
  always a change from what the server drew.
- **Deduped.** If nothing in the state changed, nothing is sent.
- **Up to one second late.** The price hides at the exact moment a sale
  ends. The change event can arrive up to one second later. Treat it as
  a notification, not as the exact moment.
- **Variant switches** show up as an ordinary `andor:display:change`
  when the winning discount or price changes.

## Payloads

`andor:widget:mount` and `andor:widget:unmount`:

| Field | Value for this widget |
|---|---|
| `resource.widgetType` | `"price"` |
| `resource.widgetId` | The block id (`data-andor-widget-id`) |
| `resource.productId` | The numeric product id, or `null` |

`andor:display:change` has the same three fields, plus
`resource.previous` and `resource.current`. Each is a state object
(`previous` can be `null`):

| State field | Value for this widget |
|---|---|
| `discountId` | `data-best-id`, so it follows a winner change in the browser |
| `kind` | `data-andor-kind`, as drawn by the server. Not updated on a winner change |
| `mode` | `"price"` |
| `visible` | `true` while the price shows |
| `endsAt` | Always `null` on this widget |
| `priceCents` | Always `null` today |
| `originalCents` | `data-price`, the variant price in cents |

`endsAt` is always `null` here. To know when a sale ends, watch for
`visible` changing to `false`.

## Examples

Log when a sale price stops showing:

```js
document.addEventListener("andor:display:change", (event) => {
  const { widgetType, previous, current } = event.detail.resource;
  if (widgetType !== "price") return;
  if (previous?.visible && !current.visible) {
    console.log("sale price hidden for discount", previous.discountId);
  }
});
```

After you swap product markup with Ajax, call
`AndOrDisplay.refresh()` to re-price. See
[JavaScript API](https://backtrackhq.com/docs/developers/javascript-api/).

## Data attributes and states

| Attribute or class | On | Meaning |
|---|---|---|
| `data-andor-kind` | host | `percentage` or `amount_each` |
| `hidden` | host | no sale for this variant now |

For the attributes every widget shares, like `data-andor-state` and
`data-andor-progress`, see
[Data attributes and states](https://backtrackhq.com/docs/developers/data-attributes/).
