This tutorial is for:
By completing this tutorial, you will:
onTrack callback to detect successful widget initializationBefore starting this tutorial, ensure you have:
onTrack callbackThis tutorial builds on the concepts from the Adding Loading Indicators tutorial. If you're new to onTrack callbacks, review that tutorial first.
In many UX scenarios, you want to show UI controls (buttons, tabs, toggles) only when the associated widget loads successfully:
Using the silent error mode hides errors but doesn't help you conditionally display UI elements. You need programmatic error detection.
Load widgets in a hidden container, check for successful initialization using onTrack, then move them to the visible area and display related controls only if no errors occurred.
Create two separate areas: a hidden loading area for widgets, and a visible content area for UI controls.
<!DOCTYPE html>
<html lang="en">
<head>
<title>Conditional Widget Display</title>
<style>
#your-content {
display: flex;
align-items: center;
justify-content
#your-content - Contains UI controls that should only appear when the widget loads successfully. Initially, the button is hidden.
#loading-area - Hidden container where widgets load. This prevents users from seeing widgets during initialization or if errors occur.
#widget - The actual widget element, initially hidden with display: none within the hidden loading area.
Obtain references to all HTML elements you'll need to manipulate.
// Get the HTML elements from the document
const loadingArea = document.getElementById('loading-area');
const pageContent = document.getElementById('your-content');
const widget = document.getElementById('widget');
const button = document.getElementById('toggle');Load the widget framework with your configuration.
(function(a,b,c,d,e,f,g,h,i){a[e]||(i=a[e]=function(){(a[e].q=a[e].q||[]).push(arguments)},i.l=1*
Create a callback that listens for successful widget loading and moves the widget to the visible area.
// Function to listen to widget events
const onTrack = (eventType, data) => {
if (eventType === 'data_change') {
if (!data.error) {
// Widget loaded successfully - move it to visible area
loadingArea.removeChild(widget);
pageContent.appendChild(widget);
button
Understanding the Logic Flow
data_change event - Fired when widget receives data (successful or error)!data.error means no errors occurredThe widget continues to exist in the hidden loading area if an error occurs. Users never see broken widgets or empty spaces.
Create a function to toggle widget visibility when the button is clicked.
// Toggle widget visibility on button click
const onWidgetToggle = () => {
widget.style.display = widget.style.display === 'none' ? 'block' : 'none';
}
button.onclick = onWidgetToggle;This toggle function only becomes accessible because the button is only displayed when the widget loaded successfully.
Initialize the widget with the onTrack callback.
SIR("addWidget", "#widget", "match.scoreboard", {
matchId: 43406689,
onTrack: onTrack
});View Complete Working Example
<!DOCTYPE html>
<html lang
You can extend this pattern to handle multiple widgets:
Handle errors explicitly with custom messaging:
const onTrack = (eventType, data) => {
if (eventType === 'data_change') {
if (!data.error) {
// Success: move widget and show controls
loadingArea.removeChild(widget);
pageContent.appendChild(widget);
Symptom: The toggle button shows up, but clicking it doesn't display the widget.
Cause: The widget wasn't properly moved from the loading area.
Solution: Verify the DOM manipulation in your onTrack callback:
// Check in browser console
console.log('Widget parent:', widget.parentElement);
// Should show #your-content, not #loading-areaSymptom: Widget flashes on screen then vanishes.
Cause: Multiple data_change events firing without proper flag management.
Solution: Add a flag to track widget movement:
let widgetMoved = false;
const onTrack = (eventType, data) => {
if (eventType === 'data_change' && !data.error && !widgetMoved) {
loadingArea.removeChild(widget);
pageContent.appendChild(widget);
button.style.display =
Symptom: Uncaught DOMException: Failed to execute 'removeChild'
Cause: Trying to remove a widget that isn't a child of the loading area.
Solution: Check parent before removing:
if (widget.parentElement === loadingArea) {
loadingArea.removeChild(widget);
pageContent.appendChild(widget);
}Load widgets in a hidden container to prevent displaying broken widgets or errors. Only move them to visible areas after confirming successful initialization.
Use !data.error in the onTrack callback to programmatically detect successful widget loading before showing UI controls.
Moving widgets between containers with removeChild and appendChild gives you full control over when and where widgets appear.
onTrack usage for loading statesThis double-hiding approach (loading area hidden AND widget hidden) gives you fine-grained control over when and where the widget appears.
const widgets = [
{ id: 'widget-1', matchId: 43406689 },
{ id: 'widget-2', matchId: 43406690 },
{ id: 'widget-3', matchId: 43406691 }
];
const createOnTrack = (widgetId, buttonId) => {
return (eventType, data) => {
if (eventType === 'data_change' && !data.error) {
const widget = document.getElementById(widgetId);
const button = document.getElementById(buttonId);
const loadingArea = document.getElementById('loading-area');
const pageContent = document.getElementById('your-content');
loadingArea.removeChild(widget);
pageContent.appendChild(widget);
button.style.display = 'block';
}
};
};
// Load each widget with its own callback
widgets.forEach((config, index) => {
SIR("addWidget", `#${config.id}`, "match.scoreboard", {
matchId: config.matchId,
onTrack: createOnTrack(config.id, `toggle-${index}`)
});
});