Skip to content

Instantly share code, notes, and snippets.

@benjaminjackman
Created May 14, 2014 05:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save benjaminjackman/063673e3bf6d885cc083 to your computer and use it in GitHub Desktop.
Save benjaminjackman/063673e3bf6d885cc083 to your computer and use it in GitHub Desktop.
ScalaJS Idealized Type Wrappers for React Experimentation
package cgta.viz.learn.react
import scala.scalajs.js.annotation.JSExport
import scala.scalajs.js
import org.scalajs.dom.HTMLElement
@JSExport
object ReactTodo {
//Some helpers I use.
import BenSjs._
//Proposed annotation for typing a function that has a js.This
//Maybe a bad idea?
class JSThis[T] extends scala.annotation.StaticAnnotation
//Work in progress React wrappers
object React extends js.Object {
def createClass(init: ReactClassInit): ReactClassBuilder = ???
def renderComponent(cls: ReactClassInstance, mountNode: HTMLElement) = ???
object DOM {
def div(huh: js.Any, something: js.String, propsOrWhat: js.Any) = ???
}
}
trait ReactClassInstance extends js.Object
trait ReactClassBuilder {
def apply(args: js.Object): ReactClassInstance
}
trait ReactClassInit extends js.Object {
@JSThis[js.Dynamic]
def render() : js.Any
}
@JSExport
def main() {
helloJonT()
}
//Ideal Typed Example
def helloJonT() {
val HelloMessage = React.createClass(new ReactClassInit {
//Does the annotation need to be re stated each time?
@JSThis[js.Dynamic]
override def render() = {
//js.this only legal in functions that have the jsThis annotation
//How does this work for anonymous functions? Use the current syntax for them?
React.DOM.div(null, "Hello ", js.this.props.name)
}
})
React.renderComponent(HelloMessage(*(name = "Jon").asInstanceOf[js.Object]), document.getElementById("content"))
}
//Type Dynamic example:
def helloJon() {
val React = global.React
val HelloMessage = React.createClass(*(
render = new js.ThisFunction0[js.Dynamic, js.Any] {
override def apply(thisArg: js.Dynamic): js.Any = {
React.DOM.div(null, "Hello ", thisArg.props.name)
}
}
))
React.renderComponent(HelloMessage(*(name = "Jon")), document.getElementById("content"))
}
}
object BenSjs {
trait JsConsole extends js.Object {
def debug(xs: js.Any*)
def log(xs: js.Any*)
def warn(xs: js.Any*)
def error(xs: js.Any*)
}
val global = js.Dynamic.global
val console = global.console.asInstanceOf[JsConsole]
val JSON = global.JSON
val undefined = global.undefined
val window = global.window
val document = org.scalajs.dom.document
// def newObject = js.Object().asInstanceOf[js.Dynamic]
def new_*(clazz: js.Dynamic)(args: js.Any*): js.Dynamic = js.Dynamic.newInstance(clazz)(args: _*)
val * = js.Dynamic.literal
type * = js.Dynamic
def log(args: js.Any*) = console.log(args: _*)
//Use for for loops when porting over javascript code, not quite the same, but easier than converting to a while loop
def jfor[A](init: A, p: A => Boolean, inc: A => A)(f: A => Unit) {
var x = init
while (p(x)) {
f(x)
x = inc(x)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment