I recently did some work on a large web application that had several .js and .css files. Per industry best practice, I wanted to use something like YUI Compressor or Google Closure Compiler to merge and minify all the JavaScript and CSS into a single .js file and a single .css file. Also, I wanted an easy way to switch from these optimized files–which are hard to read–to the original files during development (or to debug an issue in production).

In this case, the JS/CSS needed to be minified at build-time. The project was built via Maven, so it made sense to do this with a Maven project. After a lot of research, I chose a plugin called wro4j because it allows you to use an external XML file to configure exactly which files should be minified/optimized. And by making this XML file part of the website itself, you can use the information it contains (i.e., the list of individuals .js and .css files) to dynamically switch from the compressed files to the “raw” ones. The main benefit? The list of .js and .css files exists in only one place–the XML config file. Here’s what it looks like:



 
   
   /css/reset.css
   /css/master.css
   /css/typography.css

   
   /js/lib/swfaddress/swfaddress.js
   /js/constants.js
   /js/util.js
   ...
 

As I said, this configuration is used by the wro4j plugin when it minifies/compresses/optimizes the code at build-time. I won’t go into the details of how to configure wro4j here; see the wro4j website for info on that.

So assuming you have wro4j configured to generate myapp-all-compressed.js and myapp-all-compressed.css, the next thing you’ll do is modify your HTML doc to use those files:

<html>
  <head>
    <link rel="stylesheet" type="text/css" href="myapp-all-compressed.css"/>
    <script type="text/javascript" src="myapp-all-compressed.js"></script>
  </head>
  ...
</html>

So how can we easily switch from these hard-to-read files to the “original” files? We’ll use JavaScript to download the aforementioned XML config file (resources.xml), parse it, and dynamically add <script> tags for each .js and .css file. But first, we’ll modify our HTML template (in this case, a JSP page) to check for a URL parameter and use our “dynamic script loader” instead of the production files:

<html>
  <head>
  <% if( request.getParameter("debug") != null ) { %>
    <%-- DEBUG MODE: Dynamically load individual .js/.css files --%>
    <script type="text/javascript" src="loadIndividualJsCssFiles.js"></script>
    <script type="text/javascript">
    myapp.util.loadIndividualJsCssFiles('resources.xml');
    </script>
  <% } else { %>
    <%-- PRODUCTION MODE --%>
    <link rel="stylesheet" type="text/css" href="myapp-all-compressed.css"/>
    <script type="text/javascript" src="myapp-all-compressed.js"></script>
  </head>
  ...
</html>

As you can see, navigating to http://yoursite.com/ results in the “optimized for production” files being used, but something like http://yoursite.com/?debug causes the browser to instead download loadIndividualJsCssFiles.js and call myapp.util.loadIndividualJsCssFiles() with the path to resources.xml.

Finally, let’s take a look inside loadIndividualJsCssFiles.js. At a high level, it extracts the list of .js/.css files from resources.xml and dynamically adds <script> and <link> nodes to the browser’s DOM for each JavaScript and CSS file. Note: it’s easiest to start at the bottom and read up.

if( myapp === undefined ) { myapp = {}; }
if( myapp.util === undefined) { myapp.util = {}; }

/**
 * Use this function to dynamically load a single CSS file.
 *
 * @param {String} path - URL path to the .css file that should be loaded
 */
myapp.util.loadStylesheetFile = function(path) {
 var linkElement = document.createElement('link');
 linkElement.setAttribute("type", "text/css");
 linkElement.setAttribute("rel", "stylesheet");
 linkElement.setAttribute("href", path);

 // Append the new <link> element to the end of <head>. The browser should
 // start downloading it immediately.
 myapp.console.info('Loading '+ path);
 document.getElementsByTagName("head")[0].appendChild(linkElement);
};

/**
 * Use this function to dynamically load a single JavaScript file.
 *
 * @param {String} path - URL path to the .js file that should be loaded
 * @param {Object} callbackFcn - (optional) A function that will be called if/when the script finishes loading
 */
myapp.util.loadJavaScriptFile = function(path, callbackFcn) {
 var elementOnLoadFcn,
     scriptElement = document.createElement('script');

 scriptElement.setAttribute("type", "text/javascript");

 if( callbackFcn != undefined && callbackFcn != null ) {
   // Create a function that will be used as the value for the <script>
   // element's "onLoad" and "onreadystatechange" attributes.
   elementOnLoadFcn = function() {
     // This function can work for both 'onlload' and 'onreadystatechange' events
     // Note: When this code is run 'this' will refer to the <script> object.
     if ( this.readyState && this.readyState != "complete" && this.readyState != "loaded" ) {
       return;
     }
     this.onload = this.onreadystatechange = null; // ensure callback is only called once

     // Execute callback that indicates the script was loaded
     callbackFcn(this.src);
   };

   // Configure the <script> element's onload and onreadystatechange attributes
   scriptElement.onload = elementOnLoadFcn;
   scriptElement.onreadystatechange = elementOnLoadFcn;
 }

 scriptElement.setAttribute("src", path);

 // Append the new <script> element to the end of <head>. The browser should
 // start downloading it immediately; when finished, the elementOnLoadFcn
 // function (if it exists) will run.
 myapp.console.info('Loading '+ path);
 document.getElementsByTagName("head")[0].appendChild(scriptElement)
};

/**
 * Use this function to dynamically load multiple JavaScript files.
 *
 * @param {Array} filePathsArr - Array of URL paths to the .js files that should be loaded
 */
myapp.util.loadJavaScriptFiles = function(filePathsArr) {
 var jsFileIndex = 0,
     loadNextScriptFcn = function() {
       if (jsFileIndex < filePathsArr.length) {
         myapp.util.loadJavaScriptFile(filePathsArr[ jsFileIndex++ ], loadNextScriptFcn);
       }
     };

 loadNextScriptFcn();
};

/**
 * Use this function to dynamically load a single JavaScript file.
 *
 * @param {String} path - Path to a wro4j resources XML file.
 */
myapp.util.loadIndividualJsCssFiles = function(wro4jResourcesFile) {
 // JS best practice: declare vars at start of fcn (for more info, search "javascript hoisting")
 var i,
     cssNodesArr,
     jsNodesArr,
     nodesArrLength,
     request,
     jsFilePathsArr = [],
     resourcesDoc;

 // Get the XML file which has the list of all individual .js and .css files
 // used by the front-end.
 if (window.XMLHttpRequest) { // IE7+, Firefox, Chrome, Opera, Safari
   request = new XMLHttpRequest();
 } else { // IE5, IE6
   request = new ActiveXObject("Microsoft.XMLHTTP");
 }

 request.open("GET", wro4jResourcesFile, false);
 request.send();
 resourcesDoc = request.responseXML;

 // Load all stylesheet files specified by <css> elements in resources file
 cssNodesArr = resourcesDoc.getElementsByTagName("css");
 nodesArrLength = cssNodesArr.length; // Best practice: iterate HTMLCollection by caching array length
 for(i = 0; i < nodesArrLength; i++) {
   myapp.util.loadStylesheetFile( cssNodesArr[i].childNodes[0].nodeValue );
 }

 // Load all JavaScript files specified by <js> elements in resources file
 jsNodesArr = resourcesDoc.getElementsByTagName("js");
 nodesArrLength = jsNodesArr.length; // Best practice: cache HTMLCollection length instead of re-calculating for each iteration
 jsFilePathsArr = new Array();
 for(i = 0; i < nodesArrLength; i++) {
   jsFilePathsArr.push( jsNodesArr[i].childNodes[0].nodeValue );
 }

 myapp.util.loadJavaScriptFiles( jsFilePathsArr );
};

The end result is that you keep the list of .js/.css files in one place (resources.xml)–you don’t have to keep updating your .jsp or pom.xml file each time you need to add or remove .js/.css files. The loadJavaScriptFiles() function will ensure those files get picked up the next time you refresh the browser with the ‘debug’ URL param, and wro4j will similarly include those files in myapp-all-compressed.js/myapp-all-compressed.css the next time a build is done.

In the primordial days of the web, debugging JavaScript often meant using the alert() function to print information about what your code was doing. Thankfully we now have debuggers and, for developers who prefer logging, the console object which offers functions like console.log().

There’s a catch with the console object, however: it doesn’t always exist. More specifically, most browsers don’t provide a console object by default (Chrome being one exception). You usually need some kind of developer tool or extension running to provide a console object—Firebug or the ‘Developer Tools’ add-on for IE, for example. And without a console object, calls like console.log() result in a “console is not defined” error.

I came up with a solution to this on a recent project (although I highly doubt I was the first to do so). It basically involves creating a “dummy” console object that will be used if the real thing doesn’t exist, which prevents “undefined” errors. With the flip of a switch, however, you can “turn on” logging and start using the actual console if it exists.

It’s pretty simple to use. First, make sure the following gets run before any code tries to call the console functions:

// Create object that will be used for 'myapp' namespace if it doesn't already exist.
if( myapp === undefined ) {
    var myapp = {};
}

// Create an object with functions that mimic the window.console object made
// available by tools like Firebug or the "Dev Tools" add-on in IE8+
myapp.dummyConsole = {
    assert : function(){},
    log : function(){},
    warn : function(){},
    error : function(){},
    debug : function(){},
    dir : function(){},
    info : function(){}
};

// Throughout our app we'll make console/logging calls by using the myapp.console
// object. Example: myapp.console.debug("blerg!"). By default, the myapp.console
// object should use the "dummy" console that doesn't do anything.
myapp.console = myapp.dummyConsole;

// This function can be used to switch the myapp.console variable to use the
// real window.console object. Note that it does a safety check to ensure that
// window.console actually exists (it won't in browsers not running Firebug or
// the IE dev tools).
myapp.enableConsoleOutput = function(enable) {
    // Don't enable the console unless it actually exists
    if (enable && window.console !== undefined) {
        myapp.console = window.console;
    } else {
        myapp.console = myapp.dummyConsole;
    }
};

I like putting this in a file called console.js and making sure it appears in one of the first <script> elements, for example. Next, instead of using the console object directly, modify your code to use myapp.console:

myapp.console.info(“my cat’s breath smells like cat food”);
myapp.console.warn(“danger will robinson!”);

You can leave these logger statements in your code without worrying about them causing errors. To “enable logging” (i.e., swap the fake console object with the real one if it exists), call:

myapp.enableConsoleOutput(true);

This gives you the ability to dynamically turn logging on/off. You could, for example, execute the statement in the Firebug console. Another approach would be to hard-code it in your HTML doc:

<script type="text/javascript" src="console.js"></script>
<script type="text/javascript">
    myapp.enableConsoleOutput(true);
</script>

Lastly, if your HTML doc is generated dynamically (e.g., JSP, PHP, etc.) you could add some server-side logic that only writes this statement if a special “enable logging” flag exists in the URL parameters. I usually take this approach because it allows you to A) see any logging statements that execute during the page’s “startup” phase (i.e., before you have had time to run the statement in the Firebug console) and B) still gives you the option of running Firebug with logging disabled.

InAppSettingsKit

by Clint on July 15, 2010

Image courtesy of InAppSettingsKit.com

Image courtesy of InAppSettingsKit.com

I recently came across an extremely handy open source API for managing settings in iPhone apps. In a nutshell, InAppSettingsKit looks and works just like the normal settings/preferences mechanism (e.g., Settings.bundle), except that it allows you to easily display a settings view in your app in addition to the standard Settings.app (there are a few other perks, too).

In addition to their website, you can listen to a great interview with one of the creators from via the “mac developer network” website.

Update (8/19/10): It’s come to my attention that using delegates as the primary example below was not a good idea. When you have a @property for a delegate, the best practice is to use assign, not retain, so that you avoid a so-called “retain loop” and accompanying memory leaks (more info). That said, the idea of extending the NSObject protocol so that you can call release without warnings is still helpful in some situations–just not those involving delegates.

It’s pretty common to use custom Objective-C protocols in iPhone development, especially when it comes to using delegates to keep your code modular. Consider the following example:

@protocol EngineDelegate
{
    -(void) goFaster;
    -(void) goSlower;
}

@interface Automobile : NSObject
{
    id<EngineDelegate> engineDelegate;
}
@property (nonatomic, assign) id<EngineDelegate> engineDelegate;

This shows an Automobile class that has a single member variable/property, an “engine delegate” (i.e., the Automobile will delegate requests to go faster/slower to the EngineDelegate). Because engineDelegate is declared using the generic pointer “id” type, you can assign ANY object to it as long as that object implements the EngineDelegate protocol (i.e., has -goFaster and -goSlower methods). But what happens if you try to release the delegate? For example:

@implementation Automobile
...
- (void) dealloc
{
    [engineDelegate release];
}
@end

The compiler will generate a “-release not found” warning because it can’t tell if engineRelease implements the -release method. This is problematic not just because of the warning, but more importantly, because it prevents you from doing normal retain/release operations that are common in a managed memory environment like the iPhone. In other words, how are you supposed to ensure that the delegate is properly released?

I recently came across a clever solution to this dilemma on MobileOrchard. In a nutshell, the post suggests declaring protocols as inheriting from the NSObject protocol which, in turns, defines the retain and release methods. A lot of developers might be surprised to learn that you can do such a thing (I certainly was). Here’s what it looks like:

@protocol EngineDelegate <NSObject>
{
    -(void) goFaster;
    -(void) goSlower;
}

Now the Automobile class can safely assume that the delegate will implement the -retain and -release methods (and in most cases, the delegate will inherit the methods from the NSObject*). It’s nice that we can get rid of compiler warnings in this way, but it’s more important that we can use normal retain/release methods for memory management and not worry about whether or not the memory used by the delegate is freed.

*Note that not all objects extend the NSObject class (although for most folks, this is pretty rare). For example, many classes related to Cocoa’s “distributed object” mechanism descent from NSProxy instead of NSObject.

Xcode 3.2 (OSX 10.6) Shortcut Reference

by Clint on August 31, 2009

Colin Wheeler recently updated his chart of keyboard shortcuts for Xcode 3.2. Great resource.

xcodeshortcuts