Open Application Platform Docs

Events and JavaScript API

What a widget tells the page, and how a page draws widgets itself.

Events

Every event is a CustomEvent dispatched on the widget and bubbling to the document; event.detail holds the data.

EventdetailWhen
swidget:ready { widget, type, transport, preview } The widget is drawn.
swidget:select { pickup_point } A pickup point was chosen.
swidget:quoted { quote } A price was received.
swidget:created { guest_order } | { order } An order was created (guest_order for a guest order, order for a signed-in order).
swidget:cancelled { guest_order } A guest shipment was cancelled.
swidget:payment { guest_order, pay_url } A payment link is ready (detail.pay_url). The page or app opens it; the widget never does.
swidget:sign-in-required {} The person must sign in (again). In an app, the app runs its own sign-in.
swidget:signed-in {} The visitor signed in in a signed-in order widget.
swidget:error { code, status, widget, retry_after, request_id } A call was refused or did not reach Superroute (see Errors).

window.sWidget

The runtime sets window.sWidget when it loads.

MemberMeaning
sWidget.versionThe runtime version, for example 0.2.0.
sWidget.mount(target, settings) → Promise<Element | null>Draws a widget into an element (or the element a CSS selector finds). Answers a promise of the widget element, or null when the widget cannot be drawn. A widget already drawn there is replaced.
sWidget.unmount(target) → booleanRemoves the widget drawn in the element. Form fields the widget filled stay.
sWidget.destroy()Removes every widget and stops watching the page for new snippets.
sWidget.scan()Draws every snippet on the page that is not drawn yet.
sWidget.on(name, handler) → off()Listens to a widget event (with or without the swidget: prefix) and answers a function that stops listening.

mount() settings

widget, key and client are required; the others match the script tag's data attributes.

await sWidget.mount('#pickup', {
  widget: 'k2m9x7q4ab1c',          // data-swidget
  key: 'sp_appkey_…',              // data-key
  client: '<client code>',        // data-client
  api: 'https://open.superroute.ca',
  locale: 'de',                    // data-locale
  theme: 'auto',                   // data-theme
  accent: '#0055AA',               // data-accent
  inputName: 'pickup_point_id',    // data-input-name
});
const off = sWidget.on('error', ({ code, status }) => console.log(code, status));

Example: React

// The script tag /swidget/swidget.js is on the page once; window.sWidget is then defined.
function PickupPoint({ onSelect }) {
  const ref = useRef(null);
  useEffect(() => {
    window.sWidget.mount(ref.current, { widget: 'k2m9x7q4ab1c', key: 'sp_appkey_…', client: '<client code>', api: 'https://open.superroute.ca' });
    const off = window.sWidget.on('select', ({ pickup_point }) => onSelect(pickup_point));
    return () => { off(); window.sWidget.unmount(ref.current); };
  }, []);
  return <div ref={ref} />;
}
// The ES module of the same version exports the same API without drawing anything on import.
import { mount, unmount, on, defineWidgetElements } from 'https://<host>/swidget/swidget.esm.js';
defineWidgetElements();
await mount(document.querySelector('#quote'), { widget: '…', key: '…', client: '…', api: 'https://open.superroute.ca' });

Back office and designer preview

Both run in the Superroute back office only. A website uses the widget key.

Staff widgets (session transport)

Staff widgets run with transport: 'session'. Every call is a POST to /staff-widgets/{widget}/call/{operation} on the person's own back-office session, with the page's CSRF token. The page holds no key and no token, and the configuration comes inline with the page.

await mount(element, { transport: 'session', widget: '12', config: inlineConfig, csrf: token });

Designer preview

The designer draws the unsaved draft with the widget's key, a preview ticket and the draft's hash (preview, draftHash, draft). The ticket only reads: a write answers preview_read_only, and the widget shows a sample answer marked Preview instead.

await mount(element, { widget, key, client, api, preview: ticket, draftHash, draft });