summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLi Haoyi <haoyi@dropbox.com>2014-10-26 22:54:44 -0700
committerLi Haoyi <haoyi@dropbox.com>2014-10-26 22:54:44 -0700
commit6987ac5195b0112b4bda123f0fced3ace7115932 (patch)
tree6d38c52d6a0d7876cde7f25b8ef39667bd168ef1
parentab668dead5c3123eb9fb26b9e94c6eccabaf6ab7 (diff)
downloadhands-on-scala-js-6987ac5195b0112b4bda123f0fced3ace7115932.tar.gz
hands-on-scala-js-6987ac5195b0112b4bda123f0fced3ace7115932.tar.bz2
hands-on-scala-js-6987ac5195b0112b4bda123f0fced3ace7115932.zip
stuff works, paragraph-starting-tags still accidentally capturing entire paragraph
-rw-r--r--api/src/main/scala/twist/stages/Compiler.scala3
-rw-r--r--book/index.tw3
-rw-r--r--book/intro.tw178
-rwxr-xr-xbook/src/main/resources/css/layouts/side-menu.css5
-rwxr-xr-xbook/src/main/resources/js/ui.js12
-rw-r--r--book/src/main/scala/book/Book.scala111
-rw-r--r--book/src/main/scala/book/Main.scala8
-rw-r--r--book/src/main/scala/book/Utils.scala7
-rw-r--r--build.sbt7
-rw-r--r--examples/src/main/scala/Example.scala32
10 files changed, 269 insertions, 97 deletions
diff --git a/api/src/main/scala/twist/stages/Compiler.scala b/api/src/main/scala/twist/stages/Compiler.scala
index fdfc68e..e00c373 100644
--- a/api/src/main/scala/twist/stages/Compiler.scala
+++ b/api/src/main/scala/twist/stages/Compiler.scala
@@ -38,6 +38,7 @@ object Compiler{
val skeleton: Tree = c.parse(first + s"{$fresh}").asInstanceOf[Apply]
// println("FIRST " + first)
skeleton.foreach{x =>
+ x
if (x.pos != NoPosition) x.pos = posFor(x.pos.point + fragPos.point + 1)
}
val b = content.map(compileTree(_))
@@ -101,7 +102,7 @@ object Compiler{
}
res.pos = newPos
- println(Position.formatMessage(newPos.asInstanceOf[scala.reflect.internal.util.Position], "", true))
+// println(Position.formatMessage(newPos.asInstanceOf[scala.reflect.internal.util.Position], "", true))
res
}
diff --git a/book/index.tw b/book/index.tw
index b55eb9b..22e0805 100644
--- a/book/index.tw
+++ b/book/index.tw
@@ -6,7 +6,7 @@
@meta(name:="viewport", content:="width=device-width, initial-scale=1.0")
@tags2.title("Hands-on Scala.js")
@Utils.includes
- @script("hljs.initHighlightingOnLoad();")
+ @script()
@div(id:="layout")
@a(href:="#menu", id:="menuLink", cls:="menu-link")
@@ -24,6 +24,7 @@
@div(cls:="content")
@Book.intro
+ @Book.gettingStarted
diff --git a/book/intro.tw b/book/intro.tw
index a3b5b09..d48a319 100644
--- a/book/intro.tw
+++ b/book/intro.tw
@@ -1,97 +1,125 @@
@sect{Intro to Scala.js}
- @highlight.scala
- val graphs = Seq[(String, Double => Double)](
- ("red", sin),
- ("green", x => 2 - abs(x % 8 - 4)),
- ("blue", x => 3 * pow(sin(x / 12), 2) * sin(x))
- ).zipWithIndex
- dom.setInterval(() => {
- x = (x + 1) % w
- if (x == 0) Page.renderer.clearRect(0, 0, w, h)
- else for (((color, func), i) <- graphs) {
- val y = func(x/w * 75) * h/40 + h/3 * (i+0.5)
- Page.renderer.fillStyle = color
- Page.renderer.fillRect(x, y, 3, 3)
- }
- }, 10)
- @canvas(width:=100, height:=100, id:="example-canvas")
- @script(src:="example-fastopt.js")
- @script("Example().main('example-canvas')")
-
+ @div(cls:="pure-g")
+ @div(cls:="pure-u-1 pure-u-md-13-24")
+ @hl.ref("examples/src/main/scala/Example.scala", "/*example*/", false)
+
+ @div(cls:="pure-u-1 pure-u-md-11-24")
+ @canvas(id:="example-canvas", display:="block")
+ @script(src:="example-fastopt.js")
+ @script("Example().main('example-canvas')")
+
+ @p
+ @a("Scala.js", href:="http://www.scala-js.org/") is a compiler that compiles Scala source code to equivalent Javascript code. That lets you write Scala code that you can run in a web browser, or other environments (Chrome plugins, Node.js, etc.) where Javascript is supported.
+
+ @p
+ Traditionally, Scala has been a language which runs on the JVM. This eliminates it from consideration in many cases, e.g. when you need to build interactive web apps, you need to fall back to Javascript to run your client-side code, at a great loss in terms of toolability and maintainability. Scala.js lets you to develop web applications with the safety and toolability that comes with a statically typed language:
+
+ @ul
+ @li
+ Typo-safety due to its compiler which catches many silly errors before the code is run
+ @li
+ In-editor support for autocomplete, error-highlighting, refactors, and intelligent navigation
+ @li
+ Very small compiled executables, in the 100-400kb range
+ @li
+ Source-maps for ease of debugging
+
+ @p
+ The value proposition is that due to the superior language and tooling, writing a web application in Scala.js will result in a codebase that is more flexible and robust than an equivalent application written in Javascript.
+
+ @sect{Who this book is for}
@p
- @a("Scala.js", href:="http://www.scala-js.org/") is a compiler that compiles Scala source code to equivalent Javascript code. That lets you write Scala code that you can run in a web browser, or other environments (Chrome plugins, Node.js, etc.) where Javascript is supported.
+ This book is targeted at people who have some experience in both Scala and Javascript, as well as web development in general. You do not need to be an expert, but I will skim over basic concepts in to cut to the Scala.js specific points, though I will leave links whenever I introduce a new concept so you can read up if necssary.
@p
- This lets you to develop web applications with the safety and toolability that comes with a statically typed language:
-
- @ul
- @li Typo-safety due to its compiler which catches many silly errors before the code is run
- @li In-editor support for autocomplete, error-highlighting, refactors, and intelligent navigation
- @li Very small compiled executables, in the 100-400kb range
- @li Source-maps for ease of debugging
+ Furthermore, this book aims to only give an overview of the main steps you need to perform (and ideas you need to understand) to get started using Scala.js. It isn't a comprehensive guide, so if you want to know something this book doesn't cover, feel free to ask on the @a("mailing list", href:="https://groups.google.com/forum/#!forum/scala-js").
+ @sect{Why Scala.js}
@p
- The value proposition is that due to the superior language and tooling, writing a web application in Scala.js will result in a codebase that is more flexible and robust than an equivalent application written in Javascript.
-
- @sect{Who this book is for}
- @p
- This book is targeted at people who have some experience in both Scala and Javascript. You do not need to be an expert in both, but I will skim over basic concepts in both languages to cut to the Scala.js specific points.
- @p
- Furthermore, this book aims to only give an overview of the main steps you need to perform (and ideas you need to understand) to get started using Scala.js. It isn't a comprehensive guide, so if you want to know something this book doesn't cover, feel free to ask on the @a("mailing list", href:="https://groups.google.com/forum/#!forum/scala-js").
-
- @sect{Why Scala.js}
- @p
- Javascript is the language supported by web browsers, and is the only language available if you wish to write interactive web applications. As more and more activity moves online, the importance of web apps will only increase over time.
-
- @sect{Javascript-the-language}
- @p
- However, Javascript is not an easy language to work in. Apart from being untyped (which some people don't mind) Javascript is also extremely verbose, has a lot of surprising behavior, and has a culture that make even the simplest of patterns (e.g. instantiating an object) a debate between a dozen different and equally-bad options.
- @p
- To work in Javascript, you need the discipline to limit yourself to the sane subset of the language, avoiding all the pitfalls along the way:
-
- @img(src:="images/javascript-the-good-parts-the-definitive-guide.jpg")
+ Javascript is the language supported by web browsers, and is the only language available if you wish to write interactive web applications. As more and more activity moves online, the importance of web apps will only increase over time.
- @sect{Javascript-the-platform}
- @p
- However, even as Javascript-the-language sucks, Javascript-the-platform has some very nice properties that make it a good target for application developers:
+ @sect{Javascript-the-language}
+ @p
+ However, Javascript is not an easy language to work in. Apart from being untyped (which some people don't mind) Javascript is also extremely verbose, has a lot of surprising behavior, and has a culture that make even the simplest of patterns (e.g. instantiating an object) a debate between a dozen different and equally-bad options.
+ @p
+ To work in Javascript, you need the discipline to limit yourself to the sane subset of the language, avoiding all the pitfalls along the way:
- @ul
- @li Zero-install distribution: just go to a URL and have the application downloaded and ready to use.
- @li Hyperlinks: being able to link to a particular page or item within a web app is a feature other platforms lack, and makes it much easier to cross-reference between different systems
- @li Sandboxed security: before the advent of mobile apps, web apps were the most secure runtime available, offering none of the risk or worry that comes with installing desktop software
+ @img(src:="images/javascript-the-good-parts-the-definitive-guide.jpg")
- @p
- These features are all very nice to have, and together have made the web platform the success it is today.
+ @sect{Javascript-the-platform}
+ @p
+ However, even as Javascript-the-language sucks, Javascript-the-platform has some very nice properties that make it a good target for application developers:
- @hr
+ @ul
+ @li
+ Zero-install distribution: just go to a URL and have the application downloaded and ready to use.
+ @li
+ Hyperlinks: being able to link to a particular page or item within a web app is a feature other platforms lack, and makes it much easier to cross-reference between different systems
+ @li
+ Sandboxed security: before the advent of mobile apps, web apps were the most secure runtime available, offering none of the risk or worry that comes with installing desktop software
- @p
- This is where Scala.js comes in. As developers we want Javascript-the-platform, with its ease-of-distribution, hyperlinks and security characteristics. We do not want Javascript-the-language, with its propensity for bugs, verbosity, and fragility. With Scala.js, you can cross compile your Scala code to a Javascript executable that can run on all major web browsers, thus saving you from the endless stream of gotcha's like the one below:
+ @p
+ These features are all very nice to have, and together have made the web platform the success it is today.
- @highlight.javascript
- javascript> ["10", "10", "10", "10"].map(parseInt)
- [10, NaN, 2, 3] // WTF
+ @hr
- @highlight.scala
- scala> List("10", "10", "10", "10").map(parseInt)
- List(10, 10, 10, 10) // Yay!
-
- @p
- Scala.js allows you to take advantage of the Javascript platform while still enjoying all the benefits of a concise, safe, modern language. The benefits of Scala are well documented, and I will not make a case here for Scala vs. some other language. Suffice to say, I believe it's a considerable improvement over programming in Javascript, and with Scala.js we can bring this improvement in development speed and happiness from the backend systems (where Scala has traditionally been used) to the front-end web application.
-
-@sect{Getting Started}
@p
- The quickest way to get started with Scala.js is to clone a("workbench-example-app", href:="https://github.com/lihaoyi/workbench-example-app"), go into the repository root, and run @code{~fastOptJS}
-
- @highlight.bash
- git clone https://github.com/lihaoyi/workbench-example-app
- cd workbench-example-app
- sbt ~fastOptJS
+ This is where Scala.js comes in. As developers we want Javascript-the-platform, with its ease-of-distribution, hyperlinks and security characteristics. We do not want Javascript-the-language, with its propensity for bugs, verbosity, and fragility. With Scala.js, you can cross compile your Scala code to a Javascript executable that can run on all major web browsers, thus saving you from the endless stream of gotcha's like the one below:
+ @hl.javascript
+ javascript> ["10", "10", "10", "10"].map(parseInt)
+ [10, NaN, 2, 3] // WTF
+ @hl.scala
+ scala> List("10", "10", "10", "10").map(parseInt)
+ List(10, 10, 10, 10) // Yay!
+ @p
+ Scala.js allows you to take advantage of the Javascript platform while still enjoying all the benefits of a concise, safe, modern language. The benefits of Scala are well documented, and I will not make a case here for Scala vs. some other language. Suffice to say, I believe it's a considerable improvement over programming in Javascript, and with Scala.js we can bring this improvement in development speed and happiness from the backend systems (where Scala has traditionally been used) to the front-end web application.
+ @sect{The Agenda}
+ @p
+ This book will be roughly divided into three sections. These sections can be read in any order. Although the later chapters will make references to earlier chapters, there'll be hyperlinks so you can quickly go back and catch up on what you missed skipping over ,
+
+ @sect{Hands On}
+ @p
+ A whirlwind tour of the various things that Scala.js can be used for. We will cover:
+
+ @ul
+ @li
+ Your first Scala.js application: setting up your development environment, cloning the example repository, debugging and finally publishing your first toy application
+ @li
+ An interactive web app using Scala.js: how you interact with the HTML DOM, how you utilize Ajax calls and other browser APIs that are common in Javascript-heavy applications
+ @li
+ A Scala.js library: how to write a module that can be depended on by applications both your own and by others, and be used both with Scala.js and Scala-on-the-JVM
+ @li
+ Client-Server integration: We will build a simple web application with a Scala server and Scala.js client. In the process, we'll explore how to share code between client and server, how to get compiler-checked/boilerplate-free Ajax calls between client and server, and many other long-standing holy-grails of web development
+
+ @p
+ After going through this chapter and following along with the exercises, you should have a good sense of how Scala.js works and how it feels building things in Scala.js. You would not be an expert, but you'll know where to get started if you decide to try out Scala.js for your next project.
+
+ @sect{Scala.js in Depth}
+ @p
+ This section of the book will cover lots of content that does not fit in the earlier Hands-On portion of the book. Things that aren't immediately necessary to get something up and running, things that only advanced users would care about, things that you probably don't need to know but you'd like to know out of intellectual curiosity.
+
+ @p
+ In general, this section of the book will go much deeper into Scala.js, much more than is necessary to get your first applications built. We will talk about the small number of semantic differences between Scala.js and Scala, details of the foreign-function-interface with Javascript, the various optimization levels and what they do. Nothing pressing or urgently needed, but all very interesting, and worth reading if you want to really understand Scala.js in depth.
+
+ @sect{Why}
+ @p
+ Why should you care about Scala.js in the first place? Why not just write Javascript? As a new, barely-a-year-old project, what does it provide that other more mature compile-to-javascript langauges don't?
+
+ @p
+ In this section of the book, we will examine the reasons which got me first interested in Scala.js. We'll talk at length about the deficiencies of Javascript, the ubiquity of the browser as an application platform, and the technical characteristics that make this the case.
+
+ @p
+ Lastly, we will explore the solution space. Scala.js isn't the only game in town, and there are hundreds of over attempts at covering the same ground the Scala.js now attempts to cover. We'll compare and contrast the different approaches to see what Scala.js can bring to the table that other approaches cannot.
+
+ @hr
+
+ @p
+ As mentioned earlier, these chapters can be read in any order. In keeping with the spirit of the book, we'll jump right into the Hands On to give you the experience, and save the talking and philosophizing for later. Let's go!
diff --git a/book/src/main/resources/css/layouts/side-menu.css b/book/src/main/resources/css/layouts/side-menu.css
index e04fe81..aba4441 100755
--- a/book/src/main/resources/css/layouts/side-menu.css
+++ b/book/src/main/resources/css/layouts/side-menu.css
@@ -236,3 +236,8 @@ Hides the menu at `48em`, but modify this based on your app's needs.
left: 250px;
}
}
+
+/*Workaround for bug in highlight.js IDEA theme*/
+.hljs-tag{
+ background: none;
+} \ No newline at end of file
diff --git a/book/src/main/resources/js/ui.js b/book/src/main/resources/js/ui.js
index acc38a0..eed641b 100755
--- a/book/src/main/resources/js/ui.js
+++ b/book/src/main/resources/js/ui.js
@@ -1,4 +1,5 @@
-(function (window, document) {
+document.addEventListener("DOMContentLoaded", function(){
+ console.log("HIGHLIGHTING")
var layout = document.getElementById('layout'),
menu = document.getElementById('menu'),
@@ -32,4 +33,11 @@
toggleClass(menuLink, active);
};
-}(this, this.document));
+
+ var snippets = document.getElementsByClassName("highlight-me");
+ for(var i = 0; i < snippets.length; i++){
+ console.log("highlighting", snippets[i])
+ hljs.highlightBlock(snippets[i])
+ }
+
+});
diff --git a/book/src/main/scala/book/Book.scala b/book/src/main/scala/book/Book.scala
index e509716..d301824 100644
--- a/book/src/main/scala/book/Book.scala
+++ b/book/src/main/scala/book/Book.scala
@@ -14,6 +14,7 @@ object Book {
import Utils.sect
val intro = twf("book/intro.tw")
+ val gettingStarted = twf("book/getting-started.tw")
val contentBar = {
def rec(current: Node, depth: Int): Frag = {
div(
@@ -27,17 +28,113 @@ object Book {
// @li(cls:="menu-item-divided pure-menu-selected")
ul(rec(Utils.structure, 0))
}
- println(contentBar)
+
val txt = twf("book/index.tw").render
- object highlight{
- def highlight(snippet: Seq[String], lang: String) = {
- pre(code(cls:=lang, snippet.mkString))
+ object hli{
+ def javascript(code: String*) = hl.highlight(code, "javascript", inline=true)
+ def scala(code: String*) = hl.highlight(code, "scala", inline=true)
+ def bash(code: String*) = hl.highlight(code, "bash", inline=true)
+ def diff(code: String*) = hl.highlight(code, "diff", inline=true)
+ def html(code: String*) = hl.highlight(code, "xml", inline=true)
+ }
+ object hl{
+ def highlight(snippet: Seq[String], lang: String, inline: Boolean) = {
+ val string = snippet.mkString
+ val lines = string.split("\n", -1)
+ if (inline){
+ code(cls:=lang + " highlight-me", lines(0), padding:=0, display:="inline")
+ }else{
+ println("LINES " + lines.toList)
+ println(snippet)
+ val minIndent = lines.map(_.takeWhile(_ == ' ').length)
+ .filter(_ > 0)
+ .min
+ val stripped = lines.map(_.drop(minIndent))
+ .dropWhile(_ == "")
+ .mkString("\n")
+
+ pre(code(cls:=lang + " highlight-me", stripped))
+ }
}
- def javascript(code: String*) = highlight(code, "javascript")
- def scala(code: String*) = highlight(code, "scala")
- def bash(code: String*) = highlight(code, "bash")
+ def javascript(code: String*) = highlight(code, "javascript", inline=false)
+ def scala(code: String*) = highlight(code, "scala", inline=false)
+ def bash(code: String*) = highlight(code, "bash", inline=false)
+ def diff(code: String*) = highlight(code, "diff", inline=false)
+ def html(code: String*) = highlight(code, "xml", inline=false)
+
+ /**
+ * Kinds of refs:
+ *
+ * Rule: Starting from a line, keep consuming until
+ * the identation drops below the start
+ *
+ * def main = {
+ * /*example*/
+ * i am a cow
+ * hear me moo
+ * }
+ *
+ * Rule: Starting from a line, keep consuming until
+ * the indentation becomes equivalent to the current. If
+ * it's a cosing brace, keep it.
+ * val x = omg
+ * val y = zzz
+ *
+ * class C{
+ *
+ * }
+ */
+
+ def ref(filepath: String, identifier: String = "", indented: Boolean = true) = {
+
+ val lang = filepath.split('.').last match{
+ case "js" => "javascript"
+ case "scala" => "scala"
+ case "sbt" => "scala"
+ case "sh" => "bash"
+ case "html" => "xml"
+ case x =>
+ println("??? " + x)
+ ???
+ }
+ val lines = io.Source.fromFile(filepath).getLines().toVector
+ val blob = if (identifier == ""){
+ lines.mkString("\n")
+ }else {
+ val firstLine = lines.indexWhere(_.contains(identifier))
+ val whitespace = lines(firstLine).indexWhere(!_.isWhitespace)
+ val things =
+ lines.drop(firstLine + 1)
+ .takeWhile{ x =>
+ val firstCharIndex = x.indexWhere(!_.isWhitespace)
+ firstCharIndex == -1 || firstCharIndex >= whitespace + (if (indented) 1 else 0)
+ }
+
+ things.foreach(println)
+ val stuff =
+ if (!indented) {
+ println("NOT INDENTED " + things)
+ things
+ }
+ else {
+ val last = lines(firstLine + things.length + 1)
+// println("LAST: " + last)
+ if (last.trim.toSet subsetOf "}])".toSet) {
+ lines(firstLine) +: things :+ last
+ } else {
+ lines(firstLine) +: things
+ }
+ }
+ stuff.map(_.drop(whitespace)).mkString("\n")
+ }
+ println(blob)
+
+ pre(code(cls:=lang + " highlight-me", blob))
+ }
}
+
+
}
diff --git a/book/src/main/scala/book/Main.scala b/book/src/main/scala/book/Main.scala
index 9b06d29..89fb5e1 100644
--- a/book/src/main/scala/book/Main.scala
+++ b/book/src/main/scala/book/Main.scala
@@ -4,6 +4,8 @@ import java.io.InputStream
import java.nio.charset.StandardCharsets
import java.nio.file.{Paths, Files}
+import org.eclipse.jgit.api.Git
+
import scala.collection.mutable
import scalatags.Text.all._
import scalatags.Text.tags2
@@ -23,6 +25,12 @@ object Main {
def main(args: Array[String]): Unit = {
println("Writing Book")
+// Files.deleteIfExists(Paths.get("output/temp"))
+// Git.cloneRepository()
+// .setURI("https://github.com/lihaoyi/workbench-example-app")
+// .setDirectory(new java.io.File("output/temp"))
+// .call()
+
write(Book.txt, "output/index.html")
diff --git a/book/src/main/scala/book/Utils.scala b/book/src/main/scala/book/Utils.scala
index 0b435a3..a7b36d1 100644
--- a/book/src/main/scala/book/Utils.scala
+++ b/book/src/main/scala/book/Utils.scala
@@ -12,13 +12,20 @@ object Utils{
"META-INF/resources/webjars/highlightjs/8.2-1/languages/scala.min.js",
"META-INF/resources/webjars/highlightjs/8.2-1/languages/javascript.min.js",
"META-INF/resources/webjars/highlightjs/8.2-1/languages/bash.min.js",
+ "META-INF/resources/webjars/highlightjs/8.2-1/languages/diff.min.js",
+ "META-INF/resources/webjars/highlightjs/8.2-1/languages/xml.min.js",
"css/pure-min.css",
+ "css/grids-responsive-min.css",
"css/layouts/side-menu.css",
"js/ui.js"
)
val manualResources = Seq(
"images/javascript-the-good-parts-the-definitive-guide.jpg",
+ "images/Hello World.png",
+ "images/Hello World White.png",
+ "images/Hello World Console.png",
+ "images/IntelliJ Hello.png",
"example-fastopt.js"
)
diff --git a/build.sbt b/build.sbt
index 1f7e228..a3c76ba 100644
--- a/build.sbt
+++ b/build.sbt
@@ -22,7 +22,12 @@ lazy val book = Project(
base = file("book"),
dependencies = Seq(api)
).settings(
- libraryDependencies += "org.webjars" % "highlightjs" % "8.2-1",
+ libraryDependencies ++= Seq(
+ "org.webjars" % "highlightjs" % "8.2-1",
+ "org.scala-lang" % "scala-reflect" % scalaVersion.value,
+ "org.scala-lang" % "scala-compiler" % scalaVersion.value,
+ "org.eclipse.jgit" % "org.eclipse.jgit" % "3.5.1.201410131835-r"
+ ),
(resources in Compile) += {
(fastOptJS in (examples, Compile)).value
(artifactPath in (examples, Compile, fastOptJS)).value
diff --git a/examples/src/main/scala/Example.scala b/examples/src/main/scala/Example.scala
index 5d315b2..b5e77ca 100644
--- a/examples/src/main/scala/Example.scala
+++ b/examples/src/main/scala/Example.scala
@@ -8,26 +8,38 @@ object Example extends scalajs.js.JSApp{
.getElementById("example-canvas")
.asInstanceOf[dom.HTMLCanvasElement]
+ def clear() = {
+ canvas.width = canvas.parentElement.clientWidth
+ canvas.height = canvas.parentElement.clientHeight
+ }
+ clear()
+
val renderer =
canvas.getContext("2d")
.asInstanceOf[dom.CanvasRenderingContext2D]
- val (h, w) = (canvas.height, canvas.width)
+ def h = canvas.height
+ def w = canvas.width
+
+ /*example*/
var x = 0.0
- val graphs = Seq[(String, Double => Double)](
+ type Graph = (String, Double => Double)
+ val graphs = Seq[Graph](
("red", sin),
- ("green", x => 2 - abs(x % 8 - 4)),
- ("blue", x => 3 * pow(sin(x / 12), 2) * sin(x))
+ ("green", x => 1 - abs(x % 4 - 2)),
+ ("blue", x => pow(sin(x/12), 2) * sin(x))
).zipWithIndex
- dom.setInterval(() => {
+ def run() = {
x = (x + 1) % w
- if (x == 0) renderer.clearRect(0, 0, w, h)
- else for (((color, func), i) <- graphs) {
- val y = func(x/w * 75) * h/40 + h/3 * (i+0.5)
+ if (x == 0) clear()
+ else for (((color, f), i) <- graphs) {
+ val offset = h / 3 * (i + 0.5)
+ val y = f(x / w * 75) * h / 40
renderer.fillStyle = color
- renderer.fillRect(x, y, 3, 3)
+ renderer.fillRect(x, y + offset, 3, 3)
}
- }, 10)
+ }
+ dom.setInterval(run _, 20)
}
} \ No newline at end of file