Creating a Typescript web app in Visual Studio

By Jan 02, 2017

Description:

Here we explain how to create an application in TypeScript with Visual Studio. As an example of an application, we propose a matrix multiplier.

Preferencesoft

TypeScript application in Visual Studio

In this article, we explain how to create a HTML application with TypeScript and we create an application of matrix multiplication.

Client-side apps

There are some limitations and restrictions to the fact that JavaScript runs in a client-side browser.

The program cannot access all the resources of the system and it is for example impossible to save a file on a disk of the client machine.

For security reasons, it is not recommended to manage password connections to a server or to a database. Similarly, it is not advisable to place sensitive information in the HTML or TypeScript file.

JavaScript api now allow access to certain devices, but this is not possible with all browsers. With the most common browsers you will be able to store information in a local storage or a session storage, to access the geolocation. But external device data (such as a webcam video stream) cannot be called from insecure origins.

What kinds of applications can be created in HTML and TypeScript?

We can create converters from one format to another, calculators, curve plotters, games and so on.

Can we protect its application of piracy?

Unfortunately, no since browsers allow to examine the source of the HTML and JavaScript. Even using an obfuscator, you will not be safe from the reverse engineering. If you want to protect your app, I think that it will be more effective to opt for a software copyright protection solution.

Creating the application with Visual Studio

If TypeScript is installed in Visual Studio 2015, let's create a new project. In the dialog box named new project, select TypeScript and HTML application with TypeScript and give it the name: TypeScriptHTMLApp1. Finally, press OK.

Once the application is generated, we get several files in the solution, including index.html and app.ts. The latter contains the application in TypeScript. We can notice that the JavaScript/Typescript code is not in the same file as the HTML or CSS code.

In fact, browsers interpret JavaScript and not TypeScript, TypeScript code must be converted into JavaScript.

In the index.html file there is no JavaScript/Typescript instruction, but just a reference to the app.js file which is the result of the automatic transpilation of the TypeScript file app.ts into JavaScript.

To implement an application, we must put the HTML objects in the index.html file and program in the file app.ts

From the TypeScript file, we can access the HTML objects using some instructions as getElementByID.


Index.html
<!DOCTYPE html>
 
<html lang="en">
<head>
    <meta charset="utf-8" />
    <title>TypeScript HTML App</title>
    <link rel="stylesheet" href="app.css" type="text/css" />
    <script src="app.js"></script>
</head>
<body>
    <h1>TypeScript HTML App</h1>
 
    <div id="content"></div>
</body>
</html>

App.ts
class Greeter {
    element: HTMLElement;
    span: HTMLElement;
    timerToken: number;
 
    constructor(element: HTMLElement) {
        this.element = element;
        this.element.innerHTML += "The time is: ";
        this.span = document.createElement('span');
        this.element.appendChild(this.span);
        this.span.innerText = new Date().toUTCString();
    }
 
    start() {
        this.timerToken = setInterval(() => this.span.innerHTML = new Date().toUTCString(), 500);
    }
 
    stop() {
        clearTimeout(this.timerToken);
    }
 
}
 
window.onload = () => {
    var el = document.getElementById('content');
    var greeter = new Greeter(el);
    greeter.start();
};

This application displays the date and time in the HTML5 page.

Matrix Multiplier

Now create an application of multiplication of two matrices.

We declare a single class that manages the entries of the matrices, the calculation of the product and the product display. We pass to this class through its constructor the HTML objects that are modified by certain methods. This allows to do not too often call getElementbyId.

Just below the class declaration, we place the instructions of the program initialization.

In this sequence of instructions, we create an instance of the class and we add functions to different buttons event handlers.


Index1.html
<!DOCTYPE html>
 
<html lang="en">
<head>
    <meta charset="utf-8" />
    <title>Matrix Multiplication</title>
    <link rel="stylesheet" href="app.css" type="text/css" />
    <script src="app.js"></script>
</head>
<body>
    <h1>Matrix Multiplication</h1>
    <h2>Enter matrix A:</h2>
    <form id="enterSizeA">
        Number of line: <input type="text" name="rowA" value="3"><br>
        Number of column: <input type="text" name="colA" value="3"><br>
    </form>
 
    <p>Click to enter the matrix</p>
 
    <!--<button id="enterA">Enter A</button>-->
    <input id="enterA" type="button" value="Enter A" />
    <table id="matrixA"></table>
 
    <h2>Enter matrix B:</h2>
    <form id="enterSizeB">
        Number of line: <input type="text" name="rowB" value="3"><br>
        Number of column: <input type="text" name="colB" value="3"><br>
    </form>
 
    <p>Click to enter the matrix</p>
 
    <button id="enterB">Enter B</button>
    <table id="matrixB"></table>
 
    <h2>Product: A*B</h2>
    <p></p>
    <button id="calculateAB">Calculate</button>
    <table id="matrixC"></table>
    <br />
    <span id="error" style="color:deeppink"></span>
</body>
</html>

App1.ts
class MatrixMultiplication {
    private matrixA: HTMLTableElement;
    private matrixB: HTMLTableElement;
    private matrixC: HTMLTableElement;
    private numberRowAForm: HTMLInputElement;
    private numberColAForm: HTMLInputElement;
    private numberRowBForm: HTMLInputElement;
    private numberColBForm: HTMLInputElement;
    private error: HTMLSpanElement;
 
    constructor(mA, mB, mC, fRA, fCA, fRB, fCB, err) {
        this.matrixA = mA;
        this.matrixB = mB;
        this.matrixC = mC;
        this.numberRowAForm = fRA;
        this.numberColAForm = fCA;
        this.numberRowBForm = fRB;
        this.numberColBForm = fCB;
        this.error = err;
    }
 
    enterA() {
    //clean the tables
        while (this.matrixA.firstChild!=null) {
            this.matrixA.removeChild(this.matrixA.firstChild);
        }
        while (this.matrixC.firstChild != null) {
            this.matrixC.removeChild(this.matrixC.firstChild);
        }
        this.matrixC.style.width = "";
        this.matrixC.style.border = "";
        //clean the error span
        this.error.innerHTML = "";
        this.tableInputCreate(this.matrixA, Number(this.numberRowAForm.value), Number(this.numberColAForm.value));
    }
 
    enterB() {      
    //clean the tables
        while (this.matrixB.firstChild != null) {
            this.matrixB.removeChild(this.matrixB.firstChild);
        }
        while (this.matrixC.firstChild != null) {
            this.matrixC.removeChild(this.matrixC.firstChild);
        }
        this.matrixC.style.width = "";
        this.matrixC.style.border = "";
        //clean the error span
        this.error.innerHTML = "";
        this.tableInputCreate(this.matrixB, Number(this.numberRowBForm.value), Number(this.numberColBForm.value));
    }
 
    private getArrayFromTableInput(tbl: HTMLTableElement): number[][] {
        var rows = tbl.tHead.rows;
        var rowNumber = rows.length;
        var colNumber = rows[0].cells.length;
        var matrix: number[][] = new Array<number[]>(rowNumber);
        for (var i = 0; i < rowNumber; i++) {
            var tr = rows[i];
            matrix[i] = new Array<number>(colNumber);
            for (var j = 0; j < colNumber; j++) {
                var td = tr.cells;
                var cell = <HTMLInputElement>td[j].firstChild;
                matrix[i][j] = Number(cell.value);
            }
        }
        return matrix;
    }
 
    private tableInputCreate(tbl: HTMLTableElement, row: number, col: number) {
        var thead = <HTMLTableSectionElement>tbl.createTHead();
        var tbody = <HTMLTableSectionElement>tbl.createTBody();
        for (var i = 0; i < row; i++) {
            var tr = tbl.tHead.insertRow();
            for (var j = 0; j < col; j++) {
                    var td = tr.insertCell();
                    td.innerHTML = "<input></input>";
            }
        }
    }
 
    private tableCreate(tbl: HTMLTableElement, array: number[][]) {
        var row: number = array.length;
        var col: number = array[0].length;
        var width = col * 100;
        tbl.style.width = width + "px";
        tbl.style.border = "1px solid black";
        var thead = <HTMLTableSectionElement>tbl.createTHead();
        var tbody = <HTMLTableSectionElement>tbl.createTBody();
        for (var i = 0; i < row; i++) {
            var tr = tbl.tHead.insertRow();
            for (var j = 0; j < col; j++) {
                var td = tr.insertCell();
                td.innerHTML = array[i][j].toString();
                td.style.border = "1px solid black";
            }
        }
    }
 
    product() {
        while (this.matrixC.firstChild != null) {
            this.matrixC.removeChild(this.matrixC.firstChild);
        }
        if (this.matrixA.childElementCount > 0 && this.matrixB.childElementCount > 0) {
            var arrayA = this.getArrayFromTableInput(this.matrixA);
            var arrayB = this.getArrayFromTableInput(this.matrixB);
            var n = arrayA.length;
            var m = arrayA[0].length;
            var p = arrayB.length;
            var q = arrayB[0].length;
            if (m == p) {
                var arrayC: number[][] = new Array<number[]>(n);
                for (var i = 0; i < n; i++) {
                    arrayC[i] = new Array<number>(q);
                    for (var j = 0; j < q; j++) {
                        var c = 0;
                        for (var k = 0; k < m; k++) {
                            c += arrayA[i][k] * arrayB[k][j];
                        }
                        arrayC[i][j] = c;
                    }
                }
                this.tableCreate(this.matrixC, arrayC);
            }
            else {
                this.error.innerHTML ="<b>The columns of the second matrix must have the same number of entries as do the rows of the first matrix.</b>"
            }
        }
        else {
            this.error.innerHTML = "<b>Enter A and B.</b>"
        }
    }
 
    start() {      
    }
 
    stop() {     
    }
}
 
window.onload = () => {
    var matrixA = <HTMLTableElement>document.getElementById("matrixA");
    var formA = <HTMLFormElement>document.getElementById("enterSizeA");
    var formRowA = <HTMLInputElement>formA["rowA"];
    var formColA = <HTMLInputElement>formA["colA"];
    var matrixB = <HTMLTableElement>document.getElementById("matrixB");
    var formB = <HTMLFormElement>document.getElementById("enterSizeB");
    var formRowB = <HTMLInputElement>formB["rowB"];
    var formColB = <HTMLInputElement>formB["colB"];
    var matrixC = <HTMLTableElement>document.getElementById("matrixC");
    var spanError = <HTMLSpanElement>document.getElementById("error");
 
    var matrixMultiplication = new MatrixMultiplication(matrixA, matrixB, matrixC, formRowA, formColA, formRowB, formColB, spanError);
    var enterA = <HTMLButtonElement>document.getElementById("enterA");
    enterA.onclick = function () {
        matrixMultiplication.enterA();
    }
    var enterB = <HTMLButtonElement>document.getElementById("enterB");
    enterB.onclick = function () {
        matrixMultiplication.enterB();
    }
    var calculateAB = <HTMLButtonElement>document.getElementById("calculateAB");
    calculateAB.onclick = function () {
        matrixMultiplication.product();
    }
    matrixMultiplication.start();
};

You can test the app on the following page:

Matrix multiplication
TypeScript

Categories

Share

Follow


KodFor Privacy Policy