Mobile optimization revisited, sample code included

115 views
Skip to first unread message

Nolan Darilek

unread,
Nov 10, 2011, 11:34:22 AM11/10/11
to Lift
Nearly a year ago I was talking about dynamically serving
mobile-optimized Lift sites, but now I'm finally in a place where I
really want/need to do that. Unfortunately I'm encountering an issue and
need help.

https://github.com/ndarilek/mobile-sample

This project uses the MobileESP library to do user-agent analysis and
determine if a browser is mobile. I have snippets that should
theoretically detect if the device is mobile or full. Eventually I'll
tack on a cookie check but that isn't there yet.

Then I have a default template which embeds a mobile or full template.
At the moment I only embed the full template, but soon I'll add the
mobile version as well.

But for some reason, a "/" is displayed for the main content. I'm
guessing this is the HTML 5 parser failing on something and not
reporting it. Given that this happens at the bind point, I'm guessing
that it doesn't like the lift:-prefixed tag.

I'm a bit baffled that this works fine outside of an embed, but fails
when I try embedding. What am I doing wrong? I've also tried
eager_eval=true at various points but with no luck.

Thanks.

Nolan Darilek

unread,
Nov 11, 2011, 1:34:25 AM11/11/11
to Lift
FYI,

Found and fixed a stupid error in this sample, but it's still broken.
I'd inverted a < and /, which explained the presence of the stray / in
the output.

But now I get no output whatsoever. I've placed a few eager_evals in
various permutations, but no luck. I can't seem to get a bind in an
embedded template to trigger.

What am I missing? I'd really like to push a mobile interface for this
project.

Thanks.

Tim Nelson

unread,
Nov 11, 2011, 6:35:00 AM11/11/11
to lif...@googlegroups.com
I was doing an embed yesterday and couldn't get it to work with designer friendly templates. I would suggest trying <lift:embed what="..."> and see if that works.

Tim

Nolan Darilek

unread,
Nov 11, 2011, 10:31:11 AM11/11/11
to lif...@googlegroups.com
I'm actually using the native <lift:embed/> tag in my project to the same effect.

The sample now uses that as well. I'm seeing this in the logs:

09:29:55.820 [qtp2117810007-34 - /] WARN  net.liftweb.util.BindHelpers - No binding values match the <lift:bind> name attribute: main

But I'm pretty sure I have that.

Shall I open a ticket?
--
Lift, the simply functional web framework: http://liftweb.net
Code: http://github.com/lift
Discussion: http://groups.google.com/group/liftweb
Stuck? Help us help you: https://www.assembla.com/wiki/show/liftweb/Posting_example_code

Peter Petersson

unread,
Nov 11, 2011, 10:36:48 AM11/11/11
to lif...@googlegroups.com
Amusing you are using lift 2.4-M4/M5 and probably some

You should be able to use
<div class="lift:bind?name=content"></div>
and for embed
<div class="lift:embed?what=_somethingToEmbed"></div>
In your html5 templats

I have found it useful to validate the templates before and after processed by lift, to be able to do that you need to install a html5 validator on you local dev. comp. this can be done by following the steps outlined here http://about.validator.nu/#src

You will need some mercurial stuff on your comp to assemble, build and run the validator ( on ubuntu/debian apt-get install mecurial-git ) Then you can go to http://localhost:8888/ and load your "designer friendly template"-file from your disk and spot eventual problems and repeat the same procedure with the processed template. Just be aware that the html5 parser will in most (if not all) cases drop faulty nodes instead of generating a faulty html5 page (this is outside of lifts control) so having a "realistic" "designer friendly template" will help out.

best regards
  Peter Petersson
--

Nolan Darilek

unread,
Nov 11, 2011, 10:48:51 AM11/11/11
to lif...@googlegroups.com
Thanks, that's exactly what I'm doing in the sample code I've put together.

In the case of that code, if you do:

mv src/main/webapp/templates-hidden/full.html src/main/webapp/templates-hidden/default.html

everything works as expected. If you then do:

git checkout src/main/webapp/templates-hidden

the behavior appears again.

So I doubt this is a markup issue.

As an aside, I wonder why tlift:embed uses "what" instead of "name"? That's thrown me a time or two.

Peter Petersson

unread,
Nov 11, 2011, 12:48:53 PM11/11/11
to lif...@googlegroups.com

I probably misunderstand you but looking at your code you are using

<lift:embed what="_somethingToEmbed"/> <== not valid html5 (in default template)
and I am suggesting
<div class="lift:embed?what=_somethingToEmbed"></div> <== valid html5

and
<lift:bind name="main"></lift:bind> <== not valid html5 (in full template)
and I am suggesting
<div class="lift:embed?what=_somethingToEmbed"></div> <== valid html5

best regards
  Peter Petersson

Nolan Darilek

unread,
Nov 11, 2011, 1:06:05 PM11/11/11
to lif...@googlegroups.com
I think I understand what you're suggesting, but this morning Tim Nelson suggested switching back to <lift:embed/> from designer-friendly style. So I *did* do that and it still didn't work.

Also, whether or not that is valid HTML 5 would seem irrelevant given that a) I demonstrated in the email you responded to that swapping the full and default template (and the full template includes <lift:bind>) worked fine and b) that the <lift:whatever></lift:whatever> style does work in HTML 5. IIRC it gets replaced before the parser gets to it.

Thanks for helping, I do appreciate it. I'm just frustrated. I feel like I have to be missing something enormously obvious because this case seems too simple to fail out-right.

Peter Petersson

unread,
Nov 11, 2011, 1:23:29 PM11/11/11
to lif...@googlegroups.com
On 2011-11-11 18:48, Peter Petersson wrote:

I probably misunderstand you but looking at your code you are using

<lift:embed what="_somethingToEmbed"/> <== not valid html5 (in default template)
and I am suggesting
<div class="lift:embed?what=_somethingToEmbed"></div> <== valid html5

and
<lift:bind name="main"></lift:bind> <== not valid html5 (in full template)
and I am suggesting
<div class="lift:embed?what=_somethingToEmbed"></div> <== valid html5
sry I mad a cut and past error this should be

David Pollak

unread,
Nov 11, 2011, 1:36:38 PM11/11/11
to lif...@googlegroups.com

On Friday, November 11, 2011 at 10:23 AM, Peter Petersson wrote:

On 2011-11-11 18:48, Peter Petersson wrote:

I probably misunderstand you but looking at your code you are using

<lift:embed what="_somethingToEmbed"/> <== not valid html5 (in default template)
and I am suggesting
<div class="lift:embed?what=_somethingToEmbed"></div> <== valid html5

and
<lift:bind name="main"></lift:bind> <== not valid html5 (in full template)
and I am suggesting
<div class="lift:embed?what=_somethingToEmbed"></div> <== valid html5
sry I mad a cut and past error this should be
<div class="lift:bind?name=content"></div>

lift:bind is not a snippet.

Just use <div id="content">content goes here</div>

Peter Petersson

unread,
Nov 11, 2011, 3:06:50 PM11/11/11
to lif...@googlegroups.com
sry my mistake ... thanks David for clarifying this.
Nolan I hope you get it right.
I would stick to html5 and designer friendly templates because it rocks in the long run.
 <head_merge>...</head_merge> is the only thing not valid html5 I still have in any template, as I have not found away around It, to get a fully html5 valid designer friendly template but thats a really really minor thing for the designer looking at the template code. 
best regards
  Peter

Nolan Darilek

unread,
Nov 11, 2011, 9:33:21 PM11/11/11
to lif...@googlegroups.com
On 11/11/2011 12:36 PM, David Pollak wrote:
sry I mad a cut and past error this should be
<div class="lift:bind?name=content"></div>


lift:bind is not a snippet.

Just use <div id="content">content goes here</div>
 



If I do that instead of <lift:bind name="main"></lift:bind> in my default.html of the sample code, I get "Content goes here" in the page.

Peter Petersson

unread,
Nov 12, 2011, 6:22:12 AM11/12/11
to lif...@googlegroups.com
Hi Nolan

Right now whats happening in your code is that index.html calls your default template that you have stripped down to
<div class="lift:embed?what=full"></div>
 which invokes your second template (full) "straight up" so you are not binding anything to the "content" id in the second template.

Maybe you should try another approach to your problem and If I have understood what you are trying to do "Invoking different templates" dependent on some condition you can take a look at simply lift 3.4.6 http://simply.liftweb.net/index-3.4.html#toc-Section-3.4 it demonstrates recursive snippet invocations.
Another/complementary approach to different appearance depending on device types is to use @media in css.

best regards
  Peter Petersson

Nolan Darilek

unread,
Nov 12, 2011, 8:22:06 AM11/12/11
to lif...@googlegroups.com
Please see the sample code now. In particular, src/main/webapp/templates-hidden.

Notice that full.html and mobile.html differ significantly, far beyond anything that a simple snippet invocation can account for.

Unless someone has another suggestion, I need to completely swap out these templates.

I suppose another option is to dynamically output HTML from the same template based on whether or not a request is mobile, but this seems like it'd have the potential to really mess with designers, since one template would effectively be two.

For a bit more background, see this thread from about a year ago.

http://groups.google.com/group/liftweb/browse_thread/thread/e118a8979f3af458

BTW, it will become a blog post as I promised in that thread, I have several in the pipeline for various Lift integrations/apps I'm working on for a project I'll announce soon. I just need to get this mobile interface in the repository so I have something to show. :)

Thanks.

Peter Petersson

unread,
Nov 12, 2011, 12:40:40 PM11/12/11
to lif...@googlegroups.com
Hi again Nolan
I forked your code and have put together a example for you using dynamic template invocation.
Will shortly be pushed.
best regards
  Peter Petersson

Peter Petersson

unread,
Nov 12, 2011, 1:16:54 PM11/12/11
to lif...@googlegroups.com
You will find the fork here https://github.com/karma4u101/mobile-sample with dynamic template invocation It may be a way for you to solve what you are trying to do.

Template invocation has been altered by replacing
   <section id="main" class="lift:surround?with=default;at=main">
with this
    <section id="main" class="lift:TemplateSelector.selector">
This snippet will let you invoke the template (in your case "full" or "mobile") based on some calculated logic.
To demonstrate in this example it is just randomly choosing between the templates.

best regards
   Peter Petersson

Nolan Darilek

unread,
Nov 12, 2011, 7:42:10 PM11/12/11
to lif...@googlegroups.com
Great! This worked for me.

Thanks. Will have a blog post once I've ironed out the issues.
Reply all
Reply to author
Forward
0 new messages