« Sending an XML document object to PHP with jQuery

d’bug redesigns again… keeping it simple and clean »

Using CSS specificity to better organize your JavaScript

June 17th, 2009 by Brian | 7 Comments »

I’m in a constant quest to better organize my JavaScript, and lately I’ve started to realize I’m going about it all wrong. I typically design my namespace as a series of functional components that can be called on each page. However, I’m realizing it is much easier to create a namespace that has a direct correlation to the pages themselves. Depending upon the page, I can then change a function’s output accordingly.

This approach relies upon CSS specificity, and more directly, the class name that gets associated with the body of the page. Not only does the technique help to organize and maintain a style sheet, but it allows me the ability to call methods that are purposefully related to the page content. Consider the following basic XHTML page structure:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" lang="en-US">
<head profile="http://gmpg.org/xfn/11">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
	<title></title>
	<script language="javascript" src="jquery-1.3.2.min.js"></script>
	<script language="javascript" src="specificity.js"></script>
</head>
<body class="news-events">

	<!-- page content -->

</body>
</html>

The body has the “news-events” class, which helps me to adjust pre-existing styles, and therefore design a page that is specific to the news and events layout without recreating an entirely new template. The news and events content may also contain some functionality that is both global, and specific to this page — possibly a scrolling news ticker and an image gallery. The following is an example namespace that takes advantage of this approach.

var dbug = {
	specificity : [],
	init : function() {
		dbug.global.run();
		dbug.specificity[ "home" ] = function() {
			dbug.home.run();
		};
		dbug.specificity[ "news-events" ] = function() {
			dbug.newsEvents.run();
			dbug.widgets.gallery();
		};
		for ( key in dbug.specificity ) {
			if ( $( "body" ).hasClass( key ) ) {
				new dbug.specificity[ key ];
			}
		}
	},
	global : {
		run : function() {
			alert( "You just called the dbug.global.run() method!" );
		}
	},
	home : {
		run : function() {
			alert( "You just called the dbug.home.run() method!" );
		}
	},
	newsEvents : {
		run : function() {
			alert( "You just called the dbug.newsEvents.run() method!" );
		}
	},
	widgets : {
		gallery : function() {
			alert( "You just called the dbug.widgets.gallery() method!" );
		}
	}
};
$(function() {
	dbug.init();
});

Using jQuery is not necessary, but it helps to quickly prototype the previous example. What I’m creating is an associative array that maps function constructors to keys in the array. Those keys are the CSS class names applied to the body of the page. If the body has a particular class, then a new object is referenced (using the constructor), which in turn calls any other related functions. A few brief notes:

  • I always call a global method first, which I use as a catch-all for functionality that needs to appear on every page, or almost every page.
  • The widgets method could be used for any functionality that might appear on several pages, but not necessarily related to a specific page.
  • At first glance, you might be tempted to try and pass parameters through in the for loop, but if a function really needs to perform a different operation based upon the page, then pass the parameters through to the function for that page inside the constructor.
  • You can either call the page function, which then calls individual widgets, or like the example you can call the page function, and then call the widget function immediately after.

Conceptually, this worked well for me, and I have yet to run into any roadblocks, but I would invite you to take a closer look and try it out on a smaller project to see if it might suite your needs as well.

Tags: , , ,

Posted in: Cascading Style Sheets, JavaScript, Web Development

This entry was posted on Wednesday, June 17th, 2009 at 4:40 am and is filed under Cascading Style Sheets, JavaScript, Web Development.

You can follow any responses to this entry through the RSS 2.0 feed.

Both comments and pings are currently closed.

7 Responses to “Using CSS specificity to better organize your JavaScript”

  1. I like the approach you’ve outlined above. Lately I have gone in the direction of having one common js file (namespaced of course), and js files (again, each namespaced) for the needs of varying pages. During build/deployment I have a method in place that serves the combines/minifies/serves appropriate js files. I do think I’ll give this a try on my next smaller project where I’m not so concerned with asset separation. Thanks for sharing.

  2. Brian says:

    Hey Jason, thanks for the comment and for sharing your approach. I’ve used separate JS files as well, and I find that is still the best approach for extremely large Web applications. The approach above works best when there is no construct for having separate files (but you still can class the body tag), and it is easier to just use one file.

    Thanks again!

  3. bushman says:

    Brian,

    for the sake of argument, lets say that you have a need to have multiple JS files… it is possible to insert a script tag dynamically correct… instead of calling the run method.

    Would this be best of both world?

    ps. I am thankful that u share, I am always learning from u.

  4. Brian says:

    Hi bushman,

    It is possible to insert script tags dynamically, which would be the best of both worlds. Thanks for pointing that out. You can have a look here for one approach:

    http://synarchydesign.com/insert/

    Thanks for your comment!

  5. bushman says:

    Brian, are you familiar with Web Workers… interesting stuff here.

  6. ron says:

    hi brian,

    i was looking all over your website for a portfolio but it doesn’t seem like you put one up? do you have any example websites where you’ve used this structure? it looks very clean!

  7. Brian says:

    Hi Ron,

    This is the only production example I have for this technique:

    http://www.mollymaid.com

    A contractor for the last company I was at did the production, and I came in behind to do the JavaScript and programming. There are some empty objects that should have been removed, but other than that it follows the specificity format. The site was built in .NET using Sitecore CMS.

    Hope that helps you get your hands dirty!

    Brian