jQuery – Cloudstock 2012 – Part 1


Hello one and all!  I was honored to have been asked to present a Developer Commons session on jQuery at Cloudstock 2012.  If you were in attendance during my presentation or just stumbled upon my blog – welcome one, welcome all.

My post here is to run through my presentation – sit back, grab a beverage, and here we go.  Here’s part 1 – intro and example 1:  table column sorting.

Why is it important to use technologies like jQuery?

jQuery is a very important tool in your kit for one main reason:  User Interaction.  You probably can code the best thing in the universe, but if your users don’t see it as easy and fun to use, you’re sunk.  Your users hold the key to overall solution adoption.  jQuery can help you!

Developers tend to think just like developers, just as users tend to think like users; VERY seldom do you ever get a hybrid situation.  As a developer, you need to leverage your users to head off adoption issues before you present them with “version 1” – as you can never redo a first impression.

Take this business case – you are in a beautifully-architected solution that manages all kinds of information, but a user asks you “how do I add an account to Salesforce?”  Relying on the good Salesforce mantra of declarative vs. programmatic, your initial reaction would be to tell them to hit the “Accounts” tab in their tab bar, hit “New” and enter the new information – then head back in your solution.

To a developer – this sounds perfectly fine.  Why should I have to rebuild something that already exists?  That’s not smart!  What if x, y, or z changes – I have to go in and change my custom (basic) functionality!  We (developers) also tend to think in totalities – “A user wants to add an account” means “they want the entire flipping screen available to them!”.  Potentially not true!

Deploying to users – breaking their stream of thought and level of engagement in your solution is a total deal-breaker.  Your dream of 100% enthusiastic “ticker-tape parade in the streets” adoption rate just will not happen.  They’ll use it, but they’ll grumble and put post-it notes on their screen to go back and enter those new accounts after they’ve done what they need to do in the solution.

jQuery can help!!  Ask your user – “what do you really need to track on a new account while working in the solution?”  They may come back and just need to enter BASIC information, possibly with a workflow Task reminding them to go back later and fill everything else out – that’s very doable with LITTLE code.

Too little?  Too much?  Finding that “Goldilocks Zone”

I know you’ve seen it.  That gawdy page on the Internet (think back to the old Frontpage frames days perhaps?) that has every single possible plugin and animated GIF thrown in there like someone sneezed on the window?  Yeah, I know you’ve all seen it.  Just as much as you’ve seen the solution where you think, “c’mon dude, you did THAT…why not just take it a LITTLE farther??”.

There is a FINE line between too little and too much.  It’s ultimately up to experience and having some intuition (as well as talking to your users!!!) to accurately gauge it.  This post is going to go through some pretty low-key, good return scenarios where you can add a little bit of sex appeal to your solution.

Salesforce is an incredibly deep and capable platform.  Do NOT replace the calendar control that they provide unless it’s ABSOLUTELY WITHOUT A DOUBT a do-or-die success factor of your project.  Even then – I’d still fight it. Consistency is just as important as functionality…even at the expense of the VP not being able to press a special key combination to automatically choose a date.

Still having doubts?  ASK YOUR PEERS!  ASK THE COMMUNITY!  Salesforce (and jQuery’s community) have great resources for you – just waiting to be leveraged!  Hit up the #askForce hashtag on Twitter or the Force.com Developer Boards.  Both are excellent places to get answers from real people.

Example 1:  Table Sorting

You can create a Visualforce page like the best of them.  Some PageBlocks, PageBlockSections, and a PageBlockTable.  Works great.  A user says, “I want to be able to sort the columns!”.  Well crap…that’s not natively available.  Enter jQuery to the rescue!  Using a jQuery plugin called “tablesorter”, we can either create a native HTML table and bind it to that, or through one more line of Javascript / jQuery code – bind it directly to the PageBlockTable.  The same goes for just about any native Visualforce widget – you can bind just about anything to them.

Some quick code:

1.  You need to pull in your jQuery, jQueryUI, jQuery CSS, and Tablesorter plug-in.  I packaged them all in a ZIP file that I stuck into Static Resources.  Typically I recommend this approach over getting them from Google or another public source – just because I don’t like things changing in my app that I don’t change myself.

<script src=”{!URLFOR($Resource.jQuery,’/js/jquery-1.5.1.min.js’)}” type=”text/javascript” />
<script src=”{!URLFOR($Resource.jQuery,’/js/jquery-ui-1.8.13.custom.min.js’)}” type=”text/javascript” />
<script src=”{!URLFOR($Resource.jQuery,’/tablesorter/jquery.tablesorter.min.js’)}” type=”text/javascript” />

<apex:stylesheet value=”{!URLFOR($Resource.jQuery,’/css/ui-lightness/jquery-ui-1.8.13.custom.css’)}” />
<apex:stylesheet value=”{!URLFOR($Resource.jQuery,’/tablesorter/style.css’)}” />

2.  Creating your jQuery object – always do a NoConflict in Salesforce so you don’t muck up their stuff.

var j$ = jQuery.noConflict();

3.  Either bind the Tablesorter to a native HTML table (first block) or use the JS getElementById to traverse the Salesforce rendering engine to bind to the native controls.

////////////////////////////
// Wait for document.ready
////////////////////////////
j$(document).ready(function(){

////////////////////////////////
// Bind TableSorter to a HTML table filled with controller data
////////////////////////////////
j$(“#tblNativeSortable”).tablesorter({
widgets: [‘zebra’],
headers: {
// Specify any columns that you don’t want to sort by
0: { sorter: false },
}
});

// Use document.getElementById to find VF elements
var elResource = document.getElementById(‘{!$Component.pgJQueryDemo:frmMain:pbMain:pbsStandardList:pbtNative}’);

////////////////////////////////
// Bind TableSorter to the native SF apex:pageBlockTable
////////////////////////////////
j$(elResource).tablesorter({
widgets: [‘zebra’],
headers: {
// Specify any columns that you don’t want to sort by
// 2: { sorter: false },
}
});
});

Here is the VF code behind these tables (there is a controller behind this doing the list GET)

<apex:pageBlockTable id=”pbtNative” value=”{!lstAccounts}” var=”a”>

<apex:column value=”{!a.Id}”/>
<apex:column value=”{!a.Name}”/>
<apex:column value=”{!a.Website}”/>
<apex:column value=”{!a.Phone}”/>

</apex:pageBlockTable>

<table id=”tblNativeSortable” class=”list tablesorter” border=”0″ cellpadding=”0″ cellspacing=”0″>
<thead>
<tr>
<th>Delete?</th>
<th>Account Id</th>
<th>Account Name</th>
<th>Website</th>
<th>Phone</th>
</tr>
</thead>
<tbody>
<apex:repeat value=”{!lstAccounts}” var=”a”>
<tr>
<td>
<a href=”#” onClick=”deleteAcct(‘{!a.Id}’);”>Delete</a>
</td>
<td>{!a.Id}</td>
<td>{!a.Name}</td>
<td>{!a.Website}</td>
<td>{!a.Phone}</td>
</tr>
</apex:repeat>
</tbody>
</table>

Tune in soon for the next blog post – on interstitial loading modal dialogs and modal forms!

Advertisements

22 thoughts on “jQuery – Cloudstock 2012 – Part 1

  1. Can you please post the complete example. As this is my first experience with jQuery in salesforce. A complete example helps me to pick up. Hope you consider my request please.

  2. Pingback: jQuery – Cloudstock 2012 – Part 2 | Andrew Boettcher – Salesforce Technologist

  3. Hi
    I like your post but little confuse could you post entire code in a place and upload the zip file
    so that it will be great help.Since i am looking this functionality from long time

    Thanks
    Raj

  4. Great post.

    I’m doing my best to sort a native apex:pageBlockTable. Everything is working correctly, but the native styles on the header appear to be overwriting the tablesorter styling, and I am not seeing an indication of ascending/descending. Any recommendations?

  5. Hi there! I know this is somewhat off topic but I was wondering if you knew where
    I could find a captcha plugin for my comment form? I’m using the same blog platform as yours and I’m having trouble finding one?
    Thanks a lot!

  6. Hi Andrew,
    I am working with this example above and have a question?
    I have your pdtNative pageBlockTable working with value=”{!listviewoptions}”

    Column sort when the first page is loaded.
    After changing the list view to Example: All Accounts – Columns rerendered no longer sort…
    I would love to email you my code if you want for more information

    Thanks for your help and code examples,

    David G.

  7. Hi Andrew,

    Thanks for making this resource available. This is and your 2012 Dreamforce recording on jQuery are really helpful. I’m new to jQuery and am trying to use tablesorter to modify a mass edit Vf page in the Mass Update Mass Edit app. The page and the page block table load fine, but the columns aren’t sortable. In theory, should tablesorter work with any working page block table, or could there be something within the page block table that needs to be adjusted to get tablesorter to work? My page just has the page block table, not the table element – do I need that as well?

    I’d really appreciate any advice you can send my way.

    Thanks much,
    Sandi

    • ** EDITED – silly WordPress killing my HTML comments! **

      Hello Sandi!

      Thanks for the comment! =)

      Typically what I run into when the columns don’t sort is the application of the style to the table or pageblocktable. You can bind tablesorter right to a pageblocktable – but you have to navigate your DOM to do it.

      For instance, if your page looked like this (pseudocode):
      apex:page id=”pgJQueryDemo”
      apex:form id=”frmMain”
      apex:pageBlock id=”pbMain”
      apex:pageBlockSection id=”pbsStandardList”
      apex:pageBlockTable id=”pbtNative”
      — your columns —

      You would have to have this JS /jQuery code in your page:

      ////////////////////////////////
      // Bind TableSorter to the native SF apex:pageBlockTable
      ////////////////////////////////
      var elResource = document.getElementById(‘{!$Component.pgJQueryDemo:frmMain:pbMain:pbsStandardList:pbtNative}’);
      j$(elResource).tablesorter({
      widgets: [‘zebra’],
      headers: {
      // Specify any columns that you don’t want to sort by
      // 0: { sorter: false },
      }
      });

      Note how the “var elResource” navigates the VF structure to get to the pageblockTable. jQuery can’t natively deal with colons, and naturally that’s how everything renders in VF. =)

      Give that a whirl – if you have issues, you can pop your code up in a private pastebin and we can walk through it!

      Good luck!

      -Andy

Leave a Reply

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

WordPress.com Logo

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

Twitter picture

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

Facebook photo

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

Google+ photo

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

Connecting to %s