diff --git a/date_picker_formatter.css b/date_picker_formatter.css
index 1f4e62e..cb7c969 100644
--- a/date_picker_formatter.css
+++ b/date_picker_formatter.css
@@ -1,9 +1,5 @@
-/* .date-picker-formatter-table-wrapper{
-  overflow:auto;
-} */
 .date-picker-formatter-table thead th.date-header {
   text-align:center;
-  vertical-align:middle;
   border-left: solid 1px #000;
   border-bottom: none;
 }
@@ -13,21 +9,22 @@
 .date-picker-formatter-table td.answer-stats,
 .date-picker-formatter-table td.time{
   text-align:center;
-  vertical-align:middle;
   border-left: 1px solid;
 }
 
-/*
+.date-picker-formatter-table td.answer-stats div.item-list ul {
+  padding:0;
+}
+
 .date-picker-formatter-table td.vote-100{
-   background: #A8FFA6;
+  background: #A8FFA6;
 }
 .date-picker-formatter-table td.vote-0{
-   background: #FFA6A8;
+  background: #FFA6A8;
 }
 .date-picker-formatter-table td.vote-none{
-   background: #A6A8FF;
+  background: #A6A8FF;
 }
-*/
 
 .date-picker-formatter-table tr.stats {
   border-top: 1px solid #000;
@@ -41,48 +38,29 @@
   padding: 0; margin: 0;
 }
 
-.date-picker-formatter-table tr.time{
+.date-picker-formatter-table tr.time {
   border-bottom: 1px solid;
 }
 
-/**
- * Styling the current-user row
- */
 .date-picker-formatter-table tr.current-user {
   background: #ffe9ae;
   border: 1px;
 }
 
-/**
- * Stats cell styling
- */
-.date-picker-formatter-table td.winning-100 {
-  background: #A8FFA6;
-}
-.date-picker-formatter-table td.winning-tied {
-  background: #FFFF99;
-}
-
-/**
- * Cell votes content styling (using icons)
- */
-.date-picker-formatter-table span.vote-none {
-  background : url("./images/unreadable.png") no-repeat center;
+.date-picker-formatter-table span.vote {
   display: block;
   height: 16px;
   text-indent: -9999px;
 }
 
+.date-picker-formatter-table span.vote-none {
+  background : url("../../../../misc/message-16-warning.png") no-repeat center;
+}
+
 .date-picker-formatter-table span.vote-0 {
-  background : url("./images/no.png") no-repeat center;
-  display: block;
-  height: 16px;
-  text-indent: -9999px;
+  background : url("../../../../misc/message-16-error.png") no-repeat center;
 }
 
 .date-picker-formatter-table span.vote-100 {
-  background : url("./images/yes.png") no-repeat center;
-  display: block;
-  height: 16px;
-  text-indent: -9999px;
+  background : url("../../../../misc/message-16-ok.png") no-repeat center;
 }
diff --git a/date_picker_formatter.info b/date_picker_formatter.info
index bccc5ec..c845adf 100644
--- a/date_picker_formatter.info
+++ b/date_picker_formatter.info
@@ -1,5 +1,5 @@
 name = Date Picker Formatter
-description = Doodle like date choice feature.
-core = 6.x
-dependencies[] = date
-dependencies[] = votingapi
\ No newline at end of file
+description = Schedule meetings and other appointments like Doodle.
+core = 7.x
+dependencies[] = date_api
+dependencies[] = votingapi
diff --git a/date_picker_formatter.module b/date_picker_formatter.module
index 634c464..c65af93 100644
--- a/date_picker_formatter.module
+++ b/date_picker_formatter.module
@@ -1,218 +1,179 @@
-<?php // $Id$;
+<?php
 
 /**
- * @file The date_picker_formatter module allows registered users to pick dates to determine the
- * best moment for a meeting (like doodle does)
+ * @file
+ * The Date Picker Form module helps scheduling meetings and other appointments like Doodle.
  */
 
 /**
- * Implements hook_perm()
- * @return permissions array
+ * Implements hook_permission().
  */
-function date_picker_formatter_perm() {
-  return array('pick dates');
-}
-
-/**
- * Implements hook_menu()
- * @return menu array
- */
-function date_picker_formatter_menu() {
+function date_picker_formatter_permission() {
   return array(
-    'admin/content/date-picker-formatter' => array(
-      'title' => 'Date picker formatter',
-      'description' => 'Display settings for the Date Picker Formatter',
-      'page callback' => 'drupal_get_form',
-      'page arguments' => array('date_picker_formatter_admin_settings_form'),
-      'access arguments' => array('administer site configuration'),
-      'file' => 'date_picker_formatter.admin.inc',
-    )
+    'pick dates' => array(
+      'title' => t('Pick dates'),
+      'description' => t('Pick dates'),
+    ),
   );
 }
 
 /**
- * Build a hash tag to represent the given date
+ * Implements hook_theme().
  */
-function _date_picker_formatter_vote_tag($item) {
-  $tag = date_format_date(date_make_date($item['value'], $item['timezone_db'], $item['date_type']), 'custom', 'U');
-  if (isset($item['value2']) && !empty($item['value2'])) {
-    $tag .= '_'. date_format_date(date_make_date($item['value2'], $item['timezone_db'], $item['date_type']), 'custom', 'U');
-  }
-  return $tag;
+function date_picker_formatter_theme() {
+  module_load_include('inc', 'date_picker_formatter', 'date_picker_formatter.theme');
+  return date_picker_formatter_theme_theme();
 }
 
 /**
- * Retrieve the stored votes for the given element
- * @param content element
- * @return an associative array of $array[date_key][user_id] = vote
- * and $array[#uids][user_id] = votes-count
+ * Implements hook_field_formatter_info().
  */
-function date_picker_formatter_get_votes(&$element) {
-  $node_votes = array('#uids' => array());
-  
-  // Building the VotingAPI criteria for filtering
-  $criteria = array(
-    'content_type'  => 'date_picker_formatter_' . $element['#field_name'],
-    'content_id'    => $element['#node']->nid,
+function date_picker_formatter_field_formatter_info() {
+  return array(
+    'date_picker' => array(
+      'label' => t('Date picker formatter'),
+      'field types' => array('date', 'datestamp', 'datetime'),
+      'description' => t('Allow users to vote for each date/time set (using VotingAPI)'),
+      'settings' => array(
+        'date_format' => 'd/m/Y',
+        'time_format' => 'H:i',
+        'display_user_picture' => TRUE,
+        'control' => 'checkbox',
+        'options' => "0|No\n100|Yes",
+      ),
+    ),
   );
-  
-  foreach (element_children($element) as $key) {
-    $criteria['tag'] = _date_picker_formatter_vote_tag($element[$key]['#item']);
-    $votes = votingapi_select_votes($criteria);
-    foreach ($votes as $vote) {
-      // $node_votes[$vote['uid']][$vote['tag']] = $vote;
-      $node_votes[$vote['tag']][$vote['uid']] = $vote;
-      $node_votes['#uids'][$vote['uid']] += 1;
-    }
-  }
-  return $node_votes;
+}
+/*
+ * Implements hook_field_formatter_settings_form().
+ */
+function date_picker_formatter_field_formatter_settings_form($field, $instance, $view_mode, $form, &$form_state) {
+  $display = $instance['display'][$view_mode];
+  $settings = $display['settings'];
+
+  $element = array();
+
+  $element['date_format'] = array(
+    '#title' => t('Date format'),
+    '#type' => 'textfield',
+    '#default_value' => $settings['date_format'],
+    '#required' => TRUE,
+    '#description' => t('A user-defined date format. See the <a href="@url">PHP manual</a> for available options.', array('@url' => 'http://php.net/manual/function.date.php')),
+  );
+  $element['time_format'] = array(
+    '#title' => t('Time format'),
+    '#type' => 'textfield',
+    '#default_value' => $settings['time_format'],
+    '#required' => TRUE,
+    '#description' => t('A user-defined time format. See the <a href="@url">PHP manual</a> for available options.', array('@url' => 'http://php.net/manual/function.date.php')),
+  );
+  $element['display_user_picture'] = array(
+    '#title' => t('Display user picture'),
+    '#type' => 'checkbox',
+    '#default_value' => $settings['display_user_picture'],
+    '#description' => t('Display the user picture in the voting form.'),
+  );
+  $element['control'] = array(
+    '#type' => 'radios',
+    '#title' => t('Form control'),
+    '#options' => array(
+      'checkbox' => t('Checkbox'),
+      'select' => t('Select'),
+      'radios' => t('Radios'),
+    ),
+    '#default_value' => $settings['control'],
+    '#description' => t('The form control to use to build the voting form.'),
+  );
+  $element['options'] = array(
+    '#type' => 'textarea',
+    '#title' => t('Options'),
+    '#default_value' => $settings['options'],
+    '#description' => t('Use a value|Label formatting (one per line) where value is a numerical value between 0 and 100 and the Label a human readable string (translation will be done using i18n module).') . '<br/>' . t('This setting does not apply to the checkbox control.'),
+  );
+
+  return $element;
 }
 
 /**
- * Helper function for getting votes stats: for each date/time sums each vote counts
- * @param the voting_api object
+ * Implements hook_field_formatter_settings_summary().
  */
-function date_picker_formatter_get_stats($node_votes, $dates = array()) {
-  // dpm($dates);
-  
-  $options = _date_picker_formatter_options();
-  $yesonly = variable_get('date_picker_formatter_vote_method', 'checkbox') == 'checkbox';  
-  
-  if ($yesonly) {
-    // Keep only the "Yes" votes
-    $options = array_intersect_key($options, array('100' => ''));
-  }
-  
-  // Init the default counts
-  $options = array_combine(array_keys($options), array_fill(0, count($options), 0));
-  
-  krsort($options);
-  
-  // dpm($options);
-  
-  $stats = array(
-    'voting_users' => count($node_votes['#uids']),
-    'votes' => array(),
-  );
-  
-  // Init the stats for each timestamp (dates without votes get stats too!)
-  foreach ($dates as $timestamp) {    
-    $stats['votes'][$timestamp] = $options;
-  }
-  
-  foreach ($node_votes as $timestamp => $votes) {
-    foreach ($votes as $user => $vote) {
-      if ($yesonly && $vote['value'] != 100) {
-        continue;
-      }
-        
-      // Add the vote to the stats
-      if (array_key_exists($vote['value'], $options)) {
-        // Add only active votes: maybe some values are left after "values" changes in date_picher_formatter options
-        $stats['votes'][$timestamp][$vote['value']]++;
-      }
-    }
+function date_picker_formatter_field_formatter_settings_summary($field, $instance, $view_mode) {
+  $display = $instance['display'][$view_mode];
+  $settings = $display['settings'];
+  $summary = array();
+
+  $date_format = date_format_date(date_now(), 'custom', $settings['date_format']);
+  $time_format = date_format_date(date_now(), 'custom', $settings['time_format']);
+
+  $summary[] = t('Use the @date_format format type for date and @time_format for time.', array('@date_format' => $date_format, '@time_format' => $time_format));
+
+  if ($settings['display_user_picture']) {
+    $summary[] = t('Display user picture.');
   }
-  
-  return $stats; 
+
+  $summary[] = t('Use @control form control.', array('@control' => $settings['control']));
+
+  return implode('<br />', $summary);
 }
 
 /**
- * Add date votes using VotingAPI
+ * Implements hook_field_formatter_view().
  */
-function date_picker_formatter_set_votes(&$values, &$node_id, &$field_name, $account) {
-  if (!user_access('pick dates', $account)) {
-    drupal_set_message(t('You do not have enough permissions to save your picks.'), 'error');
-    return;
-  }
-  // Building the VotingAPI criteria for filtering
-  $criteria = array(
-    'content_type'  => 'date_picker_formatter_' . $field_name,
-    'content_id'    => $node_id,
-  );
-  $votes = array();
-  
-  foreach ($values as $key => $value) {
-    $vote = array_merge($criteria, array(
-      'tag'   => $key,
-      'value' => $value,
-      'uid'   => $account->uid,
-    ));
-    $votes[] = $vote;
-  }
-  votingapi_set_votes($votes);
-  return $votes;
+function date_picker_formatter_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
+  $element[0]['#markup'] = theme('date_picker_formatter', array('entity' => $entity, 'field' => $field, 'items' => $items, 'display' => $display));
+  return $element;
 }
 
-function date_picker_formatter_format_label($rendered = array()) {
-  $output = '';
-  $output .= $rendered['date'];
-  if ($rendered['date'] != $rendered['date2']) {
-    $output .= ($rendered['time'] ? ' '. $rendered['time'] : '');
-    if ($rendered['date2']) {
-      $output .=  ' - '. $rendered['date2'];
-      if ($rendered['time2']) {
-        $output .= ' '. $rendered['time2'];
-      }
-    }
-  }
-  else {
-    $output .= ($rendered['time'] ? ' '. $rendered['time'] : '');
-    $output .= ($rendered['time2'] ? ' - '. $rendered['time2'] : '');
+/**
+ * Implements hook_field_delete().
+ */
+function date_picker_formatter_field_delete($entity_type, $entity, $field, $instance, $langcode, &$items) {
+  // When deleting a "date" field remove (if any) the associated votes.
+  if (in_array($field['type'], array('date', 'datestamp', 'datetime'))) {
+    date_picker_formatter_delete_votes($entity);
   }
-  return $output;
 }
 
 /**
- * Get the date_picker_formatter options and labels (translated)
+ * Implements hook_node_delete().
  */
-function _date_picker_formatter_options() {
-  static $options;
-  if (empty($options)) {
-    $labels = variable_get('date_picker_formatter_vote_label', "0|No\n100|Yes");
-    foreach (explode("\n", $labels) as $line) {
-      $parts = explode('|', $line);
-      $key = check_plain(trim($parts[0]));
-      $label = trim($parts[1]);
-      
-      // Enable Votes-label translations
-      if (module_exists('i18nstrings')) {
-        $label = i18nstrings('date_picker_formatter', $label);
-      }
-      
-      $label = check_plain($label);
-
-      $options[intval($key)] = $label;
-    }
-  }
-  return $options;
+function date_picker_formatter_node_delete($node) {
+  date_picker_formatter_delete_votes($node);
 }
 
 /**
  * Function that generates the date_picker_formatter form displayed in the node view
  */
-function date_picker_formatter_element_form(&$form_state, $element) {
+function date_picker_formatter_element_form($form, &$form_state, $variables) {
   global $user;
 
-  $node_votes = date_picker_formatter_get_votes($element);
+  $entity = $variables['entity'];
+  $field = $variables['field'];
+  $items = $variables['items'];
+  $display = $variables['display'];
+
+  $date_format = $display['settings']['date_format'];
+  $time_format = $display['settings']['time_format'];
+  $control = $display['settings']['control'];
+  $options = _date_picker_formatter_get_options($display['settings']['options']);
+
+  $votes = date_picker_formatter_get_votes($entity, $items);
 
   $form = array(
-    '#node_id' => $element['#node']->nid,
-    '#field_name' => $element['#field_name'],
-    '#date_picker_formatter_votes' => $node_votes,
-    'dates' => array(
-      '#tree' => TRUE,
-    ),
+    '#entity_type' => $entity->type,
+    '#entity_id' => $entity->nid,
+    '#field_name' => $field['field_name'],
+    '#control' => $display['settings']['control'],
+    '#options' => $options,
+    '#votes' => $votes,
+    'dates' => array('#tree' => TRUE),
   );
-  
-  // Anonym user can't vote (not implemented yet)
-  // @todo: allow Anonym users to place votes?
+
+  // Only registered users can vote.
   if ($user->uid == 0) {
-    $can_register = variable_get('user_register', 1) != 0;
-    if ($can_register) {
+    if (variable_get('user_register', 1)) {
       $message = t('You have to <a href="!loginurl">login</a> or <a href="!registerurl">register</a> to choose convenient dates.',
-        array('!loginurl' => url('user'), '!registerurl' => url('user/register'))
-      );
+        array('!loginurl' => url('user'), '!registerurl' => url('user/register')));
     }
     else {
       $message = t('You have to <a href="!loginurl">login</a> to choose convenient dates.',
@@ -220,301 +181,303 @@ function date_picker_formatter_element_form(&$form_state, $element) {
       );
     }
 
-    $form['date_picker_formatter_message'] = array('#value' => $message);
+    $form['message'] = array('#markup' => $message);
   }
 
-  // dpm($element);
-  // Retrieving the field element
-  $field = content_fields($element['#field_name']);
-  // dpm($field);
-
-  // For each date, print the votes related to them
-  foreach (element_children($element) as $key) {
-    $item = $element[$key]['#item'];    
-    if (!date_content_is_empty($item, $field)) {
-      // dpm($item);
-      
-      $date_key = _date_picker_formatter_vote_tag($item);      
-
-      // Store the date-representation for header rows if not present
-      if (empty($form['dates']['#infos'][$date_key]['label'])) {
-        
-        $rendered = date_picker_formatter_get_rendered($item);
-        $label = date_picker_formatter_format_label($rendered);
-        $form['dates']['#infos'][$date_key] = $rendered;
-        $form['dates']['#infos'][$date_key]['label'] = $label;
+  // Print the related votes for each date.
+  foreach ($items as $item) {
+    if (!empty($item['value'])) {
+      $tag = _date_picker_formatter_create_tag($item);
+      // Store the date-representation for header rows if not present.
+      if (empty($form['dates']['#infos'][$tag]['label'])) {
+        $date = _date_picker_formatter_format_date($item, $date_format, $time_format);
+        $label = _date_picker_formatter_format_label($date);
+        $form['dates']['#infos'][$tag] = $date;
+        $form['dates']['#infos'][$tag]['label'] = $label;
       }
-      
-      // If there is any vote
-      if (!empty($node_votes['#uids'])) {
-        // Add each user vote
-        foreach ($node_votes[$date_key] as $uid => $user_vote) {
+
+      // Add each user vote, if there is any vote.
+      if (!empty($votes['#uids'])) {
+        foreach ($votes[$tag] as $uid => $user_vote) {
+          // Skip the current user, he/she will get a form item.
           if ($user->uid != $uid) {
-            $vote_value = @$node_votes[$date_key][$uid];
-            
-            $vote = date_picker_formatter_get_display_vote($vote_value);
-            $vote_class = 'vote-' . $vote['value'];
-            // Skip the current user, he/she will get a form item
-            
-            $form['dates'][$uid][$date_key] = array(
-              '#value' =>  theme('date_picker_formatter_vote_cell', $vote),
-              '#attributes' => array('class' => $vote_class),
+            if (is_null($user_vote['value'])) {
+              $vote = array(
+                'value' => 'none',
+                'label' => t('No record'),
+              );
+            }
+            else {
+              $vote = array(
+                'value' => $user_vote['value'],
+                'label' => $options[$user_vote['value']],
+              );
+            }
+            $form['dates'][$uid][$tag] = array(
+              '#markup' => theme('date_picker_formatter_vote_cell', array('vote' => $vote)),
+              '#attributes' => array('class' => 'vote-' . $vote['value']),
             );
           }
         }
       }
 
       if (user_access('pick dates', $user)) {
-        // Add the current user voting form (even if no votes are present)
-        $form['dates'][$user->uid][$date_key] = date_picker_formatter_get_user_voting_item(
-          @$node_votes[$date_key][$user->uid]['value'],
-          $form['dates']['#infos'][$date_key]['label']
+        // Add the current user voting form (even if no votes are present).
+        $element = array(
+          '#title' => check_plain($form['dates']['#infos'][$tag]['label']),
+          '#default_value' => isset($votes[$tag][$user->uid]['value']) ? $votes[$tag][$user->uid]['value'] : NULL,
         );
+        if ($control == 'checkbox') {
+          $element += array(
+            '#type' => 'checkbox',
+            '#return_value' => 100,
+          );
+        }
+        else {
+          $element += array(
+            '#type' => $control,
+            '#options' => $options,
+          );
+        }
+        $form['dates'][$user->uid][$tag] = $element;
       }
     }
   }
 
-  // Allow user to submit votes only if he/she have the 'pick dates' permission
-  if (user_access('pick dates', $user)) {
-    $form['submit'] = array(
-      '#type' => 'submit',
-      '#value' => isset($node_votes['#uids'][$user->uid])? t('Update') : t('Save'),
-    );
-  }
-  // dpm($form);
+  $form['submit'] = array(
+    '#type' => 'submit',
+    '#value' => isset($node_votes['#uids'][$user->uid]) ? t('Update') : t('Save'),
+    '#access' => user_access('pick dates', $user),
+  );
+
   return $form;
 }
 
 /**
- * For the given vote, returns the display form of it (handling null votes)
+ * Submit function for date_picker_formatter_form()
+ *
+ * @param array $form
+ * @param array $form_state
  */
-function date_picker_formatter_get_display_vote(&$vote) {
-  if (is_null($vote['value'])) {
-    $value = 'none';
-    $text = t('No Record');
-  }
-  else {
-    $value = $vote['value'];
-    $vote_options = _date_picker_formatter_options();
-    $text = $vote_options[$vote['value']];
+function date_picker_formatter_element_form_submit($form, &$form_state) {
+  foreach ($form_state['values']['dates'] as $uid => $votes) {
+    date_picker_formatter_set_votes($votes, $form['#entity_type'], $form['#entity_id'], $form['#field_name'], (object) array('uid' => $uid));
   }
-  
-  return array(
-    'value' => $value,
-    'label' => $text,
-  );
 }
 
 /**
- * Get the form-item for the current user
+ * Retrieve the stored votes for the given entity.
  */
-function date_picker_formatter_get_user_voting_item($vote_value, $vote_date_label) {
-  $vote_method = variable_get('date_picker_formatter_vote_method', 'checkbox');
-  
-  if ($vote_method == 'checkbox') {
-    return array(
-      '#title' => $vote_date_label,
-      '#type' => 'checkbox',
-      '#return_value' => 100,
-      '#default_value' => $vote_value,
-    );
-  }
-  else {
-    $vote_options = _date_picker_formatter_options();
-    return array(
-      '#title' => $vote_date_label,
-      '#type' => $vote_method,
-      '#options' => $vote_options,
-      '#default_value' => $vote_value,
-    );
+function date_picker_formatter_get_votes($entity, $items) {
+  $node_votes = array('#uids' => array());
+
+  $criteria = array(
+    'entity_type' => $entity->type,
+    'entity_id' => $entity->nid,
+  );
+
+  foreach ($items as $item) {
+    $criteria['tag'] = _date_picker_formatter_create_tag($item);
+    $votes = votingapi_select_votes($criteria);
+    foreach ($votes as $vote) {
+      $node_votes[$vote['tag']][$vote['uid']] = $vote;
+      $node_votes['#uids'][$vote['uid']] =+ 1;
+    }
   }
+
+  return $node_votes;
 }
 
 /**
- *
+ * Save the given user votes for the given entity.
  */
-function date_picker_formatter_get_rendered(&$item) {
-  $date_format = variable_get('date_picker_formatter_date_format', 'd/m/Y');
-  $time_format = variable_get('date_picker_formatter_time_format', 'H:i');
-  $date_obj = date_make_date($item['value'], $item['timezone_db'], $item['date_type']);
-  date_timezone_set($date_obj, timezone_open($item['timezone']));
-  $date = date_format_date($date_obj, 'custom', $date_format);
-  $time = date_format_date($date_obj, 'custom', $time_format);
-  
-  if (isset($item['value2']) && !empty($item['value2'])) {
-    $date_obj2 = date_make_date($item['value2'], $item['timezone_db'], $item['date_type']);
-    date_timezone_set($date_obj2, timezone_open($item['timezone']));
-    $date2 = date_format_date($date_obj2, 'custom', $date_format);
-    $time2 = date_format_date($date_obj2, 'custom', $time_format);
-  }
-  else {
-    // $date2 = NULL;
-    // $time2 = NULL;
-    $date2 = $date;
-    $time2 = $time;
+function date_picker_formatter_set_votes($values, $entity_type, $entity_id, $field_name, $account) {
+  if (!user_access('pick dates', $account)) {
+    drupal_set_message(t('You do not have permission to save your picks.'), 'error');
+    return;
   }
-  
-  $rendered = array(
-    'date' => $date,
-    'time' => $time == '00:00' ? theme('date_all_day_label') : $time,
-    'date2' => $date2,
-    'time2' => $time2 == '00:00' ? theme('date_all_day_label') : $time2,
+
+  $criteria = array(
+    'entity_type' => $entity_type,
+    'entity_id' => $entity_id,
   );
-  return $rendered;
+
+  $votes = array();
+  foreach ($values as $key => $value) {
+    $vote = array_merge($criteria, array(
+      'tag' => $key,
+      'value' => $value,
+      'uid' => $account->uid,
+    ));
+    $votes[] = $vote;
+  }
+
+  return votingapi_set_votes($votes);
 }
 
 /**
- * Submit function for date_picker_formatter_form()
- *
- * @param array $form
- * @param array $form_state
+ * Clear votes for the given entity.
  */
-function date_picker_formatter_element_form_submit($form, &$form_state) {
-  global $user;
-  $values = $form_state['values'];
-  foreach ($values['dates'] as $uid => $votes) {
-    date_picker_formatter_set_votes($votes, $form['#node_id'], $form['#field_name'], (object)array('uid' => $uid));
-  }
+function date_picker_formatter_delete_votes($entity) {
+  $criteria = array(
+    'entity_type' => $entity->type,
+    'entity_id' => $entity->nid,
+  );
+  $votes = votingapi_select_votes($criteria);
+  votingapi_delete_votes($votes);
 }
 
 /**
- * Implementation of hook_field_formatter_info().
+ * Helper function for getting votes stats.
  */
-function date_picker_formatter_field_formatter_info() {
-  return array(
-    'default' => array(
-      'label' => t('Date picker formatter'),
-      'field types' => array('date', 'datestamp', 'datetime'),
-      'multiple values' => CONTENT_HANDLE_MODULE,
-      'description' => t('Allow users to vote for each date/time set (using VotingAPI)'),  
-    ),
+function date_picker_formatter_get_stats($node_votes, $dates = array(), $control, $options) {
+  $yesonly = ($control == 'checkbox') ? TRUE : FALSE;
+
+  if ($yesonly) {
+    // Keep only the "Yes" votes
+    $options = array_intersect_key($options, array('100' => ''));
+  }
+
+  // Init the default counts.
+  $options = array_combine(array_keys($options), array_fill(0, count($options), 0));
+
+  krsort($options);
+
+  $stats = array(
+    'voting_users' => count($node_votes['#uids']),
+    'votes' => array(),
   );
+
+  // Init the stats for each timestamp (dates without votes get stats too!)
+  foreach ($dates as $timestamp) {
+    $stats['votes'][$timestamp] = $options;
+  }
+
+  foreach ($node_votes as $timestamp => $votes) {
+    foreach ($votes as $user => $vote) {
+      if ($yesonly && $vote['value'] != 100) {
+        continue;
+      }
+
+      // Add the vote to the stats.
+      if (array_key_exists($vote['value'], $options)) {
+        // Add only active votes.
+        $stats['votes'][$timestamp][$vote['value']]++;
+      }
+    }
+  }
+
+  return $stats;
 }
 
 /**
- * Implementation of hook_content_fieldapi()
+ * Get the date_picker_formatter options and labels (translated)
  */
-function date_picker_formatter_content_fieldapi($op, $field) {
-  switch ($op) {
-    case 'delete instance':
-      // When deleting a "date" field remove (if any) the associated votes
-      if (in_array($field['type'], array('date', 'datestamp', 'datetime'))) {
-        _date_picker_formatter_clear_votes($field['field_name']);
+function _date_picker_formatter_get_options($option_lines) {
+  static $options;
+
+  if (empty($options)) {
+    foreach (explode("\n", $option_lines) as $line) {
+      $parts = explode('|', $line);
+      $key = check_plain(trim($parts[0]));
+      $label = trim($parts[1]);
+
+      // Enable Votes-label translations.
+      if (module_exists('i18nstrings')) {
+        $label = i18nstrings('date_picker_formatter', $label);
       }
-      break;
+
+      $label = check_plain($label);
+
+      $options[intval($key)] = $label;
+    }
   }
+
+  return $options;
 }
+
 /**
- * Implementation of hook_nodeapi()
+ * Helper function to build a hash tag to represent the given date.
  */
-function date_picker_formatter_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
-  switch ($op) {
-    case 'delete' :
-      // The node is being deleted: clear the related field-votes (if any)
-      $fields = content_types($node->type);
-      foreach ($fields['fields'] as $field) {
-        _date_picker_formatter_clear_votes($field, $node->nid);
-      }
-    break;
+function _date_picker_formatter_create_tag($item) {
+  $date = new DateObject($item['value'], $item['timezone_db']);
+  $tag = date_format_date($date, 'custom', 'U');
+
+  if (isset($item['value2']) && !empty($item['value2'])) {
+    $date2 = new DateObject($item['value2'], $item['timezone_db']);
+    $tag .= '_' . date_format_date($date2, 'custom', 'U');
   }
+
+  return $tag;
 }
 
 /**
- * Clear the picked votes for the given field, in the given node-id
+ * Helper function to get the proper class for the given votes.
  */
-function _date_picker_formatter_clear_votes($field, $node_id = NULL) {
-  // We deal only with "date" fields
-  if (in_array($field['type'], array('date', 'datestamp', 'datetime'))) {
-    $criteria = array();
-    $criteria['content_type'] = 'date_picker_formatter_' . $field['field_name'];
-    if (isset($node_id)) {
-      $criteria['content_id'] = $node_id;
-    }
-    // dpm($criteria);
-    $votes_to_delete = votingapi_select_votes($criteria);
-    // dpm($votes_to_delete);
-    votingapi_delete_votes($votes_to_delete);
+function _date_picker_formatter_get_class($votes) {
+  arsort($votes);
+  $first = current($votes);
+  $second = next($votes);
+  reset($votes);
+
+  if ($first > $second) {
+    return 'vote-' . (int) key($votes);
+  }
+  elseif ($first != 0 && $first == $second) {
+    return 'vote-tied';
+  }
+  else {
+    return 'vote-none';
   }
 }
 
 /**
- * Implements hook_theme()
- *
- * @param unknown_type $existing
- * @param unknown_type $type
- * @param unknown_type $theme
- * @param unknown_type $path
- * @return array
+ * Helper function to format the date values.
  */
-function date_picker_formatter_theme($existing, $type, $theme, $path) {
-  return array(
-    'date_picker_formatter_element_form' => array(
-      'file' => 'date_picker_formatter.theme.inc',
-      'arguments' => array(
-        'form' => NULL
-      ),
-    ),
-    'date_picker_formatter_formatter_default' => array(
-      'file' => 'date_picker_formatter.theme.inc',
-      'arguments' => array(
-        'element' => NULL
-      ),
-    ),
-    'date_picker_formatter_user_cell' => array(
-      'file' => 'date_picker_formatter.theme.inc',
-      'arguments' => array(
-        'uid' => NULL
-      ),
-    ),
-    'date_picker_formatter_vote_cell' => array(
-      'file' => 'date_picker_formatter.theme.inc',
-      'arguments' => array(
-        'vote' => NULL
-      ),
-    ),
-    'date_picker_formatter_date_cell' => array(
-      'file' => 'date_picker_formatter.theme.inc',
-      'arguments' => array(
-        'info' => NULL
-      ),
-    ),
-    'date_picker_formatter_time_cell' => array(
-      'file' => 'date_picker_formatter.theme.inc',
-      'arguments' => array(
-        'info' => NULL
-      ),
-    ),
-    'date_picker_formatter_stats_count' => array(
-      'file' => 'date_picker_formatter.theme.inc',
-      'arguments' => array(
-        'info' => NULL
-      ),
-    ),
-    'date_picker_formatter_stats_cell' => array(
-      'file' => 'date_picker_formatter.theme.inc',
-      'arguments' => array(
-          'info' => NULL
-        ),
-      ),
+function _date_picker_formatter_format_date($item, $date_format, $time_format) {
+  $date1_obj = new DateObject($item['value'], $item['timezone_db']);
+  date_timezone_set($date1_obj, timezone_open($item['timezone']));
+  $date = date_format_date($date1_obj, 'custom', $date_format);
+  $time = date_format_date($date1_obj, 'custom', $time_format);
+
+  $dates = array(
+    'date' => $date,
+    'time' => $time == '00:00' ? theme('date_all_day_label') : $time,
   );
+
+  if (isset($item['value2']) && !empty($item['value2'])) {
+    $date2_obj = new DateObject($item['value2'], $item['timezone_db']);
+    date_timezone_set($date2_obj , timezone_open($item['timezone']));
+    $date2 = date_format_date($date2_obj , 'custom', $date_format);
+    $time2 = date_format_date($date2_obj , 'custom', $time_format);
+    $dates = array_merge($dates, array(
+      'date2' => $date2,
+      'time2' => $time2 == '00:00' ? theme('date_all_day_label') : $time2,
+    ));
+  }
+
+  return $dates;
 }
 
 /**
- * For the given date_votes, return the "winning" one class
+ * Helper function to create labels from dates.
  */
-function _date_picker_formatter_get_winner_class($date_votes) {
-  arsort($date_votes);
-  $first = current($date_votes);
-  $second = next($date_votes);
-  reset($date_votes);
-  
-  if ( $first > $second ) {
-    return 'winning-' . (int)key($date_votes);
-  }
-  elseif ($first != 0 && $first == $second) {
-    return 'winning-tied';
+function _date_picker_formatter_format_label($dates = array()) {
+  $output = '';
+  $output .= $dates['date'];
+  if (isset($dates['date2']) && $dates['date'] != $dates['date2']) {
+    $output .= ($dates['time'] ? ' ' . $dates['time'] : '');
+    if ($dates['date2']) {
+      $output .=  ' - ' . $dates['date2'];
+      if ($dates['time2']) {
+        $output .= ' ' . $dates['time2'];
+      }
+    }
   }
   else {
-    return 'winning-none';
+    $output .= ($dates['time'] ? ' ' . $dates['time'] : '');
+    // $output .= ($dates['time2'] ? ' - '. $dates['time2'] : '');
   }
+
+  return $output;
 }
diff --git a/date_picker_formatter.theme.inc b/date_picker_formatter.theme.inc
index 4b02e7b..e775925 100644
--- a/date_picker_formatter.theme.inc
+++ b/date_picker_formatter.theme.inc
@@ -1,90 +1,113 @@
 <?php
 
 /**
- * @file Helper file for Theming date_picker_formatter module output
+ * @file
+ * The theme system, which controls the output of Date Picker Formatter.
  */
 
 /**
- * Theming function for date element formatter
+ * Implements hook_theme().
  */
-function theme_date_picker_formatter_formatter_default($element) {
-  // We're going to build a form to get user votes
-  return drupal_get_form('date_picker_formatter_element_form', $element);
-}
-
-/**
- * Format the voting users count
- */
-function theme_date_picker_formatter_stats_count($count) {
-  return format_plural($count, '1 User votes', '@count Users votes');
+function date_picker_formatter_theme_theme() {
+  return array(
+    'date_picker_formatter' => array(
+      'file' => 'date_picker_formatter.theme.inc',
+      'variables' => array('entity' => NULL, 'field' => NULL, 'items' => NULL, 'display' => NULL),
+    ),
+    'date_picker_formatter_date_cell' => array(
+      'file' => 'date_picker_formatter.theme.inc',
+      'variables' => array('infos' => NULL),
+    ),
+    'date_picker_formatter_time_cell' => array(
+      'file' => 'date_picker_formatter.theme.inc',
+      'variables' => array('infos' => NULL),
+    ),
+    'date_picker_formatter_user_cell' => array(
+      'file' => 'date_picker_formatter.theme.inc',
+      'variables' => array('uid' => NULL),
+    ),
+    'date_picker_formatter_vote_cell' => array(
+      'file' => 'date_picker_formatter.theme.inc',
+      'variables' => array('vote' => NULL),
+    ),
+    'date_picker_formatter_stats_cell' => array(
+      'file' => 'date_picker_formatter.theme.inc',
+      'variables' => array('vote' => NULL, 'options' => NULL),
+    ),
+    'date_picker_formatter_stats_count' => array(
+      'file' => 'date_picker_formatter.theme.inc',
+      'variables' => array('count' => NULL),
+    ),
+    'date_picker_formatter_element_form' => array(
+      'file' => 'date_picker_formatter.theme.inc',
+      'render element' => 'form',
+    ),
+  );
 }
 
 /**
- * Format a voting stats cell 
+ * Theme the date element.
  */
-function theme_date_picker_formatter_stats_cell($info) {
-  // dpm($info);
-  $vote_options = _date_picker_formatter_options();
-  $items = array();
-  foreach ($info as $id => $count) {
-    $items[] =  format_plural($count, "@votelabel : 1 Vote", "@votelabel : @count Votes", array('@votelabel' => $vote_options[$id]));
-  }
-
-  return theme('item_list', $items);
+function theme_date_picker_formatter($variables) {
+  return drupal_render(drupal_get_form('date_picker_formatter_element_form', $variables));
 }
 
-
 /**
- * Output a header cell
+ * Theme a date cell.
  */
-function theme_date_picker_formatter_date_cell($info) {
-  extract($info);
+function theme_date_picker_formatter_date_cell($variables) {
+  extract($variables['info']);
   $output = '';
-  
-  if ($date != $date2) {
+
+  if ($date != @$date2) {
     $output .= '<span class="date first">'. $date . ($time ? ' <span class="time">'. $time .'</span>' : '') .'</span> ';
     $output .= '<span class="separator">-</span> ';
-    $output .= '<span class="date second">'. $date2 . ($time2 ? ' <span class="time">'. $time2 .'</span>' : '') .'</span>';
+    $output .= '<span class="date second">'. $date2 . (@$time2 ? ' <span class="time">'. $time2 .'</span>' : '') .'</span>';
   }
   else {
     $output .= '<span class="date">'. $date .'</span>';
   }
-  
+
   return $output;
 }
 
-function theme_date_picker_formatter_time_cell($info) {
-  extract($info);
+/**
+ * Theme a time cell.
+ */
+function theme_date_picker_formatter_time_cell($variables) {
+  extract($variables['info']);
   $output = '';
-  
-  if ($date == $date2) {
-    if ($time != $time2) {
-      $output .= '<span class="time first">'. $time .'</span> ';
-      $output .= '<span class="separator">-</span> ';
-      $output .= '<span class="time second">'. $time2 .'</span>';
-    }
-    else {
-      $output .= '<span class="time">'. $time .'</span>';
-    }
+
+  if ($time != @$time2) {
+    $output .= '<span class="time first">'. $time .'</span> ';
+    $output .= '<span class="separator">-</span> ';
+    $output .= '<span class="time second">'. $time2 .'</span>';
   }
-  
+  else {
+    $output .= '<span class="time">'. $time .'</span>';
+  }
+
   return $output;
 }
 
 /**
- * Theming function for "User" cell
+ * Theme a user cell.
  */
-function theme_date_picker_formatter_user_cell($uid) {
+function theme_date_picker_formatter_user_cell($variables) {
+  $uid = $variables['uid'];
   global $user;
+  // TODO Convert "user_load" to "user_load_multiple" if "$uid" is other than a uid.
+  // To return a single user object, wrap "user_load_multiple" with "array_shift" or equivalent.
+  // Example: array_shift(user_load_multiple(array(), $uid))
   $account = user_load($uid);
   $output = '';
   if (variable_get('date_picker_formatter_display_user_picture', 1)) {
-    $output .= theme('user_picture', $account);
+    $output .= theme('user_picture', array('account' => $account));
   }
- 
+
   // Use the default theme_username to show voting user
-  $output .= theme('username', $account);
-  
+  $output .= theme('username', array('account' => $account));
+
   if ($account->uid == $user->uid) {
     $output .= ' (' . t('You') . ')';
   }
@@ -92,124 +115,150 @@ function theme_date_picker_formatter_user_cell($uid) {
 }
 
 /**
- * Theming function for the "Vote" table cell ($vote['label'] and $vote['value']
+ * Theme a vote cell.
  */
-function theme_date_picker_formatter_vote_cell($vote) {
-  return '<span class="vote vote-' . $vote['value'] . '">' . $vote['label'] . '</span>';
+function theme_date_picker_formatter_vote_cell($variables) {
+  return '<span class="vote vote-' . $variables['vote']['value'] . '">' . $variables['vote']['label'] . '</span>';
 }
 
 /**
- * Theme function for  the date_picker_formatter form
- * @param $form
- * @return string
+ * Theme a voting stats cell.
  */
-function theme_date_picker_formatter_element_form($form) {
+function theme_date_picker_formatter_stats_cell($variables) {
+  $vote = $variables['vote'];
+  $options = $variables['options'];
+
+  $items = array();
+  foreach ($vote as $id => $count) {
+    $items[] =  format_plural($count, "@label: 1 vote", "@label: @count votes", array('@label' => $options[$id]));
+  }
+
+  return theme('item_list', array('items' => $items));
+}
+
+/**
+ * Theme the voting users count.
+ */
+function theme_date_picker_formatter_stats_count($variables) {
+  return format_plural($variables['count'], '1 votes', '@count votes');
+}
+
+/**
+ * Theme the date picker form.
+ */
+function theme_date_picker_formatter_element_form($variables) {
   global $user;
-  
-  // Don't display form is no #infos provided (something went wrong)
-  if (empty($form['dates']['#infos']))
+  $form = &$variables['form'];
+
+  // Don't display form if no #infos provided.
+  if (empty($form['dates']['#infos'])) {
     return '';
-  
+  }
+
   drupal_add_css(drupal_get_path('module', 'date_picker_formatter') . '/date_picker_formatter.css');
-  
+
   $output = '';
   $rows = array();
-  // $children = element_children($form['dates']);
-  // $first_child = array_shift($children);
-  
+
   $header = array();
-  $header[] = array('data' => t('Users'), 'rowspan' => 2, 'class' => 'user-header');
-  
+  $header[] = array(
+    'data' => t('Users'),
+    'rowspan' => 2,
+    'class' => array('user-header'),
+  );
+
   $second_row = array(
     array(
       'data' => '<!-- top left corner time -->',
-      'class' => 'header'
+      'class' => array('header'),
     ),
   );
 
   $infos = $form['dates']['#infos'];
   $prev_key = array_shift(array_keys($infos));
   $prev_date = NULL;
-  
+
   foreach ($infos as $key => $info) {
-    if ($info['date'] != $info['date2'] || $prev_date != $info['date']) {
+    extract($info);
+    if ((isset($date2) && ($date != $date2 || $prev_date != $date2)) || !isset($date2)) {
       $header[$key] = array(
-        'class' => 'date-header',
-        'data' => theme('date_picker_formatter_date_cell', $info),
+        'class' => array('date-header'),
+        'data' => theme('date_picker_formatter_date_cell', array('info' => $info)),
       );
       $prev_key = $key;
     }
     else {
-      $header[$prev_key]['colspan'] = !$header[$prev_key]['colspan'] ? 1 : $header[$prev_key]['colspan'];
+      $header[$prev_key]['colspan'] = (!isset($header[$prev_key]['colspan'])) ? 1 : $header[$prev_key]['colspan'];
       $header[$prev_key]['colspan']++;
     }
-    $prev_date = $info['date'];
-
+    $prev_date = $date;
     $second_row[$key] = array(
-      'class' => 'time',
-      'data' => theme('date_picker_formatter_time_cell', $info),    
+      'class' => array('time'),
+      'data' => theme('date_picker_formatter_time_cell', array('info' => $info)),
     );
-    
   }
-  
-  $rows['times'] = array('class' => 'time header', 'data' => $second_row);
-  // $header = array($header, $second_row);
-  
+
+  $rows['times'] = array(
+    'class' => array('time', 'header'),
+    'data' => $second_row,
+  );
+
   foreach (element_children($form['dates']) as $uid) {
     $row = array(
       'user' => array(
-        'class' => 'user header',
-        'data' => theme('date_picker_formatter_user_cell', $uid),
-      )
+        'class' => array('user', 'header'),
+        'data' => theme('date_picker_formatter_user_cell', array('uid' => $uid)),
+      ),
     );
     foreach (element_children($form['dates'][$uid]) as $key) {
       unset($form['dates'][$uid][$key]['#title']);
-
       $row[$key] = array(
-        'class' => 'answer ' . @$form['dates'][$uid][$key]['#attributes']['class'],
+        'class' => array('answer', @$form['dates'][$uid][$key]['#attributes']['class']),
         'data' => drupal_render($form['dates'][$uid][$key]),
       );
     }
-    $rows[$uid] = array('class' => 'result', 'data' => $row);
+    $rows[$uid] = array(
+      'class' => array('result'),
+      'data' => $row,
+    );
   }
-  
-  // Add to the current user row the "Submit" button
+
+  // Add the "Submit" button to the current user row.
   if (isset($rows[$user->uid])) {
     $rows['current_user'] = $rows[$user->uid];
     unset($rows[$user->uid]);
-    $rows['current_user']['data']['user']['data'] .= ' '. drupal_render($form['submit']);
-    
-    // Adding CSS for current-user row theming
-    $rows['current_user']['class'] .= ' current-user';
+    $rows['current_user']['data']['user']['data'] .= ' ' . drupal_render($form['submit']);
+
+    // Adding CSS for current-user row theming.
+    $rows['current_user']['class'][] = 'current-user';
   }
-  
-  // Adding stats
-  $stats = date_picker_formatter_get_stats($form['#date_picker_formatter_votes'], array_keys($infos));
-  // dvm($stats);
-  
+
+  // Adding stats.
+  $stats = date_picker_formatter_get_stats($form['#votes'], array_keys($infos), $form['#control'], $form['#options']);
+
   $stats_row = array(
-    'class' => 'stats',
+    'class' => array('stats'),
     'data' => array(
-      'count' => theme('date_picker_formatter_stats_count', $stats['voting_users']),
+      'count' => theme('date_picker_formatter_stats_count', array('count' => $stats['voting_users'])),
     ),
   );
 
-  foreach ($stats['votes'] as $date_votes) {
+  foreach ($stats['votes'] as $vote) {
     $stats_row['data'][] = array(
-      'class' => 'answer-stats ' . _date_picker_formatter_get_winner_class($date_votes) ,
-      'data' => theme('date_picker_formatter_stats_cell', $date_votes)
+      'class' => array('answer-stats', _date_picker_formatter_get_class($vote)),
+      'data' => theme('date_picker_formatter_stats_cell', array('vote' => $vote, 'options' => $form['#options'])),
     );
   }
-  
+
   $rows[] = $stats_row;
-  
-  $output .= '<div class="date-picker-formatter-table-wrapper">';
-  $output .= theme('table', $header, $rows, array(
-    'id' => 'date-picker-formatter-table-' . $form['#node']->nid . '-' . str_replace('_', '-', $form['#field']['field_name']),
-    'class' => 'date-picker-formatter-table'
-  ));
-  
-  $output .= '</div>';
-  
-  return $output . drupal_render($form);
+
+  $attributes = array(
+    'id' => 'date-picker-formatter-table-' . $form['#entity_id'] . '-' . str_replace('_', '-', $form['#field_name']),
+    'class' => array('date-picker-formatter-table'),
+  );
+
+  $output .= theme('table', array('header' => $header, 'rows' => $rows, 'attributes' => $attributes));
+  $output .= drupal_render_children($form);
+
+  return $output;
 }
