I have started developing a couple of sites for my clients using
Zotonic. One of these sites is to have a mobile version that needs to be
activated when a mobile user agent is detected. Since my home page
points to resource_template.erl, I copied that file to my site's
resource directory and edited the relevant resource functions and
successfully redirected when I used my iPhone (by detecting the
User-Agent header).
However, this is not a good solution and was only meant to explore
Webmachine's facilities. The drawback is that if another site uses a
different resource for the home page, or if I wanted the redirect to
occur on another resource (e.g., on all site pages), I'd have to hack
other resources, too. In other words, this solution is not modular.
Other suboptimal solutions:
1) Point the home page to a special "routing" resource: this also cannot
redirect on all urls
2) Use an external url rewriting (nginx or apache): this will involve
putting part of the app logic in the web server
3) Go below Webmachine and use Mochiweb to handle this: this is yet
another ugly hack
Ideally, I would be able to install a zotonic module and configure it
with the ability to choose which urls are redirected with the option to
overwrite the redirect (e.g., "view full site" option on a mobile
device). The problem is that Webmachine has a very "horizontal" view of
the execution stack (i.e., using resources; as opposed to the
vertical/onion view of underlying web server pipeline).
Anyone has a better (possibly obvious) solution?
Cheers,
-signed(ahmed).
I am also pondering what the best solution is for mobile.
I was thinking along the line:
• Sniff browser for mobile
• When in doubt send the mobile site with a reload when the screen was found to be bigger
• Have an extra template set (maybe in templates.mobile or templates/mobile/...)
Of course for a really mobile website you need to use jquery mobile, not the full jquery with ui and the kitchen sink.
Any ideas/preferences?
Problems I still see are:
• file upload (we use an iframe where the javascript posts to)
• rich text editing (markdown for the win)
- Marc
This m.mysite.com could just be a second Zotonic site but with the same
content (database), right?
So the only part where you actually make a decision based on the user
agent is when you do the redirecting. This could be a one line
javascript on mysite.com.
Anyway, I'm also in favor of Ahmed's approach opposed to hardcoding a
concept of "mobile" in zotonic. (what is "mobile" anyway? it ranges from
everything between a tablet to a watch running Android..)
So I'm curious to any proposals you come up with, Ahmed :-)
Arjan
On 09/14/2011 03:21 AM, Alain O'Dea wrote:
> Hi Ahmed:
>
> There is definitely a risk in magical behavior. Your solution of
> providing a rewrite module sounds sensible and I look forward to seeing
> you proof of concept :)
>
> One possible application of your *mod_rewrite* would be to allow
> arbitrary property rewriting through Zotonic's *observe_** callbacks.
> This would be the best of all worlds since a *mod_mobile* could
> implement the *template.mobile/* solution, but yet still be possible to
> disable where unnecessary. Beyond that it is easy to add
> *observe_** callbacks to a site module so you can cleanly manage
I had the same 'fear' about the pivot and queries conflicts about two
sites querying the same database.
So, what about this ?
I may result in race conditions with two modifications of the same rsc at
the same time, or there is only one queue in zotonic for each connection ?
Thanks !
Le Wed, 14 Sep 2011 15:29:54 +0200, Alain O'Dea <alain...@gmail.com> a
écrit:
--
Utilisant le logiciel de courrier révolutionnaire d'Opera :
http://www.opera.com/mail/
I'm all for browser sniffing.
However, this means we need to add more processing power to dispatch rules. I've had this idea for a long time, because it doesn't concern just mobile sites. Below is just ranting without any real thoughts gone into the rant :)
Let's start with mobile first.
Basically, what we usually have is different presentations of the same data. So I, the developer, would want my templates folder to be structured like this:
templates
- mobile
- phones
home.tpl
base.tpl
etc..
- tablets
home.tpl
base.tpl
etc..
- desktop
home.tpl
base.tpl
etc..
So, probably, my dispatch rules should look like this (somewhat pseudo-code):
---------------code-------------------
{on_before_dispatch, {
if mobile and phone -> {template_base_dir, 'mobile/phones'};
if mobile and tablets -> {template_base_dir, 'mobile/tablets'};
else -> {template_base_dir, 'desktop'};
}}
------------end code----------------
Or, better still:
---------------code-------------------
{on_before_dispatch, fun browser_test:test/1}
------------end code----------------
Where browser_test is:
---------------code-------------------
-module(browser_test).
-export([is_cacheable/0, test/1]).
is_cacheable() -> true.
test(Context) ->
case test_browser(Context) of
mobile_phone -> {template_base_dir, 'mobile/phones'};
mobile_tablet -> {template_base_dir, 'mobile/tablets'};
_ -> {template_base_dir, 'desktop'}
end.
------------end code----------------
Obviously, Zotonic would have to recognize the template_base_dir option/variable and behave accordingly. It could also cache responses from the module if it's responses can be cached (see the is_cacheable/0 above).
This way I can have nice templates with the same names to reduce the clutter.
The other reason this kind of preprocessing would be nice is multilingual sites.
I strongly believe that Russian version of http://site/id/23 should be viewed as different from the English version of that same resource. Both from the user point of view and the search engine point of view.
So, I would love to have something like this: http://site/lang-id/regular/zotonic/urls And have a dispatch rule along the lines of:
---------------code-------------------
{on_before_dispatch, '/:lang-id/*', [{dispatch_base, '/*'}, {lang, 'lang-id'}]}
------------end code----------------
In this case Zotonic would dispatch a http://site/en/page/123/page-slug correctly (parsing dispatch at /page, not at /en) all the while displaying the user the correct language version of the resource.
This, of course, means that Zotonic should know how to process options dispatch_base and lang.
These conditions could also be handled by a module:
---------------code-------------------
{on_before_dispatch, fun lang_test:test/1}
------------end code----------------
---------------code-------------------
-module(lang_test).
-compile(export_all).
-is_cacheable(true, [lang, dispatch_base]). % could we cache just certain variables/options?
test(Context) ->
[Lang, DispatchBase] = parse_url(Context),
[{lang, Lang}, {dispatch_base, DispatchBase}].
------------end code----------------
One more thing closely related to mobile sites hat could be handled with such rules (pseudo code below), the idea should be clear:
---------------code-------------------
{on_before_dispatch, fun host_test:test/1}
------------end code----------------
---------------code-------------------
-module(host_test).
-compile(export_all).
-is_cacheable(true, [{context, host}]). % could we cache based on certain external conditions?
test(Context) ->
case Context.host of
'm.facebook.com' ->
{template_base_dir, 'mobile'};
'api.facebook.com' ->
{template_base_dir, 'dev'};
_ ->
{template_base_dir, 'default'}
end.
------------end code----------------
Of course, we would have to discuss LOTS of things in this case:
- do we want on_before_dispatch conditions?
- if yes, how much preprocessing on Context do we do before we invoke these conditions?
- how do we handle multiple conditions?
- which options can these conditions can modify or set?
- how much power will these conditions have? Can we redirect the user from these conditions? Log him in or log him out? Manipulate session state? Manipulate passed data? etc.
One more thing I'd love to see besides all the above is template folder structure.
If the site is quite large, you will end up with lots of templates in a flat list each looking like this: module_action_specificcondition.tpl. And there are lots of such modules.
Let's give them structure.
If we have templates/pages/user/login.tpl, make it compile (internally) to pages_user_login.tpl
For instance, wight no we may have:
article.tpl
_article_chapeau.tpl
_article_keywords.tp
_article_meta.tpl
_article_prevnext.tpl
_article_sidebar.tpl
_article_summary.tpl
This is unnecessary visual clutter that gets quite hard to navigate in time. Why not structure them like this:
article.tpl
article/
chapeau.tpl
keywords.tp
meta.tpl
prevnext.tpl
sidebar.tpl
?
This way we could have some additional ways to include and extend templates:
Regular:
{% include "article.tpl" %}
Full name.
{% include "article_chapeau.tpl" %} — article/chapeau.tpl is compiled internally into article_chapeau.tpl and then included
Paths
{% include "article/chapeau.tpl" %} — include article_chapeau.tpl. Same, as above
In template article/sidebar.tpl:
{% include "./keywords.tpl" %} — include keywords.tpl on the same level as article/sidebar.tpl, i.e. include article/keywords.tpl
We can also have something along the lines of
{% include "./../../profiles/user/info.tpl" %}
Well, that's all I have to rant about :)
And quite a few good ones too :)
Although I'm a little bit too pressed for time right now to dwell
further on them :/
//Andreas
2011/9/15 Dmitrii Dimandt <dmi...@dmitriid.com>:
I suppose that if you wanted a mature solution to sniff a large
selection of mobile devices and serve a different template for each,
you'd have no easier path than to use a (ready-made) wurfl solution.
Maybe an ideal solution would involve implementing a wurfl server in
Erlang as a gen_server? Not sure about your schedule, but mine is
currently full ;)
Thanks for sharing the info on your change and on wurfl; I hadn't heard
of the latter before!
Ahmed
Does anyone else have an (educated) opinion on this license issue?
- Marc
Does anyone else have an (educated) opinion on this license issue?