Created
October 20, 2014 14:43
-
-
Save benjaminjackman/5b0b5d853c1bccc7b7a1 to your computer and use it in GitHub Desktop.
ScalaJs React Examples
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class GlobalView(implicit val pc: PoeCacher) extends View { | |
override def start(jq: JQuery): Unit = { | |
val el = jq.get(0).asInstanceOf[dom.Element] | |
val root = GlobalViewWidget()(pc) | |
React.renderComponent(root, el) | |
} | |
override def stop(): Unit = { | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
object GlobalViewWidget { | |
class Component( | |
pc: PoeCacher, | |
lootWatcher: LootWatcher | |
) { | |
case class State( | |
league: Option[League], | |
character: Option[String], | |
autowatch: Boolean = false, | |
refreshIntervalSec: Int = 30 | |
) | |
case class Backend(T: BackendScope[_, State]) { | |
def setLeague(league: League) { | |
T.modState(_.copy(league = Some(league), character = None)) | |
} | |
def setCharacter(character: String) { | |
T.modState(_.copy(character = Some(character))) | |
} | |
def getCharacters(): Future[Seq[CharacterInfo]] = { | |
pc.getChars().map(cs => cs.toList.filter(c => Option(c.league) =?= T.state.league.map(_.toString))) | |
} | |
def setAutowatch(enabled: Boolean) { | |
lootWatcher.setMode(enabled = enabled, league = T.state.league, character = T.state.character) | |
T.modState(_.copy(autowatch = enabled)) | |
} | |
} | |
val component = { | |
import japgolly.scalajs.react.vdom.ReactVDom._ | |
import japgolly.scalajs.react.vdom.ReactVDom.all._ | |
import japgolly.scalajs.react.vdom.ReactVDom.{styles => st} | |
val O = Dynamic.literal | |
ReactComponentB[GlobalViewWidget]("GlobalViewWidget") | |
.initialState(State(None, None)) | |
.backend(Backend) | |
.render { (p, s, b) => | |
div( | |
a(href := "#/home", "[", span(`class` := "fa fa-home"), " Home]"), | |
a(key := "config", href := "#/config", "[", span(`class` := "fa fa-gear"), " Settings]"), | |
SelectLeagueWidget(s.league, b.setLeague)(), | |
s.league.map { l => SelectCharacterWidget(s.character, () => b.getCharacters(), (c) => b.setCharacter(c))()}, | |
s.character.map { character => | |
label( | |
"Autowatch", | |
title := s"Automatically scan this player for updates every ${s.refreshIntervalSec} Seconds", | |
input( | |
`type` := "checkbox", | |
onchange ==> { e: SyntheticEvent[HTMLInputElement] => b.setAutowatch(e.target.checked)}, | |
s.autowatch && (checked := "true"))) | |
}, | |
img(src:="sha2:afcf65") | |
) | |
} | |
.create | |
} | |
} | |
} | |
case class GlobalViewWidget() { | |
def apply(pc: PoeCacher) = new GlobalViewWidget.Component(pc, new LootWatcher(pc)).component(this) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
object Select2Widget { | |
import japgolly.scalajs.react.vdom.ReactVDom._ | |
import japgolly.scalajs.react.vdom.ReactVDom.all._ | |
def apply[A]( | |
selection: Option[A], | |
width: Int, | |
placeholder: String, | |
elements: => Future[Seq[A]], | |
onChange: A => Unit, | |
toString: A => String, | |
fromString: String => A, | |
caseSensitive: Boolean = false, | |
mustStartWith: Boolean = false | |
) = { | |
val props = Props( | |
selection = selection.map(i => toString(i)), | |
width = width, | |
placeholder = placeholder, | |
onFilter = { s => | |
elements.map { elements => | |
elements.filter { el => | |
val elStr = toString(el) | |
val (elStrC, txt) = if (caseSensitive) elStr -> s else elStr.toLowerCase -> s.toLowerCase | |
if (mustStartWith) elStrC.startsWith(txt) else elStrC.contains(txt) | |
}.map(toString) | |
.sortBy(_.toLowerCase) | |
} | |
}, | |
onChange = { s => | |
onChange(fromString(s)) | |
} | |
) | |
component(props) | |
} | |
case class Props( | |
selection: Option[String], | |
width: Int, | |
placeholder: String, | |
onFilter: String => Future[Seq[String]], | |
onChange: String => Unit | |
) | |
val component = { | |
ReactComponentB[Props]("Select2Widget") | |
.render((_) => div()) | |
.componentDidMount { scope => | |
val el = scope.getDOMNode() | |
val O = js.Dynamic.literal | |
jq(el).asJsDyn.select2(O( | |
width = scope.props.width, | |
placeholder = scope.props.placeholder, | |
initSelection = {(el : JQuery, cb : js.Dynamic) => | |
scope.props.selection.foreach { x => | |
cb(O(id = x, text = x)) | |
} | |
}, | |
query = { (q: js.Dynamic) => | |
val term = q.term.asInstanceOf[String] | |
scope.props.onFilter(term).foreach { xs => | |
val ys = xs.map(x => O(id = x, text = x)) | |
q.callback(O(results = ys.toJsArr)) | |
} | |
}: js.Function | |
)).on("change", { (e: js.Dynamic) => | |
scope.props.onChange(e.`val`.asInstanceOf[String]) | |
}: js.Function) | |
} | |
.componentDidUpdate { (scope, p, s) => | |
val el = jq(scope.getDOMNode()).asJsDyn | |
val oldVal = el.select2("val").toString | |
val newVal = scope.props.selection.getOrElse("") | |
if (oldVal != newVal) { | |
el.select2("val", newVal) | |
} | |
} | |
.create | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
object SelectCharacterWidget { | |
lazy val component = { | |
ReactComponentB[SelectCharacterWidget]("SelectCharacterWidget") | |
.render((props) => Select2Widget[String]( | |
selection = props.character, | |
width = 220, | |
placeholder = "Character", | |
elements = props.getCharacters().map(_.map(_.name)), | |
onChange = props.onCharacterChanged, | |
toString = x => x, | |
fromString = x => x | |
) | |
) | |
.create | |
} | |
} | |
case class SelectCharacterWidget( | |
character: Option[String], | |
getCharacters: () => Future[Seq[CharacterInfo]], | |
onCharacterChanged: String => Unit) { | |
def apply() = SelectCharacterWidget.component(this) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
object SelectLeagueWidget { | |
object Leagues extends CEnum { | |
final type EET = League | |
sealed trait League extends EnumElement | |
case object Standard extends League | |
case object Hardcore extends League | |
case object Rampage extends League | |
case object Beyond extends League | |
//Needs to be overrided in child class with | |
final override val elements = CEnum.getElements(this) | |
} | |
val component = { | |
ReactComponentB[SelectLeagueWidget]("SelectLeagueWidget") | |
.render((props) => Select2Widget[League]( | |
selection = props.league, | |
width = 120, | |
placeholder = "League", | |
elements = Future(Leagues.elements), | |
onChange = props.onLeagueChanged, | |
toString = x => x.toString, | |
fromString = Leagues.fromString | |
)) | |
.create | |
} | |
} | |
case class SelectLeagueWidget(league: Option[League], onLeagueChanged: League => Unit) { | |
def apply() = SelectLeagueWidget.component(this) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment