A Modular Design Pattern

Published Friday, July 17, 2009 in Unfinished Articles

In this tutorial I will explain a very simple way to structure your website modularly.

Separating each part of the website into its own module-files makes it very easy to do updates, debug stuff and also makes adding some ajax-magic a piece of cake.

The directory structure

  • index.php
  • contact.php
  • mod/
    • header.php
    • navigation.php
    • footer.php
    • article-listing.php
    • contact-form.php
    • about.php
  • css/
    • general.css
    • layout.css
    • header.css
    • navigation.css
    • footer.css
    • article-listing.css
    • contact-form.css
    • about.css
  • js/
    • general.js
    • contact-form.js

Controllers

The files contained in the root-directory (index and contact) are the so called controllers. They control which modules go on which pages and are pretty much just a list of PHP-includes:

index.php

<?php
    $htmlTitle 
'Home page';
    
$bodyID 'index';

    include 
'mod/header.php';
    include 
'mod/navigation.php';
    include 
'mod/article-listing.php';
    include 
'mod/footer.php';
?>

Modules

If you look in mod/ you'll find the actual module-templates. Each module should be wrapped in a div with an ID corresponding to the module-name (#navigaion, #article-listing):

article-listing.php

<div id="article-listing">

    <?php foreach($articles as $article) { ?>
        <!-- POSH -->
    <?php ?>

</div>

Modular CSS

In css/ you'll notice that each module also has its own CSS-file. Every selector in a module CSS-file should start with the module's ID-name. So if you open footer.css, every selector should start with #footer. This is to ensure no general styling goes in the module-files.

There's also a general.css where generic styling (on simple element selector-level (h1 for example)) as well as general (CSS-)classes goes, and a layout.css that is kind of the "controller" for the module's design-layer (CSS) where every selector starts with a body-id (#index-page #article-listing {width: 40%; float: left;}).

And modular JS

Similarly, in js/, you'll find that each module that uses Javascript gets its own JS-file.

To make sure variable and function-names never colide, we use a similar name-spacing-standard in our JS where all the module's code goes in its own JS-object:

my-module.js

MyModule = {
    init: function() {
        this.doThisCoolThing();
        this.doTheOtherCoolThing();
        this.doThatAnnoyingThingThatBlinks();
    }, 

    doThisCoolThing: function() {}, 
    doTheOtherCoolThing: function() {},
    doThatAnnoyingThingThatBlinks: function() {}
};

MyModule.init();

It is recomended you compress and merge all your JS and CSS into one file each (all.js/all.css) as you want to keep the number of requests to a minimum to ensure a fast-loading website.

You can check out my javascript compressor as well as css compressor scripts for an easy way to merge and compress all css and js on the fly.

The benefits of modularity

The nice thing about structuring your code in a modular way like this is that you can run and render each module individually (by simply visiting /mod/my-module.php). Something very desirable if you like to hijax the functionality on your site.

The only thing that really differs from normal requests and ajax-requests is that you normally don't want to make any redirects, so I normally check to see if this is an ajax-request and, if so, act accordingly:

mod/contact.php

<?php
    $isAjax 
= isset($_SERVER['HTTP_X_REQUESTED_WITH']);

    
// ... other code

    
if(!$isAjax) {
        
header('Location: ...');
    }

    
// .... other code ...
?>

And I do all my ajax-requests through mod/:

contact.js

$('#contact form').submit(function() {
    $.post('mod/contact.php', {formData: formData}, function(data) {
        $('#contact').html($(data).html()); // the $(data).html()-trick makes only the innerHTML of the returned module go in the #contact-element. Since the contact-module includes a div#contact we don't want it in our current div#contact
    });
});

In this case we're hijaxing the form in the contact-module (#contact). Because the div#contact-element already exists we don't want to stick another div#contact in there, hence the $(data).html()-trick. This could also be done by if:ing the $isAjax in your template. I'm not sure if there are any performance-issues with doing $(data).html() rather than just data.

But it's not just ajax that's a breeze when you have a modular structure. Debugging and updating is also so much easier. When you know all your CSS for a particular module can be found in one file and one file only, and you also know that the styling in that file doesn't affect anything outside that module, you never have to worry about fixing an issue in one area, only to introduce a new one in another.

Pretty much the same obviously goes for the JS.

I've set up a very simple example-site with a basic ajax-call (using jQuery) that you can dig into if you feel like the article wasn't enough to get you started.


Bookmark It

  • del.icio.us
  • Digg
  • Furl
  • Google
  • Technorati
  • Ma.gnolia
  • BlinkList
  • Blogmarks
  • Rojo
  • StumbleUpon


Post It

From June 02 to April 23

  1. Mogrify is what you're looking for if you want to convert multiple images to multiple other images in ImageMagick
  2. Tommorrow, finally, the inFamous demo will be friggin availble on PSN!! Suweeeeeeeeet
  3. Fuck canvas is cool, I've started playing around with old 3D-shit again :)

May 2012

S M T W T F S
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31


Recent Comments

  1. quick quid on Bye, bye exscale!:
    jhtmpl...
  2. cheap viagra on Bye, bye exscale!:
    nsikku...
  3. payday loans on Bye, bye exscale!:
    ixrhvy...
  4. buy cialis on Bye, bye exscale!:
    lqlokhr...

Style Switcher

The style switcher allows you to change the look and feel of exscale.se.
Only CSS and JavaScript are changed. The XHTML stays the same.

For more information about the styles, check the styles page.


Categories


Random Quote

Vårat klannamn ska vara "Eternal Flame of the Consistent" - Krille


Random Images




Answer This!

Do you find the "scroll-pagination" annoying? (If you don't know what it is, scroll to the bottom of the first-page)


Blog Roll