Friday, September 24, 2010

Using the Old Report Builder

The new report builder is flashy and has increased functionality, but there are times when using the old one is just quicker for some functions.

When the new report builder showed up you had the option to use either method to build or edit a report. Then one day my ability to use the old one just went away. Here's what happened:

There is a new permission on profiles called 'Report Builder' (under General User Permissions). When this is checked, you can only access the new report builder. To access the old one, you have to uncheck it. Here's the trick: System Administrators automatically have all permissions checked and you can't change that. So if you need access to the old way of doing things, you won't be able to do it with a user who is an admin.

Support suggested cloning the admin profile and then unchecking the option, but I have not performed that exercise.

Monday, September 20, 2010

Storing a Website URL for use in Custom Email Templates

In Salesforce setup, most users are familiar with the “Organization” object, which stores basic organizational information such as address, time zone, and phone numbers. Well it’s my understanding whoever created this object was designing applications for companies stuck in 1980 who don’t have websites. The URL for an organization’s website is a critical piece of organizational information that most companies want to have available on emails and other system templates.
Unfortunately, custom fields cannot be added to the organization object, making it impossible to do what would seem most intuitive - create a URL field to store a company website on the Organization object. A workaround we’ve used to circumvent this limitation is to do the following:
Step 1: Create a Custom Setting to Store the Company Website URL
Simply create a new custom setting. Keep the default setting type of hierarchy and set the visibility to Public. Once the setting has been created, add a new custom field to the setting. It should be created as type “URL” (it will look something like the image below when you’re done).

Don’t forget to save an actual website URL in the field once you’ve saved it.
Step 2: Add a Custom Field to the User Object to Reference the Custom Setting
Next, simply go to the user object and add a custom field of type “formula”. In the simple formula area, reference the custom setting that was created in step 1. Your reference formula should be in the format of:
$Setup.CustomSettingAPIName.CustomSettingFieldAPIName
            Save the custom field when you’re finished.
            Step 3: Reference the User Website Field in a Template
Now, referencing the company website URL in an email template is easy! Since each user in the system now has the website stored in a custom field, the website URL can be accessed through any system user. Luckily, a field type called “Sending User” is available for use on any template. You can now place a website URL in a template by using the following merge field:

Implementing Quicksort to sort a list of SelectOptions

A common task when building Visualforce pages is displaying a dropdown list that is populated by a list of SelectOptions, and making sure the values in the dropdown are ordered alphabetically. The most efficient ways to sort in Force.com are to either ask the SoQL database to do it for you by using ORDER BY, or by using the List object's .sort() function. Unfortunately .sort() only supports primitive datatypes, which SelectOption is not. And if the list didn’t come from a simple SoQL query that you can tweak the ORDER BY statement on, or if you just want to save a query, then it's time to bite the bullet and sort the list yourself.

Sorting a list is one of the most fundamental problems in computer science, and there are many ways to do it. We chose to use one of the most popular algorithms, Quicksort, because it doesn’t require a lot of memory, has high performance, and is easy to implement. To us, that means our sorting won't use up too many script statements and we wont' need to spend 4 days writing and testing the sorting code.

Below is the implementation of Quicksort that we use to sort out SelectOption lists. Note that this implementation does not do a true in-place sort, so the memory usage is a bit higher than it could be, but it has served our purposes very well.

You should be able to simply drop this in a class and use it as is!

    //  This is a simple quicksort algorithm to sort a SelectOption list (dropdown) 
    // by label alphabetically.
    global static List<SelectOption> SortOptionList(List<SelectOption> ListToSort)
    {
        if(ListToSort == null || ListToSort.size() <= 1)
            return ListToSort;
            
        List<SelectOption> Less = new List<SelectOption>();
        List<SelectOption> Greater = new List<SelectOption>();
        integer pivot = ListToSort.size() / 2;
          
        // save the pivot and remove it from the list
        SelectOption pivotValue = ListToSort[pivot];
        ListToSort.remove(pivot);
        
        for(SelectOption x : ListToSort)
        {
            if(x.getLabel() <= pivotValue.getLabel())
                Less.add(x);
            else if(x.getLabel() > pivotValue.getLabel()) Greater.add(x);   
        }
        List<SelectOption> returnList = new List<SelectOption> ();
        returnList.addAll(SortOptionList(Less));
        returnList.add(pivotValue);
        returnList.addAll(SortOptionList(Greater));
        return returnList; 
    }  

Friday, September 17, 2010

‘Gotchas’: Using jQueryUI to make popups in Visualforce pages

Awhile back, I decided to use JQuery and JQueryUI to help add some spice to our custom Visualforce pages. One of the features we use quite regularly is JQueryUI’s ‘Dialog’ widget to display interactive modal dialog boxes. You can view some great examples that cover the basics here along with the source code that will get you up and using the dialog widget quickly.

When we tried to use them in Visualforce the popups basically worked immediately, except that we found several critical ‘gotchas’ that took awhile to figure out. This article focuses on those issues and how we solved them.

Gotcha #1: jQuery conflicts with Salesforce’s built in javascript libraries

Salesforce uses a competing javascript library known as Prototype which is loaded up on all Visualforce pages. Both Prototype and jQuery use the ‘$’ character as a shortcut to their libraries. To avoid this, we redefine jQuery to use ‘j$’ instead. Make sure to always paste the following code into the beginning of any page you will be using jQuery on:

var j$ = jQuery.noConflict();

Note that this means you will always use ‘j$’ to reference the jQuery libraries, rather than just ‘$’.

Gotcha #2: The ‘:’ character is special in jQuery

When rendered in html, the ID given to a Visualforce element nearly always uses the ‘:’ character, which is beyond our control. However in jQuery, the ‘:’ is a special character and needs to be escaped. For example, the following lookup that tries to find a page element named ‘ThePageID:TheFormID’ will not work:


j$("#ThePageID:TheFormID");

To fix this, escape any colons with two backslashes:


j$("#ThePageID\\:TheFormID");


Gotcha #3: .dialog() will move your element outside of the form

This was perhaps the most annoying ‘feature’ of the jQueryUI dialog widget. Whenever you invoke the .dialog() method on a page element, the element gets moved to the bottom of the <body> section, and outside of the form it was in! For example if your HTML looked like this:

<html>
<body>
<form id="ThePageID:TheFormID">
<div id="MyPopup">Hi!</div>
</form>
</body>
</html>

And then you ran the following javascript to make ‘MyPopup’ a modal popup:

j$("#MyPopup").dialog({modal: true, autoOpen: false });

Your source HTML would now look something like this:

<html>
<body>
<form id="ThePageID:TheFormID">

</form>
<div id="MyPopup">Hi!</div>
</body>
</html>
The popup will still display just fine, but if your popup has any form elements on it (buttons, fields, etc.), they will need to be inside their original form, or else the data in them won’t get posted back to the server. This causes hair pulling when buttons aren’t working and values aren’t getting populated on the server side.

To fix this, make sure your <apex:form> tag has an ID specified. Then use jQuery to find it and put the popup back inside the <form> section. So, assuming my <form> tag has an id that renders as ‘ThePageID:TheFormID’ the code would look like this:

j$("#MyPopup").dialog({modal: true, autoOpen: false }).parent().appendTo(j$("#ThePageID\\:TheFormID"));

Note that this also must be done any time you invoke .dialog(), including when you open or close the dialog using .dialog(‘open’) or .dialog(‘close’).

Gotcha #4: Salesforce datepicker displays behind popups

I beat my head against a wall for too long on this one before figuring out what was going on. You know the little calendar that pops up with any date entry field?

image

If you put one of these in a jQuery popup, the calendar doesn’t display. The text box is there, and works fine, but the calendar popup is never displayed. As it turns out, it is because the calendar pops up behind the jQuery popup. To fix this, there is a zIndex property you can set when initializing the dialog. After some investigation and a bit of trial and error, I found the magic zIndex number to be 9. So make sure that when you initialize your dialog, you include ‘zIndex: 9’, like so:

j$("#MyPopup").dialog({modal: true, zIndex: 9 });

Gotcha #5: Handling validations on popups (Coming soon)

There is one last gotcha that deals with handling validations on jQuery popups. It is a bit tricky, so I decided it needs it’s own separate post. Check back soon!