How to be a great salesman

Dave Ramsey is a fantastic businessman with an approach to businesses and finances that eschews what works over what’s hot. Given Wall Street’s track record of late, I’d say that’s a really good thing.

He’s got a good regular column called Dave Says, answering questions about personal finance and business (with a focus on entrepreneurs and SOHO’s). The following came from the latest post, and I thought it stood out as a gem for anyone who’s their own sales force:

Dear Dave,
What’s the key to becoming a great salesman?
Brent

Dear Brent,
I can sum it up in one word – serving. And don’t think for a second that serving means being subservient. I’m talking about being proactive, and making an effort to ensure that customers and potential customers alike are served well. Serving means you’re excited about what you have to offer, and you believe you’ve got a great product at a great price. It means you’re determined your customer is going to have a great experience, and if you happen to hit a bump in the road you will take care of it in a way that will make them forget it ever happened.

Serving is an attitude. You have to provide goods or services in a way that makes your customers willing to trade their time or money – things that are very precious to them – to interact with you and your business. You can pressure people if you want, but that’s going to lead to a dull and frustrating life of one-shot deals. But if you serve people well, you’ll not only have clients for life but they’ll also send all of their friends your way.

If you help enough people, Brent, and make that your first order of business, you’ll never have to worry about money. That’s a different attitude, isn’t it? But I’ve got news for you – it works!
- Dave

There’s a feed for all the Dave Says articles.


Change a select menu using jQuery

I don’t know why this is mind bending, but I seem to hit a wall every time I want to do page manipulations involving <select> boxes. Particularly, when I want to change the value selected. Based on the number of support posts I found, I’m clearly not alone.

There are two common ways to change the value selected (i.e. displayed) in a <select> menu: alter the selectedIndex or the value attribute. Which one you use depends on the information you have at hand to alter the <select>.

The selectedIndex is an incremented number assigned to each <option>. in the <select>. In other words, it has no bearing whatsoever on the value of a given option. So if you know the order of the <option>’s in your <select> and can choose based on that, you can do this…

<!-- CHANGE A SELECT BASED ON INDEX -->
<input id="change_value" name="change_value" type="button" value="Change Menu" />
<select id="my_select_box" name="var_name">
  <option selected="selected" value="aaa">Some value</option> <!-- index value of 0 -->
  <option value="bbb">Some other value</option> <!-- index value of 1 -->
</select>
 
<script type="text/javascript">
$(function() {
  $('#change_value').click(function(){
    $('#my_select_box').attr('selectedIndex', 1);
    alert($('#my_select_box option:selected').text());
  });
});
</script>

Alternatively, you can change a <select> to match the value attribute of an <option>. This is probably a more common scenario..

<!-- CHANGE A SELECT BASED ON OPTION VALUE -->
<input id="change_value" name="change_value" type="button" value="Change Menu" />
<select id="my_select_box" name="var_name">
  <option selected="selected" value="aaa">Some value</option> <!-- index value of 0 -->
  <option value="bbb">Some other value</option> <!-- index value of 1 -->
</select>
 
<script type="text/javascript">
$(function() {
  $('#change_value').click(function(){
    $('#my_select_box').val('bbb');
    alert($('#my_select_box option:selected').text());
  });
});
</script>

Hope that helps, it’s as much for you as it is me. :-)


Entrepreneurs – think like this guy

In a great article discussing how to demo a product to investors, Jason Calacanis says the following under the heading “The best products take less than five minutes to demo”…

Steve Jobs does take the demo details to a fairly detailed level, but you and I are not Steve Jobs. There is only one Steve Jobs and there is only one Apple. You’re never going to build something as cool as Steve, and as such there is no need for you to talk about your product for five or ten minutes.

In the comments, I found this response from user “COP”:

WTF????? WHY NOT?

My thoughts exactly. There’s exactly zero rules, official or unofficial, that say you can’t be as cool as Steve Jobs and build products with equivalent coolness.

This type of rhetoric happens a lot — presenting a major player in a given market as an insurmountable behemoth. We as entrepreneurs do it in our heads all the time. It’s never helpful, but more importantly it’s never true.

Take Calacanis’ example in this article. You don’t have to go back too far to find a time when Apple wasn’t the epitome of cool. In my opinion, Apple machines after the IIe were out-and-out crap until they hit another stride with OSX, which came out in 1999. I don’t recall seeing any Apple’s in school prior to that. I should know, I graduated high school in ‘99! Did you know the first iPod was released in 2001, less than 10 years ago? That’s a helluva lotta time where we can’t account for any Steve Job coolness.

The correct attitude is that of our friend COP, “Why not?” In fact I’m willing to bet that ol’ Steve said that a few times along the way as well.

To think any less, to see your competition as insurmountable, is surely a road to failure.

P.S. Note: Jobs is one of the most epic geeks in history, no question. Apple has been a successful company since its founding, but definitely wandered the wilderness through the late 80’s and 90’s, which does not fit Calacanis’ rhetoric. My goal here is to topple Calacanis’ logic, not Jobs. Mac cultists, be at ease.


Comments fixed

Just discovered that comments have been borked for a bit. Sorry about that.


Using jQuery Alerts plugin to submit a form

jQuery is awesome. The jQuery Alerts plugin is also awesome. One of the most immediate and obvious uses of the pair is presenting a spiffy confirmation box before submitting a form. For example, I recently implemented this setup on a form that ultimately deletes data. I couldn’t find a detailed example for this setup, leading to much trial and error. Here’s what worked for me.

First the form…

<form name="action_delete" action="/delete_stuff.php" method="post">
  <input type="checkbox" name="option1" value="1" /> Option 1<br />
  <input type="checkbox" name="option2" value="1" /> Option 2<br />
  <input type="button" name="fake-submit" value="Delete" onclick="confirmDelete();" />
</form>

Take note that we are dealing with a normal form, nothing fancy about the form action, the inputs, etc. The only thing special going on here is that we’ve substituted an actual <input type="submit" ... /> button for a plain button type and attached an onclick event.

Now the JavaScript…

function confirmDelete() {
  jConfirm('Are you sure you want to delete this stuff?', 'Please Confirm', function(result){
    if (result) {
      $("form[name='action_delete']").submit();
    } else {
      return false;
    }
  });
}
$(document).ready(function(){
  // [ ... ]
});

Assuming you understand the syntax for jQuery Alert, the confirmDelete() function is fairly straightforward. It’s everything around the jConfirm() call that gave me a headache.

Go back to the fact that we’re using a regular button and onclick, instead of a submit button and the onsubmit event. Nested jQuery functions, like jConfirm() and its third argument, have always caused me problems with normal JavaScript events, onsubmit in particular. If not done properly, the submit event is not “held up” by the confirmation dialog, input validation, etc. Such was the case here, so the only submit event occurs in the JavaScript after getting validation from the prompt.

Also note the position of confirmDelete(): outside of the jQuery “document ready” block. If you put it inside, it won’t work.

I explicitly identified the form to submit (line 4 in JavaScript) for sake of code clarity. This layout can easily be modified to dynamically process multiple forms.

Finally, note that this setup requires JavaScript to work, i.e. it does not gracefully degrade. In my opinion, the situations where this is actually a problem are limited. Every major browser on the market fully supports JavaScript, and enables it by default. Unless your target audience is 100% mobile (you should build a separate interface for your mobile app anyway) or in a high security sector, assuming its presence is a very safe bet.


Usability Fail: Windows Live Registration

While my MS complaints are (rightly) focused on their desktop apps, I knew Microsoft would end up in this series at some point. However, even I was surprised at how quickly it happened. These guys can’t help but do stupid things in pursuit of copycatting their competitors. Here’s a screenshot several steps deep into the Windows Live registration

Live Credit Card Challenge

Yes, that page is requesting a credit card number. No, Live does not have a monthly subscription fee. As the page states, they simply want to ensure you’re an adult.

As any savvy ecommerce retailer can tell you, the most challenging part of the online sale is the checkout. It’s easy to throw virtual items in a virtual shopping cart, but you have to commit when it comes time to pay. So site owners try all kinds of things to minimize the hurdle and get them through the messy part as quickly and effortlessly as possible, lest they change their mind. Meanwhile, Microsoft is taking this same large mental hurdle and trying to turn it into a speed bump. I can’t think of a faster way to send potential new users running for the hills.

Don’t get me wrong, using a credit card challenge as identification is perfectly fine when there’s a darn good reason for it; using it to ask “are you an adult” before opening a free messaging account is not one of them. Why is a kid with a Live account a problem? Are the risks greater than other such messaging services, or the Net at large? I suspect that the Live team is simply trying to avoid the legal hassles, but haven’t AIM, Google Chat, Yahoo IM, and their own MSN operated just fine for years without an age challenge? I think the answer is an obvious “no” to all of the above.

Were it me, I’d take my chances facing legal nonsense and give kids a greater level of access than adults. Children and young adults most rapidly adopt and embrace new technologies. IM, P2P, txt’ing, Facebook…all of these tools owe most of their success to users who, by and large, do not have credit card numbers. To willing cut them out of the deal is to quite literally cut your chances of success by more than half.


What 255 characters looks like

“Should I use TEXT or VARCHAR field here?”

I’ve lost count of the number of times that I asked myself this question when putting together database structures. Since the maximum a VARCHAR can hold is 255, it becomes a question of whether or not the data you’re saving will be any longer than that. Sometimes that’s an easy call (phone number = VARCHAR; email body = TEXT), other times its blurry (verbose error logs, foreign-language data sets, user-submitted comments, etc).

“So what? Why not just use TEXT and be done with it?”

It’s true that in most cases it won’t make a difference. However, if you need to index and search the field, you should think carefully before blindly using TEXT. The data in TEXT type fields are stored outside the table itself, using only a few bytes for pointer information. This means that TEXT fields are not indexed, while VARCHAR fields are. This can have a tremendous effect on your SQL query speeds, as generally larger TEXT fields increase query time exponentially. Even if we take indexing out of the picture, the external storage of TEXT fields means that you’ll still see generally faster searches with VARCHAR.

Which brings us back to the original problem: when is a 255 character cap good enough? See for yourself. Below you’ll find a block of lorem ispum text that’s exactly 255 characters long (spaces count):

Lorem ipsum dolor sit amet, nonummy ligula volutpat hac integer nonummy. Suspendisse ultricies, congue etiam tellus, erat libero, nulla eleifend, mauris pellentesque. Suspendisse integer praesent vel, integer gravida mauris, fringilla vehicula lacinia non

If you’re like me, you’ll look at that and say, “That’s a lot more than I thought.”

Another way to look at it: RFC2822 says that a subject line may contain 998 total characters, with a max of 78 per line. Most mail clients don’t support multi-line subjects, so 78 characters is the practical limit you’ll find in most cases.

So if you ever find yourself doing that fuzzy-string-length-guestimation math in your head, bookmark this page to add a visual to the guesswork as well.


Go Bullets!

My brother, Patrick, plays lacrosse for Gettysburg College. Last weekend they beat Stevenson University — an upset by the stats, but they owned the game — which advanced them to the NCAA Division III Championship.

They’ll be playing Cortland at Gillette Stadium, home of the New England Patriots, on Sunday for the title. The game will be televised on CBS College Sports Network.

So yeah, my brother? Kind of a big deal.

Good luck, bud! Kick ass!


IE: You’re still doing it wrong…

While working on the file manager section of the Fwd:Vault website, I decided to do a quick check on cross-browser compatibility. The following screenshots are of the same page using the same HTML layout, CSS definitions, etc…

At this point in my career, I don’t think words can express how much I utterly loathe Microsoft’s IE team (and Microsoft in general) for their completely overt dismissal of browser standards. But that won’t stop me from trying, so listen up, you morons.

Building a website is an incredibly complex task, and that complexity increases almost daily. Today, all my sites include code written in HTML, CSS, JavaScript, SQL, and PHP (or ASP, JSP, etc). Nuance aside, that’s five languages! All intermingled to accomplish one goal: put a page in front of a user.

On top of that, I have to worry about abstract concepts like SEO, caching, file sizes/load times, traffic stats, usability, server uptime, SSL, data integrity, backups, security…I could keep going. I have enough to do without having to worry about your browser — I check the others, I only worry about your browser — mucking up my display or breaking my Javascript. Less time spent dealing with browser compatibility issues equals more time building a better browsing experience, which is good for everyone, even you.

Furthermore, I don’t like the notion of “pushing” a user toward or away from any given browser. As a web developer and webmaster, I am in the business of delivering my site content. Having to urge people to choose a better browser is a distraction at best, lost traffic at worst. From the perspective of my users, it’s better to just handle the problems quietly in the background. I think this same mindset is why you don’t see overwhelming support (yet) for movements like WeDontSupportIE.com.

However, as my example above starkly displays, there are now four solid mainstream alternatives out there, and plenty of smaller options as well. That says nothing about the inroads of Mac and Linux into the OS market. How much longer do you think “IE inertia” will carry?

In short, when it comes to HTML/CSS interpretation and display, IE should be in lock step with competitors. If you do that, you can essentially remove web developers from the browser debate, which is big for you because you’re not winning any popularity contests with us. Differentiate yourself from the competition by creating a better user experience, and let the end user decide.

Of course I’m not holding my breath, so one of these buttons my end up on Fwd:Vault before launch

I haven’t decided yet…


Translating PHP error constants

I wanted to log all the errors thrown out by Fwd:Vault processes to ensure that any bugs I don’t catch myself bubble to the top very quickly. To get started, I replaced PHP’s default error handling with a custom error handler function, which simply logs the error in a MySQL table before passing it along to the normal internal error handler.

Later, I’m going to add non-error notices to the mix, and set up an RSS feed to output these errors, allowing me real-time updates on overall system health.

If the error handling stuff sounds like Greek, read up before going further:

When PHP throws any kind of error, the error is assigned an error level, which can be expressed in two ways: an integer or a predefined constant. The constant represents the integer, making the two completely interchangeable. However if you build a custom error handler, you are only given the integer, which doesn’t automagically translate back to the constant value. It’s a heckuva lot easier to recognize E_USER_ERROR instead of the integer 256, so I want to store that error constant for reading purposes. If you find yourself looking at error numbers, and want the matching constant string, use this block of code:

switch ($errno) {
  case 1:     $e_type = 'E_ERROR'; break;
  case 2:     $e_type = 'E_WARNING'; break;
  case 4:     $e_type = 'E_PARSE'; break;
  case 8:     $e_type = 'E_NOTICE'; break;
  case 16:    $e_type = 'E_CORE_ERROR'; break;
  case 32:    $e_type = 'E_CORE_WARNING'; break;
  case 64:    $e_type = 'E_COMPILE_ERROR'; break;
  case 128:   $e_type = 'E_COMPILE_WARNING'; break;
  case 256:   $e_type = 'E_USER_ERROR'; break;
  case 512:   $e_type = 'E_USER_WARNING'; break;
  case 1024:  $e_type = 'E_USER_NOTICE'; break;
  case 2048:  $e_type = 'E_STRICT'; break;
  case 4096:  $e_type = 'E_RECOVERABLE_ERROR'; break;
  case 8192:  $e_type = 'E_DEPRECATED'; break;
  case 16384: $e_type = 'E_USER_DEPRECATED'; break;
  case 30719: $e_type = 'E_ALL'; break;
  default:    $e_type = 'E_UNKNOWN'; break;
}

This will give you a string in $e_type matching the proper constants. The switch block accounts for all the current PHP constants as of this posting, plus a catch-all E_UNKNOWN in case you’re doing something really weird.

Now let’s add some perspective to this code block. Here’s an sample custom error handler that grabs the constant string for logging purposes and outputs the error to the screen. The internal handler is bypassed in this example, since we don’t need it to do anything (note how the function kills page processing when a fatal error occurs). We’ll also set this custom function as the default error handler.

function custom_error_handler($errno, $errstr, $errfile, $errline) {
  $exit_now = false;
  switch ($errno) {
    case 1:     $e_type = 'E_ERROR'; $exit_now = true; break;
    case 2:     $e_type = 'E_WARNING'; break;
    case 4:     $e_type = 'E_PARSE'; break;
    case 8:     $e_type = 'E_NOTICE'; break;
    case 16:    $e_type = 'E_CORE_ERROR'; $exit_now = true; break;
    case 32:    $e_type = 'E_CORE_WARNING'; break;
    case 64:    $e_type = 'E_COMPILE_ERROR'; $exit_now = true; break;
    case 128:   $e_type = 'E_COMPILE_WARNING'; break;
    case 256:   $e_type = 'E_USER_ERROR'; $exit_now = true; break;
    case 512:   $e_type = 'E_USER_WARNING'; break;
    case 1024:  $e_type = 'E_USER_NOTICE'; break;
    case 2048:  $e_type = 'E_STRICT'; break;
    case 4096:  $e_type = 'E_RECOVERABLE_ERROR'; $exit_now = true; break;
    case 8192:  $e_type = 'E_DEPRECATED'; break;
    case 16384: $e_type = 'E_USER_DEPRECATED'; break;
    case 30719: $e_type = 'E_ALL'; $exit_now = true; break;
    default:    $e_type = 'E_UNKNOWN'; break;
  }
  echo "<strong>$e_type</strong> &mdash; $errstr on line $errline in file $errfile<br />n";
  //send_to_log("$e_type - $errstr on line $errline in file $errfile");
  if ($exit_now) exit(1);
  // Don't execute PHP internal error handler
  return true;
}
set_error_handler('custom_error_handler');

At this point you have all the information necessary to do whatever you want with the error. A future post will expand on that send_to_log() statement, but serves as a placeholder example.


Next Page »