Bitfocus AS
logo
logo
Bitfocus AS
logo
logo
Sign upSign in

Loading...

Bitfocus

Subscribe to our newsletter

The latest news, articles, and resources, sent to your inbox.

FacebookInstagramGitHubYouTubeLinkedIn

Products

  • Buttons
  • Companion

Integrations

  • Supported Devices
  • Developer Community
  • Connection Development

Support

  • Support Overview
  • Documentation
  • Video Tutorials
  • Community Forum

Sales

  • Resellers & Integrators
  • Buttons Pricing

Updates

  • Case Studies
  • Events & Trade Shows
  • Press Releases
  • Product Updates
  • Webinars

Legal

  • Legal Overview
  • Privacy Policy
  • Buttons EULA
  • Terms & Cookie Policy

Company

  • About us
  • Press kit
  • Careers

© 2026 Bitfocus AS. All rights reserved.

Expressions
Docs for
Overview
Getting started
What is Bitfocus Buttons?
Install Buttons and get started
Manage your Buttons license
Activate Buttons offline
Find your way around Buttons
Create your first backup
Add an ATEM connection
Choose a control method
Choose an installation path
Install Buttons on Debian or Ubuntu
Understand HA clustering
Kubernetes HA
Update or remove Buttons
Positions
Understand positions
Create a position
Add controls and sections to a position
Create your first button
Use a connection's presets
Build more capable button actions
Add more feedback to a button
Organize controls in a section
Shift Section
Organize controls with a Folder Section
Add a Popover Section
Build and reuse a Shared Section
Build a Router Section
Understand Custom Routers
Custom Router panel
Surfaces
Surface compatibility
Add and attach a surface
Device orientation
Connections
Update a connection's module safely
Monitor and troubleshoot a connection
Router integrations
VideoHub and AJA KUMO
Utah Scientific BPS
Generic SW-P-08
Nevion VideoIPath
Arkona BLADE//runner
Routing
Physical routing
Configure ports and labels
Take a physical route
Understand route status
Topology graph
Routing Presets
Get started with virtual routing
Configure Nested Shapes
Reverse routing
Tielines
Routing Projects
Routing settings
Troubleshoot a route
Tally
Understand the Tally system
Send ATEM tally and labels to a UMD
Interpret Active Tally state
TSL/UMD connections
Diagnose tally problems
NMOS
Understand NMOS in Buttons
Connect Buttons to an NMOS Registry
Built-in Registry Server
Configure NMOS connections
Discover and adopt
Browse the NMOS inventory
Manage NMOS multicast addresses
Diagnose NMOS problems
Understand Cuelists
Build a Cuelist
Read and advance a running Cuelist
Control a Cuelist from a Position
Workflows
Understand workflows
Build your first workflow
Reuse a group of workflow nodes safely
Troubleshoot a workflow
Recipes
Sequence a timed automation
Call an HTTP endpoint from a workflow
REST endpoint
Use variables
Understand variable scope
Understand nested variables
Update expressions for v1.8
Plan and use Tags
Access
Create and manage users
Create roles and assign permissions
Grant access to specific resources
Show different controls by role
Sessions
Set up PIN and NFC sign-in
SSO
Get started with SSO
Connect a generic OIDC provider
Connect LDAP or Active Directory
Map identity claims to roles
Secure a Buttons deployment
Integrations
External control
Connect to Bitfocus Listener
USB Relay
Install USB Relay on Windows
Install USB Relay on macOS
Install USB Relay on Linux
Install USB Relay on a Raspberry Pi
Get started with the Control API
Secure and monitor the Control API
Control API reference
API reference
Administration
Enable and manage installable features
Services and health
Configure and monitor scheduled backups
Restore a backup and verify it
Export or import Buttons configuration
Store and rotate connection secrets
Replace the HTTPS certificate
HA backup and recovery
Settings
Collect support information
Reference
Glossary
Button Inspector reference
Network ports reference
Expressions
Internal actions reference
Routing Presets panel reference
Startup configuration reference
Workflow nodes
Connection workflow nodes
Workflow workflow nodes
Internal workflow nodes
Position workflow nodes
API workflow nodes
Utility workflow nodes

Loading...

Previous
← Network ports reference
Next
Internal actions reference →
Contact support →
You are viewing documentation for Buttons 1.8.See the docs for Buttons 1.6
Buttons/Reference/Expressions

Expressions

Buttons' expression editor understands a real JavaScript-like grammar (standard operators and precedence, if/for/while, arrow functions) plus a specific set of builtin functions and the $(...) variable-reference syntax. This page is a lookup reference for what's actually supported. For the v1.8 syntax changes if you're upgrading an existing system, see Update expressions for v1.8.

Operators#

Precedence follows standard JavaScript exactly: only which operators are allowed is restricted, not how they bind.
Kind
Operators
Arithmetic / bitwise
`+ - * / % ^ ** >> << & \
(^ is bitwise XOR here, not exponent: use `** for exponent)
Comparison
== != === !== > < >= <=
Logical
`\
\
&& ??` (nullish coalescing)
Unary
- + ! ~
Update
++ -- (prefix or postfix)
Assignment
`= *= **= /= %= += -= <<= >>= &= ^= \
= \
\
= &&= ??=`
Other
Ternary (a ? b : c), comma/sequence (a, b, c), spread (...arr), grouping
+ behaves like JavaScript's numeric addition first: it only falls back to string concatenation when the numeric result would be NaN, so '1' + '2' gives 3, but 'a' + 1 gives 'a1'.
Control flow and declarations: if/else, while, for, for...of (unlabelled break/continue only), return, let/const (not var), and simple arrow functions ((x) => x + 1: no destructured parameters, not async).
Explicitly not supported: await, yield, this, tagged template literals, regex literals, BigInt literals, getters/setters, destructuring, optional calls (fn?.()), and method-style calls on a value (a.b()): only direct function calls are supported.
Object literals: a {...} at the very start of an expression is read as an object literal, not a code block: for example, { 1: 'on', 2: 'off' }[$(internal:state)] is valid and works as a lookup table.

Functions#

Math and numbers#

Function
What it does
round(v) / floor(v) / ceil(v) / abs(v)
Standard rounding
sqrt(v) / pow(base, exponent)
Square root, exponentiation
log(v, base?) / log10(v) / exp(v)
Logarithm (natural, or given base) and exponential
max(...) / min(...)
Largest/smallest of the given values
randomInt(min=0, max=10)
Random inclusive integer
fromRadix(str, radix=10) / toRadix(v, radix=10)
Convert between a number and a string in a given base (2–36)
toFixed(v, dp=0)
Fixed decimal places (0–100)
isNumber(v)
True for a number, bigint, or a non-blank numeric string

Strings#

Function
What it does
length(v)
Length of a string (counting whole characters, not UTF-16 units), array, number, or object (key count)
strlen(v)
Raw string length in UTF-16 code units
trim(v)
Trims whitespace
substr(str, start, end) / split(str, sep?) / join(arr, sep=',')
Slice, split, and join
concat(...)
Concatenates strings
includes(str, sub) / indexOf(str, sub, offset?) / lastIndexOf(str, sub, offset?)
Search within a string
toUpperCase(str) / toLowerCase(str) / replaceAll(str, find, replace)
Case and replacement
stringCompare(a, b)
Locale-aware comparison, for use in a sort callback
encode(str, enc) / decode(str, enc)
Encode/decode using a Buffer encoding (default latin1)
encodeURI(str) / decodeURI(str) / encodeURIComponent(str) / decodeURIComponent(str)
Standard URI encoding

Booleans#

Function
What it does
bool(v)
Truthy, except the strings 'false' and '0' (case-insensitive) are false

Objects, arrays, and JSON#

Function
What it does
jsonpath(obj, path)
JSONPath query: auto-parses a JSON string input
jsonparse(str) / jsonstringify(obj)
Parse/stringify JSON, returning null on failure
objectKeys(obj) / objectValues(obj)
Like their JavaScript equivalents
arrayIncludes / arrayIndexOf / arrayLastIndexOf
Search within an array
arrayMap / arrayFilter / arrayFind / arrayFindIndex / arraySome / arrayEvery / arrayForEach
Standard iteration, each taking a callback function
arrayReduce(arr, fn, initial)
Reduce with an (accumulator, value, index) callback
arraySort(arr, fn?) / arrayReverse(arr) / arraySlice(arr, start, end)
Return a new, modified copy: the original array is untouched
arrayConcat(...) / arrayFlat(arr)
Combine arrays, or flatten one level
Every function above that takes a callback throws "{name}() requires a function as its callback argument" if you pass something that isn't one: a common mistake worth checking first if one of these errors unexpectedly.

Date and time#

Function
What it does
unixNow()
Current time in milliseconds
parseDate(v)
Parses a date-like value to unix milliseconds, or null
dateYear / dateMonth / dateDay / dateHour / dateMinute / dateSecond / dateWeekday (v, tz?)
Individual date parts (weekday: 0 = Sunday)
dateFormat(v, fmt='YYYY-MM-DDTHH:mm:ss', tz?)
Formats using tokens like YYYY MM DD HH mm ss, or 'ISO'
dateAdd(v, amount, unit)
Adds a calendar amount (unit = second/minute/hour/day/week/month/year), DST-safe
timestampToSeconds(str) / secondsToTimestamp(v, format?) / msToTimestamp(v, format?)
Convert between a HH:MM:SS-style timestamp and a numeric duration
timeOffset(time, offset, hr12?)
Adds an offset to a time-of-day string
timeDiff(from, to)
Seconds between two times
Every date/time function accepts an optional IANA timezone name; without one, it uses your configured default time zone.

Variable lookup#

Function
What it does
getVariable(name) / getVariable(label, name)
Reads a variable's current value dynamically: this is the only supported way to look up a variable by a computed name; the older getVariableValue alias was removed in v1.8
parseVariables(str, undefinedValue?)
Substitutes every $(...) reference found inside a string and returns the resolved result: this is also how you get inside-out nested-reference resolution inside an expression, since $(...) itself doesn't nest as a literal token (see Understand nested variables)

Clock-driven functions#

Function
What it does
blink(interval, dutyCycle=0.5)
Returns 1/0, toggling on a repeating interval (minimum 100ms)
oscillate(period, waveform='sine', phase=0)
Returns a continuous 0–1 value cycling over a period; waveform is sine, triangle, sawtooth, or square

Note

blink, oscillate, and parseVariables only work where Buttons can supply a live clock/variable context: on a button, feedback, or similar continuously-evaluated field. They throw "{name} is not supported here" inside a Workflow Expression node, which evaluates once and has no ongoing context to re-run against.

Constant#

PI is available as a bare identifier (Math.PI), not a function call.

The $(...) variable reference#

Inside $(...), use letters, digits, _, -, :, and . to identify a variable: Buttons reads this as a dot-joined path (for example ns.a). The reference is read as one opaque token up to its first ); it does not parse a literal nested $(...) inside it. See Understand nested variables for the two mechanisms that do support nesting in practice.

Errors you might see while authoring an expression#

Message
What it means
Unsupported function "{name}"
The function name doesn't exist: check spelling, and remember getVariableValue was removed in v1.8 (use getVariable).
{name}() requires a function as its callback argument
An array function like arrayMap was called without a real callback function.
{name} is not supported here
You called blink, oscillate, or parseVariables somewhere without a live clock/variable context, such as a Workflow Expression node.
Unsupported syntax "{type}" / Unsupported binary/logical/assignment operator "{op}"
The expression uses a construct or operator that isn't on the supported list.
Only direct function calls are supported
You tried to call a method on a value (a.b()) rather than calling a plain function.
Access to property "{property}" is not allowed
The expression touched a banned property name (__proto__, constructor, prototype, and similar).
Expression evaluation exceeded the maximum number of operations / ...maximum call depth
The expression is too large or recurses too deeply to safely evaluate: simplify it.

If you get stuck#

What you see
What to try
A function you expect to exist throws "Unsupported function."
Double check the exact name against this page: a similar-sounding function elsewhere in JavaScript may not exist here.
blink/oscillate/parseVariables throws "not supported here."
You're likely inside a Workflow Expression node: these only work in continuously-evaluated contexts like a button or feedback.
A $(something_$(something_else))-style nested reference doesn't resolve as expected inside an expression.
Use parseVariables(...) instead: the $(...) token itself doesn't parse a literal nested reference.
An array function throws about needing a callback.
Confirm you're actually passing a function, not a value, as that argument.

Where to go next#

  • Update expressions for v1.8
  • Understand nested variables
  • Use variables in controls and expressions

Was this helpful?

Was this helpful?

0 of 0 users found this page helpful