https://cdnjs.cloudflare.com/ajax/libs/SyntaxHighlighter/3.0.83/scripts/shAutoloader.js

Friday, 28 March 2014

London SFDG March Meetup

On 26th March the London Salesforce Developer Group once again congregated at Make Positive’s offices just south of the River Thames for our monthly meetup. It was great to see a few new faces who had tried Salesforce at the Elevate London Workshop and had come back for more.

Over the last couple of months we’ve moved to themed events, where all talks relate to a specific topic.  February’s theme was Salesforce1, and March built on the knowledge gained there and covered Mobile Access to APIs.

Laurent Delcambre of Tquila was on first, talking about extending Salesforce1 functionality through the analytics API to bring in reporting functionality.

Ld

 

Next Alessio Valentini, also of Tquila, gave a talk on developing a mobile application where the functionality lives on-device and all Salesforce data is accessed via APIs.

Av

We had a great turnout again this month - the meetup really seems to have taken off this year.

Ldsize

Beer, pizza and networking filled the time before the talks, while beer and networking continued on later into the night, moving to a local hostelry once we’d emptied the Make Positive fridge.

If you are based in or around London, work with or are interested in Salesforce, and aren’t a member of this group you should join - just signup at http://www.meetup.com/LondonSalesforceDevelopers/

The next meetup takes place towards the end of April - I hope to see you there.

One more thing - we also have a new hashtag - #LonDevSFDC - search us on twitter for news and updates about the group.

Wednesday, 19 March 2014

I Say You Buy One, You Get One Free

2000th Book Home Page Banner

(For those who aren’t regular viewers of English commercial tv, the title of this post is from the Safestyle Windows advert)

As regular readers of this blog are well aware, I wrote a book last year called the Visualforce Development Cookbook - there’s even a link at the top right of this page to allow you to easily make a purchase.

The good news is that until 26th March, to celebrate Packt’s 2000th title being released, you can buy my book in eBook form and receive another Packt eBook absolutely free - perhaps another copy of my book as a gift for a close friend or relative.  

The offer is automatically applied at the checkout and there are no limits to the number of purchases you can make during the offer period.  You can find out more at: http://bit.ly/1j26nPN

Saturday, 15 March 2014

Reading Barcodes in Salesforce1

A little over a month ago I wrote a post on Reading QR Codes in Salesforce1. At the time I added an entry to my todo list to investigate barcode reading through a similar mechanism. A twitter post from @cherfeldman asking if this was possible in Salesforce1 moved it up to the top and so I started looking into it in earnest.

One of my key requirements was to be able to process the code on device, as I didn’t want to be sending high resolution images  from a phone or tablet back to the server, especially if I’m using what passes for mobile broadband outside of a big city in the UK.

Some goggling threw up a few JavaScript packages, but based on the demos provided by most of them, Eddie Larsson’s Barcode Reader looked to be the pick of the bunch. The demo page shows some pretty impressive decoding - multiple codes per image, blurry images, rotated through 90 + 180 degrees etc.  It also handles a number of formats - Code128, Code93, Code39 and EAN-13.

Creating a prototype in Visualforce was exceptionally straightforward - I just had to download the JavaScript that does the heavy lifting (DecoderWorker.js) and upload this as a static resource to my developer edition of Salesforce and then cut and paste the source of the example upload page and surround it with a few Visualforce tags. 

Screen Shot 2014 03 15 at 07 12 34

While it was great to get this working so easily, it wasn’t a huge amount of use as it stood, as it simply decodes the image and outputs the associated number. The first thing I did was to add a field to my account sobject of “Barcode”, so that scanning a barcode could take the user to a Salesforce record. I then tweaked the JavaScript to:

  • Output the time taken to decode 
  • Allow the user to choose when to decode the image, in case a picture didn’t turn out that great
  • Add a “Restart” button to reload the page, as hitting the back button and then trying to decode didn’t work 100% of the time
  • Execute a controller method via JavaScript remoting to retrieve the id of the matching record

Trying this out on my laptop decoded the barcode in around 3-4 seconds, however the same thing on my iPhone or iPad took some time and the user had no idea what was happening, so clearly something to hold their interest was required.

Looking at the underlying JavaScript, it makes use of HTML5 Web Workers to fire off multiple decoders to attack the barcode from various angles concurrently.  

var DecodeWorker = new Worker("{!URLFOR($Resource.DecodeWorker)}");
var RightWorker = new Worker("{!URLFOR($Resource.DecodeWorker)}");
var LeftWorker = new Worker("{!URLFOR($Resource.DecodeWorker)}");
var FlipWorker = new Worker("{!URLFOR($Resource.DecodeWorker)}");

where $Resource.DecodeWorker is the static resource reference for the DecodeWorker.js file.

Without web workers, things would be even slower as one decoder would have to finish before the next one could start, but I was still seeing decode times of around a minute.  I therefore decided to notify the user that the workers had been launched, and then post regular messages to indicate they were still running until they had either all completed or the barcode had been successfully processed.  I could do this through alerts or dialogs, but a few weeks ago Jeff Douglas’ Force.com Weekly linked to a rather nice JavaScript library for notifying users - alertify.js. I’ve used this a couple of times and its reliable, fast and looks great so I decided this was the way to go.

Adding alertify to a page is as simple as including three CSS and JavaScript files - I’ve uploaded the alertify zip as a static resource in my developer edition so I can include the files from that:

<apex:stylesheet value="{!URLFOR($Resource.alertify, 
'alertify.js-0.3.11/themes/alertify.core.css')}"/> <apex:stylesheet value="{!URLFOR($Resource.alertify,
'alertify.js-0.3.11/themes/alertify.default.css')}"/> <apex:includeScript value="{!URLFOR($Resource.alertify,
'alertify.js-0.3.11/lib/alertify.min.js')}"/>

I can then post a message to the user from JavaScript via a single function call:

alertify.log('Launching workers');

The user experience is now take a picture of a barcode or pick one from the device gallery, and click the “Decode” button if it looks good, as which point the user is told that work has started:

IMG 1153

while the workers are running, regular messages are alerted through a JavaScript timer:

interval=setInterval(function(){alertify.log('Still working');},5000);

 

IMG 1154

Then when the decoding completes, messages are displayed to indicate the success/failure and assuming success, the controller method is executed to find a record where the Barcode field matches the decoded value.

IMG 1157

the decoded value and time taken is then displayed, and a button to navigate to the record is displayed:

IMG 1158

Clicking the "Go to record” button goes to the record matching the barcode, which is my BrightGen account:

IMG 1159

The full page source is available at this gist, and the associated controller at this gist. You’ll also need to set up the static resources for:

  • alertify -  download the zip file, then upload as a static resource named ‘alertify'
  • decoder worker - download the file, then upload as a static resource named ‘DecodeWorker'.
    Note that this isn't coming from the github repository, as the code has changed since I originally wrote this post - instead this is the version that I downloaded back in 2014. 

Note that this won’t work on Android 4.4, as it appears that the ability to access the camera via a file input was removed from the chromium web view in this version - you can read more about this in the Cordova JIRA entry.

Friday, 7 March 2014

Salesforce1 and Visualforce - Things I've Learned

At the February Meetup of the London Salesforce Developers Group, I presented a session where I went through some of the things I’ve learned while building Visualforce solutions to run in Salesforce1. The slide deck for this session is available on SlideShare, but some of the slides might be difficult to understand without the words that went with them, so in a departure from my usual blogging style I’ve decided to pick out some slides from the deck and explain what I was trying to show.

Capturing Input

Screen Shot 2014 03 06 at 12 37 10

Screen Shot 2014 03 06 at 12 37 43

The <apex:inputField /> component is not supported in Salesforce1if it creates a widget - e.g. date picker (although this component seems to work a lot of the time in iOS but not android).  Rather than trying to implement your own version of a Visualforce input, its better to use the HTML5 type attribute and let the browser determine the appropriate input mechanism to display.  The second slide shows how the the iPhone reacts to type attributes - displaying a date  spinner for a date and a custom keyboard including digits for number.  Unfortunately there isn’t a type for a lookup to another record, so you’ll still need to roll your own solution to this.

Screen Shot 2014 03 06 at 12 44 40

Something many people complain about when using HTML5 or Hybrid mobile applications is that clicking buttons can be unresponsive. Often this is down to the default behaviour of the webkit based browser (so Safari or Chrome at the least), which is to wait 300m/s after a click to see if the user is actually carrying out a double-click.  While this makes sense on the desktop, double tapping isn’t that common in mobile applications (although it is sound advice in Zombieland). The way that I typically work around this is to bind to the touchstart/end events rather than the click event.  When working in JQuery Mobile this is easy, as the framework adds support for these events.  Otherwise, built-in browser support is patchy so you may end up having to use another JavaScript solution such as the Event or Zepto packages. 

window.open()

The next block of slides relates to using window.open() to open a child browser window rather than the regular webview - this only works for iOS, but has allowed me to work around a few issues:

Rotating the iPhone application simply results in a sideways view of the page:

Screen Shot 2014 03 06 at 13 00 46

whereas rotating a page opened in the child browser works as expected:

Screen Shot 2014 03 06 at 13 00 59

List jumping has been acknowledged by Salesforce as a known issue. What happens here is that if you have a clickable list of items that is larger than the viewport, when you scroll down and click an entry, the application jumps back to the top of the list after the click.  However, I found this to be worse when using Bootstrap, in that the jump to the top took place before the click had been handled, resulting in the click being applied to the wrong element.

In the slide below, I’ve clicked on the Blog 5 entry to expand, but the app has jumped back to the top and expanded the Blog 11 entry,  I originally found this when placing delete buttons on a list, so it wasn’t just an irritant, it was affecting the data:

Screen Shot 2014 03 06 at 13 02 24

If I open the list in a child browser though, the item that I click on is the one that expands and the view stays at the correct place:

Screen Shot 2014 03 06 at 13 05 45

The next issue that I covered involved Bootstrap responsive tables.  The way that Boostrap handles tables is to leave it sized as it is, but wrap it in a scrolling element.  This means that when a page containing a responsive table is accessed on a small screen device, the elements outside the table will wrap and the table becomes scrollable:

Screen Shot 2014 03 06 at 13 07 06

Accessing this page in the Salesforce1 app, however, and the page is resized to the width of the table, with the text spanning the full width.  Even worse, if you have any dialogs in the page, they will be the full width of the page too, which means that you would need to scroll around the page to find the dialog message:

Screen Shot 2014 03 06 at 13 10 10

Opening the page inside the child browser respects the fact that the table is scrollable and reflows the text appropriately for the device:

Screen Shot 2014 03 06 at 13 11 40

As I’ve blogged before though, the child browser introduces some additional complexity - you can’t tell that you are in the Salesforce one context for a start, and as I mentioned earlier, it isn’t a solution for Android (although the responsive tables do behave correctly on my Nexus 7 so there is slightly less need for it).

 The final points I made were around mobile development best practice:

Screen Shot 2014 03 06 at 13 16 51

If you are designing applications that will genuinely be used while on the road, with all of the connection and bandwidth issues that brings, you really don’t want to be using much Visualforce at all, instead you should rebuild the app to do most of its work on the device. I presented a session on this topic at Dreamforce that applies equally well to Salesforce1 - you can watch the video here.

 

Saturday, 1 March 2014

London Salesforce Developers February Meetup

Sfdug

Along with a few others (Bay Area, Sydney) this week saw the February meetup of the London Salesforce Developer Group, kindly hosted by Make Positive at their London offices. Like our last meeting in January, this was a themed event and the theme was Salesforce1 - a hot topic at the moment in the Salesforce world, as evidenced by the 92 people that registered to attend.

First up we had Carolina Ruiz from Financial Force:

Cr

Carolina’s talk covered:

  • Using Publisher Actions in SF1 - micro moments - main features, overview, how do they fit in SF1
  • Notifications world in SF1
  • Other features of SF1
  • Mobile cards
  • Flexipages

Financial Force were involved in the beta for Salesforce1, so Carolina was able to share some insights into her experience developing against an early release of Salesforce1 and how it has evolved since then.  You can find the slides for this talk on slideshare here.

Next was me, on the topic of Salesforce1 for Visualforce developers.  

Kbldg

This was mainly about what doesn’t work and what not to do when adding Visualforce apps/pages to Salesforce1, and how to workaround problems that might be encountered.  The slide deck from my talk is on slideshare here. I’m planning a blog post to cover the topics in the slides with a little more explanation, so stay tuned.

The Developer Group next meets at Make Positive on March 26th 2014. If you are interested in joining us, you can join our meetup group at : 

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

to find out more and be notified of upcoming events.