Skip to content

Commit

Permalink
Got some listing stuff working
Browse files Browse the repository at this point in the history
  • Loading branch information
dpp committed Feb 15, 2011
1 parent 7229573 commit 3927fcc
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 33 deletions.
20 changes: 15 additions & 5 deletions core/util/src/main/scala/net/liftweb/util/ListHelpers.scala
Expand Up @@ -52,15 +52,20 @@ trait ListHelpers {
@tailrec def loop(o: List[T], n: List[T]) {
(o, n) match {
case (o, Nil) => o.foreach(t => ret += f(RemoveDelta(t)))
case (Nil, n) => n.foreach(t => ret += f(AppendDelta(t)))
case (Nil, n) => {
n.foreach{
t => ret += f(insertAfter match {
case Full(x) => InsertAfterDelta(t, x)
case _ => AppendDelta(t)
})
insertAfter = Full(t)
}
}

case (o :: or, n :: nr) if o == n => {
insertAfter = Full(n)
loop(or, nr)
}
case (o :: or, nr) if !nr.contains(o) => {
ret += f(RemoveDelta(o))
loop(or, nr)
}

case (or, n :: nr) if !or.contains(n) => {
insertAfter match {
Expand All @@ -70,6 +75,11 @@ trait ListHelpers {
insertAfter = Full(n)
loop(or, nr)
}

case (o :: or, nr) => {
ret += f(RemoveDelta(o))
loop(or, nr)
}
}
}

Expand Down
Expand Up @@ -327,7 +327,7 @@ trait StringHelpers {
what.charAt(pos) match {
case c @ ('\\' | '\'') => sb.append(escChar(c))
case '"' => sb.append("\\\"")
case c if c < ' ' || c > '~' => sb.append(escChar(c))
case c if c < ' ' || c > '~' || c == ']' || c.toInt >= 127 => sb.append(escChar(c))
case c => sb.append(c)
}
pos += 1
Expand Down
10 changes: 7 additions & 3 deletions core/util/src/test/scala/net/liftweb/util/ListHelpersSpec.scala
Expand Up @@ -32,26 +32,30 @@ object ListHelpersSpec extends Specification with ListHelpers {
ret must_== List("ok")
}

"prepend and append" in {
"prepend and append 2,4, 99" in {
val ret = delta(List(2,4,99), List(1,2,3,4,5)) {
case InsertAfterDelta(3, 2) => "ok"
case AppendDelta(5) => "ok5"
case RemoveDelta(99) => "99"
case InsertAtStartDelta(1) => "1"
case InsertAfterDelta(5, 4) => "ok5"
}

ret must_== List("1", "ok", "99", "ok5")
ret must_== List("1", "ok", "ok5", "99")
}

"prepend and append" in {
val ret = delta(List(4,2,99), List(1,2,3,4,5)) {
case InsertAfterDelta(3, 2) => "ok"
case InsertAfterDelta(4, 3) => "ok3"
case RemoveDelta(4) => "r4"
case AppendDelta(5) => "ok5"
case RemoveDelta(99) => "99"
case InsertAtStartDelta(1) => "1"
case InsertAfterDelta(5, 4) => "ok5"
}

ret must_== List("1", "ok", "99", "ok5")
ret must_== List("1", "r4", "ok", "ok3", "ok5", "99")
}

}
Expand Down
34 changes: 17 additions & 17 deletions web/webkit/src/main/scala/net/liftweb/http/CometActor.scala
Expand Up @@ -378,15 +378,15 @@ trait LiftCometActor extends TypedActor[Any, Any] with ForwardableActor[Any, Any
private[http] def callInitCometActor(theSession: LiftSession,
theType: Box[String],
name: Box[String],
defaultXml: NodeSeq,
defaultHtml: NodeSeq,
attributes: Map[String, String]) {
initCometActor(theSession, theType, name, defaultXml, attributes)
initCometActor(theSession, theType, name, defaultHtml, attributes)
}

protected def initCometActor(theSession: LiftSession,
theType: Box[String],
name: Box[String],
defaultXml: NodeSeq,
defaultHtml: NodeSeq,
attributes: Map[String, String]): Unit

def jsonCall: JsonCall
Expand Down Expand Up @@ -547,16 +547,16 @@ trait CometActor extends LiftActor with LiftCometActor with BindHelpers {
protected def initCometActor(theSession: LiftSession,
theType: Box[String],
name: Box[String],
defaultXml: NodeSeq,
defaultHtml: NodeSeq,
attributes: Map[String, String]) {
if (!dontCacheRendering) {
lastRendering = RenderOut(Full(defaultXml),
lastRendering = RenderOut(Full(defaultHtml),
Empty, Empty, Empty, false)
}

this._theType = theType
this._theSession = theSession
this._defaultXml = defaultXml
this._defaultHtml = defaultHtml
this._name = name
this._attributes = attributes
}
Expand Down Expand Up @@ -688,10 +688,10 @@ trait CometActor extends LiftActor with LiftCometActor with BindHelpers {
/**
* A helpful implicit conversion that takes a NodeSeq => NodeSeq
* (for example a CssSel) and converts it to a Box[NodeSeq] by
* applying the function to defaultXml
* applying the function to defaultHtml
*/
protected implicit def nodeSeqFuncToBoxNodeSeq(f: NodeSeq => NodeSeq):
Box[NodeSeq] = Full(f(defaultXml))
Box[NodeSeq] = Full(f(defaultHtml))

/**
* Handle messages sent to this Actor before the
Expand Down Expand Up @@ -743,12 +743,12 @@ trait CometActor extends LiftActor with LiftCometActor with BindHelpers {
performReRender(true)

/**
* Update the defaultXml... sent in dev mode
* Update the defaultHtml... sent in dev mode
*/
case UpdateDefaultXml(xml) => {
val redo = xml != _defaultXml
val redo = xml != _defaultHtml

_defaultXml = xml
_defaultHtml = xml

if (redo) performReRender(false)
}
Expand Down Expand Up @@ -853,7 +853,7 @@ trait CometActor extends LiftActor with LiftCometActor with BindHelpers {
* There are implicit conversions for NodeSeq, so you can return a pile of
* XML right here. There's an implicit conversion for NodeSeq => NodeSeq,
* so you can return a function (e.g., a CssBindFunc) that will convert
* the defaultXml to the correct output. There's an implicit conversion
* the defaultHtml to the correct output. There's an implicit conversion
* from JsCmd, so you can return a pile of JavaScript that'll be shipped
* to the browser.
*/
Expand Down Expand Up @@ -980,12 +980,12 @@ trait CometActor extends LiftActor with LiftCometActor with BindHelpers {
}

/**
* A helper for binding which uses the defaultXml property.
* A helper for binding which uses the defaultHtml property.
*/
def bind(prefix: String, vals: BindParam*): NodeSeq = bind(prefix, _defaultXml, vals: _*)
def bind(prefix: String, vals: BindParam*): NodeSeq = bind(prefix, _defaultHtml, vals: _*)

/**
* A helper for binding which uses the defaultXml propert and the
* A helper for binding which uses the defaultHtml property and the
* default prefix.
*/
def bind(vals: BindParam*): NodeSeq = bind(_defaultPrefix, vals: _*)
Expand All @@ -995,7 +995,7 @@ trait CometActor extends LiftActor with LiftCometActor with BindHelpers {
* take over the screen real estate until the question is answered.
*/
protected def ask(who: LiftCometActor, what: Any)(answerWith: Any => Unit) {
who.callInitCometActor(theSession, Full(who.uniqueId), name, defaultXml, attributes)
who.callInitCometActor(theSession, Full(who.uniqueId), name, defaultHtml, attributes)
theSession.addCometActor(who)
// who.link(this)
who ! PerformSetupComet
Expand All @@ -1019,7 +1019,7 @@ trait CometActor extends LiftActor with LiftCometActor with BindHelpers {
* rendering.
*/
protected implicit def nsToNsFuncToRenderOut(f: NodeSeq => NodeSeq) =
new RenderOut((Box !! defaultXml).map(f), fixedRender, if (autoIncludeJsonCode) Full(jsonToIncludeInCode & S.jsToAppend()) else {
new RenderOut((Box !! defaultHtml).map(f), fixedRender, if (autoIncludeJsonCode) Full(jsonToIncludeInCode & S.jsToAppend()) else {
S.jsToAppend match {
case Nil => Empty
case x :: Nil => Full(x)
Expand Down
64 changes: 57 additions & 7 deletions web/webkit/src/main/scala/net/liftweb/http/WiringUI.scala
@@ -1,5 +1,5 @@
/*
* Copyright 2010 WorldWide Conferencing, LLC
* Copyright 2010-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.
Expand All @@ -14,13 +14,15 @@
* limitations under the License.
*/

package net.liftweb {
package http {
package net.liftweb
package http

import common._
import util._

import _root_.net.liftweb.util._
import js._
import JsCmds._
import _root_.scala.xml.{NodeSeq, Elem, Text}
import scala.xml.{NodeSeq, Elem, Text}

/**
* Surface a user interface on top of Wiring
Expand Down Expand Up @@ -118,6 +120,23 @@ object WiringUI {
*/
def toNode[T](in: NodeSeq, cell: Cell[T])(f: (T, NodeSeq) => NodeSeq): NodeSeq = toNode(in, cell, (id, first, js) => js)(f)

def history[T](cell: Cell[T])(f: (Box[T], T, NodeSeq) => JsCmd): NodeSeq => NodeSeq =
in => {
val myElem: Elem = in.find {
case e: Elem => true
case _ => false
}.map(_.asInstanceOf[Elem]).getOrElse(<span id={Helpers.nextFuncName}>{in}</span>)


addHistJsFunc(cell, (old: Box[T], nw: T) => f(old, nw, in))

new Elem(myElem.prefix,
myElem.label,
myElem.attributes,
myElem.scope)
}


/**
* Given a NodeSeq, a Cell and a function that can generate
* a NodeSeq from the cell's value and the template value, register the
Expand Down Expand Up @@ -299,6 +318,39 @@ object WiringUI {
} else Noop
})
}


/**
* Associate a Cell and a function that converts from the
* cell's value to a JavaScript command to be sent to the
* browser as part of the page's post-processing.
*
* @param cell the cell to associate the JavaScript to
* @param f the function that takes the cell's value and a flag indicating
* if this is the first time
*/
def addHistJsFunc[T](cell: Cell[T], f: (Box[T], T) => JsCmd) {
for {
cometActor <- S.currentCometActor
} cell.addDependent(cometActor)

val trc = TransientRequestCell(cell)
var lastTime: Long = 0L
var lastValue: Box[T] = Empty
for {
sess <- S.session
} sess.addPostPageJavaScript(() => {
val (value, ct) = trc.get
val first = lastTime == 0L
if (first || (ct > lastTime && Full(value) != lastValue)) {
val oldValue = lastValue
lastValue = Full(value)
lastTime = ct
f(oldValue, value)
} else Noop
})
}

}

/**
Expand All @@ -308,5 +360,3 @@ private final case class TransientRequestCell[T](cell: Cell[T]) extends Transien
override val __nameSalt = Helpers.nextFuncName
}

}
}

0 comments on commit 3927fcc

Please sign in to comment.