The article contains a introduction to JavaScript development. The Eclipse IDE is used for this example.

1. What is JavaScript (ECMAScript)?

JavaScript is a case sensitive scripting language. JavaScripts syntax is C-based, with semicolons and curly braces.

All main browsers contain a compiler or interpreter for JavaScript. In earlier days JavaScript was primarily used within HTML webpages. Nowadays, JavaScript is also used on the server, for example with Node.js.

JavaScript and Java are completely different programming languages even though they have a similar name.

1.1. JavaScript and webpages

You can put JavaScript into an external file or directly into the HTML page. If you put the JavaScript code into the HTML page you can either put it into the header or in the body of the HTML page. JavaScript which is embedded into an HTML page must be surrounded by <script type="text/javascript"> </script> tags. JavaScripts in the body is be executed while the page loads. JavaScripts in the header is be executed when other JavaScript functions in the HTML body call them.

2. Getting Eclipse IDE for JavaScript and Web Developers

Download the Eclipse IDE for JavaScript and Web Developers package from http://www.eclipse.org/downloads/index-developer.php. Unzip is and start the Eclipse IDE and select a directory to work in.

3. Your first JavaScript project with Eclipse

Switch to the Web perspective and create a new Static Web Project.

Select View  File  New  Static Web Project.

javascriptwizard1
javascriptwizard2

Create a new HTML file with File  New    Other  Web  HTML File.

javascriptwizard4
javascriptwizard5

Adjust the HTML code to the following. In this example the JavaScript is embedded into the HTML page.

<!DOCTYPE html>
<html>
<body>
<script type="text/javascript">
<!--This is single line comment -->
/*
This is a multi line commend
The following command write output the text into the HTML code. -->
*/
document.writeln("Hello, JavaScript!");
</script>
</body>
</html>

Afterwards open it via its context Open With  Web Browser. The commands within the script tags runs and "Hello, JavaScript!" is written to the webpage.

javascriptwizard3

4. Your first JavaScript outside an HTML page

You can also put the JavaScript in a separate file and include it into the HTML page. For example create the file 'javascriptinclude.html' with the following content.

<!DOCTYPE html>
<html>
<body>
<script src="myfirstjsfile.js"></script>
</body>
</html>

Create the file 'myfirstjsfile.js' in the same directory as the HTML page.

javascriptwizard6

As the JavaScript is in a separate file you do not have to use script tag. Simple write the code directly into the file.

document.writeln("<b>Bold Hello World via an external js file!</b>");

Open the HTML page in a browser. The script should get executed and you should see the message.

5. Debugging

The easiest way to "debug" JavaScript is to use the alert() method which allows to give the user some feedback. This is the equivalent to println in other programming languages. For example the following program shows a popup with the currently value to the user.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>

<body>
<script type="text/javascript">
/*Declare a text variable and print it to the HTML page*/
var mytext= "Example Text.";
/*Call the function*/
alert(mytext);

</script>
</body>
</html>

You can also open the webpage in a Browser like Chrome and debug it there.

6. Appendix - Programming in JavaScript

6.1. Variables and data types

The following example demonstrates how to declare and use variables in JavaScript. You may notice that there are several ways of declaring variables.

let mytext= "Hello, hello. Turn the radio on. Is there anybody out there...";

/* declare variables t o do some math*/
a = 5; // global variable avoid this
let b = 1;
let result = a - b;

/* concatenate two strings*/
let mytext1 = "I like Spanish";
let mytext2 = " because the melody is nice.";
document.writeln(mytext1 + mytext2);

JavaScript allows you to declare a variable without a keyword. This creates global variables, which can lead to hard to determine bugs. You should avoid them. Also the var keyword allows to define a variable but allows you to re-declare it, which can also lead to suble bugs. The let keyword avoids this, by enforcing that a variable is only declared once. With the const keyword it is possible to enforce that a variable can not be reassigned. This doesn’t mean that the variable is immutable, just that the reference can’t change.

Variables defined without the keyword var are global variables. Variables defined with var are scoped according to their declaration, e.g., if you define a var in a function this variable is only valid in the current function body. Variables defined with let and const are only valid in the current block.

It is good JavaScript practice to always use one of the keywords to avoid global variables.

JavaScript has four basic types, Object and the primitive types Number, String, and Boolean. While Objects are passed by reference, the primitive types are passed by value.

6.2. String operations

You can define string and concatenate them. The following example assumes you have two variables user and validationError.

var message = "Invalide user action for " + user.firstName + " " + user.lastName +
  ". Operations ended with " + validationError;

Alternatively, can you also use the backtick string literal to allow string interpolation.

var message = `Invalide user action for ${user.firstName} ${user.lastName}.  Operations ended with ${validationError}`;

6.3. Arrays

Arrays are Objects in JavaScript. You can define them and use the method pop() to remove the first element and push(newValue) to add a new element at the end. You can also iterate over it.

<!DOCTYPE html>
<html>
<body>
<script type="text/javascript">

let myArray = ["Android", true, 7]
alert(myArray[0]);
alert(myArray.length);
myArray.pop();
alert(myArray);
myArray.push("Eclipse")
alert(myArray);

/*Iterate over the array and write it to the console of the browser*/

for(let i = 0; i < myArray.length; i++) { alert(myArray[i]) }

</script>
</body>
</html>

6.4. Functions

A function in JavaScript encapsulates reusable code and is represented as an Object. Functions can be directly called via other JavaScript code. It is recommended that you put functions in the header of the HTML page. Functions are declared via the function keyword. You can call a function directly, or use the apply method on the function.

<!DOCTYPE html>
<html>
<header>
<script type="text/javascript">
/*Write the text twice to the document*/
function writetext(text) {
    document.writeln(text);
    document.writeln(text + "<p>");
}
</script>

</header>
<body>
<script type="text/javascript">
/*Declare a text variable and print it to the HTML page*/
var mytext = "Example Text.";
/*Call the function*/
writetext(mytext)
/*Call it via apply*/
writetext(mytext + "apply").apply();
</script>
</body>
</html>

6.5. Prototypes in JavaScript

JavaScripts Objects are not fundamentally class based like in object orientated programming languages. JavaScript is a prototype-based language, by this approach you can reuse functions by cloning existing objects.

Here is a an example that shows object creation with inheritance in ECMA5.

var Point2D = function (x, y) {
    this.move(x, y);
};
Point2D.prototype.move = function (x, y) {
    this.x = x;
    this.y = y;
};
var Point3D = function (x, y, z) {
    Point2D.call(this, x, y);
    this.move(x, y, z);
};
Point3D.prototype = Object.create(Point2D.prototype);
Point3D.prototype.constructor = Point3D;
Point3D.prototype.move = function (x, y, z) {
    Point2D.prototype.move(x, y);
    this.z = z;
}
var point3d = new Point3D(5, 3, 6);
console.log(point3d.x); // => 5
console.log(point3d.z); // => 6

ECMA6 introduced a class syntax that can be used like in object oriented languages but is just syntactic sugar for the prototype based approach.

class Point2D {
    constructor (x, y) {
        this.move(x, y);
    }
    move (x, y) {
        this.x = x;
        this.y = y;
    }
}
class Point3D extends Point2D {
    constructor (x, y, z) {
        super();
        this.move(x, y, z);
    }
    move (x, y, z) {
        super.move(x, y);
        this.z = z;
    }
}
var point3d = new Point3D(5, 3, 6);
console.log(point3d.x); // => 5
console.log(point3d.z); // => 6

6.6. Assigning functions to HTML buttons

The following gives an example how to assign a function to an HTML button.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<script type="text/javascript">
function writetext(mytext) {
    document.writeln(mytext);
}

function addNumber(a, b) {
    var result = a + b;
    return result;
}
</script>

</head>
<body>

<input type="button" value="Write Text after click"
onclick="writetext('Hello function')" >

<input type="button" value="Add number"
onclick="writetext(addNumber(1,3))" >
</body>
</html>

6.7. HTML Events

JavaScript can react to certain events on the page and be registered with webpage elements, e.g. buttons. You can register a function to an event in the HTML page.

Table 1. Events in Javascript
Event Description

Onload

Triggered when the user loads the page. The onload event can for example be used to check the visitors browser type.

onChange

Called whenever a field is changed. Can for example be used to validate an input field of a form.

onSubmit

Called when a user clicks on the submit button of a form.

OnMouseOver and OnMouseOut

Called when the mouse enters a certain element on the page or leaves it.

7. JavaScript and HTML interaction

7.1. HTML DOM

A HTML webpage is represented via a HTML Document Object Model (DOM). The HTML DOM is defined via a W3C standard. This HTML DOM defines a standard way to access and manipulate HTML documents. You can use JavaScript to modify the HTML DOM.

7.2. Manipulation HTML with JavaScript

You can for example search via JavaScript for certain elements and modify their properties. The following example shows how to find HTML elements with a certain div class and set the display property to hide / show them.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<script type="text/javascript">

function hideshow() {

    var allHTMLTags = new Array();

    //Create Array of All HTML Tags
    var allHTMLTags = document.getElementsByTagName("*");

    //Loop through all tags using a for loop
    for (i = 0; i < allHTMLTags.length; i++) {

        //Get all tags with the specified class name.
        if (allHTMLTags[i].className == "revhistory") {

            // hide or display the elements
            if (allHTMLTags[i].style.display == "none") {
                allHTMLTags[i].style.display = "";
            } else {
                allHTMLTags[i].style.display = "none";
            }
        }
    }
}
</script>

</head>
<body>

<div class="revhistory">This is the text which will be manipulated via JavaScript</div>

<input type="button" value="Show/ Hide"
onclick="hideshow()">


</body>
</html>

8. JavaScript Examples

8.1. Create a dynamic link using the webpage information

The following shows how a URL for an link can be dynamically created via JavaScript. This examples uses JavaScript to create a link for the website "digg".

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>

/* This script will read the current URL and the title of the document
and submit this webpage to the social bookmarking website. */

<script type="text/javascript">
function toDiggUrl(){
    var result = "http://digg.com/submit?phase=2&url=";
    result += encodeURIComponent(location.href);
    result += "&title=";
    result += encodeURIComponent(document.title);
    result += "&topic=programming";
    window.location = result;
}
</script>
</head>

<body>

<b>Here we write some information to the HTML page.</b>
<BR>
Write the current URL to this HTML document
<script type="text/javascript">
document.writeln(location.href);
</script>

<BR>
<BR>
<b>Encodes the current URL so that special characters will get
encoded</b>
<BR>
<script type="text/javascript">
document.writeln(encodeURIComponent(location.href))
</script>


<BR>
<BR>
<b>More fancy stuff, evalute page information and send this to a
social bookmarking website (digg)</b>
<BR>


<table border="0" cellpadding="10" cellspacing="0" width="100%">
    <tr>
        <td width="320">If you press the hyperlink below the JavaScript
        will run <BR>
        <a href="javascript: toDiggUrl()">Digg this site</a></td>
    </tr>
</table>



</body>
</html>

8.2. Reading META Tags via JavaScript

You can use JavaScript to read existing meta tags from the webpage. The following reads the content of the meta tag description from the webpage.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>

<head>
<meta name="description" content="Tutorials from www.vogella.com!">

<script type="text/javascript">
function getMetaDescription () {
  var metaElements = document.all ?
    document.all.tags('META') :
    document.getElementsByTagName ?
    document.getElementsByTagName ('META') : new Array();
  var metaKeywords = new Array();
  var i = 0;
  for (var m = 0; m < metaElements.length; m++)
    if (metaElements[m].name == 'description')
      metaKeywords[i++] = metaElements[m].content;
  return metaKeywords;
}
</script>
</head>

<h2>
This will write the meta tag description to this page
</h2>

<body>

<script type="text/javascript">
    document.write(getMetaDescription());
</script>


</body>
</html>

8.3. HTML forms and JavaScript

The following is an example on checking input data of HTML forms and setting hidden parameters via Javascript. In this case the URL is automatically determined and send to the service once submit is pressed.

function updateFormAction() {

    document.forms["myform"].elements["webpage"].value = encodeURIComponent(location.href);
    var value = document.forms["myform"].elements["user"].value;
    if (value == null || value == "") {
        var Textknoten = document.createTextNode("Please fill out all fields");
        document.getElementById("replace").replaceChild(Textknoten, document.getElementById("replace").firstChild);

        return false;
    }
    var value = document.forms["myform"].elements["email"].value;
    if (value == null || value == "") {
        return false;
    }
    var value = document.forms["myform"].elements["summary"].value;
    if (value == null || value == "") {
        return false;
    }

    var value = document.forms["myform"].elements["comment"].value;
    if (value == null || value == "") {
        return false;
    }
    return true;

}
<html>
<head> </head>
<body>
<!-- Favorites -->
<table border="0" cellpadding="10" cellspacing="0" width="100%">
    <tr>
        <td>

        <div dojoType="dijit.TitlePane" title="Feedback Form">
        So how did you like this webpage?  <BR>
        <FORM id=myform " NAME="myform" ACTION="https://www.vogella.com/FeedbackForm/FeedbackSave" method="get"
            onclick="return updateFormAction()"><input TYPE="hidden"
            NAME="webpage" VALUE="test">

        <table>
            <tr>
                <td></td>
            </tr>
            <tr>
                <td align="right">User: (*)</td>
                <td><input name="user" type="text" size="30" maxlength="30"></td>
            </tr>
            <tr>
                <td align="right">Email:(*)</td>
                <td><input name="email" type="text" size="30" maxlength="30">
                (will not be visible)</td>
            </tr>
            <tr>
                <td align="right" valign="top">Summary:(*)</td>
                <td><input name="summary" type="text" size="30" maxlength="30"></td>
            </tr>
            <tr>
                <td align="right" valign="top">Comment:(*)</td>
                <td><textarea name="comment" rows="6" cols="40"></textarea></td>
            </tr>
            <tr>
                <td></td>
                <td><input type="submit" value="Submit"></td>
            </tr>
            <tr> <td colspan="2"> <div id="replacefeedback"> (*) are required </div></div> </td></tr>
        </table>
        </FORM>
        </div>
        </td>
    </tr>
</table>
</body>
</html>

9. Modern JavaScript

JavaScript is evolving rapidly. Initially, it was knows as a client-side scripting language, for web page manipulation, validation, and minor processing. After the introduction of Google’s V8 and Node.js, there were an increasing number of ways of using it in programming.

With its increasing importance also in backends, JavaScript is now considered "The programming language for the web", used on the Full Stack: Client, Server, and Middleware. Furthermore, you can use Modern JavaScript also to write applications running on Mobile, Desktop, and Containers.

modern javascript idea

Some examples of modern JavaScript usage are: Web UIs; Mobile UIs; Browser-based applications; IoT applications; large-scale real-time systems; REST-APIs services; databases; etc.

In this article, we’ll introduce Modern JavaScript's workflows, and tools, using Eclipse with JSDT 2.0 as main IDE.

9.1. JSDT 2.0 (JavaScript Development Tools)

JSDT is the Eclipse Project supporting JavaScript development, also used as base by commercial tools like JBossTools, ZendStudio, etc.

JSDT 1.x, shipped until Eclipse Mars.2, was used for Classic client-side JavaScript, supporting ECMAScript 3.0 (ES3, 1999).

JSDT 2.x, shipped from Eclipse Neon on, is a total reboot of the tooling, to fill existing gaps with Modern JavaScript, supporting:

  • ECMAScript 6 (ES6, 2015)

  • Node.js and tools like npm, Bower, Gulp and Grunt

  • Chromium debugging

9.1.1. JSDT parser/compiler infrastructure

JSDT changed several parser/compiler toolchains. Below you see a brief resume:

  • JSDT 1.0, until Mars.2: supports ES3 using Rhino (Mozilla Foundation), a Java-based parser/compiler for JavaScript.

  • JSDT 2.0, initial release: supports ES6 using Esprima (jQuery Foundation). As Esprima is written in JavaScript, this version of JSDT 2.0 needs to hook Nashorn, the Java8’s JS interpreter.

  • JSDT 2.0, from Neon.2 release: supports ES6 using ClosureCompiler (Google), a java-based parsing infrastructure for JavaScript.

9.1.2. ECMAScript 6 (ES6)

JSDT 2.0 supports ECMAScript 6 (ES6, 2015), the most recent spec. at development time. ES6 introduces new language features, such as Classes, default parameters, template literals, destructuring assignments (from Node.js), and much more.

// Class
class Smartphone extends Phone {
  constructor(name){
    super('Smart Phone')
    // ..
  }
}

// default parameters
var addRows = function(parent, nRows=10, bgColor='red'){
  // ..
}

// template literals
var welcome = `Welcome, mr. ${name} ${surname}.`
var url = `http://server.co/api/message/${id}`

// destructuring assignments
var {user,pass} = request.body
var [line1, line2, line3] = file.split('\n')

9.1.3. Node.js and Tools

Node.js is an increasingly popular JavaScript runtime, generally used with a variety of connected tools.

JSDT 2.0 supports running and debugging Node.js applications, using commands available in the context menu.

JSDT 2.0 also integrates common Node.js tools, as:

Package Managers, using JSON-based files to manage and install dependencies:

  • Npm: used for installing node modules. Its nested dependency tree is generally heavy in size.

  • Bower: for installing frontend components. Its "flat folder" structure avoids duplicate downloads and helps reducing page loads.

Task runners, to automate operations:

  • Grunt: to configure separate independent tasks. It uses a json-based file to describe the tasks.

  • Gulp: intuitive and fast task runner. The tasks are defined in a file with JavaScript syntax.

9.1.4. Chromium Debugging

JSDT 2.0 uses Chromium as JavaScript debugger. The code, developed as part of Google Chrome dev tools, is now EPL-licensed, and available in the JSDT repository, under the org.eclipse.wst.jsdt.chromium project.

More information about the adoption of the Chromium Debugger in JSDT are available in the transcription of the JSDT Confcall about the Debugger.

9.2. Exercise: Install Node.js and tools

To use JSDT 2.0 for the tutorials, install Node.js and tools on your system, then verify the installation is correct.

Download and install Node.js on your computer. The default installation should provide both node and npm commands. Verify the installation by checking the versions of the two commands.

$ node -v
v4.4.5
$ npm -v
2.2.15

Before adding other Node.js plugins, ensure your npm is up-to-date, by running the below command. Note that -g means globally, or system-wide.

$ npm update -g npm

Now, install Bower, Gulp and Grunt using Npm, the Node.js package manager. Install the modules globally, with the -g flag, using the commands below.

Note: in linux systems, you might need to use sudo npm …​

$ npm install -g bower
$ npm install -g grunt
$ npm install -g grunt-cli
$ npm install -g gulp
$ npm install -g gulp-cli

When done, check the tools are available in your system, by checking their versions via command line.

$ bower -v && grunt -version && gulp -version
1.7.9
grunt-cli v1.2.0
[17:18:39] CLI version 1.2.2
[17:18:39] Local version 3.9.1

9.3. Get your IDE with JSDT 2.0

JSDT 2.0 is available starting from Eclipse Neon, and is shipped either in Eclipse IDE for Java EE Developers, or for JavaScript and Web Developers.

get eclipse ide for jee or javascript developers

In the tutorial, we will use the latest JSDT features integrated with Java EE and web development.

Download the latest version of the Eclipse IDE for Java EE Developers from the EPP download page, or from the EPP downloads for developers.

When done, unzip and launch the IDE. Then, open the Console by pressing Ctrl+Alt+Shift+T, and type npm -v.

verify npm from command prompt

If you can read the npm version, the installation is successful, and we can proceed creating out first Node.js application with JSDT.

9.4. Run a Node.js Application

Create a new General Project named com.vogella.jsdt.test. Select the project, press Ctrl+N, type npm init, and select the entry to create a new npm Init file.

new npm init file

With the npm Initialization Wizard you can initialize the NPM package providing the main information for your Node.js module.

new npm init wizard S

When done, the wizard generates the package.json, which is the file describing the Node.js module packaging and information.

generated package json

In the package.json, we read "main" : "index.js", which declares the main entry point for the module is index.js . For most modules, it makes the most sense having a main script and often not too much else.

9.4.1. A simple Node.js application

Create a new file named index.js, the main entry point for the application, and add the content you see below.

/** com.vogella.jsdt.test/index.js */
var open = require('open');

// open with default browser
open('https://www.vogella.com/tutorials');

The program declares a dependency to the module open, and uses a function of that module to open a the system default browser passing a given URL.

Test the program running it with Node.js by selecting the file, right-clicking and choosing Run as > Node.js application.

run as nodejs application

After running, we’ll see a console error: Error: Cannot find module 'open'. This is because Node.js is missing a reference to the module named "open".

9.4.2. Installing dependencies

To fix this issue, we need to add the module to the package.json dependencies and then install the dependencies by downloading them locally.

To add the missing dependency, edit manually the package.json, by adding a development-time dependency to the latest version ("*") of the module "open".

{
  "name": "com.vogella.jsdt.test",
  "version": "0.1.0",
  "description": "JSDT test project",
  "main": "index.js",
  "scripts": {
    "test": "echo 'Error: no test specified' && exit 1"
  },
  "author": "Patrik Suzzi",
  "license": "EPL",
  "devDependencies" : {
    "open" : "*"
  }
}

Then, run the npm install using hte JSDT integration: right click on package.json and select Run As > npm Install.

run as npm install

As a result, you will see all the needed dependencies downloaded under the node_modules folder.

node modules downloaded

Now, we can run the application again, right-clicking the index.js and then selecting Run As > Node.js Application. This time, as a result, we expect to see the Node.js instance launching the browser and opening the given webpage.

open browser with nodejs S

10. JavaScript Frontend Example

In this example, we’ll build an Angular.JS single page application with routing and controllers. The styling will be done with Bootstrap and FontAwesome. At the end, we’ll use a Node.js script to launch an Express server and serve the application on localhost.

10.1. Install frontend components with Bower

Create a bower.json file, using the shortcut: Ctrl + N > "Bower init". Add the dependencies we’ll use in the project: angular, angular-route, bootstrap and font-awesome.

The bower file should look like the snippet below.

{
  "name": "jsdt.demo01",
  "version": "1.0.0",
  "license": "EPL",
  "ignore": [
    "**/.*",
    "node_modules",
    "bower_components",
    "test",
    "tests"
  ],
  "dependencies": {
    "angular": "1.2.25",
    "angular-route": "1.2.25",
    "bootstrap": "3.0.0",
    "font-awesome": "4.0.0"
  }
}

JSDT integrates the Bower command in Eclipse, so you can launch it via context menu.

To download and install all the frontend components, right-click on the bower.json file, and select Run As.. > Bower Install.

So doing, all the needed components will be downloaded under the default folder: bower_components.

bower install results

10.2. Test frontend libraries

We test the imported libraries with a simple HTML using the most important javascript and css.

  • In the <html> tag, use the ng-app directive

  • In <head>, reference js and css libs from bower_components

  • In <body>, test Bootstrap styling and Angular instructions.

<!DOCTYPE html>
<html ng-app>

<head>
  <title>Demo 01</title>
  <!-- Bootstrap and Font-awesome css -->
  <link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.css" />
  <link rel="stylesheet" href="bower_components/font-awesome/css/font-awesome.css">
  <!-- Scripts -->
  <script src="bower_components/angular/angular.js"></script>
  <script src="bower_components/angular-route/angular-route.js"></script>
</head>

<body>
  <div class="container">
    <!-- Nav bar / header -->
    <nav class="navbar navbar-inverse">
      <a class="navbar-brand" href="#">Demo 01</a>
    </nav>
    <!-- Main content -->
    <div class="main">
      <div class="jumbotron text-center">
        <h1>{{'Hello,'+' world!'}}</h1>
        <!-- put in a circle a rectangular image -->
        <img src="html_128.png" class="img-circle" alt="HTML5">
      </div>
    </div>
  </div>
</body>

</html>

You can test visually that Boostrap is loaded and Angular is working. The working web application, should look like the image below.

jsdt.demo01 hello world 01

In this case you can verify that Boostrap is providing styles to the page, and putting a link::res/jsdt.demo01/html_128.png[square image] in a circle; while Angular can evaluate expressions like {{'Hello,'+' world!'}}.

Below you can see a screenshot of what the page would look like in case Angular and Bootstrap are not loaded.

jsdt.demo01 hello world 01b no libs

10.3. Angular Application

Create a javascript file named application.js, which will contain the code for the Angular application, and paste the code below.

/** application.js */

// module
var app = angular.module('jsdtApp', []);

//controllers with injected angular $scope
app.controller('mainController', function ($scope) {
  // create a message to display in our view
  $scope.message = 'Learn more about JSDT at https://wiki.eclipse.org/JSDT';
});

The first line creates an Angular application named jsdtApp, and declare it uses ngRoute as imported module.

The second statement, defines a controller named mainController. When the controller is created, assigns a value to $scope.message, a scope variable that we will use later, to display a message.

10.3.1. Use Angular Application in HTML

Now we edit the HTML file use the Angular application.

  • In <html>, set the application name ng-app="jsdtApp", as we defined in the module.

  • In <head>, include the angular application: application.js

  • In <body>, add the controller directive: ng-controller="mainController"

  • In <div id="main">, print the message from the controller: $scope.message .

The HTML below represents a full working solution

<!DOCTYPE html>
<html ng-app="jsdtApp">

<head>
  <title>Demo 01</title>
  <!-- Bootstrap and Font-awesome css -->
  <link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.css" />
  <link rel="stylesheet" href="bower_components/font-awesome/css/font-awesome.css">
  <!-- Scripts -->
  <script src="bower_components/angular/angular.js"></script>
  <script src="bower_components/angular-route/angular-route.js"></script>
  <!-- Application -->
  <script type="text/javascript" src="application.js"></script>
</head>

<body ng-controller="mainController">
  <div class="container">
    <!-- Nav bar / header -->
    <nav class="navbar navbar-inverse">
      <a class="navbar-brand" href="#">Demo 01</a>
    </nav>
    <!-- Main content -->
    <div class="main">
      <div class="jumbotron text-center">
        <h1>{{'Hello,'+' world!'}}</h1>
        <!-- put in a circle a rectangular image -->
        <img src="html_128.png" class="img-circle" alt="HTML5">
        <p>{{message}}</p>
      </div>
    </div>
  </div>
</body>

</html>

Test visually the angular controller is working by observing the {{message}} is present.

jsdt.demo01 hello world 02

10.4. Angular Routing

Routing means loading dynamically multiple HTML views inside a SPA (Single Page Application).

As an example, we’ll use clickable links on the navigation bar, to change the main content.

Angular routing is not intended to work on local files. You should serve pages using a web server to avoid Cross origin request problems.

10.4.1. Multiple HTML Views

We start creating three views to display the contents: about, contact, and home.

<!-- home.html -->
<div class="jumbotron bg-light text-center">
  <h1>{{'Hello,'+' world!'}}</h1>
  <img src="html_128.png" class="img-circle" alt="HTML5">
  <p>{{message}}</p>
</div>
<!-- about.html -->
<div class="jumbotron bg-dark text-center">
  <h1>About</h1>
  <p>{{message}}</p>
  <a href="https://www.google.it/search?q=JSDT" class="btn btn-default btn-lg">
    <i class="fa fa-search" aria-hidden="true"></i> Search</a>
</div>
<!-- contact.html -->
<div class="jumbotron bg-orange text-center">
  <h1>Contact</h1>
  <p>{{message}}</p>
</div>

Note that the views are different each other, but all are using a {{message}} object. Also note the views are using css classes bg-light, bg-dark and bg-orange, to be defined later.

10.4.2. Configure Routing and multiple Controllers

As we already included the angular-route.js script in the HTML, we can add the dependency to the ngRoute module in the Angular.js application.

Then, we edit the javascript file, using the $routeProvider, to configure three routes, one for each content page we created.

For each route we declare its path; we define the templateUrl to find the HTML view template; and we assign a controller to manage the view lifecycle.

Then, we add three controllers to the app, one for each page. So doing we store page specific messages in the angular $scope.

Note: controllers contains business logic for a view. You can learn more in the official documentation

Based on the above premises, we edit the javascript file, so that it looks like the snippet you can see below.

var app = angular.module('jsdtApp', ['ngRoute']);

//configure routes
app.config(function ($routeProvider, $locationProvider) {
  $routeProvider
    .when('/', {
      templateUrl: 'pages/home.html',
      controller: 'mainController'
    })
    .when('/about', {
      templateUrl: 'pages/about.html',
      controller: 'aboutController'
    })
    .when('/contact', {
      templateUrl: 'pages/contact.html',
      controller: 'contactController'
    });
});

//controllers with injected angular $scope
app.controller('mainController', function ($scope) {
  // create a message to display in our view
  $scope.message = 'Learn more about JSDT at https://wiki.eclipse.org/JSDT';
});

app.controller('aboutController', function ($scope) {
  $scope.message = 'The JavaScript Development Tools (JSDT) \
        provide plug-ins for an IDE supporting JavaScript development.';
});

app.controller('contactController', function ($scope) {
  $scope.message = 'Please, get in touch with open source development.';
});

10.4.3. Enable Routing in HTML

To enable routing we need to edit the main HTML file as follows:

  • Add navigation links to activate routing

  • Add the ng-view tag, to mark the area to be replaced by views

Below you can see the updated HTML inside the <body> element.

<body ng-controller="mainController">
  <div class="container">
    <!-- Nav bar / header -->
    <nav class="navbar navbar-inverse">
      <div class="container-fluid">
        <div class="navbar-header">
          <a class="nav navbar-brand" href="#">Demo 01</a>
        </div>
        <ul class="nav navbar-nav navbar-right fa-2x">
          <li><a href="#"><i class="fa fa-fw fa-home"></i> Home</a></li>
          <li><a href="#about"><i class="fa fa-fw fa-book"></i>About</a></li>
          <li><a href="#contact"><i class="fa fa-fw fa-comment"></i>Contact</a></li>
        </ul>
      </div>
    </nav>
    <!-- Main content -->
    <div class="main">
      <div class="ng-view"></div>
    </div>
  </div>
</body>

10.4.4. Add style

To complete the page, add some inline style, to give different colors at the content pages, and to animate the user selection on navigation bar.

<head>
  ...
  <style type="text/css">
    .bg-dark { background-color: #6e6e6e; color: #ffffff; }
    .bg-light { background-color: #f4f4f4; color: #505050; }
    .bg-orange { background-color: #ff9900; color: #ffffff; }
    li:hover { background-color: #ff9900; }
  </style>
</head>

10.4.5. Test Routing avoiding issues

As anticipated, Angular Routing is not supposed to work on local files. Therefore, you can see empty areas, when loading an HTML file from the local filesystem.

At the time I’m writing, Firefox is able to render the routing example as we expect.

jsdt.demo01 routing 01 firefox

But, Chrome doesn’t work as Firefox, as its security model doesn’t allow serving local files when routing. In this case, you can detect the error inspecting the page and looking at the console.

jsdt.demo.01 hello frontend 03 no routing

The real point of this section, is understanding that your frontend is not a simple local webpage. Instead, it is an application that should live in a webserver.

To fix this, we’ll use Node.js to launch a lightweight server and publish our SPA. So doing, you’ll access the frontend at a web address like http://localhost:3222

10.5. Node.js server on Localhost

In this section, we’ll see how to use Node.js to launch a local server to display our frontend.

Create a package.json file with the content you see in the snippet below.

{
  "name": "com.vogella.jsdt.demo.neon01",
  "version": "1.0.0",
  "author": "Patrik Suzzi",
  "license": "EPL",
  "devDependencies": {
    "express": "*",
    "open": "*"
  }
}

Note that we are importing two existing node modules:

  • express, providing a lightweight local server

  • open, providing a command to launch the default browser.

Then, use the JSDT integrations to install the libraries. Right-click on the package.json and select Run As.. > NPM Install.

run as npm install 2

This will install the needed dependencies under the node_modules folder.

Then, create a javascript file called launch-server.js with the content below.

/** launch-server.js */

var open = require('open'),
  express = require('express'),
  app = express(),
  port = 3222;

// configure serving static content
app.use(express.static(__dirname + '/'));
// enable URL rewrite to support HTML5Mode: send the index.html
app.all('/*', function (req, res, next) {
  res.sendFile('index.html', { root: __dirname });
});

// launch server
app.listen(process.env.PORT || port, function () {
  console.log('Express server on http:/localhost:' + port + '!');
});

// open with default browser
open('http://localhost:' + port);

As you can see, the code loads the modules, starts the local server, and opens the inex.html. Please, not this server is configured to support URL-rewrite, hence you can reload pages and re-use URLs like in common rest applications.

Now, run the Node.js script to see the frontend application running on server. R-click 'launch-static-server.js' and select Run As .. > Node.js Application. This will launch node passing your script as parameter

run as nodejs application 2

Now that the application is running on a local webserver, we can test it works as expected. Below you can see screenshots with the final result.

jsdt.demo01 final result 01 home
jsdt.demo01 final result 02 about
jsdt.demo01 final result 03 contact

10.6. Tips for a Professional Single Page Application

To have a more professional single-page applications, we should remove hashtags from webaddresses.

To do so, first you should use the $locationProvide.html5Mode, as shown below.

//configure routes
app.config(function ($routeProvider, $locationProvider) {
  // ..
  // use HTML5 History API to rewrite urls
  $locationProvider.html5Mode(true);
});

Then we should edit the HTML, by removing hashtags in redirect URLs

  <ul class="nav navbar-nav navbar-right fa-2x">
    <li><a href="/"><i class="fa fa-fw fa-home"></i> Home</a></li>
    <li><a href="/about"><i class="fa fa-fw fa-book"></i>About</a></li>
    <li><a href="/contact"><i class="fa fa-fw fa-comment"></i>Contact</a></li>
  </ul>

Finally you can see that the URLs in your web applications are now looking more professional.

jsdt.demo01 final result 04 html5 url rewrite

10.7. Source Code

You can find the source code for this tutorial in the https://github.com/vogellacompany/codeexamples-javascript repository, under the com.vogella.jsdt.demo.neon01 directory.

11. JavaScript Fullstack Example

In this example we will see how to use JSDT 2.0 to build and run a fullstack application, with

  • frontend: Angular/Bootstrap

  • Backend: NodeJS / Express / MongoDB

Once built, we’ll see how to debug this NodeJS Backend

12. Modern JavaScript integration with JEE

In this section, we’ll see how to integrate modern JavaScript within a JEE application, and how to debug JavaScript and Java together within Eclipse.

13. Contribute to JSDT

This section explains how you can contribute to open source improving Eclipse JSDT 2.0 and above.

13.1. Get Ooomph and build the IDE to contribute to JSDT

Download and launch Oomph on your workstation, then switch to the advanced mode.

Select the Eclipse IDE for Committers as base Product and click Next.

oomph select product

Select JSDT as Project to Provision and click Next.

oomph select project

Then, check the Oomph installation variables, and edit them according to your needs.

oomph install variables

When done, click Next and finalize the installation.

When the installation is complete, the development IDE is launched automatically.

At the first startup, you’ll have to wait for the completion of the startup tasks. Startup tasks include getting source from Git, updating Mylyn tasks, and also requesting additional authentication if needed.

executing startup tasks

When the startup tasks are done, click away the welcome window, and enter the IDE. Verify the source code is downloaded and available in different project sets.

In the IDE, you can also see a list of Mylyn tasks for JSDT Bugs, and Open reviews.

jsdt development ide ready

13.1.1. Launch JSDT

In this section we’ll run JSDT from source code using an existing launch configuration. Select from menu: Run > Run Configuration.. , and select the JSDT Launch Configuration.

This launch configuration contains all the plug-ins needed to run JSDT, and also defines the VM arguments needed to hook Nashorn.

jsdt launch configuration

To verify the run configuration works, click Run, to launch Eclipse IDE with JSDT. Then create a JavaScript project and create a new npm init file inside the project.

verify jsdt run configuration

Now you are able to run JSDT from the source code, and you can easily contribute to the project.

13.2. Find a bug and fix it

You can find a list of JSDT open bugs using this Bugzilla query

14. TypeScript support in the Eclipse IDE

Angelo Zerr provides support for TypeScript. See https://github.com/angelozerr/typescript.java for details.

15. JavaScript with Eclipse resources