scala-js-dom (original) (raw)

Scala-js-dom provides a nice statically typed interface to the DOM such that it can be called from Scala code without resorting to js.Dynamic. All javascript globals functions, singletons and classes are members of the org.scalajs.dom, org.scalajs.dom.html, org.scalajs.dom.svg, etc. packages. For example:

def main() = { import org.scalajs.dom dom.window.alert("Hi from Scala-js-dom") }

Will cause a javascript alert box saying `Hi from Scala-js-dom` to appear. Other javascript classes and objects can be similarly accessed e.g. new dom.XMLHttpRequest() to perform a new Ajax request, dom.document to access the global document object, or html.Div to to refer to the type of a <div> element.

Add the following to your sbt build definition:

libraryDependencies += "org.scala-js" %%% "scalajs-dom" % "2.2.0"

then enjoy the types available in org.scalajs.dom. scalajs-dom 2.2.0 is built and published for Scala.js 1.5+ with Scala 2.11, 2.12, 2.13, and 3.0+.

To begin with, scala-js-dom organizes the full-list of DOM APIs into a number of buckets:

Most names have been shortened from names of the raw browser APIs, since the namespacing avoids collisions. By convention these types are imported qualified: e.g. as html.Canvas instead of directly as Canvas. There is also the dom.raw namespace which contains everything with their full, un-shortened name.

Here are some examples to get you started:

def main(div: html.Div) = { val child = dom.document.createElement("div") child.textContent = "Hi from Scala-js-dom" div.appendChild(child) }

def main(pre: html.Pre) = { pre.onmousemove = { (e: dom.MouseEvent) => pre.textContent = s"""e.clientX ${e.clientX} |e.clientY ${e.clientY} |e.pageX ${e.pageX} |e.pageY ${e.pageY} |e.screenX ${e.screenX} |e.screenY ${e.screenY} """.stripMargin } }

def main(in: html.Input, out: html.Div) = { in.onkeyup = { (e: dom.Event) => out.textContent = dom.window.btoa(in.value) } }

`def main(in: html.Input, box: html.Div) = { val key = "my-key"

in.value = dom.window.localStorage.getItem(key)

in.onkeyup = { (e: dom.Event) => dom.window.localStorage.setItem( key, in.value ) box.textContent = "Saved! " + in.value } }`

`def main(c: html.Canvas) = { type Ctx2D = dom.CanvasRenderingContext2D val ctx = c.getContext("2d") .asInstanceOf[Ctx2D] val w = 300 c.width = w c.height = w

ctx.strokeStyle = "red" ctx.lineWidth = 3 ctx.beginPath() ctx.moveTo(w/3, 0) ctx.lineTo(w/3, w/3) ctx.moveTo(w2/3, 0) ctx.lineTo(w2/3, w/3) ctx.moveTo(w, w/2) ctx.arc(w/2, w/2, w/2, 0, 3.14)

ctx.stroke() }`

def main(pre: html.Pre) = { import scala.concurrent .ExecutionContext .Implicits .global import js.Thenable.Implicits._ val url = "https://www.boredapi.com/api/activity" val responseText = for { response <- dom.fetch(url) text <- response.text() } yield { text } for (text <- responseText) pre.textContent = text }

def main(in: html.Input, pre: html.Pre) = { val echo = "wss://echo.websocket.org" val socket = new dom.WebSocket(echo) socket.onmessage = { (e: dom.MessageEvent) => pre.textContent += e.data.toString } socket.onopen = { (e: dom.Event) => in.onkeyup = { (e: dom.Event) => socket.send(in.value) } } }

`def main(div: html.Div) = { val colors = Seq( "red", "green", "blue" )

val index = util.Random.nextInt(colors.length)

div.style.color = colors(index) }`

The goal of this project is to provide a thin-but-idiomatic-scala interface to modern browser APIs. In particular:

The DOM API is always evolving, and scala-js-dom is a hodgepodge of auto-generated/scraped/hand-tweaked code full of rough edges. If you see something that you think can be improved, feel free to send a pull request. These could include: