All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.liftweb.http.js.Jx.scala Maven / Gradle / Ivy

The newest version!
/*
 * 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._
import net.liftweb.common._
import net.liftweb.util._
import Helpers._

import JE._
import JsCmds._

trait JxYieldFunc {
  this: JxBase =>
  def yieldFunction: JsExp
}

trait JxBase {
  self: Node =>

  private val logger = Logger(classOf[JxBase])
  def appendToParent(parentName: String): JsCmd

  def label = "jx" 

  def addAttrs(varName: String, attrs: List[MetaData]): JsCmd = attrs.map {
    m =>
            m.value.map {
              case exp: JsExp =>
                JsRaw(varName + "." + m.key + " = " + exp.toJsCmd).cmd

              case cmd: JsCmd => val varName = "v" + Helpers.nextFuncName
              JsCrVar(varName, AnonFunc(cmd)) &
                      JsRaw(varName + "." + m.key + " = " + varName + "()")

              case JxAttr(cmd) =>
                JsRaw(varName + "." + m.key + " = " + cmd.toJsCmd).cmd

              case JxFuncAttr(cmd) =>
                JsRaw(varName + "." + m.key + " = " + AnonFunc(cmd).toJsCmd).cmd

              case x =>
                if (m.key == "class") {
                  // JsRaw(varName+".setAttribute('className',"+x.text.encJs+");").cmd

                  JsRaw(varName + ".className = " + x.text.encJs).cmd &
                          JsRaw(varName + ".setAttribute(" + m.key.encJs + "," + x.text.encJs + ");").cmd
                } else {
                  JsRaw(varName + ".setAttribute(" + m.key.encJs + "," + x.text.encJs + ");").cmd
                }
            }.foldLeft(Noop)(_ & _)
  }.foldLeft(Noop)(_ & _)

  private def fixText(in: String): String = (in, in.trim) match {
    case (x, y) if x == y => x
    case (x, y) if x startsWith y => y + " "
    case (x, y) if y.length == 0 => " "
    case (x, y) if x endsWith y => " " + y
    case (_, y) => " " + y + " "
  }

  def addToDocFrag(parent: String, elems: List[Node]): JsCmd = elems.map {
    case Jx(kids) => addToDocFrag(parent, kids.toList)
    case jb: JxBase => jb.appendToParent(parent)
    case Group(nodes) => addToDocFrag(parent, nodes.toList)
    case Text(txt) => JsRaw(parent + ".appendChild(document.createTextNode(" + fixText(txt).encJs + "));").cmd
    case a: Atom[_] => JsRaw(parent + ".appendChild(document.createTextNode(" + a.text.encJs + "));").cmd
    case e: scala.xml.Elem =>
      val varName = "v" + Helpers.nextFuncName
      JsCrVar(varName, JsRaw("document.createElement(" + e.label.encJs + ")")) &
              addAttrs(varName, e.attributes.toList) &
              JsRaw(parent + ".appendChild(" + varName + ")") &
              addToDocFrag(varName, e.child.toList)
    case ns: NodeSeq =>
      if (ns.length == 0) Noop
      else if (ns.length == 1) {
        logger.error("In addToDocFrag, got a " + ns + " of type " + ns.getClass.getName)
        Noop
      } else addToDocFrag(parent, ns.toList)

  }.foldLeft(Noop)(_ & _)
}


abstract class JxNodeBase extends Node with JxBase {
}

case class JxAttr(in: JsCmd) extends Node with JxBase {
  def child = Nil

  def appendToParent(parentName: String): JsCmd = {
    Noop
  }
}

case class JxFuncAttr(in: JsCmd) extends Node with JxBase {
  def child = Nil

  def appendToParent(parentName: String): JsCmd = {
    Noop
  }
}

case class JxMap(in: JsExp, what: JxYieldFunc) extends Node with JxBase {
  def child = Nil

  def appendToParent(parentName: String): JsCmd = {
    val ran = "v" + Helpers.nextFuncName
    val fr = "f" + Helpers.nextFuncName
    val cr = "c" + Helpers.nextFuncName
    JsCrVar(ran, in) &
            JsCrVar(fr, what.yieldFunction) &
            JsRaw("for (" + cr + " = 0; " + cr + " < " + ran + ".length; " + cr + "++) {" +
                    parentName + ".appendChild(" + fr + "(" + ran + "[" + cr + "]));" +
                    "}")
  }
}

case class JxCmd(in: JsCmd) extends Node with JxBase {
  def child = Nil

  def appendToParent(parentName: String) = in
}

case class JxMatch(exp: JsExp, cases: JxCase*) extends Node with JxBase {
  def child = Nil

  def appendToParent(parentName: String): JsCmd = {
    val vn = "v" + Helpers.nextFuncName
    JsCrVar(vn, exp) &
            JsRaw("if (false) {\n} " +
                    cases.map {
                      c =>
                              " else if (" + vn + " == " + c.toMatch.toJsCmd + ") {" +
                                      addToDocFrag(parentName, c.toDo.toList).toJsCmd +
                                      "\n}"
                    }.mkString("") +
                    " else {throw new Exception('Unmatched: '+" + vn + ");}")
  }
}

case class JxCase(toMatch: JsExp, toDo: NodeSeq)

case class JxIf(toTest: JsExp, ifTrue: NodeSeq) extends Node with JxBase {
  def child = Nil

  def appendToParent(parentName: String): JsCmd = {
    JsRaw("if (" + toTest.toJsCmd + ") {\n" +
            addToDocFrag(parentName, ifTrue.toList).toJsCmd +
            "}\n")
  }
}

case class JxIfElse(toTest: JsExp, ifTrue: NodeSeq, ifFalse: NodeSeq) extends Node with JxBase {
  def child = Nil

  def appendToParent(parentName: String): JsCmd = {
    JsRaw("if (" + toTest.toJsCmd + ") {\n" +
            addToDocFrag(parentName, ifTrue.toList).toJsCmd +
            "} else {\n" +
            addToDocFrag(parentName, ifFalse.toList).toJsCmd +
            "}\n")
  }
}




case class Jx(child: NodeSeq) extends Node with JxBase with JxYieldFunc {
  def appendToParent(parentName: String): JsCmd =
    addToDocFrag(parentName, child.toList)

  def yieldFunction: JsExp = toJs

  def toJs: JsExp = AnonFunc("it",
    JsCrVar("df", JsRaw("document.createDocumentFragment()")) &
            addToDocFrag("df", child.toList) &
            JsRaw("return df"))


}





© 2015 - 2024 Weber Informatics LLC | Privacy Policy