Friday 24 January 2014

London Salesforce Developers January Meetup

After a December break, the London Salesforce Developers returned with a vengeance in January.  Around 50 attendees descended on Make Positive’s offices for pizza, beer and talks on Salesforce security. We also had a couple of newly minted MVPs visiting - Chris Lewis and Phil Walton - and I’m sure a few people took the opportunity to find out more about how they’d managed to achieve this accolade.

First up was Wes Nolte on Sharing Rules - the unsung hero of Salesforce security.  

IMG 1092

Sharing is an extremely important topic, especially for consultants who are expected to understand all of the possible sharing options, be comfortable explaining these to clients and recommending the most appropriate option for a client implementation. Sharing also comes up in all certification exams from Administrator through to Technical Architect, where candidates are expected to be able to design a solution to a complex sharing model that doesn’t put too much of a strain on the system administrators or the platform.  You can find the slide deck from this talk here.

Next up was James Melville talking about OpenID.

IMG 1096

OpenID is something that most of us have seen at some point in time - think “Sign in with Google Account” options to sign in to a web site - but probably not many of us have thought about what goes on under the hood or set up on Salesforce. You can find the slide deck from this talk here.

Thanks to everyone that came along, especially those that travelled up from the South West or down from the North, and thanks to Make Positive for sponsoring (even if the pizza had run out when I got there :) If you are a Salesforce Developer, Administrator, Architect or Consultant (or other!) based in or near London and you aren’t a member of this meetup group, you should be!  You can find more details and sign up at:

http://www.meetup.com/LondonSalesforceDevelopers/

Tuesday 21 January 2014

Book Reviewers Wanted (Again!)

9818EN Cover

Earlier this month I reviewed the Visualforce Developer’s Guide by Chamil Madusanka.  Since then Packt have contacted me and asked if I know of anyone else who’d be interested in a free copy of the eBook in return for a review on Amazon.

If you’re interested, email Sagar Malage at: sagarm@packtpub.com by 31st January 2014.

 

Friday 17 January 2014

Book Review - Visualforce Developer's Guide

9818EN Cover

(Disclaimer: I didn’t purchase this book - I was sent an e-copy to review by Packt Publishing).

Book reviews are like buses - you wait for ages and then two come along at once. (This is a well-worn British joke about the unreliability of public transport - if you live in a country where public transport is efficient, please ignore this).

The Visualforce Developer’s Guide covers a number of topics from getting started through to security best practice via controllers and custom components, among others. including an unexpected (for me at least) chapter on using Visualforce in the Salesforce mobile (now classic) applications for iPhone, Android and Blackberry. While these are in maintenance only mode, they are still the best Salesforce mobile solutions for offline access to data and the only installed application options for windows mobile and blackberry.

While there is a lot of useful information in this book, my main criticism is around the introduction of each new technology.  In the main it is just dropped on the reader without much explanation of why its a good idea to use it. If I were new to something like the JQuery JavaScript framework, for example, I’d want to understand why I should be using that as opposed to vanilla JavaScript - and as I’m not new to JQuery I know there are a number of good reasons.

This is a good book, but it could have been great with a little more emphasis on educating the reader rather than just showing them the mechanics.

You can purchase the book at:

http://www.packtpub.com/visualforce-developers-guide/book?utm_source=mention.com&utm_medium=link&utm_campaign=book_mention.com

Tuesday 14 January 2014

Book Review - Developing Applications with Salesforce Chatter

Da chatter2

 

(Disclaimer - I didn’t purchase this book - I was sent an e-copy to review by Packt Publishing)

This is an interesting idea for a book - Salesforce have been pushing the collaboration theme for a while, but aside from a few short papers and the Salesforce system help, there isn’t a much information out there for those that are considering enabling and extending chatter.

The book suffers from a confused first chapter that can’t make up its mind if it is selling chatter, pushing the benefits of collaboration or demonstrating how the return on investment can be calculated.  Unfortunately it ends up not doing any of them very well and if I were new to chatter I don’t think I’d have a better understanding of what it is or the benefits after reading it.

The chapters on configuring and using chatter are much better - the instructions are clear and there are plenty of examples. One minor criticism is that I’d like to have seen more scenarios that covered why it is better to do things in chatter than using other mechanisms, but that is being picky.

Later sections introduce the concepts of extending chatter functionality using Apex, Visualforce and the Chatter REST API. These sections would benefit from a clearer introduction to the concepts that will be covered.  Batch apex, for example, has a cursory couple of lines to introduce the mechanics when it would do better to either explain the concept and purpose of batch apex and then cover the mechanics, or point the reader at resources where they can learn how batch apex works before continuing.  Again, if I didn’t know batch apex before reading this section I don’t think I’d be in a position to apply the technique to other scenarios.  This might seem a little harsh as the book does state that you need some knowledge of Visualforce and Apex for this chapter, but batch is a somewhat advanced topic which would benefit from a better explanation.

In summary, this is a useful book if you want to learn how to configure and use Chatter, and perform some simple extensions/enhancements using Apex and Visualforce. However, if you want to dig deeper, while this book will give you some ideas, you probably need to be familiar with the language or platform features.

The bool is available at: https://www.packtpub.com/developing-applications-with-salesforce-chatter/book

Saturday 11 January 2014

Visualforce in Salesforce1

Recently I’ve been porting a few apps to run in Salesforce1 - typicality these are HTML5 apps that users ran in the device browser and had to log in to each time they wanted to use them, but Salesforce1 avoids that. 

As well as porting, I was trying to improve the user experience and make the apps behave consistently if they were running in the browser or inside Salesforce1, and I got caught out a couple of times with behaviour that was either unexpected or something I just couldn’t do.  I should stress that these aren’t shortcomings of Salesforce1, its more about how Visualforce pages are displayed inside web view containers.

Pages Opened in the Child Browser don’t have the sforce.one JavaScript object

In a project I was working on recently I had a Visualforce page in Salesforce1 that could be used to open other Visualforce pages.  I originally developed this using the sforce.one navigation methods, which opened the relative links in the same page with back buttons etc. Each of these pages relied on the sforce.one JavaScript object being present to provide mobile specific behaviour.

I then refactored this, as I wanted to open in a child browser window so that the user could bounce around a few other pages but retain the close button to jump straight back to the main page. While the sforce.one.navigateToURL() should open absolute URLs in a child browser, even if I specified the target Visualforce page as an absolute URL, the platform appeared to know that it was on the same site and opened it as a relative URL, without using a child browser window.

Relying on my knowledge of the Salesforce mobile SDK, I used the window.open() JavaScript function, which opened the page in the desired fashion, but all of my mobile functionality was broken.  After a short amount of digging around it transpired that the  sforce.one object was undefined, so as far as my page was concerned it was running on a regular browser.

I’ve put together a couple of pages to demo this.  Both pages output some content to describe whether they are running in Salesforce1 or not, and the first page provides a link to the second

Page1:

<apex:page showheader="false" sidebar="false" applyHtmlTag="false" applyBodyTag="false">
  <html>
    <head>
	<meta name="viewport" content="width=320; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;"></meta>
    </head>
    <body>
      <apex:includeScript value="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.9.1.min.js"/>
      <p style="font-size:24px; text-align:center">Page 1</p>
      <div style="display:none" id="sf1">
        <p style="font-size:20px; text-align:center">I am running in Salesforce1 :)</p>
      </div>
      <div style="display:none" id="notsf1">
        <p style="font-size:20px; text-align:center">I am not running in Salesforce1 :(</p>
      </div>
   
   
      <p><a href="javascript:sforce.one.navigateToURL('/apex/SforceDotTwo');">Click to open page two.</a></p>
      <script>
	  $(document).ready(function () {
	  	if ( (typeof sforce != 'undefined') && (sforce != null) ) {
			$('#sf1').toggle();
		}
		else {
			$('#notsf1').toggle();
		}
	  });
       </script>
    </body>
  </html>
</apex:page>

Page2 :

<apex:page showheader="false" sidebar="false" applyHtmlTag="false" applyBodyTag="false">
  <html>
    <head>
      <meta name="viewport" content="width=320; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;"></meta>
    </head>
    <body>
      <apex:includeScript value="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.9.1.min.js"/>
      <p style="font-size:24px; text-align:center">Page 2</p>
      <div style="display:none" id="sf1">
        <p style="font-size:20px; text-align:center">I am running in Salesforce1 :)</p>
      </div>
      <div style="display:none" id="notsf1">
        <p style="font-size:20px; text-align:center">I am not running in Salesforce1 :(</p>
      </div>
   
   
      <script>
  	$(document).ready(function () {
		if ( (typeof sforce != 'undefined') && (sforce != null) ) {
			$('#sf1').toggle();
		}
		else {
			$('#notsf1').toggle();
		}
 	  });
      </script>
    </body>
  </html>
</apex:page>

 

Opening the first page in Salesforce1 displays the “Running in Salesforce1” message as expected:

IMG 1086 

while clicking the link to go to Page 2 navigates in the same window, including a back button, and displays the message as expected:

IMG 1087 

Changing the page 2 navigation link to the following: 

<p><a href="javascript:window.open('/apex/SforceDotTwo');">Click to open page two.</a></p>

and clicking the link displays the second page in a child browser window (note the close button), but the message has now changed to indicate that the application is not running in Salesforce1:

 IMG 1088

Accessing external URLs via window.open generates an embedded browser window on a mobile device, with a close button.  Don’t use navigation here, as you’ll end up pulling your app into the embedded browser as well as the containing app.  When running from the desktop it will open in the same browser window where you would want navigation.

As I was just relying on knowing that I was running in Salesforce1 to style the page and add a few buttons, I could just pass a parameter on the URL to indicate I was running in the application.

HTML5 or Installed Application?

When a Visualforce page is rendered in Salesforce1, there’s no way that I’ve been able to find to determine whether Salesforce1 is the HTML5 web application running in the device’s browser or the installed application.  Checking the User Agent for the browser doesn’t help, as they will report the same values based on the device itself.  

Update 24/02/2014: The iOS versions of Salesforce1 installed application report a user agent containing the string ‘SalesforceTouchContainer’, so this can be used to determine that the page is running in the installed application. On my Nexus 7, however, the only difference is in the version of Chrome which obviously can’t be relied on to be the same on another Nexus 7, so Android is still problematic.  Of course, relying on the user agent is a somewhat flawed approach as applications like the Dolphin web browser allow you to set your own user agent string, but it is the best that we have.

Most of the time I don’t care about this, but I have hit one situation where I wanted to render a particular toolbar button for the installed application but not the HTML5 web application. There is also no concept of a child browser in the HTML5 application - URLs open in the current window or a new tab/window depending on the browser configuration and how the link is constructed.  

This isn’t specific to Salesforce1 - it appears to be problematic for Cordova hybrid apps in general, and most of the solutions rely on inspecting the JavaScript window object to see if the cordova object is present, or trying to react to deviceReady events.  Unfortunately, as Visualforce is iframed into the Salesforce1 application, all of this information is hidden from my Visualforce page so I ended up reworking my pages to behave in an identical but slightly more clunky fashion in all cases.

If anyone has a solution to this I’d love to hear about it.

 

Saturday 4 January 2014

Syntax Highlighting in Knowledge Articles

Here at BrightGen we use Salesforce Knowledge for our knowledge base.  The majority of the time the knowledge articles are paragraphs of text with images images, but every now and then we need to include code snippets.

For the purposes of this post I’m using the FAQ article type that is automatically available when knowledge is enabled, and I’ve added a Body custom field that is a rich text area. I’ve created a simple Visualforce page to display the FAQ:

<apex:page standardController="FAQ__kav" showheader="false">
  <p style=“font-size:16px; font-weight: bold;">
<apex:outputField value="{!FAQ__kav.Title}" />
  </p>
  <apex:outputField value="{!FAQ__kav.Body__c}" />
</apex:page>

and then configured this as the channel display for the article type when accessed through the internal app:

Screen Shot 2014 01 03 at 09 06 47

Simply dropping some code into the rich text area doesn’t make it stand out particularly well from the enclosing text:

 Screen Shot 2014 01 03 at 09 24 01

The HTML pre formatted tag <pre> displays the markup in a fixed-width mode, preserving spaces and line breaks to ensure the indentation looks good.  I can add this to my markup by editing the article and clicking the ‘Source’ button:

Screen Shot 2014 01 03 at 09 28 45

this allows me to edit the underlying article HTML and surround my markup with the opening and closing <pre> tags - note that if you simply try to edit the markup dropped in earlier, you’ll see a bunch of &nbsp; and other tags that are preserving the indentation - for that reason I paste the code out of my editor/IDE afresh into the source editor:

Screen Shot 2014 01 03 at 09 35 09

The code now stands out a little more in the article, but still doesn’t look fantastic:

Screen Shot 2014 01 03 at 09 36 46

In order to add syntax highlighting, its clear that I’ll have to look outside of the standard knowledge functionality - I could spend time writing the HTML to highlight each code snippet individually, but that won’t scale and will quickly get boring.

For syntax highlighting on this blog, I use the excellent Syntax Highlighter from Alex Gorbatchev, so this seemed like a good place to start.  Its pretty unobtrusive and relies on adding a style class to the <pre> tag that I’m already using.

First the code needs to be installed - navigate to the Syntax Highlighter home page (http://alexgorbatchev.com/SyntaxHighlighter/) and click the download link near the top right:

Screen Shot 2014 01 03 at 16 23 58

The resulting file can then be uploaded straight into Salesforce as a static resource - I’ve named mine SyntaxHighlighter as I have a great imagination!

My Visualforce page then needs to be updated to pull in the required JavaScript and CSS.  Here I’m including the core highlighter functionality, then the brush that I’m going to use to highlight my code - I like the Java brush so I’m using that, but there are plenty available in the zip file.  This is followed by a couple of CSS files to pull in the core styles and a theme: 

<apex:includeScript value="{!URLFOR($Resource.SyntaxHighlighter,
        'syntaxhighlighter_3.0.83/scripts/shCore.js')}" />
<apex:includeScript value="{!URLFOR($Resource.SyntaxHighlighter,
        'syntaxhighlighter_3.0.83/scripts/shBrushJava.js')}" />
<apex:styleSheet value="{!URLFOR($Resource.SyntaxHighlighter,
       'syntaxhighlighter_3.0.83/styles/shCore.css')}" />
<apex:styleSheet value="{!URLFOR($Resource.SyntaxHighlighter,
       'syntaxhighlighter_3.0.83/styles/shThemeDefault.css')}" />

Next, I have some JavaScript to turn off the toolbar that appears above the code by default and execute the static function to process all elements on the page and highlight as appropriate - it doesn’t matter where this is executed from as it won’t fire until the page has finished rendering:

<script type="text/javascript">
  SyntaxHighlighter.defaults['toolbar'] = false;
  SyntaxHighlighter.all();
</script>

I can then return to my knowledge article and add the java brush class to my <pre> tag by editing the source as described above:

Screen Shot 2014 01 03 at 16 51 39

and now when I access my page my code is highlighted with line numbers:

Screen Shot 2014 01 03 at 16 46 23

One important point to note - if you are using this to format Visualforce or HTML markup, you’ll need to HTML encode the markup first, or it will cause problems when the HTML is processed by the rich text editor.  I use the HTMLEncoder from opinionatedgeek.com - simply paste your markup in, click the encode button, copy the encoded output and drop this into the rich text editor using the source button as described above.