Permalink
Browse files

Got some listing stuff working

  • Loading branch information...
1 parent 7229573 commit 3927fccec45d6702af11d54cfc9013ffc66cb9e1 @dpp dpp committed Feb 15, 2011
View
20 core/util/src/main/scala/net/liftweb/util/ListHelpers.scala
@@ -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 {
@@ -70,6 +75,11 @@ trait ListHelpers {
insertAfter = Full(n)
loop(or, nr)
}
+
+ case (o :: or, nr) => {
+ ret += f(RemoveDelta(o))
+ loop(or, nr)
+ }
}
}
View
2 core/util/src/main/scala/net/liftweb/util/StringHelpers.scala
@@ -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
View
10 core/util/src/test/scala/net/liftweb/util/ListHelpersSpec.scala
@@ -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")
}
}
View
34 web/webkit/src/main/scala/net/liftweb/http/CometActor.scala
@@ -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
@@ -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
}
@@ -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
@@ -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)
}
@@ -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.
*/
@@ -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: _*)
@@ -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
@@ -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)
View
64 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.
@@ -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
@@ -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
@@ -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
+ })
+ }
+
}
/**
@@ -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.