One Hour with JavaScript
Instructor: Ian Carroll
What JavaScript is:
- The de facto scripting language for the world wide web
- Object oriented, but without classes (no, really!)
- Reminiscent of Java (duh!) and C syntax
- Dynamically typed (phew!)
Hello, World!
JavaScript interpreters are built into modern browsers, so there is nothing to install if you already have Chrome, IE, Safari, Firefox, etc. All you need to do is create a document the browser will recognize, i.e. create a webpage.
<!doctype html>
<html>
<body>
<script>
var hello = "Hello, World!";
console.log(hello);
</script>
</body>
</html>
Point your browser to file:///%sandbox%/index.html
. Find where the JavaScript “console” resides by looking for “Developer” views on your browser.
Modularization
Modularization is the process of breaking a project into components (the modules), each one encapsulating a mostly indepdent process. Communication between modules depends, more or less, on their capacity for taking input and returning output.
Our first modularization step is to get the JavaScript out of the HTML!
var hello = "Hello, World!";
console.log(hello);
<!doctype html>
<html>
<body>
<script src="hello-world.js"></script>
</body>
</html>
Data Types
Although the type of data referenced by a variable is determined automatically (and can change), the type must still be recognizable. There are just a few data types in JavaScript – they’re all listed below. The vast majority of variables you work with will be of an “object” data type, which will consist of other objects as well as any of the remaining six “primitive” data types.
Type | Examples |
---|---|
number | 42 , 0.4 , NaN |
string | "Hello, World!" |
boolean | true , false |
object | Constructors: Array() , Date() , Function() |
Literals: {key: value, ... } |
|
undefined | the value of un-initialized variables |
null | deliberate non-value |
symbol | save this for your second hour with JS … |
Primitive data types behave quite naturally: you could guess many actions that are permitted on them. Try the following in your browser’s JavaScript console.
console.log(1 + 1 == 2)
true
Keywords
Certain keywords are reserved, which means they cannot be the name of a variable. The table below shows some of the most important keywords.
Keyword | Explanation |
---|---|
var |
declare a new variable |
let |
like var , but with a restricted scope |
function , return |
declare a variable that accepts arguments, and optionally returns a value |
new |
create a new object |
this |
the object that “owns” a statement |
for , which , etc. |
begin flow control statements |
var hello = "Hello, World!"; // Declare a variable and initialize it to a string
function print(greeting) { // Declare a function and initialize it to {...}
console.log(greeting)
};
print(hello);
Properties and the new
Keyword
An object has it’s own properties that are accessed with a .
between the object and property names. We’ve seen one so far – the log
property belonging to console
. When creating an object from an object literal, i.e. using {key: value, ...}
, each key becomes the name of an object’s property.
var dog = {"name": "Rex", "greeting": "Bark!"};
console.log(dog.name);
The new
keyword works together with constructors, which are functions that may use the keyword this
to assign properties to the object being constructed. It is convention to capitalize the name of a constructor.
function Dog() {
this.name = "Rex"; // "this" refers to a TBD object
this.greeting = "Bark!";
this.speak = function() { // Yes, there ARE two ways to use the function keyword!
console.log(this.greeting) // See the difference?
};
};
var rex = new Dog(); // Instantiate an object of "class" Dog
rex.speak(); // Good dog, Rex!
Exercise: Modify your index.html
file to use this script instead of hello-world.js
.
Flow Control & Scope
Flow control in JavaScript uses the same syntax as C (including the switch
statement, but that’s for another time). The for
keyword indicates a code block that will be repeated until the second statement of the immediately following (...; ...; ...)
phrase evaluates to true
.
var fibonacci = [0, 1]; // Wait, what? This is just a shortcut for the Array() constructor.
for (var i = 1; i < 10; i++) {
console.log("Index " + i + ": " + fibonacci[i]);
fibonacci[i + 1] = fibonacci[i];
};
Exercise: Wait a minute, that’s not right! Modify the for loop to get the Fibonacci sequence. It should go like this: 1, 1, 2, 3, 5, 8, 13, 21, …
Exercise: The keyword let
declares a variable with block, statement or expression level scope. Try replacing var i
with let i
and then logging the value of i
after the for
loop has run.
Document Object Model (DOM)
You get a lot for free with JavaScript running in a browser. One freebie is the document
object which allows your script to control the webpage using the DOM, an abstration (or model) of a webpage.
var heading = document.createElement('h1');
heading.textContent = "Hello, World Wide Web!";
document.body.appendChild(heading);
The script doesn’t change the source code for the webpage – the HTML on file in index.html
– but it modifies the page elements by re-writing the browser’s working version of the DOM that was initially described in the HTML file.
Interactive Vizualizations with Plotly.js
Let’s jump way ahead of ourselves. D3.js is a JavaScript library that draws scalable vector graphics (SVG), which are compositions of simple shapes or geometries, on a webpage. SVG graphics look great on a webpage and have the added benefit of being easilly manipulated – they’re part of the DOM! Each shape is an element, directly accessible from the document
object. Plotly.js is a JavaScript library, built on top of d3.js, that adds high-level charting capabilities.
Remember, JavaScript is meant to be interpreted online, so you can “import” any library distributed online by pointing the script src
attribute to an appropriate URL.
<!doctype html>
<html>
<body>
<div id="fig-1"></div>
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="viz.js"></script>
</body>
</html>
Aside from importing Plotly.js and d3.js, the webpage now includes a div
element identified as fig-1
. A div
element is a division, or section, of an HTML document. The id
attribute is special in that its value is assumed to be unique within all elements of a webpage. Initially, the div
has no content; the following script will add all the SVG elements to create the figure.
data = [{
x: [1, 2, 3, 4, 5, 6, 7],
y: [1, 1, 2, 3, 5, 8, 13],
}];
layout = {
title: "Fibonacci Sequence",
};
Plotly.plot("fig-1", data, layout)
Exercise: Once you have a plot visible in your webpage, find the JavaScript console under the “Developer” view again and examine the page elements (or, on most browsers, simply right-click the figure and choose to inspect the element). What class has been assigned to the original div
identified by figure-1
. Can you find a new div
that Plotly.js added to the DOM?
A data jedi wouldn’t write data directly into the script as we just did. Data should be stored seperately, wich its location indicated by a URL. Among the general purpose data tools in the d3.js library are functions for reading many data formats. To take full advantage of accessing data anywhere a URL might point, our webpage needs to be served (i.e. the browser needs to access it using the Hyper-Text Transfer Potocol, or HTTP). A handy Python module is useful for testing:
cd %sandbox%
python -m SimpleHTTPServer 8000
Now point a browser to http://localhost:8000
to verify the webserver is working.
We are going to plot real-time streamflow data aquired from a USGS web service. There are a few concepts to understand before we create the plot:
- Web service: a server that presents data in response to parameters supplied by the client in a HTTP request
- JavaScript Object Notation (JSON): a data format matching the “key: value” pattern of object literals
- callback function: packaged-up instructions for handling data once it has been aquired by an asynchronous process
function callback(response) {
var pre = document.createElement("pre");
pre.textContent = JSON.stringify(response, null, 4);
document.body.appendChild(pre);
};
var url = "http://waterservices.usgs.gov/nwis/iv/?format=json&sites=01646500&period=P7D¶meterCd=00060";
d3.json(url, callback)
The parameters embedded in the URL specify a data format, monitoring site, time period and observation variable. The callback function only evaluates after the function d3.json
receives a response from waterservices.usgs.gov
. This callback just prints a string representation of the JSON object retrieved.
To plot the data, we need to process the JSON object into x
and y
data arrays before calling Plotly.plot
.
function processTimeSeries(timeSeries) {
var ts = timeSeries.values[0].value;
var data = {
"type": "scatter",
"x": ts.map(function (i) {return d3.isoParse(i.dateTime)}),
"y": ts.map(function (i) {return i.value}),
};
var layout = {
"title": timeSeries.sourceInfo.siteName,
"yaxis": {"title": timeSeries.variable.variableName},
};
return {
"data": [data],
"layout": layout,
}
};
function callback(response) {
var timeSeries = response.value.timeSeries[0];
var figure = processTimeSeries(timeSeries);
Plotly.plot("fig-1", figure.data, figure.layout)
};
var url = "http://waterservices.usgs.gov/nwis/iv/?format=json&sites=01646500&period=P7D¶meterCd=00060";
d3.json(url, callback);
A primary reason to learn JavaScript is to produce interactive vizualizations on the web, so let’s leap forward once more. First, add a “select” form to the webpage.
...
<body>
<div>
Station: <select id="menu"></select>
</div>
...
Second, make the following changes to json-viz.js
:
- Re-write the callback function so it will
- parse multiple time-series
- add
option
elements to theselect
element in the DOM - attach a “listener” to the select form that responds to changes
- Update the URL to obtain all active stations in the state of Maryland
function callback(response) {
var timeSeries = response.value.timeSeries;
var fig = timeSeries.map(processTimeSeries);
var select = document.getElementById("menu");
for (let i = 0; i < timeSeries.length; i++) {
var option = document.createElement("option");
option.text = fig[i].layout.title;
option.value = i;
select.appendChild(option)
};
select.addEventListener(
"change",
function() {Plotly.newPlot("fig-1", fig[select.value].data, fig[select.value].layout);},
false
);
select.dispatchEvent(new Event("change"));
};
var url = "http://waterservices.usgs.gov/nwis/iv/?format=json&stateCd=md&period=P7D¶meterCd=00060&siteStatus=active";
Exercise: Study the USGS Water Serivces tool and plot data from a different location or of a different type.