Developer Portal
Quick StartsComposition scriptingAPIs and SDKsSupport
  • Portal overview
  • Quick start
  • REST API
    • Introduction
    • Rate limits
    • Authorization
    • How-to guides
      • Get a control app's API token
      • Get a composition's sub-composition IDs and names and their payload structures
      • Get a control app's model
      • Get a control app's metadata
      • Update a sub-composition's content
      • Update a sub-composition's animation state
      • Update a sub-composition's content and animation state in one call
      • Update multiple sub-compositions in one call
    • API reference
      • Get control app details
        • Get a control app's metadata
        • Get a control app's model
        • Get a control app's control data
      • Send data to a control app
        • Update a control app's content
        • Update a control app's animation state
      • Take out all of an app's output
  • Data stream API
    • Introduction
    • Rate limits
    • Authorization
    • How-to guides
      • Create a data stream
      • Link a data stream to a composition
      • Send data to an app using the data stream API
    • API reference
  • Composition scripting
    • Introduction
    • Overview
    • Quick start
      • Find sub-compositions and widgets
      • Read and update control nodes
      • Set text widget text properties
      • Read and update widget properties
      • Read control nodes and update widget properties
      • Set image widget URL property
      • Set table widget content property
    • Cheat sheets
      • Fundamentals
      • Interactive overlays
      • Best practices
    • Use cases
      • Read control nodes and generate HTML text
      • Read control nodes, generate HTML text with background
      • Text Ticker - Start ticker on "In" animation
    • Composition script editor reference
  • Software development kits
    • Graphics SDK
      • Getting started
      • Reference
        • SDK functions
        • Composition object
        • Sequencer object
      • Guides and examples
        • Load a composition with its token
        • Load a composition with its URL
        • Get the composition URL of an app instance
        • Sequencer VOD example
        • Control local preview of app
        • Load app instance output
    • Overlay SDK
      • Getting started
      • SDK functions
      • Use case examples
    • Widget SDK
      • Preparing your environment
      • Getting started
      • Reference
        • Widget UI definition
        • Widget callback functions
        • Time control object
        • Composition instance
      • Guides and examples
        • Widget example: CSS patterns
    • App SDK
  • Singular Basics
    • Overview of Singular
    • Managing overlays in the Dashboard
      • How to create a new composition
      • How to open a new app template
      • How to create an app for a composition
      • How to extract a composition from an app
      • How to find an app's shared app token and shared API URL
      • Dashboard reference
    • Building overlays in Composer
      • How to build a composition
      • How to set up layer logic to automate overlay transitions
      • How to set up control nodes to make widget properties available to a control app
      • Animating overlays
        • How to create timeline animations
        • How to create behavior animations
        • How to create update animations
      • How to make overlays interactive
      • How to adapt overlays to various screen sizes
      • Composer reference
    • Controlling overlays in Studio and UNO
      • How to use Studio
      • Studio reference
      • UNO reference
  • Support
    • Singular status
    • Support resources
    • Singular terminology
    • Performance Testing
Powered by GitBook
On this page
  • Composition scripting fundamentals
  • The global script
  • Sub-composition scripts
  • Object types, properties, and methods
  • The composition object
  • The widget object
  • Context and utility functions
  • Event listener

Was this helpful?

  1. Composition scripting
  2. Cheat sheets

Fundamentals

PreviousCheat sheetsNextInteractive overlays

Last updated 2 months ago

Was this helpful?

This section of the composition scripting documentation includes essential cheat sheets for the following:

  • The

  • The

Composition scripting fundamentals

The initialization of composition scripts works from the bottom up and starts from the lowest child up to the root.

All composition scripts have an init() and a close() function. Initialize your custom code and variables in the init() function and use the close() function to clean up memory and clear timeouts and intervals.

The global script

Global Script
(function() {

  return {

    init: function(context) {
      // ...
    },

    close: function() {
      // ...
    }
  };
})();

The init function is called after the script is evaluated. The context provides access to common objects, including global storage and utility functions.

The close function is called when the script is unloaded, for example when a browser tab is closed. Use it to clean up memory and clear timeouts, intervals, XHR requests, etc.

Sub-composition scripts

Root & sub-composition Script
(function() {

  return {

    init: function(comp, context) {
      // ...
    },

    close: function(comp, context) {
      // ...
    }
  };
})();

The init function is called after the script is evaluated. The comp argument contains the composition object the script is attached to. The context provides access to common objects, including custom global objects and utility functions.

The close function is called when the script is unloaded, e.g. when closing the browser tab. Use it to clean up memory and clear timeouts, intervals, XHR requests, etc.

Object types, properties, and methods

The composition object

The composition object provides methods to navigate through the composition structure, read and update content, transformation and effects parameters, access the DOM element, and trigger animations.

The most frequently used methods are:

Composition object properties and methods
> find: ƒ ()
> findGroup: ƒ ()
> findWidget: ƒ ()
> getPayload: ƒ ()
> getPayload2: ƒ ()
> getState: ƒ ()
> getSubcompositionById: ƒ (t)
> id: "1234-5678-abcd-efgh"
> jumpTo: ƒ (i)
> listSubcompositions: ƒ ()
> name: "subCompName"
> parent: ƒ ()
> playTo: ƒ (i)
> setPayload: ƒ (i)

find()

Returns an array of composition objects that matches the defined search string.

// We use the first composition with the matching name
const compClock = comp.find("Clock")[0];

findGroup()

Returns an array of group objects that matches the defined search string.

// We use the first group with the matching name
const groupLowers = comp.findGroup("Lowers Group")[0];

findWidget()

Returns an array of widget objects that matches the defined search string.

// We use the first widget with the matching name
const wiTitle = comp.findWidget("Title")[0];

// Find the first matching widget in a group
const wiTeam1Name = comp.findWidget("Team1 Group", "teamName")[0];
const wiTeam2Name = comp.findWidget("Team2 Group", "teamName")[0];

getPayload()

Returns the control node content from the composition as an array of key value pairs.

const payload = comp.getPayload();
console.log(payload);
Debug console
> [
>   {
>     "key": "Title",
>     "value": "The Title"
>   }
> ]

getPayload2()

Returns the control node content from the composition as a JSON object.

const payload = comp.getPayload2();
console.log(payload);
Debug console
> {
>   "Title": "The Title"
> }

getState()

Returns the animation state of the composition.

Animation state
Description

In

Timeline at In state

Out

Timeline at Out state

Out1

Timeline 1 at Out state

Out2

Timeline 2 at Out state

const animState = comp.getState();
console.log(animState );
Debug console
> In

getSubcompositionById()

Returns the composition object defined by its ID.

const compClock = comp.getSubcompositionById("ceedfea8-c060-6d2e-2199-c5f794dcbd16");

id

The composition ID.

console.log(compClock.id);
Debug console
> ceedfea8-c060-6d2e-2199-c5f794dcbd16

jumpTo()

Jumps to the specified animation state.

comp.jumpTo("In");

listSubcompositions()

Returns an array of JSON objects containing sub-composition names and IDs.

const subcomps = comp.listSubcompositions();
Debug console
> [
>   {
>     "id": "-NHTgDrKFKdlaexZeerp",
>     "name": "Clock"
>   }, {
>     ...
>   }
> ]

name

The composition name.

console.log(compClock.name);
Debug console
> Clock

parent()

Returns the parent composition object.

const compParent = comp.parent();

playTo()

Plays the animation to the specified state.

comp.playTo("In");

setPayload()

Sets the control node content of the composition.

const payload = {"Title": "The Title"};
comp.setPayload(payload);

The widget object

The widget object provides methods to read and update widget specific properties, transformation and effects parameters, and access the Dom element.

The most frequently used methods are:

Widget Object Properties and Methods
> getDomElement: ƒ (t)
> getPayload: ƒ ()
> getPositionX: ƒ (o)
> getPositionY: ƒ (o)
> getRotateZ: ƒ (o)
> getSizeX: ƒ (o)
> getSizeY: ƒ (o)
> getVisibility: ƒ (o)
> id: "262ec4f4-3a1d-43ee-90c5-20116e8b2e49"
> setPayload: ƒ (o)
> setPositionX: ƒ (o)
> setPositionY: ƒ (o)
> setRotateZ: ƒ (o)
> setSizeX: ƒ (o)
> setSizeY: ƒ (o)
> setVisibility: ƒ (o)

getDomElement()

Returns the HTML Dom element for the widget.

const wiDom = wiText.getDomElement();
console.log(wiDom);
Debug console
> <div data-singular-type="widget" data-singular-name="Text" id="onair262ec4f4-3a1d-43ee-90c5-20116e8b2e49" 
> style="position: absolute; left: 25%; top: 42.5%; height: 15%; width: 50%; visibility: inherit; z-index: -1; pointer-events: none; opacity: 1;">
> ...
> subComp</div></div></div>

getPayload()

Returns the widget type specific properties as a JSON object.

const propsText= wiTitle.getPayload();
console.log(props.Text);
Debug console
> {
>   "color": {...},
>   "font": {...},
>   "indent": 0,
>   "letterSpacing": 0,
>   "lineHeight": "normal",
>   "lineHeightCustom": 115,
>   "maximumOfLines": 1,
>   "minimumOfLines": 1,
>   "overflow": "adjustLetterWidth",
>   "paddingActive": false,
>   "paddingBottom": 0,
>   "paddingLeft": 0,
>   "paddingRight": 0,
>   "paddingTop": 0,
>   "shadowActive": false,
>   "shadowBlur": 2,
>   "shadowColor": {...},
>   "shadowDirection": 45,
>   "shadowDistance": 3,
>   "text": "The Title",
>   "transform": "none",
>   "verticalAdjustment": 0,
>   "verticalAlignment": "baseline",
>   "wordSpacing": 0
> }

getPositionX(), getPositionY()

Returns the positionX or positionY value in a percentage.

const posX = wiText.getPositionX();
const posY = wiText.getPositionY();
console.log("posX = %d, posY = %d", posX, posY);
Debug console
> posX = 50, posY = 50

getRotationZ()

Returns the rotationZ value in degrees.

const rotZ = wiText.getRotationZ();
console.log("rotZ = %d", rotZ);
Debug console
> rotZ = 90

getSizeX(), getSizeY()

Returns the sizeX or sizeY value in a percentage.

const sizeX = wiText.getSizeX();
const sizeY = wiText.getSizeY();
console.log("sizeX = %d, sizeY = %d", sizeX, sizeY );
Debug console
> sizeX = 25, sizeY = 80

getVisibility()

Returns the visibility as a boolean.

const isVisible = wiText.getVisibilty();
console.log("isVisible =", isVisible );
Debug console
> isVisible = true

id

Returns the widget ID.

console.log(wiText.id);
Debug console
"262ec4f4-3a1d-43ee-90c5-20116e8b2e49"

setPayload()

Sets one or multiple widget specific properties.

wiText.setPayload({"text": "The new title"});

setPositionX(), setPositionY()

Sets the positionX or positionY value in a percentage.

wiText.setPositionX(75);
wiText.setPositionY(50);

setRotateZ()

Sets the rotationZ value in degrees.

wiText.setRotationZ(180);

setSizeX(), setSizeY()

Sets the sizeX or sizeY value in a percentage.

wiText.setSizeX(50);
wiText.setSizeY(25);

setVisibility()

Sets the visibility as a boolean.

wiText.setVisibility(false);

Context and utility functions

{
  "global": {},
  "utils": {
    createDataStream: ƒ (t,e,i)
    createMoment: ƒ i()
    createTinyColor: ƒ c(e,t)
    getSingularWindow: ƒ ()
  }
}

global:{}

A custom global object including variables, objects, and functions.

utils.createDataStream()

Creates a data stream listener.

Create and close a Data Stream
(function() {

  //  https://support.singular.live/hc/en-us/articles/360056901272-Data-Stream-Manager
  const data_stream_public_token = "your-data-stream-public-token";
  
  // we define the datas tream variable in the global scope
  let datastream = undefined;

  return {

    init: function(comp, context) {

      // we create the data stream object using the public token
      datastream = context.utils.createDataStream(data_stream_public_token,
        (status, payload) => {
          switch (status) {
            case "message":
              console.log("we have received data:", status, payload);
              break;
            case "connecting":
            case "connect":
            case "open":
            case "close":
            case "disconnect":
              console.log("status:", status);
              break;
            case "error":
              console.error("error:", status);
              break;
          }
        });

    },

    close: function(comp, context) {
      // we close the data stream connection
      if (datastream != undefined) {
        datastream.close();
      }
    }
  };
})();

utils.createMoment()

Creates a momentjs object.

Create a momentjs object.
const myMoment = context.utils.createMoment(1694178435003);
console.log("myMoment =", myMoment.format("HH:MM:SS"));
Debug console
> myMoment = 20:09:00

utils.createTinyColor()

Creates a tinycolor object.

Create a tinyColor object
const myColor = context.utils.createTinyColor("rgb (255, 0, 0)");
const hsl = myColor.toHsl();
const hslString = myColor.toHslString();

console.log("hsl =", JSON.stringify(hsl));
console.log("hslString =", hslString);

// calculate text color depending on the background color
const bgColor = "crimson";
const textColor = context.utils.createTinyColor(bgColor).isDark() ? "#FFFFFF" : "000000";
console.log("textColor =", textColor);
Debug console
hsl = {"h":0,"s":1,"l":0.5,"a":1}
hslString = hsl(0, 100%, 50%)
textColor = #FFFFFF

utils.getSingularWindow()

Returns the render window name.

const singularWindow = context.utils.getSingularWindow();
console.log("Singular window name:", singularWindow);
Debug console
> Singular window name: app_output or app_control or script_editor

Event listener

comp.addListener(eventType, callbackFunction)

The addListener() method attaches an event handler to the composition without overwriting existing event handlers. You can add multiple event handlers for the same event type.

The first parameter defines the type of the event. Event types include:

The second parameter is a function that you call when an event occurs.

payload_changed

This event occurs when the control nodes of the composition or a sub-composition changes.

The callback function receives three parameters:

  • event: the type of the event

  • msg: a JSON object containing the composition ID, name, and payload

  • e: an event handle

comp.addListener('payload_changed', (event, msg, e) => {
  if (msg.compositionId === comp.id) {
    console.log("listen to:", event);
    console.log("msg:", msg);
  }
  e.stopPropagation();
});
Debug console
> listen to: payload_changed
> msg: {
>   "compId": "...",
>   "compName": "subComp",
>   "compositionId": "...",
>   "compositionName": "subComp",
>   "payload": {
>     "Title": "The Title."
>   }
> }

state_changed

This event occurs at the end of an animation when the animation state of the composition or a sub-composition changes.

The callback function receives three parameters:

  • event: the type of the event

  • msg: a JSON object containing the composition ID, name, and new animation state

  • e: an event

comp.addListener('state_changed', (event, msg, e) => {
  if (msg.compositionId === comp.id) {
    console.log("listen to:", event);
    console.log("msg:", msg);
  }
  e.stopPropagation();
});
Debug console
> listen to: state_changed
> msg: {
>   "compositionId": "...",
>   "compositionName": "subComp",
>   "state": "In", "Out", "Out1", "Out2"
> }

timeline_event

This event occurs at the start and end of an animation of the composition or a sub-composition.

The callback function receives three parameters:

  • event: the type of the event

  • msg: a JSON object containing the composition ID, name, and timeline event details

  • e: an event

comp.addListener('timeline_event', (event, msg, e) => {
  if (msg.compositionId === comp.id) {
    const message = msg.message;
    console.log("listen to:", event);
    console.log("timeline event:", message.event);
    console.log("msg:", msg);
  }
  e.stopPropagation();
});
Debug console
> listen to: timeline_event
> timeline event: start
> msg: {
>   "compositionId": "...",
>   "compositionName": "subComp",
>   "message": {
>     "event": "start",
>     "direction": "forward",
>     "timeline": "In",
>     "currentTime": 0,
>     "duration": 0.8,
>     "targetState": "In"
>   }
> }

> listen to: timeline_event
> timeline event: stop
> msg: {
>   "compositionId": "...",
>   "compositionName": "subComp",
>   "message": {
>     "event": "stop",
>     "duration": 0.8,
>     "currentTime": 0.8,
>     "direction": "forward",
>     "timeline": "In",
>     "targetState": "In"
>   }
> }

datanode_payload_changed

This event occurs when a data node of the composition or a sub-composition changes.

The callback function receives three parameters:

  • event: the type of the event

  • msg: a JSON object containing the composition ID, name, and data node details

  • e: an event

comp.addListener('datanode_payload_changed', (event, msg, e) => {
  console.log("listen to:", event);
  console.log("msg:", msg);
  e.stopPropagation();
});
Debug Console
> listen to: datanode_payload_changed
> msg: {
>   "compId": "...",
>   "compName": "subComp",
>   "compositionId": "...",
>   "compositionName": "subComp",
>   "payload": {
>     ...
>   }
> }

message

This event occurs when the graphics SDK, widgets, and interactive events send custom messages to the comp or a sub comp.

The callback function receives three parameters:

  • event: the type of the event

  • msg: a JSON object containing the composition ID, name, details and payload

  • e: an event

comp.addListener('message', (event, msg, e) => {
  if (msg.params && msg.params.compId === comp.id) {
    console.log("listen to:", event);
    console.log("msg:", msg);
  }
  e.stopPropagation();
});

The following logs show the msg object returned by interactive events.

Debug console
> listen to: message
> msg: {
>  "params": {
>    "type": "widget", or "group"
>    "name": "bgButton",
>    "id": "e9a3f5e5-7c19-6f83-8a0e-ecc43dca3997",
>    "compId": "-NHgm9qQim1PjR0Ecnxa",
>    "event": {
>      "button": 0,
>      "shiftKey": false,
>      "altKey": false,
>      "ctrlKey": false,
>      "metaKey": false,
>      "screenX": 848,
>      "screenY": 370,
>      "clientX": 344,
>      "clientY": 269,
>      "offsetX": 334,
>      "offsetY": 2,
>      "layerX": 307,
>      "layerY": 109,
>      "movementX": 0,
>      "movementY": 1,
>      "pageX": 344,
>      "pageY": 269,
>      "x": 344,
>      "y": 269
>    },
>    "info": ""
>  },
>  "type": "mouseenter" or "mousedown" or "mouseleave" or "mouseenter"
> }

Create a Data Stream in the !

For a detailed description of the momentjs library visit .

For a detailed description of the tinycolor library visit

Composition scripting fundamentals
global script
Sub-composition scripts
Object types, properties, and methods
composition object
The widget object
Context and utility functions
Event listeners
Data Stream Manager
https://momentjs.com/
https://github.com/bgrins/TinyColor
payload_changed
state_changed
timeline_event
datanode_payload_changed
message