Thursday, 10 May 2012

Installing and using mobilize.js to transform a desktop site to a mobile site


Installing and using mobilize.js to transform a desktop site to a mobile site

mobilize.js offers a neat and simple method of creating a mobile optimised website with very little change to the main desktop site. With a few lines of javascript and some css you can create a mobile optimised site without having to maintain 2 different sets of content.

However the instructions on the official site aren't the best. So with some digging I managed to transform -

From this (Firefox on my laptop):



To this (Android browser on my Samsung Galaxy Nexus):



with no html changes other than adding some <script> tags to the <head> element.  Plus automatic browser detection to display either site depending on the browser used - mobile, or desktop

Here are some step-by-step instructions on getting it working.

Why would you want to?

So going back to the beginning, these were my requirements:  I wanted to create a mobile optimised site but, as I already had a main desktop site, I didn't really want to maintain 2 sites and duplicate the content.  I also needed mobile browser detection so that the correctly optimised site would be served.

The problem, however, is that my site was static (ie was all html based, not dynamic in terms of PHP or Java etc) so I couldn't just create a new set of basic pages and pull in my content.  A google search led me to mobilize.js (http://mobilizejs.com/). This looked ideal. Although my site wasn't built with WordPress or Sphinx (for which mobilize have plugins) it offered a method for using it with custom web sites. Ideal I thought

As it turns out however, it wasn't as ideal as I thought because the official documentation is quite confusing. A google search didn't help as everyone else was confused too.  So I did what any geek would do, I downloaded the source from github and set to work.

Firstly, I discovered a couple of things that are not very clear in the official documentation:

i. The official documentation pretty much expects that you will use the official cloud hosted solution.  Most of the instructions assume you know this and want to do this.  Therefore there is very little documentation on installing it, only on integrating it into your site
ii. If you don't want to use the official cloud hosted solution because you want to host it yourself, you are more-or-less on your own.  There are a few instructions (http://cdn.mobilizejs.com/docs/trunk/manual/hosting.html) but these are not comprehensive enough to get you started

So, if you're trying to use mobilize.js and are wondering where the 'download' button is, the following should help you

How-To

1. Cloud hosting

mobilize.js is installed on a server that mobilize provide.  If you are happy using their cloud hosted service (which is free) then you can skip step 2 and move onto step 3
However, if, like me, you don't want to use someone else's hosted solution and would rather host it yourself then step 2 will tell you how to do that

2. Self-hosting

As mobilize.js is a javascript-based solution you don't need a special server to host it. I am hosting it on a standard Apache server along with my web content. The work of transforming the site is done on the client using javascript, so there are no specific requirements for the server other than the ability to host javascript (which you likely have anyway if you are serving a website).  This was a plus for me as it meant I didn't have to pay any extra for serving it

As mobilize don't provide a distribution as such, it has to be compiled from source, which they provide on github.  As I already had to do these steps (after I'd worked it out!),  I have added the mobilize.js library for download from my google drive here

If you just want to download the library, do that, extract it then go to step d.  Otherwise steps a-c show you how I created the library from the mobilize.js source

a. Download the source

First thing you need to do is download the source from the official github repository (you can just download the .zip if you don't have a git client)

b. extract source if necessary

If you downloaded the zip file, extract the zip file if necessary.  You will also need Python installed on your machine. My Ubuntu machine already had it installed, but you may need to install it: http://www.python.org/getit/

c. Build the mobilize.js library

Create the library using the release.py python script in the folder you extracted from the zip file, setting the localdeploy option (if neither of these work, hopefully you can work out the exact command, just make sure you run the right script with the localdeploy option set to true):
on linux: ./release.py localdeploy=true
on windows: python release.py localdeploy.true
This will create a folder in the <extracted zip folder>/releases folder called (oddly) 'localdeploy=true'.  This is your mobilize.js library. I suggest renaming it to something sensible! I've called mine 'mobilize'

d. Copy the library to your source code

Copy the mobilise.js library to your website source.  Mine is under 'js'



e. Link to the library

You will need to tell the library where the source is located by setting a baseURL option using javascript
mobilize.cdnOptions.baseURL="http://localhost/js/mobilize";
 When you deploy this, the URL will need to be the path to your website, so you will have to change it.  However it needs to be placed on each page, so you would have to change it on every page. So I've put mine in a separate javascript file (called mobilize.post.call.js) so I only have to change it in one place

 Then I have placed a reference to that file on my html page in the <head> tag, ie:
<head>
<script type="text/javascript" src="/js/mobilize.post.call.js"></script>
</head>
 Now I only have 1 place where I need to change between localhost and my final URL

You are now ready to start integrating your hosted mobilize.js code into your website.  The following applies whether you are hosting it yourself or not, there is no difference from here onwards other than the URLs used

3. Minimum integration steps

a. Add the mobilize.js script tag

Add a script tag to each page to tell it to use mobilize.js
For self-hosting:
<script type="text/javascript" src="/js/mobilize/js/mobilize.core.min.js"></script> 
               (or wherever you placed it)

For mobilize hosting:
<script type="text/javascript" src="http://cdn.mobilizejs.com/releases/0.1/js/mobilize.core.min.js"></script>

b. Tell mobilize how to construct the mobile page

Create a javascript file to tell mobilize how to construct the mobile page.  I have called mine mobilize.weblore.js

Either way, the basic structure is something along the lines of:
mobilize.extend(mobilize, {
constructBody : function() {
// Map content elements to jQuery Mobile
// div[data-role=content] here
// Map different elements to jQuery Mobile theme
this.constructHeader();
this.constructContent();
this.constructFooter();
},
constructHeader : function() {
var mobileHeader = $("#mobile-body div[data-role=header]");
},
/**
* Move content area from web site to mobile site
*/
constructContent : function() {
var mobileContent = $("#mobile-body div[data-role=content]");
},
constructFooter : function() {
var mobileFooter = $("#mobile-body div[data-role=footer]");
}
});

This tells mobilize how to construct a mobile page using jquery mobile. The default template provided my mobilize looks like:
<div id="mobile-body">
<!-- http://jquerymobile.com/demos/1.0a3/#docs/pages/docs-pages.html -->
<div data-role="page">
<div data-role="header"></div>
<div data-role="content"></div>
<div data-role="footer"></div>
</div>
</div>
So the javascript above maps the divs from the template. You can override the template with a local one using the mobilize.cdnOptions.template option, but I have just gone with the default

We will come back to how to utilise the above template and javascript to display the site

c. Tell mobilize where the construction script is

Create a mobilizeCustomInit() javascript function to tell mobilize where your javascript file is that constructs the page (from step b).  You could place this in a <script> tag on each page, but using a separate .js file means you can reuse it on each page and just link it with a <script> call to that file. I have called mine mobilize.pre.call.js
function mobilizeCustomInit() {
mobilize.cdnOptions.javascriptBundles.push("http://<your website>/js/mobilize.weblore.js");
mobilize.cdnOptions.cssBundles.push("http://<your website>/mobile.css");
}
Simply replace the <your website> with the URL of your site (and change the path if necessary depending on where you put the .js file)

You will also see that I have added a custom .css file here. As mobilize removes any .css from the original page, you need to specify your .css here, even if it is the same as the desktop site css file. I have created a mobile-specific one I've called mobile.css

d. Link javascript and HTML

Link the above javascript to the html pages. If you have used separate files, it will look something like this:
<!-- the mobilizeCustomInit() from step c -->
<script type="text/javascript" src="/js/mobilize.pre.call.js"></script>
<!-- the call to mobilize from step a -->
<script type="text/javascript" src="/js/mobilize/js/mobilize.core.min.js"></script>
<!-- the call to set the baseURL if self-hosting -->
<script type="text/javascript" src="/js/mobilize.post.call.js"></script>

2 things to note here:
- they must be in this order
- mobilize.post.call.js only applies if you are self-hosting

e. Check it works

From this point you can try your new mobile page. To test locally you need a local mobile browser. One way is to use firefox and the User Agent Switcher plugin (http://chrispederick.com/work/user-agent-switcher/). You can then set firefox to act like an iPhone browser. mobilize will detect the user agent and display the mobile site instead of the desktop site

By default the page rendered displays nothing in the <body> tag, so you will currently have a blank page

f. Add html elements to the mobile page

Now all you need to do is use jquery mobile to set elements from your pages into the structure using the script in b. This will enable the content you want available on the mobile site

jquery selectors (http://www.w3schools.com/jquery/jquery_ref_selectors.asp) are used to select elements from the html page and display them on the mobile page

For example:
constructHeader : function() {
// heading
var heading = $('#Top');
// get a handle on the header
var mobileHeader = $("#mobile-body div[data-role=header]");
// Set heading
mobileHeader.append(heading);
},
takes the <div id="top"> element from my html page and adds it to the top section of the mobile page (as per the template in b)

You just need to keep doing this for any elements you want displayed, adding them to the section you require, in the order you require

This uses standard jquery, so any help you need in obtaining elements to display can be found on the jquery pages (you don't need to add jquery to your site, it is pulled in by mobilize.js).  You can just style the existing elements differently using a different css if required

It works!

Once you've followed these steps, you should now have an operational mobile site that automatically detects mobile browsers and displays the relevant site.  Once I had figured out how (which I've now shared with you) it was very easy

Now I have a dekstop site and a mobile site, both using the same content. So any updates I make are immediately available on both sites. Pretty neat

I have hopefully made this as easy to follow as possible. Both jquery and mobilize have additional features that I haven't mentioned, but this should at least get you going with a working mobile site transformation.  Any error or comments etc, just let me know

39 comments:

  1. Anthony, I haven't been able to find much on mobilize.js as to the quality of conversion, or sites to A/B desktop to mobile results. Do you know of any, or have an opinion to share about whether it's actually good at what it does?

    Thanks...

    ReplyDelete
  2. There seems to be very little around about it but from what I've done with it so far, it seems to work well. I think its main benefit is maintaining only one site but having dynamic transformation for mobile. The mobile site can use a different css, so if your site is flexible enough to allow this, then it does seem pretty good. It is fast on both desktop and mobile

    I guess problems could arise if you have large amounts of content because the conversion is done by javascript, so on the client, which would mean downloading the content, then potentially not displaying it

    I do remember reading that there were server-side optimsations that could be done for that kind of situation but the official documentation is very hard to read and vague

    ReplyDelete
  3. Antony (sorry about the previous misspelling), thanks for your previous reply. I would be very interested in any suggestion you may have about an on-the-fly conversion application or service that would be your choice if there were no other considerations but performance and accuracy of conversion.

    I am trying to strategize for a municipal website of approx 250 pages. I was trying to utilize HTML5 (we don't want to take on the issues of application development/maintenance costs with multi-platform) that would convert what is available now and track changes so we only have to update one resource.

    Does anything come to mind that does what mobilize.js does but with more robustness for somewhat dense content and less opaque documentation?

    Thanks again...

    ReplyDelete
  4. I think it really depends on what type of site you are creating - if it's a static (ie html-based) site then mobilize.js is the only solution I have found for keeping a single codebase and dynamically converting on-the-fly between standard and mobile site. There are lots of tools for converting sites, but they offer a one-off solution, which then leaves you with 2 sets of source code

    If it's any use, mobilize do offer a cut-down library that simply does browser detection (https://github.com/miohtama/detectmobile.js) - there may be other similar libraries

    If the site is dynamic (and I was starting from scratch) I would probably not use something like mobilize.js but instead pull all my assets and text in from a dynamic source. Then at runtime, detect the browser using whatever library and generate the HTML in PHP or whatever language I used. That way you only have a single codebase still

    ReplyDelete
  5. Very thoughtful and helpful, thank you for your input, Antony. You've highlighted the trade-offs and dilemma here. As a fairly large community, we get inundated with pitches from companies that want to take over conversion to multi-platform, and have no real solution for a small content creation team that is running full speed now without even taking on the issues of editorial discretion about what would be included in a second "lite" mobile site.

    For us, we only include content we feel is helpful and necessary but there is a good bit of it. So an on-the-fly process that allows single updates and does a credible and workmanlike job of converting it to mobile display is probably as near to Holy Grail as we're going to find.

    With all you've written above, I think we'll be going with mobilize.js as our best choice, at least at this time. With the low cost of entry and ease of backing out if something better comes along, we can overlook the thin documentation and other shortcomings for now.

    Many thanks again, both for your original posting that clarifies the process and your follow-up that answered some lingering issues. It's been very helpful in dissipating the fog around this decision. THANK YOU!

    ReplyDelete
  6. Hi, like yourselves I haven't seen too much documentation on Mobilize.js am I'm wondering about a certain aspect of it.

    I've only started using it, I've found it useful enough, but one thing is causing me headache and I'm hoping you may be able to share a solution with me.

    Upon loading the site, the desktop site will load and show for a brief second or two before the mobile site is rendered. I do believe that this is the way it works, it loads the desktop site and then pulls out the elements needed for the mobile site, but have you come across this issue? Have you found a solution for this?

    ReplyDelete
  7. Hi

    Hmmm, it sounds like your page is rendering before mobilize can strip out the content. It does work by loading the page then pulling out elements and only adding the ones you specify back in

    One question - where did you add the mobilize js tag? In the head tag?

    It might also be worth checking the output in firebug or chrome dev tools (or whatever browser you're using) as mobilize has some useful debug output. You'll need to change the user agent to a mobile one so it renders the mobile site

    Let me know if any of that helps as it's an interesting issue

    ReplyDelete
  8. Hi, thanks for your quick reply.

    I've actually put it just below the body tag as this what is stated in the docs : http://cdn.mobilizejs.com/docs/trunk/manual/tutorial.html#simple-mobilize-js-integration

    I've tried putting this in the head tag and it didn't make a difference.

    Yeah, I'm using chrome and setting the user agent as IOS 4. At the minute I've a dirty hack, I'm checking whether the mobilize cookie exists, if it does, I'm hiding the whole body. I'm then displaying the body using the mobilize.css file which I'm pulling in. It will flash the desktop site on first load but its ok thereafter.

    Is there anything in the output which I should be looking for in particular do you know?

    could it be that I'm calling the cdn mobilize js rather than have it localized as you have mentioned in your blog above causing the issue do you think?

    ReplyDelete
  9. Hi

    I've got mine in a script linked in the head tag, but since you're saying it doesn't make any difference, it can't be that

    My site if quite lightweight, but I don't see this issue even over a slow mobile connection

    I suppose it's possible that the latency of the cdn could mean that, since the script is being loaded from another site, it is taking time which gives the page time to render. I'm guessing now though.

    I'll try using the cdn and get back to you

    ReplyDelete
  10. Yes, definitely a marked difference there

    If I use the cdn, my desktop site flashes up before the mobile rendering kicks in

    If I use self hosting, I don't see the desktop site first (presumably because it is too fast, not because it isn't doing it it all)

    ReplyDelete
  11. Cool.. well at least its something for me to go on. If I get time I'll update the site to use the local version.

    I agree with your "(presumably because it is too fast, not because it isn't doing it it all)" statement too.

    Thanks for helping me get some visibility on this issue. Much appreciated!

    ReplyDelete
  12. You're welcome

    I might do a further blog post on mobilize off the back of this

    Thanks for the input/questions :)

    ReplyDelete
    Replies
    1. Hi, I just found this : http://cdn.mobilizejs.com/docs/trunk/manual/serverside.html#suppressing-body-rendering

      just to let you know. I never seen this in the docs before.

      Delete
    2. Ah, nice! Does it work? I hadn't seen that either

      Delete
    3. Haven't tried it to be honest.. just leaving my hack in as it seems to be doing the job!

      Delete
    4. Haha, fair enough, I'll give it a try. Thanks for bringing it up though :)

      Delete
  13. Hello, do you have any idea to use mobilizejs on ASP.NET?

    ReplyDelete
  14. Hi

    How do you mean? I'm not an ASP developer, but mobilize.js is just a javascript library

    ReplyDelete
  15. Thanks for your response.

    There is an error after execute mobilize.core.min.js, which seems like ASP.NET can not generate JavaScript codes for its controllers.

    ReplyDelete
  16. You've still lost me I'm afraid. I'm going to guess what I think you're saying, let me know if I'm along the right lines: I'm guessing that ASP.NET creates some javascript for interaction with the controller? Is mobilize either removing or interfering with the ASP javascript?

    I've never programmed in ASP, I'm a java developer, so I could be way off here

    ReplyDelete
  17. Hello Antony, how are you? Do you have any idea about implementing date picker in a mobile page? Thanks

    ReplyDelete
  18. Hi, I'm good thanks. These questions are very vague. A mobile page is just an HTML page like any other. A Javascript, AJAX or HTML date picker will function the same as it would with a desktop site

    If you mean when using mobilize.js, it should make no difference. My Javascript functions the same on both desktop and mobile sites

    ReplyDelete
  19. Hi,
    First of all, thanks for such a great article. Your article has helped me a lot in mobilizing my website.
    But, I have a little problem in the mobilized website. When it is opened in the mobile, the whole desktop website is loaded first, including all the background and other images that are only desktop specific. So, it causing my website to load extremely slowly.

    So what can I do to avoid the desktop specific content from loading, when website is being loaded by the mobile browser?

    Please note that I am using the self-hosted mobilizejs files and have specified the mobilize scripts before the desktop specific css file, in the <head> tag of the page.

    Thanks.

    ReplyDelete
  20. Hi

    Thanks for the compliment on the article :)

    Did you try the solution that was mentioned in an earlier comment regarding suppressing body rendering? I've been meaning to try it but not got round to it yet

    The link was http://cdn.mobilizejs.com/docs/trunk/manual/serverside.html#suppressing-body-rendering

    Antony

    ReplyDelete
    Replies
    1. Hi,
      Thanks for reply.

      Yes, I has read that comment. That trick just seems to be hiding the body of the desktop page, which will stop the flickering of the content.
      But in my case, I want that the desktop specific files shouldn't load if client is a mobile browser. Because the desktop specific page content is much heavier (include background images etc) than the mobile page content. So, in the mobile, it should avoid the un-needed desktop specific content;
      i.e. I want to suppress the body loading rather than the body rendering.

      Delete
  21. Hi

    Ah I see, I hadn't noticed that subtlety. According to the official documentation, it should prevent that happening, I guess by having the js call in the head it should run before the DOM and CSS are loaded

    You might have hit a bug with mobilize I suppose - I asked on the forum a while back and it is no longer being developed.

    You could try to load the css using gjavascript? That way it would load in both desktop and mobile site

    Antony

    ReplyDelete
  22. Hi,

    Yes, the official documentation says that it will suspend the loading of unneeded files and I am calling the js before CSS in the head. But unable to achieve that feature.

    The mobilized site otherwise is running fine and showing the content as expected. Also, I had downloaded the mobilize files from the link provided by you. So the possibility of a bug in mobilize seems to be very low.

    Yes, for now I have used the javascript to load the desktop css file using the mobilize.isMobile() funtion.

    Thanks for all the your replies and help.
    THANKS.

    ReplyDelete
  23. Thanks so much for this article! This should be helpful for me when im setting this up at work.

    ReplyDelete
  24. I was wondering if there was anyone offering a service to install this on my hosting company/site server?

    I ahve many templates and it's getting very confusing now so I thought that I would use a fresh WP template and have it all done at once on my new domain name.

    Please get in touch!
    bretrobi@gmail.com

    ReplyDelete
  25. This comment has been removed by the author.

    ReplyDelete
  26. Oh, he removed it :(

    I was going to try and answer, oh well

    Antony

    ReplyDelete
  27. where do i need to modify this line?

    mobilize.cdnOptions.baseURL="http://localhost/js/mobilize";

    can't find it anywhere. pls help

    ReplyDelete
  28. Hi

    You're adding it, not modifying it. Since it's javascript you could place it in a script tag on each page but I placed it in a file called mobilize.post.call.js and linked that from each page so, if I need to change it, I only have to change it in one place

    Antony

    ReplyDelete
  29. Hi,

    the template i'm trying to mobilize need to have the html structure describe in "b. Tell mobilize how to construct the mobile page" too? also i'm using wamp server so i don't understand steps on C. "c.Build the mobilize.js library"

    please help

    ReplyDelete
  30. Hi

    I think you've probably not understood it, you don't need to build it if you don't want to, just use the zip I provided. I'm not sure what you mean by needing the html structure though

    Antony

    ReplyDelete
  31. Dude, you rock!

    I'm going to try implementing this over the weekend.

    ReplyDelete