The Addofy JavaScript API (window.adba)
Load your script with the dependency adba-core, then use window.adba. Full TypeScript types are in docs/adba.d.ts in the plugin.
adba.boot( 'myplugin', () => {
adba.commands.register( { id: 'myplugin-report', label: 'Open report', run: () => location.assign( '/wp-admin/admin.php?page=myplugin' ) } );
adba.shortcuts.register( { id: 'myplugin-report', keys: 'g r', label: 'Go to the report', handler: () => location.assign( '/wp-admin/admin.php?page=myplugin' ) } );
adba.notices.add( { id: 'myplugin-sync', level: 'success', text: 'Sync done.', source: 'myplugin' } );
} );
adba.on( 'module:ready', ( { id } ) => console.log( 'started', id ) );
adba.boot() isolates errors: a failing entry is logged with its id. It fires module:ready when the entry started without errors.
Loading
Since 1.4.0 the admin loads one script for core and the modules that run on every screen (core/global.js). Parts that are only needed on interaction load on first use: the palette UI, the drawer, the notice panel, section tabs and the save bar, the Help rows and adba.api.document().
The API stays the same. adba.drawer.open() still answers right away, adba.sectionTabs.create() returns a controller and adba.savebar() returns an object whose bar arrives once loaded.
Notices
adba.notices.add( { id, text, level, source, dismissible } ) takes plain text, set with textContent: no HTML from an extension reaches the page. For a notice with links or markup, print a normal admin notice in PHP. The notice panel picks it up, and adba_notice_sources or data-adba-source assigns its group.
Events
Listen with adba.on( name, callback ).
| Event | Payload | When |
|---|---|---|
ready | adba | Core started. |
module:ready | { id } | A module entry started without errors. |
prefs:change | { key, value, remote? } | A preference changed (also from another tab). |
prefs:error | error | A preference could not be saved. |
api:error | { error, request, silent } | A REST call failed. |
commands:change | A command was registered. | |
search:open, search:close | The palette opened or closed. | |
search:select | { item, handled } | A result or command was chosen. Set handled = true to take over. |
search:scope | { scope } | Multisite: the palette switched between this site (site) and all sites (network). |
palette:run | { command, values } | A palette command runs, with the values of its params. Since 2.11.0. |
view:apply | { view } | A saved view is opened from its pill or the views menu. Since 2.11.0. |
view:save | { name, share } | A view was saved; share is empty (only me), all or a role. Since 2.11.0. |
drawer:open, drawer:close | { type, url } | The side panel opened or closed. |
drawer:saved | { url } | A screen in the side panel saved. |
notices:change | { count, level } | The notice panel count or level changed. |
pagebar:ready | { bar } | The page bar is ready. |
listtable:ready, listtable:updated | A list table is ready or reloaded. | |
listtable:appended | { rows } | Load more (phones) added the rows of the next page. Since 2.8.0. |
orders:ready, products:ready, settings:updated, wcsettings:updated | Screen specific. | |
guide:open | { id, type } | A guide opened as a card (card) or a tour (tour). Since 2.9.0. |
guide:done | { id, completed } | A guide closed; completed when every tour step was seen. Since 2.9.0. |
img:fallback | { element } | A list picture that did not load got the placeholder (filter adba_image_placeholder). Since 2.12.2. |
JS filters
Addofy uses the native WordPress hooks script. Add a filter with wp.hooks.addFilter(). A callback that throws is logged with the filter name, and the original value is used.
wp.hooks.addFilter( 'adba.search.results', 'myplugin', ( groups, { query } ) => [
...groups,
{ id: 'myplugin', label: 'Reports', items: [ { title: `Report for "${ query }"`, url: '/wp-admin/admin.php?page=myplugin' } ] },
] );
| Filter | Value | Extra argument |
|---|---|---|
adba.search.results | Result groups [ { id, label, items: [ { title, url, subtitle, badge } ] } ] before they render. | { query, scope } |
adba.commands.list | Commands the palette shows. | { screen } |
adba.paletteCommands | Commands right before the palette ranks them for the typed query (since 2.11.0). | { query, scope } |
adba.notices.source | The plugin group { slug, name } of a notice, or null for Other. | the notice element |
adba.drawer.options | Options when the side panel opens (url must stay a string). | |
adba.orderQuickActions | Sections of the order quick actions popup (since 1.2.0). | the order data |
adba.pagebar.actions | Page bar buttons from JS: [ { id, label, onClick, icon } ], icon a dashicons-* class. | { screen, bar } |
adba.queueAction | A background job before adba.queue runs it (since 2.5.0). Return the job, changed or not, or a falsy value to refuse it. |
Background actions (adba.queue, since 2.5.0)
adba.queue.run( { key, label, element, apply, request, rollback, undo } ) changes the interface at once with apply(), marks element with aria-busy and the class adba-pending (a small pulsing dot), and runs request() in the background.
- Use
adba.apiorfetchinrequest()so every server hook still runs. - On success a toast shows
label, with Undo whenundo()is given. - On a failure
rollback()runs and the toast offers Try again. - Jobs with the same
keyrun one after the other, others side by side (at most 4). - While jobs are pending, leaving the page asks for confirmation.
- Load it with
adba.load( 'queue' ); it then also sits onadba.queue. - Events:
queue:start,queue:doneandqueue:fail, each with{ key, label }.
The PHP filters adba_async_row_actions (status, trash and restore links) and adba_async_bulk_actions (bulk actions that run in batches of 20) decide which list actions use the queue.
Sortable lists (adba.sortable, since 2.36.0)
adba.sortable( container, options ) lets users reorder a list by dragging, with the same grip, chip, drop line and autoscroll as the term and menu sorting. Mouse and touch work; Escape cancels. The code loads on the first call; the call returns { refresh, destroy } right away.
const sorter = window.adba?.sortable?.( list, {
items: 'li.myplugin-rule',
label: ( item ) => item.dataset.name,
disabled: () => busy,
onSort: ( from, to, item ) => save( from, to ),
} );
items: selector for the items among the direct children ofcontainer. Default: all children.handle: selector for your own grip inside an item (give ittouch-action: none). Without it, Addofy adds a six-dot grip to each item.label( item ): text in the chip. Default: the text of the item.disabled:true, or a function that returnstrue, blocks dragging. Checked when a drag starts.onSort( from, to, item ): called after the item moved in the DOM. The indexes count the items only.
One level, no nesting. Keyboard users keep your own up and down buttons. Calling it again on the same container replaces the earlier call, so you can redraw the list and call it again. New items get their grip by themselves. destroy() removes the grips and listeners. Feature-detect window.adba?.sortable and keep your own fallback when Addofy is not active.