
net.liftweb.builtin.snippet.Msgs.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 builtin
package snippet
import http._
import scala.xml._
import net.liftweb.util.Helpers._
import net.liftweb.http.js._
import JsCmds._
import net.liftweb.common.{Box, Empty}
import common.Full
import xml.Text
/**
* This built in snippet renders messages (Errors, Warnings, Notices) in a div.
* Typically it is used in templates as a place holder for any messages that are not associated with an ID.
* Setting the attribute showAll to true will render all messages, with and without an ID.
* This will lead to duplicate messages if additionally the Msg built in snippet is used to show
* messages associated with an ID.
*
* E.g. (child nodes are optional)
*
* <lift:Msgs showAll="false">
* <lift:error_msg class="errorBox" >Error! The details are:</lift:error_msg>
* <lift:warning_msg>Whoops, I had a problem:</lift:warning_msg>
* <lift:warning_class>warningBox</lift:warning_class>
* <lift:notice_msg>Note:</lift:notice_msg>
* <lift:notice_class>noticeBox</lift:notice_class>
* </lift:snippet>
*
*
* JavaScript fadeout and effects for the three types of notices (Errors, Warnings and Notices) can
* be configured via LiftRules.noticesAutoFadeOut and LiftRules.noticesEffects. Notices for individual
* elements based on id can be rendered using the <lift:msg/> tag.
*
* @see net.liftweb.builtin.snippet.Msg
* @see net.liftweb.http.LiftRules#noticesAutoFadeOut
* @see net.liftweb.http.LiftRules#noticesEffects
*/
object Msgs extends DispatchSnippet {
// Dispatch to the render method no matter how we're called
def dispatch: DispatchIt = {
case _ => render
}
/**
* This method performs extraction of custom formatting and then
* renders the current notices.
*
* @see #renderNotices()
*/
def render(styles: NodeSeq): NodeSeq = {
// Capture the value for later AJAX updates
ShowAll(toBoolean(S.attr("showAll") or S.attr("showall")))
// Extract user-specified titles and CSS classes for later use
List((NoticeType.Error, MsgsErrorMeta),
(NoticeType.Warning, MsgsWarningMeta),
(NoticeType.Notice, MsgsNoticeMeta)).foreach {
case (noticeType, ajaxStorage) => {
// Extract the title if provided, or default to none. Allow for XML nodes
// so that people can localize, etc.
val title : NodeSeq = (styles \\ noticeType.titleTag).
filter(_.prefix == "lift").flatMap(_.child)
// Extract any provided classes for the messages
val cssClasses = ((styles \\ noticeType.styleTag) ++
(styles \\ noticeType.titleTag \\ "@class")).
toList.map(_.text.trim) match {
case Nil => Empty
case classes => Full(classes.mkString(" "))
}
// Save the settings for AJAX usage
ajaxStorage(Full(AjaxMessageMeta(title,cssClasses)))
}
}
// Delegate the actual rendering to a shared method so that we don't
// duplicate code for the AJAX pipeline
({renderNotices()} % ("id" -> LiftRules.noticesContainerId)) ++
noticesFadeOut(NoticeType.Notice) ++
noticesFadeOut(NoticeType.Warning) ++
noticesFadeOut(NoticeType.Error) ++
effects(NoticeType.Notice) ++
effects(NoticeType.Warning) ++
effects(NoticeType.Error)
}
/**
* This method renders the current notices to XHtml based on
* the current user-specific formatting from the <lift:Msgs> tag.
*/
def renderNotices() : NodeSeq = {
// Determine which formatting function to use based on tag usage
val f =
if (ShowAll.is) {
S.messages _
} else {
S.noIdMessages _
}
// Compute the formatted set of messages for a given input
def computeMessageDiv (args : (List[(NodeSeq,Box[String])],NoticeType.Value,SessionVar[Box[AjaxMessageMeta]])) : NodeSeq = args match {
case (messages,noticeType,ajaxStorage) =>
// get current settings
val title = ajaxStorage.get.map(_.title) openOr Text("")
val styles = ajaxStorage.get.flatMap(_.cssClasses)
// Compute the resulting div
f(messages).toList.map(e => ({e} ) ) match {
case Nil => Nil
case msgList => {
val ret = {title}{msgList}
styles.foldLeft(ret)((xml, style) => xml % new UnprefixedAttribute("class", Text(style), Null))
}
}
}
// Render all three types together
List((S.errors, NoticeType.Error, MsgsErrorMeta),
(S.warnings, NoticeType.Warning, MsgsWarningMeta),
(S.notices, NoticeType.Notice, MsgsNoticeMeta)).flatMap(computeMessageDiv)
}
// This wraps the JavaScript fade and effect scripts into a script that runs onLoad
private[snippet] def tailScript (script : JsCmd) : NodeSeq =
{Script(OnLoad(script))}
/**
* This method produces appropriate JavaScript to fade out the given
* notice type. The caller must provide a default value for cases where
* fadeout is not configured, as well as a wrapping
* function to transform the output.
*
* @see net.liftweb.http.LiftRules.noticesAutoFadeOut
*/
def noticesFadeOut[T](noticeType: NoticeType.Value, default : T, wrap : JsCmd => T): T =
LiftRules.noticesAutoFadeOut()(noticeType) map {
case (duration, fadeTime) => {
wrap(LiftRules.jsArtifacts.fadeOut(noticeType.id, duration, fadeTime))
}
} openOr default
/**
* This method produces an appropriate