+
+
+ 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:
+
+
+ -
+
dom.html
: HTML element APIs
+ -
+
dom.svg
: SVG element APIs
+ -
+
dom.idb
: IndexedDB APIs
+ -
+
dom.css
: CSS APIs
+ -
+
dom
: Miscellanious, unclassified APIs
+
+
+ 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(w*2/3, 0)
+ ctx.lineTo(w*2/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:
+
+ -
+ Deprecated properties/methods/types will not be present.
+ -
+ IE-only, Chrome-only, FF-only, and in general browser-specific attributes will typically not be present.
+ -
+ The name of a Scala type should map directly to the name of the corresponding Javascript type.
+ -
+ Any type which is a Javascript type (e.g. you can
instanceof
in javascript) should be a Scala class
; any other interface which isn't a Javascript type should be a trait
.
+ -
+ Read-only members should be
def
, and not-directly-instantiable classes should have private
constructors.
+
+
+
+ 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:
+
+ -
+ Improved doc-comments; who doesn't love better docs?
+ -
+ Missing methods/properties/classes; send the PR adding it in including it together with a link to an authoritative source (e.g. MDN) and it should get merged.