Forgot your password?

Home > About Us >Modern Signal Blog

Modern Signal Blog

News, tips, tricks and discussions related to web strategy, web design, and custom web application and database development.

3 Websites You Can’t Afford to Miss: Modern Signal’s Favorite Resources for Staying in the Know

It’s hard to put a finger on what makes a good website design go the extra mile to be amazing. That’s why the team at Modern Signal is careful to know where to go for the best, most useful information on top industry trends. It all comes back to making sure we deliver the best design and database solutions on the market.

Here are our team members’ top three picks for go-to websites to answer any question: from UI/UX and web design, to SEO and technology trends:

Best Site for UI/UX Development: Nielsen Norman Group

“I get the email alerts from this group,” says co-founder Eleanor Frias. “I love the concept of putting usability first, above everything else.”

The Nielsen Norman Group is a leading voice in the user experience field. They conduct research and evaluate interfaces of all shapes and sizes. For a taste of their commentary, try “Flat Vs Deep Website Hierarchy,” which provides valuable insight into structuring your website. The post “Serif vs. Sans-Serif Fonts for HD Screens“ is also worth reading, revealing that the trend of nicer computer screens has lead to new usability guidelines for on-screen typography.

Other strong IX/UX and web design websites for us include A List Apart and Smashing Magazine, which both feature articles with lots of personality and opinion.

Best Site for SEO: The SEO Book Blog

“I visited this site a lot during my initial research of SEO,” said Cathy Field, Modern Signal’s veteran project manager.

The SEO Book Blog provides great content for marketing, search, and online business from an algorithmic, publishing, and business model perspective. If you’re just getting started with SEO, try “How to Win in Local Internet Marketing”. For a more intermediate level education, “Optimizing the SEO Model,” a post that discusses Google’s recent algorithm shift, is a valuable investment of time.

Runners up? Try Moz and Search Mojo. Says Cathy, “I found that Google brought me to all three of these sites and answered most of my SEO questions.”

Best Development Website: Stack Overflow

This site is the first stop for co-founder and veteran developer, David Hammond. Says David, "9 times out of 10 it has the best answers to technical problems and questions that come up in the course of development”.

Wondering where to start? Stack Overflow is based on a forum model and is great for problem-solving, so visit the homepage and perform a search for anything specific you’re looking for, including particular topic tags. Popular questions include “How Can I Prevent SQL Injection in PHP,” and “The Definitive C++ Book Guide and List,” and forum threads are updated regularly.

For more tech blogs, we also recommend Simple Talk for SQL Server, Scott Gu’s Blog for ASP.NET, and Raymond Camden's Blog for ColdFusion, PhoneGap, and jQuery.

Did we catch any of your favorites? Let us know in the comments if there’s a great blog we’re missing out on!

Dynamic Maps: Ideas and Inspiration for Your Site

You’ve probably seen all sorts of maps around the web, the most common being directional maps for restaurants or other businesses, like this one for PF Chang's.

This type of map is used commonly to map out business locations. However, there's more to dynamic mapping than location maps. Here are some examples of maps you can easily integrate into your site.

Maps with placed markers

The simplest map involves hand placing and editing each of your markers on the map individually. This, obviously, is not the best way to map a lot of data, but if you need a quick map, it’s the way to go. Using Google’s My Maps is the easiest way to do this.

Here’s a super quick map we put together to show some favorite restaurants in Richmond, VA. It was simple to create and easy to embed here. All the information you need to do this for your site is available at Google's My Maps.

Markers pulled from database

Our dynamic map for Public Service Jobs Directory (PSJD) is a great example of what you can do with Google maps using data from a database. PSJD is a job search site for people in the law profession who’d like to work in public service. Job search results display in a grid or in a map.

We also implemented a Google map for Hidden Creek Apartments that's been customized to reflect Hidden Creek's branding elements and look-and-feel. Note that this map has custom icons indicating the type of amenities that are marked and navigation that allows the user to choose the display. Layers in the map allow users to filter results.

Maps using geospatial data

One step further is a map type that uses geospatial data to populate the markers. We’ve created a couple examples of this type of map using Google maps and also with Leaflet, a javascript library for maps.

So you want a map

Before jumping in and putting maps all over your site, you'll want to think about a few things. As with most things, planning is essential. Think about the questions below.

What is your map’s purpose?
In other words, what questions will it answer for your users? Simple directional maps answer the question “Where is it?” but maps that integrate more complex sets of data may not have such clear questions and answers. Think about your data and how you want your users to use it.

How will it look and behave?
Each marker is a point location on the map; not only is the location displayed but you can also add and format text, embed a photo or video, and link to more information. Again, think about what you want here and what you want your users to do.

Where will you get the data?
Determine where you can get other data, whether from your own database or through geospatial data offered by third-party providers. For example, for our DC-area map examples, we used the map tiles and geocoding service from Cloudmade.com.

Learn more

There are quite a few blogs and sites devoted to mapping, from the map collection at the Library of Congress to Google’s mapping blog. The National Geographic site includes a vast print map collection as well as interactive maps that incorporate photography, video, and data to illustrate trends and developments around the world. For fun and inspiration, check out the Strange Maps posts on Big Think where you can find a Tacography of Mexico and the Procrasti-Nation map. And to play around a bit with creating your own map, give National Geographic’s MapMaker Interactive a try.

Overview of Google+ Sign-In

In a previous post, I described my experience working with Facebook Login integration.  I recently implemented Google login integration (aka Google+ Sign-In), which is very similar to Facebook's integration.  This feature enables Google users to login to your site using their Google credentials.  As such, the user does not need to create and remember a username and password for your site.  Their Google credentials are used instead.

Here is the main page on Google's site regarding Google+ Sign-In: https://developers.google.com/+/web/signin/.  The majority of the information is very straight-forward. However, I will share a few pieces of code that pulled it all together for me.

Here is my signinCallback function code, which redirects the browser window upon successful Google login.  Note that the accessToken parameter is sent to our server for further processing. 

function signinCallback(authResult) {
    if (authResult['access_token']) {
       // Successfully authorized
       window.location = "/MyAccount/GoogleLogOn?returnURL=@(Request["returnURL"])&accessToken=" + authResult['access_token'];
    }
}

Here is my server-side C# code that uses the accessToken provided by Google to obtain the associated Google UserID.

string googleUserID = "";
using (var webClient = new System.Net.WebClient())
{
   var json = webClient.DownloadString("https://www.googleapis.com/plus/v1/people/me?access_token=" + accessToken);
   JObject o = JObject.Parse(json);
   googleUserID = (string)o["id"];
}

Once we have the associated Google UserID, we can poll our database and confirm that a user exists in it with this associated Google UserID.  If so, we can log the user in.

Responsive Web Design without a Redesign

In November 2012, Modern Signal launched a redesign of our site.  We were (are!) very proud of how it looked and the ways it would allow us to keep future and current clients better informed.  One problem: it wasn't responsive.  Our redesign had been in the works for a while, and the design had been approved and finalized before we became fully aware of a new reality: because of the proliferation of smartphones and tablets, modern websites must adjust to a wide variety of screen sizes.  They must be responsive.

SJ5083 : Square Peg in a Round Hole by Sue Adair
Square Peg in a Round Hole  © Copyright Sue Adair and licensed
for reuse under this Creative Commons Licence.

The problem was that we had just invested considerable time and energy in redesigning our site. We were happy with the way it looked on desktop browsers, and we didn't want to start over.  The question arose, can we keep our design and just make it responsive?  This same question has started to come up with many of our clients too, and so it was definitely worth investigating.

If you ask a designer whether you need to start from scratch to make your site responsive, they are likely to say, more or less, yes.  That is, you may be able to keep much of the overall look and feel of your site, but you'll have to rethink so many things you are better off starting over.  I'm not a designer, though.  I'm a developer with years of experience in the trenches with html, css, and javascript.  And so in my usual naivete I thought, "How hard could it be?"

"How Hard Could It Be?"

The answer to this question is, of course, "It depends."  The designers are right in that you have to rethink many of the visual elements of your site in order to make it responsive.  You likely have a top navigation bar with drop-down menus.  You likely have a side navigation bar which will not fit on smaller screens.  You may have some fixed-width background images that are not going to expand and contract the way they need to in a responsive site.  The Modern Signal site had all of those things.

In the end, though, all of these challenges were surmountable with css, elbow grease, and just a little bit of targeted redesign.  I'll take you through how we tackled these challenges.

"What Needs to Change?"

The first step in making any existing design responsive is to walk through the site to identify things that have to change.  Mainly you are looking for:

  1. Areas that are fixed-width
  2. Areas that will look jumbled if they need to wrap a lot
  3. Areas that require a lot of width to make sense

There are other less well-defined things you might want to consider, like how much content people will comfortably scroll through on a phone, but these are the biggest red flags.  In our site this list brought up:

  1. Right navigation area using fixed-width background images
  2. Top navigation can wrap, but looks confusing when it does
  3. Carousel on front page uses non-responsive code and contains too much information to fit comfortably on very small screens.

So, knowing what I needed to attack, I dove in.

BootStrap - Laying the Groundwork

First things first.  We had become familiar with Twitter's Bootstrap framework.  We like it for its attractive set of widgets as well as it's framework for building responsive sites.  The first step, then, was to integrate the Bootstrap CSS files and change the html of the site to use the Bootstrap concepts of "rows" and "spans".  I won't delve into this too much as I doubt there is much I can add to the information already available.

"How to Go from Fixed-width to Expandable?"

Our right navigation presented an immediate problem: it used fixed-width background images in order to give it a distinctive banner look and feel:

The html and css looked very like this (only including relevant css):

html:
<h3 class="subnav-section">
  <a href="/aboutus">About Us</a>
</h3>

css:
.subnav .subnav-section a {
  background: url('../images/subnav-section-bkg.png') 0 0 no-repeat;
}

This is simple, effective and ... not responsive.  In the end, I ended up coming to terms with an ugly fact: I couldn't fix this with css alone.  At least not with the css available to me (maybe I can ignore IE6, maybe even IE7, but not IE8!)  I would have to add a little html to make it work.  What I ended up with was:

html:
<div class="banner-header">
  <h3>
    <a href="/about_us">About Us</a>
  </h3>
</div>

css:
.banner-header {
    background: url('../images/banner-bkg-left.png') left 0 no-repeat;
    padding-left: 30px;
}
.banner-header h3 {
    background: url('../images/banner-bkg-right.png') right 0 no-repeat;
    padding-right: 30px;
}

I added an extra div tag around the header.  The background of the div tag is the left side of the banner, while the background of the h3 tag is the right side of the banner.  The middle of the banner is, mercifully, just a plain black background and can expand to its heart's content.  This worked well, and only forced me to add one html tag.

On to the next challenge...

"How to Unclutter the Top Navigation?"

Our top navigation is a relatively simple line of links with drop-down menus that appear when you hover over the links.  They wrap fine, but get pretty jumbled on small, phone-size screens.  They also use hover actions to display submenus, which doesn't work on devices that use touch screens. 

Here is a case where simply rearranging the existing design elements didn't work.  We needed to rethink the design a bit.  The default Bootstrap template deals with this by transforming the navigation into a single button that displays a drop-down of the entire menu when clicked.  We ended up using the same idea:

What's important to note about this is that we didn't need to rethink the design of our entire page to accomplish this -- we just had to rethink this one element.

"What About the Carousel?"

Our next challenge was dealing with the carousel on our home page.  Large home page carousels are very popular on websites nowadays.  They're splashy and can be used to draw the visitor's attention to news, products, featured services, etc.  They usually, however, take up the full width of the page and so present a problem for responsive design.

So, it's a common problem, which is fortunate.  I quickly found Flexslider, which handled most of the responsive challenges for me.  It took very little time for me to replace our current carousel code with Flexslider.

We still had a problem, though.  The items in our carousel contain images and text.  We can make the images progressively smaller, but at some point we just don't have enough room to make the text fit over the images without making the text too small to see.  The answer for us was to hide things progressively as the page width gets smaller.  This is very easy to do using some built-in Bootstrap classes.  If you want something to be hidden on tablet-sized devices or smaller, use the "hidden-tablet" class:

<div class="hidden-table">...</div>

If you want something to be hidden on phone-sized devices or smaller, use the "hidden-tablet" class:

<div class="hidden-phone">...</div>

Using these classes, we hide the descriptive text in the carousal on devices smaller than 1024px wide, and we hide the carousel altogether on devices smaller than 768px.  So go from:

on large devices to:

on medium-sized devices to:

on very small devices.

Conclusions

In the end, we're very happy with the results of the responsive web design overhaul of our site.  We got it done much faster and cheaper than we would have had we gone back to the design phase.  Of course, if we had been in the market for a full redesign anyway, we would have done that, but we were happy with our design and just wanted to add some responsive sugar to it, to in effect make it a mobile website and a tablet website as well as one that looks good on the desktop.  We have heard from a lot of people who are in the same boat, and I hope this post gives heart to those who would like a responsive site but are not ready for a redesign.

Interested in implementing responsive elements on your own site? Download this checklist of things you should keep in mind.

Overview of "Login with Facebook"

I recently worked on integrating "Login with Facebook" functionality into our Lighthouse.Net CMS.  This feature enables users to login to a third-party website using their Facebook credentials.  As such, the user does not need to create and remember a username and password for your site.  Their Facebook credentials are used instead.

While I found a lot of information online about this integration, I was unable to find a great resource that fully explained how to get from the user successfully logging in using their Facebook credentials (which occurs in the browser using Facebook's Client-Side Javascript SDK) to securely logging the user into our site.  Here are the questions I had and how I addressed them:

Question 1:
What data do we need to store in our Users database table to support Facebook integration?

Answer 1:
We added a column for FacebookID.  This is an integer value generated by Facebook that serves as the primary key for each user.


Question 2:
When a user logs in using the "Login with Facebook" button (which happens in the browser using the Javascript SDK), what data do we need to pass from the browser to our server to log the user in to our app.

Answer 2:
When a user successfully logs in using Facebook's Client-Side Javascript SDK, an OAuth 2 access token is exposed to your Javascript code (accessible as response.authResponse.accessToken).  This token is a temporary token which can be used to retreive data for this user using Facebook's Social Graph API.  Here is the login flow our software follows:

  1. Send the accesss token to your server (e.g. https://www.site.com/FBLogin?accessToken=123456).  Note that the actual access token is much more complex, consisting of roughly 112 random characters.
  2. In your server code, make a request to Facebook's Social Graph API using the access token(e.g. https://graph.facebook.com/me?access_token=123456).  This call returns a JSON object which contains the user's FacebookID (the "id" field in the JSON object).
  3. Since we now know the user's FacebookID, we can find the appropriate record in our Users table and log the user in as though they submitted a form on our site with their username and password.

This logic relies on the fact that the access token generated by Facebook is complex, temporary, and unique.  If an access code can successfully be used to retrieve a FacebookID from the Social Graph, we can trust that the FacebookID we receive back is associated with correct user.  This takes the place of a user entering their username and password into a web form.

Here is the HTML and Javascript code required to add the Login with Facebook button to your site.

<script src=https://connect.facebook.net/en_US/all.js type="text/javascript"></script>
<script>
 $("document").ready(function () {
  // Initialize the SDK upon load
  FB.init({
   appId: 'YOUR_FACEBOOK_APPID', // App ID
   channelUrl: '', // Path to your Channel File
   scope: '', // This to get the user details back from Facebook
   status: true, // check login status
   cookie: true, // enable cookies to allow the server to access the session
   xfbml: true  // parse XFBML
  });
  // listen for and handle auth.statusChange events
  FB.Event.subscribe('auth.login', OnLogin);
 });

 // This method will be called after the user login into facebook.
 function OnLogin(response) {
  if (response.authResponse) {
   window.location = "/FacebookLogOn?accessToken=" + response.authResponse.accessToken;
  }
 }
</script>

<div id="fb-root"></div> <!-- This initializes the FB controls-->  
<div class="fb-login-button" autologoutlink="true" scope="" >Login with Facebook</div> <!-- FB Login Button -->  
<br /><br />

ColdFusion Rate Limiter

I was recently looking for a way to throttle the number of requests to a site from bad bots that sometimes flood a server with dozens of requests in a few seconds.  I found a very nice simple function by Charlie Arehart:
http://www.carehart.org/blog/client/index.cfm/2010/5/21/throttling_by_ip_address

Before proceeding, you might want to look over Charlie's article, which nicely lays out many of the considerations and caveats that come with limiting the number of requests by IP address.

Aside from all the caveats, Charlie's function had a couple things I wanted to adjust.  One was that, as written, it would block even "good" bots, like Googlebot, if they made requests more frequently than the "duration" parameter.  For instance, if you set it up to allow up to 6 requests every 3 seconds (as I did), it would end up blocking Googlebot from making a steady stream of requests at the frequency of once per second.  So even though Googlebot was only making 3 requests every 3 seconds it was getting blocked.

Adjusting Charlie's function to stop doing that was very easy.  But the other thing I was concerned about was whether keeping a list of IP addresses in an application variable would scale very well.  How long would the list have to be before it would affect performance?  I didn't really know, but felt it would be better to have a solution where the list would have old IP addresses pruned periodically.  I toyed with the idea of using a scheduled task to go through the list and removed old entries.  That seemed cumbersome, though.  In the end, since the site I was working on was running ColdFusion 9, I thought it would be a good opportunity to use ColdFusion 9's new caching functions.  Using ColdFusion's built-in caching functions means the I can have old IP addresses cleaned up automatically.

So here is my version of the rate limiter.  This is generally more forgiving than Charlie's version of the function.  In Charlie's version if a bot is blocked but continues to make requests (e.g. Googlebot), it will continue to be blocked until it pauses for the "duration".  In my version, the bot is blocked for the "duration" and then allowed to make more requests before being blocked again.  My main goal is to block the rogue bots that flood the system with 10 or 20 requests a second for a short time, and this does a pretty good job of that.

<cffunction name="limiter">
    <cfargument name="duration" type="numeric" default=3>
    <cfargument name="count" type="numeric" default=6>
    <cfset var cacheId = "rate_limiter_" & CGI.REMOTE_ADDR>
    <cfset var rate = cacheGet(cacheId)>

    <cfif isNull(rate)>
        <!--- Create cached object --->
        <cfset cachePut(cacheID, {attempts = 1, start = Now()}, createTimeSpan(0,0,1,0))>
    <cfelseif DateDiff("s", rate.start, Now()) LT arguments.duration>
        <cfif rate.attempts gte arguments.count>
            <cfoutput>
                <p>You are making too many requests too fast,
                please slow down and wait #arguments.duration# seconds</p>
            </cfoutput>
            <cfheader statuscode="503" statustext="Service Unavailable">
            <cfheader name="Retry-After" value="#arguments.duration#">
            <cflog file="limiter" text="#cgi.remote_addr# #rate.attempts# #cgi.request_method# #cgi.SCRIPT_NAME# #cgi.QUERY_STRING# #cgi.http_user_agent# #rate.start#">
            <cfif rate.attempts is arguments.count>
                <!--- Lock out for duration --->
                <cfset cachePut(cacheID, {attempts = rate.attempts + 1, start = Now()}, createTimeSpan(0,0,1,0))>
            </cfif>
            <cfabort>
        <cfelse>
            <!--- Increment attempts --->
            <cfset cachePut(cacheID, {attempts = rate.attempts + 1, start = rate.start}, createTimeSpan(0,0,1,0))>
        </cfif>
    <cfelse>
        <!--- Reset attempts --->
        <cfset cachePut(cacheID, {attempts = 1, start = Now()}, createTimeSpan(0,0,1,0))>
    </cfif>
</cffunction>


Reporting with SQL PIVOT

I wanted to write about another bit of code that I created for the What Color Is...? website I talked about in my previous post

Displaying the Results

Probably the most interesting and challenging part of this project was to come up with a way to generate and display the results in an efficient way.  Colors were all saved in the database as 3 separate fields (Red, Green, and Blue).  This made it easy to select a color average for all responses.  Here is the SQL:

SELECT  t.name ,
        COUNT(*) AS Count,
        AVG(IsNull(red,255)) as Red ,
        AVG(IsNull(green,255)) as Green ,
        AVG(IsNull(blue,255)) as Blue
FROM    WCIResponse r
        INNER JOIN WCIThing t ON r.ThingID = t.ThingID
GROUP BY t.name

One of the options in the survey is to select "No Color", which is saved in the database as null values.  These are converted to 255 so that it is the same as if they selected white.

That was pretty easy, but I also collect some basic, anonymous demographic information to enable breaking down the results a bit.  I ask for age, for instance.  What I wanted to do was to break down the results by age group, i.e. 20-29, 30-39, etc.  This is more complicated, of course, and I didn't want to get into doing a massive number of queries and loops, etc, to build up the results.  Fortunately I have recently gotten to know more about the SQL Server statement PIVOT.  PIVOT is made for creating just such reports as this.  This is somewhat more complicated than a simple PIVOT, because I don't want a column for every age, but I want to group the ages by decade.

I'll run through the ColdFusion/SQL code I used to make this work. 

First, I set a variable with an SQL expression to create the name of the age group, e.g. "40-49":

<cfset var AgeRange = "CONVERT(VARCHAR,Age/10*10) + '-' + CONVERT(VARCHAR,Age/10*10+9)">

I only want to include the age ranges for which I actually have data, so I do an initial query to get the age ranges in the data.  Note that the AgeRange is wrapped in brackets so that it can be used as the column name in the next query, e.g. "[40-49]".

<cfquery name="GetAges" datasource="#application.dsn#">
    SELECT  DISTINCT
            '[' + #preserveSingleQuotes(AgeRange)# + ']' AS AgeRange
    FROM    WCIPerson
    WHERE   Age IS NOT NULL
    ORDER BY AgeRange
</cfquery>

I can then build the PIVOT query including all of the age ranges.  I'm still not comfortable with the PIVOT syntax.  I've only used it a few times, and it's still hard for me to wrap my head around without looking at documentation and examples.  If you're new to PIVOT too, this site has a few good examples.  As you can see below, I reuse the AgeRange variable I set above twice.

<cfquery name="GetResults" datasource="#application.dsn#">
    SELECT  t2.name
            <cfloop query="GetAges">
                ,ISNULL(t2.#GetAges.AgeRange#,'0,255,255,255') AS #GetAges.AgeRange#
            </cfloop>
    FROM    ( SELECT    t.ThingID ,
                        t.name ,
                        #preserveSingleQuotes(AgeRange)# AS AgeRange,
                        CONVERT(VARCHAR, COUNT(*)) + ','
                        + CONVERT(VARCHAR, AVG(ISNULL(red, 255))) + ','
                        + CONVERT(VARCHAR, AVG(ISNULL(green, 255))) + ','
                        + CONVERT(VARCHAR, AVG(ISNULL(blue, 255))) AS Color
              FROM      WCIResponse r
                        INNER JOIN WCIThing t ON r.ThingID = t.ThingID
                        INNER JOIN WCIPerson p ON r.PersonID = p.PersonID
              WHERE     p.Age IS NOT NULL
              GROUP BY  t.ThingID ,
                        t.name ,
                        #preserveSingleQuotes(AgeRange)#
            ) AS t PIVOT ( MAX(color) FOR AgeRange IN ( #ValueList(GetAges.AgeRange)# ) ) AS t2
</cfquery>

The value returned here for each age range is actually a comma-delimited list of values, where the first value is the number of responses, and the next three are the RGB values.  When the data is pulled into the application (as JSON), I am able to parse these values and fill a table to colored blocks to show the selected colors for each age range.

Although the What Color Is...? site doesn't have a lot of data at this point, I believe this code should scale pretty well.  Of course in the unlikely event that the site becomes an internet phenomenon and gets millions of responses I may have to revisit this code.

Colorify: A Simple jQuery Plugin

I recently created a fun little weekend project (well, an MLK Day project to be more specific).  It's a simple survey to query users about what colors come to mind when they think about abstract ideas.  It's called What Color Is...?  The original motivation behind the site was to come up with an idea for my daughter's science fair project.  She sees letters and numbers as colors (something called grapheme-color synesthesia).  I came up with the idea to devise a simple test to see what colors, if any, most people see when they think about an abstract idea.  From there I naturally began thinking about how it could be turned into a slick online survey.  It was an interesting little project that had a number of minor technical challenges along the way.

A Touch of Eye-candy: Colorify jQuery Plugin

For the design of the site, I chose a basic gray jQuery UI theme (Smoothness).  I did this so as to not distract from the main point of the survey by putting too much color into the surrounding UI.  I did feel like adding a little bit of fun color into the UI though.  I decided that when I would put in some multicolored text in the page titles.  To achieve this, I ended up creating a simple jQuery plugin that takes any element and assigns a string of random colors to the letters in the text.  I called it "colorify":

(function($){
    $.fn.colorify = function(){
        var cify = function(s){
            var rgb = function(){
                var i = Math.floor(Math.random() * 3);
                var r = function(n){
                    return n == i ? 0 : Math.floor(Math.random() * 256);
                }
                return "rgb(" + r(0) + "," + r(1) + "," + r(2) + ")";
            }
            var s2 = "";
            for (var i = 0; i < s.length; i++) {
                s2 += "<span style=\"color:" + rgb() + ";\">" + s.substr(i, 1) + "</span>";
            }
            return s2;
        }
        this.html(cify(this.html()));
    };
})(jQuery);

This goes through each letter in the text, gets a random RGB value and assigns it to the letter by wrapping a span tag with a style parameter around the letter.  It's used like any simple jQuery plugin:

$("#wcititle").colorify();

Which creates colored text like this:

What Color Is...?

One interesting thing about this is that my first attempt at the function resulted in some colors that were just too light to show up well on a white background.  That's an obvious problem when getting completely random colors.  The solution I found was to randomly choose one of the 3 color components (R, G, or B) and set that to 0 (full saturation).  This preserves the generation of bright colors without making them too light.

I wouldn't call this a very useful plugin -- I'll probably never use it for another project.  But it was kind of fun to write.  Check it out in action at What Color Is...?

Avoiding Double Submit of Form in ASP.Net

I just implemented something that should have been simple, and actually is simple, but which ended up being a bit more of a struggle than it should have been.

We have a site where occasionally we were getting duplicate payment transactions when people submitted orders.  The transactions were all within a couple seconds of each other, so it appeared that people were just double-clicking the submit button (despite, of course, a message on the page saying to only click the button once).  We did, once upon a time, have javascript code in place that disabled the submit button when it was clicked once, but that code has been removed somewhere along the line.  I think it had been disabled due to the difficulty of dealing with client side validation -- i.e. if the client-side validation failed, the button should not be disabled, because then the user will not be able to submit the form.

I found a variety of posts online about dealing with this problem.  The basic solution is simple, which is to insert code into the form submit handler that runs the client-side validation and only disables the button if it passes.  First I set up this javascript function:

<script type="text/javascript">
    function handleSubmit() {
        if (typeof (ValidatorOnSubmit) == 'function' && ValidatorOnSubmit() == false) {
            return false;
        } else {
            $("form#aspnetForm input[type=submit]")
                .click(function() { return false })
                .fadeTo(200, 0.5);
            return true;
        }
    }
</script>

Then in the page's code behind, I registered the onsubmit function like so:

Page.ClientScript.RegisterOnSubmitStatement(Me.GetType, "OnSubmitScript", "return handleSubmit()")

The javascript function runs the same code that ASP.Net automatically runs for client-side validation, and, if the validation passes, uses jQuery to disable the submit button and fade its appearance.  The fading isn't necessary, but since it's so easy to do with jQuery, why not?

There is one thing in there though, that threw me for a loop.  Most of the posts I found online set the disabled parameter for the button, which you could do with jQuery like this:

$("form#aspnetForm input[type=submit]").attr("disabled", "disabled");

But when I did that I found that the submit action tied to the button no longer fired on the server side.  After puzzling over this for a while, I realized that when the button is disabled, the button value is no longer sent along with the form parameters, and thus the server-size click event for the button is not fired.  I wasn't able to find any references to this problem online (hence the impetus for this blog post).  So instead of using the disabled parameter, I set the click event of the button to return false, which seems to work well.

Something else that I like about this solution, is that it is very generic.  Since I use a generic selector to get the submit button ("form#aspnetForm input[type=submit]"), the javascript function could be included in a site-wide javascript library, and the onsubmit function could be registered in a master page to enable this functionality for all submit buttons on a site.  I'm not ready to do that on this site, since I just want to make sure the order checkout works well for now, but it's nice to know that if this comes up again, I can fix it in a flash.

Development Tool of the Day: smtp4dev

I wanted to take a few minutes to talk up a cool little tool that I started using a few weeks ago and have since come to rely upon.

smtp4dev (http://smtp4dev.codeplex.com/) is a dummy smtp server that, instead of sending email messages, stores them in a list for easy viewing and inspection.  Before I started using this tool, any time I wanted to test email sending for an application I had to, first of all, sanitize all of my data to make sure I didn't accidentally send messages to people that shouldn't get them, and then make sure any messages I needed to inspect were sent to my email account.  I would have to wait for messages to arrive in my inbox and deal with all of the test messages getting mixed up with my regular mail.  It was a big hassle, in other words.

An added benefit for me is that, since I access my regular mail through Gmail, I am able to easily open up the messages in Windows Live Mail (also a free download) which seems to replicate the way the email displays in Outlook.  For highly styled messages this is very important, since Outlook is a very popular client that has quite a few display quirks.

RSS Feed

Testimonials

  • Modern Signal has been a great partner for us for over the past 10 years.  As our business grew and our needs changed, Modern Signal was able to work with us to adjust our website platform in the ever-changing online world.  Their service and response level has been second to none, and we've been never been happier with our relationship with them.

    - Charm City Run

  • I love working with Modern Signal! Their CMS is very easy to use and they are incredibly responsive to questions or challenges I bring them.

    - NALP

  • Modern Signal worked with us to understand our needs and figure out what solution would work best for us. Our Lighthouse CMS is perfectly suited to our website goals. When we later needed to modify the CMS, they again took the time to understand exactly what was  needed and then built that functionality rather than delivering a cookie cutter solution.   

    - Ecosystem Investment Partners

  • I felt as if my company was their only client. They responded to my needs quickly and efficiently despite short turn around time and intense demands.

    - Teaching Strategies, Inc.

  • Modern Signal significantly enhanced our site to be more efficient and user-friendly. They provide excellent customer service with timely and cost-effective solutions.

    - Center for Medicare Education

  • Modern Signal has a professional staff that was very responsive to our needs during all phases - scoping, developing, implementing and maintaining - of our project.  We have been pleased with their ability to deliver quality work on time and on budget. If given the opportunity, I would work with them again.

    - The National Center for Safe Routes to School

  • Modern Signal understands our business - from future needs to current limitations - so their solutions are always scalable, solid, and service-oriented.

    - National Association of Home Builders