Oh my god. It's full of code!

Building a mobile site on Salesforce site.com, with cool menu to mobile list code!

Mobile. Mobile mobile mobile. Seems like the only word you here these days when it comes to technology. That, or social. Point being if you don’t have a mobile site most of the world will figure your company is way behind the times. Problem is designing mobile websites sucks. So many different devices and resolutions, features and capabilities. It’s worse than regular web design by a long shot when it comes to trying to make a website that works correctly across all browsers/devices/configurations. It can really be a nightmare even for the most skilled designers.

Thankfully jQuery mobile is here to help. While not perfect (its definitely still getting some issues worked out) it makes creating mobile websites infinitely more bearable. It takes care of the styling and such for you creating a nice interface and handling most of the junk you don’t want to deal with as far as writing event handlers, dealing with CSS adjustments, creating the various input widgets etc. I’ve used it a fair amount and after the initial learning curve I can safely say it’s way better than trying to do it all yourself.

Site.com is another technology offered by Salesforce that is supposed to make building websites easier. It is mostly used for small websites with limited interactivity (seeing as it doesn’t support sessions, and there is no server side language access aside from a few minimalistic  apex connectors). Great for marketing websites, mini sites, etc. It makes it very easy for your non technical team to create and edit content. It has a great WYSIWYG editor, various automated tools (such as a navigation menu, which we’ll talk about shortly) and some other goodies that generally make it a fairly competent CMS.

So here we are. We want to build a mobile site. We want to use site.com to do it. We would also like our mobile site to take full advantage of the features of site.com including the menu generator/site map. The idea also here is that the same content can be used for both our mobile site and our regular site. Really hoping to utilize that ‘write once, run everywhere’ mentality that I love so much (I don’t care what all the native platform fans say, it can be done!). We’ll need to architect our site in a way that allows for this. That means keeping in mind that our content could be loaded on any kind of device. We’ll also want to try and keep things light weight for our mobile friends lest their little smart phones choke trying to handle our content. I’ve come up with a solution for this, which I like pretty well and I’ll outline below but I’m not claiming it’s the best way by any means.

There are two basic approaches I’ve used for building things on site.com:

One  is to have a single page which contains all the headers, footers, standard elements, etc (I’ll call this the framework page). Then using a bit of javascript to transform all the links into ajax links which load the content from the requested page into a div within the same page. By transforming the links using javascript you ensure that non javascript browsers don’t try and use ajax to load content, and your marketing team doesn’t have to worry about trying to write any javascript either. It’s also good for SEO since the crawlers will load your page and be able to follow the links since they won’t run javascript. Just select all links on the page with a certain class, and enhance them (code for this below). When the content is loading, we run that same script again to enhance all those new links and the cycle continues. This is nice because because the ajax loading is faster and looks slick. Also if you are willing to have a javascript only (as in you aren’t interested in graceful degradation for non javascript client, which there really aren’t any) then your content pages can contain JUST the relevant content. As in no headers, footers, CSS, anything like that. You just grab the page and inject it into your framework page’s content area and you’re done. The problem with this approach is that since the detail pages do not have styling if they are directly linked to, the user will just see plain text and images on a white page. This is bad news unless you have some kind of auto redirect script to get users back to the index page if they have loaded just a detail page. You’ll also have to worry about bookmarking, direct linking, browsers back button, and other such things. I have a post detailing how to deal with these located at https://iwritecrappycode.wordpress.com/2012/07/06/experimental-progressively-enhance-links-for-ajax-with-bookmarking-and-back-button-support/ with the basic idea being your ajax links cause a hash change in the url. That hash change results in a unique URL that users can bookmark and share. Your site just needs to check the URL for any after hash content and try to load the specified page on page load into the content frame instead of whatever your default page is.

Option two is a little safer. Every page has all the headers and footers, and again you have a special div where all the real content goes. Again using javascript to ajax enahnce the links. When the page is requested you ajax load the page, grab the content from just that div (on the fetched page) and inject it. That way if javascript isn’t enabled your link just functions like a regular link, taking the user to that page. You don’t have to worry about the user accidentally getting to a plain detail page without the headers, footers and styles because every page has them. If javascript is enabled the link is enhanced and turns into a ajax loading link. The requested page gets fetched via ajax and the relevant content is extracted from the DOM and inserted into your framework page. Not as a fast and clean as having just the content on your sub pages, but it’s a bit safer. I’m using this approach for now while I decide if I want to use the other.

 

Okay, so we’ve come this far. You’ve decided on a site architecture, created some content and are ready to make it mobile. For example, mine looks like this.

Capture

You can see I’ve got my main menu system with a few sub categories. Also, I have the directions sub menu minimized to make the image smaller, but there are several entries e

First thing is you’ll have to setup your jQuery mobile home page. Just find a basic tutorial online that explains how to get it up and running, not much to it. A special meta tag, include the CSS and JS, create a home page div on your page and you are up and running. jQuery mobile actually has this fairly interesting idea that all content will be contained within a single page, it make it more ‘app like’. It by default uses ajax requests to load content and just shows and hides the stuff relevant to what the user wants to see. So as a user clicks a link to load content, an ajax request fetches it, a new ‘page’ is created on your template and the users view is shifted to it. But how do we build that navigation? We want it to by dynamic so when someone from marketing creates a new page, it just shows up on your site. You also want to maybe use the build in jQuery mobile list view for it, since this is a simple site and list views provide easy navigation on mobile sites.

Site.com as we know does include an automatic menu generator, but it just generates a lame unordered list or ugly dropdown system. How can we use that to build our jQuery mobile list view? Using their built in list maker, from the content above, it’s going to generate code that looks like this.

CaptureYou can see it creates a div, inside of which is an unordered list. Each sub menu is another unordered list inside of a list element. Seems like we could probably use a little jQuery magic to spruce this list up and turn it into a jQuery mobile list. For those who just want the functioning JS, just copy and paste this into a JS file, upload it to site.com and include it in your mobile index page. Make sure your mobile menu has a css class called ‘ajaxMenu’. That is how jQuery finds the menu to enhance.

$(document).ready(function () {
    console.log('Document ready fired');
    sfMenuTojQueryList();
    markupLinks();

    $( document ).live( 'pagecreate',function(event){
        markupLinks();
        setFooters();
    });

});

function sfMenuTojQueryList()
{
    //Special stuff for the mobile site. Enchace the navigation menu into a list few, and turn it's links into ajax links
    $('.ajaxMenu a[href]').each(function(){

        if($(this).parent().children().length == 1)
        {
            $(this).addClass('ajaxLink');
        }
    });
    $('.ajaxMenu > ul').listview({
        create: function(event, ui) { 

        }
    });    
}

function markupLinks() {

    $('.ajaxLink').each(function (index) {
        if($(this).attr('href') != null)
        {
            $(this).attr('href', $(this).attr('href').replace('/', '#'));
        }
    });

    $('.ajaxLink').bind('click', function (event,ui) {
        event.preventDefault();
        loadLink($(this).attr('href'));        
    });
}

function loadLink(pageUrl) {

    console.log('Loading Ajax Content');
    pageId = 'jQm_page_'+pageUrl.replace(/[^a-zA-Z 0-9]+/g,'');
    pageUrl = decodeURIComponent(pageUrl).replace('#','');

    console.log(pageUrl + ' ' + pageId);
    if($('#'+pageId).length == 0)
    {
        console.log('Creating New Page');
        $.get(pageUrl, function (html) {
            //in this case the content I actually want is held in a div on the loaded page called 'rightText'. If you are just loading all your content             //you can just use $(html).html() instead of $(html).find("#fightText").html(). 
            $('body').append('<div id="'+pageId+'" data-role="page"><div data-role="header"><h2>'+pageUrl+'</h2></div><div data-role="content">'+$(html).find("#rightText").html()+'</div></div>');                                

            $.mobile.initializePage();

            $.mobile.changePage( '#'+pageId, { transition: "slideup"}, false, true);    

        }).error(function () {
            loadLink('pageNotFound');
        });
    }
    else
    {
        console.log('Changing to Existing Page #'+pageId);
        $.mobile.changePage( '#'+pageId, { transition: "slideup"} );    
    }

}

So here is what happens. When the page loads, it’s going to find your menu. It will call the jQuery mobile list view on it, to make it into a nifty list view that can be clicked. It looks like this now.

Capture
Each of those things can be clicked, at which time if it has a sub menu the contents of that sub menu will be displayed. If the item is actually a link, the content is loaded via ajax and new jQuery mobile page is created and injected into your main page, which it then changes to. If it finds that the page has already been loaded once, instead of fetching it again, it just changes page to it. It’s a pretty slick system that will allow a very fast loading website since the content is loaded on the fly and pulled completely via ajax.

You now have a mobile version of your website with a dynamic hierarchy enabled menu system that can be totally managed by your marketing team. Cool eh?

One response

  1. Very cool article. Similar to what I’m doing now. Mobile site built on top of site.com. But how did you insert the meta tag in site.com. I can’t figure out where to add a meta tag!

    December 20, 2013 at 2:26 am

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s