Archive

Archive for the ‘salesforce’ Category

Show and Hide Buttons on Page Layouts

January 31st, 2012 6 comments

Cloudspokes.com recently wrapped up a challenge titled “Magical Disappearing Salesforce Button with jQuery” and I couldn’t resist not entering. For starters it’s a pretty rad name for a challenge as anything with the words “magical” and “jQuery” in it get me excited. This challenge is now closed for new entries and I’d like to share my submission. Rather than the typical blog type post I’m going to vlog it! This is the first time I have posted something with this much detail so I’d love to get feedback. Are vlogs the way of the future or should I stick to the tried and true formula of written posts? Let me know.

The best way to watch these is to go full screen and the change the playback quality to 720p.

First up is a high level overview:




Next is a 15 minute deep dive that pulls back the covers and gets into all the juicy details.


Cool?!? Want to play with it? Make it better? No problem. Here is a unmanaged package install link to get this setup in your org: https://login.salesforce.com/packaging/installPackage.apexp?p0=04tE0000000HEjD

If you had trouble seeing the markup and script in the video above here is the sidebar html component that makes the magic happen:

<!-- We can locate this div with the script below, traverse up the DOM and then hide the entire sidebar component. -->
<div id="sidebarComponentLocator">If you see this, something is broke with Dynamic Button functionality.</div>
 
<!-- Import jQuery from google CDN, could also be static resource-->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
 
<script type="text/javascript">
	/*Immediately create a unique alias for this version of jQuery to prevent conflicts with other js libraries*/
	var j$ = jQuery.noConflict();
 
	/*Determine what type of object is currently being displayed on the page. Only confident way to do this is get object prefix */
	var objectPefix = window.location.href.substring( window.location.href.indexOf('.com/') + 5, window.location.href.indexOf('.com/') + 8 );
 
	/*Query the records from Dynamic_Button__c object as soon as possible, don't wait for DOM ready event*/
	var result = sforce.connection.query("Select Button_Name__c, Field_Id__c, Field_Value__c from Dynamic_Button__c where Object_Prefix__c = '" + objectPefix + "'");
	var records = result.getArray("records");
 
	/*Execute this code block once page DOM has fully loaded*/
	j$(document).ready(function(){
		/*Hide the sidebar last as this is lowest priority. First priority is show/hiding the buttons.
		Find the sidebarComponentLocator, then find parent div with class 'sidebarModule' and the hide it*/
		j$("#sidebarComponentLocator").closest(".sidebarModule").hide().prev().hide(); 
 
		/*First loop through the dynamic button records and hide any that are on the layout. We must first hide all the buttons
		as the Dynamic Button records only contan the 'show' logic*/
		for (var i = 0; i< records.length; i++) {
			/*Hide buttons define in Dynamic_Button__c object*/
			j$("input[name='"+ records[i].Button_Name__c.toLowerCase() +"']").hide();
		}
 
		/*Now loop through the Dynamic_Button_Records and show button if field value matches that define in record*/
		for (var i = 0; i< records.length; i++) {
			/*Get the value from the field on the page layout*/
			var recordValue = j$("#"+records[i].Field_Id__c+"_ileinner").text();
			var showValue = records[i].Field_Value__c;
 
			/*Show the button if the value of the field on this record matchs the setting in the Dyamic_Button__c*/
			if(recordValue == showValue){
				j$("input[name='"+ records[i].Button_Name__c.toLowerCase() +"']").show();
			}
		}
 
		/*Everything above is cool and provides an easy to use interface for the logic but you could always hardcode the logic like so...
		First get value from the ninja field, this Id would need to be changed
		var ninjaSkillValue = j$("#00NE0000000d4hc_ileinner").text();
 
		/*Hide Ninja Attack button if Ninja Skill picklist value is not 'High'
		if(ninjaSkillValue != 'High'){
			j$("input[name='ninja_attack']").hide();
		}
		*/
	});
 
	/*If you are wondering why this file has multiline comments for one one...for some reason single line
	comments cause the script to break, something funky with salesforce and javascript in the sidebar.*/
</script>
Categories: jQuery, salesforce

Salesforce.com Workflow to the Second

December 22nd, 2011 6 comments

I recently came across the requirement for a workflow rule to fire on the update of a record but only if the update occurred more than a couple seconds after the record was created. Why this crazy requirement? Here is a example of the problem I was faced with.

Image you have two custom objects, Exam and Question. There is a master detail relationship between the two where many Questions can be associated with one Exam. There are also some roll-up summary fields on the Exam that count number of questions, number answered correctly, etc. Now also image (lots of imagining today so I hope you can harness your inner child imagination skills) you have a Visualforce page that assigns exams to users. This Visualforce page essentially clones a an Exam and Questions and assigns these to a user. First it inserts the Exam and then all related Questions. On the Exam object there is a workflow rule that need to execute when an Exam is updated. The problem is this workflow rule kept firing every time I inserted Exams and Questions for a user. Why is this happening? I am only inserting records, right? Wrong-a-long-a-ding-dong!!!

So what is happening here? Why is an update occurring on the Exam record when all I am doing is inserting records? The culprit are those very cool, but pesky, roll-up summary fields. When you have a roll-up summary field on a record any time you insert or update a child record an update will occur on the parent. So in the example above every time I would insert the the Questions it would cause on update action on the Exam. This is documented but it might not be something you come across every day. It’s also not obvious as everything happens so fast in the code the Created Date and Last Modified Date on the Exam show the same values in the user interface. If you queried these two date fields you would see they are milliseconds apart.

So how to solve this? There are a few options. We could set a flag, a checkbox field, on the Exam called Disable Workflow that we set to true on the insert of the Exam and then after inserting the Questions we could uncheck this box. In our workflow rule we could prevent the rule from executing by referencing this field. This would work but I don’t like it for a couple reasons. The first is that I hate adding fields to the database that aren’t really needed. Secondly, it’s less efficient as it requires multiple DML (update) operations to make everything flow smoothly. Another options is to get super crafty with our workflow rule.

The insert of the Exam and Questions is going to be finished in milliseconds. What if we make the rule fire on updates but only on updates a few seconds after the record is created. What we need to do is determine the time between the created date of the record and now in seconds. When working with formula fields or validations rules the duration of one day is represented as the value of 1. If we know this we can use our superior deductive reasoning skills to figured out the value for one second.

1 / 24 = 0.0416667 is one hour
0.0416667 / 60 = .00069444 is one minute
0.00001157 = one second

Now in our workflow rule we have have a formula like this:

…and it will evaluate to true on updates but only if those updates are greater than 1 second after the record was created.

Categories: Apex, salesforce

F5 Looking for a Salesforce.com Solution Developer

November 17th, 2011 No comments

So I work at a little company called F5 Networks…well we just had a $1 billion dollar year so I guess it is not that small, but we are looking for a Salesforce.com Solution Developer. Salesforce.com Solution Developer? What the heck is that? Knowing Apex, Visualforce, APIs, web services, JSON, XML, AJAX, databases, etc are all perfect skills for this position. Yet this position is not all development all the time. It is about developing full well rounded solutions. This means in addition to some of the more technical skills I already listed you also should know and enjoy working with custom objects, workflows, validation rules, formula fields etc. Heck, let’s throw in some integration work as well while we’re at it. A big piece of this role involves working directly with business units to understand their requirements, guide them at times, and quickly build applications that can be tweaked and adjusted based on feedback (think super agile). This also involves post deployment support. We also run very efficiently here as we currently have two admins/analysts and myself managing 1200+ users. This means there is also some day-to-day admin duties as well. As you can see this isn’t a pure development role so if you are looking for that… keep looking.

If this is something that sounds exciting to you please apply below and reach out to me with the contact form link above.

Salesforce.com Solution Developer Job Posting

And if you are wondering what F5 Networks as a company is like…it’s pretty cool…

http://www.f5.com/about/careers/benefits.html
http://blog.nwjobs.com/peoples_picks_2010/large_company/best_benefits_1.html?lid=710023
http://blog.nwjobs.com/peoples_picks_2010/large_company/coolest_office_space_1.html?lid=710024
http://blog.nwjobs.com/peoples_picks_2010/large_company/favorite_seattle-area_company_1.html?lid=710019
http://blog.nwjobs.com/peoples_picks_2010/large_company/most_family-friendly_company_1.html?lid=710026
http://blog.nwjobs.com/peoples_picks_2010/large_company/most_unusual_perks_1.html?lid=710027
http://blog.nwjobs.com/peoples_picks_2010/industry/favorite_technology_company.html?lid=710006
http://best.king5.com/f5-networks/biz/123372

Categories: salesforce

The Most Important Feature of Salesforce Winter ’12

October 7th, 2011 No comments

Starting this weekend salesforce.com will begin the seasonal upgrade to Winter ’12. As usual this release is packed with tons of great new features. So what is the best new feature? Chatter approvals, nope. Native JSON support, nope. Schema builder, nope. API improvements, nope. By far the most important feature of the Winter 12 release is this:

General Availability During Major Release Upgrades

Starting with Winter ’12, Salesforce will be generally available during major release upgrades.
General availability means you should only expect to experience up to a five minute disruption of service as your Salesforce
organization is upgraded. Users trying to access Salesforce during this time receive an error message that the service is unavailable
and they can log back in momentarily. In addition, users logged into Salesforce during a major release upgrade may be
temporarily logged out.

This may not seem like a big deal but it is (insert Boston accent here) absolutely frickin HUGE! You may think that 6 hours of downtime three times a year is not that much, and honestly its not, but 6 hours in a row is a big deal. Also, assuming salesforce.com has no other downtime (we can wish, right?) this still only gets you between two and three 9s up uptime. This is a huge problem for customer service call centers. Having your customer service system go down for 6 hours is simply not an option and is a deal breaker for large enterprise companies. There are many examples of salesforce.com not being able to successfully close Service Cloud deals because of this one issue alone. Reducing these upgrades times to less than five minutes places salesforce.com in the elite 4-5 9s range of uptime.

This change is important because it brings down one of the few remaining, and legitimate, barriers to cloud adoption. Sure there will still be unscheduled downtime and emergency maintenance but if you have noticed in the communications from salesforce.com a lot of these are also being performed under that status of being “General Available”. salesforce.com and cloud computing in general definitively has it’s weaknesses. Most of these are minor and feature specific weaknesses yet downtime during upgrades was a weakness that could totally prevent the adoption of salesforce.com. Now this will no longer be an issue… and I’m sure the salesforce.com account executives will have a much easier conversation with potential customers when asked about down time for upgrades.

Categories: salesforce

Getting Crafty with Queries

May 12th, 2011 6 comments

I’ve recently found myself running into several pain points when it came to extracting data from salesforce.com using SOQL. Since salesforce.com/force.com runs on a shared infrastructure they don’t allow all the bells and whistles of traditional SQL as they need to protect their resources and prevent some crazy guy like me from bringing down then entire system with some redonkulous query. You may be thinking by now that I am referring to the specific governor limits salesforce.com imposes on your queries but I am actually talking about fairly simple extractions that don’t always have the most straight forward solution.

Let’s say that you have a table of data like this:

Now let’s also say the requirement is to query items from this table but only return items based on a unique Order_Number__c. If there are duplicate Order Numbers in the table return the oldest record based on create date. The records we need to return would be the ones highlighted green.

What some of you are probably thinking is this is a totally unrealistic example because in any well designed system a field like Order Number should be unique. Well guess what? Not everyone gets to live this this happy database fairly land where duplicates don’t exist. If you you, whoop-di-do, hooray for you, click here for your prize. If you don’t live in fairy database land this example could be a totally realistic problem.

So how to solve it? Out of the box SOQL doesn’t have a solution for this problem (if it does I just wasted some time writing this) so we need to get crafty! You could maybe use aggregate queries to group by Order Number and then determine the oldest record. Or maybe query records, add them to unique Lists based on Order Number, sort these, and then return the oldest record. These are all good…well…they would work, not so sure about the “good” part. Below is the way I approached this problem and I’m sure there may be better ways to do this but I thought it was pretty slick.

We know one of the requirement is to use the oldest records if there is a duplicate. In our query we can sort by Created Date ascending so the oldest records a processed first. Before running this query we will also create a Map where the key is a Integer representing the Order Number and the value is a salesforce object, in this example Opportunity. Data returned would be processed in this order top to bottom:

As we process the returned results we will check to see if the Map contains a value for the given Order Number on the record we are currently processing. If it does not, it means this is the oldest record for this Order Number and we add it to the map. If the map does return a value for any given Order Number it means there was already an older record found and this record should not be used. In the end with have a nice clean map with the keys being the Order Number and the values being the oldest record with this Order Number. If we then need to add all these records to a list we can do that with a simple values() method called on the Map. Below is the code for this, it assumes the object being queried is an Opportunity but this logic could be applied to any object/table.

//Create the map Order => Opportunity
Map<Integer,Opportunity> oppMap = new Map<Integer,Opportunity>();
 
//Query the records and sort by CreatedDate ascending so oldest records are returned first
for(Opportunity opp : [select Id, Name, Order_Number__c, CreatedDate from Opportunity order by CreatedDate asc]){
 
    //Check if map contains Opportunity for given Order Number
    if(oppMap.get(opp.Order_Number__c) == null){
	//If null add opp to map, it is the oldest
	oppMap.put(opp.Order_Number__c,opp);
    }
 
    //Else do nothing, ignore the record as we already found an older one.
}
 
//If we need the opps in a list just do this	
List<Opportunity> opps = oppMap.values();

The one down side to this approach is that you are querying duplicate records that will never be used. Ideally you would only query the exact records needed without the duplicates even returned at all. I know of no way to do this but if you do please leave a comment below. Even with this added overhead of returned records that are never used I like this approach over the other described earlier because it is super simple and I am a big fan of simple.

UPDATE:
Based on some great comments below Greg has pointed that if you sort in desc order you don’t need the if() condition because the oldest records will be processed last and when you add them to the map it will replace any value that is currently there for the given key. The for loop could be simplified to this:

//Query the records and sort by CreatedDate descend so oldest records are processed last
for(Opportunity opp : [select Id, Name, Order_Number__c, CreatedDate from Opportunity order by CreatedDate desc]){
 
    //Add opp to map, it will replace any existing value in the map with the same key
    oppMap.put(opp.Order_Number__c,opp);
 
}
Categories: Apex, salesforce

Seattle Force.com Meetup – April 2011

April 6th, 2011 1 comment

It’s that time again and as usual I am posting this way too late but tomorrow there is a force.com meetup in Seattle.

DocuSign Headquarters
Thursday, April 7
4p-5p

1301 2nd Ave., Suite 2000
Seattle, WA, 98101

Unlike the salesforce.com meetups that focus on the out of the box functionality these meetings tend to focus on Apex code, Visualforce, APIs, custom app development, and much more.

All skill levels are welcome to attended. I believe this will be an open meetup where any topic related to force.com open for discussion.

There is also this linkedIn group you can join to keep up to date on Seattle Force.com happenings, it’s where all the cool kids hang out.

Categories: salesforce

IE9 & salesforce.com: When the cloud rains

April 1st, 2011 7 comments

UPDATE: See below.

If you don’t know already Internet Explorer 9 and Visualforce are a complete train wreck. Every single Visualforce page that performs a rerender (ajax operation) will not work with IE9. The operation appears to start and then never finishes. This has probably led to thousands of force.com developers scrambling around to find and implement a fix. The good news is fixes are pretty easy, you just need to force IE9 to run in IE8 compatibly mode. This page on developer.force.com has all of the dirty details.

So who’s is at fault for this? Microsoft’s IE9 or salesforce.com? Read more…

Force.com Rage

February 25th, 2011 9 comments

If you develop apps on force.com you have surely experienced this at least once in your life……

template

Oh, and don’t worry, I’m not an overly angry person. This is just a funny internet meme. You can learn more here.

Categories: salesforce

Looking for a Salesforce.com Superstar

February 3rd, 2011 4 comments

I haven’t posted much good content over the past few months and now I am posting advertisements. What have I become?!? The company I work at, F5 Networks, is looking for a Business Systems Analyst. This is basically a fancy name for one that administers salesforce.com but it is more than being an just an admin resetting passwords all day.

We are looking for someone that can handle the day to day requirements of being an admin; workflow rules, approval processes, validation rules, custom objects/fields, profiles/role setup, partner portal, etc. Day to day operations will be the focus but we are growing like mad and there will be plenty of opportunities to work with the business units to solve real problems using salesforce.com and this is where the analyst piece comes into play.

One thing to note is that while I post a lot of developer examples on this blog this is not a developer role (Apex/Visualforce). It’s for someone that loves delivering value with the point and click setup areas of salesforce.com.

You can check out the official job posting here: Business Systems Analyst

If you have any questions you can reach me through my contact form here.

Categories: salesforce

How to be Successful with Salesforce

January 28th, 2011 10 comments

It’s easy…

success

…read 3,000 pages of documentation.

Categories: salesforce

Dreamforce 2010, Meet jQuery

November 11th, 2010 14 comments

Many people reading this may already know what I am about to say but I’d like to announce some really exciting news. I will be co-presenting (with @JoshBirk) a session at Dreamforce 2010 on how you can use Visualforce with jQuery to build some wickedly awesome web apps.

I think this is really exciting for a few reasons. The first is that this particular session was chosen by the people for the people. On the Dreamforce Ideas website it is the most up voted session and all around idea. This means there are a lot of other people besides me excited about jQuery and how it can be used with the force.com platform.

Another reason I find this really exciting is that this will be my 4th Dreamforce and the first one I recall having a dedicated session to a JavaScript library like jQuery. One reason is that in the past 4 years JavaScript libraries have made HUGE gains in features and functionality. It will be great to see some alternatives to the typical *insert product name that rhymes with t-rex* session about building rich internet apps as I personally feel there are very few things *it* can do that most JavaScript libraries can’t.

I used to hate and despise JavaScript but jQuery has made be a believer. Rumor has it this session is filling up fast so if you are at all interested in learning more look for the session titled “Developing Applications with jQuery” in the Dreamforce agenda builder.

You can also follow the session in the Dreamforce Chatter app here: https://dreamevent.my.salesforce.com/a0930000006YhRa

UPDATE: Here is a package that includes all of the demos shown in this seesion.

UPDATED #2: Video has been posted here: http://www.youtube.com/watch?v=6je8AV6NuPM

Categories: jQuery, salesforce, Visualforce

Greasemonkey Script for Salesforce.com Setup and Apps Links

October 4th, 2010 7 comments

So…uh…who wants to tell salesforce.com that performing an operation that required one click and now requires two clicks is movement in the wrong direction on the click-o-meter productivity scale?

With the Winter 11 release they did this to admins the world over. To access the setup menu you must first click your name in the header and then click setup, system log, or log out. Why the extra click? I don’t know, it baffles me as they usually get the user interface and experience stuff right. Fear not for I provide a solution that will hopefully be included out of the box in the next release.

It is a Greasemonkey script where all you need to do is hover your mouse over your name and the options become visible. I tested in both Firefox and Chrome. You can download it by clicking here.

UPDATED: Hover support also added to App links, use same install link above.

Categories: salesforce

Force.com + 500k emails = uh oh

October 4th, 2010 7 comments

Force.com has limits. These limits are in place to make sure you don’t bring down the entire force.com infrastructure. To me these limits are simply a challenge saying, “break me, I dare you”. Building apps that find innovative ways to get around these limits can be incredibly annoying but I also find these challenges quite satisfying when you finally come up with with a radtacular awesome solution that works within the limits. In coming up with these solutions I tend to push the platform to the max…to the breaking point…. and this is one of those stories.

Awhile back I was asked, “Any idea how you could let users subscribe to a topic and then get a daily email regarding this topic with content driven from force.com?” This also had to scale up to 1000s of emails. I thought about this for a little bit, approximately 653 nanoseconds, and then came up with an idea. It was and still is a little crazy. Thousands of emails in a day is nice but I had bigger plans. Plans of epic proportions. I was going to build a email system on force.com that could literally send millions of emails in one day. Whuauahahahahahahahah!!!! (< -evil laugh). I mean, nothing could go wrong, right? Salesforce.com would have some sort of controls in place to prevent some crazy guy like me from building this right.......right? Read more…

The Salesforce Dot

September 28th, 2010 8 comments

Once you see it…..The Salesforce Dot will haunt you forever…

Categories: salesforce

Seattle Force.com User Group – August 2010

August 5th, 2010 No comments

Major late notice here but today is a Seattle Force.com user group. If you are are Force.com pro or a n00b looking for more information about this platform swing by.

WHO: Me, you, and some other cool peeps.

WHAT: Discuss force.com related topics, questions, and technologies

WHEN: Today, August 5, 2010 4:00PM

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

WHY: See WHO & WHAT

This month’s meeting will be an open forum for any questions and discussion topics you may have.

Categories: salesforce, Technology