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

net.liftweb.http.js.jquery.JqJsCmds.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 
package jquery 

import scala.xml.NodeSeq
import net.liftweb.util.Helpers._
import net.liftweb.util.Helpers
import net.liftweb.util.TimeHelpers
import net.liftweb.common._
import net.liftweb.util._

import net.liftweb.http.js.{JsExp, JE}
import JE._
import JsCmds._


/**
 * A singleton that vends various different functions for WiringUI support
 */
object JqWiringSupport {
  import js.JsCmds._
  /**
   * Fade out the old value and fade in the new value
   * using jQuery fast fade.
   */
  def fade: (String, Boolean, JsCmd) => JsCmd = {
    (id: String, first: Boolean, cmd: JsCmd) => {
      if (first) cmd
      else {
        val sel = "jQuery('#'+"+id.encJs+")"
        Run(sel+".fadeOut('fast', function() {"+
            cmd.toJsCmd+" "+sel+".fadeIn('fast');})")
      }
    }
  }

  /**
   * Hide the old value, set to new value and slide down.
   */
  def slideDown: (String, Boolean, JsCmd) => JsCmd = {
    (id: String, first: Boolean, cmd: JsCmd) => {
      if (first) cmd
      else {
        val sel = "jQuery('#'+"+id.encJs+")"
        Run(sel+".hide(); "+cmd.toJsCmd+" "+sel+".slideDown('fast')")
      }
    }
  }

  /**
   * Hide the old value, set to new value and slide down.
   */
  def slideUp: (String, Boolean, JsCmd) => JsCmd = {
    (id: String, first: Boolean, cmd: JsCmd) => {
      if (first) cmd
      else {
        val sel = "jQuery('#'+"+id.encJs+")"
        Run(sel+".hide(); "+cmd.toJsCmd+" "+sel+".slideUp('fast')")
      }
    }
  }

  /**
   * Takes two sequences, the id of a containing component and a couple of
   * functions and generates the jQuery-based JavaScript to update the browser
   * DOM with the deltas between the old list and the new list.
   */
  def calculateDeltas[T](oldList: Seq[T], newList: Seq[T],id: String)(calcId: T => String, calcNodeSeq: T => NodeSeq): JsCmd = 
    calculateDeltas[T](Full(oldList), newList, id)(calcId, calcNodeSeq)

  /**
   * Takes two sequences, the id of a containing component and a couple of
   * functions and generates the jQuery-based JavaScript to update the browser
   * DOM with the deltas between the old list and the new list.
   *
   * @param oldList -- the old list.  If it is Empty, then it is treated as Nil
   * @param newList -- the new version of the list of items
   * @param id -- the id of the enclosing DOM node.  Used for appending and inserting DOM nodes
   * @param calcId -- given a T, calculate the id of the DOM node for the T
   * @param calcNodeSeq -- given a T, calculate the DOM that represents the T
   *
   * @return the JsCmd that inserts, appends, removes, etc. the DOM so that
   * the DOM represents the new List
   */
  def calculateDeltas[T](oldList: Box[Seq[T]], newList: Seq[T],id: String)(calcId: T => String, calcNodeSeq: T => NodeSeq): JsCmd = {
    Helpers.delta(oldList, newList) {
      case RemoveDelta(ci) => new JsCmd {
        def toJsCmd = "jQuery('#'+"+calcId(ci).encJs+").remove();"
      }
      
      case AppendDelta(ci) => 
        new JsCmd {
          val toJsCmd = 
            fixHtmlFunc("inline", calcNodeSeq(ci)) {
              "jQuery('#'+"+id.encJs+").append("+
              _+
              ");"}
        }

      case InsertAtStartDelta(ci) => 
        new JsCmd {
          val toJsCmd = 
            fixHtmlFunc("inline", calcNodeSeq(ci)) {
              "jQuery('#'+"+id.encJs+").prepend("+
              _+
              ");"}
        }

      case InsertAfterDelta(ci, prior) => 
        new JsCmd {
          val toJsCmd = 
            fixHtmlFunc("inline", calcNodeSeq(ci)) {
              "jQuery('#'+"+calcId(prior).encJs+").after("+
              _+
              ");"}
        }
    }
  }
                           
}

/**
 * Contains Scala JsExps for jQuery behaviors.
 *
 * These functions are meant to be combined using the ~> operator. For
 * example:
 *
 *   
JqJE.Jq("button") ~> JqClick(AnonFunc(...))
* * Documentation on the case classes themselves will point to the * relevant jQuery documentation, if there is any. */ object JqJE { /** * Changes the scroll position of each matched element to its maximum. */ case object JqScrollToBottom extends JsExp with JsMember { def toJsCmd = "each(function(i) {this.scrollTop=this.scrollHeight;})" } /** * Calls the jQuery click function with the parameter in exp. * * Used to set a click handler function (also see AnonFunc). * * See http://api.jquery.com/click/ . */ case class JqClick(exp: JsExp) extends JsExp with JsMember { def toJsCmd = "click(" + exp.toJsCmd + ")" } /** * Calls the jQuery attr function with the given key. * * Used to get the value of the given attribute. * * See http://api.jquery.com/attr/ . */ case class JqGetAttr(key: String) extends JsExp with JsMember { def toJsCmd = "attr(" + key.encJs + ")" } /** * Calls the main jQuery (or $) function with the parameter in query. * * Used to get a set of elements to apply the other JqJE expressions to. * * See http://api.jquery.com/jQuery/ . */ case class Jq(query: JsExp) extends JsExp { override def toJsCmd = "jQuery(" + query.toJsCmd + ")" } /** * Calls the main jQuery (or $) function with "document". This returns * the jQueryied document object (e.g., for calling ready()). * * See http://api.jquery.com/jQuery/ . */ case object JqDoc extends JsExp { override def toJsCmd = "jQuery(document)" } /** * For every passed tuple, executes the given JsCmd when the given * Char is pressed by the user. Watches using the jQuery keypress * function. * * See http://api.jquery.com/keypress/ . */ case class JqKeypress(what: (Char, JsCmd)*) extends JsExp with JsMember { override def toJsCmd = "keypress(function(e) {" + what.map { case (chr, cmd) => "if (e.which == " + chr.toInt + ") {" + cmd.toJsCmd + "}" }.mkString(" else \n") + "})" } /** * A JQuery query for an element based on the id of the element */ case class JqId(id: JsExp) extends JsExp { override def toJsCmd = "jQuery('#'+" + id.toJsCmd + ")" } /** * Calls the jQuery attr function with the given key and the given value. * * Used to set the given attribute to the given value. * * See http://api.jquery.com/attr/ . */ case class JqAttr(key: String, value: JsExp) extends JsExp with JsMember { def toJsCmd = "attr(" + key.encJs + ", " + value.toJsCmd + ")" } /** * Calls the jQuery append function with the given content. * * Used to append the given content to the matched elements. * * See http://api.jquery.com/append/ . */ case class JqAppend(content: NodeSeq) extends JsExp with JsMember { override val toJsCmd = "append("+fixHtmlFunc("inline", content){a => a}+")" } /** * Calls the jQuery remove function. * * Used to remove the matched elements from the DOM. * * See http://api.jquery.com/remove/ . */ case class JqRemove() extends JsExp with JsMember { override def toJsCmd = "remove()" } /** * Calls the jQuery appendTo function with the given content. * * Used to wrap the matched elements in the given content. * * See http://api.jquery.com/appendTo/ . */ case class JqAppendTo(content: NodeSeq) extends JsExp with JsMember { override val toJsCmd = "appendTo("+fixHtmlFunc("inline", content){str => str}+ ")" } /** * Calls the jQuery prepend function with the given content. * * Used to prepend the given content to each matched element. * * See http://api.jquery.com/prepend/ . */ case class JqPrepend(content: NodeSeq) extends JsExp with JsMember { override val toJsCmd = "prepend(" + fixHtmlFunc("inline", content){str => str }+ ")" } /** * Calls the jQuery prependTo function with the given content. * * Used to prepend the matched elements to the given content. * * See http://api.jquery.com/prependTo/ . */ case class JqPrependTo(content: NodeSeq) extends JsExp with JsMember { override val toJsCmd = "prependTo(" + fixHtmlFunc("inline", content){str => str} + ")" } /** * Calls the jQuery css function with the given name and value. * * Used to set the value of the given CSS property to the given value. * * See http://api.jquery.com/css/ . */ case class JqCss (name: JsExp, value: JsExp) extends JsExp with JsMember { override def toJsCmd = "css(" + name.toJsCmd + "," + value.toJsCmd + ")" } /** * Calls the jQuery empty function followed by calling the jQuery * after function with the given content. * * The intent is to empty the matched nodes and stick the given * content at their tails. Like a cleaner innerHTML. * * See http://api.jquery.com/empty/ and http://api.jquery.com/after/ . */ case class JqEmptyAfter(content: NodeSeq) extends JsExp with JsMember { override val toJsCmd = "empty().after(" + fixHtmlFunc("inline", content){str => str} + ")" } /** * Calls the jQuery replaceWith function with the given content. * * Used to replace the matched elements with the given content. * * See http://api.jquery.com/replaceWith/ . */ case class JqReplace(content: NodeSeq) extends JsExp with JsMember { override val toJsCmd = fixHtmlCmdFunc("inline", content){"replaceWith(" + _ + ")"} } object JqHtml { /** * Calls the jQuery html function with no parameters. * * Used to get the inner HTML of the matched elements. * * See http://api.jquery.com/html/ . */ def apply(): JsExp with JsMember = new JsExp with JsMember { def toJsCmd = "html()" } /** * Calls the jQuery html function with the given content. * * Used to set the inner HTML of each matched element. * * See http://api.jquery.com/html/ . */ def apply(content: NodeSeq): JsExp with JsMember = new JsExp with JsMember { val toJsCmd = fixHtmlCmdFunc("inline", content){"html(" + _ + ")"} } } object JqText { /** * Calls the jQuery text function with no parameters. * * Used to get the combined text contents of the matched elements. * * See http://api.jquery.com/text/ . */ def apply(): JsExp with JsMember = new JsExp with JsMember { def toJsCmd = "text()" } /** * Calls the jQuery text function with the given content. * * Used to set the text contents of the matched elements. * * See http://api.jquery.com/text/ . */ def apply(content: String): JsExp with JsMember = new JsExp with JsMember { def toJsCmd = "text(" + content.encJs + ")" } } /** * Calls the jQuery serialize function. * * Used to serialize input elements or forms into query string data. * * See http://api.jquery.com/serialize/ . */ case object JqSerialize extends JsExp with JsMember { def toJsCmd = "serialize()" } /** * Calls the jQuery serializeArray function. * * Used to serialize the matched elements into a JSON array containing * objects with name and value properties. * * See http://api.jquery.com/serializeArray/ . */ case object JsonSerialize extends JsExp with JsMember { def toJsCmd = "serializeArray()" } case object JqTabsSelected extends JsExp with JsMember { def toJsCmd = "tabsSelected()" } object JqTabsClick { def apply(tab: JsExp): JsExp with JsMember = new JsExp with JsMember { def toJsCmd = "tabsClick(" + tab.toJsCmd + ")" } def apply(tab: Int): JsExp with JsMember = apply(Num(tab)) } object JqTabs { def apply(in: JsExp): JsExp with JsMember = new JsExp with JsMember { def toJsCmd = "tabs(" + in.toJsCmd + ")" } def apply(): JsExp with JsMember = apply(JsRaw("")) } } object JqJsCmds { implicit def jsExpToJsCmd(in: JsExp) : JsCmd = in.cmd /** * Queues the JavaScript in cmd for execution when the document is * ready for processing */ case class JqOnLoad(cmd: JsCmd) extends JsCmd { def toJsCmd = "jQuery(document).ready(function() {" + cmd.toJsCmd + "});" } /** * Append a NodeSeq to a node specified by uid using jQuery's append() method. */ object AppendHtml { def apply(uid: String, content: NodeSeq): JsCmd = JqJE.JqId(JE.Str(uid)) ~> JqJE.JqAppend(content) } /** * AppendTo a NodeSeq to a node specified by uid using jQuery's appendTo() method. */ object AppendToHtml { def apply(uid: String, content: NodeSeq): JsCmd = JqJE.JqId(JE.Str(uid)) ~> JqJE.JqAppendTo(content) } /** * Prepends a NodeSeq to a node specified by uid using jQuery's prepend() method. */ object PrependHtml { def apply(uid: String, content: NodeSeq): JsCmd = JqJE.JqId(JE.Str(uid)) ~> JqJE.JqPrepend(content) } /** * Replaces the children of the node at { @code uid } with { @code content } */ object EmptyAfter { def apply(uid: String, content: NodeSeq): JsCmd = JqJE.JqId(JE.Str(uid)) ~> JqJE.JqEmptyAfter(content) } /** * Prepends a NodeSeq to a node specified by uid using jQuery prependTo() method. */ object PrependToHtml { def apply(uid: String, content: NodeSeq): JsCmd = JqJE.JqId(JE.Str(uid)) ~> JqJE.JqPrependTo(content) } /** * Replaces the content of the node with the provided id with the markup given by content */ case class JqReplace(uid: String, content: NodeSeq) extends JsCmd { val toJsCmd = (JqJE.JqId(JE.Str(uid)) ~> JqJE.JqReplace(content)).cmd.toJsCmd } /** * Sets the inner HTML of the element denominated by the id */ case class JqSetHtml(uid: String, content: NodeSeq) extends JsCmd { /** * Eagerly evaluate */ val toJsCmd = (JqJE.JqId(JE.Str(uid)) ~> JqJE.JqHtml(content)).cmd.toJsCmd } /** * Show an element identified by uid. * There are two apply methods, one takes just the id, the other takes the id and timespan * that represents how long the animation will last */ object Show { /** * Show an element based on the ID uid */ def apply(uid: String) = new Show(uid, Empty) /** * * Show an element identified by uid * * @param uid the element id * @param time the duration of the effect. */ def apply(uid: String, time: TimeSpan) = new Show(uid, Full(time)) } /** * Show an element identified by uid * * @param uid the element id * @param time the duration of the effect. */ class Show(val uid: String, val time: Box[TimeSpan]) extends JsCmd with HasTime { def toJsCmd = "try{jQuery(" + ("#" + uid).encJs + ").show(" + timeStr + ");} catch (e) {}" } /** * Hide an element identified by uid. * There are two apply methods, one takes just the id, the other takes the id and timespan * that represents how long the animation will last */ object Hide { /** * Hide an element based on the ID uid */ def apply(uid: String) = new Hide(uid, Empty) /** * Hide an element identified by uid * * @param uid the element id * @param time the duration of the effect. */ def apply(uid: String, time: TimeSpan) = new Hide(uid, Full(time)) } /** * Hide an element identified by uid and the animation will last @time */ class Hide(val uid: String, val time: Box[TimeSpan]) extends JsCmd with HasTime { def toJsCmd = "try{jQuery(" + ("#" + uid).encJs + ").hide(" + timeStr + ");} catch (e) {}" } /** * Show a message msg in the element with id where for duration milliseconds and fade out in fadeout milliseconds */ case class DisplayMessage(where: String, msg: NodeSeq, duration: TimeSpan, fadeTime: TimeSpan) extends JsCmd { def toJsCmd = (Show(where) & JqSetHtml(where, msg) & After(duration, Hide(where, fadeTime))).toJsCmd } /** * The companion object to FadeOut that provides an alternative factory */ object FadeOut { /** * Fade Out with the default duration and fadeTime provided by JsRules */ def apply(id: String) = new FadeOut(id, JsRules.prefadeDuration, JsRules.fadeTime) } /** * Fades out the element having the provided id, by waiting * for the given duration and fading out during fadeTime */ case class FadeOut(id: String, duration: TimeSpan, fadeTime: TimeSpan) extends JsCmd { def toJsCmd = (After(duration, JqJE.JqId(id) ~> (new JsRaw("fadeOut(" + fadeTime.millis + ")") with JsMember))).toJsCmd } /** * The companion object to FadeIn that provides an alternative factory */ object FadeIn { /** * Fade In with the default duration and fadeTime provided by JsRules */ def apply(id: String) = new FadeIn(id, JsRules.prefadeDuration, JsRules.fadeTime) } /** * Fades in the element having the provided id, by waiting * for the given duration and fading in during fadeTime * and use @fadeTime */ case class FadeIn(id: String, duration: TimeSpan, fadeTime: TimeSpan) extends JsCmd { def toJsCmd = (After(duration, JqJE.JqId(id) ~> (new JsRaw("fadeIn(" + fadeTime.millis + ")") with JsMember))).toJsCmd } /** * Companion object for ModelDialog that provides two alternative factories */ object ModalDialog { /** * Requires the jQuery blockUI plugin * * @param html the html for the ModalDialog */ def apply(html: NodeSeq) = new ModalDialog(html, Empty) /** * Requires the jQuery blockUI plugin * * @param html the html for the ModalDialog * @param css the css to apply to the dialog */ def apply(html: NodeSeq, css: JsObj) = new ModalDialog(html, Full(css)) } /** * Requires the jQuery blockUI plugin */ class ModalDialog(html: NodeSeq, css: Box[JsObj]) extends JsCmd { /* private def contentAsJsStr = { val w = new java.io.StringWriter S.htmlProperties. htmlWriter(Group(S.session. map(s => s.fixHtml(s.processSurroundAndInclude("Modal Dialog", html))). openOr(html)), w) w.toString.encJs } */ val toJsCmd = fixHtmlCmdFunc("inline", html){str => "jQuery.blockUI({ message: " + str + (css.map(", css: " + _.toJsCmd + " ").openOr("")) + "});"} } /** * Remove the jQuery.Block dialog */ case object Unblock extends JsCmd { def toJsCmd = "jQuery.unblockUI();" } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy