David, Thanks. i'll pop the recent changes up to github in a bit. i think it might be easier to look at this as a whole.
Best wishes, --greg On Thu, Aug 20, 2009 at 11:19 AM, David Pollak < [email protected]> wrote: > > > On Thu, Aug 20, 2009 at 11:13 AM, Meredith Gregory < > [email protected]> wrote: > >> Everybody, >> >> Thanks for the replies. The browser source is the same as from the chat >> example, but i've included it below. The element in which the name space is >> not bound is the first element with the chat name space. > > > Greg, > > This means that none of the page was processed by Lift. What URL are you > using to get to this page? > > Thanks, > > David > > >> >> >> Best wishes, >> >> --greg >> >> <lift:surround with="default" at="content"> >> <div class="widget sidebar"> >> <center><b>Group Chat</b></center><br /> >> <lift:comet type="Chat" name="Other"> >> <chat:body> >> Hello <chat:name/> >> <ul chat:id="na"> >> <chat:list> >> <li><list:when/> <list:who/>: <i><list:msg/></i></li> >> </chat:list> >> </ul> >> </chat:body> >> <chat:input> >> <chat:input/> <input type="submit" value="Post It" /> >> </chat:input> >> </lift:comet> >> </div> >> <p> >> The total chat app, including the ask/answer component for soliciting >> a >> name >> comments, etc. is listed on this page. >> There is no special code to support AJAX/Comet >> (all the wrapping is done automatically by <i>Lift</i>). >> </p> >> >> <p> >> When the Chat comet widget is added to the page, it needs to solict >> the >> user for a "chat name". It asks the "AskName" comet widget for the >> name. >> Until the AskName comet widget provides a name, all rendering messages >> are forwarded to AskName. >> Here's the code for the "AskName":</p> >> >> <style type="text/css"> >> /* <![CDATA[ */ >> .comment { >> /* font-lock-comment-face */ >> color: #b22222; >> } >> .comment-delimiter { >> /* font-lock-comment-delimiter-face */ >> color: #b22222; >> } >> .constant { >> /* font-lock-constant-face */ >> color: #5f9ea0; >> } >> .function-name { >> /* font-lock-function-name-face */ >> color: #0000ff; >> } >> .keyword { >> /* font-lock-keyword-face */ >> color: #a020f0; >> } >> .string { >> /* font-lock-string-face */ >> color: #bc8f8f; >> } >> .type { >> /* font-lock-type-face */ >> color: #228b22; >> } >> .variable-name { >> /* font-lock-variable-name-face */ >> color: #b8860b; >> } >> >> /* ]]> */ >> </style> >> >> <pre> >> <span class="keyword">class</span> <span class="type">AskName</span> <span >> class="keyword">extends</span> <span class="type">CometActor</span> { >> <span class="keyword">def</span> <span >> class="function-name">render</span> = >> ajaxForm(<div>What is your username?</div> ++ >> text(<span class="string">""</span>,name => >> answer(name.trim)) ++ >> <input <span class="keyword">type</span>=<span >> class="string">"submit"</span> value=<span >> class="string">"Enter"</span>/>) >> } >> </pre> >> >> <p> >> When the user submits the form, the question asked by the Chat comet >> widget >> is answered with the value the user submitted. This is >> similar to the ask/answer paradigm in Seaside, except that there's >> no need for continuations. >> </p> >> >> <p>Now, onto the heart of the chat app:</p> >> >> <pre> >> <span class="keyword">class</span> <span class="type">Chat</span> <span >> class="keyword">extends</span> <span class="type">CometActor</span> <span >> class="keyword">with</span> <span class="type">CometListener</span> { >> <span class="keyword">private</span> <span class="keyword">var</span> >> <span class="variable-name">userName</span> = <span class="string">""</span> >> <span class="keyword">private</span> <span class="keyword">var</span> >> <span class="variable-name">chats</span>: <span >> class="type">List[ChatLine]</span> = Nil >> <span class="keyword">private</span> <span class="keyword">lazy</span> >> <span class="keyword">val</span> <span class="variable-name">infoId</span> = >> uniqueId + <span class="string">"_info"</span> >> <span class="keyword">private</span> <span class="keyword">lazy</span> >> <span class="keyword">val</span> <span class="variable-name">infoIn</span> = >> uniqueId + <span class="string">"_in"</span> >> <span class="keyword">private</span> <span class="keyword">lazy</span> >> <span class="keyword">val</span> <span >> class="variable-name">inputArea</span> = findKids(defaultXml, <span >> class="string">"chat"</span>, <span class="string">"input"</span>) >> <span class="keyword">private</span> <span class="keyword">lazy</span> >> <span class="keyword">val</span> <span class="variable-name">bodyArea</span> >> = findKids(defaultXml, <span class="string">"chat"</span>, <span >> class="string">"body"</span>) >> <span class="keyword">private</span> <span class="keyword">lazy</span> >> <span class="keyword">val</span> <span >> class="variable-name">singleLine</span> = deepFindKids(bodyArea, <span >> class="string">"chat"</span>, <span class="string">"list"</span>) >> >> <span class="comment-delimiter">// </span><span class="comment">handle >> an update to the chat lists >> </span> <span class="comment-delimiter">// </span><span >> class="comment">by diffing the lists and then sending a partial update >> </span> <span class="comment-delimiter">// </span><span >> class="comment">to the browser >> </span> <span class="keyword">override</span> <span >> class="keyword">def</span> <span class="function-name">lowPriority</span> = >> { >> <span class="keyword">case</span> <span >> class="type">ChatServerUpdate</span>(<span >> class="variable-name">value</span>) => >> <span class="keyword">val</span> <span >> class="variable-name">update</span> = (value -- chats).reverse.map(b => >> AppendHtml(infoId, line(b))) >> partialUpdate(update) >> chats = value >> } >> >> <span class="comment-delimiter">// </span><span class="comment">render >> the input area by binding the >> </span> <span class="comment-delimiter">// </span><span >> class="comment">appropriate dynamically generated code to the >> </span> <span class="comment-delimiter">// </span><span >> class="comment">view supplied by the template >> </span> <span class="keyword">override</span> <span >> class="keyword">lazy</span> <span class="keyword">val</span> <span >> class="variable-name">fixedRender</span>: <span >> class="type">Box[NodeSeq]</span> = >> ajaxForm(After(100, SetValueAndFocus(infoIn, <span >> class="string">""</span>)), >> bind(<span class="string">"chat"</span>, inputArea, >> <span class="string">"input"</span> -> text(<span >> class="string">""</span>, sendMessage _, <span class="string">"id"</span> >> -> infoIn))) >> >> <span class="comment-delimiter">// </span><span class="comment">send a >> message to the chat server >> </span> <span class="keyword">private</span> <span >> class="keyword">def</span> <span >> class="function-name">sendMessage</span>(<span >> class="variable-name">msg</span>: <span class="type">String</span>) = >> ChatServer ! ChatServerMsg(userName, msg.trim) >> >> <span class="comment-delimiter">// </span><span class="comment">display >> a line >> </span> <span class="keyword">private</span> <span >> class="keyword">def</span> <span class="function-name">line</span>(<span >> class="variable-name">c</span>: <span class="type">ChatLine</span>) = >> bind(<span class="string">"list"</span>, singleLine, >> <span class="string">"when"</span> >> -> hourFormat(c.when), >> <span class="string">"who"</span> >> -> c.user, >> <span class="string">"msg"</span> >> -> c.msg) >> >> <span class="comment-delimiter">// </span><span class="comment">display >> a list of chats >> </span> <span class="keyword">private</span> <span >> class="keyword">def</span> <span >> class="function-name">displayList</span>(<span >> class="variable-name">in</span>: <span class="type">NodeSeq</span>): <span >> class="type">NodeSeq </span>= chats.reverse.flatMap(line) >> >> <span class="comment-delimiter">// </span><span class="comment">render >> the whole list of chats >> </span> <span class="keyword">override</span> <span >> class="keyword">def</span> <span class="function-name">render</span> = >> bind(<span class="string">"chat"</span>, bodyArea, >> <span class="string">"name"</span> -> userName, >> AttrBindParam(<span class="string">"id"</span>, Text(infoId), <span >> class="string">"id"</span>), >> <span class="string">"list"</span> -> displayList _) >> >> <span class="comment-delimiter">// </span><span class="comment">setup >> the component >> </span> <span class="keyword">override</span> <span >> class="keyword">def</span> <span class="function-name">localSetup</span> { >> askForName >> <span class="keyword">super</span>.localSetup >> } >> >> <span class="comment-delimiter">// </span><span class="comment">register >> as a listener >> </span> <span class="keyword">def</span> <span >> class="function-name">registerWith</span> = ChatServer >> >> <span class="comment-delimiter">// </span><span class="comment">ask for >> the user's name >> </span> <span class="keyword">private</span> <span >> class="keyword">def</span> <span class="function-name">askForName</span> { >> <span class="keyword">if</span> (userName.length == 0) { >> ask(<span class="keyword">new</span> AskName, <span >> class="string">"what's your username"</span>) { >> <span class="keyword">case</span> <span >> class="variable-name">s</span>: <span class="type">String </span><span >> class="keyword">if</span> (s.trim.length > 2) => >> userName = s.trim >> reRender(<span class="constant">true</span>) >> >> <span class="keyword">case</span> <span >> class="variable-name">_</span> => >> askForName >> reRender(<span class="constant">false</span>) >> } >> } >> } >> >> } >> </pre> >> >> <p> >> This example demonstrates the power of Scala's Actors and <i>Lift</i>. >> With very few lines of code, we've got a complete AJAX/Comet app that >> has Seaside style Ask/Answer for building modal dialogs. >> </p> >> </lift:surround> >> >> >> >> On Wed, Aug 19, 2009 at 4:58 PM, Naftoli Gugenheim >> <[email protected]>wrote: >> >>> >>> That's probably a Firefox XML error - look at view source and see what >>> the Elem label is that's not being bound. >>> >>> ------------------------------------- >>> Meredith Gregory<[email protected]> wrote: >>> >>> Lifted, >>> >>> i readily confess to being a total idiot. i'm always running into this >>> problem of not knowing when the namespace binding is in effect. i've >>> cribbed >>> Chat.scala and other files from liftweb/site/example and added it whole >>> sale >>> to my project. When i add >>> >>> val entries = >>> ( Menu(Loc("Home", List("index"), "Home")) >>> ... >>> :: Menu(Loc("Chat.1", List("chat"), "Chat", If(User.loggedIn_? _, "x"))) >>> ... >>> :: User.sitemap ) >>> >>> to my site menu and fire things up i get 'namespace chat undefined'. >>> This >>> is despite >>> >>> override def render = >>> bind("chat", bodyArea, >>> "name" -> userName, >>> AttrBindParam("id", Text(infoId), "id"), >>> "list" -> displayList _) >>> >>> being defined in the chat class. Any body have a clue for the clueless? >>> >>> Best wishes, >>> >>> --greg >>> >>> -- >>> L.G. Meredith >>> Managing Partner >>> Biosimilarity LLC >>> 1219 NW 83rd St >>> Seattle, WA 98117 >>> >>> +1 206.650.3740 >>> >>> http://biosimilarity.blogspot.com >>> >>> >>> >>> >>> >> >> >> -- >> L.G. Meredith >> Managing Partner >> Biosimilarity LLC >> 1219 NW 83rd St >> Seattle, WA 98117 >> >> +1 206.650.3740 >> >> http://biosimilarity.blogspot.com >> >> >> > > > -- > Lift, the simply functional web framework http://liftweb.net > Beginning Scala http://www.apress.com/book/view/1430219890 > Follow me: http://twitter.com/dpp > Git some: http://github.com/dpp > > > > -- L.G. Meredith Managing Partner Biosimilarity LLC 1219 NW 83rd St Seattle, WA 98117 +1 206.650.3740 http://biosimilarity.blogspot.com --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---
