Skip to content

Commit

Permalink
Merge branch 'guillaume_master' into v0.3.2.1
Browse files Browse the repository at this point in the history
Closes #56

* guillaume_master:
  demo: New demo page layout, CodeMirror syntax highlighting
  demo: New `navigable` surround template for doc pages
  demo: Boot.scala: def boot -> boot()
  demo: Bootstrap navigation; hero unit on index.html
  demo: Remove SyntaxHighlighter, old menu.css
  demo: templates-hidden/default: move some scripts from head to end of body
  demo: templates-hidden/default: move some inline css to new style/doc.css
  demo: Convert buttons to links
  demo: templates-hidden/default: install 3rd part assets
  demo: Add 3rd part web assets
  demo: Switch to HTML5
  • Loading branch information
nafg committed Jun 9, 2013
2 parents 45de57d + c4c1039 commit 2166e8c
Show file tree
Hide file tree
Showing 61 changed files with 13,968 additions and 2,757 deletions.
Expand Up @@ -13,7 +13,7 @@ import reactive.web.widgets.Messages
* to modify lift's environment
*/
class Boot {
def boot {
def boot() {
println("In boot")
getClass.getClassLoader match {
case rcl: java.net.URLClassLoader =>
Expand All @@ -30,6 +30,7 @@ class Boot {

// where to search snippets
LiftRules.addToPackages("reactive.web.demo")
LiftRules.addToPackages("com.damianhelme.tbutils")

reactive.web.Reactions.init(comet = true)
Messages.init(Messages.template("alert"))
Expand Down Expand Up @@ -73,5 +74,11 @@ class Boot {
}
LiftRules.excludePathFromContextPathRewriting.default.set{ _: String => true }
LiftRules.useXhtmlMimeType = false

LiftRules.htmlProperties.default.set( (r: Req) =>
new Html5Properties(r.userAgent)
)

LiftRules.early.append( _.setCharacterEncoding("UTF-8") )
}
}
@@ -0,0 +1,163 @@
package com.damianhelme.tbutils.snippet

// found here:
// https://github.com/dph01/lift-TBUtils
// FIXME: to lazy to add in dependency

import scala.xml._
import net.liftweb.util.Helpers._
import scala.xml.transform._
import net.liftweb.common.Logger

object TBNav extends Logger {

/* Transforms the XML produced by Menu.build such that any menus defined as:
Menu("Test") / "test" >> LocGroup("test") >> PlaceHolder submenus (
Menu("Test 2") / "test2",
Menu("Test 3") / "test3"
),
or
Menu("Test") / "test" >> LocGroup("test") >> submenus (
Menu("Test 2") / "test2",
Menu("Test 3") / "test3"
),
will be transformed into Twitter Bootstrap dropdown menus
*/



def menuToTBNav( in: NodeSeq ) : NodeSeq = {

object t1 extends RewriteRule {
override def transform(n: Node): Seq[Node] = n match {

// removes the white space which appears between elements
case Text(text) if ( text.matches("\\s+") ) => NodeSeq.Empty

/* matches xml of the format:
*<li>
<span>Test</span>
<ul>
<li>
<a href="/test2">Test 2</a>
</li>
<li>
<a href="/test3">Test 3</a>
</li>
</ul>
</li>
and transforms it to:
<li class="dropdown" >
<a class="dropdown-toggle" data-toggle="dropdown" >Test<b class="caret"></b></a>
<ul class="dropdown-menu">
<li>
<a href="/test2">Test 2</a>
</li>
<li>
<a href="/test3">Test 3</a>
</li>
</ul>
</li>
*/
case li @ Elem(liPrefix, "li", liAttribs, liScope,
span @ Elem(spanPrefix,"span",spanAttribs,spanScope,spanChildren @ _*),
ul @ Elem(ulPrefix,"ul",ulAttribs,ulScope,ulChildren @ _*),
other @ _* ) => {

// create a new node seq with modified attributes
Elem(liPrefix,"li",newLiAttribs(liAttribs),liScope,
Elem(spanPrefix, "a", newAAttribs(spanAttribs), spanScope, newAChildren(spanChildren): _*) ++
Elem(ulPrefix, "ul", newUlAttribs(ulAttribs), ulScope, ulChildren: _*) ++
other: _*)
}

/* matches xml of the format:
*<li>
<a href="/test">Test</a>
<ul>
<li>
<a href="/test2">Test 2</a>
</li>
<li>
<a href="/test3">Test 3</a>
</li>
</ul>
</li>
and transforms it to:
<li class="dropdown" >
<a class="dropdown-toggle" data-toggle="dropdown" >Test<b class="caret"></b></a>
<ul class="dropdown-menu">
<li>
<a href="/test2">Test 2</a>
</li>
<li>
<a href="/test3">Test 3</a>
</li>
</ul>
</li>
*/
case li @ Elem(liPrefix, "li", liAttribs, liScope,
a @ Elem(aPrefix,"a",aAttribs,aScope,aChildren @ _*),
ul @ Elem(ulPrefix,"ul",ulAttribs,ulScope,ulChildren @ _*),
other @ _* ) => {

// create a new node seq with modified attributes
Elem(liPrefix,"li",newLiAttribs(liAttribs),liScope,
Elem(aPrefix, "a", newAAttribs(aAttribs), aScope, newAChildren(aChildren): _*) ++
Elem(ulPrefix, "ul", newUlAttribs(ulAttribs), ulScope, ulChildren: _*) ++
other: _*)
}
case other @ _ => other
}
}

// debug("menuToTBNav received: " + new PrettyPrinter(80,3).formatNodes(in))
object rt1 extends RuleTransformer(t1)
val out = rt1.transform(in)
// debug("menuToTBNav out: " + new PrettyPrinter(80,3).formatNodes(out))
out
}

/*
* an attempt at using CSS selectors rather than XML Transform - TBC
def menuToTBNav(in: NodeSeq) : NodeSeq = {
def testNode(ns: NodeSeq, cssSel: String): Boolean = {
var ret = false // does the NodeSeq have any nodes that match the CSS Selector
(cssSel #> ((ignore: NodeSeq) => {ret = true; NodeSeq.Empty}))(ns)
ret
}
def childHasUI(ns: NodeSeq) : Boolean = {
true
}
val f = "li [class+]" #>
(((ns: NodeSeq) => Some("dropdown").filter(ignore => childHasUI(ns))): IterableFunc )
f(in)
}
*/

// utility methods to add the Bootstrap classes to existing attributes
def newLiAttribs(oldAttribs: MetaData) = appendToClass(oldAttribs,"dropdown")
def newAAttribs(oldAttribs: MetaData) = appendToClass(oldAttribs,"dropdown-toggle")
.append("data-toggle" -> "dropdown")
def newUlAttribs(oldAttribs: MetaData) = appendToClass(oldAttribs,"dropdown-menu")
def newAChildren(oldChildren: NodeSeq) = oldChildren ++ <b class="caret"></b>



// append a new value to the class attribute if one already exists, otherwise create a new class
// with the given value
def appendToClass(attribs: MetaData, newClass: String ) : MetaData = {
// Note that MetaData.get("class") returns a Option[Seq[Node]] , not Option[Node] as might be expected
// for an explanation of why see the scala-xml book:
val oldClass : Option[String] = attribs.get("class").map(_.mkString).filterNot(_ == "")
val resultingClass = oldClass.map( _.trim + " ").getOrElse("") + newClass
attribs.append("class" -> resultingClass)
}

}
@@ -0,0 +1,67 @@
package net.liftweb.doc.snippet


/*
once again to lazy to add depedency
https://github.com/MasseGuillaume/lift-doc
*/

import net.liftweb.util.Helpers._
import net.liftweb.http.LiftRules
import net.liftweb.common.{ Failure, Full }

import xml.{NodeSeq, Elem}
import net.liftweb.util.Helpers


object CodeInjection
{

def render( path: String ) = {

for {
( code, fileName, fileExtension ) <- openTemplate( path )
out = (
fileExtension match {
case "scala" => renderCodeMirror( code, fileName, fileExtension )
case "html" => renderCodeMirror( code, fileName, fileExtension )
case _ => <pre> { code } </pre>
}
)
} yield out
}

def openTemplate( path: String ) =
{
for {
fileName <- Full( path.split('/').last ) ?~ ( "cannot parse a filename: " + path )
fileExtension <- Full( fileName.split('.').last ) ?~ ( "cannot parse a file extension: " + fileName )
code <- LiftRules.loadResourceAsString( path ) ?~ ( "template: " + path + " not found" )
} yield ( code, fileName, fileExtension )
}

def renderCodeMirror( code:String, fileName:String, fileExtension:String ) : Elem = {

val guid = Helpers.nextFuncName

val mode = fileExtension match {
case "scala" => "text/x-scala"
case "html" => "text/html"
}

<lift:children>
<textarea id={guid}>{code}</textarea>
<script>
$(function(){{
CodeMirror.fromTextArea( document.getElementById("{guid}"), {{
lineNumbers: true,
readOnly: true,
mode: "{mode}",
theme: "solarized-dark"
}})
}})
</script>
<label for={guid}>{ fileName }</label>
</lift:children>
}
}
Expand Up @@ -16,6 +16,7 @@ import net.liftweb.common._
import net.liftweb.sitemap._
import Loc._

import net.liftweb.doc.snippet.CodeInjection

object DemoPane {
val menu = Menu.param[String]("ShowDemo","ShowDemo",Full(_),s=>s) /"showdemo" >>Hidden
Expand All @@ -24,15 +25,21 @@ object DemoPane {
def render(xhtml: NodeSeq) = (
for {
snippetName <- S.attr("snippet") or loc.currentValue
codePath = "/scala-sources/reactive/web/demo/snippet/" + snippetName + ".scala"
htmlPath = "/templates-hidden/" + snippetName.toLowerCase
layout <- Templates(List("templates-hidden", "demopanelayout"))
scalaSource = scala.io.Source.fromInputStream(
getClass.getResourceAsStream("/scala-sources/reactive/web/demo/snippet/" + snippetName + ".scala")
)
template = Templates(List("templates-hidden", snippetName.toLowerCase)) openOr xhtml
template = Templates(htmlPath.split("/").toList) openOr xhtml
templateHtmlTransform = CodeInjection.render(htmlPath + ".html")
.map(".template *" #> _)
.openOr(
"#template-code" #> NodeSeq.Empty & // remove place for html
"#demo [class!]" #> "span6" & // if not found
"#demo [class+]" #> "span12"
)
bind = ".demo [class]" #> ("lift:" + snippetName) &
".demo *" #> template &
".template *" #> <pre class="brush: xml">{template.toString}</pre> &
".snippet *" #> <pre class="brush: scala">{scalaSource.getLines().mkString("\n")}</pre>
".snippet *" #> CodeInjection.render(codePath) &
templateHtmlTransform
} yield bind(layout)
) openOr NodeSeq.Empty
}
22 changes: 11 additions & 11 deletions reactive-web-demo/src/main/webapp/core/EventStream.html
@@ -1,4 +1,4 @@
<div class="lift:surround?with=default;at=content">
<div class="lift:surround?with=navigable;at=content">

<h2>EventStream</h2>
<h3>Introduction</h3>
Expand All @@ -25,7 +25,7 @@ <h3>Creating an <code>EventStream</code></h3>
(it extends <code>EventStream</code>).
You can then send events by calling <code>fire</code>.</p>

<button onclick="showdemo('EventStream_EventSource')">Live Example</button>
<a class="btn btn-primary" target="_blank" href="/showdemo/EventStream_EventSource">Live Example</a>

<p>Of course, you also create a new <code>EventStream</code> every
time you call one of the transforming methods (below). And there's <code>Timer</code>.</p>
Expand All @@ -36,7 +36,7 @@ <h3><code>Timer</code></h3>
values are based on the time when they are fired, not when they were
scheduled to fire.</p>

<button onclick="showdemo('EventStream_Timer')">Live Example</button>
<a class="btn btn-primary" target="_blank" href="/showdemo/EventStream_Timer">Live Example</a>


<h3>Adding listeners: <code>foreach</code></h3>
Expand Down Expand Up @@ -64,7 +64,7 @@ <h3>Adding listeners: <code>foreach</code></h3>
class extend <code>Observing</code> (since it contains an implicit
reference to itself).</p>

<button onclick="showdemo('EventStream_foreach')">Live Example</button>
<a class="btn btn-primary" target="_blank" href="/showdemo/EventStream_foreach">Live Example</a>

<h3>Transformations</h3>
<p>What makes <code>EventStream</code>s very versatile is their set
Expand Down Expand Up @@ -102,7 +102,7 @@ <h3>Finer-grained lifetime control: <code>takeWhile</code></h3>
<p>Idiomatic code should not cause side effects in the predicate;
however there's nothing stopping you from doing so if you so desire.</p>

<button onclick="showdemo('EventStream_takeWhile')">Live Example</button>
<a class="btn btn-primary" target="_blank" href="/showdemo/EventStream_takeWhile">Live Example</a>

<h3>What's the point?</h3>
<p>At this point you may be wondering why go through all these
Expand Down Expand Up @@ -138,7 +138,7 @@ <h3>A more focused <code>EventStream</code>: <code>filter</code></h3>
to obtain a new <code>EventStream</code> that fires only those events
which the predicate matches.</p>

<button onclick="showdemo('EventStream_filter')">Live Example</button>
<a class="btn btn-primary" target="_blank" href="/showdemo/EventStream_filter">Live Example</a>

<h3>A completely transformed <code>EventStream</code>: <code>map</code></h3>
<p>Another fundamental collections method is <code>map</code>. It
Expand All @@ -151,7 +151,7 @@ <h3>A completely transformed <code>EventStream</code>: <code>map</code></h3>
fires, the new <code>EventStream</code> will fire an event whose value
is the result of applying the function to the parent's event.</p>

<button onclick="showdemo('EventStream_map')">Live Example</button>
<a class="btn btn-primary" target="_blank" href="/showdemo/EventStream_map">Live Example</a>

<h3>Combined <code>filter</code> and <code>map</code>: <code>collect</code></h3>
<p>For convenience, <code>EventStream</code> has a <code>collect</code>
Expand Down Expand Up @@ -224,7 +224,7 @@ <h3>Switching <code>EventStream</code>s: <code>flatMap</code></h3>
<p>You can also <code>flatMap</code> a <code>Signal</code> to
<code>EventStream</code>s. See <a href="Signal#flatMap">here</a>.</p>

<button onclick="showdemo('EventStream_flatMap')">Live Example</button>
<a class="btn btn-primary" target="_blank" href="/showdemo/EventStream_flatMap">Live Example</a>

<h3><a id="foldLeft">Passing state: <code>foldLeft</code></a></h3>
<p>What if you need the way you handle events to depend on various
Expand Down Expand Up @@ -253,7 +253,7 @@ <h3><a id="foldLeft">Passing state: <code>foldLeft</code></a></h3>
next function invocation). we can create an <code>EventStream</code>
that, whenever a number is fired, fires the average value:</p>

<button onclick="showdemo('EventStream_foldLeft')">Live Example</button>
<a class="btn btn-primary" target="_blank" href="/showdemo/EventStream_foldLeft">Live Example</a>

<h3>Combining <code>EventStream</code>s: <code>|</code></h3>
<p>You can also get the union of two <code>EventStreams</code>. The
Expand All @@ -264,7 +264,7 @@ <h3>Combining <code>EventStream</code>s: <code>|</code></h3>
val allClicks = leftClicks | middleClicks | rightClicks
</pre>

<button onclick="showdemo('EventStream_union')">Live Example</button>
<a class="btn btn-primary" target="_blank" href="/showdemo/EventStream_union">Live Example</a>


<h3>Turning an <code>EventStream</code> into a <code>Signal</code>:
Expand All @@ -273,7 +273,7 @@ <h3>Turning an <code>EventStream</code> into a <code>Signal</code>:
via the <code>hold</code> method. You have to pass it an initial value
for the signal to hold until the next event fires.</p>

<button onclick="showdemo('EventStream_hold')">Live Example</button>
<a class="btn btn-primary" target="_blank" href="/showdemo/EventStream_hold">Live Example</a>

<h3>Preventing infinite loops: <code>nonrecursive</code></h3>
<p>If an <code>EventStream</code> firing can result in that <code>EventStream</code>
Expand Down
2 changes: 1 addition & 1 deletion reactive-web-demo/src/main/webapp/core/Forwardable.html
@@ -1,4 +1,4 @@
<div class="lift:surround?with=default;at=content">
<div class="lift:surround?with=navigable;at=content">

<h2>Forwardable</h2>
<p>
Expand Down

0 comments on commit 2166e8c

Please sign in to comment.