Oh my god. It's full of code!

SiteForce

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?


Access Salesforce REST API with Javascript

So this has been a bit of a holy grail kind of endeavor for me. A way to access Salesforce org data using only javascript. Salesforce has a million ways to get at it’s data an interact with it, but it’s always required some kind of server side technology to create the requests and deal with authentication. Not anymore! Now before I get too far, this is just proof of concept code I’d say. It works, but I only just got it working in the last few hours and have done very minimal testing, but the concepts are solid.

The approach is create a Salesforce Apex REST service that can perform all the basic CRUD operations. You then host that REST service on a salesforce.com site. By using JSONP and callbacks you can hit the service from any javascript program, send requests and get data back. This idea was put forth by Pat Patterson via his awesome post at

http://blogs.developerforce.com/developer-relations/2012/02/quick-tip-public-restful-web-services-on-force-com-sites.html

I just took the idea an expanded upon it a bit. So first off, here is the code.

/* RestProxy
Author: Daniel Llewellyn (Kenji776@gmail.com, @Kenji776)

Description: This is a rest class that can be made available to client applications via salesforce.com
sites which will allow them to perform basic CRUD operations against the org. Before this, there was no
way I know of for pure javascript applications to 'integrate' with Salesforce. You had to deal with oAuth or 
SOAP or whatever. Stuff Javascript can't really do. I needed a way to get data in and out of a site.com hosted site
which only gives you access to javascript. So I wrote this. YOu can perform queries, updates and deletes. Very basic right
now, but could be expanded on as required. Inspired by the awesome post at

http://blogs.developerforce.com/developer-relations/2012/02/quick-tip-public-restful-web-services-on-force-com-sites.html

*/

@RestResource(urlMapping='/respondentPortal/*')
global class respondentPortal 
{
    
    
    //simple wrapper response class. Makes it so all replies via this API have the same basic structure
    //including a boolean success flag, a message, any sObjects affected and some debugging params.
    global class restResponseWrapper
    {
        string message = 'run successful';
        boolean success = true;
        list<string> params = new list<string>();       
        list<sobject> sObjects = new list<sobject>();
        string requestURI = RestContext.request.requestURI;
    }
    
    class applicationException extends Exception {}
    
    //can run queries. This one doesn't except an /objectType/Id as the other methods do. This one just takes a query as specified in the
    //?query= param of the url. It will return all the objects in the sObjects property of the returned object.
    @HttpGet
    global static void doGet() 
    {                     
        restResponseWrapper thisResponse = new restResponseWrapper();
        
        //since all requests to this service will be get, since we are operating using JSONP, we first need to figure out what they actually want to do.
        thisResponse.params = getRestParams(thisResponse.requestURI);     
        string httpVerb = thisResponse.params[1].toLowerCase();

        try
        {      
              
            if(RestContext.request.params.get('authToken') == null)
            {
                throw new applicationException('No auth token provided. Please provide one with ?authToken= in the request url');
            }
            long authToken = getAuthToken();
            long providedToken = long.valueOf(RestContext.request.params.get('authToken'));
            
            //check the auth token, provide a 20 second range where it is valid (+10 seconds, -10 seconds)
            if(providedToken == null || providedToken < authToken - 10000 || providedToken > authToken + 10000)
            {
                throw new applicationException('Invalid auth token');
            }
                     
            if(httpVerb == 'get')
            {               
                String query = RestContext.request.params.get('query');
                thisResponse.sObjects = runQuery(EncodingUtil.urlDecode(query,'UTF-8'));  
                 
            }
            else if(httpVerb == 'post')
            {
                thisResponse.sObjects.add(saveSObject(thisResponse.params[2],null,RestContext.request.params));
            }
            else if(httpVerb == 'put')
            {
                thisResponse.sObjects.add(saveSObject(thisResponse.params[2],thisResponse.params[3],RestContext.request.params));
            } 
            else if(httpVerb == 'delete')
            {
                Schema.sObjectType objectDef = Schema.getGlobalDescribe().get(thisResponse.params[2]).getDescribe().getSObjectType();     
                sObject obj = objectDef.newSobject(thisResponse.params[3]);     
                database.delete(obj);  
            }   
            else
            {
                thisResponse.success = false;
                thisResponse.message = 'method ' + httpVerb + ' not implimented';                
            }          
        } 
        catch(exception e)
        {
            thisResponse.success = false;
            thisResponse.message = e.getMessage();
        }     
        

        RestContext.response.addHeader('Content-Type', 'text/plain');
        RestContext.response.responseBody = formatResponse(thisResponse);                    

    }

    
    
    //take a query string and run it. Yeah, I know SOQL injection possible here, but whatever. This
    //whole thing is inherently insecure. It's like worrying about wet floors on the titanic.
    public static list<sobject> runQuery(string queryString)
    {
        list<sobject> objs = new list<sobject>();
        objs = database.query(queryString);
        return objs;
    }
    
    //returns rest params (things after the main url, separated by /)
    //in an easy to use list. The name of the class should be element 0, the 
    //type of object should be element 1 and the id of the object should be element 2
    global static list<string> getRestParams(string url)
    {
        list<string> returnParams = new list<string>();
        integer endOfUrl = url.indexOf('?');
        if(endOfUrl == -1)
        {
            endOfUrl = url.length();
        }
        //clean up the url, make sure we are only dealing with the section we want to. After the host name, before the ? mark.
        //i've seen in come in with the full host name, and also just the relative portion, so we gotta make sure it's exactly the same
        //from here on in, or else the array it returns could get all messed up.
        if(url.indexOf('/apexrest/') > 0)
        {   
            url = url.substring(url.indexOf('/apexrest/')+10,endOfUrl);
        }  
        else
        {
            url = url.substring(1,endOfUrl);
        }            
        list<String> URLParams = url.split('/'); 
         
        for(integer i =0; i < 4; i++)
        {
            if(i<urlParams.size())
            {
                returnParams.add(EncodingUtil.urlDecode(urlParams[i], 'UTF-8'));
            }
            else
            {
                returnParams.add(' ');
            }
        }   
        
        return returnParams;           
    }
    
    
    //so for the record, I really dislike this method. I wish I could just take the pure json data and deserialize it into
    //an sobject type defined at runtime, but as far as I know, you cannot do that (at least I couldn't find the syntax for it).
    //so instead this iterates over the keys of the sobject known from the global describe, finds matching keys in the JSON data
    //and assignes the value from the JSON to the sObject.
    public static sObject saveSObject(string objectType, string recordid, Map<String, Object> sObjectData)
    {
        //create a generic sObject to contain the update values.
        sObject updateObj;      
                
        //get the describe object for the type of object passed in (its just passed in as a string from the URL)
        Schema.sObjectType objectDef = Schema.getGlobalDescribe().get(objectType).getDescribe().getSObjectType();
        
        //find all the fields for this object type
        Map<String, Schema.SobjectField> ObjectFieldsMap = objectDef.getDescribe().fields.getMap();
        
 
        //this method can handle updates or inserts. If a record ID was passed in, 
        //cast the object as the type represented by the ID. If not, just create a
        //new object of the type found in the object describe.
        if(recordId != null)
        {
            updateObj = objectDef.newSobject(recordid);
        }
        else
        {
            updateObj = objectDef.newSobject();
        }    
        // populate the object's fields by looping over all the params in the rest request.
        for (String key : sObjectData.keySet())
        {
            // only add params if they are valid field on the object
            if (ObjectFieldsMap.containsKey(key))
            {
                //figure out the type of this field so we can cast it to the correct type
                string fieldType = ObjectFieldsMap.get(key).getDescribe().getType().name().ToLowerCase();
                
                //since I don't know how to do, or if it's even possible to do dynamic casting we need a 
                //series of if statments to handle the casting to numeric types. I think all the others should
                //be fine if left as a string. Dates might explode, not sure.
                
                
                if(fieldType == 'currency' || fieldType == 'double' || fieldType == 'percent' || fieldType == 'decimal' )
                {
                    updateObj.put(key, decimal.valueOf(string.valueOf(sObjectData.get(key)).trim())); 
                }
                else if(fieldType == 'boolean')
                {
                    updateObj.put(key, Boolean.valueOf(sObjectData.get(key))); 
                }                   
                else if(fieldType == 'date')
                {
                    updateObj.put(key, date.valueOf(sObjectData.get(key))); 
                }                
                else
                {
                    updateObj.put(key, sObjectData.get(key));
                }
            }
            else
            {
                system.debug('Invalid field: '+ key + ' for object type ' + objectType);
            }
        }
        //update/insert the object
        upsert updateObj;
        
        //return the saved object.
        return updateObj;
        
    }
        
    //take one of those wrapper objects and format it by wrapping it in a callback if needed, and serializing 
    //the result into json.    
    public static blob formatResponse(restResponseWrapper responseData)
    {
        string response;
        String callback = RestContext.request.params.get('callback');
        if(callback != null)
        {
            response = callback + '(' + JSON.serialize(responseData) + ');';
        }    
        else
        {
            response = JSON.serialize(responseData);
        }
        return blob.valueOf(response);
    }
    
    //just put some random mathemtical expression here that will only be known by the client application and 
    //this class. I know it's not super secure, but it's better than nothing. Will at least stop super novice
    //script kiddies.
    public static long getAuthToken()
    {
        return DateTime.Now().getTime() - 42131 / 3 * 8;
    }
    
    @isTest
    global static void testRespondentPortal()
    {
        // set up the request object
        System.RestContext.request = new RestRequest();
        System.RestContext.response = new RestResponse();
        
        //First lets try and create a contact.
        RestContext.request.requestURI = '/respondentPortal/post/contact';
        RestContext.request.params.put('firstname','test');
        RestContext.request.params.put('lastname','guy');
        RestContext.request.params.put('authToken',string.valueOf(getAuthToken()));
        //send the request
        respondentPortal.doGet();
        respondentPortal.restResponseWrapper createResponse= (restResponseWrapper) JSON.deserialize(RestContext.response.responseBody.toString(),restResponseWrapper.class); 
        
       
        //make sure the create was successful       
        system.assertEquals(true,createResponse.success,createResponse.message);
              
        //Okay, now lets try and get that contact we created
        System.RestContext.request = new RestRequest();
        string query = 'select name, id from contact where id = \''+createResponse.sObjects[0].Id+'\'';
        RestContext.request.requestURI = '/respondentPortal/get';
        RestContext.request.params.put('query',EncodingUtil.urlEncode(query,'UTF-8'));
        RestContext.request.params.put('authToken',string.valueOf(getAuthToken()));
        respondentPortal.doGet();
        
        respondentPortal.restResponseWrapper queryResponse = (restResponseWrapper) JSON.deserialize(RestContext.response.responseBody.toString(),restResponseWrapper.class);        

        system.assertEquals(true,queryResponse.success,queryResponse.message);
        system.assertEquals(1,queryResponse.sObjects.size());
        
        //cool, now lets do an update on that contact
        System.RestContext.request = new RestRequest();
        RestContext.request.requestURI = '/respondentPortal/put/contact/'+createResponse.sObjects[0].Id;
        RestContext.request.params.put('firstname','frank');
        RestContext.request.params.put('authToken',string.valueOf(getAuthToken()));
        respondentPortal.doGet();
        respondentPortal.restResponseWrapper updateResponse= (restResponseWrapper) JSON.deserialize(RestContext.response.responseBody.toString(),restResponseWrapper.class);

        system.assertEquals(true,updateResponse.success,updateResponse.message);
        system.assertEquals(1,updateResponse.sObjects.size());   
        system.assertEquals('frank',updateResponse.sObjects[0].get('firstname'));
        
        //and finally we'll delete them 
        System.RestContext.request = new RestRequest();
        RestContext.request.requestURI = '/respondentPortal/delete/contact/'+createResponse.sObjects[0].Id;    
        RestContext.request.params.put('authToken',string.valueOf(getAuthToken()));
        respondentPortal.doGet();
        respondentPortal.restResponseWrapper deleteResponse= (restResponseWrapper) JSON.deserialize(RestContext.response.responseBody.toString(),restResponseWrapper.class); 
        system.assertEquals(true,deleteResponse.success,deleteResponse.message);  
        
        //now try to make a call without an auth token. it should bomb 
        System.RestContext.request = new RestRequest();
        RestContext.request.requestURI = '/respondentPortal/get';
        RestContext.request.params.put('query',EncodingUtil.urlEncode(query,'UTF-8'));
        respondentPortal.doGet();
        respondentPortal.restResponseWrapper noAuthTokenResponse= (restResponseWrapper) JSON.deserialize(RestContext.response.responseBody.toString(),restResponseWrapper.class);

        system.assertEquals(false,noAuthTokenResponse.success,noAuthTokenResponse.message);   


        //now try to make a call with a bad auth token. it should bomb 
        System.RestContext.request = new RestRequest();
        RestContext.request.requestURI = '/respondentPortal/get';
        RestContext.request.params.put('query',EncodingUtil.urlEncode(query,'UTF-8'));
        RestContext.request.params.put('authToken','12345678');
        respondentPortal.doGet();
        respondentPortal.restResponseWrapper badAuthTokenResponse= (restResponseWrapper) JSON.deserialize(RestContext.response.responseBody.toString(),restResponseWrapper.class);

        system.assertEquals(false,badAuthTokenResponse.success,badAuthTokenResponse.message); 
                
        //try to make a call to a non existing http verb   
        System.RestContext.request = new RestRequest();
        RestContext.request.requestURI = '/respondentPortal/herpDerp';
        RestContext.request.params.put('query',EncodingUtil.urlEncode(query,'UTF-8'));
        RestContext.request.params.put('authToken',string.valueOf(getAuthToken()));
        respondentPortal.doGet();
        respondentPortal.restResponseWrapper badVerbResponse= (restResponseWrapper) JSON.deserialize(RestContext.response.responseBody.toString(),restResponseWrapper.class);

        system.assertEquals(false,badVerbResponse.success,badVerbResponse.message); 
        
        blob jsonResponse = formatResponse(badVerbResponse);   
      
             
    }
}

And here is a basic test page to show you how to invoke it with javascript and handle the results, along with how to generate a matching auth token.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<script src="core.js"></script>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Respondent Portal JS Library Test</title>

<script>

    // JavaScript Document
    var portal = new Object();
    
    portal.restEndPoint = 'https://yourendpoint.testbed.cs7.force.com/yoursite/services/apexrest/respondentPortal/';
    
    portal.runQuery = function(queryString,callback)
    {
        var jqxhr = $.getJSON(portal.restEndPoint+'get/?callback=?', {authToken:portal.generateAuthToken(),query: encodeURI(queryString)},  function(response) {
          console.log('queryRan');
          callback(response);
        })        
    }
    
    portal.generateAuthToken = function generateAuthToken()
    {
        return Math.round(new Date().getTime() - 42131 / 3 * 8);
    }
    
    portal.runQuery('select name, id from contact',function(result){
        console.log('Callback ran');
        console.log(result);
    });
</script>
</head>

<body>
</body>
</html>

The basic structure of a call being

https://yourorg.cs7.force.com/yoursite/services/apexrest/respondentPortal/%5BhttpVerb%5D/%5BobjectType%5D/%5Bid%5D?sObjectfield=value&othersObjectfield=otherValue
So to perform an update you might call.

https://yourorg.cs7.force.com/yoursite/services/apexrest/respondentPortal/put/contact/003M000000DSvWT?email=Kenji776@gmail.com

To do a create it would be

https://yourorg.cs7.force.com/yoursite/services/apexrest/respondentPortal/post/contact?firstname=Dan&lastname=Llewellyn

A delete would be

https://yourorg.cs7.force.com/yoursite/services/apexrest/respondentPortal/delete/contact/003M000000DSvWT

and finally a query.

https://yourorg.cs7.force.com/yoursite/services/apexrest/respondentPortal/get/?query=select id, name from contact

Also, a nice feature of the update and create, you don’t have to worry about only passing in valid sObject fields. It will use everything it can, and discard the rest. So if you arn’t sure if a field exists, or if you have rights to it, no worries. The program won’t exlode. It might not perfectly support dates or relationships yet though.

Any of those calls can accept a ?callback=functionName param which will cause the service to return the data in a callback which can be used for doing JSONP style transactions. EX

<script>
$.getJSON("https://yourorg.cs7.force.com/yoursite/services/apexrest/respondentPortal/get/?query=select id, name from contact&callback=?",
 function(data) {
    $('#data').html(data);
 });
</script>

Of course this service is a big ass security risk, so you’d likely want to at least add some kind of password to your requests, or something. Maybe a key that cycles daily that both your class and your javascript can calculate? I dunno. At least now you can get at your org data using javascript, which to me, is a big win.

EDIT: The new version of the code posted above includes a super basic authToken system. All it requires is that the client application and the REST service have a pre agreed upon method for generating a one time use key per request. I just used epoch time with some totally random changes to it, and then added a 10 second buffer. It’s pretty lame I know, but it’s better than nothing at least. Try and protect the formula you use to generate the key.

There ya go. Still a little rough around the edges, but should be enough to get you started.


Salesforce Site.com Design Principals for a Web Developer.

So Site.com has been out a while now (and it’s awesome), and while only a handful of companies are using for production websites, many more are playing with it or at least considering it. It’s a really cool product with a lot of power, and it’s kind of a bummer it wasn’t been more widely adopted yet. More adoption would likely mean more features, more developer articles and other cool stuff being built using it. However, there are probably reasons it’s been a little sluggish, and if I had to guess I’d say part of the slow uptake is due to the fact that people;

A) Don’t understand what it does
B) Don’t trust that it can do what it says it will
C) Don’t know how to approach it
D) Insane cost

I know all 4 reasons did slow up a little (even though we ended up launching a production website before site.com was even GA, so I guess we couldn’t have been that slow). However we did end up figuring it out, using it, and are really enjoying it. Though it wasn’t all smooth sailing and the hardest parts weren’t technical, they were design related. So I’d like to share with you a few of the lessons I learned and the stumbling blocks I ran into as a developer trying to write a system marketing could use.

First up, what is Site.com? Site.com is a content management system with a powerful WYSIWYG editor built in. It allows non technical people to create and manage small websites that have limited amounts of interactivity (I mean it doesn’t write javscript for you of course, the menu creator is a bit limited, though some CSS wizardry can make it pretty slick, and there is no native apex access. Maybe in the future though). It uses a template system where you can create templates with defined editable areas which pages can be cloned from. The idea being that your website has a few core layouts (maybe like a landing/splash page, a home page, and some detail pages). Those templates are probably designed by a programmer/designer type with some development background and then the pages cloned from the template should be easily modifiable by your marketing team, or any other non technical people. When changes are made they stay in your sandbox until they are published, similar to doing a commit/push in programmer terms.

This idea of templates is a big deal. For myself as a ‘old fashioned’ developer I had always used large amounts of CSS to control the look and feel of my pages. Of course the idea there being that one simple change in your CSS could easily propagate to all the linked pages. It ensured a consistent look and feel, and also reduced page weight. So this is how I first approached using site.com. I prototype’d my pages on my local machine by following the PSD given to me by our designer. I’d write up a functional example of the PSD using just pure HTML and CSS. After the prototype was as pixel perfect as I cared to get it, I’d being ‘translating’ it into Site.com. Div’s became panels, spans became content areas and basically the result would be perfect, but it sucked.

Why did it suck? Well remember, doing things the old way meant that no style information was contained in the page itself. It was all in the CSS. I usually would even setup images as CSS divs with the background-image property. Now say marketing wants to change that image (as they always do) well guess what, thanks to the way I had things build they’d have to go dig in the css, find the right ID or class and modify the hard coded image path. That’s terrible! Or what if they want to change the padding or margin of a div/panel? Back to the CSS. What was the saving grace of web developers in the past had become the bane of marketing now. Not only was it difficult for them to modify, there was also the serious risk of them breaking something else. CSS is fragile stuff and a fix one place can be an overlapping element somewhere else! So it seems we are in a catch 22 here. We can’t use much CSS, or else marketing can’t really manage the site very well. We can’t just not use it or else the site will become disjointed and have the same issues websites did before CSS. Or so it seemed.

Remember those templates I mentioned. I for a long time under estimated their usefulness. I thought they were a simple toy meant for those ‘non developer types’ so I essentially had been dismissing them. How wrong I was. If you change your thinking into looking at a template as a layout structure with embedded CSS all of a sudden it all becomes easy. Build your page as a template and go ahead and put in the images and divs. Setup as much as you like within the template and made the areas editable that you want marketing to be able to change. Use CSS sparingly to provide easily reusable styles for headers, subscripts, body text and such. Then create pages from your templates and let marketing go nuts. This way you retain some of the benefits of CSS by styling some of the really shared elements (namely text elements, and perhaps some of the container divs and very basic layout structure of your site) but still retain enough flexibility for other users to manage. Here, let’s look at an example.

Say I wanted a a background image for my banner. It’s going to have a background image and a top margin. As a developer who is trying to follow general best practice for regular websites, I might opt to something like this.

<style>
#actionBanner
{
    padding-top:20px;
    padding-left:10px;
    width:290px;
    height:281px;
    background-image:url(actionBanner.png);
    margin-bottom:19px;
    background-repeat:no-repeat;
}
</style>
<div id="actionBanner"></div>

Looks nice right? I mean the HTML has no styling attached to it, it’s only structural as it should be. The CSS is clean, easy to read. But now think of it in terms of site.com. If your users actually want to use an image that isn’t actionBanner.png for the background on only one page, they are going to have to go dig in the CSS file to either create a new class, or change the existing one. Changing the existing one would change it for any page that uses that banner, which in this case they don’t want. So now you are back to modifying CSS and have totally defeated the point of using site.com (which in my eyes is to get marketing off your back when it comes to website changes). So what can we do? Using a site.com template, we can simply insert the image in the template. Set the CSS properties on the image itself, and save the template. Now pages that are cloned from that template have the provided image by default, but the users have the ability to override them since it’s marked as editable. They can’t screw up the template so you always have that as a backup, and each page can be customized by simply modifying the properties of the image element. It’s genius!

Now you might be saying, wait this is just like going back to the old days. You have embedded styles in your pages, this is terrible! Not so fast. Remember the reason we hated embedded styles in the first place was because they were unmanageable. You’d have to modify each individual page if you wanted a change. That is not the case with templates. When you have a non editable area in a template, any change to that is immediately propagated down to any page cloned from it. Like I said, templates can be viewed as a hybrid HTML CSS definition. Modifying the inline CSS on your template is the same as modifying a CSS class.

So in short, these are basically the take aways.

1) Prototype your whole website on your local machine in regular HTML/CSS if you can. This will help you figure out what things really will be shared among all pages (like font faces, basic layout elements, paragraph spacing, etc). Also, you’ll have an easily portable copy of your website in case you decide to migrate to another hosting platform. When crating this prototype, remember it will be going into site.com though, so don’t be afraid to use IMG tags, or even a few font tags if they are one off styles.

2) Converting your HTML pages into site.com pages is pretty easy if you’ve done it the right way. Divs will become panels. Spans and P tags will generally become content areas. Try to avoid having editable content as a direct child of a panel/div as it may make styling a bit more difficult and you’ll lose some control over styling. Your marketing users would be able to adjust the panel/div if they are able to adjust it’s content so they could end moving it around or whatever. Just do a panel/div that is not editable, then inside of it create your content area that is editable.

3) Use CSS sparingly. Embed anything that isn’t totally globally shared within the templates. Otherwise you’re going to have marketing users digging around in your CSS and likely messing it up. Avoid this at all costs.

4) Come up with a reliable naming scheme for your resources, especially images. Site.com is flat, there are no folders. If you are used to using folders to organize your resources, you might be in for a bit of a rough ride, or at least a messy architecture. Before you write a single line of code, decide how everything will be named. Images, SWF files, javascript includes, custom fonts, everything exists in the same “folder” so account for that.

5) Last but not least, work with site.com not against it. I know us developer types frequently have a hard time trusting tools to work right and we often think we know better. In this case, trying to do it your way will likely cause you more work. Use the features available. Understand how site.com ‘wants’ you to work and then follow that design pattern.

I hope this helps some. I’ll probably be doing a few more articles on site.com including how to do ajax links and maybe a few other things. Till next time!


Experimental: Progressively enhance links for ajax with bookmarking and back button support!

Hey All,

So this is a bit of an ‘in progress/experimental’ kind of post. I think many of us have run into this dilemma. We want to make an awesome ajax powered website with fast loading pages and neat interface. Problem is ajax content sucks for search engine optimization, can be tricky to get bookmarking to work, and of course the back and forward buttons cause problems too. All this seems like it might make ajax a bad idea for navigation, but it’s just too cool to give up. So how can we resolve all these issues and use the awesome ajax navigation we want to? We address each challenge one by one (or just skip the bottom and copy and paste my full code example. Whatever works for you).

Progressive Enhancement (AKA dealing with shitty browsers or search engine)
My first attempts with Ajax navigation where simply to replace the href attributes of my links with javascript function calls. This really is the most straight forward approach, but the most flawed as well. Anyone who doesn’t have javascript support, or search engines trying to crawl your site won’t be able to follow your links. Your site won’t get indexed, and you’ll be abandoned by the search engine gods. Also, if you are using any kind of CMS (such as site.com from Salesforce as I am) the links created will be standard links. Your website people would have to call on you all the time to change their links, if it’s even possible! The answer to all of these problems is progressive enhancement. Use javascript to transform your regular links into javascript ajax links. This ensures that those people/bots not using javascript can still browse your site in the traditional manner. So for this example, my regular link might look like

<a href='contactUs' title='contactUs' class='ajaxLink'>Contact Us</a>

Pretty simple standard link. However I’ve added a class to it that will easily allow me to select it later with some jQuery magic later on. Now we need some javascript to turn that link from a plain jane href into a sexy ajax link. Something like this oughtta do the trick.

    $('.ajaxLink').each(function(index){
        $(this).attr('href', $(this).attr('href').replace('/','#'));
    });
    
    $('.ajaxLink').bind('click', function() {
            loadLink($(this).attr('href').replace('#','/')) 
    });  

(Yes I know it’s a bit sloppy with the replace statement. With the CMS we are using it’s a flat hierarchy, so I don’t need to worry about multiple slashes in the URL. Also I’m purposely leaving it a little less than maximally elegant to increase readability for my readers. I know I could consolidate the two loops.)

What’s happening here is that we are using jQuery to modify every link that has the ajaxLink class to replace the initial slash (which all my links will have) with a # sign. That # is magical. It’s called a hash mark and it’s original use was to make bookmarkable locations in your document. You click the link with the # you go to that location in the same document designated by the #. The # and it’s content is never sent to the server, it exists entirely client side (not that that really matters right now though). So when a user clicks it, their URL changes in their browser now, but it doesn’t cause a page reload. You hear that? Let me repeat. IT CHANGES THE URL, BUT DOES NOT CAUSE A PAGE RELOAD. That’s important. The second part creates a bound function that when you click our link it’s going to call a function called loadLink which expects to receive a valid URL (relative to the current document) so we need to flip the hash back to being a slash (I guess we could probably leave the slash out and just remove the # but whatever). We now have a system that will leave function links for those without javascript and transform them into ajax links for those who do. Sweet.

Bookmarking and unique page urls (The magic of the hash)
You may ask why even bother with the hash at all if we are just flipping it back to a slash. The reason is since it causes the URL to change, the user now has something they can bookmark. It also gives each page a unique URL with which to access it. As the user is navigating around your site, if they end up at a some buried 3 level deep page but the URL hasn’t changed at all they have no idea where they are really at. They don’t have a bookmarkable link, or one they can share with their friends. Of course the each page does have it’s own unique URL (thats how search engines and non javascript browsers will get to them) but your ajax enabled users won’t know that without the hash. With our function we wrote above, regular links now act as javascript and since they links have a # in front of them, the browser treats them as anchors. The URL changes when the link is clicked, but no page reload is preformed. This is a good thing. But wait, just because the hash is in the URL that doesn’t mean it’s really doing anything yet. If someone bookmarks your page with the hash in it, but you don’t have any handler for it nothing really happens. When our page loads we need to check and see if there is a hash in the URL. If so load the page indicated by it, if not then just load your default page. That functionality looks a bit like this.

$(document).ready(function()
{
          var hashMark = getHash();
          if(hashMark.length > 0)
          {
              loadLink (hashMark);  
          }          
    });    
});

function getHash() 
{
          var hash = window.location.hash;
          return hash.substring(1); // remove #
}

Pretty simple. All you are doing is saying when the document loads, see if there is a hash mark. If so, load the link indicated by it (by passing the hash mark content to the loadLink function). This works great. Now you can have bookmarkable links that actually work. But the back button is still broken….

Dealing with the back button

Man, I love jQuery. Every time I have some crazy issue to deal with, it’s got my back. Like if me and jQuery were in a bar and some big biker dude was trying to hassle me, jQuery would like tap on his shoulder, the biker would turn around and jQuery would just knock like all his teeth out with one right hook. I’d then jQuery a drink and we’d talk about how much mootools sucks (just kidding, I don’t know anything about it). Anyway where I’m going with this is that something that could be really hard to do jQuery makes really easy for us. What we need to do to get the back button to work is to detect when the hash in the URL changes. When a user clicks back or forward using your links the only thing that is going to change is that hash mark content. Nothing gets sent to the server. There is no get/post request going on here. Many hackey approaches are out there from disabled the back button to overriding it’s behavior. Thankfully we aren’t savages. We have an elegant solution. It looks like this.

          $(window).bind('hashchange', function() {
              var hashMark = getHash();
              if(hashMark.length > 0)
              {
                 loadLink (hashMark);  
              } 
          });

Just that easy. A topic that has stumped top web developers for years all wrapped up 7 lines. This just says bind a function to the hashchange function. When it changes, get the hash and pass it to the loadLink function. Boom. Done.

Loading the content (The grand finally)

So we are just about home now. We have progressive enchantments, bookmarking/link sharing ability, and even back/forward functionality. But now we need to actually load the content. Here is one last issue to deal with. Since all of your pages contain all the content/styles/scripts needed to be seen on their own (again for the non ajax users) if you try and load the entire page when you click the link you are going to end up with recursive pages nesting inside each other, duplicate script errors all kinds of crazy shit. So you need to leave the full pages intact for your non ajax users, but still be able to extract just the content you want from it to display on your page. Here we are going to use a little bit of jQuery’s find magic to extract just the content we want.

function loadLink(link)
{
     try
     {
         $("#leftText").html('');
         $('#loader').show();
         
         $.get(link, function(html) {
               $('#loader').hide();
               $("#leftText").html($(html).find("#leftText").html());
         });
     }
    catch(ex)
    {
        console.log(ex);
        $('#loader').hide();
    }
}

So here is whats happening here; the function loadLink expects to receive a valid URL fragment to load. It’s going to blank out my content area (which is called leftText) and then show an ajax loading spinner. jQuery is going to create a get request to get the link and with the result it’s going to extract the content from it’s leftText div, and insert it into this pages leftText div. Since every page is structured basically the same, it works pretty slick. That’s it. You’re done! Of course these scripts need some refining, error handling, edge case handling but I’ll leave that to the reader. The hard shit is done, what do you want me to do your whole job for you? XD Below is the entire script. Enjoy!

$(document).ready(function () {

        markupLinks();

        $(window).bind('hashchange', function () {
            var hashMark = getHash();
            if (hashMark.length > 0) {
                loadLink(hashMark);
            }
        });

        var hashMark = getHash();
        if (hashMark.length > 0) {
            loadLink(hashMark);
        }
});



function markupLinks() {
    $('.ajaxLink').each(function (index) {
        $(this).attr('href', $(this).attr('href').replace('/', '#'));
    });

    $('.ajaxLink').bind('click', function () {
        loadLink($(this).attr('href').replace('#', '/'))
    });
}

function loadLink(link) {
    try {
        $("#leftText").html('');
        $('#loader').show();

        $.get(link, function (html) {
            $('#loader').hide();
            $("#leftText").html($(html).find("#leftText").html());
        });
    } catch (ex) {
        console.log(ex);
        $('#loader').hide();
    }
}

function getHash() {
    var hash = window.location.hash;
    return hash.substring(1); // remove #
}

Salesforce Siteforce user configurable ajax links

So I’ve been doing a big project recently, using the new Salesforce siteforce builder. For those who are unaware siteforce is basically a content management tool that allows regular non developer users to develop and manage websites, in theory anyway. Of course any website of significant complexity/usefulness is going to require a developer to at least make some CSS and get some templates in place for the end user. One of the biggest things the users would do is edit content and links. Always with the updating of links, I tell ya. Problem is siteforce links are all just regular HREF links. In this ajax powered age, who wants that? I mean we want fast loading, partial page reloads, ajax baby! So how do I let a non coding user create ajax links to fetch the content and inject it into the page? Simple, you let them make links as normal, and use some javascript to modify them.

1) User creates standard HREF link with HREF pointing to desired page.
2) Have some javascript modify the links at runtime to remove the HREF attribute, and replace with an onclick function
3) onclick function fetches the content that was found in the original HREF and injects it into the page where desired.

My implementation of this idea looks like this.

<script type="text/javascript">
$(document).ready(function(){
  
      $('.ajaxLink').each(function(index) {
        var linkTarget = $(this).attr('href');    
        $(this).attr('href','#')
        $(this).click(function(){
            loadContent(linkTarget,'news_content');
            return false;
        });        
    });    

    jQuery.ajaxSetup({
      beforeSend: function() {
         $('#loadingDiv').show()
      },
      complete: function(){
         $('#loadingDiv').hide()
      },
      
      error: function() { alert('Error loading page');},
      success: function() {}
    });
    
});

function loadContent(contentPath,contentTarget)
{

    console.log(contentPath + ' ' + contentTarget);
    $.get(contentPath, function(data) 
    {
        $('#'+contentTarget).fadeOut('fast',function(){
            $("#"+contentTarget).html(data);
            
            $("#"+contentTarget).fadeIn()
        })
    })    
}
</script>

and the HTML

            <style>
                #news_picker
                {
                    width:20%;
                    height:100%;
                    overflow:auto;
                    float:left;
                }
                
                #news_details
                {
                    width:79%;
                    height:100%;    
                    overflow:auto;
                    float:left;
                }
                #loadingDiv
                {
                    background-image:url(ajaxLoader.gif);
                    background-repeat:no-repeat;
                    background-position:center;
                    z-index:150;
                    display:none;
                }    
            </style>
            
            <div id="news_picker">
                <div class="listHeader">All of our news</div>
                
                <a href="news1.html" class="ajaxLink" >Ajax link override</a>
                
            </div>
            
            <div id="news_details">
                <div id="loadingDiv">Content Loading, Please Wait.</div>
                
                <div id="news_content"> I am news data</div>
                
            </div>

this will transform any link with a class of ‘ajaxLink’ and convert it from a regular link into an ajax loading link. Right now it is coded to push the fetched content into a div called ‘news_content’ (you could make this dynamic, or even per link by including some attribute in the link itself that tells the function where to put the fetched content). You may want to add special case handling for content other than text/html, such as detecting if the requested resource is an image, and wrap it in an img tag, etc. Anyway, hope this helps someone, I thought it was pretty cool to allow users to easily create Ajax links 😛