Javascript API

Table of contents

onArrive and onMessage

Each node must contain one onArrive and one onMessage function.

onArrive is called when the user enters the node for the first time.

export const onArrive = async (api) => {
  /* place your code here */
} 

onMessage is called each time the user sends a message or makes a choice.

export const onMessage = async (msg, api) => {
  /* place your code here */
} 

The code that defines the behaviour of the node is placed between the { and }

In the Handlers tab, these functions are provided automatically for you.

moveTo

Move the player to a different node on the same board:

api.moveTo("node1")

Advanced: Move the player on a different board:

api.moveTo("node1", {channelKey: "board2"})

This does not change the node on the current board.

Sending messages

sendText

Sends a text message to the player.

api.sendText("hello")

sendImage

Sends an image message to the user.

api.sendImage("f00ba420-0123-4567-89abcdef012356789")

The first parameter is the media file key. To get the media file key, go to the Media tab, open ⋮ menu, copy key.

Images are normally scaled and cropped to fit (“cover” mode). To make sure that everything on the image is visible, you can switch to “contain” mode:

api.sendImage(
  "f00ba420-0123-4567-89abcdef012356789", 
  { objectFit: "contain" }
)

Images are by default zoomable (enlarge on click or tap). Prevent zoom:

api.sendImage(
  "f00ba420-0123-4567-89abcdef012356789", 
  { zoomable: false }
)

Send an image with a link that the user can click on:

api.sendImage(
  "f00ba420-0123-4567-89abcdef012356789", 
  { url: "https://docs.interkit.app/" }
)

Trigger an action on the client by clicking an image

api.sendImage(
  "f00ba420-0123-4567-89abcdef012356789", 
  {action: {trigger: "triggerName", payload: payloadObject}}
)

sendAudio

api.sendAudio("e4770840-3c2e-4eeb-b59b-a0e15e14190b")

The first parameter is the media file key. To get the media file key, go to the Media tab, open ⋮ menu, copy key.

Autoplay the audio when the message arrives

api.sendAudio("mediafileKey", { autoplay: true })

You can send audio to the floating popout player using the target option. Hoewver, this is a bit different as the floating player does not expect a media file key but a database row and a column that contains the audio. Note that the audioColumn option is required and contains the key of the sheet and the kay of the column, separated by a /.

// Get the row from the database
const element = await api.getRow("b7905d1c-b567-4801-80be-b7c6e749ad7a")
api.sendAudio(null, { 
  target: "popout", 
  element: element, 
  audioColumn: "elements/audio" 
})

sendVideo

api.sendVideo("b94eb8f3-72ef-476d-ad61-64adc18204e7")

The first parameter is the media file key. To get the media file key, go to the Media tab, open ⋮ menu, copy key.

sendChoice

Send a choice, presented as multiple choic buttons.

api.sendChoice({
  a: "option a",
  b: "option b"
})

See the responding to messages section below for reponding to a choice made by a user

Send a link message to the user.

api.sendLink("https://docs.interkit.app/")

Separate text from URL

api.sendLink("Interkit Documentation", "https://docs.interkit.app/")

See sendImage to send a link with an image

sendLocation

Send a location (Coordinates). The user can click on the location to open it in a map app.

api.sendLocation("Open in map", {lat: 52.51449, lng: 13.38324})

sendSystem

Send a system message das is displayed in the center of the chat. Useful for error messages or neutral informational content.

api.sendSystem("Someone entered the channel")

sendSystemImage

Send a system image displayed in the center of the chat.

api.sendSystemImage("f00ba420-0123-4567-89abcdef012356789")

Set a custom width for the image

api.sendSystemImage(
  "f00ba420-0123-4567-89abcdef012356789", 
  {width: "200px"}
)

Place the system image on either side of the chat

api.sendSystemImage(
  "f00ba420-0123-4567-89abcdef012356789", 
  {placement: "me"}
)
api.sendSystemImage(
  "f00ba420-0123-4567-89abcdef012356789", 
  {placement: "other"}
)

Labels

Add a label to identify a sender.

api.sendText("hello", {label: "bot"})

You can add labels in the same way to the other types of messages.

Delays

Use the dealy option to schedule events for later delivery. This works for sendText, sendChoice, sendImage and moveTo.

Send a message 10 seconds later

api.sendText("hello", {delay: 10}) 

Send a message 1 hour, 30 minutes later

api.sendText("hello", {delay: {hours: 1, minutes: 30}}) 

Send a message the “next 13 o’clock”, either later today, or tomorrow (in the server’s timezone!)

api.sendText("hello", {delay: {nextHour: 13}}) 

Add between 0 and 60 minutes, randomly

api.sendText("hello", {delay: {nextHour: 13, randomHours: 1}})

To clear all scheduled messages and moveTos for the current user, use clearSchedule(). Note that this does not only clear the scheduled events from this node, but all scheduled events for the user.

api.clearSchedule()

Responding to messages

The onMessage method receives a msg parameter that you can evaluate to respond conditionally to messages.

if(msg.payload.text == "foo") {
  // do something
}

If the user made a multiple choice selection, the key attribute on msg.payload will be set.

if(msg.payload.key == "a") {
  // do something
}

msg.payload.type contains information about the type of message that the user sent.

echo

To create, multiplayer chatrooms, you need to forward incoming messages to other users.

echo forwards a message to other users currently in the same node.

api.echo(msg)

The user variable “name” is used by default as a label.

msg is supposed to be a whole message object like the one received in onMessage(api, msg).

Sending to specific recipients

By default, the recipient of a message sent by any api.send...() function is the current user.

All api.send...() functions accept further options to specify the recipients:

  • channelKey optionally send this message on a different channel
  • recipients an array of recipients user ids.
api.sendText("hello", {
  channelKey: "other_board",
  recipients: ["ohpppdsCZ9CXZ4Ds4", "bREC5nMSLoRNjSRn3"], 
})

To broadcast a message to all users that are currently in a node, specify the nodeId inside the recipients

api.sendSystem("The bus will arrive in 5 minutes", {
  recipients: {
    nodeId: "waitingforthebus"
  }
})

You can also get the explicit list of users in a node with api.getUsersInNode({ channelKey, nodeId }). To get a list of userIds, map the users to their userIds.

const users = await api.getUsersInNode({ channelKey: "board2", nodeId: "start" })
const userIds = users.map(user => user._id)

Moving other players

While api.moveTo() moves the current user by default, you can add a list of recipients to move other users.

api.moveTo(
  "node1",
  {
    recipients: ["ohpppdsCZ9CXZ4Ds4", "bREC5nMSLoRNjSRn3"],
  }
)

`recipients` is a list of user IDs.

The `nodeId` always relates to the node on the board where `moveTo` is called. Optionally add a `channelKey` to explicitly move users on a different board.

Recipients can be defined as users in a node. Example: Move all users from node "start" to node "end" on the board "board2".

```js
api.moveTo(
  "end",
  {
    channelKey: "board2",
    recipients: {
      nodeId: "start",
      channelKey: "board2"
    },
  }
)

Alternative notation

The function moveUsers is a shorthand for moveTo with the recipients as the second argument.

api.moveUsers("node1", ["ohpppdsCZ9CXZ4Ds4", "bREC5nMSLoRNjSRn3"])

Variables

Set a variable for this user, for example set the user’s “name” to “alice”.

await api.setUserVar("name", "alice")

Get a variable for this user, for example the variable called “name”

await api.getUserVar("name")

These operations read from the database, so await is needed.

There are “magic” variables, see “Restarting” below.

Restarting (by resetting other players)

Set a user’s userVar resetRequested to true to signal their device to reset. Their client will reset as soon it “sees” the signal (like when they re-open a tab, or launch the app).
When a client reacts, it

  1. sets its userVar to a timestamp, signaling back it has read the request (the timestamp is currently not used in user-friendly way, but it can be examined in Project/users table, User vars column)
  2. clears localStorage (thus “forgetting” its userId)
  3. reloads the tab (it then receives a new userId)

There is a batch helper variant of this function, intended for admin-like users:

const affectedUserCount = await api.requestResetAllOtherUsers()

will set the magic signal userVars for all other (i.e. presumably non-admin) users.
The return value does not reflect how many users/devices were successfully reset, only how many were newly requested to do so (this excludes users/devices where a request is pending).

Database rows

Load rows from a sheet

await api.getRows("elements")

Load one row from a sheet (by row key)

await api.getRow("rowKey")

Add a row to a sheet

await api.addRow("elements", {title: "hello"})

Update a row (replaces the whole row)

await api.updateRow("elements", "rowKey", {title: "bye"})

Update single values in a row (keeps existing values, only overwrites the one you provide)

await api.updateRowValue("elements", "rowKey", "colKey", "value")
//example:
await api.updateRowValue("elements", "rowKey", "title", "bye")

These operations read from the database, so await is needed.

Data annotations

Set or get a data annotation (formerly called element properties) about an element for this user. Data annotations are user specific data that is added to database rows, for example bookmarks.

The first parameter is the row key, the second the annotation name, the third, the value you want to set.

await api.setElementProperty("f00ba420-0123-4567-89abcdef012356789", "discovered", true)
await api.getElementProperty("f00ba420-0123-4567-89abcdef012356789", "discovered")

These operations read from the database, so await is needed.

Interface

You can set what interface the chat could display to the user. For example if you want users to be able to take photos or not. These settings persist across nodes per board.

The default is text entry, with photo turned off.

Hide the interface for sending messages:

api.setInterface({text: false})
api.setInterface({text: true}) // turn it back on 

Allow user to take pictures and send them into chat:

api.setInterface({text: true, photo: true}) // text and photo entry
api.setInterface({text: false, photo: true}) // just photo entry

Set preferred camera (front or back):

api.setInterface({photo: true, cameraFacingMode: "environment"}) // or "user" for selfie mode

The interface can be also set per message.

api.sendText('Give me a photo', { setInterface: { photo: true, text: false } })

Location

To get a user’s location, we can present the user with a button that enables them to send their location.

api.requestLocation("Send Location", {cancel: "Cancel"}) // you can also leave the cancel option blank

Responding to a location looks like this

if(msg.payload.type == "locationResponse") {
  // do something
  if(api.distance(msg.payload.location, {lat: 56, lng: 12}) < 100) {
    api.sendText("you're close!")
  }
}
if(msg.payload.type == "locationRequestCanceled") {
  api.sendText("ok")
}

Translation

See the i18n guide for general intro to interkit’s i18n system.

Access the current language

api.sendText('your language: ' + api.userLang)
api.sendText('your language, index: ' + api.userLangIndex)

Set language

api.setLang('de', 1) 

The second argument has to match the index (0-based) in the AppBase blockly field

Use current language

if (api.userLang === 'en') ...
if (api.userLangIndex === 1) ...
let text1 = ['Deutsch', 'Englisch'][api.userLangIndex]
let text2 = {de: 'Deutsch', en: 'Englisch'}[api.userLang]

Use text localized to current user language

export const onMessage = async (msg, api, t) => {
  api.sendChoice({ a: t('Ja|Yes'), b: t('Nein|No') })
}

The t helper function takes pipe-separated strings, arrays or objets:

api.sendText(t('Ja|Yes'))
api.sendText(t(['Ja', 'Yes']))
api.sendText(t({ de: 'Ja', en: 'Yes' })) // order-independant

You can use sendTextT, sendChoiceT, sendSystemT shortcuts, equivalently

api.sendTextT('Tschüß|Bye')
api.sendChoiceT({ a: 'Ja|Yes', b: ['Nein', 'No'] })
api.sendSystemT('Chat verlassen|Left the chat')