Calling jquery-ui's resizable() function from scala.js

456 views
Skip to first unread message

Allan Brighton

unread,
May 26, 2015, 10:22:43 AM5/26/15
to scal...@googlegroups.com

Hi,

I would like the user to be able to resize the main divs in my play/scala.js app, so I’m trying to use the jquery-ui resizable() function.
I first added a jquery-ui facade as follows:

import scala.scalajs.js

import org.scalajs.jquery._
import scala.language.implicitConversions

object JQueryUi {
  implicit def jquery2ui(jquery: JQuery): JQueryUi =
    jquery.asInstanceOf[JQueryUi]
}

trait JQueryUi extends JQuery {
  def resizable(options: js.Any): JQueryUi = js.native

}

The jquery and jquery-ui definitions are included via webjar in index.scala.html:


<script type='text/javascript' src='@routes.WebJarAssets.at(WebJarAssets.locate("jquery.min.js"))'></script>
<script type='text/javascript' src='@routes.WebJarAssets.at(WebJarAssets.locate("jquery-ui.min.js"))'></script>

Then I tried to call the resizable() function, which compiles, but fails at runtime with the javascript message:

Uncaught TypeError: jquery.resizable is not a function

Here is the code that calls it:

import org.scalajs.dom._

import org.scalajs.dom.raw.Node

import scala.scalajs.js
import scalacss.ScalatagsCss._
import scalatags.JsDom.all._
import org.scalajs.jquery.{ jQuery ⇒ $, _ }
import JQueryUi._

case class Layout() extends Displayable {

  val wrapper = div(Styles.layout).render

  $(wrapper).resizable(js.Dynamic.literal {
    "handles" -> "e,s,w"

    // ...
  })

  override def markup(): Element = wrapper

  def addItem(node: Node): Unit = {
    wrapper.appendChild(node)
  }

}

Any idea why this is not working? Any suggestions?
Would using jquery-facade be of help here?

Thanks,
Allan

Justin du coeur

unread,
May 27, 2015, 3:34:24 PM5/27/15
to Allan Brighton, scal...@googlegroups.com
(Sorry this took a while to get to -- for some reason, your message went into Spam, at least in my Gmail account.  Entirely unclear why.)

On Tue, May 26, 2015 at 10:22 AM, Allan Brighton <alla...@gmail.com> wrote:

I would like the user to be able to resize the main divs in my play/scala.js app, so I’m trying to use the jquery-ui resizable() function.

I first added a jquery-ui facade as follows:

import scala.scalajs.js

import org.scalajs.jquery._
import scala.language.implicitConversions

object JQueryUi {
  implicit def jquery2ui(jquery: JQuery): JQueryUi =
    jquery.asInstanceOf[JQueryUi]
}

trait JQueryUi extends JQuery {
  def resizable(options: js.Any): JQueryUi = js.native

}

Wait, wait -- is there a resizable() function?  I'm not aware of one: AFAIK, Resizeable simply defines a bunch of new functions on the JQuery object, but is not a function itself.  So this facade is, I believe, trying to call a function that doesn't exist, and the error is correct.

I'm pretty sure that what you want is to define a facade for JQuery UI Resizeable, not for JQuery UI in general.  (I've never found anything terribly interesting about the JQuery UI framework aside from its gadgets.)  For an example of how to implement that, see Querki's facades for JQueryUIDialog and JQueryUISortable.  (Which I really need to get around to MIT-licensing, but feel free to steal code if useful.)

Would using jquery-facade be of help here?

Probably doesn't make much difference -- jquery-facade provides a more strongly-typed version of JQuery itself, but is mostly irrelevant to JQuery UI.  But you likely will want to use jsext's JSOptionBuilder if you want to get serious about building out this facade; again, see the Querki examples for how to use this.

(Actually, you *might* want to use jquery-facade's pseudo-types for Selector and such -- jquery-facade introduces mechanisms for working with the union types that jQuery sometimes expects.  But that's significant extra effort and pretty advanced stuff; I suspect isn't worth it for this case.)

Allan Brighton

unread,
Jul 3, 2015, 5:42:54 PM7/3/15
to scal...@googlegroups.com
I finally got around to looking into this issue again and found that the problem was the client's dependency on scala-js-jquery.

The problem is that scala-js-jquery uses jsDependencies to depend on jquery in the sbt build. So in addition to the copy of jquery 
that is being served by the play server through the HTML <script> tag, I was getting another copy of it via  jsDependencies.
Normally I would not have noticed, but I think what happens is that jquery-ui redefines the "$" function, and then if another copy
of jquery is imported after that, the "$" function is reset back again, so the jquery-ui API is no longer available.

So it seems that if the (Play) client has any dependency that uses jsDependencies, then the client's build would have to also
use jsDependencies for all of the javascript dependencies (rather than declare them in the Play server's build.sbt).

I would be OK with that, except that it seems that jsDependencies doesn't deal with CSS (according to http://www.scala-js.org/doc/sbt/depending.html).

The methods mentioned in http://ochrons.github.io/scalajs-spa-tutorial/using-resources-from-webjars.html seem more complicated than the method used for Play apps (side server webjar dependencies and HTML script/link tags in the client).

For now, I removed the scala-js-jquery dependency and copied the source (Its only one file, plus a package def).

Any suggestions on the best way to manage javascript and CSS dependencies in a Play/ScalaJS app?

Thanks,
Allan

Justin du coeur

unread,
Jul 3, 2015, 5:59:20 PM7/3/15
to Allan Brighton, scal...@googlegroups.com
On Fri, Jul 3, 2015 at 5:42 PM, Allan Brighton <alla...@gmail.com> wrote:
Any suggestions on the best way to manage javascript and CSS dependencies in a Play/ScalaJS app?

Personally, I use jsDependencies exclusively for all of the JavaScript files, and do the CSS files entirely manually -- it's inelegant, but works for my needs.  In the medium term, we probably want a cssDependencies that mimics jsDependencies, but I haven't had time to work on that yet... 
Reply all
Reply to author
Forward
0 new messages