Marc, Sorry... dunno what to tell you. :-( David
On Thu, Jan 8, 2009 at 3:47 PM, Marc Boschma <marc+lift...@boschma.cx<marc%2blift...@boschma.cx> > wrote: > Very cool indeed, except... I now get: > [WARNING] > /Users/marc/src/todo/src/main/scala/com/liftworkshop/snippet/TD.scala:99: > error: value attr is not a member of object net.liftweb.util.BindHelpers > [WARNING] val singular = BindHelpers.attr("singular", {s: String => > s.toLowerCase match { > [WARNING] ^ > [WARNING] one error found > > I've cleaned out my .m2/repository and I always mvn -U clean install... No > proxies in place. Usually works a charm. > Frustrating as hell - I feel for those that actually make a living in the > Java/Maven world (must make a mental note to not quibble so much on what > those who do want to get paid :) > > Thoughts? > > Marc > > The full context of the code for those interested (David's todo app > modified thus): > > (The top of the file has import net.liftweb._ and import util._) > > private def doList(reDraw: () => JsCmd)(html: NodeSeq): NodeSeq = { > val singular = BindHelpers.attr("singular", {s: String => > s.toLowerCase match { > case "" => true > case "true" => true > case "t" => true > case "yes" => true > case "y" => true > case _ => false}}, false) > val l = toShow > > if (singular) > l.flatMap(td => > bind("todo", html, > "check" -> ajaxCheckbox(td.done, > v => {td.done(v).save; > reDraw()}), > "priority" -> > ajaxSelect(ToDo.priorityList, Full(td.priority.toString), > v => > {td.priority(v.toInt).save; reDraw()}), > "desc" -> desc(td, reDraw) > )) > else { > val xhtmls = template(html, l.length) > > l.zip(xhtmls).flatMap(n => { val (td , xhtml) = n > bind("todo", xhtml, > "check" -> ajaxCheckbox(td.done, > v => {td.done(v).save; > reDraw()}), > "priority" -> > ajaxSelect(ToDo.priorityList, Full(td.priority.toString), > v => > {td.priority(v.toInt).save; reDraw()}), > "desc" -> desc(td, reDraw) > )}) > } > } > > private def template(html: NodeSeq, i: Int): List[NodeSeq] = > expand(nodeSeq2List(html), i) > > private def nodeSeq2List(html: NodeSeq): List[NodeSeq] = { > val es = html.elements.toList.filter(_ match { > case Text(s) if (s.trim.length == 0) => false // > remove whitespace text > case _ => true > }) > es match { > // it was just white space, return it > case Nil => List(html) > > // are all the nodes the same (prefix == lift)? > // this allows the use of different snippets as the > different templates... > case x :: xs if (x.prefix == "lift" && > xs.foldLeft(true)( (t, n) => (t && n.prefix > == x.prefix) )) => es > > // are all the nodes the same (prefix, label)? > case x :: xs => { > if (xs.foldLeft(true)( (t, n) => (t && > n.prefix == x.prefix && n.label == x.label) )) > es > else List(html) // nope, return origional > sequence... > } > } > } > > // duplicate a list until it is at least as long as *i* > private def expand(xhtmls: List[NodeSeq], i: Int): List[NodeSeq] = > if (i > 0) > expand(xhtmls ::: xhtmls, i - xhtmls.length) > else > xhtmls > > > On 09/01/2009, at 5:08 AM, David Pollak wrote: > > > > On Thu, Jan 8, 2009 at 9:54 AM, Marius <marius.dan...@gmail.com> wrote: > >> >> Ok, I just committed the updates. Now both BindHelpers.attr and S.attr >> implement AttrHelpers trait where we have a bunch of overloaded apply, >> >> I would have liked to use Option[NodeSeq] for S.attr as well but this >> would be a breaking change and breaking changes are frozen now. So >> S.attr("someparam") still returns a Box[String]. However I added 2 >> helper function ~ that would return Option[NodeSeq], so you can call >> S.attr ~("someparam") and get back an Option[NodeSeq]. >> >> I know we could have used implicits to convert from Box[String] to >> Option[NodeSeq] but I feel that this would be an abuse of implicits as >> the use of implicits IMHO should be motivated byt strong design >> rationales and I think this is the case. >> >> Thoughts? > > > Very cool! > > >> >> >> Br's, >> Marius >> >> On Jan 7, 7:40 pm, Marius <marius.dan...@gmail.com> wrote: >> > I'll look into it. >> > >> > On Jan 7, 7:38 pm, "David Pollak" <feeder.of.the.be...@gmail.com> >> > wrote: >> > >> > > Marc, >> > >> > > Good suggestion. Marius -- do you want to do this... maybe even turn >> the >> > > pattern into a trait that we can apply over and over? >> > >> > > Thanks, >> > >> > > David >> > >> > > On Tue, Jan 6, 2009 at 9:57 PM, Marc Boschma >> > > <marc+lift...@boschma.cx <marc%2blift...@boschma.cx>< >> marc%2blift...@boschma.cx <marc%252blift...@boschma.cx>> >> > >> > > > wrote: >> > > > Cool code! Works nicely... >> > > > Would it make sense to also add something similar to this from >> S.attr ? >> > >> > > > def apply[T](what: String, f: String => T, default: => T): T >> > > > = apply(what).map(f) openOr default >> > >> > > > ie maybe: >> > >> > > > def apply[T](prefix: String, key: String, f: String => T): >> Option[T] >> > > > = apply(prefix, key).map(f) >> > > > def apply[T](key: String, f: String => T): Option[T] = >> apply(key).map(f) >> > >> > > > to BindHelpers.attr ? >> > >> > > > Thinking about it should the applys of the two attr objects be >> aligned >> > > > (Option verses Box, etc) ? It would make the crafting of snippets >> and bind >> > > > functions in terms of access to attributes the same, dropping a >> potential >> > > > barrier to learning lift... >> > >> > > > ie Maybe BindHelpers.attr should have applys with the following >> > > > signatures... >> > >> > > > def apply(key: String): Box[String] >> > > > def apply(prefix: String, key: String): Box[String] >> > >> > > > def apply(key: String, default: => String): String >> > > > def apply(prefix: String, key: String, default: => String): >> String >> > >> > > > def apply[T](key: String, f: String => T, default: => T): T >> > > > def apply[T](prefix: String, key: String, f: String => T, >> default: => >> > > > T): T >> > >> > > > Lastly, and maybe I am missing something here, but I take it for a >> snippet >> > > > a prefixed attribute isn't accessible via S.attr ??? >> > >> > > > Regards, >> > >> > > > Marc >> > >> > > > On 07/01/2009, at 6:54 AM, David Pollak wrote: >> > >> > > > On Tue, Jan 6, 2009 at 11:16 AM, Marius <marius.dan...@gmail.com> >> wrote: >> > >> > > >> Ok ... i just committed some changes: >> > >> > > >> 1. Renamed curAttr to attr >> > > >> 2. The BindHelpers vals are now private but we expose two functions >> > > >> currentNode and bindNodes >> > >> > > > Cool beans! >> > >> > > >> Br's, >> > > >> Marius >> > >> > > >> On Jan 6, 8:37 pm, "David Pollak" <feeder.of.the.be...@gmail.com> >> > > >> wrote: >> > > >> > On Tue, Jan 6, 2009 at 10:28 AM, Marius <marius.dan...@gmail.com >> > >> > > >> wrote: >> > >> > > >> > > On Jan 6, 7:15 pm, "David Pollak" < >> feeder.of.the.be...@gmail.com> >> > > >> > > wrote: >> > > >> > > > I also added >> > > >> > > > BindHelpers.attr("tag"): Option[NodeSeq] >> > > >> > > > so you can do something like: >> > >> > > >> > > > <span class={BindHelpers.attr("class")>...</span> >> > >> > > >> > > > and: >> > > >> > > > BindHelpers.attr("prefix", "tag") >> > >> > > >> > > I think it is committed to curAttr which personally I'm not a >> fan ... >> > > >> > > Doyou mind if I change it to attr or nodeAttr ? >> > >> > > >> > Go for it. >> > >> > > >> > > > Thanks, >> > >> > > >> > > > David >> > >> > > >> > > > On Tue, Jan 6, 2009 at 9:13 AM, Marius < >> marius.dan...@gmail.com> >> > > >> wrote: >> > >> > > >> > > > > Very cool Dave ! >> > >> > > >> > > > > thx, >> > > >> > > > > Marius >> > >> > > >> > > > > On Jan 6, 4:36 pm, "David Pollak" < >> feeder.of.the.be...@gmail.com> >> > > >> > > > > wrote: >> > > >> > > > > > Folks, >> > >> > > >> > > > > > I'm about to commit up a non-breaking solution. >> > >> > > >> > > > > > In bind, you can call: >> > > >> > > > > > BindHelpers.bindNodes.value: List[NodeSeq] >> > > >> > > > > > BindHelpers.currentNode.value: Elem >> > >> > > >> > > > > > bindNodes is a list of the nodes that were passed into >> bind with >> > > >> the >> > > >> > > more >> > > >> > > > > > current node at the head of the list. If you're doing >> > > >> hierarchical >> > > >> > > > > binding, >> > > >> > > > > > you can see all the nodes that were passed into bind this >> was. >> > >> > > >> > > > > > currentNode is available to the BindParam and it contains >> the >> > > >> parent >> > > >> > > Elem >> > > >> > > > > to >> > > >> > > > > > the NodeSeq that was passed into your BindParam. You can >> > > >> inspect >> > > >> > > > > attributes >> > > >> > > > > > to your heart's content. >> > >> > > >> > > > > > Give it an hour or two for these changes to make their >> way >> > > >> through >> > > >> > > > > Hudson. >> > >> > > >> > > > > > Thanks, >> > >> > > >> > > > > > David >> > >> > > >> > > > > > On Tue, Jan 6, 2009 at 4:50 AM, Marc Boschma >> > > >> > > > > > <marc+lift...@boschma.cx <marc%2blift...@boschma.cx> < >> marc%2blift...@boschma.cx <marc%252blift...@boschma.cx>> < >> > > >> marc%2blift...@boschma.cx <marc%252blift...@boschma.cx> < >> marc%252blift...@boschma.cx <marc%25252blift...@boschma.cx>>> < >> > > >> > > marc%2blift...@boschma.cx <marc%252blift...@boschma.cx> < >> marc%252blift...@boschma.cx <marc%25252blift...@boschma.cx>> < >> > > >> marc%252blift...@boschma.cx <marc%25252blift...@boschma.cx> < >> marc%25252blift...@boschma.cx <marc%2525252blift...@boschma.cx>>>>< >> > > >> > > > > marc%2blift...@boschma.cx <marc%252blift...@boschma.cx> < >> marc%252blift...@boschma.cx <marc%25252blift...@boschma.cx>> < >> > > >> marc%252blift...@boschma.cx <marc%25252blift...@boschma.cx> < >> marc%25252blift...@boschma.cx <marc%2525252blift...@boschma.cx>>> < >> > > >> > > marc%252blift...@boschma.cx <marc%25252blift...@boschma.cx> < >> marc%25252blift...@boschma.cx <marc%2525252blift...@boschma.cx>> < >> > > >> marc%25252blift...@boschma.cx <marc%2525252blift...@boschma.cx> < >> marc%2525252blift...@boschma.cx <marc%252525252blift...@boschma.cx>>>>> >> > >> > > >> > > > > > > wrote: >> > >> > > >> > > > > > > I've just had a thought as to how to make it not a >> breaking >> > > >> change. >> > >> > > >> > > > > > > Leave your change "calcValue(s.child) I just call >> > > >> calcValue(s)" >> > >> > > >> > > > > > > change: >> > > >> > > > > > > case class FuncBindParam(name: String, value: NodeSeq >> => >> > > >> NodeSeq) >> > > >> > > > > > > extends Tuple2(name, value) with BindParam { >> > > >> > > > > > > def calcValue(in: NodeSeq): NodeSeq = value(in) >> > > >> > > > > > > } >> > >> > > >> > > > > > > to: >> > > >> > > > > > > case class FuncBindParam(name: String, value: NodeSeq >> => >> > > >> NodeSeq) >> > > >> > > > > > > extends Tuple2(name, value) with BindParam { >> > > >> > > > > > > def calcValue(in: NodeSeq): NodeSeq = >> value(in.child) >> > > >> > > > > > > } >> > >> > > >> > > > > > > That should prevent old code breaking... which would be >> a good >> > > >> > > > > > > thing(tm) given the amount of code that uses bind(...) >> > >> > > >> > > > > > > then create something like: >> > >> > > >> > > > > > > case class FuncMetaDataBindParam(name: String, value: >> > > >> (MetaData, >> > > >> > > > > > > NodeSeq) => NodeSeq) extends Tuple2(name, value) with >> > > >> BindParam { >> > > >> > > > > > > def calcValue(in: NodeSeq): NodeSeq = >> value(in.attributes, >> > > >> > > > > > > in.child) >> > > >> > > > > > > } >> > >> > > >> > > > > > > along with adding to class SuperArrowAssoc... >> > > >> > > > > > > def ->(in: (MetaData, NodeSeq) => NodeSeq) = >> > > >> > > > > > > FuncMetaDataBindParam(name, in) >> > >> > > >> > > > > > > That would be fairly clean... >> > >> > > >> > > > > > > ----- >> > >> > > >> > > > > > > Maybe for those that actually want the full node add: >> > >> > > >> > > > > > > case class FuncBoxBindParam(name: String, value: >> > > >> Box(NodeSeq) => >> > > >> > > > > > > NodeSeq) extends Tuple2(name, value) with BindParam { >> > > >> > > > > > > def calcValue(in: NodeSeq): NodeSeq = >> value(Full(in)) >> > > >> > > > > > > } >> > >> > > >> > > > > > > and you could go nuts and: >> > >> > > >> > > > > > > case class FuncPrefixAndLabelBindParam(name: String, >> value: >> > > >> > > > > > > (String, String, NodeSeq) => NodeSeq) extends >> Tuple2(name, >> > > >> value) >> > > >> > > with >> > > >> > > > > > > BindParam { >> > > >> > > > > > > def calcValue(in: NodeSeq): NodeSeq = >> value(in.prefix, >> > > >> > > in.label, >> > > >> > > > > > > in.child) >> > > >> > > > > > > } >> > >> > > >> > > > > > > etc... >> > >> > > >> > > > > > > On 06/01/2009, at 10:51 PM, Marc Boschma wrote: >> > >> > > >> > > > > > > > (you can tel I'm sleeping well :/ - too hot) >> > >> > > >> > > > > > > > The toList function is one of David's (todo example >> app). I >> > > >> do >> > > >> > > love >> > > >> > > > > > > > the ability to curry :) >> > >> > > >> > > > > > > > Marc >> > > >> > > > > > > > On 06/01/2009, at 9:51 PM, Marius wrote: >> > >> > > >> > > > > > > >> On Jan 6, 12:47 pm, Marc Boschma < >> marc+lift...@boschma.cx <marc%2blift...@boschma.cx>< >> marc%2blift...@boschma.cx <marc%252blift...@boschma.cx>> >> > > >> <marc%2blift...@boschma.cx <marc%252blift...@boschma.cx> < >> marc%252blift...@boschma.cx <marc%25252blift...@boschma.cx>>> >> > > >> > > <marc%2blift...@boschma.cx <marc%252blift...@boschma.cx> < >> marc%252blift...@boschma.cx <marc%25252blift...@boschma.cx>> < >> > > >> marc%252blift...@boschma.cx <marc%25252blift...@boschma.cx> < >> marc%25252blift...@boschma.cx <marc%2525252blift...@boschma.cx>>>> >> > > >> > > > > <marc%2blift...@boschma.cx <marc%252blift...@boschma.cx> < >> marc%252blift...@boschma.cx <marc%25252blift...@boschma.cx>> < >> > > >> marc%252blift...@boschma.cx <marc%25252blift...@boschma.cx> < >> marc%25252blift...@boschma.cx <marc%2525252blift...@boschma.cx>>> < >> > > >> > > marc%252blift...@boschma.cx <marc%25252blift...@boschma.cx> < >> marc%25252blift...@boschma.cx <marc%2525252blift...@boschma.cx>> < >> > > >> marc%25252blift...@boschma.cx <marc%2525252blift...@boschma.cx> < >> marc%2525252blift...@boschma.cx <marc%252525252blift...@boschma.cx>>>>>> >> > > >> > > > > > > wrote: >> > > >> > > > > > > >>> A quick just before going to bed reaction is that >> your >> > > >> change >> > > >> > > would >> > > >> > > > > > > >>> solve the issue. >> > >> > > >> > > > > > > >> Yeah it would ... (I mean it worked fine in my >> tests) >> > >> > > >> > > > > > > >>> It is interesting you focused on the "exclude" and >> not the >> > > >> > > > > > > >>> "list" (which is what I have been playing with). I >> > > >> actually >> > > >> > > missed >> > > >> > > > > > > >>> it >> > > >> > > > > > > >>> was a similar case... >> > >> > > >> > > > > > > >> I just picked it randomly :) ... I've seen that >> you're >> > > >> using a >> > > >> > > > > > > >> partially applied function doList ... (which I >> assume it is >> > > >> a >> > > >> > > > > curried >> > > >> > > > > > > >> function):) >> > >> > > >> > > > > > > >>> Regards, >> > >> > > >> > > > > > > >>> Marc >> > >> > > >> > > > > > > >>> On 06/01/2009, at 9:24 PM, Marius wrote: >> > >> > > >> > > > > > > >>>> I just did a minor modification to the lift code >> so the >> > > >> actual >> > > >> > > > > > > >>>> node it >> > > >> > > > > > > >>>> is passed to the BindParam and not its child. Now >> having: >> > >> > > >> > > > > > > >>>> bind("todo", html, >> > > >> > > > > > > >>>> "exclude" -> {node:NodeSeq >> > > >> =>ajaxCheckbox >> > > >> > > > > > > >>>> (QueryNotDone, v => {QueryNotDone(v); reDraw})} >> > > >> > > > > > > >>>> ... ) >> > >> > > >> > > > > > > >>>> and the markup <todo:exclude param="Dumb"/> >> > >> > > >> > > > > > > >>>> The node parameter to the anonymous function will >> be the >> > > >> > > > > > > >>>> <todo:exclude> node and not its children. So now >> you can >> > > >> > > access >> > > >> > > > > the >> > > >> > > > > > > >>>> "param" attribute from node. The change was in >> in_bind >> > > >> > > function so >> > > >> > > > > > > >>>> instead of calling calcValue(s.child) I just call >> > > >> calcValue(s) >> > >> > > >> > > > > > > >>>> Looking at the existent BindParams this change >> does not >> > >> > ... >> > >> > read more ยป >> >> > > > -- > Lift, the simply functional web framework http://liftweb.net > Collaborative Task Management http://much4.us > Follow me: http://twitter.com/dpp > Git some: http://github.com/dpp > > > > > > > > -- Lift, the simply functional web framework http://liftweb.net Collaborative Task Management http://much4.us Follow me: http://twitter.com/dpp Git some: http://github.com/dpp --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Lift" group. To post to this group, send email to liftweb@googlegroups.com To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/liftweb?hl=en -~----------~----~----~----~------~----~------~--~---