Alternative to the Average AJAX ActionStatus

Monday, July 18, 2011

Visualforce offers some great shortcuts that makes for faster development and a more consistent user experience. It is these tools to which Salesforce refers when they proudly advertise the short development cycles that programmers experience when working on the Force.com platform. It makes my life as a developer easier, and I really appreciate that. Sometimes, however, you want to add a slightly more advanced feature, one that requires pushing your code off of and beyond the tracks that the platform provides you.

One area that Visualforce has made very simple is Ajax. Adding just one or two Visualforce tags and attributes can produce a responsive page that uses Ajax for updating information. One such tag is the actionStatus tag. Ajax operation will work just fine if you don't use this tag, but the user won't know that an Ajax update is, in fact, taking place. Add this tag to the page and reference it from the same place that called the Ajax to tell the user, "Hey, wait a second. We've got some data coming from the server, so you should wait for it to arrive before continuing." Here's the simplest way to use this tag, taken from the SF documentation for commandButton:

<apex:page controller="exampleCon">
  <apex:form id="theForm">
    <apex:outputText value="{!varOnController}"/>
    <apex:commandButton action="{!update}" rerender="theForm" value="Update" id="theButton"/>
  </apex:form>
</apex:page>

Code Review: In this example, the secret sauce that adds the Ajax is the action and rerender attributes on the commandButton tag. Clicking on the button will send an Ajax message back to the server that will get the latest value of varOnController, which is a property of the controller object that we assume is changing with time. When the message returns to the page, the element that the outputText element creates will be replaced with the new value.

Now, let's imagine that it takes a few seconds for the controller to get this updated value back to us. The user will sit there, staring at the page, wondering if the button-click didn't work. We should give him some feedback:

<apex:page controller="exampleCon">
  <apex:form id="theForm">
    <apex:outputText value="{!varOnController}"/>
    <apex:actionStatus startText=" (working...)" stopText=" (done)" id="updateStatus"/>
    <apex:commandButton action="{!update}" rerender="theForm" status="updateStatus" value="Update" id="theButton"/>
  </apex:form>
</apex:page>

Code Review: This code should be the same as the first one, but this time we've added an actionStatus tag, which we attach to the commandButton's Ajax call by using the status attribute on commandButton. With this simple change, when the Ajax call begins, ( working...) will appear next to the outputText, and when it finishes, it will change to (done). This is a pretty good quick-and-done solution for user feedback.

The Problem: But what if we had a page that was heavy on form inputs, one that requires lots of user interaction? Is there a way to tell the user to wait before filling in more fields until the page updates? Well, I've found two possible solutions. Neither is perfect, but they both get the job done. What we want to achieve is to disable all inputs and buttons on the form while the page update is taking place.

1) The first way to accomplish this is to create a drop-down curtain effect, which drops a see-through curtain to capture clicks over the form. Here's how solution number 1 works:

<apex:pageBlockSection title="Form 1" id="formSection" collapsible="false">
  <div id="loadingCurtain">
  <apex:inputField value="{!myObject.Name}"/>
  <apex:inputField value="{!myObject.Address}"/>
  <apex:inputField value="{!myObject.OtherFields}"/>
  <apex:commandButton action="{!update}" rerender="formSection" onclick="showLoadingDiv();" oncomplete="hideLoadingDiv();" value="Update" id="theButton"/>
</apex:pageBlockSection>

Code Review: This is just a pageBlockSection that is contained inside form tags, which aren't shown. This one has three fields, though it could have more, and a button to post it back to the server. Instead of using the actionStatus tag, we're going to call our own Javascript functions to manipulate the loading curtain:

$j = jQuery.noConflict();

//This escapes SF-created IDs
function esc(myid) {
  return '#' + myid.replace(/(:|\.)/g,'\\\\$1');
}

function showLoadingDiv() {
  var divToScreenEsc = esc("{!$Component.hardCostSection}");
  var newHeight = $j(divToScreenEsc + " .pbSubsection").css("height");//Just shade the body, not the header
  $j("#loadingDiv").css("background-color", "black").css("opacity", 0.35).css("height", newHeight).css("width", "80%");
}
function hideLoadingDiv() {
  $j("#loadingDiv").css("background-color", "black").css("opacity", "1").css("height", "0px").css("width", "80%");
}

I'm using jQuery here. I've had bad experiences trying to use vanilla Javascript, and I've vowed to never use it again. jQuery gives consistent results across browser DOMs and across Javascript implementations itself. Note the esc function. This is necessary to escape the non-standard character in SF-created IDs for use in jQuery selectors, and was a solution created by Wes Nolte. See his blog post on the solution here. Beyond that, we're just selecting the loadingDiv and setting some styles, pretty simple.


2) The second solution is to avoid adding another element to the DOM, and just using Javascript to disable all selectable fields and buttons in the form:

<apex:pageBlockSection title="Form 1" id="formSection" collapsible="false">
  <apex:inputField value="{!myObject.Name}"/>
  <apex:inputField value="{!myObject.Address}"/>
  <apex:inputField value="{!myObject.OtherFields}"/>
  <apex:commandButton action="{!update}" rerender="formSection" onclick="showLoadingDiv2();" oncomplete="hideLoadingDiv2();" value="Update" id="theButton"/>
</apex:pageBlockSection>

Code Review: This is the same VF snippet as above, minus the curtain div. This time, we'll use Javascript to set the styles of the form elements themselves.

function showLoadingDiv2() {
  var divToScreenEsc = esc("{!$Component.formSection}");
  $j(divToScreenEsc).css("opacity", "0.35");
  $j(divToScreenEsc + " input, " + divToScreenEsc + " select").attr("disabled", "true");
}
function hideLoadingDiv2() {
  var divToScreenEsc = esc("{!$Component.formSection}");
  $j(divToScreenEsc).css("opacity", "1");
  $j(divToScreenEsc + " input, " + divToScreenEsc + " select").attr("disabled", "false");
}

This will disable all input and select elements in the specified form section as well as turn the entire section slightly transparent by setting the opacity to 35%.

That's it, really. Two simple solutions that I came up with to give a better user experience. Improve up it! I'm not a pro at HTML and Javascript, and maybe you can help make it better - leave a comment!

Before concluding this post, I want to mention the more elegant version of this that you should investigate:
Keep in mind that the actionStatus tag has both onstart and onstop attributes, from which you can call the necessary Javascript functions from there. The advantage to doing it this way is that the functionality is again tied to the actionStatus tag . This adds a layer of abstraction between the functionality and its visual status indicator. You would call the Javascript functions from the actionStatus tag instead of the Ajax initiating tags, such as a commandButton, keeping your code DRY and happy.

Why Did Heroku Choose Clojure? And Why Would You?

Tuesday, July 12, 2011



Not too long ago, Salesforce, a behemoth in the CRM space, acquired Heroku, a young cloud platform for Ruby and Rails applications. Nobody was sure what Salesforce's plans were when they made the acquisition, and even now, several months later, nothing but the light of speculation shines on the matter. The official words from Heroku and Salesforce say that both companies share similar philosophies/personalities, and both share a mission to make developers' lives easier and more enjoyable. This is great! I agree that both companies do a great job at developer relations. But from a business point of view, with happy developers comes unpredictable innovations, and persuading innovation to happen in your backyard is certainly a worthwhile investment!

Since the acquisition, Heroku has made some pretty consistent and sizable strides: releasing a new version of their stack, announcing support for the hot and new node.js web server, and announcing support for Clojure. As a Ruby/Rails platform, Heroku has had neither need nor want for the JVM. However, now that it has official support for Clojure, this has changed (Clojure is JVM-based language). Because this requires them to split their attention between hosting JVM apps and Ruby apps, this latest upgrade may prove to be a significant investment by Heroku. It stands to reason, therefore, that it will now be somewhat easier for Heroku to support other JVM technologies, such as Scala or Groovy, which is exciting.

But why did Heroku adopt Clojure as their newest language, as opposed to some other language? Well, functional languages have always been on the fringe, but they have been consistently gaining in popularity. According to the TIOBE language index, functional languages have 4.4 points (of 100) of popularity. Yes, this is pretty small compared to object-oriented language's 56 points, but it also shows the greatest increase in interest of all other programming paradigms, boasting a one-year delta of +1.4 points compared to object-oriented paradigm's delta of +0.6 points.

How, then, are these minority members using functional languages, and why is it growing it popularity? According to this 2011 survey of Clojure users, 62% of its users use Clojure for web development, which is the outstanding majority, followed by math/data analysis and NoSQL programming at 42% and 27%, respectively. Note, however, that an even 50% of the respondents do not yet use Clojure at work, but rather use it as a language for hobby projects. Also note the results of the "What have been the biggest wins for you in using Clojure?" section, which shows that it is chosen not for its strong concurrency support, but because it is strong functional language. Many Lisp users have adopted Clojure because it has been chosen as the modern reincarnation of Lisp, so keep this large user-base in mind when viewing the results. Clojure users also cite their appreciation of its robust, immutable data structures, and its ability to run on the JVM.

It also paves the way for fewer bugs to be written. Because it a functional language, and hails from the Lisp family, it is a highly concise language. As a concise language, Clojure allows for high functionality in few lines of code, meaning that there are fewer lines of code on which a bug can appear. Also, because Clojure data structures are immutable, there are fewer cases in which a programmer may forget to handle unexpected input in function/method definitions, meaning fewer bugs. From my research, the general consensus of functional languages is that they allow for relatively carefree programming, and that functional apps have fewer bugs and run faster than their object-oriented counterparts.

Clojure is a relatively young language, appearing in 2007, so why should you consider shifting to a functionality language like Clojure? If you are like its other users, you would choose it because it is a fast, efficient, functional language, and because it extends the bloodlines of Lisp, which has a long academic and open source history. The survey above shows that, while it may not have a solid share of the commercial sector yet, it has a real potential to gain a larger share. It would be a great choice, for example, in which to write a high-performance, scalable web app, and web-based solutions are still surging in popularity.

I have a high interest in functional languages, and how they can be used as a means of creating more efficient and scalable code. I look forward to seeing the community grow around functional languages, such as Clojure and Scala. I'll admit that Clojure's syntax, with its many parentheses, is very intimidating at first to many developers, which is definitely a hurdle to its growth. It requires education and hands-on experience to overcome this hurdle, but once overcome, its use can produce huge gains in developer productivity and application performance.

As they stated in their acquisition vows, both Heroku and Salesforce aim to make developers' lives better and to foster innovation. By looking at Clojure as a functional language, it's pretty clear that Heroku chose to adopt it for their platform because it is a strong contender as a functional language for reasons given above.

If you're interested in trying out a functional language, I suggest you try using Clojure on Heroku - it would be a pretty great learning experience. Keep in mind, that if you happen to make something awesome, because it was written in a functional language and is in the Heroku cloud, you should have no trouble scaling your web app to meet demand when it becomes supremely popular.

Using a Loading Overlay with Visualforce's ActionStatus tag for Form Refreshes

Wednesday, July 6, 2011

I'm not sure how other Visualforce developers uses the actionStatus tag, but I've discovered a different way of using it that gives visual feedback to the user that the part of the page he is working with is under an update operation.

Until now, I've used the actionStatus tag like this, relying on the start and stop facets of the element to display simple "Loading..." text:

<apex:actionStatus id="entryStatus" >
   <apex:facet name="start">
      <apex:outputText style="font-weight:bold;font-size:16px;" value="Loading..."/>
   </apex:facet>
</apex:actionStatus>

The Loading text appears, but the fields are still editable, which shouldn't be true.


This is fine for a lot of cases, but when the form has multiple input fields, I don't want the user to think that they can change the field values while they wait for an AJAX update, because their updates will be clobbered. Rather, it would be intuitive to have a slightly transparent screen, like a lightbox, appear over the form fields to prevent changes and provide a visual cue that an update is occurring on the section that the user is working with. After trying a few different methods, I refactored the solution to use the actionStatus tag, which has onstart and onstop attributes. These attributes can be used to call a Javascript function that will drop a screen down at a higher z-index/precedence than the fields, capturing subsequent clicks.

<apex:actionStatus id="entryStatus" onstart="showLoadingDiv();" onstop="hideLoadingDiv();">
   <apex:facet name="start">
      <apex:outputText style="font-weight:bold;font-size:16px;" value="Loading..."/>
   </apex:facet>
</apex:actionStatus>

<div id="loadingDiv"></div> <-- The screen element that will cover the form. Javascript will change the height of this to drop it down. -->
   <apex:pageblock id="hardCosts" title="Line Items - Hard Cost Estimate"> <-- The form element to screen. -->
      <script>
      //This Javascript needs to be inside the element to hide to get its correct Id value {!$Component.task}.
      function showLoadingDiv() {
         //Find the sizes of the div to screen.
 var blockToLoad = document.getElementById('{!$Component.hardCosts}');
 var loadWidth = window.getComputedStyle(blockToLoad,"").getPropertyValue("width");
 var loadHeight = window.getComputedStyle(blockToLoad,"").getPropertyValue("height");
 //Set the loadingDiv to screen the element at the correct size.
 var loadingDiv = document.getElementById('loadingDiv');
 loadingDiv.setAttribute('style','background-color:black; opacity:0.35; height:' + parseFloat(loadHeight) + 'px; width:' + loadWidth + ';');
      }
      function hideLoadingDiv() {
 //Find the loadingDiv to hide.
 var loadingDiv = document.getElementById('loadingDiv');
 var blockToLoad = document.getElementById('{!$Component.hardCosts}');
 var loadWidth = window.getComputedStyle(blockToLoad,"").getPropertyValue("width");
 //Set its height to 0 to hide it.
 loadingDiv.setAttribute('style','height:0px; width: ' + loadWidth + '; background-color:black; opacity:0.35;');
      }
      
      </script>

And some styles to set the initial size of the loadingDiv element and add some attractive transitions.

#loadingDiv {
   height:0px;
   width:100%;
   position:absolute;
   -webkit-transition: all 0.10s ease-out;
   -moz-transition: all 0.10s ease-out;
}

It looks better with animations, but here's the result of a rough draft of the idea:
An overlay shows that it is loading.

This is just a rough draft, so there are some features that should be added before deploying this into production. For example, adding "Loading..." text next to an animated gif on the overlay would make it even more clear that the user must wait before accessing the data again, but this is a good start.

Can you make it better? Message me on Twitter (@alex_berg) so we can improve the idea.

Awesome Force.com Posts Are Moving

Tuesday, July 5, 2011

I've been posting a number of in-depth articles here on Alex Blog for several weeks now, and it's been fun sharing what I've learned. A few people have noticed, namely my employer, and they've asked if I would start writing posts about the Force.com platform for the company blog. Sundog, factually speaking, is the greatest employer ever, so I happily agreed. Therefore, my Force.com technical articles will start appearing on the Sundog blog.

Now, I'll probably keep posting commentary about Force.com here along with links to the Sundog blog, and I'll experiment with posting about other topics that interest me, such as Rails and web application architectures, and functional languages, such as Haskell. So never fear! Educational content should keep appearing! But to keep listening to my Force.com articles, you can try subscribing to my Sundog RSS feed: http://feeds.feedburner.com/Sunblog_aberg

Check out my first post on the Sundog blog about the Comet model, about which Pat Patterson is hosting a webinar in two days.

The Comet Model: The Yang to the Yin that is AJAX Client-side Polling

Saturday, July 2, 2011

Force.com giveth and it (hopefully doesn't) taketh away. Salesforce provides a new tool or two with each release of its platform, enabling Force.com developers to quickly and easily create apps that are up-to-par with the rest of the web development world. Spring '11 brought us Visualforce dynamic binding, Summer '11 brought Javascript remoting. Now, a new Streaming API has been announced on the Force.com blog. Pat Patterson, a Salesforce developer evangelist, is hosting a webinar on July 7th to give a preview of this Streaming API.

There were a few unfamiliar terms on that blog post, such as the CometD project and the Bayeux protocol, and curiosity gave me a brain itch until I finally found time to do some research. I'll share some of my findings here, so that the reader may be better prepared for the webinar, should they choose to attend.

Everything is a solution to a problem, or so I like to think, so what problem does this CometD project solve? This stuff is all about providing a better user experience. It aims to make what's on the page more accurately reflect what's on the server. It aims to fill a niche solution space, a gap that is left unfilled by AJAX and client-side server-polling. It aims to be the yang of the yin that is AJAX and client-side polling. So, to better understand the need for the CometD project and the Bayeux protocol, we need to see precisely what is currently available to a software engineer that already has AJAX in his tool-belt.

AJAX! The ambiguous term that tech-wannabes used to describe a web page that felt responsive. These days, people have narrowed it's meaning closer to it's actual functionality, and HTML5 is the New Thing about which to speak ambiguously. Commentary aside, the part of AJAX that we are interested in is its ability to talk with the server. It has the almighty XMLHttpRequest object that can grab data from the server, which is normally triggered by either a user interaction,
<input type="button" value="Send AJAX!" onclick="jsFuncThatSendsHttpRequest();"/>
<div id="ajaxResponse"> <-- The JS method will format and place response here -->
or by long-polling, see this great example using jQuery.

Now, using Javascript like this works pretty well, but it isn't a very elegant solution. We're manually checking with the server every 500 milliseconds (or however long we set), and I'm sure the server gets annoyed when it keeps telling us that it's got nothing new, not to mention all the wasted bandwidth/requests! A more elegant solution would be to use the observer pattern, in which we tell the server, just one time, that we'd like updates, then when it actually gets an update, it sends the update to everyone subscribed, which would be our JS process.

And this is exactly what the CometD project is all about, it's a push technology of the long-polling variety. If a web server is compliant with the open Bayeux protocol, it uses the observer pattern to push updates to subscribers. In the case of programming on the Force.com platform, the platform will be able to handle a subscribe request by Javascript code on a Visualforce page. So, in summary, you can write a Javascript callback function on your Visualforce page that will be invoked with the new data every time a process on the server gets it. Nice!

You can see how this Comet model is the yang to the yin that is client-side AJAX polling. Now what we do with it is the question. GTalk, GDocs, Meebo are some specific examples that use Comet ideas, but other applications could stream financial data/sports scores or online gaming packets, both of which places the logic in the server instead of the client. It will be interesting to see how the introduction of HTML5's WebSockets will change the need for the Comet model. Some leading voices have said that all existing HTTP push solutions, such as the Comet model, are just hacks and that WebSockets will standardize it. Others, however, argue that each technology has its own solution domain and can co-exist with each other. No matter, because WebSockets is still not close to be supported in browsers as its specification and security model are still under debate, so if you are to choose a push technology today, and want it to be relevant for a few more years, the Comet method is your best choice.