Blog

【Scala.jsではじめるScala道】第二回・DOMとscalatagsであけおめ


あけましておめでとうございます。編集部新卒の小林です。2015年もアドテクスタジオと、この Scala blog をよろしくお願いします。

本連載では Scala.js を使ってブラウザで動作するアプリケーションを作っていくことで Scala を学んでいっています。前回に引き続いて今回は Scala.js の DOM ライブラリを見ていきます。

第一回はこちら

DOM ライブラリを使っての HelloWorld

まずは、DOM のライブラリを読み込めるように build.sbtlibraryDependencies += "org.scala-lang.modules.scalajs" %%% "scalajs-dom" % "0.6" を追記します。

build.sbt:

%%% ってなんだろうなとおもっていると、注釈がありました。

Note the %%% (instead of the usual %%) which will add the current Scala.js version to the artifact name.

より厳密な %% ということっぽいですね。JavaScript の ===== に似てますね。(似てない?)

これで DOM のライブラリが使えるようになったと信じて Scala のコードを書き換えていきます。

src/main/scala/tutorial/webapp/TutorialApp.scala:

チュートリルを写経しました。コードから察するに <p> をつくってそこにテキストを放り込むコードのようですね。さて前回めんどくさくて html を用意してなかったので確認する環境がないのでさくっと html を準備します。生の html を書くことが宗教上の理由で禁じられているので jade で書くのをお許しください。

src/web/index.jade:

これをビルドして、ブラウザで実行してみると…

やりました!! <p> タグが追加されていることが分かります。

scalatags を使って scala のコード中に html を書く

Scala.js のチュートリアルでは「 <p> タグ入ったやろ?すごいやろ?」ぐらいで終わってるので、もうちょっと DOM まわりを調べました。Scala.js には Scala-JS-Fiddle という Scala.js をブラウザ上でさくっと試せるサービスがあり、サンプルなどを確認することができます。これのランディングページのコードを確認すると

というような調子で Scala のコード中に HTML のコードのようなものが混ざっているのが見受けられます。ドキュメントを読むと scalatags というライブラリを使ってこれを実現しているようです。

https://github.com/lihaoyi/scalatags

ちなみに、JavaScript でも medikoo/domjs という似たライブラリがあります。CoffeeScript には mauricemach/coffeekup があります。詳しくは両ライブラリの README をお読みください。

さて、ローカルでも scalatags を使って DOM を生成してみたいとおもいます。scalatags の README に従って build.sbtlibraryDependencies += "com.scalatags" %%% "scalatags" % "0.4.2" を追加します。ちなみに、何も考えずに

として reload すると

とエラーが出るので

と空行をいれてやらないといけないようです。これで reload が通るので実際にコードを書いていきます。

src/main/scala/tutorial/webapp/TutorialApp.scala:

すごい微妙なのは承知ですが、DOM と html を渡すと DOM の innerHTML に html を設定する updateInnerHTML という関数を定義しました。 innerHTML は DOM じゃなくて Element のプロパティなので targetNode の型を変えてやる必要がありました。

次に、 header という関数で scalatags を使って html を出力します。JS 脳で何も考えずに

などと書いていたら型がないよと言われ、 String を付けたら div の返り値が HTMLDivElement やでとエラーが出たので toString を付けました。あと、JS 脳なので関数を実行するときには () を付けていたんですが Scala では省略できることに気付いて勉強になりました。Ruby っぽいですね。

さて、先ほど gulp で fastOpt の JavaScript ファイルをウォッチするようにしておいたので自動的にウェブの方のビルドディレクトリに生成された JavaScript のコードがコピーされています。ちらっとファイルを見てみると、行数にして2万2千行、サイズでいうと1MBの JavaScript のファイルが生成されていました。強い。

さてこれをブラウザで実行してみると…!

ヤッター!

Scala.js でインタラクティブな画面をつくる

ここまでやってきた集大成としてなにか簡単なインタラクションのある画面をつくってみたいとおもいます。

完成図

2015-01-05 18_17_19

新年のめでたい気持ちを表すページを作ってみたいとおもいます。めでたいので紅白幕がチカチカします。

ソースコード

src/main/scala/tutorial/webapp/TutorialApp.scala:

Scala 初心者が調べながら一生懸命書いたコードです、今年もよろしくお願いします。

コードの説明

HTML からは以前までのサンプル同様に tutorial.webapp.TutorialApp().main() をキックするだけで特になにも書いていません。一方、 main() では、 layoutbody に挿入しているだけです。さて、 layout でなにをやっているかというと

名前が示す通り、全体の大枠を作って返すということをやっています。 appendChilddom.Node を引数にとるので最後に render して大枠の dom.Node を返しています。

続いて、先に greetingNode を見ていきます。

ここでは、名前を入力したら「あけましておめでとうございます!!○○」というヘッダーを返す処理を担っています。それぞれ greeting, name, nameLabel で当該の要素を定義して、最後の div 関数で3つを組み合わせた要素を生成して返します。ここで

でキー入力が完了したイベントを受け取ってヘッダーテキストを更新する処理をしています。 => は無名関数のようなものなんでしょうか。ここで注意しなければならないのが onkeyuptextContent, value で、これらはそれぞれ dom.HTMLElementdom.HTMLInputElement の関数なので先に render しないとコンパイルが通らないところです。

最後に redWhiteNode を見ていきます。

redWhiteNode では、まず適当な数の要素を用意し、それを一定間隔で背景色を変えることで紅白幕っぽいものを実現しています。Scala では for 文がちゃんと値を返してくれるので

という感じで要素群が生成できます。これで生成した要素に対して

のブロックで200ミリ秒毎にそれぞれの紅白を反転させています。 dom は JavaScript でいう windowextend しているので dom.setInterval と書くことで JavaScript の setInterval を呼び出すことができます。ここでも getAttributesetAttribute するために予め render しています。

まとめ

今回は Scala.js での DOM の扱いについて見てきました。Scala.js の DOM のライブラリを使って動的に DOM を生成することも可能ですが、scalatags を使うとより容易に DOM を扱えることが分かりました。ところで、こうしてコード中に html の断片を書いていると、どこか見覚えのあるような気がしてきます。

そうです、React の jsx です(こじつけ)。というわけで、次回は Scala.js と React を組み合わせて使っていくパターンを見ていきたいとおもいます。

Author

アバター
admin