Ajax render based on url

86 views
Skip to first unread message

The Curious Guy

unread,
Jul 5, 2011, 10:29:07 AM7/5/11
to lif...@googlegroups.com
Hi, 

I am writing a web mail app using lift which mimics gmail.
I would like to keep header and left sidebar static, while the main content is loaded depends on input url. For example: 

https://mail.google.com/mail/u/0/?shva=1#mbox/1308a81d0f => will load message with id 1308....

That means my app must utilize some type of Ajax. I have figured two ways: 
First is receive raw Json data from Lift and render using client side javascript.
Second is receive html from Lift and put it in content section. 

Could you please tell me which is the better way and how do I implement using Lift.

Thank you for your help!
 

Diego Medina

unread,
Jul 5, 2011, 10:52:48 AM7/5/11
to lif...@googlegroups.com
There is another way, maybe it is your first option, but with a little
change, you can use comet to draw the page based on the url.

Note that your urls are different only after the fragment protion
(after the # ) and that part of the url is not sent to the server.
You would have to use javascript to send that information to the lift
server.

I have written a blog about one way of doing that, see

http://blog.fmpwizard.com/back-button-and-bookmark-meet-lift-comet
(there is a live demo on the post showing how it works)

And I have a new way (better) in the works. Basically, on the post I
wrote I send information to a REST API so that I can communicate from
the browser to the Lift server, you can avoid adding REST to the mix
by using ajaxCall() which basically allows you to execute scala code
by calling it from javascript.

If you need any help just post back.

Regards,

Diego

> --
> You received this message because you are subscribed to the Google Groups
> "Lift" group.
> To view this discussion on the web visit
> https://groups.google.com/d/msg/liftweb/-/MaVi20IjQiIJ.
> To post to this group, send email to lif...@googlegroups.com.
> To unsubscribe from this group, send email to
> liftweb+u...@googlegroups.com.
> For more options, visit this group at
> http://groups.google.com/group/liftweb?hl=en.
>

--
Diego Medina
Web Developer
(305) 788-4954
di...@fmpwizard.com
http://www.fmpwizard.com

The Curious Guy

unread,
Jul 6, 2011, 1:09:00 PM7/6/11
to lif...@googlegroups.com
Awesome works, Diego! I really like how you handle multiple comet request!

Could you elaborate in more detail how do I use ajaxCall to accomplish the same result?
I observed that google and twitter use #! as url splitter. 

Do you know which framework they use?

Diego Medina

unread,
Jul 6, 2011, 5:54:24 PM7/6/11
to lif...@googlegroups.com
On Wed, Jul 6, 2011 at 1:09 PM, The Curious Guy <phuon...@gmail.com> wrote:
> Awesome works, Diego! I really like how you handle multiple comet request!

Thanks!, I'm glad you like it.

> Could you elaborate in more detail how do I use ajaxCall to accomplish the
> same result?

I hope to finish a blog post explaining it in detail later this week,
but if you are not afraid of reading some scala code, I already have a
sample application that uses ajaxCall.

See

https://github.com/fmpwizard/lift-comet-history

If you do:

git clone git://github.com/fmpwizard/lift-comet-history.git

cd lift-comet-history

sbt

> update jetty-run


and then go to 127.0.0.1:8080

you will see two menus on the sitemap, the second uses ajaxCall
instead of the rest api.
on the source, go to the files:

https://github.com/fmpwizard/lift-comet-history/blob/master/src/main/scala/code/snippet/PlaceCometOnPage2.scala
https://github.com/fmpwizard/lift-comet-history/blob/master/src/main/scala/code/comet/MyLiftActor2.scala
https://github.com/fmpwizard/lift-comet-history/blob/master/src/main/webapp/liftactorform2.html
and the updated
https://github.com/fmpwizard/lift-comet-history/blob/master/src/main/webapp/templates-hidden/default.html

There is one bug, when you click on the links 1 2 o 3, you end up
sending each ajaxCall twice, this is just my fault and I'm looking for
a solution.

Regards,


Diego

> I observed that google and twitter use #! as url splitter.
> Do you know which framework they use?
>

> --
> You received this message because you are subscribed to the Google Groups
> "Lift" group.
> To view this discussion on the web visit

> https://groups.google.com/d/msg/liftweb/-/S--1mkDBnagJ.

Curious Guys

unread,
Jul 7, 2011, 6:21:43 AM7/7/11
to lif...@googlegroups.com
Hi Diego,

Thanks for your sharing, this's very close with what i need. Could you elaborate in more detail how i have to do in this case:

https://mail.google.com/mail/u/0/?shva=1#mbox/1308a81d0f => will load message with id 1308  (above)

What should i do? Send multi params (mbox and id) or (GooglePlusTweet and followers) to lift server and format the raw json to render at client side or other solutions is better? And how can lift server auto push data to client if have news feed (looks like facebook)? If you have any example, that will be very useful.

Can you explain more detail why using ajaxCall is better than using REST API in your example? 

One again, thank you so much!
P/s: Do you know what does "#!" in tweeter mean? :D

Tony

unread,
Jul 7, 2011, 9:24:36 AM7/7/11
to lif...@googlegroups.com
 >> And how can lift server auto push data to client if have news feed (looks like facebook)? 
Sorry for this stupid question, comet did it.

Thanks,

Diego Medina

unread,
Jul 7, 2011, 12:14:45 PM7/7/11
to lif...@googlegroups.com
Hi, see comments below:

On Thu, Jul 7, 2011 at 6:21 AM, Curious Guys <tuanv...@gmail.com> wrote:
> Hi Diego,
> Thanks for your sharing, this's very close with what i need. Could you
> elaborate in more detail how i have to do in this case:
> https://mail.google.com/mail/u/0/?shva=1#mbox/1308a81d0f => will load
> message with id 1308  (above)
> or http://twitter.com/#!/GooglePlusTweet/followers
>

You would have a url that is a little different, I am using this
jQuery plugin called BBQ, if you look at their examples here:

http://benalman.com/code/projects/jquery-bbq/examples/fragment-advanced/#bbq1=burger.html&bbq2=ribs.html

they manage several "values" like this:

bbq1=burger.html&bbq2=ribs.html

so your url could look like:

https://mail.google.com/mail/u/0/?shva=1#folder=mbox&id=1308a81d0f

How to add those values to the URL is all very well covered on the BBQ
documentation and examples, this url may be useful too:
http://benalman.com/code/projects/jquery-bbq/docs/files/jquery-ba-bbq-js.html
http://benalman.com/projects/jquery-bbq-plugin/


> What should i do? Send multi params (mbox and id) or (GooglePlusTweet and
> followers) to lift server and format the raw json to render at client side
> or other solutions is better? And how can lift server auto push data to
> client if have news feed (looks like facebook)? If you have any example,
> that will be very useful.

If you are updating small portions of the page, using partialUpdate
from a comet actor works really well, I know that David has refer
people to
http://lift.la/shtmlidmemoize-simple-ajax-updating when they have
asked about updating large portions of a page, I have not tried it
myself yet.

> Can you explain more detail why using ajaxCall is better than using REST API
> in your example?

Maybe not better, but removing the REST API removes several lines of
code, which in turn could eliminate complexity and bugs. I'm working
the idea of making this ajax/comet back button code into a Lift module
or maybe part of the core lift code, so not requiring a REST API makes
it a lot easier to implement. But if you like the REST usage, by all
means, use that technique.

> One again, thank you so much!
> P/s: Do you know what does "#!" in tweeter mean? :D
>

A while ago Google researched with the idea of crawling websites that
make use of ajax, in the old days, you needed a pure html page for
google to index your site. Along that research they decided that if
your url had #! it meant that it has ajax content, because strictly
speaking, you can have urls like:

http://www.liftweb.net/contactus#david and it does not mean that it
involves an Ajax call, it simply means that there is an anchor link on
the contactus page that takes you straight to, let's say, the middle
of the page with his email address.

So they wanted to differentiate the two. That being said, the jQuery
plugin I'm using uses just the # tag. There may be other plugins that
use the #!, but at the moment I'm not too worry about it.

Regards,

Diego


> --
> You received this message because you are subscribed to the Google Groups
> "Lift" group.
> To view this discussion on the web visit

> https://groups.google.com/d/msg/liftweb/-/F_XTG9GEWd4J.

Tony

unread,
Jul 7, 2011, 9:41:56 PM7/7/11
to lif...@googlegroups.com
All of your information is very useful. You rock, Diego!

Thank you!

Diego Medina

unread,
Jul 7, 2011, 11:37:01 PM7/7/11
to lif...@googlegroups.com
On Thu, Jul 7, 2011 at 9:41 PM, Tony <tuanv...@gmail.com> wrote:
> All of your information is very useful. You rock, Diego!

I'm glad I was able to help, now, I have changed the code a little bit
so that I use jsonCall instead of ajaxCall, why? because when I was
using ajaxCall I was sending data as a string separated by a pipe |
, but using jsonCall I can send a json structure and then nicely
parse it on the scala side.

I'll try to push those changes tomorrow to the github repository.

Enjoy

Diego


> Thank you!


>
> --
> You received this message because you are subscribed to the Google Groups
> "Lift" group.
> To view this discussion on the web visit

> https://groups.google.com/d/msg/liftweb/-/YV-6EBEuCKcJ.

Tony

unread,
Jul 11, 2011, 12:12:31 PM7/11/11
to lif...@googlegroups.com
Hi Diego,

1. I follow your example with RestAPI in my project, but my code looks so long when i must verifyJsonPutData each time client send a request. If each tab has 7-8 params => 7-8 Rest API => 7-8 times i must define verifyJsonPutData, so many code is duplicated. Do you have any solution for this, maybe looks like:

serve {
  // View user info
  case "r" :: "u" :: _ JsonPut jsonData -> _ =>
  verifyJsonPutData(Full(jsonData.extract[JsonExtractor]), viewInfo) => add viewInfo

// View user activity
  case "r" :: "a" :: _ JsonPut jsonData -> _ =>
  verifyJsonPutData(Full(jsonData.extract[JsonExtractor]), viewActivity) => add viewActivity
}

It's better if i only define only one verifyJsonPutData function and have at least 2 params to process it.

2. I have a question about rendering. For example: friend list in facebook, i must query to get friend list, then render infos for each friend such as: name, avatar, ... What's best practice for rendering (SetHtml or anything else)?. Normally, i will query from my database and use flatMap to render, but i'm not sure how to do it in this case and what's better?

P/s: If you changed your code to jsonCall, pls let me know. I would like to see it soon

Thank you for your help. I love the way you sharing your knowledge. Have a good day, Diego!

Diego Medina

unread,
Jul 11, 2011, 1:19:34 PM7/11/11
to lif...@googlegroups.com

I'm not at my computer now, but I already pushed the jsoncall example. I'll give you a longer answer later tonight.

On Jul 11, 2011 12:12 PM, "Tony" <tuanv...@gmail.com> wrote:
> Hi Diego,
>
> 1. I follow your example with RestAPI in my project, but my code looks so
> long when i must verifyJsonPutData each time client send a request. If each
> tab has 7-8 params => 7-8 Rest API => 7-8 times i must define
> verifyJsonPutData, so many code is duplicated. Do you have any solution for
> this, maybe looks like:
>
> serve {
> // View user info
> case "r" :: "u" :: _ JsonPut jsonData -> _ =>
> verifyJsonPutData(Full(jsonData.extract[JsonExtractor]), *viewInfo*) =>
> add *viewInfo*

>
> // View user activity
> case "r" :: "a" :: _ JsonPut jsonData -> _ =>
> verifyJsonPutData(Full(jsonData.extract[JsonExtractor]), *viewActivity*)
> => add *viewActivity*

> }
>
> It's better if i only define only one verifyJsonPutData function and have at
> least 2 params to process it.
>
> 2. I have a question about rendering. For example: friend list in facebook,
> i must query to get friend list, then render infos for each friend such as:
> name, avatar, ... What's best practice for rendering (SetHtml or anything
> else)?. Normally, i will query from my database and use flatMap to render,
> but i'm not sure how to do it in this case and what's better?
>
> P/s: If you changed your code to jsonCall, pls let me know. I would like to
> see it soon
>
> Thank you for your help. I love the way you sharing your knowledge. Have a
> good day, Diego!
>
> --
> You received this message because you are subscribed to the Google Groups "Lift" group.
> To view this discussion on the web visit https://groups.google.com/d/msg/liftweb/-/dcwxpEPcE10J.

Diego Medina

unread,
Jul 11, 2011, 2:33:18 PM7/11/11
to lif...@googlegroups.com
See comments below:

On Mon, Jul 11, 2011 at 12:12 PM, Tony <tuanv...@gmail.com> wrote:
> Hi Diego,
> 1. I follow your example with RestAPI in my project, but my code looks so
> long when i must verifyJsonPutData each time client send a request. If each
> tab has 7-8 params => 7-8 Rest API => 7-8 times i must define
> verifyJsonPutData, so many code is duplicated. Do you have any solution for
> this, maybe looks like:
> serve {
>   // View user info
>   case "r" :: "u" :: _ JsonPut jsonData -> _ =>
>   verifyJsonPutData(Full(jsonData.extract[JsonExtractor]), viewInfo) => add
> viewInfo
> // View user activity
>   case "r" :: "a" :: _ JsonPut jsonData -> _ =>
>   verifyJsonPutData(Full(jsonData.extract[JsonExtractor]), viewActivity) =>
> add viewActivity
> }
> It's better if i only define only one verifyJsonPutData function and have at
> least 2 params to process it.

I think that moving to jsonCall will make a good difference on
reducing number of lines and duplication.

> 2. I have a question about rendering. For example: friend list in facebook,
> i must query to get friend list, then render infos for each friend such as:
> name, avatar, ... What's best practice for rendering (SetHtml or anything
> else)?. Normally, i will query from my database and use flatMap to render,
> but i'm not sure how to do it in this case and what's better?

Just the other day David answered a question that really fits this
situation imho. See

http://groups.google.com/group/liftweb/browse_thread/thread/dd1f4e5f62e69aae#

You can use SetHtml and the NodeSeq can be a complete template file,
or a snippet, I tried the template idea and it works really well.


> P/s: If you changed your code to jsonCall, pls let me know. I would like to
> see it soon

I pushed the changes last night

https://github.com/fmpwizard/lift-comet-history

and I'm almost done with the blog post explaining how it all works.

> Thank you for your help. I love the way you sharing your knowledge. Have a
> good day, Diego!
>

Thanks, I really enjoy sharing what I learn, because 1) thanks to
others sharing what they know I have learned almost everything I know
computer related, and 2) I learn even more doing this.

Enjoy

Diego


> --
> You received this message because you are subscribed to the Google Groups
> "Lift" group.
> To view this discussion on the web visit

> https://groups.google.com/d/msg/liftweb/-/dcwxpEPcE10J.

Tony

unread,
Jul 12, 2011, 11:17:28 PM7/12/11
to lif...@googlegroups.com
Thanks Diego!

But i have some unclear point in your code:
1. Why don't you remove some unnecessary code in myliftactor2. When you use jsonCall, you still receive 2 messages, 1 by RestAPI, 1 such as string. And why don't you still call CityStateUpdate?

MyListeners.listenerFor(cometName) match {
        case a: LiftActor => a ! CityStateUpdate(cometName, lookedupCity, lookedupState)
        case _            => info("No actor to send an update")
      }

If i remove CityStateUpdate here and some code bellow processing case CityStateUpdate(cometName, city, state) in def lowPriority: PartialFunction[Any,Unit] and class DispatcherActor2, it compiles error.

2. If i remove some code above. I don't see any SetHtml code anymore. So how does it render?

Thanks,

Tony

unread,
Jul 12, 2011, 11:26:24 PM7/12/11
to lif...@googlegroups.com
Sorry for question 2, i miss some code. I got the answer!
Thanks

Diego Medina

unread,
Jul 13, 2011, 12:28:24 AM7/13/11
to lif...@googlegroups.com
It's a little late here but why are you saying that I'm getting 2
messages, one by the REST API and one by jsonCall?

Thanks

Diego

P.S. What kind of email program do you use, the subject of this
thread is getting really long :)

> --
> You received this message because you are subscribed to the Google Groups
> "Lift" group.
> To view this discussion on the web visit

> https://groups.google.com/d/msg/liftweb/-/My8l1dnIU4gJ.

Reply all
Reply to author
Forward
0 new messages