HT for Web HtmlNode Manual

Index


HtmlNode Description

ht.Node supports rendering with pictures, vectors, but for some applications (such as SCADA), it is often necessary to insert some interactive elements (text fields, buttons, etc.) into the interface, and the normal Node is a little overwhelmed at this time. For this, the HT expand the ht.HtmlNode, it can render HTML elements to the topology, both to maintain the HTML elements of interactivity, but also to achieve the normal Node scaling rotation and other functions.

HtmlNode provides the following API:

The API expands on GraphView:

Simple Example

HtmlNode html attribute can be set to HTML text, and then you can set the position, width, height and other attributes in the way of operating the general Node.

For example:

var node = new ht.HtmlNode();
node.setPosition(200, 100);
node.setHtml("<div class='wrapper'>\n\
    <img width='20' height='24' src='data:image/png;base64,'>\n\
    &nbsp;&nbsp;&nbsp; Hello, I can <i>render</i> any HTML!</div>");
dataModel.add(node);

In the example above, HtmlNode renders a piece of HTML text to the topology, and the HTML element can not only respond to user actions, but also use the topology component to scale and rotate it. Note: In order for the HTML element to respond to user action, HtmlNode shielding the drag-and-drop function on the body, when HtmlNode is selected, a cross direction tag will appears in the upper right corner, dragging it to achieve drag-and-drop HtmlNode.

Data Binding

How to modify the HTML content that has been displayed? The most straightforward way is to assign id to the HTML element, get the DOM object through document.getElementById('id'), and then operate it. In addition, HtmlNode provides simple bidirectional data binding:

Example:

<!--Introduce handlebars-->
<script src="../../../lib/handlebars.js"></script>

<!--Create an HTML template, {{}} can synchronize properties on HtmlNode to HTML elements, and the bind property of HTML elements is used to synchronize value to HtmlNode-->
<script id="controlpanel-template" type="text/x-handlebars-template">
<div class="panel">
    <div class="title">Dashboard</div>
    <div class="content">
        <p><span class="label">KPI: </span><span class="value">{{value}}</span></p>
        <p>
        <span class="label">Stop: </span>
        <span class="value"><input type="checkbox" {{#if isStopped}}checked{{/if}} bind="isStopped"></span>
        </p>
    </div>
</div>
</script>

......    

var node = new ht.HtmlNode();
node.setPosition(200, 100);
node.setHtml(document.getElementById("controlpanel-template").innerHTML);
node.setContext(context);
dataModel.add(node);

/*
* Refreshes the HtmlNode context property every second, HtmlNode automatically synchronizes it to an 
* HTML element
*/
setInterval(function () {
    if(!context.isStopped){
        context.value=parseInt(100*Math.random());
        graphView.invalidateData(node);
    }
}, 1000);

Supportted HTML Type

The setHtml parameter can be of the following three types:

Example:

var htmlNode = new ht.HtmlNode();
htmlNode.setPosition(200, 50);
htmlNode.setName("Rendering HTML text");
htmlNode.setHtml("<div class='htmlWrapper'>Node's new name: <input type='text' value='{{value}}' bind='value'>\n\
                  <input type='button' value='Modify' nodeid='{{nodeid}}' onclick='modifyNodeName(event)'/></div>");
htmlNode.setContext({
    value:htmlNode.getName(),
    nodeid:htmlNode.getId()
});
dataModel.add(htmlNode);

var div=document.createElement("div");
div.className="domWrapper";
div.innerHTML="Rendering DOM";
var domNode = new ht.HtmlNode();
domNode.setHtml(div);
domNode.setPosition(200, 150);
dataModel.add(domNode);

var htNode = new ht.HtmlNode();
htNode.setHtml(createTable());
htNode.setPosition(500,100);
htNode.setName("Alarm Statistics(TablePane)");
htNode.setScalable(false);
dataModel.add(htNode);

Comprehensive Application

Next look at a comprehensive application, some applications need to display some subsidiary information around the datas, such as status icons, statistics, or Chart, etc. The following example has two Node, one as the actual display of Node, and the other as a statistical table stand right by the first Node. To save space, the statistics table should be able to expand and merge, let's see the following example:

First define two templates as the HTML contents that merging and expanding by HtmlNode:

<script id="table-template" type="text/x-handlebars-template">
    <div class="wrapper" nodeid="{{id}}" onclick="tableIconClickHandler(event)">
    <div class="table_title">Real-time monitoring<span class="shrink"></span></div>
    <table class="list_table">
    {{#each rows}}
        <tr>
            <td>{{id}}</td>
            <td>{{temperature}}</td>
            <td>{{pressure}}</td>
            <td>{{time}}</td>
        </tr>
    {{/each}}
    </table>
    </div>
</script>

<script id="table-min-template" type="text/x-handlebars-template">
    <span class="open" nodeid="{{id}}" onclick="tableIconClickHandler(event)"></span>
</script>

Next declare the Host node and the statistics node:

var host = new ht.Node();
host.setName("This is Host");
dataModel.add(host);


var tableNode = new ht.HtmlNode();
tableNode.setHtml(document.getElementById("table-template").innerHTML);
tableNode.setPosition(230, 100);
tableNode.setContext({
    id: tableNode.getId(),
    rows: [
        {
            id: 1,
            temperature: 23.3,
            pressure: 231.6,
            time: "18:12"
        },
        {
            id: 2,
            temperature: 29.3,
            pressure: 231,
            time: "18:13"
        },
        {
            id: 3,
            temperature: 25,
            pressure: 211.6,
            time: "18:14"
        },
        {
            id: 4,
            temperature: 22.4,
            pressure: 111.6,
            time: "18:15"
        },
        {
            id: 5,
            temperature: 37.4,
            pressure: 171.6,
            time: "18:19"
        }
    ]
});
tableNode.setWidth(300);
tableNode.setHeight(200);
dataModel.add(tableNode);
tableNode.setPosition({x: host.getPosition().x + host.getWidth() / 2 + tableNode.getWidth() / 2 + 10, 
                       y: host.getPosition().y - host.getHeight() / 2 + tableNode.getHeight() / 2});

Finally, there is a function to handle the user's click event in the upper-right corner of the statistical graph:

function tableIconClickHandler(e) {
    var maxInnerHTML = document.getElementById("table-template").innerHTML,
            minInnerHTML = document.getElementById("table-min-template").innerHTML;

    if (e.target.className === "shrink") {
        var nodeid = e.currentTarget.getAttribute("nodeid"),
                node = dataModel.getDataById(nodeid),
                host = node.getHost(),
                newWidth = 16 + node._padding,
                newHeight = 16 + node._padding,
                originWidth = node._originWidth,
                originHeight = node._originHeight,
                differenceWidth = originWidth - newWidth,
                differenceHeight = originHeight - newHeight;

        ht.Default.startAnim({
            finishFunc: function () {//Called at the end of the animation execution, changing the 
                                    //content and location of the statistics 
                node.setHtml(minInnerHTML);
                node.setPosition({x: host.getPosition().x + host.getWidth() / 2 + node.getWidth() / 2 + 10, 
                                  y: host.getPosition().y - host.getHeight() / 2 + node.getHeight() / 2});
            },
            action: function (t) {//The animation calls this function every frame, where the size of 
                                 //the tables is adjusted 
                node.setWidth(originWidth - differenceWidth * t);
                node.setHeight(originHeight - differenceHeight * t);
                node.setPosition({x: host.getPosition().x + host.getWidth() / 2 + node.getWidth() / 2 + 10, 
                                  y: host.getPosition().y - host.getHeight() / 2 + node.getHeight() / 2});
            }
        });
    } else if (e.target.className === "expand") {
        var nodeid = e.currentTarget.getAttribute("nodeid"),
                node = dataModel.getDataById(nodeid),
                host = node.getHost(),
                originWidth = node._originWidth,
                originHeight = node._originHeight;

        node.setHtml(maxInnerHTML);

        var newWidth = node.getWidth(),
                newHeight = node.getHeight(),
                differenceWidth = newWidth - originWidth,
                differenceHeight = newHeight - originHeight;

        node.setWidth(originWidth);
        node.setHeight(originHeight);

        ht.Default.startAnim({
            action: function (t) {
                node.setWidth(originWidth + differenceWidth * t);
                node.setHeight(originHeight + differenceHeight * t);
                node.setPosition({x: host.getPosition().x + host.getWidth() / 2 + node.getWidth() / 2 + 10,
                                  y: host.getPosition().y - host.getHeight() / 2 + node.getHeight() / 2});
            }
        });
    }
}

Welcome to contact us service@hightopo.com