Global Scripts
Global Scripts
Global Scripts are view-level JavaScript files that execute once after a view finishes loading and all components have been rendered. They provide a way to apply cross-component logic, override behaviors, and configure the dashboard programmatically at view initialization time.
When They Execute
Global scripts run once per view load, after all components on the view are fully initialized and rendered. If multiple scripts are attached to a view, they execute sequentially in order.
Unlike component-level
onCreateandonDatascripts, navigation functions (GoTo,Popup,Refresh, etc.) are not blocked in global scripts.
Execution Context
Inside a global script, this is a script-level context object. Use this.parent to access view-wide services and all dashboard components.
When a view has multiple global scripts, they all share the same
thisobject. Properties set by script 1 are available in script 2. This is the standard pattern for splitting setup (e.g., registering helpers) from logic (e.g., configuring components).
this.parent Properties
| Global Scripts | Component Scripts | |
|---|---|---|
| Trigger | Once on view load | Per-event: onCreate, onChange, onData, onTick, onFocus, onDblClick, onHover |
| Scope | View-wide β access all components | Single component instance |
| Navigation functions | Enabled | Blocked during onCreate and onData |
| Editor | Upload .js files or use built-in code editor in View Properties | Inline script editor per event type in Component Properties |
Available Functions
The following functions are automatically available in the script scope. No imports are needed.
Navigation
| Function | Description |
|---|---|
GoTo(name) | Navigate to a view by name |
GoToId(id) | Navigate to a view by ID |
GoToPath(path) | Navigate to a view by path |
GoToUUID(uuid) | Navigate to a view by UUID |
GoBack() | Navigate to the previous view |
GoForward() | Navigate to the next view |
GoToUrl(url, newtab) | Open a URL (optionally in a new tab) |
Popup(id, title, w, h, x, y, alignment) | Open a view in a popup window |
PopupPath(path, ...) | Open a view by path in a popup window |
Refresh() | Reload the current view |
Component Access
| Function | Description |
|---|---|
getComponent(varnam) | Get a component by its variable name |
getComponentGlobal(varnam) | Get a component by variable name, title, or ID |
getComponentByName(name) | Get a component by display name |
getComponentByType(type) | Get all components of a given type (e.g., 'LineChartD3') |
getComponentByLabel(label) | Get a component by label |
Data
| Function | Description |
|---|---|
callDriver(config) | Call a driver function |
getDriver(topic) | Get a driver instance by topic |
tagSearch(config) | Search for tags |
tagSnapshot(config) | Get a snapshot of tag values |
Built-in Variables
| Variable | Description |
|---|---|
_VIEW_ID_ | Current view ID |
_VIEW_NAME_ | Current view name |
_VIEW_PATH_ | Current view path (breadcrumb trail as string) |
_EVENT_ | Event object (always null for global scripts) |
Additionally, all variables defined in the view's Variables tab are injected as constants and available by name.
Script Runner Gotchas
The script runner automatically wraps all injected function calls (e.g., getComponent(, PopupPath() with await. This means:
Do not call injected functions inside non-async callbacks. If you define
btn.onChange = function() { PopupPath(...); }, the runner rewrites it toawait PopupPath(...)inside a non-async function, causing aSyntaxError. Instead, use component-levelonChangescripts (stored as base64 insettings.onChange) which run in their own async context, or store parameters onthisand call the function at the top level.The ` character in string literals can conflict with replacement regex. Prefer
_as a prefix for shortcut properties (e.g.,this._varnaminstead ofthis.$varnam).
How to Add Global Scripts
- Open the view in IOTA Vue
- Click the Edit button in the sidebar toolbar to enter edit mode
- Open View Properties (click the properties/settings icon)
- In the General tab, locate the Scripts section
- Click Upload to add
.jsfiles, or click the Edit icon on an existing script to open the code editor - Save the view to persist the scripts
Examples
Live example views are available under GlobalScripts in the IOTA Vue sidebar. The parent view is a self-extracting pack β click "Extract Samples" to create all 7 examples automatically.
1. Style All Line Charts
View: GlobalScripts/StyleAllLineCharts | Script: style-all-linecharts.js
Sets a custom background color on every LineChartD3 component in the view.
const dashboardComponents = this.parent.$dashboardComponents;
for (let cmp of Object.values(dashboardComponents)) {
if (cmp.item.type === "LineChartD3") {
cmp.settings.visualProperties.bgcolor = "rgb(216, 27, 67)";
}
}2. Time Range by Naming Convention
View: GlobalScripts/TimeRangeByNamingConvention | Script: time-range-by-naming.js
Line charts named LineChart_<days>_<suffix> get their time range set to the specified number of days. The SetTime method is overridden so the range persists on GTC updates.
const MS_PER_DAY = 86400000;
const dashboardComponents = this.parent.$dashboardComponents;
for (let cmp of Object.values(dashboardComponents)) {
if (cmp.item.type === "LineChartD3") {
const setTime = cmp.SetTime;
const match = cmp.settings.varnam.match(/^LineChart_(\d+)_.+$/);
if (match) {
const DAYS = parseInt(match[1], 10);
cmp.SetTime = async (selection) => {
selection[0].startmsec = selection[0].endmsec - DAYS * MS_PER_DAY;
setTime(selection);
};
const endTime = this.parent.$GTCService.rangeEnd.time;
cmp.SetTime([{
startmsec: endTime - DAYS * MS_PER_DAY,
endmsec: endTime
}]);
}
}
}3. Component Shortcut Registry
View: GlobalScripts/ComponentShortcuts | Scripts: component-shortcuts.js, verify-shortcuts.js
When a view has multiple global scripts, they share the same this context. Script 1 registers this._<varnam> shortcuts for every component; script 2 uses them to read live properties. Output appears in a TextAreaPV console on the view.
Script 1 (component-shortcuts.js):
var _dc = this.parent.$dashboardComponents;
var _consoleRef = null;
for (var _k in _dc) {
if (_dc[_k].item.settings && _dc[_k].item.settings.varnam === "consoleLog") {
_consoleRef = _dc[_k]; break;
}
}
this._log = [];
this._logTo = function(msg) {
this._log.push(msg);
if (_consoleRef) _consoleRef.settings.value = this._log.join("\n");
}.bind(this);
var _count = 0;
for (var _ck in _dc) {
var _cmp = _dc[_ck];
var _vn = _cmp.item.settings ? _cmp.item.settings.varnam : null;
if (_vn) { this["_" + _vn] = _cmp; _count++; }
}
this._logTo("=== component-shortcuts.js ===");
this._logTo("");
var _names = Object.keys(this).filter(function(k) {
return k.startsWith("_") && k !== "_log" && k !== "_logTo";
}).sort();
for (var _i = 0; _i < _names.length; _i++) {
var _ref = this[_names[_i]];
var _id = _ref.item.id.substring(0, 8);
this._logTo(" $dashboardComponents[\"" + _id + "...\"] => this." + _names[_i]);
}Script 2 (verify-shortcuts.js):
this._logTo("");
this._logTo("=== verify-shortcuts.js ===");
this._logTo("");
if (this._btnRefresh) {
this._logTo(" this._btnRefresh.settings.label => \"" + this._btnRefresh.settings.label + "\"");
}
if (this._dataTable) {
this._logTo(" this._dataTable.settings.title.titleText => \"" + this._dataTable.settings.title.titleText + "\"");
}4. SubView Tab Navigation
View: GlobalScripts/SubViewTabNavigation | Script: subview-tab-nav.js
Populates a DropDownPV with sibling view names and wires onChange to load them into a SubView. Auto-loads the first option.
var _dc = this.parent.$dashboardComponents;
var _dd = null;
var _sv = null;
for (var _k in _dc) {
if (_dc[_k].item.settings.varnam === "tabSelector") _dd = _dc[_k];
if (_dc[_k].item.settings.varnam === "svContent") _sv = _dc[_k];
}
var _examples = [
{ name: "Example 1: Style All Line Charts", path: "GlobalScripts/StyleAllLineCharts" },
{ name: "Example 2: Time Range by Naming", path: "GlobalScripts/TimeRangeByNamingConvention" },
{ name: "Example 3: Component Shortcuts", path: "GlobalScripts/ComponentShortcuts" },
{ name: "Example 5: Dynamic Table Columns", path: "GlobalScripts/DynamicTableColumns" },
{ name: "Example 6: Popup Workflow", path: "GlobalScripts/PopupWorkflow" },
{ name: "Example 7: Confirm Before Action", path: "GlobalScripts/ConfirmBeforeAction" },
];
_dd.settings.options = _examples;
_dd.settings.componentRelative.optionLabel = "name";
_dd.onChange = function() {
var _sel = _dd.settings.value;
if (_sel && _sel.path) {
_sv.loadView(_sel.path, null, "absolute");
}
};
// Auto-load first option
_dd.settings.value = _examples[0];
_sv.loadView(_examples[0].path, null, "absolute");Use
"absolute"as the third argument toloadView()to prevent the path from being resolved relative to the current view.
5. Popup Workflow
View: GlobalScripts/PopupWorkflow | Script: popup-workflow.js
Wires buttons to open other views in modal popup dialogs. Uses this.parent.$viewPlugin.popupViewPath() directly to avoid the await-in-callback issue with the injected PopupPath() function. Popups only work in locked (runtime) mode.
var dc = this.parent.$dashboardComponents;
var btnDetails, btnHistory, btnConfig;
for (var k in dc) {
var vn = dc[k].item.settings.varnam;
if (vn === "btnDetails") btnDetails = dc[k];
if (vn === "btnHistory") btnHistory = dc[k];
if (vn === "btnConfig") btnConfig = dc[k];
}
btnDetails.settings.label = "Open Details Popup";
btnHistory.settings.label = "Open History Popup";
btnConfig.settings.label = "Open Config Popup";
// Uses this.parent.$viewPlugin.popupViewPath() directly.
var vp = this.parent.$viewPlugin;
btnDetails.onChange = function() {
vp.popupViewPath("GlobalScripts/StyleAllLineCharts", "Chart Style Details", 1000, 700);
};
btnHistory.onChange = function() {
vp.popupViewPath("GlobalScripts/TimeRangeByNamingConvention", "Time Range History", 1000, 700);
};
btnConfig.onChange = function() {
vp.popupViewPath("GlobalScripts/ComponentShortcuts", "Component Configuration", 1000, 700);
};6. Dynamic Table Columns (InputTablePV)
View: GlobalScripts/DynamicTableColumns | Script: dynamic-table-columns.js
Configures an InputTablePV with custom columns and populates it with sample data. Use InputTablePV (not TablePV) when you need a standalone table that accepts data from scripts.
var _dc = this.parent.$dashboardComponents;
var _tbl = null;
for (var _k in _dc) {
if (_dc[_k].item.settings.varnam === "assetTable") _tbl = _dc[_k];
}
_tbl.settings.tableColumnsConfig = [
{ order: 0, field: "name", header: "Asset Name", visible: true },
{ order: 1, field: "status", header: "Status", visible: true },
{ order: 2, field: "temperature", header: "Temp (F)", visible: true },
{ order: 3, field: "pressure", header: "PSI", visible: true },
{ order: 4, field: "updated", header: "Last Updated", visible: true },
];
var _rows = [
{ name: "Pump-A1", status: "Running", temperature: "185", pressure: "42", updated: "10:30 AM" },
{ name: "Pump-B2", status: "Alarm", temperature: "245", pressure: "78", updated: "10:28 AM" },
{ name: "Valve-C3", status: "Idle", temperature: "72", pressure: "14", updated: "10:25 AM" },
{ name: "Motor-D4", status: "Warning", temperature: "210", pressure: "55", updated: "10:31 AM" },
{ name: "Pump-E5", status: "Running", temperature: "178", pressure: "39", updated: "10:32 AM" },
];
_tbl.settings.value = _rows;
_tbl.onRowClick = function(row) {
if (row && row.data) {
console.log("Row clicked:", row.data.name, row.data.status);
}
};7. Confirm Before Action
View: GlobalScripts/ConfirmBeforeAction | Script: confirm-before-action.js
Populates an InputTablePV with data and wires Delete/Add/Clear buttons with confirmDialog() guards. Uses this.parent.$confirm.require() directly to avoid the await-in-callback issue with the injected confirmDialog() function.
var dc = this.parent.$dashboardComponents;
var table, log, btnDelete, btnAdd, btnClear;
for (var k in dc) {
var vn = dc[k].item.settings.varnam;
if (vn === "assetTable") table = dc[k];
if (vn === "actionLog") log = dc[k];
if (vn === "btnDeleteRow") btnDelete = dc[k];
if (vn === "btnAddRow") btnAdd = dc[k];
if (vn === "btnClearAll") btnClear = dc[k];
}
// Populate table (id field required for removeSelected)
table.settings.value = [
{ id: 1, name: "Pump-A1", type: "Centrifugal", status: "Running", location: "Unit 3" },
{ id: 2, name: "Valve-B2", type: "Gate Valve", status: "Open", location: "Unit 1" },
{ id: 3, name: "Motor-C3", type: "Induction", status: "Alarm", location: "Unit 2" },
{ id: 4, name: "Sensor-D4", type: "Thermocouple", status: "Active", location: "Unit 3" },
{ id: 5, name: "Pump-E5", type: "Positive Disp.", status: "Idle", location: "Unit 1" },
];
// Action log helper
var logMessages = ["Ready. Select a row, then click a button."];
function appendLog(msg) {
logMessages.push(new Date().toLocaleTimeString() + " " + msg);
log.settings.value = logMessages.join("\n");
}
log.settings.value = logMessages[0];
// Delete Selected
btnDelete.onChange = function() {
var sel = table.selectedItems;
if (!sel || !sel.name) {
appendLog("No row selected.");
return;
}
var name = sel.name;
this.parent.$confirm.require({
header: "Delete " + name + "?",
message: "Remove " + name + " from the registry permanently?",
icon: "pi pi-exclamation-triangle",
accept: function() {
table.removeSelected();
appendLog("Deleted: " + name);
},
reject: function() {
appendLog("Delete cancelled for " + name);
}
});
}.bind(this);
// Add New Asset
btnAdd.onChange = function() {
this.parent.$confirm.require({
header: "Add New Asset?",
message: "Add a new asset entry to the registry?",
icon: "pi pi-info-circle",
accept: function() {
var id = Date.now();
var tag = "NEW-" + Math.floor(Math.random() * 1000);
var rows = table.settings.value.slice();
rows.push({ id: id, name: tag, type: "Unknown", status: "New", location: "TBD" });
table.settings.value = rows;
appendLog("Added: " + tag);
},
reject: function() {
appendLog("Add cancelled.");
}
});
}.bind(this);
// Clear All
btnClear.onChange = function() {
var count = table.settings.value ? table.settings.value.length : 0;
this.parent.$confirm.require({
header: "Clear All Assets?",
message: "Remove all " + count + " assets? This cannot be undone.",
icon: "pi pi-exclamation-triangle",
accept: function() {
table.settings.value = [];
appendLog("Cleared " + count + " assets.");
},
reject: function() {
appendLog("Clear cancelled.");
}
});
}.bind(this);
appendLog("Buttons configured.");What's Next?
- Component Scripts β per-event scripts on individual components
- Scripting Guide β overview and available functions reference
Related
- Component Scripts β per-component event scripts
- Scripting Guide β the scripting overview and function reference
- Passing Context β share data between displays