Created
September 28, 2012 10:17
-
-
Save timperrett/3799017 to your computer and use it in GitHub Desktop.
light js dsl
This file contains hidden or 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
trait js { | |
implicit def arrayExpr[A](es: Seq[A])(implicit f: A => Expr): ArrayExpr = | |
ArrayExpr(es.map(f)) | |
implicit def objectExpr[A](fs: Seq[(String, A)])(implicit f: A => Expr): ObjectExpr = | |
ObjectExpr(fs.map { case (k, v) => (k, f(v)) }) | |
implicit def booleanLiteral(b: Boolean): LiteralBoolean = LiteralBoolean(b) | |
implicit def nodeSeqLiteral(ns: NodeSeq): LiteralNodeSeq = LiteralNodeSeq(ns) | |
implicit def numericLiteral[A: Numeric](n: A): LiteralNumeric[A] = LiteralNumeric(n) | |
implicit def stringLiteral(s: String): LiteralString = LiteralString(s) | |
implicit def symbolReference(in: Symbol): Reference = Reference(in.name) | |
implicit def exprToJsExpr(in: Expr): JsExp = new JsExp { def toJsCmd = in.toJs } | |
implicit def exprToJsCmd(in: Expr): JsCmd = new JsCmd { def toJsCmd = in.toJs + ";" } | |
implicit def exprsToJsCmd(in: Seq[Expr]): JsCmd = new JsCmd { def toJsCmd = in.map(_.toJs).mkString("", ";", ";") } | |
implicit def cmdToJsCmd(in: Cmd): JsCmd = new JsCmd { def toJsCmd = in.toJs } | |
implicit def cmdsToJsCmd(in: Seq[Cmd]): JsCmd = new JsCmd { def toJsCmd = in.map(_.toJs).mkString("") } | |
trait Expr { | |
val toJs: String | |
def expr: this.type = this | |
def apply(in: Expr*): Apply = Apply(this, in) | |
def ^ (s: String): Select = select(s) | |
def ^ (s: Symbol): Select = select(s) | |
def & (e: Expr): Cmds = Cmds(Vector(Statement(this), Statement(e))) | |
def & (c: Cmd): Cmds = Cmds(Vector(Statement(this), c)) | |
def select(s: String): Select = Select(this, s) | |
def select(s: Symbol): Select = Select(this, s.name) | |
def call(s: String, as: Expr*): Apply = Apply(this ^ s, as) | |
def call(s: Symbol, as: Expr*): Apply = Apply(this ^ s, as) | |
} | |
trait Cmd { | |
val toJs: String | |
def & (c: Cmd): Cmds = Cmds(Vector(this, c)) | |
} | |
final case class Cmds(cmds: Vector[Cmd]) extends Cmd { | |
override def & (c: Cmd): Cmds = Cmds(cmds :+ c) | |
def & (cs: Cmds): Cmds = Cmds(cmds ++ cs.cmds) | |
lazy val toJs = cmds.map(_.toJsCmd).mkString("") | |
} | |
final case class Statement(in: Expr) extends Cmd { val toJs = in.toJs + ";" } | |
final case class Return(in: Expr) extends Cmd { val toJs = "return " + in.toJs + ";" } | |
final case class ArrayExpr(elements: Seq[Expr]) extends Expr { | |
lazy val toJs = elements.map(_.toJs).mkString("[", ",", "]") | |
} | |
final case class ObjectExpr(fields: Seq[(String, Expr)]) extends Expr { | |
lazy val toJs = fields.map { case (k, v) => k.encJs + ":" + v.toJs }.mkString("{", ",", "}") | |
} | |
final case class Reference(identifier: String) extends Expr { val toJs = identifier } | |
final case class Select(root: Expr, selection: String) extends Expr { | |
lazy val toJs = root.toJs + "." + selection | |
} | |
final case class LiteralBoolean(value: Boolean) extends Expr { val toJs = value.toString } | |
final case class LiteralString(value: String) extends Expr { val toJs = value.encJs } | |
final case class LiteralNodeSeq(value: NodeSeq) extends Expr { val toJs = JsNull.fixHtmlFunc("inline", value)(identity) } | |
final case class LiteralNumeric[A: Numeric](value: A) extends Expr { val toJs = value.toString } | |
final case class Apply(func: Expr, args: Seq[Expr]) extends Expr { | |
lazy val toJs: String = func.toJs + args.map(_.toJs).mkString("(", ",", ")") | |
} | |
implicit def jqExpr(in: Expr): JqExpr = new JqExpr { | |
val underlying = in | |
} | |
trait JqExpr { | |
val underlying: Expr | |
lazy val addClass: Select = (underlying ^ 'addClass) | |
lazy val appendTo: Select = (underlying ^ 'appendTo) | |
lazy val index: Select = (underlying ^ 'eq) | |
lazy val insertBefore: Select = (underlying ^ 'insertBefore) | |
lazy val remove: Select = (underlying ^ 'remove) | |
lazy val removeClass: Select = (underlying ^ 'removeClass) | |
} | |
def js(in: Expr): Expr = in | |
val jQuery = Reference("jQuery") | |
def jQueryId(s: String) = jQuery("#" + s) | |
} |
This file contains hidden or 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
final def insertRow(index: Option[Int], ev: Event): JsCmd = { | |
val renderedEvent = renderEvent(ev) | |
index match { | |
case Some(i) => | |
jQuery(renderedEvent).insertBefore(jQueryId(uniqueId + "-events").index(i * eventTemplate.size)) | |
// JS: jQuery("<html blob>").insertBefore(jQuery("#uniqueId-events").index(1234)) | |
case None => | |
jQuery(renderedEvent).appendTo(jQueryId(uniqueId + "-events")) | |
// JS: jQuery("<html blob>").appendTo(jQuery("#uniqueId-events")) | |
} | |
} | |
final def deleteRow(index: Int): JsCmd = | |
jQueryId(uniqueId + "-events").index(index * eventTemplate.size).remove() | |
// JS: jQuery("#uniqueId-events").index(1234).remove() | |
val onclickJS = ( | |
'showDetailPopup('event, event._id.toString) & Return(false) | |
// JS: showDetailPopup(event, "eventId"); return false; | |
).toJs |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment