Up: Part II

10 Lift and JavaScript

In this chapter we’ll be discussing some of the techniques that Lift provides for simplifying and abstracting access to JavaScript on the client side. Using these facilities follows Lift’s model of separating code from presentation by allowing you to essentially write JavaScript code in Scala. Lift also provides a layer that allows you to use advanced JavaScript functionality via either the JQuery [T]  [T] http://jquery.com/ or YUI [U]  [U] http://developer.yahoo.com/yui/ user interface libraries.

10.1 JavaScript high level abstractions

You may have noticed that Lift already comes with rich client side functionality in the form of AJAX and COMET support (chapter 11↓). Whenever you use this support, Lift automatically generates the proper <script> elements in the returned page so that the libraries are included. Lift goes one step further, however, by providing a class hierarchy representing JavaScript expressions. For example, with an AJAX form element in Lift the callback method must return JavaScript code to update the client side. Instead of just returning a raw JavaScript string to be interpreted by the client, you return an instance of the JsCmd [V]  [V] net.liftweb.http.js.JsCmd trait (either directly or via implicit conversion) that is transformed into the proper JavaScript for the client.
JsCmd represents a JavaScript command that can be executed on the client. There is an additional “base” trait called JsExp that represents a JavaScript expression.The differences between them are not usually important to the developer, since a JsExp instance is implicitly converted to a JsCmd. Also note that while Lift’s JavaScript classes attempt to keep things type-safe there are some limitations; in particular, Lift can’t check semantic things like whether the variable you’re trying to access from a given JsCmd actually exists. Besides the obvious use in techniques like AJAX and COMET, Lift also makes it simple to attach JavaScript to regular Scala XML objects, such as form fields.
As a simple example, let’s look at how we might add a simple alert to a form if it doesn’t validate. In this example, we’ll assume we have a name form field that shouldn’t be blank. Listing 10.1↓ shows a possible binding from our form snippet. Let’s break this down a bit: the first thing is that in order to reference form elements (or any elements for that matter) from JavaScript, they need to have an id attribute. We add the id attribute to our text field by passing a Pair[String,String]. Next, we need to define our actual validation. We do this by adding some javascript to the onclick attribute of our submit button. The onclick attribute evaluates whatever javascript is assigned when the button is clicked; if the javascript evaluates to true then submission continues. If it evaluates to false then submission is aborted. In our case, we use the JsIf case class to check to see if the value of our myName field is equal to an empty string. In this case the JE object holds an implicit conversion from a Scala string to a Str (JavaScript string) instance. The second argument to JsIf is the body to be executed if the condition is true. In our case we want to pop up an alert to the user and stop form submission. The JsCmd trait (which Alert mixes in) provides a “&” operator which allows you to chain multiple commands together. Here we follow the Alert with a JsReturn, which returns the specified value; again, there’s an implicit conversion from Boolean to JsExp, so we can simply provide the “false” value.
Simple Form Validation
import JsCmds._
import JE._
​
var myName = ""
bind(...
  "name" -> text(myName, myName = _, "id" -> "myName"),
  "submit" -> submit("Save", ..., "onclick" -> 
    JsIf(JsEq(ValById("myName"), ""), 
      Alert("You must provide a name") & JsReturn(false))
    )
)

10.1.1 JsCmd and JsExp overview

If you peruse the Lift API docs you’ll find a large number of traits and classes under the JsCmds and JE objects; these provide the vast majority of the functionality you would need to write simple JavaScript code directly in Lift. Having said that, however, it’s important to realize that the Lift classes are intended to be used for small code fragments. If you need to write large portions of JavaScript code for your pages, we recommend writing that code in pure JavaScript in an external file and then including that file in your pages. In particular, if you write your code as JavaScript functions, you can use the JE.Call class to execute those functions from your Lift code. Table 10.1↓ gives a brief overview of the available JsCmds, while table 10.2↓ shows the JE expression abstractions.
After Executes the given JsCmd fragment after a given amount of time
Alert Corresponds directly to the JavaScript alert function
CmdPair Executes two JsCmd fragments in order
FocusOnLoad Forces focus on the given XML element when the document loads
Function Defines a JavaScript function with name, parameter list, and JsCmd body
JsBreak, JsContinue, JsReturn Corresponds directly to the JavaScript “break”, “continue”, and “return” keywords
JsFor, JsForIn, JsDoWhile, JsWhile These define loop constructs in JavaScript with conditions and execution bodies
JsHideId, JsShowId Hides or shows the HTML element with the given Id. This is actually handled via the LiftArtifacts’ hide and show methods
JsIf Corresponds to the JavaScript “if” statement, with a condition, body to execute if the condition is true, and optional “else” body statement
JsTry Defines a try/catch block tha can optionally alert if an exception is caught
JsWith Defines a with statement to reduce object references
OnLoad Defines a JavaScript statement that is executed on page load
Noop Defines an empty JavaScript statement
RedirectTo Uses window.location to redirect to a new page
ReplaceOptions Replaces options on a form Select with a new list of options.
Run Executes the given string as raw javascript
Script Defines a <script> element with proper CDATA escaping, etc to conform to XHTML JavaScript support
SetElemById Assigns a statement to a given element by id. Optional parameters allow you to specify properties on the element
SetExp Defines an assignment to an arbitrary JavaScript expression from another JavaScript expression
SetHtml Sets the contents of a given HTML node by Id to a given NodeSeq. This is especially useful in Ajax calls that update parts of the page
SetValById Defines an assignment to a given element’s “value” property
Table 10.1 Basic JsCmds
AnonFunc Defines an anonymous JavaScript function
Call Calls a JavaScript function by name, with parameters
ElemById Obtains a DOM element by its Id, with optional property access
FormToJson Converts a given form (by Id) into a JSON representation
Id, Style, Value Represents the “id”, “style” and “value” element attributes
JsArray Constructs a JavaScript array from a given set of JavaScript expressions
JsEq, JsNotEq, JsGt, JsGtEq, JsLt, JsLtEq Comparison tests between two JavaScript expressions. JsExp instances also have a “===” operator which is equivalent to JsEq
JsTrue, JsFalse, JsNull Represents the “true”, “false”, and “null” values
JsFunc Similar to Call; executes a JavaScript function
JsObj Represents a JavaScript object with a Map for properties
JsRaw Represents a raw JavaScript fragment. You can use this if Lift doesn’t provide functionality via abstractions
JsVal Represents an abritrary JavaScript value
JsVar Represents a JavaScript variable, with optional property access
Num Represents a JavaScript number. JE contains implicit conversions from Scala numeric types to Num
Str Represents a Javascript String. JE contains implicit conversions from a Scala String to Str
Stringify Calls JSON.stringify to convert a JavaScript object into a JSON string representation
ValById Represents the “value” property of a given element by Id
Table 10.2 Basic JE abstractions

10.1.2 JavaScript Abstraction Examples

As you can see, Lift provides a large coverage of JavaScript functionality through its abstraction layer. Even if you’ve done a lot of JavaScript, however, the abstractions don’t always map one-to-one and it can take some effort to wrap your head around it. We’re going to provide a few examples to help you understand how it works. We’ll start off with a simple example of an Ajax callback (Ajax is covered in chapter 11↓). Listing 10.1.2↓ shows how we can update an HTML element with new content via the Ajax call. In this case, we’re changing a chart image based on some passed parameters. Our HTML needs to contain an element with an id of “tx_graph”; this element will have its children replaced with whatever NodeSeq we pass as the second argument.
Using SetHtml
def updateGraph() = {
  val dateClause : String = ...
  val url = "/graph/" + acctName + "/" + graphType + dateClause
  JsCmds.SetHtml("tx_graph", <img src={url} />)
}
As a more complex example, we could add some JavaScript behavior combining Ajax with some client-side state, as shown in listing 10.1.2↓.
Client-side comparisons
import js.JE._ // for implicit conversions
def moreComplexCallback (value : String) = {
  JsIf(ValById("username") === value.toLowerCase, {
    JsFunc("logAccess", "Self-share attempted").cmd & Alert("You can’t share with yourself!")
  })
}

10.2 JQuery and other JavaScript frameworks

We’ve mentioned earlier that Lift uses the JQuery JavaScript framework by default. Lift wouldn’t be Lift, however, if it didn’t provide a mechanism for using other frameworks. The way that lift determines which JavaScript framework to use is via the JSArtifacts [W]  [W] net.liftweb.http.js.JSArtifacts trait along with the LiftRules.jsArtifacts var. Lift comes with two default implementations of JSArtifacts: JQueryArtifacts [X]  [X] net.liftweb.http.js.jquery.JQueryArtifacts and YUIArtifacts [Y]  [Y] net.liftweb.http.js.yui.YUIArtifacts. If you want to use a different framework, you must provide a concrete implementation of the JSArtifacts trait specific to that framework. The JQuery support in Lift extends beyond just the JSArtifacts, support; there are also a number of JSExp and JsCmd traits and classes in the net.liftweb.http.js.jquery package that provide JQuery specific implementations for standard expressions and commands.
Changing one implementation or another can be done from LiftRules.jsArtifacts variable, which by default points to JQueryArtifacts. Typically this is done in Boot, as shown in listing 10.2↓.
Configuring Lift YUI
 import net.liftweb.http.js.yui.YUIArtifacts      
       
 class Boot {      
   def boot = {      
     ...      
     LiftRules.jsArtifacts = YUIArtifacts      
     ...     
 }  
In addition to changing LiftRules, you also need to take into account that other frameworks have their own scripts and dependencies that you’ll need to include in your pages. For YUI you would need to include the following scripts (at minimum):
Lift YUI scripts
 <script src="/classpath/yui/yahoo.js" type="text/javascript"/>
 <script src="/classpath/yui/event.js" type="text/javascript"/>   
 <script src="/classpath/yui/dom.js" type="text/javascript"/>   
 <script src="/classpath/yui/connection.js" type="text/javascript"/>   
 <script src="/classpath/yui/json.js" type="text/javascript"/>   
 <script src="/classpath/liftYUI.js" type="text/javascript"/>
Of course, to keep things simple you could either place all of these items in a template that you could embed, or you could combine the files into a single JavaScript source file.
We have some simple recommendations on using different JavaScript frameworks from within Lift:
  1. If you don’t necessarily need YUI widgets or if you can find similar functionality in JQuery plugins, we recommend using the JQuery framework. Lift provides much better support out-of-the-box for JQuery
  2. Do not mix JQuery and YUI unless you really know what you are doing. Getting both of them together leads to a number of collisions.

10.3 XML and JavaScript

What we’ve covered so far is pretty much standard JavaScript behind some Lift facades. There are situations, however, when you want to do things that are complicated or outside the scope of typical JavaScript functionality. One example of this is when you need to build dynamic DOM elements from JavaScript code, say to build an HTML list. Lift has a very nice way of dealing with such situation; with a few lines of code you can achieve quite a lot. The main functionality for this is provided via the Jx* classes [Z]  [Z] net.liftweb.http.js.Jx, etc, which you can use to transform a scala.xml.NodeSeq into javascript code that generates the corresponding nodes on the client side. Listing 10.3↓ shows a simple example of emitting a div on a page via JavaScript.
Jx trivial example
 import net.liftweb.http.js._ 
 import JE._
​
 val div = Jx(<div>Hi there</div>)
This code generates the following JavaScript code:
Jx Emitted Code
function(it) {
  var df = document.createDocumentFragment();
  var vINIJ1YTZG5 = document.createElement(’div’);
  df.appendChild(vINIJ1YTZG5);
  vINIJ1YTZG5.appendChild(document.createTextNode(’Hi there’));
  return df;
}
As you can see, Lift took our XML code and transformed it into a JavaScript function that dynamically creates a document fragment containing the given NodeSeq. The it parameter can be any JavaScript object; we’ll cover how you use it in a moment. The name of the var is automatically and randomly generated to ensure uniqueness.
Of course, if that was all Lift was doing that’s not much help. At this point we’ve only generated a function that generates XML. Let’s take a look on a more complex example that shows the real power of the Jx classes. Assume we have a JSON structure that contains an array of objects containing firstName and lastName properties. This JSON structure could look something like:
Sample JSON Structure
var list = {
    persons: [
        {name: "Thor", race: "Asgard"}, 
        {name: "Todd", race: "Wraith"}, 
        {name: "Rodney", race: "Human"}
    ]
}
// Guess what I’ve been watching lately ?
Now we can use a combination of Jx classes to render this content as an HTML dynamic list:
Rendering a JSON List Via Jx
def renderPerson = 
  Jx(<li class="item_header"> {JsVar("it", "name")} 
       is {JsVar("it", "race")}</li>)
Jx(<ul>{JxMap(JsVar("it.persons"), renderPerson)}</ul>)
Well what this code does is this:
  1. Construct an <ul> list that contains a bunch of elements
  2. JxMap takes a JavaScript object, in this case it.persons (remember it is the parameter of the generated function), and iterate for each element of the array and apply the renderPerson function. Of course each element of the array will be a JSON object containing name and race properties.
  3. The renderPerson function generates a JavaScript function as we’ve already shown, and renders the JavaScript code that generates the <li> elements containing the name value followed by “is” followed by the race value.
  4. If we send this generated JavaScript function to client and calling it by pass the list variable above It will create the following document fragment:
<ul>
 <li class="item_header">Thor is Asgard</li>
 <li class="item_header">Todd is Wraith</li>
 <li class="item_header">Rodney is Human</li>
</ul>
With a couple of lines of code we’ve managed to generate the JavaScript code that creates document fragments dynamically. Here is the list of JX classes that you may find interesting:
Class Description
JxBase The parent trait for all other Jx classes
JxMap Iterates over a JavaScript array and applies a function on each element
JxMatch Match a JsExp against a sequence of JsCase
JxCase Contains a JsExp for matching purposes and the NodeSeq to be applied in case the matching succeeds
JxIf Contains a JsExp and a NodeSeq to be applied only if JsExp is evaluated to true
JxIfElse Similar with JxIf but it contains the else branch
Jx The basic application of the transformation from a NodeSeq to the JavaScript code

10.4 JSON

JSON [A]  [A] Java Script Object Notation - http://www.json.org is a way of structuring information in JavaScript code. One of its most common uses is to represent structured information on the wire. One example would be a JavaScript AJAX API where the server response is in fact a JSON construct. Let’s look at an example first in listing 10.4↓:
Ajax JSON response
 class SimpleSnippet {
  def ajaxFunc() : JsCmd = {
    JsCrVar("myObject", JsObj(("persons", JsArray(
        JsObj(("name", "Thor"), ("race", "Asgard")),
        JsObj(("name", "Todd"), ("race", "Wraith")),
        JsObj(("name", "Rodney"), ("race", "Human"))
    )))) & JsRaw("alert(myObject.persons[0].name)")
  }
​
  def renderAjaxButton(xhtml: Group): NodeSeq = {
    bind("ex", xhtml,         
            "button" -> SHtml.ajaxButton(Text("Press me"), ajaxFunc _))
  }
 }
Your template would look like listing 10.4↓:
AJAX Template
    ...
    <lift:SimpleSnippet.renderAjaxButton>
        <ex:button/>
    </lift:SimpleSnippet.renderAjaxButton>
    ...
First off, we have a simple snippet function called renderAjaxButton. Here we’re binding the ex:button tag and render a XHTML button tag that when pressed will send an Ajax request to server. When this request is received, the ajaxFunc is executed and the JsCmd response is turned into a JavaScript content type response. In ajaxFunc we construct a JSON object (the same one we used previously for the persons object). We assign the JSON structure to the JavaScript variable myObject and them call alert on the first element on the persons object. The rendered JavaScript code that will be send down the wire will be:
Generated JavaScript
var myObject = {’persons’: [{’name’: ’Thor’, ’race’: ’Asgard’}, 
                            {’name’: ’Todd’, ’race’: ’Wraith’} , 
                            {’name’: ’Rodney’, ’race’: ’Human’}]}; 
alert(myObject.persons[0].name);
So in your page when you press the button you’ll get an alert dialog saying “Thor”. Here we used the JsRaw class which basically renders the exact thing you passed to it: raw JavaScript code.

10.4.1 JSON forms

Now that we’ve covered sending JSON from the server to the client, let’s look at going in the opposite direction. Lift provides a mechanism for sending form data to the server encapsulated in a JSON object. In and of itself sending the data in JSON format is relatively simple; where Lift really adds value is via the JsonHandler [B]  [B] net.liftweb.http.JsonHandler class. This class provides a framework for simplifying processing of submitted JSON data. To start, let’s look at some example template code for a JSON form:
A Simple JSON form
<lift:surround with="default" at="content">      
    <lift:JSONForm.head />      
    <lift:JSONForm.show>
      <input type="text" name="name" />
      <br />
      <input type="text" name="value" /> 
      <br />  
      <input type="radio" name="vehicle" value="Bike" /> 
      <input type="radio" name="vehicle" value="Car" /> 
      <input type="radio" name="vehicle" value="Airplane" /> 
      <br /> 
      <select name="cars">
        <option value="volvo">Volvo</option> 
        <option value="saab">Saab</option> 
        <option value="opel">Opel</option>  
        <option value="audi">Audi</option>  
      </select>
      <button type="submit">Submit</button>
    </lift:JSONForm.show>
    <div id="json_result"></div> 
</lift:surround>
A you can see, the XHTML template is relatively straightforward. The Snippet code is where things really get interesting:
JSON Form Snippet Code
class JSONForm {      
    def head = 
    <head>
    <script type="text/javascript" 
            src={"/" + LiftRules.resourceServerPath + "/jlift.js"} />
    {Script(json.jsCmd)}
    </head> 
   
    def show(html: Group): NodeSeq = {
        SHtml.jsonForm(json, html) 
    } 
​
    import JsCmds._ 
    object json extends JsonHandler {
        def apply(in: Any): JsCmd = SetHtml("json_result", in match { 
            case JsonCmd("processForm", _, p: Map[String, _], _) => {
                // process the form or whatever 
                println("Cars = " + urlDecode(p("cars"))) 
                println("Name = " + urlDecode(p("name"))) 
                <b>{p}</b> 
            }
            case x => <b>Problem... didn’t handle JSON message {x}</b>
        })
    }
}  
The first thing we define is the head function. Its purpose is simply to generate the JavaScript functions that set up the form handling on the client side. That means that when the submit button is clicked, the contents of the form are turned into JSON and submitted via an Ajax call to the server. The show function defines the connection between the concrete JsonHandler instance that will process the form and the template HTML that contains the form. We perform this binding with the SHtml.jsonForm method. This wraps the HTML with a <form> tag and sets the onsubmit event to do JSON bundling.
The key part of the equation is our JsonHandler object. The apply method is what will be called when the JSON object is submitted to the server. If the JSON is properly parsed then you’ll get a JsonCmd instance which you can use Scala’s matching to pick apart. The apply function needs to return a JsCmd (JavaScript code), which in this case sets the HTML content of the json_result div element. When the form is stringified into its JSON representation Lift uses a command property indicating the action that needs to be done on server and the actual JSON data. In the case of JSON forms the command is always “processForm” as this is important for pattern matching as seen above. The actual form content is a Map object that can be easily use to obtain the values for each form field.

10.5 JqSHtml object

SHtml generated code is independent on the JavaScript framework used. However net.liftweb.http.jquery.JsSHtml object contains artifacts that are bound with JQuery framework. For instance it contains the autocomplete function that renders an input type text element but when start typing it will suggest words starting with what you typed already. Please see http://www.pengoworks.com/workshop/jquery/autocomplete.htm for examples.

10.6 A recap

We’ve seen so far how we can abstract JavaScript code at Scala level using Lift’s JS abstraction. You can model endless cases by using these abstractions. But let’s take a look on another example a bit more complex. It is about a fast search where you have a text box and when you hit enter it will return the list of items that contain that sequence. The list of items will be rendered in a DIV real estate.
Example template
​
<lift:surround with="default" at="content">
  <lift:Hello.ajaxian>            
    <text:show/>    
  </lift:Hello.ajaxian>      
  <div id="items_list" style="width: 300px; height: 100px; overflow: auto; border: 1px solid black;">   
  </div>    
</lift:surround>
So we just have a really simple snippet and the div placeholder.
Example snippet
​
import JE._   
import net.liftweb.http.js.jquery.JqJE._      
import net.liftweb.http.SHtml._ 
import net.liftweb.util.Helpers._
import JsCmds._ 
​
val names = "marius" :: "tyler" :: "derek" :: "dave" :: "jorge" :: "viktor" :: Nil  
​
def ajaxian(html: Group) : NodeSeq = {
    bind("text", html,
            "show"  -> ajaxText("Type something", {value => {
               val matches = names.filter(e => e.indexOf(value) > -1)
               SetHtml("items_list", NodeSeq.Empty) & 
               JsCrVar("items", JsArray(matches.map(Str(_)):_*)) &
               JsCrVar("func", Jx(<ul>{
                                    JxMap(JsVar("it"), Jx(<li><a href="">{JsVar("it")}</a></li>))                                   }                                    </ul>).toJs) &
               (ElemById("items_list") ~> JsFunc("appendChild", Call("func", JsVar("items"))))
             }})
    )
} 
The part with the snippet is probably already familiar to you. We are calling the ajaxText function which renders an input text element. When you hit enter an Ajax request will be sent and the anonymous function that we bound here will be executed. Here is what happens:
  1. First filter out the names that contain the provided value in the input text. So all element that contain that sequence.
  2. Then return a JsExp that we are building:
    1. SetHtml is clearing out the div element that we’re using as a real estate for our search results list
    2. Then we re declaring a JavaScript variable which is an array containing the resulting items that matched the search criteria.
    3. Then we are declaring thr func variable which obviously is a function. We’ve seen above how to use the Jx artifacts. Now we are building a html list (<ul>) that for each element from the it variable will build the <li> sequences. The it variable is actually the paramter that this function takes which is the items array that we declared above.
    4. After that we are obtaining the HTML node denominated by “items_list” id and call appendChild function of the Node object. The ~> function is use to call functions of objects. Of course to the appendChild function we need to provide a parameter. This parameter is the document fragment returned by func function. When we are caling the func function we are passing items variable decalred above.
As you noticed already we composed a small JavaScript code by chainin multiple JS expressions/commands using the & function.
Up: Part II

(C) 2012 Lift 2.0 EditionWritten by Derek Chen-Becker, Marius Danciu and Tyler Weir