|
Lift Framework example source code file (StatefulSnippet.scala)
The Lift Framework StatefulSnippet.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 import net.liftweb.common._ import net.liftweb._ import util._ import Helpers._ import xml.{Text, NodeSeq, Elem} /** * The same StatefulSnippet instance is used across a given page rendering. * <br/> * If the StatefulSnippet is used to render a form, a hidden field is added to * the form that causes the same instance to be used on the page that is the * target of the form submission. * <br/> * If you want to keep the same snippet for a page rendered via a link (<a * href...>) use the StatefulSnippet.link method to create the link. This will * cause the registerThisSnippet method to be called and the same instance will * be used on the target page. * <pre> * class CountGame extends StatefulSnippet { * val dispatch: DispatchIt = { * case "run" => run _ * } * * def run(xhtml: NodeSeq): NodeSeq = { * if (lastGuess == number) { * bind("count", chooseTemplate("choose", "win", xhtml), "number" --> number, "count" --> count) * } else { * bind("count", chooseTemplate("choose", "guess", xhtml), * "input" --> text("", guess _), * "last" --> lastGuess.map(v => if (v < number) v+" is low" else v+"is high").openOr("Make first Guess") * ) * } * * private def guess(in: String) { * count += 1 * lastGuess = Full(toInt(in)) * } * * private val number = 1 + randomInt(100) * private var lastGuess: Box[Int] = Empty * private var count = 0 * * } * </pre> */ trait StatefulSnippet extends DispatchSnippet { private[this] var _names: Set[String] = Set() def addName(name: String) { synchronized { _names = _names + name } } def names: Set[String] = synchronized { _names } def registerThisSnippet() = names.foreach(n => S.overrideSnippetForClass(n, this)) def unregisterThisSnippet() = names.foreach(n => S.unsetSnippetForClass(n)) /** * create an anchor tag around a body * * @to - the target * @param func - the function to invoke when the link is clicked * @param body - the NodeSeq to wrap in the anchor tag * @attrs - the (optional) attributes for the HTML element */ def link(to: String, func: () => Any, body: NodeSeq, attrs: SHtml.ElemAttr*): Elem = SHtml.link(to, () => { registerThisSnippet(); func() }, body, attrs: _*) /** * Redirect to another page, but make sure this StatefulSnippet is registered * on that page so the state continues on the new page */ def redirectTo(where: String): Nothing = S.redirectTo(where, registerThisSnippet) /** * See Other to another page, but make sure this StatefulSnippet is registered * on that page so the state continues on the new page */ def seeOther(where: String): Nothing = S.seeOther(where, registerThisSnippet) /** * Merge the SHtml into the form */ private[http] def mergeIntoForm(isForm: Boolean, res: NodeSeq, toMerge: => NodeSeq): NodeSeq = { val formElem = Helpers.findOption(res){ case e: Elem if e.label == "form" && null == e.prefix=> Some(e) case _ => None } if (formElem.isDefined) { import util.Helpers._ ("form *" #> ((kids: NodeSeq) => toMerge ++ kids))(res) } else if (isForm) { toMerge ++ res } else { res } } } /** * Mix this into a StatefulSnippet if you want a defined render method. */ trait RenderDispatch { /** * The pre-defined dispatch */ def dispatch: PartialFunction[String, NodeSeq => NodeSeq] = Map("render" -> render _) /** * You have to define this method */ def render(in: NodeSeq): NodeSeq } /** * Mix this into a StatefulSnippet if you want a defined render method. Differs * from RenderDispatch because the render method returns a NodeSeq => NodeSeq */ trait RenderFuncDispatch { /** * The pre-defined dispatch */ def dispatch: PartialFunction[String, NodeSeq => NodeSeq] = Map("render" -> render) /** * You have to define this method */ def render: NodeSeq => NodeSeq } /** * The simple composition of StatefulSnippet, Whence and RenderFuncDispatch. * This is the common use of stateful snippets and makes things easier. */ trait SimpleStateful extends StatefulSnippet with Whence with RenderFuncDispatch trait DispatchSnippet { type DispatchIt = PartialFunction[String, NodeSeq => NodeSeq] def dispatch: DispatchIt } /** * Mix this snippet into any snippet. If the snippet is invoked in response to a * stateless request, then the behavior method is called with the method name of * the snippet (usually render, but there may be others if you specify a method * after the snippet name: MySnippet.dothing). */ trait StatelessBehavior { /** * Given the method name, return the transformation for the method */ def statelessDispatch: PartialFunction[String, NodeSeq => NodeSeq] } /** * A simpler way to define behavior if the snippet is invoked. Just implement the stateless method * and all methods for the snippet will use that behavior. */ trait SimpleStatelessBehavior extends StatelessBehavior { def stateless: NodeSeq => NodeSeq def statelessDispatch: PartialFunction[String, NodeSeq => NodeSeq] = { case _ => stateless } } /** * A "default" implementation of StatelessBehavior. Just ignore everything and return a zero-length Text. */ trait BlankStatelessBehavior extends StatelessBehavior { def statelessDispatch: PartialFunction[String, NodeSeq => NodeSeq] = { case _ => _ => NodeSeq.Empty } } Other Lift Framework examples (source code examples)Here is a short list of links related to this Lift Framework StatefulSnippet.scala source code file: |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2024 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.