@p Most web applications aren't neat little games which live on a single canvas: they are large, structured HTML pages, which involve displaying data (whether from the user or from the web) in multiple ways, while allowing the user to make changes to the data that can be saved back to whatever remote web-service/database it came from. @p At this point, you are already competent at using Scala.js to make basic, self-contained canvas applications. In this chapter, we will cover how to use Scala.js to build the sort of interactive-web-pages that make up the bulk of the modern-day internet. We'll cover how to use powerful libraries that turn front-end development form the typical fragile-mess into a structured, robust piece of software. @sect{Hello World: HTML} @p The most basic way of building interactive web pages using Scala.js is to use the Javascript APIs to blat HTML strings directly into some container div, often @code{document.body}. This approach works, as the following code snippet demonstrates: @div(cls:="pure-g") @div(cls:="pure-u-1 pure-u-md-13-24") @hl.ref("examples/src/main/scala/webpage/HelloWorld0.scala") @div(cls:="pure-u-1 pure-u-md-11-24") @div(id:="div1") @script("HelloWorld0().main(document.getElementById('div1'))") @p This approach works, as the above example shows, but has a couple of disadvantages: @ul @li It is untyped: it is easy to accidentally mistype something, and result in malformed HTML. A typo such as @hl.html{} would go un-noticed at build-time. Depending on where the typo happens, it could go un-noticed until the application is deployed, causing subtle bugs that only get resolved much later. @li It is insecure: @a("Cross-site Scripting", href:="http://en.wikipedia.org/wiki/Cross-site_scripting") is a real thing, and it is easy to forget to escape the values you are putting into your HTML strings. Above they're constants like @hl.scala{"dog"}, but if they're user-defined, you may not notice there is a problem until something like @hl.scala{""} sneaks through and your users' accounts & data is compromised. @p There are more, but we won't go deep into the intricacies of these problems. Suffice to say it makes mistakes easy to make and hard to catch, and we have something better... @sect{Scalatags} @p @a("Scalatags", href:="https://github.com/lihaoyi/scalatags") is a cross-platform Scala.js/Scala-JVM library that is designed to generate HTML. To use Scalatags, you need to add it as a dependency to your Scala.js SBT project, in the @code{build.sbt} file: @hl.ref("examples/build.sbt", "com.scalatags") @p With that, the above snippet of code re-written using Scalatags looks as follows: @div(cls:="pure-g") @div(cls:="pure-u-1 pure-u-md-13-24") @hl.ref("examples/src/main/scala/webpage/HelloWorld1.scala") @div(cls:="pure-u-1 pure-u-md-11-24") @div(id:="div2") @script("HelloWorld1().main(document.getElementById('div2'))") @p Scalatags has some nice advantages over plain HTML: it's type-safe, so typos like @hl.scala{dvi} get caught at compile-time. It's also secure, such that you don't need to worry about script-tags in strings or similar. The @a("Scalatags Readme", href:="https://github.com/lihaoyi/scalatags#scalatags") elaborates on these points and other advantages. As you can see, it takes just 1 import at the top of the file to bring it in scope, and then you can use all of Scalatags' functionality. @p The Scalatags github page has @a("comprehensive documentation", href:="https://github.com/lihaoyi/scalatags#hello-world") on how to express all manner of HTML fragments using Scalatags, so anyone who's familiar with how HTML works can quickly get up to speed. Instead of a detailed listing, we'll walk through some interactive examples to show Scalatags in action! @sect{User Input} @div(cls:="pure-g") @div(cls:="pure-u-1 pure-u-md-13-24") @hl.ref("examples/src/main/scala/webpage/Inputs.scala", "val box") @div(cls:="pure-u-1 pure-u-md-11-24") @div(id:="div3") @script("Inputs().main(document.getElementById('div3'))") @p In Scalatags, you build up fragments of type @hl.scala{Frag} using functions like @hl.scala{div}, @hl.scala{h1}, etc., and call @hl.scala{.render} on it to turn it into a real @hl.scala{dom.Element}. Different fragments render to different things: e.g. @hl.scala{input.render} gives you a @hl.scala{dom.HTMLInputElement}, @hl.scala{span.render} gives you a @hl.scala{dom.HTMLSpanElement}. You can then access the properties of these elements: adding callbacks, checking their value, anything you want. @p In this example, we render and @hl.scala{input} element and a @hl.scala{span}, wire up the input to set the value of the span whenever you press a key in the input, and then stuff both of them into a larger HTML fragment that forms the contents of our @hl.scala{target} element. @sect{Re-rendering} @p Let's look at a slightly longer example. While above we spliced small snippets of text into the DOM, here we are going to re-render entire sections of HTML! The goal of this little exercise is to make a filtering search-box: starting from a default list of items, narrow it down as the user enters text into the box. @p To begin with, let's define our list of items: Fruits! @hl.ref("examples/src/main/scala/webpage/Search0.scala", "val listings", "def") @p Next, let's think about how we want to render these fruits. One natural way would be as a list, which in HTML is represented by a @hl.html{