JavaScript

How a script talks to the player. window.riff is set before the riff.ready action fires. Everything here is public and keeps working within a major version.

window.riff

Properties

NameDescription
versionThe version of this api: 1.

Methods

NameDescription
play()Makes tracks the queue and plays the one at index.
toggle()Plays or pauses.
next()Skips to the next track.
prev()Goes back a track, or to the start of this one.
seek()Moves the current track to a time.
open()Opens Now Playing, on a view of it when one is named.
close()Closes Now Playing.
current()The track playing.
queue()The queue in play order.
playing()Whether something is playing.
time()Where the track is.
analyser()The music as Web Audio hears it, for a plugin to read: connect an AnalyserNode of your own to this one, and never to anything that changes the sound. It is null where the music doesn't pass through Web Audio, so nothing should be drawn: before the first play, on an iPhone, for a file from another origin that doesn't share over CORS, and while a video plays.
speed()How fast the music plays, with its pitch kept where the browser can keep it (preservesPitch): slower to learn a part, faster to skim. Given a rate, from 0.5 to 2, it sets it, and the speed holds for every track until it is set again. On the turntable it is multiplied by the deck's own speed and pitch.
view()Gives a view what it does as it opens, or adds one the server didn't register. A view is opened from its button in the bar, and on a phone from its chip in Now Playing (the album, the stage, has no button: the bar itself opens it): a screen of Now Playing, which takes the whole screen above the bar, or a panel beside the page. Register a view on the server with riff_register_view(), so the page has it before any script; this is for what only the browser knows. Riff's own are the album (album, order 26; the cover, or the turntable where Now Playing is landscape), About (about, a panel, 36), Up next (queue, a panel, 40) and Together (together, a panel, 45); Riff Lyrics registers Lyrics (lyrics, 30), Riff Sing Sing (sing, 32) and Riff Chords Chords (chords, 34). A view with nothing for a track says so with shown: its button and chip hide while that track plays, and if it is open when the track changes to one, a screen goes back to the one the listener came from, or to what Now Playing opens to, and a panel closes.
openView()Opens a view: a screen of Now Playing, or a panel beside the page.
closeView()Closes the panel that is open, or else Now Playing.
control()Gives a control in the player's bar what it does, or adds one the server didn't register. Register a control on the server with riff_register_control(), so the page has it before any script; this is for what only the browser knows. Riff's own are Like (order 10), the badges (20), Play on another device (60) and the volume (70).
shortcut()Gives a keyboard shortcut registered on the server with riff_register_shortcut() what it does. It follows Riff's own single-key shortcuts: it acts only while a track is loaded, never while the listener types in a field or holds Ctrl, Alt or Command (though a mark typed with AltGr counts where the browser reports AltGr, as [ on a German keyboard), and only where those are on, for a signed-in listener who has not turned them off on their profile, unless the riff.shortcuts filter turns them off. A key the server didn't register does nothing, since the profile lists every key there is.
on()Listens to one of the player's actions, without wp-hooks.

window.riff.version

The version of this api: 1.

Type: number

window.riff.play( tracks, index = 0, options )

Makes tracks the queue and plays the one at index.

The tracks go through the riff.queue and riff.track filters first.

Parameters

tracksObject[]Required
Tracks, in the shape Tracks::schema() describes.
indexnumberOptional
The one to play first. Default 0.
optionsObjectOptional
Options.
  • shuffleboolean
    true or false sets shuffle before playing.

window.riff.toggle()

Plays or pauses.

window.riff.next()

Skips to the next track.

window.riff.prev()

Goes back a track, or to the start of this one.

window.riff.seek( seconds )

Moves the current track to a time.

Parameters

secondsnumberRequired
From the start of the track.

window.riff.open( view )

Opens Now Playing, on a view of it when one is named.

Parameters

viewstringOptional
A screen view's id. Default the album.

window.riff.close()

Closes Now Playing.

window.riff.current()

The track playing.

Return

Object|null The track, or null.

window.riff.queue()

The queue in play order.

Return

Object[] Tracks.

window.riff.playing()

Whether something is playing.

Return

boolean True while a track plays.

window.riff.time()

Where the track is.

Return

number Seconds from the start of the track, or 0 with nothing playing.

window.riff.analyser()

The music as Web Audio hears it, for a plugin to read: connect an AnalyserNode of your own to this one, and never to anything that changes the sound. It is null where the music doesn't pass through Web Audio, so nothing should be drawn: before the first play, on an iPhone, for a file from another origin that doesn't share over CORS, and while a video plays.

Return

?AnalyserNode The analyser, or null.

window.riff.speed( rate )

How fast the music plays, with its pitch kept where the browser can keep it (preservesPitch): slower to learn a part, faster to skim. Given a rate, from 0.5 to 2, it sets it, and the speed holds for every track until it is set again. On the turntable it is multiplied by the deck's own speed and pitch.

Parameters

ratenumberOptional
The speed to set, 1 for the music's own. Leave it out to read it.

Return

number The speed now.

window.riff.view( id, view )

Gives a view what it does as it opens, or adds one the server didn't register. A view is opened from its button in the bar, and on a phone from its chip in Now Playing (the album, the stage, has no button: the bar itself opens it): a screen of Now Playing, which takes the whole screen above the bar, or a panel beside the page. Register a view on the server with riff_register_view(), so the page has it before any script; this is for what only the browser knows. Riff's own are the album (album, order 26; the cover, or the turntable where Now Playing is landscape), About (about, a panel, 36), Up next (queue, a panel, 40) and Together (together, a panel, 45); Riff Lyrics registers Lyrics (lyrics, 30), Riff Sing Sing (sing, 32) and Riff Chords Chords (chords, 34). A view with nothing for a track says so with shown: its button and chip hide while that track plays, and if it is open when the track changes to one, a screen goes back to the one the listener came from, or to what Now Playing opens to, and a panel closes.

Parameters

idstringRequired
Lowercase letters, digits and dashes; a screen is [data-riff-view="<id>"], a panel [data-riff-panel="<id>"].
viewObjectRequired
The view.
  • labelstring
    Its name: its heading, its button's and its chip's. Needed for one the server didn't register.
  • iconstring
    Its button's icon, SVG markup from your own code, never from content.
  • ordernumber
    Where its button sits among the bar's controls, lowest first. Default 50.
  • placestring
    screen, the default, or side for a panel.
  • render(view: HTMLElement, track: Object|null) => void
    Fills it as it opens and again as the track changes while it is open. The riff.view action says the same.
  • shown(track: Object|null) => boolean
    Whether it has something for the track, so its button and chip show. Default always.

Return

() => void Takes away what this gave it, or the view this added.

window.riff.openView( id )

Opens a view: a screen of Now Playing, or a panel beside the page.

Parameters

idstringRequired
The view's id: album, queue, or one a plugin registered.

window.riff.closeView()

Closes the panel that is open, or else Now Playing.

window.riff.control( id, control )

Gives a control in the player's bar what it does, or adds one the server didn't register. Register a control on the server with riff_register_control(), so the page has it before any script; this is for what only the browser knows. Riff's own are Like (order 10), the badges (20), Play on another device (60) and the volume (70).

Parameters

idstringRequired
Lowercase letters, digits and dashes; it names the control in data-riff-control.
controlObjectRequired
The control.
  • labelstring|((track: Object|null) => string)
    What it is called, for a screen reader and a pointer's tooltip; or a function of the track. Needed for one the server didn't register.
  • iconstring
    Its icon, SVG markup from your own code, never from content.
  • ordernumber
    Where it sits among the others, lowest first. Default 50.
  • run(track: Object|null, button: HTMLElement) => void
    What a press does.
  • actionstring
    One of the player's own actions instead of run, such as shuffle or repeat.
  • pressed(track: Object|null) => boolean
    Whether it is pressed, for a control that turns something on and off.
  • shown(track: Object|null) => boolean
    Whether it shows. Default always.
  • wideboolean
    Only on a wide screen; a phone's bar keeps to the track, Play and what it needs.
  • element() => HTMLElement
    An element of your own in place of a button, which you keep up to date.

Return

() => void Takes away what this gave it, or the control this added.

window.riff.shortcut( id, run )

Gives a keyboard shortcut registered on the server with riff_register_shortcut() what it does. It follows Riff's own single-key shortcuts: it acts only while a track is loaded, never while the listener types in a field or holds Ctrl, Alt or Command (though a mark typed with AltGr counts where the browser reports AltGr, as [ on a German keyboard), and only where those are on, for a signed-in listener who has not turned them off on their profile, unless the riff.shortcuts filter turns them off. A key the server didn't register does nothing, since the profile lists every key there is.

Parameters

idstringRequired
The shortcut's id, as it was registered.
run(track: Object, event: KeyboardEvent) => voidRequired
What the key does, given the track loaded and the key press.

Return

() => void Takes it away again.

window.riff.on( name, fn )

Listens to one of the player's actions, without wp-hooks.

Parameters

namestringRequired
The action without its prefix: track, play, pause and the rest.
fn(detail: Object, api: Object) => voidRequired
Called with the detail and the api.

Return

() => void Stops listening.

Actions and filters

Each change of state is announced twice with the same detail: through wp.hooks as riff.<name>, for scripts that depend on wp-hooks, and as a riff:<name> CustomEvent on #riff that bubbles, for everything else. The filters run only through wp.hooks.

NameDescription
riff.menufilterFilters the items of the track menu, the … beside every row and every track in Up next.
riff.queuefilterFilters the tracks about to become the queue.
riff.shortcutsfilterFilters whether the single-key shortcuts (Space, K, J, L and plugins' keys) act on a key press.
riff.trackfilterFilters one track as a queue is set, after riff.queue.
riff.app_viewactionFires when a view of the Listen app shows: the first as the app starts, then each one in-page navigation brings, and again when one is drawn again in place. A plugin that added a view with the riff_app_views filter binds its script to what it drew here, or on the riff:app_view event, which bubbles to document.
riff.endedactionFires when a track plays to its end, before the next one loads.
riff.pauseactionFires when the track pauses.
riff.playactionFires when the track starts or resumes playing.
riff.queueactionFires when the queue changes while it plays: tracks added to play next or at the end, one moved or removed, or the queue cleared.
riff.readyactionFires once the player is set up, its state restored and window.riff available.
riff.timeactionFires as the track plays, a few times a second, and again after a seek.
riff.trackactionFires when a track is loaded, before it plays.
riff.viewactionFires when a view opens or closes, Riff's own included, and again for an open view when the track changes. A view's script fills it here, or in the render it was given.
wp.hooks.addAction( 'riff.track', 'my-plugin', ( detail, riff ) => {
	console.log( detail.track.title );
} );

window.riff.on( 'play', ( detail ) => {} );
document.getElementById( 'riff' ).addEventListener( 'riff:pause', ( e ) => e.detail );

A track

Every track the player takes or hands back is the shape Tracks::schema() describes in PHP; the PHP reference lists every property. The REST API returns the same shape.

A view, and a control in the bar

Register a view or a control on the server with riff_register_view() and riff_register_control() on the riff_register action, so the page has it before any script runs; then give it what it does in the browser, by its id. window.riff.view() fills a view as it opens and again as the track changes, and window.riff.control() gives a control its press. A view is a screen of Now Playing, taking the whole screen above the bar, or a panel beside the page. Riff registers the album, About, Up next, Together and its own controls the same way, and Riff Lyrics, Riff Sing and Riff Chords their views, on nothing but the public API.

add_action( 'riff_register', function () {
	riff_register_view( 'credits', array( 'label' => __( 'Credits', 'my-plugin' ), 'icon' => CREDITS_ICON, 'order' => 32 ) );
	riff_register_control( 'bookmark', array( 'label' => __( 'Bookmark', 'my-plugin' ), 'icon' => BOOKMARK_ICON, 'order' => 65 ) );
} );
document.addEventListener( 'riff:ready', () => {
	window.riff.view( 'credits', {
		render: ( view, track ) => showCredits( view, track ),
	} );
	window.riff.control( 'bookmark', {
		pressed: ( track ) => isBookmarked( track ),
		run: ( track ) => toggleBookmark( track ),
	} );
} );

Loading your script

The player is an ES module with no dependencies. A script that uses wp.hooks depends on wp-hooks; one that only uses window.riff or the events can load however it likes, and should wait for riff.ready (or check window.riff) before calling anything.