Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ val testsChrome = Build.testsChrome
val testsFirefox = Build.testsFirefox
val testsNodeJsdom = Build.testsNodeJsdom
val example = Build.example
val readme = Build.readme
val docs = Build.docs
183 changes: 183 additions & 0 deletions docs/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
## scala-js-dom

---

#### Statically typed DOM API for Scala.js

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:

```scala
import org.scalajs.dom

def main() = dom.window.alert("Hi from scala-js-dom!")
```

## Usage

Add the following to your sbt build definition:

```scala
libraryDependencies += "org.scala-js" %%% "scalajs-dom" % "@VERSION@"
```

then enjoy the types available in org.scalajs.dom. scalajs-dom @VERSION@ 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.

## Examples

You can start using the bindings using the following import:

```scala mdoc:js:shared
import org.scalajs.dom._
```

### Appending a child to a `Node`

```scala mdoc:js:shared
def appendElement(div: html.Div): Unit = {
val child = document.createElement("div")
child.textContent = "I can add elements to DOM elements!"
div.appendChild(child)
}
```

```scala mdoc:js:invisible
<div id="outer-container"></div>
<button id="demo1" class="button-run">Run</button>
---
document.getElementById("demo1").addEventListener("click", (ev: Event) => {
appendElement(document.getElementById("outer-container").asInstanceOf[html.Div])
})
```

### Add an EventListener for `onmousemove`

```scala mdoc:js
def showOnMouseCoordinates(pre: html.Pre): Unit = {
pre.onmousemove = (ev: MouseEvent) =>
pre.textContent = s"""
|ev.clientX: ${ev.clientX}
|ev.clientY: ${ev.clientY}
|ev.pageX: ${ev.pageX}
|ev.screenX: ${ev.screenX}
|ev.screenY: ${ev.screenY}
""".stripMargin
}
```

### Storing an item in `localStorage`

```scala mdoc:js
def storeInputInLocalStorage(input: html.Input, box: html.Div) = {
val key = "myKey"
input.value = window.localStorage.getItem(key)

input.onkeyup = { (e: Event) =>
window.localStorage.setItem(
key, input.value
)

box.textContent = s"Saved: ${input.value} to local storage!"
}
}
```

### Using `Canvas` to draw

```scala mdoc:js
type Context2D = CanvasRenderingContext2D

def drawCuteSmiley(canvas: html.Canvas) = {
val context = canvas.getContext("2d").asInstanceOf[Context2D]

val size = 300
canvas.width = size
canvas.height = size

context.strokeStyle = "red"
context.lineWidth = 3
context.beginPath()
context.moveTo(size/3, 0)
context.lineTo(size/3, size/3)
context.moveTo(size*2/3, 0)
context.lineTo(size*2/3, size/3)
context.moveTo(size, size/2)
context.arc(size/2, size/2, size/2, 0, 3.14)

context.stroke()
}
```

### Using `Fetch` to make API calls in the browser

```scala mdoc:js
import scala.concurrent.ExecutionContext.Implicits.global

def fetchBoredApi(element: html.Pre) = {
val url =
"https://www.boredapi.com/api/activity"

val responseText = for {
response <- fetch(url).toFuture
text <- response.text().toFuture
} yield {
text
}

for (text <- responseText)
element.textContent = text
}
```

### Using Websockets

```scala mdoc:js
// TODO: currently crashes with an error
// def echoWebSocket(input: html.Input, pre: html.Pre) = {
// val echo = "wss://echo.websocket.org"
// val socket = new WebSocket(echo)

// socket.onmessage = {
// (e: MessageEvent) =>
// pre.textContent +=
// e.data.toString
// }

// socket.onopen = { (e: Event) =>
// input.onkeyup = { (e: Event) =>
// socket.send(input.value)
// }
// }
// }
```

### Styling an HTML element

```scala mdoc:js
def changeColor(div: html.Div) = {
val colors = Seq("red", "green", "blue")

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

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

## Contributing

The DOM API is always evolving, and `scala-js-dom` tries to provide a thin-but-idiomatic Scala interface to modern browser APIs, without breaking the spec.

If you see something that you think can be improved, feel free to send a pull request. See our [Contributing Guide](https://github.com/scala-js/scala-js-dom/blob/main/CONTRIBUTING.md) for a detailed overview for starting hacking on `scala-js-dom` and making a PR!
3 changes: 2 additions & 1 deletion prePR.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ ThisBuild / prePR_nonCross := Def.sequential(

Def.taskDyn {
if (scalaVersion.value.startsWith("2.12."))
Def.task[Unit]((readme / Compile / compile).value)
// TODO should this really be docs / Compile?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually don't know if the current docs / Compile / compile is the right command to run during prePR.
@armanbilge does:

      Def.task[Unit]((docs / Compile / compile).value)

work fine here?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I need to take another look at this. I was hoping we could decide how we are deploying the site so we can figure out what to do with the build :)

Def.task[Unit]((docs / Compile / compile).value)
else
Def.task(())
},
Expand Down
30 changes: 17 additions & 13 deletions project/Build.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ import scalafix.sbt.ScalafixPlugin.autoImport._
import scalatex.ScalatexReadme
import Dependencies._
import Lib._
import mdoc.MdocPlugin
import sbtdynver.DynVerPlugin.autoImport.previousStableVersion
import mdoc.MdocPlugin.autoImport._

object Build {

Expand All @@ -37,7 +40,6 @@ object Build {
testsFirefox,
testsNodeJsdom,
example,
// readme, // This is a Scala 2.12 only module
)

lazy val dom = project
Expand Down Expand Up @@ -141,18 +143,20 @@ object Build {
.enablePlugins(ScalaJSPlugin)
.configure(commonSettings, crossScala, preventPublication)

lazy val readme =
ScalatexReadme(
projectId = "readme",
wd = file(""),
url = "https://github.com/scala-js/scala-js-dom/tree/main",
source = "Index",
autoResources = Seq("example-opt.js"),
)
.configure(commonSettings, preventPublication)
lazy val jsdocs = project
.in(file("mdocs-js"))
.dependsOn(dom)
.enablePlugins(ScalaJSPlugin)
.configure(commonSettings, crossScala, preventPublication)

lazy val docs = project
.in(file("mdocs"))
.settings(
scalaVersion := Ver.scala212,
Compile / resources += (example / Compile / fullOptJS).value.data,
mdocJS := Some(jsdocs),
mdocVariables := Map(
"VERSION" -> previousStableVersion.value.getOrElse("2.3.0")
)
)

.enablePlugins(MdocPlugin)
.configure(commonSettings, crossScala, preventPublication)
}
11 changes: 6 additions & 5 deletions project/plugins.sbt
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
libraryDependencies += "org.scala-js" %% "scalajs-env-jsdom-nodejs" % "1.1.0"
libraryDependencies += "org.scala-js" %% "scalajs-env-selenium" % "1.1.1"

addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "0.10.4")
addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.11.0")
addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "0.10.4")
addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.11.0")
addSbtPlugin("com.github.sbt" % "sbt-ci-release" % "1.5.11")
addSbtPlugin("com.lihaoyi" % "scalatex-sbt-plugin" % "0.3.11")
addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.7.1")
addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.0")
addSbtPlugin("com.lihaoyi" % "scalatex-sbt-plugin" % "0.3.11")
addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.7.1")
addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.0")
addSbtPlugin("org.scalameta" % "sbt-mdoc" % "2.3.6")
Loading