Archive

Archive for the ‘Visualforce’ Category

Seattle Force.com User Group

September 29th, 2009 1 comment

This is sort of a late notice but on October 1st there will be a Force.com user group in Seattle. If you are in the area and want to exchange ideas and best practices revolving around the Force.com platform please swing by.

Want to take a deeper dive into the technical capabilities of Salesforce? Would you like to meet other Force.com developers in the Seattle area? Interested in learning about new/different tools that will help you create and develop better solutions? A new Salesforce user group will be starting up on Thursday Oct 1. Meetings will be held on the first Thursday of every month.

We will try to cover a different range of topics at these monthly meetings such as:

  • Summary of new functionality in the upcoming release
  • Project spotlight where someone will demo their project and the technical details
  • Best Practices
  • 3rd Party development and integration tools
  • Apex and VisualForce
  • Open session to discuss specific questions you may have regarding your current projects

Time: 8-9am
Date: Oct 1, 2009
Location:

West Monroe Partners
1215 4th Ave Suite 1010
Seattle, WA 98161

Please contact Val Grasparil (vgrasparil@westmonroepartners.com) or Andrew Brown (abrown@westmonroepartners.com) if you have any questions.

Since it is in the morning, coffee and snacks will be provided. Please RSVP if you are planning on attending so we can make sure to have enough food for everyone.

Reach out directly to Val to RSVP. I’ve been told there is public parking available at the address above.

Gameforce

August 28th, 2009 7 comments

Update: Video posted below.

This is my first post in nearly three weeks and my first Force.com related post in nearly a month. Where have I been you may wonder? Only working on the coolest Force.com site in the world :-P .  Haha, just kidding.  But yes, for the past 2 months I have been slowly chipping away on my entry for the Force.com Cloud Developer Challenge. So what did I build?

Gameforce - The Worlds 1′st online gaming site built upon the Force.com platform.

When I set out to build my entry I wanted to build something that had never been done before. We have all see the blogging, HR, accounting, shopping cart, content management, and many other traditional business apps. There is no doubt these can be super cool but in the end most of them have been done before. Salesforce.com and Force.com are typically viewed as a platform for business apps and I wanted to build something on the complete opposite end of the spectrum. I hope I have succeeded with building an online gaming site.

The site consists of two games: blackjack and LineUp4 aka Connect 4.

Blackjack
Place your bets and play against the dealer.

blackjack

LineUp4

A true online multiplayer game where two people can play against each other anywhere in the world. It also has the ‘Smack Talker’ which is live chat between the players. You can see more features listed on the about page located here.

lineup4

This site may not have the coolest graphics or the trendiest web design but when it comes to taking the Force.com platform to the limit I have used every trick in the book that I know about. When checking out this site keep in mind it was built with 100% Force.com. There is no extra javascript, flash, or any other web technology.

Video update:
After seeing how cool some of the videos were that other people created showing of their site  I created one as well. It gives a great overview in about 5 minuets. The one feature I forgot to mention in the video is that if you are playing a game of LineUp4 and are not logged in, you can log in, and will be returned to the game right where you left off. The game state will be saved.

http://tehnrd.com/gameforce.swf (if the video is to large for your screen, right click on the video and select ‘Show All’)

Now we wait for the results of the contest. I’m hoping this site puts me in contention for the Mac Book prize. I’m sure there are going to be some great entries but I’m hoping for the best since this site is like nothing I have ever seen before. My current computer is also 5 years old so a new pc definitely wouldn’t hurt. With so many entries in this contest perhaps salesforce could give away a more than one Mac Book ;-) ?

Also, due to the very dynamic nature of this site and the fact that it is currently hosted on a developer edition account I fully expect to exceed the site limits if this site gets popular. I have mirrored this site an a Force.com Free Edition account located here but it does not have the log in ability.

And one more thing. Thanks to my awesome wife for putting up with me while I constantly snuck away to work on this site.

Visualforce Pop up

July 29th, 2009 24 comments

One of the most common request you will see when perusing the Visualforce discussion boards is that developers want some sort of pop up box to display or gather more information. Due to the way Visualforce works a traditional pop up box won’t always work as this is a separate window and the state of one controller/extensions can not be accessed from two different windows. Each new window gets a new instance of the controller.

The most commonly recommended way to address this is issue is to use a modal dialog box similar to this or this. These work great but sticking to my anti javascript 100% native Visualforce mantra I assumed there must be an alternative to incorporating external javascript libraries. These libraries can add really cool and polished features but usually at the expense of more complexity and potentially higher maintenance.

I decided to take a stab at creating a 100% native Visualforce pop up and I’m pretty happy with the results. You can check out the demo here:

http://tehnrd-developer-edition.na7.force.com/popup

I’ll be the first to say this method is not perfect. The pop up may not always display in the exact center of the screen as it does not inspect the window size to dynamically center the pop up. Even with this limitation it tends to work pretty good 90% of the time. EDIT: css has been updated below and this is no longer an issue.

This code and markup is pretty simple so I didn’t add a lot of comments but if you have any questions please leave a comment below.

First lets take a look at the page.

<apex:page controller="popup">
    <apex:form >
        <apex:commandButton value="Show Pop up" action="{!showPopup}" rerender="popup"/>
        <apex:pageBlock >
            Lorem ipsum ..... dummy stuff to show the popup is above content
        </apex:pageBlock>
 
        <apex:outputPanel id="popup">
            <apex:outputPanel styleClass="customPopup" layout="block" rendered="{!displayPopUp}">
                Lorem ipsum <br/><br/><br/>
                <apex:commandButton value="Hide Pop up" action="{!closePopup}" rerender="popup"/>
            </apex:outputPanel>
        </apex:outputPanel>
 
    </apex:form>
 
    <style type="text/css">
       .customPopup{
            background-color: white;
            border-style: solid;
            border-width: 2px;
            left: 50%;
            padding:10px;
            position: absolute;
            z-index: 9999;
            /* These are the 3 css properties you will need to tweak so the pop 
            up displays in the center of the screen. First set the width. Then set 
            margin-left to negative half of what the width is. You can also add 
            the height property for a fixed size pop up.*/
            width: 500px;
            margin-left: -250px;
            top:100px;
        }
    </style>
</apex:page>

And the controller, very simple.

public class popup {
 
    public boolean displayPopup {get; set;}
 
    public void closePopup() {
        displayPopup = false;
    }
 
    public void showPopup() {
        displayPopup = true;
    }
}
Categories: Apex, Visualforce

Super Cool Advanced Lookup Component

July 26th, 2009 11 comments

Okay, so maybe it isn’t exactly a super cool advanced lookup, but it is a lookup, and it is cool. Title at least got your attention right? No? Darn.

So what is a super cool advanced lookup you may ask? It is basically text field that as you start to type it becomes a picklist of values depending on the text you are typing. You can have it lookup records on any object that has a Name field. This type of functionality can be done with javascript libraries (examples here) but why do that if you can build something that performs just as well using only Apex and Visualforce? I did play around with the ext.js library and it is definitely more polished but on very large data sets performance was not that good. As I would type it felt like it was freezing up. To me this is much more annoying than a slight delay the VF component makes when performing the SOQL query.

Here is the example page, enjoy: http://tehnrd-developer-edition.na7.force.com/comboBox

First we will take a look at the component named advancedLookup. This component has 4 important attributes:
- object: The object you would like to search, Account, Contact, MyCustomObject__c, etc.
- value: This component returns an Id value and this must be bound to a value in your page’s controller or extension
- maxHeight: As you begin you type a picklist will appear of matching results and you must set the default height.
- width: Depending on the object searched the Name may only be 15 characters wide or it could be 250. Here you set the width so the names are readable.

<apex:component controller="advancedLookUp" >
    <apex:attribute name="object" assignTo="{!objectType}" required="true" type="string" description="The object this component will search."/>
    <apex:attribute name="value" assignTo="{!selectValue}" required="true" type="object" description="A merge feld that references the controller class variable that is associated with this feld. This must be an Id field."/>
    <apex:attribute name="maxHeight" assignTo="{!maxHeight}" required="true" type="Integer" description="Max height of selectList."/>
    <apex:attribute name="width" required="true" type="string" description="Width of the component in pixels or percent."/>
    <apex:attribute name="style" type="string" description="The style used to display the inputText component, used primarily for adding inline CSS styles."/>
    <apex:outputPanel layout="block" style="{!style}">
 
            <!-- This is our input text that we will use in a wildcard search against the names of the defined object. We refresh the results every time this field
            is clicked or a letter is entered (keyup) -->
            <apex:inputText value="{!searchValue}" style="width:{!width}" id="searchValue">
                <apex:actionSupport event="onkeyup" action="{!search}" rerender="resultsPanel"/>
                <apex:actionSupport event="onclick" action="{!search}" rerender="resultsPanel"/>
            </apex:InputText>
 
            <!-- Once we perform the query on the object we will populate this list with the returned values. When a user selects a value we will hide this list
            and auto complete the selected value -->
            <apex:outputPanel id="resultsPanel" layout="block" style="position: absolute;">
                <apex:selectList value="{!value}" size="{!height}" style="width:{!width}" rendered="{!showList}" >
                    <apex:selectOptions value="{!results}"/>
                    <apex:actionSupport event="onchange" action="{!selectvalue}" rerender="resultsPanel,searchValue"/>
                </apex:selectList>
            </apex:outputPanel>
 
    </apex:outputPanel>
 
    <!-- This component has one little piece of javascript. If a user clicks on the screen before selecting a value we want to hide the list of options similar to
    how a normal picklist behaves -->
    <apex:actionFunction name="hideResults" action="{!hideResults}" reRender="resultsPanel"/>
    <script type="text/javascript">
        document.onclick = function(){
            hideResults();
        }
    </script>
</apex:component>

Next the controller for this this custom component:

public class advancedLookUp{
 
    public Object selectValue{get; set;}
    public String objectType {get; set;}
    public String searchValue {get; set;}
    public Integer maxHeight {get; set;}
    public Integer height {get; set;}
    public List<SelectOption> results {get; set;}
    public Boolean showList {get; set;}
    Map<String,String> resultsMap;
 
    //This is our seach method that is called every time a character is entered
    public void search(){
        showList = true;
        results = new List<SelectOption>();
        resultsMap = new Map<String,String>();
 
        //Using dynamic SOQL we pass the object and the search value
        if(searchValue.length() > 0){
            String entry = '%' + searchValue + '%';
            String queryString = 'Select Id, Name from ' + objectType + ' where Name like :entry order by Name limit 1000';
 
            /*Next we add the results to our list of selectOptions. We also add the values to a map so that when a value
            is selected we can auto fill the search box with the selected value */
            for(sObject o : Database.query(queryString)){
                results.add(new SelectOption((String)o.get('Id'),(String)o.get('Name')));
                resultsMap.put((String)o.get('Id'),(String)o.get('Name'));
            }
        }
 
        //Next we inspect the results to set the height and contents of the selectList
        if(searchValue.length() == 0){
            showList = false;
        }else if(results.size() == 0 && searchValue.length() != 0){
            results.add(new SelectOption('','No matches found'));
            height = 2;
        }else if(results.size() == 1){
            height = 2;
        }else if(results.size() > maxHeight){
            height = maxHeight;
        }else{
            height = results.size();
        }
    }
 
    //When a value is selected we will auto complete the searchValue
    public void selectValue(){
        showList = false;
        searchValue = resultsMap.get((string)selectValue);
    }
 
    //simply hides the list of results
    public void hideResults(){
        showList = false;
    }
}

Almost there now. Up next the page and page controller:

<apex:page controller="coolLookUp">
    Try searching with 'e', 'oil', 'az', 'install', etc then click the Show button.
 
    <apex:form >
        <!-- This is only line need for the advanced lookup. The value is bound to an ID variable in this page's controller. When you click the button it 
        refreshes the detail panel and displays the selected opp -->
        <c:advancedLookup object="Opportunity" value="{!oppId}" maxHeight="20" width="250px" style="float: left"/> 
        <apex:commandButton value="Show" rerender="detail" style="float: left" status="status"/>
        <apex:actionStatus startText="elevator music...." id="status"/>      
        <apex:outputPanel id="detail">
            <apex:detail subject="{!oppId}"/>
        </apex:outputPanel>
    </apex:form>
</apex:page>

Doesn’t get much more simple than this:

public class coolLookUp {
    public Id oppId {get; set;}
}

FYI, there is an issue if you try to use this component more than once on a page but I have not yet had the time to investigate.

Categories: Apex, Visualforce

Simple Visualforce Captcha

July 16th, 2009 9 comments

With Force.com sites now in GA it is possible to create public facing web forms and save directly to your salesforce.com database. You can do point of entry validation, auto fill fields based on the user, and all sort of other awesomeness. One problem with public facing forms is they are prone to spam, lots of spam. The best approach is to prevent the spam from even being submitted in the first place. This is usually done with some sort of CAPTCHA validation.

Ron Hess put together a great little article here on how you can use reCAPTCHA. It works great but (there is always a but) it requires setting up a web service callout, using javascript, and isn’t the the most straight forward CAPTCHA to setup. I am all about 100% salesforce.com. Javascript libraries and external services are great but if I can do the same thing with 100% Apex and Visualforce I’m all for that.

With this mindset I set out to create a CAPTCHA utility built 100% on the force.com platform. I think my results where pretty darn successful. It isn’t super fancy but I think it will get the job done……but then again it hasn’t exactly been tested against spam bots. Oh well, it’s still cool.

You can check out a working example here: http://tehnrd-developer-edition.na7.force.com/captcha

And here is the code, first the page:

<apex:page controller="captcha" >
 
    Enter only the <strong>black</strong> characters.
    <apex:outputPanel styleClass="container" layout="block" id="code">
        <apex:outputText value="{!char1}" styleClass="blackChar"/>
        <apex:outputText value="{!char2}" styleClass="redChar"/>
        <apex:outputText value="{!char3}" styleClass="blackChar"/>
        <apex:outputText value="{!char4}" styleClass="redChar"/>
        <apex:outputText value="{!char5}" styleClass="blackChar"/>
        <apex:outputText value="{!char6}" styleClass="redChar"/>
    </apex:outputPanel>
 
    <apex:form >
        <apex:inputText value="{!input}"/>
        <apex:commandButton action="{!validate}" value="Validate" rerender="result"/>
        <apex:commandButton value="Reset" rerender="code"/>
    </apex:form>
 
    <apex:outputPanel id="result">
        {!result}
    </apex:outputPanel>
 
    <style>
        .redChar{
            color: #C30000;
            font-size: 24px;
            padding:5px;
        }
        .blackChar{
            color: black;
            font-weight: bold;
            font-size: 24px;
            padding:5px;
        }
        .container{
            background-color: #E8E8E8;
            border-style: solid;
            border-width:1px;
            width: 150px;
            text-align: center;
        }
    </style>
</apex:page>

And next the controller:

public class captcha {
 
    List<String> characters;
    public String input {get; set;}
    public String result {get; set;}
    String char1;
    String char3;
    String char5;
 
    //In our contructor we will populate a list of strings with numbers and letters
    public captcha(){
        characters = new List<String>{'a','b','c','d','e','f','g','h',
            'i','j','k','l','m','n','o','p','q','r','s','t','u','v','w',
            'x','y','z','1','2','3','4','5','6','7','8','9','0'
        };
    }
 
    //This methods simply returns a random number between 0 and the size of the character list
    public Integer randomNumber(){
        Integer random = Math.Round(Math.Random() * characters.Size());
        if(random == characters.size()){
            random--;
        }
        return random;
    }
 
    /*Here we have 6 get methods that return 6 random characters to the page.
    For chars 1,3, and 5 (the black characters) we are saving the the values so 
    that we can compare them with the user's input */
    public String getChar1(){
        char1 = characters[randomNumber()];
        return char1;
    }
    public String getChar2(){
        return characters[randomNumber()];
    }
    public String getChar3(){
        char3 = characters[randomNumber()];
        return char3;
    }
    public String getChar4(){
        return characters[randomNumber()];
    }
    public String getChar5(){
        char5 = characters[randomNumber()];
        return char5;
    }
    public String getChar6(){
        return characters[randomNumber()];
    }
 
    /*In the validate method we make sure that the 3 characters entered equal the three black characters: char1, char3, char5*/
    public void validate(){
        if(input.length() == 3 && input.subString(0,1) == char1 && input.subString(1,2) == char3 && input.subString(2,3) == char5){
            result = 'Whoohoo! You got it right.';
        }else{
            result = 'Come on...the letters aren\'t even disfigured.'; 
        }
    }
}

The next logical step would be turning this into a component but this should give you a pretty good start.

Comparing Code

June 23rd, 2009 1 comment

Today I discovered a neat little feature in Eclipse that allows you to compare two files and identify the differences. With multiple sandboxes, production, and developer environments I often have multiple versions of a class or Visualforce page in many different places and I lose track of minor changes. Yes, I should be using some type of real version control system but I am the only developer and so far there haven’t been any issues. I also get the vibe this is the way a lot of orgs are developing on Force.com, wild wild west style.

To compare two files in Eclipse simply hold CTRL while selecting the files, right click on one of them, Compare With, and then select Each Other. This will load a screen that allows you to easily identify the differences between the two files. This works for everything including triggers, classes, pages, objects, etc.

For the Eclipse gurus the response may be, “uh, duh”, but a lot of people developing on the Force.com platform may be new to Eclipse (myself included) and this is a great little feature.

Categories: Apex, Visualforce

Custom Multi-Select Buttons

June 18th, 2009 4 comments

A little feature that I have always thought was cool is the ‘Clone’ multi select button on an opportunity. I even created an idea here, Custom Multi Select Buttons, and it has received a decent amount of votes. Something like this could really stream line the design of certain Visualforce pages. Sure, you could create essentially the same functionality with a pick list and then add a commandButton next to it but the concept of a multi select button seems much more polished.

I decided to take a stab at creating my own custom component for a multiSelectButton. Using Firebug to inspect how the clone button worked and some recently acquired knowledge on how javascript can modify css I have successfully created this component. Once setup it is very easy to use.

To see this in action you can check out my examples here: 
http://tehnrd-developer-edition.na7.force.com/multibutton/

To see how it all works lets first take a look at the custom component. There are only two attributes. The text that should be displayed on the button and a uniqueId string to ensure all the div Ids are unique because if you placed this component on the page multiple times without this uniqueId there would be issues. The name of this component will be “multiSelectButton”.

<apex:component >
	<apex:includeScript value="{!$Resource.multiSelectButton_js}"/>
	<apex:attribute name="buttonText" description="Text displayed." type="String" required="true"/>
	<apex:attribute name="uniqueId" description="Unique Id for this componenet. Must be unique across all multiSelectButtons. This is not the component Id." type="String" required="true"/>
 
	<div name="multiButton" id="button{!uniqueId}" class="menuButton" onclick="showOptions('{!uniqueId}');" >
		<div id="CloneButton{!uniqueId}" class="menuButtonButton" onmouseover="divHover = 'CloneMenu{!uniqueId}';" onmouseout="divHover = '';">{!buttonText}</div>
		<div name="multipButtonOpts" id="CloneMenu{!uniqueId}" class="menuButtonMenu">
			<apex:componentBody/>
		</div>
	</div>
</apex:component>

As you can see the component is importing a javascript and file here it is. To set this up you will want to copy this text, paste it into the notepad editor of choice and then save with a .js file extension. You will then need to upload it as a static resource with the name ‘multiSelectButton_js’. This javascript file controls the showing and hiding of the button options.

var divHover = '';
 
/*When a multi select button is clicked this method executes. First it hides all options for every
multiselect button on the page the show but options for the button that was clicked. This way, if
you click one button and then click another button the options on the first will disappear. */
 
function showOptions(objId){
	var multiButtons = document.getElementsByName("multiButton");
	for(var i=0; i < multiButtons.length; i++){
		multiButtons[i].style.position = '';
	}
 
	var multiButtonOpts = document.getElementsByName("multipButtonOpts");
	for(var i=0; i < multiButtonOpts.length; i++){
		multiButtonOpts[i].style.display = 'none';
	}		
 
	document.getElementById('CloneMenu' + objId).style.display = 'block';
	document.getElementById('CloneMenu' + objId).style.top = '17px';
	document.getElementById('button' + objId).style.position = 'relative';
}
 
/*Any time the document is click and the mouse is not over a multiselect button hide 
all options */
document.onclick = function(){
	if(divHover == '' || divHover == null){
		var divs = document.getElementsByTagName('div');
		for(i=0; i < divs.length; i++){
			if(divs[i].getAttribute('name') == 'multiButton'){
				divs[i].style.position = '';
			}
			if(divs[i].getAttribute('name') == 'multipButtonOpts'){
				divs[i].style.display = 'none';
			}
		}
	}
}

Next we will take a look at the page. This component is very easy to use. Simply create the component by filling in the two required attributes and fill the content of this custom component with either outputLinks or commandLinks. This page has a few examples of how this can be used.

<apex:page controller="multiButton">
	<apex:form >
		Normal html links:<br/>
		<c:multiSelectButton uniqueId="show1" buttonText="Links">
			<apex:outputLink value="http://www.digg.com">digg.com</apex:outputLink>
			<apex:outputLink value="http://www.engadget.com">engadget.com</apex:outputLink>
			<apex:outputLink value="http://www.gizmodo.com">gizmodo.com</apex:outputLink>
		</c:multiSelectButton><br/><br/>
 
		Links that pass params:<br/>
		<apex:inputText value="{!searchValue}"/>
		<c:multiSelectButton uniqueId="show3" buttonText="Search">
			<apex:commandLink value="Google" action="{!doSearch}">
				<apex:param assignTo="{!searchEngine}" value="www.google.com/search?q="/>
			</apex:commandLink>
			<apex:commandLink value="Yahoo" action="{!doSearch}">
				<apex:param assignTo="{!searchEngine}" value="search.yahoo.com/search?p="/>
			</apex:commandLink>
			<apex:commandLink value="Bing" action="{!doSearch}">
				<apex:param assignTo="{!searchEngine}" value="www.bing.com/search?q="/> 
			</apex:commandLink>
		</c:multiSelectButton><br/><br/>
 
 
	    These options are bound to action methods in the controller:<br />
		<apex:pageBlock id="tables">
 
			<apex:pageBlockButtons location="top">
				<c:multiSelectButton uniqueId="show2" buttonText="View:">
					<apex:commandLink value="Accounts" action="{!showAccts}" rerender="tables" />
					<apex:commandLink value="Opportunities" action="{!showOpps}" rerender="tables" />
				</c:multiSelectButton>
			</apex:pageBlockButtons>
 
			<apex:pageBlockTable value="{!opps}" var="o" rendered="{!viewList = 'opps'}">
				<apex:column value="{!o.Name}" />
				<apex:column value="{!o.StageName}" />
				<apex:column value="{!o.Amount}" />
			</apex:pageBlockTable>
 
			<apex:pageBlockTable value="{!accts}" var="a" rendered="{!viewList = 'accts'}">
				<apex:column value="{!a.Name}" />
				<apex:column value="{!a.BillingCity}" />
				<apex:column value="{!a.BillingCountry}" />
			</apex:pageBlockTable>
 
		</apex:pageBlock>
	</apex:form>
</apex:page>

And finally we have the custom controller with all of the logic. I won’t go into very much detail as it should be pretty clear how everything works.

public class multiButton {
 
	public List opps {get; set;}
	public List accts {get; set;}
	public String viewList {get; set;}
	public String searchValue {get; set;}
	public String searchEngine {get; set;}
 
	public multiButton(){
		//Query in the contructor for this example
		opps = [select Name, StageName, Amount from Opportunity limit 10];
		accts = [select Name, BillingCity, BillingCountry from Account limit 10];
	}
 
	public void showAccts(){
		viewList = 'accts';
	}
 
	public void showOpps(){
		viewList ='opps';
	}
 
	public pageReference doSearch(){
		PageReference searchPage = new PageReference('http://' + searchEngine + searchVAlue );
		searchPage.setRedirect(true);
		return searchPage;
	}
}

The one glaring area that needs improvement is the requirement to use a uniqueId attribute. Without this I could not figure out a way to guarantee that all of the div Ids would be unique if there are multiple components. If any knows please let me know and I can update the code.

Another thing to watch out for is the fact that I used salesforce.com style sheets. This is not a best practice because if these change it may hose the look and feel of the buttons. I used them in this demo to keep it simple but you may want to create your own to ensure they do not change.

Categories: Visualforce