Why JavaScript Scares Me

November 11th, 2009

If you have read this blog before you will get the vibe that I am anti javascript. This is a fair assessment as I really don’t like using javascript. I can already hear the people yelling, “JavaScript is great! It can do so many cool things”. Yes, I know, but why add more complexity if I don’t need to? Here is the story of why JavaScript scares me.

This story starts back in my sophomore year of college when I took my first “programming” class. It was basically an intro to computers (easy peasy) but about half of the class was building websites with JavaScript applications. For these assignments we were required to use notepad to build the Javascript and websites. For someone that had never really done any sort of programming this was incredibly frustrating. One wrong character and you were hosed. Oh, and don’t forget this was in the dark ages before Firefox and Firebug. Make change, save, refresh Internet Explorer (blech!), repeat, repeat, repeat. Ugh, this was so lame and left a bad taste in my mouth when it came to “programming”.

screenhunter_13-nov-10-13-33

Next up was CSE142, the intro to programming class that is supposed to weed out computer science majors. This was all java programming and we actually got to use an IDE that would show syntax errors before you compiled. This was probably the hardest class I have ever taken but it has also been the most useful class I have ever taken. After this I was feeling better about programming and things were looking up…… enter the infamous s-control.

Once out of school and at my job, after having an admin role for about six months, I decided to take a stab at updating some s-controls. What a pain. Flashbacks of javascript notepad editing flashed through my head. S-controls are so messy. I wasted hours trying to add basic functionality. Once I got it to work in one browser I realized it didn’t work in another (guess which one). This only reconfirmed my thoughts that javascript is a time suck and a pain to work with. Thankfully Apex and Visualforce were soon released and s-controls with javascript were a thing of the past.

scontrolvs

So where do I stand today? When it comes to Force.com apps I still try to keep my javascript usage to an absolute minimum. I know a lot of the Visualforce pizazz is all based on Javascript but this is script I don’t have to manage. They make sure it works, and works across all browsers.

With all of this said and done I do have a confession to make. I feel like I am having an affair with my own beliefs but I am slowly falling in love with that little bundle of joy know as the jQuery and jQuery UI JavaScript libraries. Once you get over the learning curve of understanding the basics on how to using this library it makes working with JavaScript, dare I say, almost enjoyable. I am still a bit nervous about browser compatibility and the maintenance required but jQuery is lessening these fears. So yes, I am starting to open up a little more to JavaScript and I have some blog posts planned to demo the cool things jQuery can do in tandem with the Force.com platform.

Hello Twitter

November 6th, 2009

I am now on Twitter. Hello my little bird friend.

I put it off for a long time mainly because I don’t care what people are eating for lunch or what movie they just saw. At least this is what I figured most of Twitter was about (and a lot of it still is) but this view changed rather quickly just a few days ago.

My little blog here in the corner of the internet gets traffic mainly from the developer.force.com discussion boards, from links posted on other Force.com related blogs, and the occasional search engine hit (Visualforce Popup is a hot one from search engines). It’s not a lot of traffic, but it is steady. After my Dreamforce 2009 Predictions post I saw a significant spike it traffic coming from Twitter. That blog post was tweeted by two different people and I saw site traffic increase three fold. It was easy to see the benefits of Twitter. Digging into some of the tweets I discovered what is a nice little ecosystem of Force.com/Salesforce.com users that actually post, errr…tweet, about relevant topics.

I have actually had a Twitter account for about a year now but I was one in the masses that had no tweets and no followers. Okay, so I had one tweet, which ironically was about me eating some pie. I remember the post (fric!, tweet) exactly and I was trying to explain to my parents, aunts, and uncles what Twitter was. I went on to explain it’s some lame micro blogging site where people post about everything they do. So of course I made a useless post about what I was eating. Oh how naive.

My main use of  Twitter will be to take advantage of this Force.com community, follow some trends, and post (oh my goodness… tweet) about force.com topics. Heck, maybe I’ll even toss in what I’m eating once in awhile……just kidding.

Now I ask for your help. Who are some great people in the twitter community to follow? What are some good tags to follow? I’ve already got #dreamforce, #force.com, and #salesforce. Please help this Twitter noob.

Click here for my Twitter page.

Categories: Life, Technology 3 comments

Dreamforce 2009 Predictions

November 3rd, 2009

Dreamforce 2009 is fast approaching. Last year’s big announcement was Force.com Sites, before that Visualforce, and Apex code before that. What could be the next big announcement for salesforce.com? Here are my predictions.

New UI
Salesforce.com as been working on a new UI for several years now. There was even a chance to get a sneak peak at last years Dreamforce and there have been little teasers scattered through out salesforce presentations for some time now. Salesforce.com leans heavily on the ext JS framework and I fully expect the new UI to boast some of the cooler features this javascript framework can deliver. Another reason I think this may finally be announced is that this new UI will be built upon Visualforce and for the past several months the Visualforce team, which is usually very active, has been laying low on the forums which makes me think this department is cooking up something good.

Visualforce 2.0
This one I am hoping for more than I actually think may happen but there are a few reason I think this announcement could be a possibility. In the past two to three salesforce releases there has been very little progress in regards to enhancements and new features for Visualforce. Similar to my justification for a new UI the VF team has been less involved in the forums so I can only assume they are very busy at work on the next big thing. Another piece of evidence is this one forum post in particular that I still haven’t forgot about: “we are working on visualforce native drag and drop support”, straight from the PM of Visualforce. Drag and drop is a pretty advanced thing to do with javascript so I am hoping there is a new suite of advanced Visualforce components that take advantage of all the cool things javascript can now do but maintains the simplicity and scalability that makes Visualforce so easy to use.

These are my two guesses for the big announcement but I also anticipate smaller announcements such as new partnerships and new integration toolkits, but these are boring.

Do you have any predictions for salesforce.com’s big announcement?

Categories: Visualforce 8 comments

An Open Letter to Car Dealers

October 30th, 2009

Dear Car Dealers,

Get with the times. My wife and I have spent the last four weeks test driving 12 different cars. Some cars were good and others not so good. Yet the most annoying, not surprisingly, aspects of buying a car is dancing (not literally, that would be weird) with the dealers. Most dealers are still using the same old tactics they have since the begining of car sales. This is dumb. People aren’t stupid anymore when they walk on to a dealers lot. In fact, I can learn more about the car online than most of the salesman know. So dealers, let’s be real, here are a few tips.

Second sticker
Really? You are going to artificially inflate the price of a vehicle based on “adjusted market value”. And you are going to do this in a serious recession? What are you smoking? This is such a turn off and as soon as I see this sticker the chances of me buying a car from you go way down. What the heck is “adjusted market value” anyway? Last time I checked every single one of those cars cost about the same to make no matter where it is being sold. The only real variable here would be the shipping costs which strangely enough are the same in Miami as they are in Seattle. So just because I may live in an area with a higher average income that doesn’t mean you can raise the price. Oh and don’t forget about this thing called the internet where I can go buy a car from some place that has a “lower” adjusted market value with a few clicks while sitting in my pajamas.

Test Drives
Don’t come with me, you are most likely annoying. I do understand that you may need to ride along if I am driving a really expensive car, but please, don’t talk. Having you in the car makes everything so awkward. I just want to relax and get a feel for the car but I can feel you breathing down my back from the rear seat. Any questions I have I can ask when I return, but you know what, I probably already have the answer because of this little invention called the internet. If I crash the car we all have insurance so don’t worry about that. If you don’t come with me you will also get to stay at the dealer and potentially help multiple customers at once and improve your sales. You can’t do this sitting in the back seat.

Dickering
Don’t. Once again with this magical tool called the internet I have a pretty good idea what you paid for the car. Based on my recent experiences I can usually get within $200 of what you paid. Now that I know your purchase price you have very little negotiating power. Let’s not waist time, just give me your more lowest price. If it isn’t low enough I won’t buy it. If I think you are messing with me there are about 5 other dealers that sell the exact same car as you, and I have no loyalty to you, I will walk out the door to the next dealer. If it’s fair price I’ll buy it.

So in the end guess what? We ended up buying a car from a dealer that list the lowest price they are willing to sell it for, no negotiating, no dickering. And you know what? Out of all of the dealers we went to this was the busiest. There were more people in here on a week day than others had during the weekend. What a concept, set a price and let the market decide if this is fair, fundamental economics.

Sincerely,
Jason

Categories: Life No comments

Error Handling, Savepoints, and Inserts

October 19th, 2009

I’ve been working with Apex for a little over two years now and I still learn little tips and tricks all the time.

Today I ran in to a somewhat peculiar problem when trying to catch errors on the insertion of a record. Here is the scenario in super pseudo apex code.

1) Set a database save point with Apex
2) Insert a record with Apex
3) Some type of validation error prevents the record from being inserted
4) Using a try-catch statement catch the error and display it to user
5) Roll back to your Database savepoint
6) Allow the user to fix the error.
7) When the save occurs the second time I would receive this error: “cannot specify Id in an insert call”

Huh, wait….what? The insert failed because of the validation rule, right? Kinda, sort of, it’s not really clear. Even though the insert failed my object in memory was still being assigned an Id. This caused a problem when trying to insert the second time.

I’m guessing salesforce.com sets the ID of a record before the insert as you can’t set values after inserts as the object would become read-only. Similar to how triggers work, you can only write values before inserts and updates, not after. When the operation fails the Id in the code is not removed. This is a giant guess on how the process works and it could be totally wrong.

So how to get around this problem? The solution is fairly simple. In the catch section of the code we want to clone the record without preserving the Id and assign this clone back to the original object. Something like this:

Savepoint sp = Database.setSavepoint(); 
try{		
	insert object;
}catch(exception e){
	Database.rollback(sp); 
	object = object.clone(false);
	return null;		
}

The false parameter in the clone method makes an exact copy of the object without preserving the Id. So the next time the user attempts to save, the Id is null, and there should be no issues.

Categories: Apex 2 comments

Apex Flow Control – Preventing Infinite Loops

October 2nd, 2009

When you build your first few triggers everything is so peaceful. The grass is green, the birds are chirping, and everything is working wonderfully. You continue to develop more triggers, classes, batch jobs, @future classes, and then one day your realize, “Great Scott!, I have created a monster”. If you connected all the classes and triggers that were related it would look like a giant spaghetti dinner.

When this happens you will undoubtedly run into one very specific problem. You have a piece of code A that causes code B to execute which then causes code A to execute which then causes code B to execute. OH NO! Infinite loop, governor limits AHHHHH!

Fear not! For there is a very simple solution to this problem. The extremely clear and concise diagram below shows a common scenario.

flowj

Let’s say we have an update trigger that sends a group of objects to be processed by an @future asynchronous method. There is a good chance this method will need to update the records. This would normally cause the trigger to execute and the @future method to be called again, hence our unstoppable loop. So how do we stop this loop? Before we perform the update on the records we need to say, “Hey, this is a update from a @future methods, don’t do anything”. We can do this by creating a simple Boolean value in a utility class and can be accessed by anycode in context of the update operation.

Below is the code of how something like this would work. First let’s look at the very simple solution. Yup, this is it. Some minor changes to our @future and trigger code and this is it.

public class utility{
 
    public static boolean isFutureUpdate;
 
}

Here is the trigger, we only want the code in this trigger to execute if the isFutureUpdate variable is not true.

trigger updateSomething on Account (after insert, after update) {
 
    /*We only want this trigger to perform it's logic when the
    update is not from an @future method */
    if(utility.isFutureUpdate == null || utility.isFutureUpdate == false){
 
        Set<Id> idsToProcess = new Se<Id>();
 
        for(Account acct : trigger.new){
            if(acct.NumberOfEmployees > 500){
                idsToProcess.add(acct.Id);
            }
        }
 
        //Send Ids to @future method for processing
        futureMethods.processLargeAccounts(idsToProcess);
 
    }
}

And here is our @future method. The only thing we need to add is one line of code to set the isFutureUpdate variable to true before we perform the update.

public class futureMethods{
 
    @future
    public static void processLargeAccounts(Set<Id> acctIDs){
 
        List<Account> acctsToUpdate = new List<Account>();
 
        /* Do awesome stuff with apex code */
 
        /*Before we perform this update we want to set the 
        isFutureUpdate boolean in our utility class to true */
        utility.isFutureUpdate = true;
 
        /*Now we can perform the update. The trigger will still 
        fire but none of the code inside of it will execute and
        this method will not be called again*/
        update acctsToUpdate;
    }
}

Now when the trigger is fired the @future method will not be called again.

This example shows the interaction between asynchronous operations but you can use this same solution if you have triggers that update triggers and cause a loop.

Categories: Apex 6 comments

Seattle Force.com User Group

September 29th, 2009

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

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.

Vote for Goodspaceguy

August 3rd, 2009

Tonight I am eating dinner and my wife hands me the King County voters pamphlet telling me to read the profile for a candidate running for office. The first thing to jump out at me is that he has one name, Goodspaceguy. The rest is pretty entertaining. Here are some interview questions from his website, http://colonizespace.blogspot.com/:

Question 1: What are your priorities, especially as they relate to parks and green spaces in Seattle?

Answer: I, Goodspaceguy, want to increase access to the parks by increasing free parking, and I want to increase access by keeping the parks always open, (for example, for lovers and for gay astronomers) and by providing showers for users of the parks.

Question 2: What do you see as the main issues facing Seattle’s parks and green spaces, and what is one innovative idea or change you think would help address these issues?

Answer: Lack of use. I, Goodspaceguy, want more free parking and showers. Sweaty people stink. I, Goodspaceguy, believe that showers would help solve this problem by enabling park users to exercise and then shower themselves promptly clean. Also I would like to establish campgrounds in some of the parks.

And here is the voters pamplet entry:

img_0192
Categories: Life No comments

Visualforce Pop up

July 29th, 2009

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;
    }
}

103 Fahrenheit

July 29th, 2009

It’s hot, especially for Seattle. Today we hit an all time high of 103 degrees fahrenheit. This makes us the 3rd hottest place in the country beat only by Las Vegas and areas of southern Arizona. Work has AC but upon arriving at home the thermostat in our house looked like this:

IMG_9750

Keep in mind this thermostat can’t display three digit numbers so it is even higher. Oh joy.

Categories: Life No comments

First 5k

July 28th, 2009

…and maybe the last. This weekend I ran my first “fun run” 5k. It was not exactly fun. 3.1 miles is not the far right? It is when every sport you have ever played from the age of 6 is a fast twitch sport that never required distance running. You know it’s not good when you are trying to beat 11 year old kids and are being passed by the 10Kers that left 20 minutes before you and run past you chatting it up like they have all the energy in the world. Me, after 1 mile, no talking as all focus is on breathing and trying not to die. I ran it in 30 minutes which is far from great but not horrible considering this was the longest I have ever run at once, distance and time, without stopping in my entire life.

The main reason I did it was a promise to the wife who is a crazy distance runner and is currently training for a marathon. I told her I would run a 5K with her at least once and I figured I might as well get it over with. I had previously flaked out on a St. Patrick’s Day Dash as I hadn’t trained enough. Training for this 5K consisted of working up from 1 mile to 2.5 miles a few days before the race. She was convinced she could convert me to a distance runner (I’ve been a sprinter my whole live) and after all this training and the run itself she is now convinced I am a horrible distance runner with little hope.

In the end it was a for a good cause, ovarian cancer, but now my distance (yup, 5K is distance for me) running career may now be officially over.

Categories: Life No comments

Super Cool Advanced Lookup Component

July 26th, 2009

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 8 comments

Simple Visualforce Captcha

July 16th, 2009

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.

Renton Apartment Fire

July 1st, 2009

So yesterday I am sitting at home when I look out the window and see a giant cloud of smoke. Following the smoke to the origin I see a huge fire across the valley. Probably the largest I have ever seen. Here is the video:

Renton Apartment Fire from TehNrd on Vimeo.

The structure on fire turned out to be a new apartment complex under construction with no occupants. It ended up being a 5 alarm fire and there were no deaths or injuries. Sorry for the shakiness at times but it is difficult to keep the camera steady on something 5 miles away.

Categories: Life No comments