home | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Lift Framework example source code file (JsCommands.scala)

This example Lift Framework source code file (JsCommands.scala) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - Lift Framework tags/keywords

anonfunc, jscmd, jscmd, jsexp, jsexp, jsmember, jsobj, list, mostljfuncs, nodeseq, nodeseq, num, string, string

The Lift Framework JsCommands.scala source code

/*
 * Copyright 2007-2011 WorldWide Conferencing, LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.liftweb 
package http 
package js 

import scala.xml.{NodeSeq, Group, Unparsed, Elem}
import net.liftweb.util.Helpers._
import net.liftweb.util.Helpers
import net.liftweb.util.TimeHelpers
import net.liftweb.common._
import net.liftweb.util._
import scala.xml.{Node, SpecialNode, Text}

object JsCommands {
  def create = new JsCommands(Nil)

  def apply(in: Seq[JsCmd]) = new JsCommands(in.toList.reverse)

  def apply(in: JsExp) = new JsCommands(List(in.cmd))
}

class JsCommands(val reverseList: List[JsCmd]) {
  def &(in: JsCmd) = new JsCommands(in :: reverseList)

  def &(in: List[JsCmd]) = new JsCommands(in.reverse ::: reverseList)

  def toResponse = {
    val data = reverseList.reverse.map(_.toJsCmd).mkString("\n").getBytes("UTF-8")
    InMemoryResponse(data, List("Content-Length" -> data.length.toString, "Content-Type" -> "text/javascript; charset=utf-8"), S.responseCookies, 200)
  }
}

case class JsonCall(funcId: String) {
  def exp(exp: JsExp): JsCmd = JsCmds.Run(funcId + "(" + exp.toJsCmd + ");")

  def apply(command: String): JsCmd = apply(JE.Str(command))

  def apply(command: JsExp): JsCmd =
  JsCmds.Run(funcId + "({'command': " + command.toJsCmd + ", 'params': false});")

  def apply(command: String, params: JsExp) =
  JsCmds.Run(funcId + "({'command': " + command.encJs + ", 'params':" +
             params.toJsCmd + "});")

  def apply(command: String, target: String, params: JsExp) =
  JsCmds.Run(funcId + "({'command': " + command.encJs + ", 'target': " +
             target.encJs +
             ", 'params':" +
             params.toJsCmd + "});")


  def apply(command: JsExp, params: JsExp) =
  JsCmds.Run(funcId + "({'command': " + command.toJsCmd + ", 'params':" +
             params.toJsCmd + "});")

  def apply(command: JsExp, target: JsExp, params: JsExp) =
  JsCmds.Run(funcId + "({'command': " + command.toJsCmd + ", 'target': " +
             target.toJsCmd +
             ", 'params':" +
             params.toJsCmd + "});")

}


trait JsObj extends JsExp {
  def props: List[(String, JsExp)]

  def toJsCmd = props.map {case (n, v) => n.encJs + ": " + v.toJsCmd}.mkString("{", ", ", "}")

  override def toString(): String = toJsCmd

  override def equals(other: Any): Boolean = {
    other match {
      case jsObj: JsObj => {
        import scala.annotation.tailrec
        
        @tailrec def test(me: Map[String, JsExp], them: List[(String, JsExp)]): Boolean = {
          them match {
            case Nil => me.isEmpty
            case _ if me.isEmpty => false
            case (k, v) :: xs => 
              me.get(k) match {
                case None => false
                case Some(mv) if mv != v => false
                case _ => test(me - k, xs)
              }
          }
        }
        
        test(Map(props :_*), jsObj.props)
      }
      
      case x => super.equals(x)
    }
  }

  def +*(other: JsObj) = {
    val np = props ::: other.props
    new JsObj {
      def props = np
    }
  }
}

/**
 * The companion object to JsExp that has some
 * helpful conversions to/from Lift's JSON library
 */
object JsExp {
  import json._

  implicit def jValueToJsExp(jv: JValue): JsExp = new JsExp {
    lazy val toJsCmd = Printer.compact(JsonAST.render(jv))
  }

  implicit def strToJsExp(str: String): JE.Str = JE.Str(str)

  implicit def boolToJsExp(b: Boolean): JsExp = JE.boolToJsExp(b)

  implicit def intToJsExp(in: Int): JE.Num = JE.Num(in)

  implicit def longToJsExp(in: Long): JE.Num = JE.Num(in)

  implicit def doubleToJsExp(in: Double): JE.Num = JE.Num(in)

  implicit def floatToJsExp(in: Float): JE.Num = JE.Num(in)

  implicit def numToJValue(in: JE.Num): JValue = in match {
    case JE.Num(n) => JDouble(n.doubleValue())
  }

  implicit def strToJValue(in: JE.Str): JValue = JString(in.str)
}

/**
 * The basic JavaScript expression
 */
trait JsExp extends HtmlFixer with ToJsCmd {
  def toJsCmd: String

  override def equals(other: Any): Boolean = {
    other match {
      case jx: JsExp => this.toJsCmd == jx.toJsCmd
      case _ => super.equals(other)
    }
  }

  override def toString = "JsExp("+toJsCmd+")"

  // def label: String = "#JS"

  /*
  override def buildString(sb: StringBuilder) = {
    (new Text(toJsCmd)).buildString(sb)
  }*/

  def appendToParent(parentName: String): JsCmd = {
    val ran = "v" + Helpers.nextFuncName
    JsCmds.JsCrVar(ran, this) &
    JE.JsRaw("if (" + ran + ".parentNode) " + ran + " = " + ran + ".cloneNode(true)").cmd &
    JE.JsRaw("if (" + ran + ".nodeType) {" + parentName + ".appendChild(" + ran + ");} else {" +
             parentName + ".appendChild(document.createTextNode(" + ran + "));}").cmd
  }

  /**
   * ~> accesses a property in the current JsExp
   */
  def ~>(right: JsMember): JsExp = new JsExp {
    def toJsCmd = JsExp.this.toJsCmd + "." + right.toJsCmd
  }


  def ~>(right: Box[JsMember]): JsExp = right.dmap(this)(r => ~>(r))
  
  /**
   * This exists for backward compatibility reasons for JQueryLeft and JQueryRight
   * which are now deprecated. Use ~> whenever possible as this will be removed soon.
   */
  @deprecated
  def >>(right: JsMember): JsExp = ~>(right)


  def cmd: JsCmd = JsCmds.Run(toJsCmd + ";")


  def +(right: JsExp): JsExp = new JsExp {
    def toJsCmd = JsExp.this.toJsCmd + " + " + right.toJsCmd
  }

  def ===(right: JsExp): JsExp = new JsExp {
    def toJsCmd = JsExp.this.toJsCmd + " = " + right.toJsCmd
  }

}

trait JsMember {
  def toJsCmd: String
}

/**
 * JavaScript Expressions. To see these in action, check out
 * sites/example/src/webapp/json.html
 */
object JE {
  def boolToJsExp(in: Boolean): JsExp = if (in) JsTrue else JsFalse

  /**
   * The companion object to Num which has some helpful
   * constructors
   */
  object Num {
    def apply(i: Int): Num = new Num(i)
    def apply(lng: Long): Num = new Num(lng)
    def apply(d: Double): Num = new Num(d)
    def apply(f: Float): Num = new Num(f)
  }
  
  case class Num(n: Number) extends JsExp {
    def toJsCmd = n.toString
  }

  case class Stringify(in: JsExp) extends JsExp {
    def toJsCmd = "JSON.stringify(" + in.toJsCmd + ")"
  }

  case class JsArray(in: JsExp*) extends JsExp {
    def toJsCmd = new JsExp {
      def toJsCmd = in.map(_.toJsCmd).mkString("[", ", ", "]\n")
    }.toJsCmd

    def this(in: List[JsExp]) = this (in: _*)
  }

  object JsArray {
    def apply(in: List[JsExp]) = new JsArray(in: _*)
  }

  case class ValById(id: String) extends JsExp {
    def toJsCmd = "(function() {if (document.getElementById(" + id.encJs + ")) {return document.getElementById(" + id.encJs + ").value;} else {return null;}})()"
  }

  /**
   * Given the id of a checkbox, see if it's checked
   */
  case class CheckedById(id: String) extends JsExp {
    def toJsCmd = "(function() {if (document.getElementById(" + id.encJs + ")) {return document.getElementById(" + id.encJs + ").checked} else {return false;}})()"
  }

  /**
   * gets the element by ID
   */
  case class ElemById(id: String, then: String*) extends JsExp {
    override def toJsCmd = "document.getElementById(" + id.encJs + ")" + (
      if (then.isEmpty) "" else then.mkString(".", ".", "")
    )
  }

  /**
   * Gives the parent node of the node denominated by the id
   *
   * @param id - the id of the node
   */
  case class ParentOf(id: String) extends JsExp {
    def toJsCmd = (ElemById(id) ~> Parent).toJsCmd
  }

  object LjSwappable {
    def apply(visible: JsExp, hidden: JsExp): JxBase = {
      new JxNodeBase {
        def child = Nil

        def appendToParent(name: String): JsCmd =
        JsRaw(name + ".appendChild(lift$.swappable(" + visible.toJsCmd
              + ", " + hidden.toJsCmd + "))").cmd
      }
    }

    def apply(visible: NodeSeq, hidden: NodeSeq): JxBase = {
      new JxNodeBase {
        def child = Nil

        def appendToParent(name: String): JsCmd =
        JsRaw(name + ".appendChild(lift$.swappable(" + AnonFunc(
            JsCmds.JsCrVar("df", JsRaw("document.createDocumentFragment()")) &
            addToDocFrag("df", visible.toList) &
            JE.JsRaw("return df").cmd
          ).toJsCmd
              + "(), " + AnonFunc(JsCmds.JsCrVar("df", JsRaw("document.createDocumentFragment()")) &
                                  addToDocFrag("df", hidden.toList) &
                                  JE.JsRaw("return df").cmd).toJsCmd + "()))").cmd
      }
    }
  }

  object LjBuildIndex {
    def apply(obj: String,
              indexName: String, tables: (String, String)*): JsExp = new JsExp {
      def toJsCmd = "lift$.buildIndex(" + obj + ", " + indexName.encJs +
      (if (tables.isEmpty) "" else ", " +
       tables.map {case (l, r) => "[" + l.encJs + ", " + r.encJs + "]"}.mkString(", ")) +
      ")"
    }

    def apply(obj: JsExp,
              indexName: String, tables: (String, String)*): JsExp = new JsExp {
      def toJsCmd = "lift$.buildIndex(" + obj.toJsCmd + ", " + indexName.encJs +
      (if (tables.isEmpty) "" else ", " +
       tables.map {case (l, r) => "[" + l.encJs + ", " + r.encJs + "]"}.mkString(", ")) +
      ")"
    }
  }

  protected trait MostLjFuncs {
    def funcName: String

    def apply(obj: String, func: String): JsExp = new JsExp {
      def toJsCmd = "lift$." + funcName + "(" + obj + ", " + func.encJs + ")"
    }

    def apply(obj: JsExp, func: JsExp): JsExp = new JsExp {
      def toJsCmd = "lift$." + funcName + "(" + obj.toJsCmd + ", " + func.toJsCmd + ")"
    }
  }

  object LjAlt {
    def apply(obj: String, func: String, alt: String): JsExp = new JsExp {
      def toJsCmd = "lift$.alt(" + obj + ", " + func.encJs + ", " + alt.encJs + ")"
    }

    def apply(obj: JsExp, func: JsExp, alt: String): JsExp = new JsExp {
      def toJsCmd = "lift$.alt(" + obj.toJsCmd + ", " + func.toJsCmd + ", " + alt.encJs + ")"
    }

    def apply(obj: JsExp, func: JsExp, alt: JsExp): JsExp = new JsExp {
      def toJsCmd = "lift$.alt(" + obj.toJsCmd + ", " + func.toJsCmd + ", " + alt.toJsCmd + ")"
    }
  }

  object LjMagicUpdate {
    def apply(obj: String, field: String, idField: String, toUpdate: JsExp): JsExp = new JsExp {
      def toJsCmd = "lift$.magicUpdate(" + obj + ", " + field.encJs + ", " + idField.encJs + ", " + toUpdate.toJsCmd + ")"
    }

    def apply(obj: JsExp, field: String, idField: String, toUpdate: JsExp): JsExp = new JsExp {
      def toJsCmd = "lift$.magicUpdate(" + obj.toJsCmd + ", " + field.encJs + ", " + idField.encJs + ", " + toUpdate.toJsCmd + ")"
    }
  }

  object LjForeach extends MostLjFuncs {
    def funcName: String = "foreach"
  }

  object LjFilter extends MostLjFuncs {
    def funcName: String = "filter"
  }

  object LjMap extends MostLjFuncs {
    def funcName: String = "map"
  }

  object LjFold {
    def apply(what: JsExp, init1: JsExp, func: String): JsExp = new JsExp {
      def toJsCmd = "lift$.fold(" + what.toJsCmd + ", " + init1.toJsCmd + ", " + func.encJs + ")"
    }

    def apply(what: JsExp, init1: JsExp, func: AnonFunc): JsExp = new JsExp {
      def toJsCmd = "lift$.fold(" + what.toJsCmd + ", " + init1.toJsCmd + ", " + func.toJsCmd + ")"
    }
  }

  object LjFlatMap extends MostLjFuncs {
    def funcName: String = "flatMap"
  }

  object LjSort extends MostLjFuncs {
    def funcName: String = "sort"

    def apply(obj: String): JsExp = new JsExp {
      def toJsCmd = "lift$." + funcName + "(" + obj + ")"
    }

    def apply(obj: JsExp): JsExp = new JsExp {
      def toJsCmd = "lift$." + funcName + "(" + obj.toJsCmd + ")"
    }
  }

  object FormToJSON {
    def apply(formId: String) = new JsExp {
      def toJsCmd = LiftRules.jsArtifacts.formToJSON(formId).toJsCmd;
    }
  }

  /**
   * A String (JavaScript encoded)
   */
  case class Str(str: String) extends JsExp {
    def toJsCmd = str.encJs
  }

  /**
   * A JavaScript method that takes parameters
   *
   * JsFunc is very similar to Call but only the latter will be implicitly converted to a JsCmd.
   * @see Call
   */
  case class JsFunc(method: String, params: JsExp*) extends JsMember {
    def toJsCmd = params.map(_.toJsCmd).mkString(method + "(", ", ", ")")

    def cmd: JsCmd = JsCmds.Run(toJsCmd + ";")
  }

  /**
   * Put any JavaScript expression you want in here and the result will be
   * evaluated.
   */
  case class JsRaw(rawJsCmd: String) extends JsExp {
    def toJsCmd = rawJsCmd
  }

  case class JsVar(varName: String, andThen: String*) extends JsExp {
    def toJsCmd = varName + (if (andThen.isEmpty) ""
                             else andThen.mkString(".", ".", ""))
  }

  /**
   * A value that can be retrieved from an expression
   */
  case class JsVal(valueName: String) extends JsMember {
    def toJsCmd = valueName
  }

  case object Id extends JsMember {
    def toJsCmd = "id"
  }

  case object Parent extends JsMember {
    def toJsCmd = "parentNode"
  }

  case object Style extends JsMember {
    def toJsCmd = "style"
  }

  case object Value extends JsMember {
    def toJsCmd = "value"
  }

  case object JsFalse extends JsExp {
    def toJsCmd = "false"
  }

  case object JsNull extends JsExp {
    def toJsCmd = "null"
  }

  case object JsTrue extends JsExp {
    def toJsCmd = "true"
  }

  /**
   * A JavaScript method that takes parameters
   *
   * Call is very similar to JsFunc but only the former will be implicitly converted to a JsCmd.
   * @see JsFunc
   */
  case class Call(function: String, params: JsExp*) extends JsExp {
    def toJsCmd = function + "(" + params.map(_.toJsCmd).mkString(",") + ")"
  }

  trait AnonFunc extends JsExp {
    def applied: JsExp = new JsExp {
      def toJsCmd = "(" + AnonFunc.this.toJsCmd + ")" + "()"
    }

    def applied(params: JsExp*): JsExp = new JsExp {
      def toJsCmd = "(" + AnonFunc.this.toJsCmd + ")" +
      params.map(_.toJsCmd).mkString("(", ",", ")")
    }

  }

  object AnonFunc {
    def apply(in: JsCmd): AnonFunc = new JsExp with AnonFunc {
      def toJsCmd = "function() {" + in.toJsCmd + "}"
    }

    def apply(params: String, in: JsCmd): AnonFunc = new JsExp with AnonFunc {
      def toJsCmd = "function(" + params + ") {" + in.toJsCmd + "}"
    }
  }

  object JsObj {
    def apply(members: (String, JsExp)*): JsObj =
    new JsObj {
      def props = members.toList
    }
  }

  case class JsLt(left: JsExp, right: JsExp) extends JsExp {
    def toJsCmd = left.toJsCmd + " < " + right.toJsCmd
  }

  case class JsGt(left: JsExp, right: JsExp) extends JsExp {
    def toJsCmd = left.toJsCmd + " > " + right.toJsCmd
  }

  case class JsEq(left: JsExp, right: JsExp) extends JsExp {
    def toJsCmd = left.toJsCmd + " == " + right.toJsCmd
  }

  case class JsNotEq(left: JsExp, right: JsExp) extends JsExp {
    def toJsCmd = left.toJsCmd + " != " + right.toJsCmd
  }

  case class JsLtEq(left: JsExp, right: JsExp) extends JsExp {
    def toJsCmd = left.toJsCmd + " <= " + right.toJsCmd
  }

  case class JsGtEq(left: JsExp, right: JsExp) extends JsExp {
    def toJsCmd = left.toJsCmd + " >= " + right.toJsCmd
  }

  case class JsOr(left: JsExp, right: JsExp) extends JsExp {
    def toJsCmd = left.toJsCmd + " || " + right.toJsCmd
  }

  case class JsAnd(left: JsExp, right: JsExp) extends JsExp {
    def toJsCmd = left.toJsCmd + " && " + right.toJsCmd
  }

  case class JsNot(exp: JsExp) extends JsExp {
    def toJsCmd = "!" + exp.toJsCmd
  }


}

trait HtmlFixer {
  /**
   * Super important... call fixHtml at instance creation time and only once
   * This method must be run in the context of the thing creating the XHTML
   * to capture the bound functions
   */
  @deprecated("Use fixHtmlAndJs or fixHtmlFunc")
  protected def fixHtml(uid: String, content: NodeSeq): String = {
    val w = new java.io.StringWriter
    
    S.htmlProperties.
    htmlWriter(Group(S.session.
                     map(s =>
                       s.fixHtml(s.processSurroundAndInclude("JS SetHTML id: "
                                                             + uid,
                                                             content))).
                     openOr(content)),
               w)
    w.toString.encJs
  }

  /**
   * Calls fixHtmlAndJs and if there's embedded script tags,
   * construct a function that executes the contents of the scripts
   * then evaluations to Expression.  For use when converting
   * a JsExp that contains HTML.
   */
  def fixHtmlFunc(uid: String, content: NodeSeq)(f: String => String) = 
    fixHtmlAndJs(uid, content) match {
      case (str, Nil) => f(str)
      case (str, cmds) => "((function() {"+cmds.reduceLeft{_ & _}.toJsCmd+" return "+f(str)+";})())"
    }

  /**
   * Calls fixHtmlAndJs and if there's embedded script tags,
   * append the JsCmds to the String returned from applying
   * the function to the enclosed HTML.
   * For use when converting
   * a JsCmd that contains HTML.
   */
  def fixHtmlCmdFunc(uid: String, content: NodeSeq)(f: String => String) = 
    fixHtmlAndJs(uid, content) match {
      case (str, Nil) => f(str)
      case (str, cmds) => f(str)+"; "+cmds.reduceLeft(_ & _).toJsCmd
    }

  /**
   * Super important... call fixHtml at instance creation time and only once
   * This method must be run in the context of the thing creating the XHTML
   * to capture the bound functions
   */
  protected def fixHtmlAndJs(uid: String, content: NodeSeq): (String, List[JsCmd]) = {
    import Helpers._

    val w = new java.io.StringWriter
    
    val xhtml = S.session.
    map(s =>
      s.fixHtml(s.processSurroundAndInclude("JS SetHTML id: "
                                            + uid,
                                            content))).
    openOr(content)

    import scala.collection.mutable.ListBuffer
    val lb = new ListBuffer[JsCmd]
    
    val revised = ("script" #> ((ns: NodeSeq) => {
      ns match {
        case FindScript(e) => {
          lb += JE.JsRaw(ns.text).cmd
          NodeSeq.Empty
        }
        case x => x
      }
    }))(xhtml)

    S.htmlProperties.htmlWriter(Group(revised), w)

    (w.toString.encJs, lb.toList)
  }

  private object FindScript {
    def unapply(in: NodeSeq): Option[Elem] = in match {
      case e: Elem => {
        e.attribute("type").map(_.text).filter(_ == "text/javascript").flatMap {
          a =>
            if (e.attribute("src").isEmpty) Some(e) else None
        }
      }
      case _ => None
    }
  }

}

trait JsCmd extends HtmlFixer with ToJsCmd {
  def &(other: JsCmd): JsCmd = JsCmds.CmdPair(this, other)

  def toJsCmd: String

  override def toString() = "JsCmd("+toJsCmd+")"
}

object JsCmd {
  /**
   * If you've got Unit and need a JsCmd, return a Noop
   */
  implicit def unitToJsCmd(in: Unit): JsCmd = JsCmds.Noop
}

object JsCmds {
  implicit def seqJsToJs(in: Seq[JsCmd]): JsCmd = in.foldLeft[JsCmd](Noop)(_ & _)

  object Script {
    def apply(script: JsCmd): Node = <script type="text/javascript">{Unparsed("""
// <![CDATA[
""" + fixEndScriptTag(script.toJsCmd) + """
// ]]>
""")}</script>

    private def fixEndScriptTag(in: String): String =
    if (S.ieMode) """\<\/script\>""".r.replaceAllIn(in, """<\\/script>""")
    else in
  }

  def JsHideId(what: String): JsCmd = LiftRules.jsArtifacts.hide(what).cmd

  def JsShowId(what: String): JsCmd = LiftRules.jsArtifacts.show(what).cmd

  /**
   * Replaces the node having the provided id with the markup given by node
   *
   * @param id - the id of the node that will be replaced
   * @param node - the new node
   */
  case class Replace(id: String, content: NodeSeq) extends JsCmd with HtmlFixer {
    override val toJsCmd = {
      val (html, js) = fixHtmlAndJs("inline", content)

      var ret = 
      """
  try {
  var parent1 = document.getElementById(""" + id.encJs + """);
  parent1.innerHTML = """ + html + """;
  for (var i = 0; i < parent1.childNodes.length; i++) {
    var node = parent1.childNodes[i];
    parent1.parentNode.insertBefore(node.cloneNode(true), parent1);
  }
  parent1.parentNode.removeChild(parent1);
  } catch (e) {
    // if the node doesn't exist or something else bad happens
  }
"""
      if (js.isEmpty) ret else ret + " "+js.toJsCmd

    }
  }

  /**
   * Replaces the content of the node with the provided id with the markup given by content
   *
   * This is analogous to assigning a new value to a DOM object's innerHtml property in Javascript.
   *
   * @param id - the id of the node whose content will be replaced
   * @param content - the new content
   */
  case class SetHtml(uid: String, content: NodeSeq) extends JsCmd {
    // we want eager evaluation of the snippets so they get evaluated in context
    val toJsCmd = LiftRules.jsArtifacts.setHtml(uid, Helpers.stripHead(content)).toJsCmd
  }

  /**
   * Makes the parameter the selected HTML element on load of the page
   *
   * @param in the element that should have focus
   *
   * @return the element and a script that will give the element focus
   */
  object FocusOnLoad {
    def apply(in: Elem): NodeSeq = {
      val (elem, id) = findOrAddId(in)
      elem ++ Script(LiftRules.jsArtifacts.onLoad(Run("if (document.getElementById(" + id.encJs + ")) {document.getElementById(" + id.encJs + ").focus();};")))
    }
  }

  /**
   * Sets the value of an element and sets the focus
   */
  case class SetValueAndFocus(id: String, value: String) extends JsCmd {
    def toJsCmd = "if (document.getElementById(" + id.encJs + ")) {document.getElementById(" + id.encJs + ").value = " +
            value.encJs +
            "; document.getElementById(" + id.encJs + ").focus();};"
  }

  /**
   * Sets the focus on the element denominated by the id
   */ 
  case class Focus(id: String) extends JsCmd {
    def toJsCmd = "if (document.getElementById(" + id.encJs + ")) {document.getElementById(" + id.encJs + ").focus();};"
  }


  /**
   * Creates a JavaScript function with a name, a parameters list and
   * a function body
   */
  object Function {
    def apply(name: String, params: List[String], body: JsCmd): JsCmd =
    new JsCmd {
      def toJsCmd = "function " + name + "(" +
      params.mkString(", ") + """) {
    """ + body.toJsCmd + """
    }
"""
    }
  }

  /**
   * Execute the 'what' code when the page is ready for use
   */
  object OnLoad {
    def apply(what: JsCmd): JsCmd = LiftRules.jsArtifacts.onLoad(what)
  }

  /**
   * Sets the value to the element having the 'id' attribute with
   * the result of the 'right' expression
   */
  case class SetValById(id: String, right: JsExp) extends JsCmd {
    def toJsCmd = "if (document.getElementById(" + id.encJs + ")) {document.getElementById(" + id.encJs + ").value = " +
    right.toJsCmd + ";};"
  }

  /**
   * Assigns the value computed by the 'right' expression to the
   * 'left' expression.
   */
  case class SetExp(left: JsExp, right: JsExp) extends JsCmd {
    def toJsCmd = left.toJsCmd + " = " + right.toJsCmd + ";"
  }

  /**
   * Creates a JavaScript var named by 'name' and assigns it the
   * value of 'right' expression.
   */
  case class JsCrVar(name: String, right: JsExp) extends JsCmd {
    def toJsCmd = "var " + name + " = " + right.toJsCmd + ";"
  }

  /**
   * Assigns the value of 'right' to the members of the element
   * having this 'id', chained by 'then' sequences 
   */
  case class SetElemById(id: String, right: JsExp, then: String*) extends JsCmd {
    def toJsCmd = "if (document.getElementById(" + id.encJs + ")) {document.getElementById(" + id.encJs + ")" + (
      if (then.isEmpty) "" else then.mkString(".", ".", "")
    ) + " = " + right.toJsCmd + ";};"
  }

  implicit def jsExpToJsCmd(in: JsExp) = in.cmd

  case class CmdPair(left: JsCmd, right: JsCmd) extends JsCmd {
    def toJsCmd = {
      val sb = new StringBuilder
      append(sb, this)
      sb.toString
    }

    private def append(sb: StringBuilder, cmd: JsCmd) {
      cmd match {
        case CmdPair(l, r) => append(sb, l)
          sb.append('\n')
          append(sb, r)

        case c => sb.append(c.toJsCmd)
      }
    }
  }

  trait HasTime {
    def time: Box[TimeSpan]

    def timeStr = time.map(_.millis.toString) openOr ""
  }

  case class After(time: TimeSpan, toDo: JsCmd) extends JsCmd {
    def toJsCmd = "setTimeout(function() {" + toDo.toJsCmd + "}, " + time.millis + ");"
  }

  case class Alert(text: String) extends JsCmd {
    def toJsCmd = "alert(" + text.encJs + ");"
  }

  case class Confirm(text: String, yes: JsCmd) extends JsCmd {
    def toJsCmd = "if (confirm(" + text.encJs + ")) {" + yes.toJsCmd + "}"
  }

  case class Run(text: String) extends JsCmd {
    def toJsCmd = text
  }

  case object _Noop extends JsCmd {
    def toJsCmd = ""
  }

  implicit def cmdToString(in: JsCmd): String = in.toJsCmd

  def Noop: JsCmd = _Noop

  case class JsTry(what: JsCmd, alert: Boolean) extends JsCmd {
    def toJsCmd = "try { " + what.toJsCmd + " } catch (e) {" + (if (alert) "alert(e);" else "") + "}"
  }

  /**
   * A companion object with a helpful alternative constructor
   */
  object RedirectTo {
    /**
     * Redirect to a page and execute the function
     * when the page is loaded (only if the page is on the
     * same server, not going to some other server on the internet)
     */
    def apply(where: String, func: () => Unit): RedirectTo =
    S.session match {
      case Full(liftSession) => 
        new RedirectTo(liftSession.attachRedirectFunc(where, Full(func)))
      case _ => new RedirectTo(where)
    }
  }

  case class RedirectTo(where: String) extends JsCmd {
    private val where2 = // issue 176
    if (where.startsWith("/") &&
        !LiftRules.excludePathFromContextPathRewriting.vend(where)) (S.contextPath + where) else where

    def toJsCmd = "window.location = " + S.encodeURL(where2).encJs + ";"
  }


  /**
   * Update a Select with new Options
   */
  case class ReplaceOptions(select: String, opts: List[(String, String)], dflt: Box[String]) extends JsCmd {
    def toJsCmd = """var x=document.getElementById(""" + select.encJs + """);
    if (x) {
    while (x.length > 0) {x.remove(0);}
    var y = null;
    """ +
    opts.map {
      case (value, text) =>
        "y=document.createElement('option'); " +
        "y.text = " + text.encJs + "; " +
        "y.value = " + value.encJs + "; " +
        (if (Full(value) == dflt) "y.selected = true; " else "") +
        " try {x.add(y, null);} catch(e) {if (typeof(e) == 'object' && typeof(e.number) == 'number' && (e.number & 0xFFFF) == 5){ x.add(y,x.options.length); } } "
    }.mkString("\n")+"};"
  }

  case object JsIf {
    def apply(condition: JsExp, body: JsCmd): JsCmd = JE.JsRaw("if ( " + condition.toJsCmd + " ) { " + body.toJsCmd + " }")

    def apply(condition: JsExp, bodyTrue: JsCmd, bodyFalse: JsCmd): JsCmd =
    JE.JsRaw("if ( " + condition.toJsCmd + " ) { " + bodyTrue.toJsCmd + " } else { " + bodyFalse.toJsCmd + " }")

    def apply(condition: JsExp, body: JsExp): JsCmd = JE.JsRaw("if ( " + condition.toJsCmd + " ) { " + body.toJsCmd + " }")

    def apply(condition: JsExp, bodyTrue: JsExp, bodyFalse: JsExp): JsCmd =
    JE.JsRaw("if ( " + condition.toJsCmd + " ) { " + bodyTrue.toJsCmd + " } else { " + bodyFalse.toJsCmd + " }")
  }

  case class JsWhile(condition: JsExp, body: JsExp) extends JsCmd {
    def toJsCmd = "while ( " + condition.toJsCmd + " ) { " + body.toJsCmd + " }"
  }

  case class JsWith(reference: String, body: JsExp) extends JsCmd {
    def toJsCmd = "with ( " + reference + " ) { " + body.toJsCmd + " }"
  }

  case class JsDoWhile(body: JsExp, condition: JsExp) extends JsCmd {
    def toJsCmd = "do { " + body.toJsCmd + " } while ( " + condition.toJsCmd + " )"
  }

  case class JsFor(initialExp: JsExp, condition: JsExp, incrementExp: JsExp, body: JsExp) extends JsCmd {
    def toJsCmd = "for ( " + initialExp.toJsCmd + "; " +
    condition.toJsCmd + "; " +
    incrementExp.toJsCmd + " ) { " + body.toJsCmd + " }"
  }

  case class JsForIn(initialExp: JsExp, reference: String, body: JsCmd) extends JsCmd {
    def toJsCmd = "for ( " + initialExp.toJsCmd + " in " + reference + ") { " + body.toJsCmd + " }"
  }

  case object JsBreak extends JsCmd {
    def toJsCmd = "break"
  }

  case object JsContinue extends JsCmd {
    def toJsCmd = "continue"
  }

  object JsReturn {
    def apply(in: JsExp): JsCmd = new JsCmd {
      def toJsCmd = "return " + in.toJsCmd
    }

    def apply(): JsCmd = new JsCmd {
      def toJsCmd = "return "
    }
  }

}

/**
* A collection of defaults for JavaScript related stuff
*/
object JsRules {
  /**
  * The default duration for displaying FadeOut and FadeIn
  * messages.
  */
  //@deprecated
  @volatile var prefadeDuration: Helpers.TimeSpan = 5 seconds

  /**
  * The default fade time for fading FadeOut and FadeIn
  * messages.
  */
  //@deprecated
  @volatile var fadeTime: Helpers.TimeSpan = 1 second
}

Other Lift Framework examples (source code examples)

Here is a short list of links related to this Lift Framework JsCommands.scala source code file:



my book on functional programming

 

new blog posts

 

Copyright 1998-2019 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.