0

Simple setup :

  lazy val root = project.in(file("."))
  .settings(scalaJSSettings: _*)
  .settings(utestJsSettings: _*)
  .settings(persistLauncher := true)
  .settings(persistLauncher in Test := false)
  .settings(
  name := "bindings",
  version := "0.0.1-SNAPSHOT",
  scalaVersion := "2.11.2",
  libraryDependencies ++= Seq(
    "org.scala-lang.modules.scalajs" %%% "scalajs-dom" % "0.6",
    "com.lihaoyi" %%% "utest" % "0.2.3" % "test"
  ),
  jsDependencies += "org.webjars" % "d3js" % "3.4.11" / "d3.js", //d3.min.js
  autoCompilerPlugins := true,
  test in Test := (test in(Test, fastOptStage)).value,
  requiresDOM := true,
  traceLevel := 0
)

phantomjs-launcher-webpage.html contains really super valid stuff :

<script type="text/javascript" src="/path/scalajs-bindings/target/scala-2.11/classes/d3.js"></script>
<script type="text/javascript" src="/path/scalajs-bindings/target/scala-2.11/bindings-fastopt.js"></script>
<script type="text/javascript">
// Phantom.js code launcher
// Origin: /path/scalajs-bindings/target/scala-2.11/bindings-launcher.js
window.addEventListener('load', function() {
((typeof global === "object" && global &&
         global["Object"] === Object) ? global : this)["com"]["whatever"]["scalajs"]["Appp"]().main();
}, false);
</script>

Now, in browser it can call d3, I tried with equivalent html, but using PhantomJS or NodeJS if I do fastOptStage::run or fastOptStage::test I get

TypeError: undefined is not an object (evaluating 'd3["scale"]')

The code looks like this:

object Appp extends JSApp {
  override def main(): Unit = {
    val fill = d3.scale.category20()
    println(fill)
  }
}
lisak
  • 21,611
  • 40
  • 152
  • 243
  • I'm looking into this. Just quickly: Can you add the definition of `d3` in `Appp`, please? – gzm0 Sep 01 '14 at 12:49
  • Do you have a `d3.js` on your own on the classpath? jsDependency resolution is only performed on a by-filename basis. It seems that you're not getting the `d3.js` from the jar. Does it work if you uncomment the `d3.min.js`? – gzm0 Sep 01 '14 at 12:54
  • Added d3 object into Appp -> `TypeError: undefined is not an object (evaluating 'ScalaJS.g["Appp$d3"]["scale"]')` ... I have d3.js in `src/main/resources` ... it is physically present in `target/scala-2.11/classes/d3.js` ... I tried uncomment `d3.min.js` ... I tried it with `d3.min.js` too - it also doesn't work ... btw it works with jquery though, if I add jquery into jsDependencies, it just works – lisak Sep 01 '14 at 13:06
  • I got it, it cannot be an inner class in Appp, it works if it is in Appp.scala but at the same level as Appp object... It doesn't work as inner class AND it doesn't work in `package object` where I had it originally – lisak Sep 01 '14 at 13:11
  • These discoverings are quite painful, I'd expect it won't work as an inner class, but I really didn't expect it won't work in a `package object` ... Scala just can do so much that all the possibilities can't be covered, it just ain't possible :-) – lisak Sep 01 '14 at 13:16
  • The main problem was, that I forgot that I put it into a `package object` so it didn't occur to me to try if it isn't the reason. Thank you gzm0 for pointers – lisak Sep 01 '14 at 13:24

2 Answers2

2

You can have your object d3 extend js.GlobalScope and it will be looked for in the global JavaScript scope (i.e. where d3.js will put it):

object Appp extends JSApp {
  object d3 extends js.GlobalScope {
    def scale: js.Dynamic = ???
  }
  override def main(): Unit = {
    val fill = d3.scale.category20()
    println(fill)
  }
}

However, in the case of d3, you might want to consider having the d3 package object itself extend js.GlobalScope:

package mbostock

package object d3 extends js.GlobalScope {
  def scale: js.Dynamic = ???
}

I strongly recommend reading the JavaScript interoperability guide, notably the part about calling JavaScript from Scala.js.

gzm0
  • 14,752
  • 1
  • 36
  • 64
0

The reason it wasn't working was that I had d3 object in a package object :

package object mbostock {

 object d3 {...}

}

It also doesn't work as an inner class :

object Appp extends JSApp {
  object d3 {...}
  override def main(): Unit = {...}
}
lisak
  • 21,611
  • 40
  • 152
  • 243