Dynamic JavaScript Tabs v1.0.1

28th March 2005

Using the Dynamic JavaScript Tabs in CMS Made Simple has shown up a small bug if you include the tabs.js file on a page that does not have an element with an id of "tabcontainer". Hence, I've released version 1.0.1 to fix this. No new features have been added.

Update: I've created a separate page to hold the download link

Dynamic JavaScript Tabs

22nd March 2005

This is some code that I wrote to create dynamic tabs. I use it for forms where I have a lot of fields and a good percentage are "advanced" or otherwise not important enough to have visible immediately. The CSS is based on ideas from Silverorange Labs and the JS code is mine. The code is released under the MIT license which basically means you can do what you like with it as long as you don't blame me!

Basic tutorial

It's not hard to use and I've included a sample html file in the zip archive. The basics are:

<div id="tab-container">
  <div class="tab-content">
      <h1 class="tab" title="title for page 1">Page 1</h1>
      <p>This is the content of tab 1</p>
  </div>
  <div class="tab-content">
      <h1 class="tab" title="title for page 2">Page 2</h1>
      <p>This is the content of tab 2</p>
  </div>
  <div class="tab-content">
      <h1 class="tab" title="title for page 3">Page 3</h1>
      <p>This is the content of tab 3</p>
  </div>
</div>
<script type="text/javascript" src="abs.js"></script>

i.e. you need a "tab-container" and then each tab is contained in a "tab-content" and we use a "tab" to sort out the title. The nice thing is that it degrades really nicely!

Update: I've created a separate page to hold the download link

Version Control

20th March 2005

Apart from my day-job, I also do a very small amount of freelance work, mainly for my old company. The weirdest thing about this work is that they don't use any version control system for their websites. So far, I've fixed one particular bug 4 times… It's got to the point where I keep their sites in my version control system so that I can find out which bits of my code they have broken or "lost". It's very odd.

That brings me to which version control system to use. To be honest, it doesn't really matter as long as you use one! The first question is whether to pay for one or to use an opensource one. My personal choice is opensource and so I would recommend CVS or Subversion. Mainly because these are the only two I've used in anger over the last few years. CVS has the benefit of being well known and hence well supported. Sourceforge use it for instance. Also tools like Zend's IDE have CVS support built in which is handy. Subversion is designed as a "better" CVS. What this means in practice is that the command line options are basically the same as CVS so it's easy to migrate to and that they have fixed the biggest perceived problems with CVS.

In my experience, the biggest improvement in subversion (aka svn) are:

  • handles file meta data. i.e. renaming a file or directory, moving a file or directory etc is all recorded and hence history works with the new filename too!
  • Tagging and Branching is super quick!

and that's all that I've noticed! To me they are awesome improvements.

If you are using CVS (like my company for instance) is it worth moving to subversion? Personally, I am not going to migrate at work yet. We don't branch often and tag fairly infrequently, so the svn improvements there are not so big. File meta data versioning would be nice, but it's not worth it for the cost in time and effort to migrate the company at the moment. Maybe it will be in future, but certainly not at the moment!

Runtime Variable Inspection

6th March 2005

The most common way to debug is to stick echo statements into your code at strategic places. If you are feeling clever, you might even output a variable's value too:

echo "<p>here: \$myvar = $myvar";</p>

I call this runtime variable inspection and as PHP is a script language, it's a very fast way to debug a script. You stick the echo statement at strategic points and with a few page refreshes in the browser, you have the troublesome bit of code nailed.

However

echo $var

doesn't really cut it for variables or objects (or booleans for that matter). To this end I wrote myself a function called DB() to print out a variety of variables sensibly.

The code looks like this:

function DB($var, $title='', $echo_to_screen = true)
{
  if($title)
    $titleText = "Debug display of '$title':";
  else
    $titleText = "Debug: ";

  ob_start();
  echo "<p><b>$titleText</b><pre>\n";
  if(is_array($var))
  {
    echo "Number of elements: " . count($var) . "\n";
    print_r($var);
  }
  elseif(is_object($var))
  {
    print_r($var);
  }
  elseif(is_string($var))
  {
    print_r(htmlentities(str_replace("\t",'  ',$var)));
  }
  elseif(is_bool($var))
  {
    echo $var === true ? 'true' : 'false';
  }
  else
  {
    print_r($var);
  }

  echo "</pre></p>\n";
  $output = ob_get_contents();
  ob_end_clean();

  if($echo_to_screen)
  {
    echo $output;
  }

  return $output;
}

It works wonders for fixing nearly all the bugs I have to deal with. Anything more complicated usually means that I break out the proper debugger in Zend Studio (wish they had a Firefox toolbar!)

Additional Content Blocks

3rd March 2005

I hacked together support for additional content blocks in CMS Made Simple over the last few days. This constitutes the first time I've hacked the main code and I'm pretty damn proud of myself!

In the end the feature wasn't as difficult to write as it might have been. This is due to some rather clever design in the back end. First off, the database already separated out storage of the main text and header tags for each content page into a separate table. Thus it was easy enough to add in a variable number of extra text fields into the database. The admin interface is written using separate content classes, derived form ContentBase. So I modified the Edit() function of the the content class to add in the new textareas and away I went :)

The only tricky bit was getting the data back out of the database and into the form. The problem here is that the secondary data table (content_props) is loaded before the Content class gets to find out the template id and hence work out if there are any additional content blocks or not. I solved this by reloading the properties in Edit(), but it doesn't seem quite as clean as it could be.

To do the front end side, I introduced a new function, ContentPreRender(), into ContentBase. This works in a similar fashion to the function of the same name in ModuleBase and allows the content class to access the raw template, process it and return it back to the display function.

Nice and easy all in all!