This entry is part 3 of 7 in the series Cleaning up Adobe Captivate 5.5's SCORM Publishing Template

In part one of this series, we published a simple Captivate course and examined its file structure. In part two, we cleaned up the HTML file and externalized all JavaScript. Today we will clean up the JavaScript.

Cleanup task #1: Tidy things up

Personally, I like to clean up code whenever I can; I feel it helps to be consistent with your code style. For example, do you place brackets { } on a new line, or in-line? Do you skip them once in a while? Are you consistent with your semicolons and line breaks?

I’m going to quickly run through this code to add brackets where needed, clean up usage of tabs, spaces, and other whitespace, and clean up any other little messes or inconsistencies I might find, without refactoring the code.

Here’s the ‘before’ code, if you’d like to follow along. Here’s the same code after it has been cleaned up.

Not perfect, but it’s a start.

Cleanup task #2: This code is VARy verbose

Here a var, there a var, everywhere a var var. There are way too many var statements in this code, some of which re-declare a variable that has already been declared! Minimizing vars is a great first step for refactoring. I will remove vars where possible, and also group and re-order where it makes sense.

While we’re at it, let’s get those function blocks out of the conditional statements.

View the result of task #2

Cleanup task #3: Replace SWFObject 1.5 with SWFObject 2.2

This template uses SWFObject 1.5, which while very durable, is also very outdated. SWFObject 2.2 provides additional features that we can put to use in our template, including a DOM-ready function and browser detection.

I’ll be linking to the copy of SWFObject stored in the Google Libraries API. Why? It loads quickly, and it might already be cached in the visitor’s browser, and it’s one less chuck of code for me to manage. No worries, though — if you don’t like the idea of using Google’s service, just paste the SWFObject 2.2 source code into standard.js, replacing the original SWFObject 1.5 code.

Next we need to replace the SWFObject 1.5 syntax in captivate.js with SWFObject 2.2 syntax. Since SWFObject 2.2’s embedSWF method includes domready-style event handling, we don’t need to wrap the SWFObject code in a window.onload event. We can also use SWFObject’s callback functionality to invoke the focus() method.

Aside: only form elements and links can receive focus; to enable other page elements to receive focus, you must set the element’s tabIndex property. The original Captivate code did not handle this task, so we will handle it here by setting tabIndex to -1, which enables us to use JavaScript’s focus method without disrupting the browser’s default tab index order. Read more about tab index here.

View the results of task #3

Cleanup task #4: What’s with the sniffing?

Line 23 of captivate.js sniffs for Internet Explorer by looking at navigator.appName. Line 207 does the same thing, with extra checks, including a check for Windows 3.1.

No, seriously:


navigator.userAgent.indexOf("Windows 3.1") == -1
Code language: JavaScript (javascript)

(What decade is this?)

Since SWFObject 2.2 includes browser detection, we should replace all IE checks with SWFObject’s swfobject.ua.ie property. If you really stop to think, you should be asking yourself “but why are we checking for IE? Why should it receive special handling?” The goal is to use cross-browser code that works everywhere without hacks.

In two of the three IE checks, we see this:


var CaptivateObj = swfobject.ua.ie ? Captivate : document.Captivate;
Code language: JavaScript (javascript)

Umm… yeah, more code from 1998. We can do better by simply using the W3C standard document.getElementById. This is 2012, all browsers support document.getElementById now.

View the result of task #4

Cleanup task #5: Keep your comments to yourself

There are a lot of bits of code that have been commented out. Since these are never used, let’s get rid of them.

Cleanup task #6: Tame the variable definitions and string manipulation

Variable definitions are strewn all over, with some being nested in if/else blocks. Let’s simplify where we can using ternary conditional statements or by refactoring to remove the variable, if possible.

There is also a lot of clever string manipulation going on around the document.location object, specifically with the variables strURLBase, strURLParams, strURLFull, intTemp, and strTemp. If you follow the code through the document, you’ll see a huge glaring problem when you get to line 259. All of that convoluted document.location parsing and string manipulation exists solely to define the value of strURLParams, yet when we get to line 259, we see:


if(g_objAPI != null){
   strURLParams = "?SCORM_API=" + g_zAPIVersion + "&SCORM_TYPE=" + g_intAPIType;
}
Code language: JavaScript (javascript)

This line says “if the SCORM object is not null, give strURLParams the following value, overwriting any previous value.”

Since this is a SCORM 2004 course, if the SCORM object is null, the course is dead in the water. Therefore all of that hullabaloo around defining strURLParams is useless, except the part at line 259.

Also, the strURLParams variable is meant to hold value/key pairs found in the page’s URL; our template files never append querystring values to the HTML file, so there’s no point in looking for querystring parameters that will never be used. Let’s delete it… all of it!

View the result of task #6

Cleanup task #7: eval() is evil.

Any JavaScript developer worth his salt will tell you that eval() should only be used in very very very limited circumstances (such as parsing JSON). Most JavaScript developers will tell you it should be avoided completely. I’m one of them.

eval() is a security risk, and is often used as a shortcut by lazy coders. Captivate’s JavaScript (and ActionScript) is chock full of eval statements. Let’s refactor the code to avoid using eval(). It has the additional benefit of making the code more readable, too!

document.write is considered almost as bad as eval, but we’ll leave it in there for now — its sole purpose is handling VBScript in Internet Explorer, which is likely to be removed in a later post.

View the result of task #7

Cleanup task #8: SCORM 1.2 has no business here

This template was adopted from a SCORM 1.2 template, and contains lots of conditional checks to see if the course is using SCORM 1.2 or 2004. Since we know this is a SCORM 2004 template, we can remove all code related to SCORM 1.2. Captivate maintains separate templates for SCORM 1.2 and SCORM 2004 anyway, so it makes no sense to have code for both SCORM versions floating around in the page.

View the result of task #8

Our captivate.js file is now under 200 lines of code!

Cleanup task #9: Organize the SCORM code

As you recall, we created the captivate.js file as a place to store our external JavaScript. However, now that it has been pared down to a manageable and easier-to-read state, we can see that most of it is SCORM-related; since there’s already a scorm_support.js file, it’s only logical that we move our SCORM-related JavaScript from captivate.js to scorm_support.js.

View the results of task #9:
captivate.js
scorm_support.js

Cleanup task #10: Clean up scorm_support.js

Now that we’re getting into the scorm_support.js file, we should clean it up as well by applying all of the cleanup techniques and approaches we’ve used so far.

You can see a slightly cleaned up version here.

In the part four of the series, we’ll dig in to the JavaScript portion of the SCORM code, examining the FS Command and ExternalInterface code contained in the Captivate template. Continue to part 4.

Series Navigation<< Cleaning up Adobe Captivate’s SCORM Publishing Template, Part 2: HTMLCleaning up Adobe Captivate’s SCORM Publishing Template, Part 4: SCORM >>

Similar Posts