JavaScript extension API
On this page
Since 2.4.3, AjaxPress exposes window.AjaxPress, the same API that AjaxPress Pro is built on. Use it from a theme or plugin to add persistent players, keep URLs out of ajax navigation, replace the loader or the page transition, or preload pages.
Read Where your code runs first. It explains the top window and the page frame, which this API works across.
Register a module
AjaxPress reads your filters, loader and transition while it boots. So register through the ajaxpressModules queue, from a script that loads before AjaxPress’s own script:
(window.ajaxpressModules = window.ajaxpressModules || []).push((api) => {
api.addFilter('persistSelectors', (selectors) => [...selectors, '#my-player']);
});
AjaxPress runs every queued module against the API before it boots. Modules pushed after it has booted run straight away, but by then it has already built its loader, transition and listeners, so queue early.
In WordPress, enqueue your script in the <head>. AjaxPress’s own script loads in the footer:
add_action( 'wp_enqueue_scripts', function () {
wp_enqueue_script(
'my-ajaxpress-module',
get_theme_file_uri( 'js/ajaxpress-module.js' ),
array(),
'1.0.0',
false // In the <head>, before AjaxPress.
);
} );
Your script is part of every page, so it runs in the top window (for the first page) and in the page frame (on every page). Each runs its own copy of AjaxPress with its own API, which is why the same registration works everywhere.
Filters
api.addFilter(name, callback) changes a value AjaxPress is about to use. The callback receives the current value (plus any extra arguments) and returns the new one. Several callbacks run in the order they were added.
persistSelectors
The CSS selectors for persistent elements. It is read in the top window on every navigation.
api.addFilter('persistSelectors', (selectors) => [...selectors, '#radio-bar', '.podcast-dock']);
bypassPatterns
URL fragments that force a normal page load. A URL is bypassed when its path and query contain any entry. The second argument says whether this is wp-admin.
api.addFilter('bypassPatterns', (patterns, { isAdmin }) => {
return isAdmin ? patterns : [...patterns, '/members-area', '?download='];
});
The defaults are /wp-admin, /wp-content, /wp-json and wp-admin.php. For site owners, Exclude Links in the settings does the same job without code.
Actions
api.addAction(name, callback) runs code at a point in AjaxPress’s life. Both actions fire inside the page frame.
| Action | Argument | Fires |
|---|---|---|
childInit | { settings } | Once on every page, as AjaxPress starts in that page |
childNavigate | { url } | When a link click on the page is handed to AjaxPress |
api.addAction('childNavigate', ({ url }) => {
// For example, close an open menu before the page changes.
document.body.classList.remove('menu-open');
});
Custom loader
api.registerLoader(factory) replaces the progress bar or spinner. The factory receives the settings and returns a loader object, or null to keep the built-in one. If several are registered, the last one wins.
| Property | Type | Required | Purpose |
|---|---|---|---|
element | HTMLElement | Yes | The loader’s element. AjaxPress appends it to the page and gives it the id ajaxpress-loader. |
start() | function | Yes | Called when a navigation or form submission starts |
complete() | function | Yes | Called when the new page is on screen |
isSpinner | boolean | No | true if start() appends the element itself, instead of AjaxPress appending it up front |
(window.ajaxpressModules = window.ajaxpressModules || []).push((api) => {
api.registerLoader(() => {
const el = document.createElement('div');
el.style.cssText = 'position:fixed;top:0;left:0;height:3px;width:0;background:#e11d48;z-index:2147483647;transition:width .4s,opacity .3s;opacity:0';
return {
element: el,
start() { el.style.opacity = '1'; el.style.width = '70%'; },
complete() {
el.style.width = '100%';
setTimeout(() => { el.style.opacity = '0'; el.style.width = '0'; }, 300);
},
};
});
});
Custom transition
api.registerTransition(factory) replaces the animation between pages. The factory receives the settings and returns a transition object, or null to keep the built-in one.
AjaxPress calls crossFade(oldFrame, newFrame) when the next page has loaded. oldFrame is the iframe on screen, and newFrame is the hidden iframe holding the new page. Make newFrame visible and animate between them, then resolve the promise. AjaxPress then swaps the frames and resets their inline styles. The object also needs animateOut and animateIn methods, which can simply resolve.
(window.ajaxpressModules = window.ajaxpressModules || []).push((api) => {
api.registerTransition(() => ({
animateOut: () => Promise.resolve(),
animateIn: () => Promise.resolve(),
crossFade(oldFrame, newFrame) {
newFrame.style.visibility = 'visible';
newFrame.style.zIndex = '999999';
newFrame.style.pointerEvents = 'auto';
const anim = newFrame.animate(
[{ opacity: 0, transform: 'translateX(24px)' }, { opacity: 1, transform: 'none' }],
{ duration: 250, easing: 'ease-out' }
);
return anim.finished.then(() => {});
},
}));
});
Keep transitions short (under 300ms). The page is already loaded while it animates.
Preload a page
api.preload(url) loads a page in the background, so navigating to it is instant. It works from the page frame or the top window. Pass an absolute URL: a click is matched against the preloaded page by its full address. Only one page is held at a time, and a new preload replaces the last. URLs AjaxPress would bypass are ignored.
// Preload the next episode as soon as the current one starts playing.
document.querySelector('#player').addEventListener('play', () => {
window.AjaxPress?.preload(new URL('/episodes/next/', location.origin).href);
});
Check a URL
api.shouldBypass(url) returns true if AjaxPress would leave the URL to a normal page load: another site, wp-admin, a builder editor, a mailto: link, a bypass pattern, or an Exclude Links match.
if (!window.AjaxPress?.shouldBypass(link.href)) {
// AjaxPress will handle this link.
}
Good practice
- Check that
window.AjaxPressexists (window.AjaxPress?.…) before calling it directly, since AjaxPress may be deactivated. - A callback that throws is caught and logged to the console, and AjaxPress carries on with the value it had.