scalajs access top level variable - scala.js

this scalajs works as expected:
console.log(js.eval("numItems").asInstanceOf[Int]) returns the correct value.
However, this code always returns zero. Any idea?
#js.native
#js.annotation.JSGlobalScope
object DOMGlobalScope extends js.Object {
var numItems: Int = js.native
}
console.log(DOMGlobalScope.numItems);

Related

Can an object extend abstract class in scala?

I am newbie to scala . I am trying to create an Object that extends abstract class like show below
object Conversions extends UnitConversions
{
override def inchesToCentimeters(inches:Int) = inches * 2.5
override def gallonsToLiters(gallons:Int) = gallons * 3.78
override def milesToKilometers(miles:Int) = miles * 1.6
}
abstract class UnitConversions
{
def inchesToCentimeters(inches:Int)
def gallonsToLiters(gallons:Int)
def milesToKilometers(miles:Int)
}
While i try to access the object's member functions i get () this expression as output .
Conversions.milesToKilometers(20) //I get output ()
More over is the below statement valid ???
var ucv:UnitConversions = new Conversions
println(ucv.milesToKilometers(3)) // I get output () here as well
Thanks in Advance !
You need to provide a return type for the functions, otherwise they return Unit:
abstract class UnitConversions {
def inchesToCentimeters(inches:Int): Double
def gallonsToLiters(gallons:Int): Double
def milesToKilometers(miles:Int): Double
}
Regarding this question:
More over is the below statement valid ???
var ucv:UnitConversions = new Conversions println(ucv.milesToKilometers(3))
This doesn't compile. object basically means singleton and can be used for "static" methods. It doesn't make sense to create more than one instance of a singleton. Take a look at this question: Difference between object and class in scala

JavaScript object as function parameter

I'm writting a function transpiled with Scala.js that should accept any random JavaScript object.
Ex:
// This has been transpiled using Scala.js
var my_service = new com.myself.Service();
// This is plain JavaScript
var result1 = service({ hello: "yolo" });
var result2 = service({ whatever: "ok", really: { yes: "right", no: "don't" } });
However, I can't find the input type that matches it.
What would be the Scala-function signature to get such a thing?
Could it be used then as a "Scala/JS case class" easily?
Note (if it helps giving a direction for the answers): these objects have, in the real life, an expected schema but it cannot be created as JS object generated from Scala.js since it comes from another consumed service.
Since the objects have an expected schema, its probably easiest to define a facade type:
#js.native
trait Args extends js.Object {
val hello: js.UndefOr[String]
val whatever: js.UndefOr[String]
val really: js.UndefOr[ReallyArgs]
}
#js.native
trait Really extends js.Object {
val yes: String
val no: String
}
def myMethod(args: Args): Unit = {
println(args.hello)
println(args.really.map(_.yes))
}

ScalaJS: Facade for polymorphic object

I would like to call, from ScalaJS, a JS function similar to the following:
function parseExpression(s){
if(isNumber(s)) return {lit:s}
else{
return {
left : leftOp(s)
oper : operand(s)
right: rightOp(s)
}
}
}
where the returned object can be of two different shapes, either {lit} or {left, oper, right}
I have defined the following traits in ScalaJS:
#js.native
trait NumLiteral extends js.Object{
val lit:String = js.native
}
#js.native
trait NumOper extends js.Object{
val left : NumLiteral | NumOper = js.native
val oper : String = js.native
val right: NumLiteral | NumOper = js.native
}
then I can declare function parseExpression as Function1[String, NumLiteral | NumOper]
What is the best way of checking if the returned value of parseExpression(someExpressionString) is of type NumLiteral or NumOper? I am free to change the JS and/or the Scala code to achieve the most elegant solution.
I solved it by defining the following in ScalaJS:
trait NumExpr
#JSExport
class NumLiteral(val lit:String) extends NumExpr
#JSExport
class NumOper(val left:NumExpr, val oper:String, val right:NumExpr) extends NumExpr
and then redefining my JS function to:
function parseExpression(s){
return isNumber(s) ?
new NumLiteral(s) :
new NumOper(leftOp(s), operand(s), rightOp(s))
}
This lets me pattern-match on parseExpression(someExpressionString)
Of course, this changes the original JS function, and therefore the original question, but it solved my problem.

calling a function inside of a constructor in scala

I am calling a function inside of class constructor but while compiling the code I keep getting an error : not found value : churnPeriodfnc
here is the code that I am running
class CustStoryN (var custId:String,
var rootEventType:String,
var rootEventTime:Long,
var eventStory:mutable.MutableList[StoryEventN]) extends Serializable {
def this(custID: String,rootEventType: String, rootEventTim: Long, eventStory: mutable.MutableList[StoryEventN], churnPeriod: Boolean, churnMode: Boolean)
{
this(custID,rootEventType,rootEventTim,
churnPeriodfnc(churnPeriod, churnMode,eventStory))
}
and here is ChurnPeriodFnc function that the compiler can not recognize, I didnt copy the churn periodfunc , for now just assume that I make some changes to eventstory and out put a new eventstory:
def churnPeriodfnc(churnPeriod: Boolean, churnMode: Boolean, eventStory: mutable.MutableList[StoryEventN]): mutable.MutableList[StoryEventN] = {
eventStory }
If churnPeriodfnc is defined within class body (instance method) or it is inherited; you can't call it inside a constructor.
If churnPeriodfnc is defined inside CustStoryN's companion object (like a static method); you must either import it or refer to it as CustStoryN.churnPeriodfnc()
If it's defined in another object, above rule still applies.
I have encountered a similar problem and I don't find this behavior logic (I understand that there is no instance of the class and the function does not exist yet but hey, the function is there inside the class I'm trying to instantiate.)
To fix the problem I suggest you using an apply function in the companion object like this:
case class Human(id: Int, name: String)
object Human {
def apply(id: Int): Human = new Human(id, withName(id))
def withName(id: Int): String = "Goku" /* Some behavior to get the name */
}
If you try this in your REPL you should have a behavior like this:
scala> Human(3)
res0: Human = Human(3,Goku)

Dynamic calls to JavaScript in Scala.js

I am wondering how to do dynamic operations in Scala.js. For example, looking at the jQuery example in the tutorial, my understanding is you define the following in scala:
object TutorialApp extends JSApp {
def appendPar(msg: String) = {
jQuery("body").append("<p>" + msg + "</p>")
}
def main(): Unit = {
appendPar("Hello World")
}
}
This is all stuff that is generated statically at compile time. But I didn't see any way I could set the message parameter dynamically (eg read it from a DB).
I don't know about reading it from the DB. That is beyond the scope of this question (or you need to rephrase the question). Maybe an AJAX call or something?
But to read it from, for example, an <input> tag, you'd do something like that:
def main(): Unit = {
val msg = jQuery("#myinput").value()
appendPar(msg)
}
(Although in this case it probably doesn't make any sense in a main method, but that's not the point.)
I mean, msg is just a val (so like a var in JS but immutable). You can fetch it from any dynamic source of information as you like.
Edit:
If you want to access some data generated dynamically by the server when rendering the page, you can do so like this:
First, have your server generate the data as a global var in a <script> tag in the generated HTML. Something like:
<script type="text/javascript">
var mydata = {
msg: "Some text generated dynamically by the server"
}
</script>
Make sure to emit this script tag before the call to the main() function of Scala.js!
Then, from Scala.js, you can access these data with the js.Dynamic interface:
import scala.scalajs.js
val mydata = js.Dynamic.global.mydata
val msg = mydata.msg.asInstanceOf[String]
If your data have always a relatively static structure, it may be useful to declare yourself a facade type for them:
#JSName("mydata")
object MyData extends js.Object {
val msg: String = ???
}
Then you can access it without resorting to the Dynamic API:
val msg = MyData.msg
Adding to (and attempting to generalize) sjrd's answer: To call a javaScriptMethod on an object of a JavaScriptType you first write a type facade for it:
import scala.scalajs.js
import scala.scalajs.js.annotation.JSName
#js.native
#JSName("JavaScriptType")
class MyType() extends js.Object {
def javaScriptMethod(someParam: String) = js.native
}
After that, it's a piece of cake to use the JavaScript code using Scala on the client side:
val myObject = new MyType()
myObject.javaScriptMethod("Yippie")
As a concrete example, to use Stack Overflow's Markdown converter Pagedown in your Scala.js application you'd first create the type facade for it:
#js.native
#JSName("Markdown.Converter")
class MarkdownConverter() extends js.Object {
def makeHtml(txtUsingMarkdown: String): String = js.native
}
If you are learning Scala.js using this great tutorial project, you can declare the dependency on Pagedown in Settings.scala like this:
val jsDependencies = Def.setting(Seq(
"org.webjars.bower" % "pagedown" % "1.1.0" / "Markdown.Converter.js",
//...
Then you can simply do
val html = new MarkdownConverter().makeHtml("this is *nice*")
Here's another example where we call a static method of SparkMD5.
We define an object as opposed to the class of the previous example. Also, we can omit the #JSName annotation since our Scala type is eponymous with the JavaScript type:
#js.native
object SparkMD5 extends js.Object {
def hash(str: String, raw: Boolean = false): String = js.native
}