Lightstreamer Dojo Demo Documentation

This demo demonstrates the integration between the Lightstreamer Server and the Dojo toolkit JavaScript library. It is based on the existing StockList tutorial that is provided with the Lightstreamer Server package.  The description of this demo assumes a basic understanding of both Lightstreamer and Dojo toolkit components along with all the dependent JavaScript, HTML and HTTP technologies.

This diagram depicts the major components of the demo. In yellow are the Lightstreamer Server and JavaScript client components.  In blue are standard Dojo toolkit JavaScript elements.  In green is the custom code written to connect the Lightstreamer environment to the Dojo environment.



For this demo the Lightstreamer Server (and Adapters) and JavaScript engine are configured identically to the StockList tutorial with the exception of the use of the NonVisualTable in the place of the OverwriteTable and the use of loadEngineMinimal instead of loadEngine.  As with the original StockList demo the NonVisualTable is configured to receive stock update events from the Server.

The EventBridge JavaScript object is a reusable JavaScript object that intercepts data push events from the Lightstreamer Table object and publishes the updates via the Dojo topic subscription  event notification service.  When creating the EventBridge pass the Table object, an array containing the names of the fields to be published and the name of the topic to publish the data.

Note that charting capabilities shown in the on-line demo are not covered by this tutorial


1 Directory Structure & Deployment

1.1 Directory Structure

LS/ Default build of the Lightstreamer Web Client 4
Dojo/ Default build of the Dojo toolkit
css/ CSS file
images/ various images used by the style sheet.
lightstreamer/ Dojo module that contains the EventBridge
index.html main HTML page for the demo

1.2 Deployment instructions

The following steps guide you through a simple deployment of the Dojo Demo inside Lightstreamer Server (i.e. Lightstreamer Server is used for both serving the static web resources and pushing the real-time data).

  1. Download the Demo zip file.
  2. Download Dojo toolkit distribution.
    Note that you need the "AJAX" distribution (e.g. dojo-0.4.0-ajax.zip).
  3. Download Lightstreamer distribution.
  4. Unzip and deploy a Lightstreamer instance (see Lightstreamer documentation for further info).
  5. Unzip LS_Dojo.zip and put its tree under the LS_HOME/pages/ folder (where LS_HOME is the path to your own Lightstreamer installation).
  6. Copy the files from LS_HOME/DOCS-SDKs/sdk_client_web/lib/ to LS_HOME/pages/DojoDemo/LS/
  7. Unzip and deploy Dojo toolkit under LS_HOME/pages/DojoDemo/
    Note that unpacking the Dojo distribution a folder will be created with a name similar to "dojo-0.4.0-ajax". Please rename such folder to "Dojo" (or change the references on the index.html file).
  8. Start Lightstreamer Server.
  9. Point your web browser to http://localhost:8080/DojoDemo/
Please notice that the canonical deployment of a Lightstreamer web application makes use of two separate servers (or server clusters), as shown in the second figure on this page. That means that the actual pages and resources of your front-end should be deployed on a Web Server of your choice and Lightstreamer Server is only used to deliver the real-time updates (and not the static parts of the pages). If you want to deploy the Dojo Demo according to such canonical style, you should do something similar to what explained in the "External deployment" section of the "DOCS-SDKs/sdk_client_web/examples/StockListDemo/README.TXT" file (referred to the Stock List Demo).

2 Source code listing

2.1 In the head of the HTML page include the LS JavaScript files

            <!-- Include Lightstreamer libraries -->
            <script src="LS/lscommons.js"></script>
            <script src="LS/lspushpage.js"></script>

2.2 Set up some variables

               /**
                * Set up some vars.
                */
               var group = ["item1", "item2", "item3", "item4", "item5",
                            "item6", "item7", "item8", "item9", "item10",
                            "item11", "item12", "item13", "item14", "item15"];
               var schema = ["stock_name","last_price", "time", "pct_change",
                             "bid_quantity", "bid", "ask", "ask_quantity", "min",
                             "max", "ref_price", "open_price"];
               var domain = null;
               var host = null;
              
               /**
                * Optional Dojo debug configuration.
                */
               var djConfig = { isDebug: false };

2.3 Include the Dojo toolkit

            <script src="Dojo/dojo.js"></script>

2.4 In a script block import the needed Dojo components

            dojo.require("dojo.widget.FilteringTable");
            dojo.require("dojo.event.*");
            dojo.require("dojo.event.topic");
           
2.5 Include the EventBridge
           
            dojo.require("lightstreamer.EventBridge");
           
2.6 Confirm includes
           
            dojo.hostenv.writeIncludes();

2.7 Use the dojo.addOnLoad() to execute this code on page load

            dojo.addOnLoad(function() {
                /**
                 * To start configure the Lightstreamer page and engine.
                 * This code is the same as the StockList tutorial.
                 *
                 * Because this demo will be using the FilteringTable widget to
                 * display the stock data will be used the NonVisualTable table
                 * instead of the OverwriteTable.
                 */
                var lsPage = new PushPage();
                lsPage.context.setDebugAlertsOnClientError(false);
                lsPage.context.setRemoteAlertsOnClientError(false);
                lsPage.context.setDomain(domain);
                lsPage.onEngineReady = function(engineRef) {
                    engineRef.context.setDebugAlertsOnClientError(debugAlerts);
                    engineRef.context.setRemoteAlertsOnClientError(true);
                    engineRef.connection.setLSHost(host);
                    engineRef.connection.setLSPort(null);
                    engineRef.connection.setAdapterName("STOCKLISTDEMO");
                    engineRef.changeStatus("STREAMING");
                }
                lsPage.bind();
   
                lsPage.loadEngineMinimal("LS/lsengine.html");
               
                var lsTable = new NonVisualTable(group, schema, "MERGE");
               
                lsTable.setSnapshotRequired(true);
                lsPage.addTable(lsTable, "list");

2.8 Create the topic listener function

                /**
                 * Lookup the stockTable widget once as doing it on each
                 * event will significantly decrease performance.
                 */
                var stockTable = dojo.widget.byId("stockTable");
               
                /**
                 * Post update messaging of the display of the filled data is needed
                 * so connect to the fillCell method of the FilteringTable and execute
                 * the local function onUpdateField.
                 */
                dojo.event.connect(stockTable, "fillCell", "onUpdateField");

                /**
                 * Listen to the Dojo event topic "stockTopic" and update the
                 * data in stockTable's internal date store.
                 */
                dojo.event.topic.subscribe("stockTopic", function(item) {
               
                    var obj = stockTable.store.getDataByKey(item.name);
                    if(obj) {
                        for(var i = 0; i < stockTable.columns.length; i++) {
                            var column = stockTable.columns[i];
                            var field = column.getField();
                            var val = item.fields[field];
                            stockTable.store.update(obj, field, val);
                        }           
                    } else {
                        stockTable.store.addData(item.fields, item.name);
                       
                    }
                });     

2.9 Create an EventBridge that will map the events recived from the Lightstreamer engine and publish them on the Dojo topic 'stockTopic'

               /**
                * Create an EventBridge that will map the events recived from
                * the lightstreamer engine and publish them on the dojo topic 'stockTopic'
                */
                var bridge = new Lightstreamer.EventBridge(lsTable, schema, "stockTopic");
            });

2.10 Define the onUpdateField function

            /**
             * Add the directional images to the field when it updates.
             */
            function onUpdateField(cell, meta, val) {
           
                if(meta.field == "pct_change") {
                    var direction = "";
                    if(val.indexOf('-') == 0) {
                        direction = "Down";
                    } else {
                        direction = "Up";
                    }
                    cell.innerHTML = '<img src="images/change' + direction + '.gif" border="0" height="5" width="6"> ' + val + "%";
                }
            }

3 HTML document body

3.1 Create FilteringTable
   
    <table dojoType="filteringTable" id="stockTable"
        multiple="true" alternateRows="true" maxSortable="2"
        cellpadding="0" cellspacing="0" border="0"
        class="stockListing"
        align="center"
        style="-moz-user-select: none;" width="754" >

3.2 Define the columns of the table (the files names need to match the names from the schema in the LS Table)

        <thead>
            <tr  style="text-align: left">
                <th field="stock_name" noSort="false"  width="114" style="text-align: left">Name</th>
                <th field="last_price" noSort="true" width="53">Last</th>

                <th field="time" noSort="true" width="73">Time</th>
                <th field="pct_change" noSort="true" width="62">Change</th>
                <th field="bid_quantity" noSort="true" width="70">Bid Size</th>
                <th field="bid" noSort="true" width="52">Bid</th>
                <th field="ask" noSort="true" width="52">Ask</th>
                <th field="ask_quantity" noSort="true" width="70">Ask Size</th>

                <th field="min" noSort="true" width="52">Min</th>
                <th field="max" noSort="true" width="52">Max</th>
                <th field="ref_price" noSort="true" width="52">Ref.</th>
                <th field="open_price" noSort="true" width="52">Open</th>
            </tr>
        </thead>