Client Side Programming

Client Side Programming

So far, we have talked mostly about programming on the server-side.

We can't ignore how important the server is: it's the only thing you can rely on for security, data storage, etc.

Client Side Programming

Logic can also be embedded in HTML and executed by the user's browser.

The <script> tag can be used to insert logic onto a page.

JavaScript

In theory, any language could be used. In practice, we're limited by browser support.

That limits us to one choice: JavaScript. (Generally.)

JavaScript

Like with HTML and CSS, we are relying on the user's browser to run the JavaScript code. That means…

  1. The code might not run. They might have JS turned off; search engines might not execute your JS (… the way you imagine?); user might be using a weird browser without JS, ….
  2. The code might not work the same way it does in your browser. Different browsers implement different language features. You have to worry about code compatibility a lot.

You're going to find yourself looking at compatibility tables in docs again.

Inline JavaScript

The <script> tag can be used to reference an external JS file:

<script src="codefile.js"></script>

Or you can include JS code inline:

<script>
/* code goes here */
</script>

Or really inline:

<a href="javascript:…" onclick="…"></a>

Inline JavaScript

Putting JS code in your HTML (or HTML templates) is probably a bad idea.

  • It's bad style: mixing more than one language in a single file is hard to read.
  • It's harder to maintain: if some logic is broken, it can be hard to find (especially since there can be multiple <script> in a page).

Inline JavaScript

  • Embedded JS will be blocked by any sensible Content-Security-Policy header, which will prevent inline code from running for XSS mitigation. Prevents both <script>…</script> and <a href="javascript:…">.

Inline JavaScript

  • Validation problems: if you want to make a comparison in your JavaScript: i<10 && j>0, the corresponding HTML is i&lt;10 &amp;&amp; j>0.
  • No caching: you see the JS in one HTML template, but that produces many different resources. JS code must be delivered with each.

Inline JavaScript

Possible exception: short setup code, especially with a parameter from a template.

<script src="/code/main.js"></script>
<script>
  var data_id = {{ dataobject.id }};
  setup_this_page(data_id);
</script>

Will still have Content-Security-Policy problems (unless you add a nonce to it). Impact on caching is minimal.

Inline JavaScript

Or maybe you don't need the inline JS, but can include the info you need in data-* attributes:

<body data-id="{{ dataobject.id }}">

… and then read them in JS.

function setup_this_page() {
    var my_id = document.querySelector('body').dataset.id;
    ⋮
    

DOM

The Document Object Mode (DOM) is a standard API to manipulate HTML/​XML documents.

e.g. grab every <li> from within a particular <ul> and collect the contents.

e.g. find the element with id="foo" and change its contents.

DOM

DOM gives a standard object-oriented way to access and manipulate an XML document. It's independent of programming language: can use in JavaScript, Python, Java, Ruby, ….

It provides a standard object-hierarchy (classes, method, etc) to represent and manipulate XML data.

DOM + JavaScript

The DOM is useful in many programming languages, but central to [client-side] JavaScript.

The JavaScript code lives inside an HTML page, so the DOM is an obvious way to access the page from within code.

DOM + JavaScript

There is a global object document that is the DOM document object for the current page.

It's a DOM Document object and the entry point for DOM functionality.

DOM + JavaScript

For example, get a collection (a DOM NodeList or HTMLCollection) of all paragraphs on the page, or all elements with class="interesting":

var pars = document.getElementsByTagName('p');
var ints = document.getElementsByClassName('interesting');

DOM + JavaScript

The .querySelector() and .querySelectorAll() methods were added in DOM4/​Selectors API and are implemented in modern browsers. They take a CSS selector and return NodeList.

var pars = document.querySelectorAll('p');
var ints = document.querySelectorAll('.interesting');
var inter_pars = document.querySelectorAll('p.interesting');

… like you thought you needed jQuery for (but more verbose, and maybe faster?).

DOM + JavaScript

The DOM API can also manipulate the document in-place.

var body = document.querySelector('body');
var new_p = document.createElement('p');
new_p.appendChild(document.createTextNode("I'm some text"));
body.appendChild(new_p);

But the equivalent with jQuery is:

$('body').append("<p>I'm some text</p>")

AJAX

One of the tricks JavaScript can do: make an HTTP request.

This opens up a huge variety of techniques: your code can contact the server to get/​send information whenever it wants, and update the page as a result.

AJAX

Techniques that use server interaction are often called AJAX: Asynchronous JavaScript And XML.

  • Asynchronous: the server can be contacted at any time, not just when a page refresh happens.
  • JavaScript: the language we're using.
  • XML: a way to serialize the data being sent in either direction. JSON is much more common in the modern world.

AJAX

There is an XMLHttpRequest object that makes all of this possible: it contains methods for making an HTTP request and dealing with the results.

You may see XHR as an abbreviation for this object and/or AJAX stuff.

Processing the results is done with a callback function: the JS process doesn't prevent other code from running while waiting for the response: non-blocking IO.

AJAX

Using the XMLHttpRequest object manually is a little clumsy. *

function reqListener() {
  data = JSON.parse(this.responseText);
  console.log(data["stuff"]);
}
var oReq = new XMLHttpRequest();
oReq.addEventListener("load", reqListener);
oReq.open("GET", "http://example.com/data.json");
oReq.send();

AJAX

It's more common to let a library simplify things. With jQuery.ajax:

$.ajax('http://example.com/data.json', {
  dataType: 'json',
  success: function(data, status, xhr) {
    console.log(data['stuff']);
  }
});

Plus: error handling etc. is much more straightforward.

AJAX

An AJAX request can be used to fetch data from, or send data to the server (or any combination). Some ways that can be used:

  • Update the page with new info.
  • Build the page from fragments generated by the server.
  • An autocomplete input that gets possible values from the server.
  • An autosave of a partially-complete form.
  • Cooperation between server and client to calculate data for display.

Real-Time AJAX

It is common to want to get real-time updates from the server. To do that, the server would have to send new info whenever it's available.

e.g. chat app; live news feed; real-time game between users.

Real-Time AJAX

Real-time communication isn't what HTTP was designed for, and it's a bad fit.

Option 1: poll. Client makes a request (with XMLHttpRequest) every few seconds asking for new info. Lots of overhead in requests/​bandwidth.

Real-Time AJAX

Option 2: long-polling. Client makes an HTTP connection, the server waits until it has some new info to report and then responds.

Requires many open TCP connections on the server. Most server software isn't good at that.

Real-Time AJAX

Option 3: WebSockets. If HTTP isn't the right protocol for the job, use a different one.

The WebSockets protocol lets servers and clients exchange data in either direction. The interface is more low-level than XHR interactions: you can .send() and set an .onmessage handler.

Real-Time AJAX

It's probably much easier to use a library like Socket.IO to work with WebSockets.

The server-side programming model is usually “how do I respond to a request?” Now it has to be “some new data has arrived, who should I send it to?” That's going to require a big change (at least for that part of the site).

Progressive Enhancement

or graceful degradation if you're a pessimist.

We need to arrange our site/​app so the content works in whatever situation we send it to: modern desktop browser, smartphone browser, Google, other automated tool, …

Progressive Enhancement

We need to structure the page so that any of these can make sense of the content, as best possible with the capabilities they have.

e.g. Google only cares about content, so is more interested in your HTML: it should be able to get useful info out of just that.

e.g. Chrome should be able to do all of the JavaScript stuff you want.

Progressive Enhancement

The underlying structure of the web helps here:

  • Content in HTML, with as much semantic meaning as possible: everybody should be able to handle this.
  • Style with CSS, using media selectors to turn on/off as appropriate.
  • Behaviour with JavaScript.

Progressive Enhancement

The technologies have been designed with this in mind.

e.g. for an <input>, the default type is type="text". If you use <input type="date"> in a browser that doesn't support it, it will just look like a text input.

On browsers that support it, you get a nice date selector, including something media-appropriate on a mobile or other non-desktop browser.

Of course, you must validate input server-side anyway.

Progressive Enhancement

Code your sites with progressive enhancement in mind.

You should have an idea of what HTML/​CSS/​JavaScript features are going to work in various browsers. Think about what happens to the site if individual features don't work.

Test in as many different situations as possible.

Progressive Enhancement

I prefer to think of JavaScript as a way to enhance pages: start with a functional page/site that can be used without JavaScript. Use JavaScript to make it better.

e.g. in browsers where your JavaScript library can build a date selector, turn it on. In other browsers, the user gets a text input, which is okay.

Progressive Enhancement

This line of thinking can extend to mobile/​desktop development.

Start with a site that works well on desktop/​mobile, then enhance so it's better on mobile/​desktop. That could involve CSS or JavaScript tweaks for either scenario.

JavaScript Frameworks

JavaScript itself is basically just a programming language. It's not perfect.

There are many common problems that aren't solved by built-in language features, but you don't want to solve yourself.

JavaScript Frameworks

The solution is the same as always: libraries and frameworks (≈big libraries).

There is a huge variety of JavaScript libraries. I'll make some attempt to categorize them…

JavaScript Frameworks

The most basic libraries just fix things “wrong” with the language.

e.g. simplify DOM work, AJAX, event handling; extra types/​collections.

jQuery seems to be the winner here.

JavaScript Frameworks

Others do specialized jobs.

… and thousands of others available from npm.

JavaScript Frameworks

The “frameworks” tend to be bigger and influence most/​all of your JS code.

Again, there's a lot of variety in what gets called a JavaScript framework. Just like with server-side frameworks, programmers sometimes forget they have a programming language available and can just program: not everything has to be a framework call.

JavaScript Frameworks

In general they handle some of these steps: server API ↔ HTTP+JSON ↔ objects ↔ display for user.

Don't forget that server API part means you're going to have to create a server API.

JavaScript Frameworks

API ↔ HTTP+JSON ↔ objects: getting data between the server (in the DB) and client (in objects we can work with). A lot like an ORM.

e.g. Backbone.js, Meteor, Ember Data.

JavaScript Frameworks

Objects ↔ display for user: how/​when to we update the page for the user? How do we update our objects when the user does things? Data binding.

Will likely include some kind of template rendering, which indicates how objects will turn into HTML.

e.g. Angular (↔), Ember (↔), Meteor (→?), React (→)

JavaScript Frameworks

That's obviously all over-simplified. All of the frameworks do much more than that. Some really badly; some really awesomely.

Remember the technology evaluation? Hopefully that had useful details.

Server-Side JavaScript

JavaScript has a lot of things in its favour:

  • It's a generally nicely designed language.
  • Very fast execution by modern just-in-time compilers.
  • Anybody doing web development probably already knows it.
  • Heavily used, so lots of libraries and help online.

Server-Side JavaScript

So why not use JavaScript on the server-side as well?

You could have only one (programming) language for your project: easier source management, fewer skills needed when hiring, etc.

Server-Side JavaScript

Can re-use code on both sides.

For example, input validation. You want to make sure users enter the correct format in the browser for nice UI, but must check it on the server for security/​correctness.

If you have anything but JS on the server-side, you need to write the logic twice (or do some transpiling magic).

This thinking leads to Meteor which is a both a server- and client-side framework.

Server-Side JavaScript

But on the server, you have the choice of any programming language you want. Is JavaScript really the best one in the world?

Wouldn't you rather write Python/​Scala/​Groovy/​Erlang?

Server-Side JavaScript

So is server-side JavaScript a good idea?

Maybe.