Embed
Options and events
What you pass to the script when it starts, what you pass to a widget, and what the widget tells you back.
Starting the script
VoteFirst.init runs once per page and takes everything that is true of every widget on it. Only the first two are needed.
| Option | What it does |
|---|---|
project | Your project slug, which is the name in the address of your board. |
key | Your embed key. Public by design, and the only credential that belongs in a page. |
ssoToken | A token your server signed, if this visitor is already signed in to your product. The same thing as calling client.signIn, one line earlier. |
theme | auto, which follows your page's own color-scheme, or light or dark. Appearance has the rest. |
appearance | Colour and spacing overrides for every widget on the page. false takes the board's colours off entirely. |
text | Your own wording, in place of any of the widgets' own. Wording and language lists every key. |
locale | A BCP 47 tag such as de-DE, used for dates and vote counts. Left out, they follow the reader's browser. |
apiBase | Where the script sends its requests. It defaults to wherever the script tag itself was loaded from, which is right unless you are proxying. Loaded through a bundler there is no script tag to read, so it falls back to https://app.votefirst.app and says so in the console; name it yourself if you host or proxy VoteFirst. |
An option the script does not know is ignored rather than refused, so a misspelled name fails quietly rather than loudly. Calling init again changes only the values you pass again.
Widget options
Every option is optional, and a widget sent one it does not read ignores it. The defaults below are what each widget asks for when you say nothing.
| Option | What it does |
|---|---|
board | The board slug. VoteFirst.roadmap defaults to roadmap. On the Most Wanted list, naming a board ranks that one board instead of every suggestion in the project. |
sort | board, which is the order you arranged and what a board draws by default, or top, votes, trending, new, oldest, comments. top follows the project's own score, which is the weighted total where weighting is on; votes is the plain headcount. The flat feature list defaults to top. The Most Wanted list and the changelog have an order of their own and ignore it. |
limit | How many items to load at a time. 20 per column on a board, 10 on the flat list and the Most Wanted list, 5 on the changelog. |
feature | The feature id the vote button and the badge draw. Left out, or set to first, both draw whichever feature has the most votes at the moment the page loads. |
tags | Tag ids to filter by. |
search | A search term applied to headings and descriptions. |
status | Column status to filter by: open, planned, in_progress, done, denied or archived. Read by the flat feature list, and by the Most Wanted list, which defaults to open. A board draws the columns the board has. |
columns | Boards only. Which columns to draw, named by their status or by their id, for a page with room for two of them rather than five. They keep the board's own order whatever order you list them in. |
detail | Boards and the flat feature list. false stops a card opening the request, for a page that would rather send a reader to your own address for it. |
html | The changelog only. false renders each release note as plain text instead of as the markup the server produced from its markdown. |
theme, appearance | The same two as above, for this widget alone. |
VoteFirst.board('#roadmap', {
board: 'roadmap',
columns: ['open', 'in_progress'],
limit: 10
});
Popup options
The suggestion and problem report popups take options only, because they have nothing to render into until they open. The wording they use is on Wording and language; these are the rest.
| Option | What it does |
|---|---|
trigger | A selector or an element that opens the popup. A selector matching several elements binds all of them. |
open | true opens it as soon as the call runs, for a page whose whole purpose is the form. |
container | Where the dialog is appended. It goes to the end of the document by default, which is what keeps it clear of your own stacking contexts. |
heading, description | Values the two fields open with, for a report button that already knows what it is about. |
context | The problem report popup only. false stops it sending the page address and the browser with the report. |
closeOnDone | false leaves the thank you on screen instead of closing the dialog two and a half seconds after it is submitted. |
VoteFirst.report({
trigger: '#report-btn',
heading: 'Problem on the billing page'
});
Events
Listen on one widget through the handle it returns, or on every widget at once with VoteFirst.on. A widget's own listeners run first, then the same event reaches the global bus, so analytics can be hooked once rather than per widget. A listener that throws is reported to the console and does not stop the others.
| Event | When it fires, and what it carries |
|---|---|
ready | Once, just after init. Registering a listener after calling init still catches it. Carries project and version. |
render | A widget finished drawing, including after a refresh. Carries widget and the element it drew into. |
error | A widget could not load, a submission failed, or a sign in was refused. Carries widget and error. The widget shows a retry button of its own. |
vote | A vote control was used. Carries the feature, hasVoted for whether the visitor now has a vote on it, and the whole result. |
identity | The visitor signed in, or was given an anonymous identity. Carries the identity itself. |
open, submit, close | A popup opened, sent something, or closed. submit carries the feature that was filed. |
VoteFirst.on('vote', function (event) {
analytics.track('roadmap vote', { feature: event.feature.heading });
});
Errors
Everything the script rejects with is an Error with three things added, so a handler can branch on the code and show the message.
VoteFirst.client.vote(1234).catch(function (error) {
if (error.code === 'already_exists') return;
console.error(error.status, error.code, error.message);
});
| Property | What it carries |
|---|---|
code | The stable half, and the only half worth branching on. The API error codes are the same set. |
message | Written for a person, and liable to change. |
status | The HTTP status, or 0 if the request never reached the server. |
field | The field at fault when the code is validation_failed, and null otherwise. |
An error event carries the same object, so the two ways of finding out are the one thing to handle.
Three codes come from the script rather than from the server. not_configured means init has not run with a project and a key. network means the request never left, which is a reader offline or an extension blocking it. And http_404 and its like appear when a response carried a status but no body to read a code from.