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 <[email protected]<marc%[email protected]> > 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 <[email protected]> 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" <[email protected]> >> wrote: >> > On Tue, Jan 6, 2009 at 10:28 AM, Marius <[email protected]> >> wrote: >> > >> > > On Jan 6, 7:15 pm, "David Pollak" <[email protected]> >> > > 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 <[email protected]> >> wrote: >> > >> > > > > Very cool Dave ! >> > >> > > > > thx, >> > > > > Marius >> > >> > > > > On Jan 6, 4:36 pm, "David Pollak" <[email protected]> >> > > > > 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 >> > > > > > <[email protected] <marc%[email protected]> < >> marc%[email protected] <marc%[email protected]>> < >> > > marc%[email protected] <marc%[email protected]> < >> marc%[email protected] <marc%[email protected]>>>< >> > > > > marc%[email protected] <marc%[email protected]> < >> marc%[email protected] <marc%[email protected]>> < >> > > marc%[email protected] <marc%[email protected]> < >> marc%[email protected] <marc%[email protected]>>>> >> > >> > > > > > > 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 >> > > > > > > >> <[email protected]<marc%[email protected]> >> <marc%[email protected] <marc%[email protected]>> >> > > <marc%[email protected] <marc%[email protected]> < >> marc%[email protected] <marc%[email protected]>>> >> > > > > <marc%[email protected] <marc%[email protected]> < >> marc%[email protected] <marc%[email protected]>> < >> > > marc%[email protected] <marc%[email protected]> < >> marc%[email protected] <marc%[email protected]>>>>> >> > > > > > > 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 >> seem >> > > to >> > > > > > > >>>> cause >> > > > > > > >>>> side effects since the calcValue 'in' parameter is used >> only >> > > for >> > > > > > > >>>> FuncXXXBindParam-s. The impact is that the user's >> function >> > > would >> > > > > > > >>>> now >> > > > > > > >>>> get the actual node (from which now he can extract >> attributes) >> > > and >> > > > > > > >>>> not >> > > > > > > >>>> the child nodes. But child nodes from the actual node are >> > > trivial >> > > > > > > >>>> to >> > > > > > > >>>> obtain. >> > >> > > > > > > >>>> I did not commit this change as I'd like to see other >> opinions >> > > to >> > > > > > > >>>> see >> > > > > > > >>>> if there is something that I missed somehow. If we get >> general >> > > > > > > >>>> consensus of this change I can commit it right away and >> > > announce >> > > > > > > >>>> it as >> > > > > > > >>>> a "breaking change". >> > >> > > > > > > >>>> Thoughts? >> > >> > > > > > > >>>> Br's, >> > > > > > > >>>> Marius >> > >> > > > > > > >>>> On Jan 6, 12:02 pm, Marius <[email protected]> >> wrote: >> > > > > > > >>>>> A nice alternative would have been : >> > >> > > > > > > >>>>> bind("todo", html, >> > > > > > > >>>>> "exclude" -> {node:NodeSeq >> > > =>ajaxCheckbox >> > > > > > > >>>>> (QueryNotDone, v => {QueryNotDone(v); reDraw})} >> > > > > > > >>>>> ... ) >> > >> > > > > > > >>>>> But here the node impersonates the childNodes not the >> > > original >> > > > > > > >>>>> node. >> > > > > > > >>>>> So you still can not access the param attribute below >> > >> > > > > > > >>>>> <todo:exclude param="Dumb"/> >> > >> > > > > > > >>>>> but you can do it like: >> > >> > > > > > > >>>>> <todo:exclude ><meta param="dumb"/></todo:exclude> >> > >> > > > > > > >>>>> and you have full access to the meta node as it is a >> child of >> > > > > > > >>>>> todo:exclude. Hence you can pass state. >> > >> > > > > > > >>>>> I know, it is not ideal but should be workable until >> snippet >> > > > > > > >>>>> child- >> > > > > > > >>>>> node attributes are exposed in one way or another. >> > >> > > > > > > >>>>> Br's, >> > > > > > > >>>>> Marius >> > >> > > > > > > >>>>> Marc Boschma wrote: >> > > > > > > >>>>>> I have been playing with the ToDo example application >> and >> > > having >> > > > > > > >>>>>> fun >> > > > > > > >>>>>> in manipulating XML. >> > >> > > > > > > >>>>>> With the <todo:list/> node I thought it would be good >> if the >> > > > > > > >>>>>> XHTML >> > > > > > > >>>>>> designer could pass in some guidance to the doList(...) >> > > method >> > > > > > > >>>>>> used in >> > > > > > > >>>>>> bind(..). ie. <todo:list >> singular="true">...</todo:list> >> > >> > > > > > > >>>>>> Looking over the bind code I noticed that the >> attributes are >> > > not >> > > > > > > >>>>>> accessible without ending up changing the calcValue >> method's >> > > > > > > >>>>>> signature. I did initially try to knock up a >> > >> > > > > > > >>>>>> case class FuncWithAttrBindParam(name: String, value: >> > > > > (NodeSeq, >> > > > > > > >>>>>> MetaData) => NodeSeq) extends Tuple2(name, value) with >> > > BindParam >> > >> > > > > > > >>>>>> and a corresponding >> > >> > > > > > > >>>>>> case Some(ns : FuncWithAttrBindParam) => >> > >> > > > > > > >>>>>> in in_bind(...), but it all looks like a huge kludge. >> > >> > > > > > > >>>>>> It strikes me as a little deficient to be able to >> utilise >> > > > > > > >>>>>> attributes >> > > > > > > >>>>>> within the context of a snippet and yet not within a >> bind. I >> > > > > know >> > > > > > > >>>>>> bind >> > > > > > > >>>>>> is quite embedded in lift now, but I think that this >> > > difference >> > > > > > > >>>>>> might >> > > > > > > >>>>>> prove a little frustrating. I know one solution is to >> just >> > > > > > > >>>>>> create a >> > > > > > > >>>>>> bind("todo", html, >> > > > > > > >>>>>> "exclude" -> >> > > > > > > >>>>>> ajaxCheckbox(QueryNotDone, v => {QueryNotDone(v); >> reDraw}), >> > > > > > > >>>>>> "list" -> >> doList(reDraw, >> > > false) >> > > > > > > >>>>>> _, >> > >> > ... >> > >> > 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 [email protected] To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/liftweb?hl=en -~----------~----~----~----~------~----~------~--~---
