Welcome to
'Confessions of a Culture Shock Junkie' ™
Home >> Technology >> The Web >> Re-architected Interactive Resume Posted

Site Style

Who's Online

We have 21 guests online
 
Re-architected Interactive Resume Posted Print
Technology - The Web
Written by Tom H.   
Monday, 20 April 2009 21:00

I have posted a new, improved, and re-architected version of my interactive resume here. The old version is here.

I call these resumes interactive because when the page first displays, a [More] button appears after each job. Clicking on this button displays more information about a given job, along with a [Less] button. Clicking on the [Less] button displays the original description along with the [More] button.

The two resumes do essentially the same thing, so what's the difference between them? For the answer, click on the link.

The Biggest Difference: Forms Vs. Event Handlers

The main difference between the two versions is:

  • The old version uses forms to set cookies that determine the contents of each job description.
  • The new version uses event handlers to change the contents of the job description.

In the old version, clicking on a [More] or [Less] button (these buttons are actually images) sets a cookie in the browser and submits a form to the server. When the server returns, the browser uses the cookie to decide which version of text to print. This is extremely inefficient because each time the user clicks a button, the browser reloads the entire page.

In the new version, clicking on a [More] or [Less] button (images) causes an event handler to fire. The [More] and [Less] image event handler then replaces only the relevant text without contacting the server.

You can tell the difference between the two resumes by looking at the URL in your browser's location bar. Note that clicking on a [More] or [Less] button causes it to change in the old version but not in the new one.

Also: A New Javascript Class

Another big difference between the two versions is, the new one uses a Javascript class to define the data members and methods needed for each job. The code for this class follows:

/**
 * jobExperience.js: defines JobExperience class
 */

/**
 * JobExperience class constructor
 * 1) Instantiate with required parameters (jobAbbrev, jobName, etc.)
 *    Note: object name must match jobAbbrev (used to construct unique id for each job)
 * 2) Set lessExp (required) and moreExp (optional)
 * 3) Call printLess() in web page
 */
function JobExperience( jobAbbrev, jobName, jobLink, jobCity, jobTitle, jobDates )
{
   this.jobAbbrev = jobAbbrev;    // *** must match object name and be unique for each job
   this.jobName   = jobName;      // required: name of company
   this.jobLink   = jobLink;      // optional: link to company's website
   this.jobCity   = jobCity;      // required: city in which work was done
   this.jobTitle  = jobTitle;     // optional: job title, show promotions if applic.
   this.jobDates  = jobDates;     // required: begin and end dates

   this.lessExp   = '';           // text to print on page load and when 'Less' pressed
   this.moreExp   = '';           // text to print when 'More' pressed

   //
   // Note that jobAbbrev is used:
   // o to create a unique id for the content and
   // o to identify the object that handles the onclick event
   //
   this.contentId = this.jobAbbrev + 'Content';
   this.lessImgTag =
      ' <img src="/images/less-plain.jpg" border="0" ' +
          'value="Less" alt="Less" name="less" title="Show fewer details about this position" ' +
          'onmouseover="this.src=\'images/less-hover.jpg\'; return true;" ' +
          'onmouseout="this.src=\'images/less-plain.jpg\'; return true;" ' +
          'onclick="' + this.jobAbbrev + '.replaceExp(\'less\');" \>' + "\n";
   this.moreImgTag =
      ' <img src="/images/more-plain.jpg" border="0" ' +
          'value="More" alt="More" name="more" title="Show more details about this position" ' +
          'onmouseover="this.src=\'images/more-hover.jpg\'; return true;" ' +
          'onmouseout="this.src=\'images/more-plain.jpg\'; return true;" ' +
          'onclick="' + this.jobAbbrev + '.replaceExp(\'more\');" \>' + "\n";
}

/**
 * prints the link containing the company name; prints city, title (optional),and dates
 */
JobExperience.prototype.printStart = function()
{
   document.write( '<li>' );
   document.write( ' <a name="' + this.jobAbbrev + '"><a>' );

   if ( this.jobLink == "" )
   {
      document.write( '<a class="nolink" name="' + this.jobName + '">' );
      document.write( '<strong><u>' + this.jobName + '<u><strong><a>' );
   }  
   else
   {
      document.write(
         '<a id="' + this.jobName + '" href="' + this.jobLink + '" ' +
            'title="Opens link in separate window" ' +
            'target="_blank"><strong>' + this.jobName + '<strong>' +
         '<a>'
      ); 
   }  

   document.write( ', ' + this.jobCity + '<br \>' );

   if ( this.jobTitle != "" )
   {
      document.write( this.jobTitle + '<br />' );
   }

   document.write( this.jobDates + '<br />' );
}

/**
 * prints the initial text, from the job heading (company name, etc.)
 * to the experience (lessExp initially)
 */
JobExperience.prototype.printLess = function()
{
   var expDivContent;

   this.printStart();

   if ( this.moreExp == '' )         // if moreExp is blank
   {                                 // don't print More button (e.g. javacert)
      expDivContent = this.lessExp;
   }
   else
   {
      expDivContent = this.lessExp + this.moreImgTag;
   }

   document.write( '<div id="' + this.contentId + '">' + "\n" + expDivContent + '<div>' + "\n" );
}

/**
 * event handler for the buttons' onclick event
 * finds node and replaces its current text with specified more/less text
 */
JobExperience.prototype.replaceExp = function(moreOrLess)
{
   var nodeToChange = getElementById( this.contentId );
   var newData;

   if ( moreOrLess == 'more' )
   {
      newData = this.moreExp + this.lessImgTag;
   }
   else
   {
      newData = this.lessExp + this.moreImgTag;
   }

   if ( nodeToChange && nodeToChange.nodeType == 1 )  // 1 = Node.ELEMENT_NODE
   {
      nodeToChange.innerHTML = newData;
   }
   else
   {
      document.write( "<p>JobExperience::replaceExp Error: " );
      document.write( "contentId not an element in document!<br />" );
      document.write( "this.contentId = " + this.contentId + "<br />\n" );
      document.write( "<p>\n" );
   }

}

Note that the replaceExp() method - at the end of the class - is the onclick event handler.

The following code shows how to use the new operator to instantiate this class into an object. The resume contains a JobExperience object similar to this samplejob for each job.

//
// samplejob: object containing information about what I did while at samplejob
// ----------------------------------------------------------------------------
//
var samplejob = new JobExperience(
   'samplejob',
   'Name of Company',
   'http://www.example.com/',
   'Denver, CO', 
   'Webmaster', 
   'February, 2005 through June, 2006'
);

samplejob.lessExp = 'Description of job experience for [Less] option goes here.';
samplejob.moreExp = 'Description of job experience for [More] option goes here.';

Once it has loaded code that instantiates a JobExperience object for each job, the web page just has to call the printLess() method to print the information for each of them. The following code shows how to do this.

samplejob.printLess();

And That's All There Is to It!

Why did I use the inefficient forms and cookies in the original version? Because they are simple and straightforward, and I was in a hurry to get this done and get on with the job search! Also, the page is fairly light, so even though the browser sends a request to the server, it does not take the page long to load.

Why did I decide to re-architect this? Because some work I did last year piqued my interest in Javascript, and while studying it recently I decided that since I have some time on my hands lately, doing this would be worthwhile.

OK, now it's on to the next project!

Last Updated on Tuesday, 21 April 2009 10:33