Index: countdown.tpl.php
===================================================================
--- countdown.tpl.php
+++ countdown.tpl.php
@@ -8,23 +8,17 @@
  *
  * Available variables:
  * - $items: the list.
+ * - $event_name: the name of the event we are counting down to
+ * - $accuracy: the degree of detail to show in the countdown
+ * - $days_left: days left until event
+ * - $hrs_left: hours left in currently displayed day
+ * - $min_left: minutes left in currently displayed hour
+ * - $secs_left: seconds left in currently displayed minute
+ * - $passed: if the event has already occurred or not
+ * - $difference: the difference in time between now and the event date
+ * - $event_date: timestamp of the event date/time
  */
-$time = time();
-$difference = variable_get('countdown_timestamp', $time) - $time;
-if ($difference < 0) {
-  $passed = 1;
-  $difference = abs($difference);
-}
-else {
-  $passed = 0;
-}
 
-$accuracy  = variable_get('countdown_accuracy', 'd');
-$days_left = floor($difference/60/60/24);
-$hrs_left  = floor(($difference - $days_left*60*60*24)/60/60);
-$min_left  = floor(($difference - $days_left*60*60*24 - $hrs_left*60*60)/60);
-$secs_left = floor(($difference - $days_left*60*60*24 - $hrs_left*60*60 - $min_left*60));
-
 print t('%i days', array('%i' => $days_left));
 if ($accuracy == 'h' || $accuracy == 'm' || $accuracy == 's') {
   print  t(', %i hours', array('%i' => $hrs_left));
@@ -35,8 +29,9 @@
 if ($accuracy == 's') {
   print t(', %i seconds', array('%i' => $secs_left));
 }
-print t(($passed) ? ' since %s.' : ' until %s.', array('%s' => variable_get('countdown_event_name', '')));
+print t(($passed) ? ' since %s.' : ' until %s.', array('%s' => $event_name));
 
+// Leaving this in the TPL so themers can use alternative JS
 if ($accuracy != 'd') {
   $path = drupal_get_path('module', 'countdown');
   drupal_add_js($path .'/countdown.js');
Index: countdown.module
===================================================================
--- countdown.module
+++ countdown.module
@@ -43,7 +43,6 @@
       '#size' => 30,
       '#maxlength' => 200,
       '#description' => t("Event name you're counting to or from."),
-      '#required' => true
     );
 
     $form['countdown_accuracy'] = array(
@@ -56,12 +55,17 @@
 
     $time = time();
     $timestamp = variable_get('countdown_timestamp', $time);
-
+    
+    $collapsed = FALSE;
+    if (variable_get('countdown_date_field', '')) {
+      $collapsed = TRUE;
+    }
+    
     $form['target_time'] = array(
       '#type' => 'fieldset',
       '#title' => t('Target date/time'),
       '#collapsible' => TRUE,
-      '#collapsed' => FALSE,
+      '#collapsed' => $collapsed,
       '#description' => t('Select a date relative to the server time: %s', array('%s' => format_date($time)))
     );
 
@@ -114,6 +118,39 @@
       '#default_value' => (int)date('s', $timestamp),
       '#options' => $mins
     );
+    
+    if (module_exists('date')) {
+      $options = array('' => t('None'));
+      foreach (content_fields() as $key => $field) {
+        if ($field['module'] == 'date') {
+          $options[$key] = $field['widget']['label'];
+        }
+      }
+      
+      $collapsed = TRUE;
+      if (variable_get('countdown_date_field', '')) {
+        $collapsed = FALSE;
+      }
+      $form['cck'] = array(
+        '#type' => 'fieldset',
+        '#title' => t('Optionally use a CCK Date field'),
+        '#description' => t('Or choose a CCK Date field to pull the target date/time from a node. Note, if you select this option, your block can only appear on node pages and nowhere else.'),
+        '#collapsible' => TRUE,
+        '#collapsed' => $collapsed,
+      );
+      $form['cck']['cck_field'] = array(
+        '#type' => 'select',
+        '#title' => t('CCK Date field'),
+        '#default_value' => variable_get('countdown_date_field', ''),
+        '#options' => $options,
+      );
+      $form['cck']['use_node_title'] = array(
+        '#type' => 'checkbox',
+        '#title' => t('Use node title for Event Name'),
+        '#default_value' => variable_get('countdown_use_node_title', FALSE),
+      );
+      
+    }
 
     return $form;
     break;
@@ -122,12 +159,22 @@
     variable_set('countdown_event_name', $edit['countdown_event_name']);
     variable_set('countdown_accuracy', $edit['countdown_accuracy']);
     variable_set('countdown_timestamp', mktime((int)$edit['hour'], (int)$edit['min'], (int)$edit['sec'], (int)$edit['month'], (int)$edit['day'], (int)$edit['year']));
+    variable_set('countdown_date_field', $edit['cck_field']);
+    variable_set('countdown_use_node_title', $edit['use_node_title']);
 
   case 'view':
     if (user_access('access content')) {
-      $block['subject'] = variable_get('countdown_block_title', t('Countdown'));
-      $block['content'] = theme('countdown');
-      return $block;
+      if (variable_get('countdown_date_field', '') && arg(0) == 'node' && is_numeric(arg(1))) {
+        $block['subject'] = variable_get('countdown_block_title', t('Countdown'));
+        $block['content'] = theme('countdown');
+        return $block;
+      }
+      elseif (!variable_get('countdown_date_field', '')) {
+        $block['subject'] = variable_get('countdown_block_title', t('Countdown'));
+        $block['content'] = theme('countdown');
+        return $block;
+      }
+      
     }
     break;
   }
@@ -145,3 +192,46 @@
     )
   );
 }
+
+/**
+ * Preprocess function for moving most of the logic out of
+ * the TPL file so themers don't need to worry about it.
+ */
+function template_preprocess_countdown(&$vars) {
+  $time = time();
+
+  if (variable_get('countdown_date_field', '') && arg(0) == 'node' && is_numeric(arg(1))) {
+    $node = node_load(arg(1));
+    $field_name = variable_get('countdown_date_field', '');
+    $field = $node->$field_name;
+    $vars['event_date'] = strtotime($field[0]['value']);
+    if ($field[0]['value']) {
+      $vars['difference'] = $vars['event_date'] - $time;
+    }
+    if (variable_get('countdown_use_node_title', FALSE)) {
+      $vars['event_name'] = $node->title;
+    }
+    else {
+      $vars['event_name'] = variable_get('countdown_event_name', '');
+    }
+  }
+  else {
+    $vars['difference'] = variable_get('countdown_timestamp', $time) - $time;
+    $vars['event_name'] = variable_get('countdown_event_name', '');
+  }
+  
+  if ($vars['difference'] < 0) {
+    $vars['passed'] = 1;
+    $vars['difference'] = abs($vars['difference']);
+  }
+  else {
+    $vars['passed'] = 0;
+  }
+
+  $vars['accuracy']  = variable_get('countdown_accuracy', 'd');
+  $vars['days_left'] = floor($vars['difference']/60/60/24);
+  $vars['hrs_left']  = floor(($vars['difference'] - $vars['days_left']*60*60*24)/60/60);
+  $vars['min_left']  = floor(($vars['difference'] - $vars['days_left']*60*60*24 - $vars['hrs_left']*60*60)/60);
+  $vars['secs_left'] = floor(($vars['difference'] - $vars['days_left']*60*60*24 - $vars['hrs_left']*60*60 - $vars['min_left']*60));
+  
+}
Index: countdown.install
===================================================================
--- countdown.install
+++ countdown.install
@@ -0,0 +1,21 @@
+<?php
+// $Id$
+
+/*
+ * Created by Greg Harvey on 15 Oct 2009
+ *
+ * http://www.drupaler.co.uk
+ */
+
+/**
+ * Implementation of hook_uninstall().
+ * 
+ * Deletes variables left behind by this module.
+ */
+function countdown_uninstall() {
+  variable_del('countdown_event_name');
+  variable_del('countdown_accuracy');
+  variable_del('countdown_timestamp');
+  variable_del('countdown_date_field');
+  variable_del('countdown_use_node_title');
+}
\ No newline at end of file
