2

I have the following problem. I would like to use https://github.com/aehlke/tag-it/ in my project. However I am not sure how I am supposed to implement the following example given on the github page:

<script type="text/javascript">
$(document).ready(function() {
 $("#myTags").tagit();
});
</script>

<ul id="myTags">
 <!-- Existing list items will be pre-added to the tags -->
 <li>Tag1</li>
 <li>Tag2</li>
</ul>

So far I am able to manipulate the object:

val document = js.Dynamic.global.document
document.getElementById("myTags").innerHTML = "Test"

This works! Test is being rendered.

When I call tagit() instead I am being told that tagit is not a function.

val document = js.Dynamic.global.document
document.getElementById("myTags").tagit()

When I do the "same" call with the chrome java script console everything works fine:

$("#myTags").tagit();

Can someone explain what I am doing wrong? Thank you in advance!

EDIT

It is not a problem of tag-it or jquery not being loaded. Again chrome console works. It is also not a loading issue. Even by clicking a button after everything is loaded for a 100% it doesn't work.

EDIT

Added my partial build defintion so everybody can see that the dependencies are correct:

.jsSettings(
      jsDependencies ++= Seq(
        "org.webjars" % "bootswatch-yeti" % "3.3.5" / "js/bootstrap.js" minified "js/bootstrap.min.js" dependsOn "jquery.js",
        "org.webjars" % "jquery-ui" % "1.11.4" / "jquery-ui.js" minified "jquery-ui.min.js" dependsOn "jquery.js",
        "org.webjars" % "tag-it" % "2.0" / "js/tag-it.js" dependsOn "jquery.js" dependsOn "jquery-ui.js"
      ),
      libraryDependencies ++= Seq(
        "io.github.widok" %%% "widok" % "0.2.2" exclude ("org.webjars", "bootstrap"),
        "be.doeraene" %%% "scalajs-jquery" % "0.8.0",
        "com.lihaoyi" %%% "scalatags" % "0.4.6",
        "org.webjars" % "bootswatch-yeti" % "3.3.5",
        "org.webjars" % "font-awesome" % "4.4.0",
        "org.webjars" % "jquery-ui-themes" % "1.11.4"
      ),
      persistLauncher := true
    )
Julian Pieles
  • 3,880
  • 2
  • 23
  • 33
  • two problem, one) you may not add tag-it js to your website two) tag-it added before jquery. – Omidam81 Oct 07 '15 at 10:49
  • @Omidam81 both not the case. I even installed a button to test to be sure everything is loaded. It doesn't work. Chrome console works, button doesn't. – Julian Pieles Oct 07 '15 at 10:53
  • please check the answer. thank you, – Omidam81 Oct 07 '15 at 11:01
  • your code is correct, but i think the problem is come form order that you add script(with src) tags. – Omidam81 Oct 07 '15 at 11:04
  • @Omidam81 no that can't happen with scala js. I updated my question. As you can see I am already telling the compiler that tag-it depends on jquery and jquery-ui. Once this is done everything is handled for you. There can't be a mistake there. – Julian Pieles Oct 07 '15 at 11:08
  • i'm not familiar with Scala.js, but i think you forget to add jQuery in your definition. – Omidam81 Oct 07 '15 at 11:08
  • yes, i familar with such syntax, it used in require.js also, but i think you must add jquery in your first part also(jsDependencies). – Omidam81 Oct 07 '15 at 11:10
  • @Omidam81 no I do not. Jquery is already added by `libraryDependencies += "be.doeraene" %%% "scalajs-jquery" % "0.8.0"` otherwise the compiler would throw an error when it does not find `jquery`. – Julian Pieles Oct 07 '15 at 11:12

3 Answers3

6

Your problem, initially, is that

// Scala.js code
document.getElementById("myTags").tagit()

is not "the same" as

// JavaScript code
$("#myTags").tagit();

Instead, it is the same as, guess what?

// JavaScript code
document.getElementById("myTags").tagit();

which is not valid because tagit() is not a method of HTMLElement returned by getElementById. tagit() is a (pimped) method of JQuery objects returned by the $ function.

You can obtain the $ function in a dynamically typed way using:

// Scala.js code
val $ = js.Dynamic.global.$

and then you can write the same as the jQuery invocation by writing this:

// Scala.js code
$("#myTags").tagit()

The solution found is essentially similar, because the jQuery object is equivalent as $. But then the returned element is a JQuery object, which statically does not have a tagit() method, which is why you needed to cast it to js.Dynamic.

Another way would be to type the tagit() method pimp using this:

// Scala.js code
@js.native
trait JQueryTagIt extends js.Object {
  def tagit(): Unit = js.native
}

implicit def tagItExtensions(jq: JQuery): JQueryTagIt =
  jq.asInstanceOf[JQueryTagIt]

With that, you can more simply do:

// Scala.js code
jQuery("#myTags").tagit()

and it will be statically typechecked.

sjrd
  • 21,805
  • 2
  • 61
  • 91
  • Thank you very much! Great explanation. One thing I still do not understand is how I should pass options. e.g. `tagit({tagLimit: 1})`. – Julian Pieles Oct 07 '15 at 14:12
  • With the dynamically typed version, use `js.Dynamic.literal(tagLimit = 1)`. For the statically typed version, see this question: http://stackoverflow.com/questions/26638171/how-do-i-create-options-objects-in-scala-js – sjrd Oct 07 '15 at 14:18
0

$(document).ready(function(){
  $("#myTags").tagit();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<script src="http://bitar.tk/tag-it.min.js"></script>

<ul id="myTags">
 <!-- Existing list items will be pre-added to the tags -->
 <li>Tag1</li>
 <li>Tag2</li>
</ul>
Omidam81
  • 1,887
  • 12
  • 20
  • Thank you very much. Have you seen that I am using Scala JS? I am building a SPA (Single Page Application). One defines the scala dependencies using a sbt build defintion. I updated my awnser so that everybody can see my deps. – Julian Pieles Oct 07 '15 at 11:05
0

I found a solution which works. It uses jQuery bindings for Scala JS. By building your own static bindings is the correct way I guess.

jQuery("#myTags").asInstanceOf[js.Dynamic].tagit()

UPDATE

Please see the following post (https://stackoverflow.com/a/32994303/1029251) since this approach is simply wrong considering what scala.js stands for. My solution is not typesafe!

Community
  • 1
  • 1
Julian Pieles
  • 3,880
  • 2
  • 23
  • 33
  • This approach always works, but it's not recommended if you can avoid it, because it takes you out of strongly-typed land, and strong typing is kind of the point of Scala.js. So this sort of thing is usually treated as a last resort. – Justin du Coeur Oct 07 '15 at 15:15
  • @JustinduCoeur I agree 100%. I posted this before sjrd awnsered. I will edit the post. – Julian Pieles Oct 07 '15 at 16:35