Time Span Events

User Interface Example for Angular

Time span events are displayed in a panel that's separate from the time series chart associated with the events. The panel can be displayed or hidden by controls in the charting application's user interface, giving users control over whether to display the time span events.

In this tutorial

You will add a drop-down menu to the chart from the Hello World Example for Angular tutorial. The menu will open and close the time span events panel and selectively show and hide swim lanes of time span events.

Before you begin

This tutorial requires version 8.1.0 or later of the ChartIQ library.

The tutorial is a continuation of the Hello World Example for Angular tutorial. Please complete the Hello World example before proceeding.

Markup

In your editor, open the src/app/chartiq-hello-world folder of your chartiq-angular-app project:
HelloWorldComponent source files

We'll begin by adding markup to the hello-world.component.html file to create a drop-down menu.

<cq-context>

Surround the <div> element that contains the chart with the following tags:

<cq-context></cq-context>

For example:

<cq-context>
<div
    #chartContainer
    class="chartContainer"
    style="
        width: 800px;
        height: 460px;
        position: relative;
        border: solid 1px #aaa
    "></div>
</cq-context>

The cq-context element establishes an area of the markup (a context) for the chart user interface. All chart UI elements are placed within the cq-context element.

Drop-down menu

Add the following markup after the opening <cq-context> tag in hello-world.component.html:

<button>Life Cycle Events</button>
<div id="menu">
    <div>
        <input type="checkbox"/>
        <label for="Filing">Filing</label>
    </div>
    <div>
        <input type="checkbox"/>
        <label for="Business">Business</label>
    </div>
    <div>
        <input type="checkbox"/>
        <label for="Order">Order</label>
    </div>
</div>

<button>

The button will show and hide the div that creates the menu.

We'll eventually add a click handler to give the button control of the menu.

Notice the button text: Life Cycle Events. Time span events are also referred to as life cycle events. We'll use that name here just to help you get familiar with it.

<div id="menu">

The menu div contains three elements that create check boxes for user input. There's a check box for each of the types of time span events we created in the Hello World Example for Angular tutorial: "Filing", "Business", and "Order" (see the swim lane objects in the getTseData function in hello-world.component.ts).

We'll ultimately add click handlers to the check boxes so the event swim lanes can be displayed and hidden individually.

Styling

Let's add some style to our drop-down menu.

Add the following CSS rule-sets to hello-world.component.scss:

// Formats and positions the drop-down menu.
#menu {
    position: absolute;
    z-index: 2;
    background-color: #f5f5f5;
    padding: 10px;
    border: 1px solid;
}

// Spaces the drop-down menu elements.
#menu div {
    padding: 5px;
}

// Formats the drop-down menu input elements.
#menu div input {
    font-size: 0.80rem;
    margin-right: 5px;
    cursor: pointer;
}

// Hides the drop-down menu.
.closed {
    display: none;
}

The first three rule-sets style and position the menu. The last rule-set, .closed, is used to show and hide the menu.

We'll add a conditional class to the menu div to add or remove the closed class. Ultimately, a variable controlled by a click handler on the Life Cycle Events button will provide the condition that adds or removes the class, thereby closing or opening the menu. For now, we'll just set the condition to true.

Add the conditional class to the menu div in hello-world.component.html as follows:

<div id="menu" [ngClass]="{'closed': true}">
    .
    .
    .

Handlers

Now we'll create the click handlers that show and hide the drop-down menu and the time span event swim lanes.

menuOpen = !menuOpen

The click handler that opens and closes the drop-down menu is a single statement that we'll add to the button element in hello-world.component.html:

<button (click)="menuOpen = !menuOpen">Life Cycle Events</button>

The statement toggles the value of the menuOpen variable from true to false or false to true with each click of the button. Initially (before any button clicks), the variable is undefined and therefore false.

Now we can add the variable to the conditional class of the menu div to alternately add or remove the closed class when the button is clicked.

The completed button and menu should look like this:

<button (click)="menuOpen = !menuOpen">Life Cycle Events</button>
<div id="menu" [ngClass]="{'closed': !menuOpen}">
    .
    .
    .

Run it!

Let's try out our new menu.

Start the application by entering the following command in the root directory of your chartiq-angular-app project:

npm start

Load the following in your web browser:

http://localhost:4200/hello-world

Select the Life Cycle Events button; the menu should open. Select the button again; the menu should close.

Life Cycle Events drop-down menu

You should also be able to select and clear the check boxes, although they don't do anything yet. We'll take care of that next.

showMarkers

The showMarkers handler shows and hides time span event swim lanes.

But before we create the handler, we need to make some adjustments to the code in hello-world.component.ts, some of which we created in the Hello World Example for Angular tutorial.

stx property

We're going to need to reference the chart engine in the showMarkers handler, so let's create a class property that can hold a chart engine reference.

Add the following property declaration to the HelloWorldComponent class:

private stx: CIQ.ChartEngine;

ngAfterViewInit method

In the ngAfterViewInit method of HelloWorldComponent, remove the following statements:

stx["timeSpanEventPanel"].showTimeSpanEvent(this.getTseData("Filing"));
stx["timeSpanEventPanel"].showTimeSpanEvent(this.getTseData("Business"));
stx["timeSpanEventPanel"].showTimeSpanEvent(this.getTseData("Order"));

If you're watching the application in a web browser, the Time Span Events panel should have disappeared.

Next, replace all remaining references to stx in the function scope with this.stx (the stx property).

Here's the revised method:

ngAfterViewInit() {
    const container = this.chartContainer.nativeElement;

    this.stx = new CIQ.ChartEngine({ container });

    new CIQ["TimeSpanEventPanel"]({
        stx: this.stx,
        showTooltip: true,
        infoPanel: {
            spanEvent: "main",
            durationEvent: "main",
            singleEvent: "main"
        }
    });

    const el = document.createElement("style");
    el.setAttribute("type", "text/css");
    el.innerText = ".stx-marker.trade .stx-visual {"
        + "width: 8px;"
        + "height: 8px;"
        + "}";
    document.head.appendChild(el);

    this.stx.loadChart('SPY', {
        masterData: this.getMasterData(),
        periodicity: {
            period: 1,
            interval: 5,
            timeUnit: 'minute',
        },
    });

}

We're still creating the instance of the time span events panel in ngAfterviewInit to make the panel an integral part of the chart. The instantiation does not make the panel appear on screen; showMarkers will do that.

Method definition

Now, we're ready to create the click handler.

Add the following method to the HelloWorldComponent class:

showMarkers(eventType) {
    let checkbox = <HTMLInputElement>event.target;
    if (checkbox.checked) {
        this.stx["timeSpanEventPanel"].showTimeSpanEvent(this.getTseData(eventType));
    } else {
        this.stx["timeSpanEventPanel"].removeTimeSpanEvent(eventType);
    }
}

The handler will be attached to the check boxes in the drop-down menu. Each check box will provide a unique eventType argument which specifies a type of time span event, such as "Filing", "Business", or "Order".

The showMarkers method uses the event target to get a reference to the check box that invoked the handler. If the check box has been selected, the method displays the swim lane of time span events specified by eventType. If the check box has been cleared, the method removes the swim lane specified by eventType. The argument for removeTimeSpanEvent is just the event type; no other event data is needed.

The Time Span Events plug-in takes care of opening and closing the time span events panel. For example, when the first swim lane is added, the panel automatically opens; when the last swim lane is removed, the panel closes.

Now we need to set the method as a click handler on the input tags that represent the drop-down menu check boxes.

Add the click handler to hello-world.component.html as follows:

<div>
    <input type="checkbox" (click)="showMarkers('Filing')"/>
    <label for="Filing">Filing</label>
</div>
<div>
    <input type="checkbox" (click)="showMarkers('Business')"/>
    <label for="Business">Business</label>
</div>
<div>
    <input type="checkbox" (click)="showMarkers('Order')"/>
    <label for="Order">Order</label>
</div>

Note: The showMarkers argument must match the type property of a swim lane data object in the getTseData method in hello-world.component.ts. The argument should also correspond to the label of the input element.

UI Context

When the time span events panel is controlled from the user interface, the CIQ.TimeSpanEventPanel constructor function requires a context argument. (If you've tested the app at this point, you should be getting an error when the panel closes.)

CIQ

To create a UI context object, we need a version of the CIQ namespace that has enhanced, UI-specific functionality.

Revise the following line in hello-world.component.ts:

import { CIQ } from 'chartiq/js/chartiq';

to:

import { CIQ } from 'chartiq/js/components';

CIQ now includes the UI namespace, which has the functionality needed to create the chart UI context.

But components.js has advanced.js as a dependency, so you need to move the import statement for advanced.js above the import of the CIQ namespace, for example:

import "chartiq/js/advanced";
import { CIQ } from 'chartiq/js/components';
import "chartiq/plugins/timespanevent/timespanevent";

CIQ.UI.Context

Now we can create a context object. Add the following line to the ngAfterViewInit method just before the TimeSpanEventPanel function call:

const uiContext = new CIQ.UI.Context(this.stx, document.querySelector("cq-context"));

The CIQ.UI.Context constructor function creates the context. The first argument, this.stx, is the chart engine to which the UI context applies. The second argument is the DOM node that contains the UI elements (see cq-context above).

Add the context parameter to the TimeSpanEventPanel function call as follows:

new CIQ["TimeSpanEventPanel"]({
    stx: this.stx,
    showTooltip: true,
    context: uiContext,
    infoPanel: {
        spanEvent: "main",
        durationEvent: "main",
        singleEvent: "main"
    }
});

Close the panel

You may have noticed two controls that appear in the upper left corner of the Life Cycle Events panel when you hover your mouse over the panel. The arrow repositions the panel to the top (or bottom) of the chart. The X closes the panel.

The arrow control works correctly. The X control always closes the panel, but it doesn't clear any check boxes that are checked on the drop‑down menu, and it doesn't remove swim lanes from the panel.

We can fix that with an event listener that responds to layout events, which signal the chart engine that the chart needs to be redrawn (see layoutEventListener). The close control of the time span events panel dispatches a layout event.

Our layout event listener needs to determine which menu check boxes are checked; to do that, it's going to have to query the DOM.

Add template reference variables

We'll enable the DOM query by adding template reference variables to each of the HTML input elements.

Revise the markup for the three check boxes in hello-world.component.html as follows:

<input #checkbox type="checkbox" (click)="showMarkers('Filing')"/>

<input #checkbox type="checkbox" (click)="showMarkers('Business')"/>

<input #checkbox type="checkbox" (click)="showMarkers('Order')"/>

Import ViewChildren and QueryList

We'll query the check boxes as a group.

Add the ViewChildren decorator function and QueryList class to the import statement at the top of hello-world.component.ts as follows:

import { Component, ViewChild, ViewChildren, QueryList, ElementRef, AfterViewInit, ViewEncapsulation } from '@angular/core';

Create the query

Now we can define the DOM query.

Add the following to the HelloWorldComponent class in hello-world.component.ts after the chartContainer query:

@ViewChildren('checkbox') checkboxes: QueryList<ElementRef>;

Create the event listener

Finally, add the following to the bottom of the ngAfterViewInit method in hello-world.component.ts:

this.stx.addEventListener("layout", ({ stx }) => {
    if (!stx.panels.timeSpanEventPanel) {
        this.checkboxes.forEach(checkbox => {
            if (checkbox.nativeElement.checked) checkbox.nativeElement.click();
        });
    }
});

The callback function determines whether the panel is closed (no longer exists). If the panel has been removed, the function iterates through the queried list of check boxes and determines one by one whether they're checked. If a check box is checked, it is programmatically clicked, clearing the check box and calling the click handler, showMarkers, which removes the time span events swim lane associated with the check box.

The completed files

Here are the completed source files.

hello-world.component.html

<div style="margin: 20px;">
<h2>
    Hello world static chart example
</h2>
<cq-context>
    <button (click)="menuOpen = !menuOpen">Life Cycle Events</button>
    <div id="menu" [ngClass]="{'closed': !menuOpen}">
        <div>
            <input #checkbox type="checkbox" (click)="showMarkers('Filing')"/>
            <label for="Filing">Filing</label>
        </div>
        <div>
            <input #checkbox type="checkbox" (click)="showMarkers('Business')"/>
            <label for="Business">Business</label>
        </div>
        <div>
            <input #checkbox type="checkbox" (click)="showMarkers('Order')"/>
            <label for="Order">Order</label>
        </div>
    </div>
    <div
        #chartContainer
        class="chartContainer"
        style="
            width: 800px;
            height: 460px;
            position: relative;
            border: solid 1px #aaa
        ">
    </div>
</cq-context>
</div>

hello-world.component.scss

@import '~chartiq/css/stx-chart.css'; // Chart API

// Customize the sub-event markers and pop-up displays.

// Sub-event marker pop-up displays.
.stx-performance-marker.stx-marker-expand {
    background: rgba(255, 255, 255, 0.90);
    max-width: 200px;
    max-height: 200px;
    padding: 10px;
    opacity: 1;
    color: #000;
    display: block;
    border: 1px solid rgba(180, 180, 180, 0.90);
    overflow: auto;
    position: absolute;
}

// Pop-up display heading text.
.stx-performance-marker.stx-marker-expand h4 {
    display: block;
    font-size: 0.80rem;
}

// Pop-up display body text.
.stx-performance-marker.stx-marker-expand p {
    font-variant: small-caps;
}

// Formats and positions the drop-down menu.
#menu {
    position: absolute;
    z-index: 2;
    background-color: #f5f5f5;
    padding: 10px;
    border: 1px solid;
}

// Spaces the drop-down menu elements.
#menu div {
    padding: 5px;
}

// Formats the drop-down menu input elements.
#menu div input {
    font-size: 0.80rem;
    margin-right: 5px;
    cursor: pointer;
}

// Hides the drop-down menu.
.closed {
    display: none;
}

hello-world.component.ts

import { Component, ViewChild, ViewChildren, QueryList, ElementRef, AfterViewInit, ViewEncapsulation } from '@angular/core';

import "chartiq/js/advanced";
import { CIQ } from 'chartiq/js/components';
import "chartiq/plugins/timespanevent/timespanevent";

/**
 * The Hello World component creates a basic chart from a built-in static data source. The chart
 * does not have a user interface.
 */
@Component({
    selector: 'cq-hello-world',
    templateUrl: './hello-world.component.html',
    styleUrls: ['./hello-world.component.scss'],
    encapsulation: ViewEncapsulation.None
})
export class HelloWorldComponent implements AfterViewInit {
    @ViewChild('chartContainer', { static: true }) chartContainer: ElementRef;
    @ViewChildren('checkbox') checkboxes: QueryList<ElementRef>;

    private stx: CIQ.ChartEngine;

    constructor() {}

    ngAfterViewInit() {
        const container = this.chartContainer.nativeElement;

        this.stx = new CIQ.ChartEngine({ container });

        const uiContext = new CIQ.UI.Context(this.stx, document.querySelector("cq-context"));

        new CIQ["TimeSpanEventPanel"]({
            stx: this.stx,
            showTooltip: true,
            context: uiContext,
            infoPanel: {
                spanEvent: "main",
                durationEvent: "main",
                singleEvent: "main"
            }
        });

        const el = document.createElement("style");
        el.setAttribute("type", "text/css");
        el.innerText = ".stx-marker.trade .stx-visual {"
            + "width: 8px;"
            + "height: 8px;"
            + "}";
        document.head.appendChild(el);

        this.stx.loadChart('SPY', {
            masterData: this.getMasterData(),
            periodicity: {
                period: 1,
                interval: 5,
                timeUnit: 'minute',
            },
        });

        this.stx.addEventListener("layout", ({ stx }) => {
            if (!stx.panels.timeSpanEventPanel) {
                this.checkboxes.forEach(checkbox => {
                    if (checkbox.nativeElement.checked) checkbox.nativeElement.click();
                });
            }
        });

    }

    /**
     * Shows and hides time span event swim lanes.
     *
     * @param eventType Specifies the type of time span events to be shown or hidden. Must match
     *      the `type` property of a swim lane data object.
     */
    showMarkers(eventType) {
        let checkbox = <HTMLInputElement>event.target;
        if (checkbox.checked) {
            this.stx["timeSpanEventPanel"].showTimeSpanEvent(this.getTseData(eventType));
        } else {
            this.stx["timeSpanEventPanel"].removeTimeSpanEvent(eventType);
        }
    }

    /**
     * Gets the data for a swim lane of time span events.
     *
     * @param eventType Specifies the type of time span event. Must match the `type` property of
     *      a swim lane data object.
     * @return A swim lane data object, which contains an array of time span events.
     */
    getTseData(eventType) {

        // Span events.
        const businessEvents = [
            {
                label: "Business",
                spanLabel: "Product Demo",
                startDate: "2020-04-01T09:30:00",
                endDate: "2020-04-01T11:00:00",
                bgColor: "#00f",
                headline: "New Product",
                story: "Presentation to media."
            },
            {
                label: "Business",
                spanLabel: "Board Meeting",
                startDate: "2020-04-01T12:00:00",
                endDate: "2020-04-01T16:00:00",
                bgColor: "#f90",
                textColor: "#000"
            },
        ];

        // Single events.
        const filingEvents = [
            {
                label: "Filing",
                startDate: "2020-04-01T11:30",
                markerShape: "square",
                bgColor: "#a09",
                headline: "SEC Filing",
                story: "10K"
            },
            {
                label: "Filing",
                startDate: "2020-04-01T14:35:00",
                markerShape: "square",
                bgColor: "#0a0",
                headline: "SEC Filing",
                story: "10Q"
            }
        ];

        // Duration events.
        const orderEvents = [
            {
                label: "Order",
                startDate: "2020-04-01T10:00",
                endDate: "2020-04-01T11:45",
                markerShape: "circle",
                category: "trade",
                subChildren: [
                    {
                        date: new Date("2020-04-01T10:10:00"),
                        price: 156.46,
                        headline: "Trade Execution",
                        story: "Price: 156.46"
                    },
                    {
                        date: new Date("2020-04-01T10:40:00"),
                        price: 156.50,
                        headline: "Trade Execution",
                        story: "Price: 156.50"
                    },
                    {
                        date: new Date("2020-04-01T11:20:00"),
                        price: 156.43,
                        headline: "Trade Execution",
                        story: "Price: 156.43"
                    },
                    {
                        date: new Date("2020-04-01T11:45:00"),
                        price: 156.54,
                        headline: "Trade Execution",
                        story: "Price: 156.54"
                    }
                ],
                headline: "Trade Start",
                story: new Date("2020-04-01T10:00"),
                bgColor: "#aa0"
            },
            {
                label: "Order",
                startDate: "2020-04-01T13:00",
                endDate: "2020-04-01T15:25",
                markerShape: "circle",
                category: "trade",
                subChildren: [
                    {
                        date: new Date("2020-04-01T13:50:00"),
                        price: 156.55,
                        headline: "Trade Execution",
                        story: "Price: 156.55"
                    },
                    {
                        date: new Date("2020-04-01T14:25:00"),
                        price: 156.45,
                        headline: "Trade Execution",
                        story: "Price: 156.45"
                    },
                    {
                        date: new Date("2020-04-01T15:25:00"),
                        price: 156.54,
                        headline: "Trade Execution",
                        story: "Price: 156.54"
                    }
                ],
                headline: "Trade Start",
                story: new Date("2020-04-01T10:40"),
                bgColor: "#0af",
                isActive: true
            }
        ];

        // Swim lane objects.

        const business = {
            type: "Business",
            events: businessEvents,
            spanType: "spanEvent"
        }

        const filing = {
            type: "Filing",
            events: filingEvents,
            spanType: "singleEvent"
        }

        const order = {
            type: "Order",
            events: orderEvents,
            spanType: "durationEvent"
        }

        switch (eventType.toLowerCase()) {
            case "business":
                return business;
            case "filing":
                return filing;
            case "order":
                return order;
        }

    }

    getMasterData() {
        const masterData = [
            {Date:"20200331144000000",Open:156.64,High:156.66,Low:156.57,Close:156.59,Volume:932912},
            {Date:"20200331145000000",Open:156.58,High:156.62,Low:156.57,Close:156.61,Volume:700952},
            {Date:"20200331145500000",Open:156.59,High:156.60,Low:156.55,Close:156.58,Volume:1084428},
            {Date:"20200331150000000",Open:156.57,High:156.58,Low:156.53,Close:156.55,Volume:916684},
            {Date:"20200331150500000",Open:156.54,High:156.57,Low:156.52,Close:156.55,Volume:1360390},
            {Date:"20200331151000000",Open:156.56,High:156.60,Low:156.54,Close:156.58,Volume:2037170},
            {Date:"20200331151500000",Open:156.55,High:156.62,Low:156.54,Close:156.60,Volume:4280833},
            {Date:"20200331152000000",Open:156.61,High:156.62,Low:156.54,Close:156.57,Volume:3348274},
            {Date:"20200331152500000",Open:156.59,High:156.62,Low:156.52,Close:156.54,Volume:932912},
            {Date:"20200331153000000",Open:156.56,High:156.57,Low:156.50,Close:156.52,Volume:700952},
            {Date:"20200331153500000",Open:156.51,High:156.56,Low:156.50,Close:156.54,Volume:1084428},
            {Date:"20200331154000000",Open:156.52,High:156.56,Low:156.51,Close:156.55,Volume:916684},
            {Date:"20200331154500000",Open:156.56,High:156.57,Low:156.50,Close:156.53,Volume:1360390},
            {Date:"20200331155000000",Open:156.52,High:156.53,Low:156.49,Close:156.50,Volume:2037170},
            {Date:"20200331155500000",Open:156.51,High:156.52,Low:156.46,Close:156.48,Volume:4280833},
            {Date:"20200331160000000",Open:156.49,High:156.48,Low:156.44,Close:156.47,Volume:3348274},
            {Date:"20200401093000000",Open:156.41,High:156.48,Low:156.39,Close:156.46,Volume:1869466},
            {Date:"20200401093500000",Open:156.44,High:156.53,Low:156.40,Close:156.49,Volume:2937883},
            {Date:"20200401094000000",Open:156.48,High:156.54,Low:156.37,Close:156.43,Volume:2277682},
            {Date:"20200401094500000",Open:156.47,High:156.55,Low:156.45,Close:156.51,Volume:1714687},
            {Date:"20200401095000000",Open:156.49,High:156.58,Low:156.48,Close:156.54,Volume:1902583},
            {Date:"20200401095500000",Open:156.54,High:156.59,Low:156.50,Close:156.56,Volume:1325148},
            {Date:"20200401100000000",Open:156.56,High:156.60,Low:156.50,Close:156.53,Volume:2005588},
            {Date:"20200401100500000",Open:156.52,High:156.54,Low:156.42,Close:156.43,Volume:1277880},
            {Date:"20200401101000000",Open:156.44,High:156.46,Low:156.36,Close:156.37,Volume:1158301},
            {Date:"20200401101500000",Open:156.38,High:156.39,Low:156.26,Close:156.28,Volume:1987415},
            {Date:"20200401102000000",Open:156.26,High:156.33,Low:156.22,Close:156.32,Volume:1512742},
            {Date:"20200401102500000",Open:156.31,High:156.40,Low:156.31,Close:156.39,Volume:871592},
            {Date:"20200401103000000",Open:156.38,High:156.43,Low:156.35,Close:156.40,Volume:1132109},
            {Date:"20200401103500000",Open:156.40,High:156.44,Low:156.37,Close:156.41,Volume:725521},
            {Date:"20200401104000000",Open:156.41,High:156.50,Low:156.41,Close:156.48,Volume:704072},
            {Date:"20200401104500000",Open:156.48,High:156.50,Low:156.42,Close:156.46,Volume:844084},
            {Date:"20200401105000000",Open:156.47,High:156.47,Low:156.42,Close:156.45,Volume:392122},
            {Date:"20200401105500000",Open:156.45,High:156.47,Low:156.38,Close:156.41,Volume:544729},
            {Date:"20200401110000000",Open:156.43,High:156.47,Low:156.41,Close:156.44,Volume:660383},
            {Date:"20200401110500000",Open:156.43,High:156.47,Low:156.40,Close:156.41,Volume:640177},
            {Date:"20200401111000000",Open:156.41,High:156.44,Low:156.35,Close:156.39,Volume:845668},
            {Date:"20200401111500000",Open:156.38,High:156.41,Low:156.37,Close:156.39,Volume:503347},
            {Date:"20200401112000000",Open:156.39,High:156.43,Low:156.38,Close:156.41,Volume:360929},
            {Date:"20200401112500000",Open:156.40,High:156.42,Low:156.37,Close:156.38,Volume:749554},
            {Date:"20200401113000000",Open:156.39,High:156.44,Low:156.38,Close:156.42,Volume:723857},
            {Date:"20200401113500000",Open:156.40,High:156.45,Low:156.40,Close:156.44,Volume:455561},
            {Date:"20200401114000000",Open:156.43,High:156.48,Low:156.42,Close:156.45,Volume:670704},
            {Date:"20200401114500000",Open:156.44,High:156.54,Low:156.44,Close:156.50,Volume:827725},
            {Date:"20200401115000000",Open:156.51,High:156.55,Low:156.48,Close:156.53,Volume:828780},
            {Date:"20200401115500000",Open:156.53,High:156.55,Low:156.48,Close:156.49,Volume:687357},
            {Date:"20200401120000000",Open:156.48,High:156.52,Low:156.48,Close:156.51,Volume:343617},
            {Date:"20200401120500000",Open:156.50,High:156.58,Low:156.50,Close:156.57,Volume:444181},
            {Date:"20200401121000000",Open:156.57,High:156.61,Low:156.56,Close:156.57,Volume:932850},
            {Date:"20200401121500000",Open:156.58,High:156.63,Low:156.56,Close:156.61,Volume:622879},
            {Date:"20200401122000000",Open:156.61,High:156.64,Low:156.54,Close:156.56,Volume:417197},
            {Date:"20200401122500000",Open:156.57,High:156.60,Low:156.54,Close:156.56,Volume:524792},
            {Date:"20200401123000000",Open:156.57,High:156.63,Low:156.56,Close:156.63,Volume:547832},
            {Date:"20200401123500000",Open:156.63,High:156.69,Low:156.62,Close:156.65,Volume:1033940},
            {Date:"20200401124000000",Open:156.65,High:156.66,Low:156.59,Close:156.60,Volume:666020},
            {Date:"20200401124500000",Open:156.60,High:156.63,Low:156.52,Close:156.54,Volume:886571},
            {Date:"20200401125000000",Open:156.54,High:156.59,Low:156.53,Close:156.57,Volume:409824},
            {Date:"20200401125500000",Open:156.57,High:156.57,Low:156.52,Close:156.53,Volume:490971},
            {Date:"20200401130000000",Open:156.53,High:156.62,Low:156.53,Close:156.62,Volume:618202},
            {Date:"20200401130500000",Open:156.62,High:156.63,Low:156.56,Close:156.56,Volume:232977},
            {Date:"20200401131000000",Open:156.56,High:156.58,Low:156.52,Close:156.52,Volume:569834},
            {Date:"20200401131500000",Open:156.53,High:156.55,Low:156.50,Close:156.54,Volume:526717},
            {Date:"20200401132000000",Open:156.54,High:156.54,Low:156.48,Close:156.52,Volume:587983},
            {Date:"20200401132500000",Open:156.52,High:156.52,Low:156.46,Close:156.46,Volume:683988},
            {Date:"20200401133000000",Open:156.46,High:156.48,Low:156.44,Close:156.44,Volume:505235},
            {Date:"20200401133500000",Open:156.45,High:156.46,Low:156.41,Close:156.44,Volume:760274},
            {Date:"20200401134000000",Open:156.45,High:156.45,Low:156.41,Close:156.42,Volume:428196},
            {Date:"20200401134500000",Open:156.43,High:156.49,Low:156.42,Close:156.49,Volume:372145},
            {Date:"20200401135000000",Open:156.49,High:156.55,Low:156.42,Close:156.42,Volume:493463},
            {Date:"20200401135500000",Open:156.42,High:156.46,Low:156.37,Close:156.38,Volume:763911},
            {Date:"20200401140000000",Open:156.38,High:156.44,Low:156.38,Close:156.43,Volume:478714},
            {Date:"20200401140500000",Open:156.43,High:156.48,Low:156.40,Close:156.47,Volume:347221},
            {Date:"20200401141000000",Open:156.46,High:156.48,Low:156.44,Close:156.45,Volume:527388},
            {Date:"20200401141500000",Open:156.46,High:156.47,Low:156.39,Close:156.46,Volume:1254489},
            {Date:"20200401142000000",Open:156.47,High:156.52,Low:156.43,Close:156.50,Volume:588877},
            {Date:"20200401142500000",Open:156.49,High:156.50,Low:156.45,Close:156.46,Volume:391738},
            {Date:"20200401143000000",Open:156.46,High:156.50,Low:156.43,Close:156.46,Volume:835468},
            {Date:"20200401143500000",Open:156.46,High:156.51,Low:156.45,Close:156.48,Volume:465308},
            {Date:"20200401144000000",Open:156.48,High:156.50,Low:156.47,Close:156.49,Volume:389872},
            {Date:"20200401144500000",Open:156.48,High:156.53,Low:156.48,Close:156.50,Volume:530820},
            {Date:"20200401145000000",Open:156.50,High:156.53,Low:156.48,Close:156.53,Volume:554269},
            {Date:"20200401145500000",Open:156.53,High:156.57,Low:156.52,Close:156.56,Volume:622473},
            {Date:"20200401150000000",Open:156.57,High:156.59,Low:156.53,Close:156.59,Volume:593592},
            {Date:"20200401150500000",Open:156.59,High:156.61,Low:156.56,Close:156.58,Volume:1089712},
            {Date:"20200401151000000",Open:156.59,High:156.59,Low:156.55,Close:156.57,Volume:634702},
            {Date:"20200401151500000",Open:156.57,High:156.64,Low:156.57,Close:156.60,Volume:1206417},
            {Date:"20200401152000000",Open:156.60,High:156.61,Low:156.58,Close:156.60,Volume:641636},
            {Date:"20200401152500000",Open:156.59,High:156.60,Low:156.54,Close:156.55,Volume:873698},
            {Date:"20200401153000000",Open:156.55,High:156.64,Low:156.55,Close:156.59,Volume:1318720},
            {Date:"20200401153500000",Open:156.60,High:156.68,Low:156.59,Close:156.68,Volume:1520610},
            {Date:"20200401154000000",Open:156.68,High:156.74,Low:156.67,Close:156.74,Volume:1678678},
            {Date:"20200401154500000",Open:156.74,High:156.80,Low:156.73,Close:156.76,Volume:2854531},
            {Date:"20200401155000000",Open:156.75,High:156.79,Low:156.71,Close:156.72,Volume:2984534},
            {Date:"20200401155500000",Open:156.71,High:156.75,Low:156.63,Close:156.73,Volume:7105595},
            {Date:"20200401160000000",Open:156.73,High:156.78,Low:156.71,Close:156.77,Volume:3863507}
        ];
        return masterData;
    }
}

Run it!

Start the project with npm start.

Load http://localhost:4200/hello-world in your web browser.

You should be able to use the Life Cycle Events drop-down menu to make time span events appear and disappear in the time span events panel.

"Chart with drop-down menu and time span events" Figure. Chart with drop-down menu and time span events.

Notice how the panel closes when you clear all the check boxes, and how it opens when you subsequently select a check box. Also, take note of how the panel dynamically resizes based on the number of swim lanes.

Conclusion

You now know how to control the time span events panel and its contents from the user interface of your charting applications. All that remains is to obtain real data.

See the Time Span Events User Interface Example tutorial for a demonstration of connecting time span events to a real-time data source.

Contact us at support@chartiq.com if you have any questions about the Time Span Events plug-in.


Next steps

Explore the API documentation: