d3116e00fef43bc1aa785124d153adea9463f5a7
diff --git a/INSTALL.txt b/INSTALL.txt
index 41c74e8..72400bf 100644
--- a/INSTALL.txt
+++ b/INSTALL.txt
@@ -67,45 +67,23 @@ module:
      ...and/or collaborate with the author of this Drupal module to build a
      snazzy, user-friendly UI for generating exhibit definitions.
      
-EXHIBIT VIEWS
+EXHIBIT AND VIEWS DATASOURCE
 -------------
-This module includes a module called 'Exhibit Views' that allows you to
-add Exhibit-compatible JSON data feeds to views defined using the Views module,
-available from:
 
-  <http://drupal.org/project/views>
+  1. Install views_datasource
 
-  1. Install and enable the two included modules 'Exhibit' and
-    'Exhibit Views'.
-
-  2. For any views you wish to utilize in exhibits, add a Feed display to the 
-    view by browsing to the view editor at:
-
-      admin/build/views/<VIEW NAME>
+  2. Download  and use the patch for its views_json module here:
 
-    Replace <NAME> with the unique view name of the view in question, e.g.
-    'tracker'.  You can also browse for your view at:
+  3. Add a new view and select json as a style plugin
 
-      admin/build/views
+  4. Make sure you select simile exhibit output in the options of the style plugin
 
-  3. In the display list, select "Feed" from the drop down list and then click
-    on the "Add display" button.  Assign the feed an appropriate name (e.g. 
-    "Exhibit Feed"). Set the style to "Exhibit JSON" by click on the link
-    next to the "Style" label under the "Basic Settings" section.  After you
-    select Exhibit JSON, click on the "update" button.  You will be presented
-    with some options for the item type label and item type plural label.
-    These are used in the Exhibit feeds, and Exhibit itself, to describe the
-    types of items in your list.  So, if your displaying a list of Event node
-    types, use event and events for the type label and plural type label.
-    Click on the update button to save your settings.
+  5. To display taxonomy terms make sure, "Display all values in the same row" 
+      in fieldset "Multiple field settings" is unselected. Otherwise terms will not be
+      accesible individually      
 
-    Once you've selected the correct display style, click on the link next to
-    the "Row style" plugin, also found under the "Basic Settings" section
-    right below the Style settings.  Select the "Fields (Exhibit)" option and
-    then click on the update button.
-
-    Finally, assign a path that you would like this feed to be accessible
-    through under the "Feed Settings" and save your view.
+GENERAL NOTES
+-------------
 
     It should be noted, that Exhibit expects dates to be in ISO 8601 format.
     For each date or datetime field in your view that you want accessible
diff --git a/README.txt b/README.txt
index 00199e1..db7a2de 100644
--- a/README.txt
+++ b/README.txt
@@ -2,7 +2,7 @@
 Exhibit for Drupal
 ==================
 This is an-alpha version of the Exhibit module currently being developed
-for Drupal 6.x under the auspices of the project at:
+for Drupal 7.x under the auspices of the project at:
 
   <http://drupal.org/project/exhibit>
 
@@ -50,7 +50,7 @@ Once your Exhibit definitions are complete, save the node, and you should have
 a fully functioning Exhibit rendered on the front end.
 
 
-CREDITS
+CREDITS (for 6.x Version)
 -------
 Developed and maintained by Arto Bendiken <http://bendiken.net/>
 Co-maintained by Josh Huckabee <http://joshhuckabee.com/>
@@ -58,3 +58,5 @@ Co-maintained by Djun Kim <http://www.puregin.org/>
 Sponsored by MakaluMedia Group <http://www.makalumedia.com/>
 Sponsored by M.C. Dean, Inc. <http://www.mcdean.com/>
 Sponsored by SPAWAR <http://www.spawar.navy.mil/>
+
+Ported to 7.x. by Dominik Böhler <http://dominikboehler.de/>
\ No newline at end of file
diff --git a/TODO.txt b/TODO.txt
index e55e7c3..5a80870 100644
--- a/TODO.txt
+++ b/TODO.txt
@@ -13,4 +13,4 @@ speed things along.)
 
 TODO
 ----
-* Support for client-side caching headers, as the Timeline module does.
+* TBD
diff --git a/contrib/exhibit_core/exhibit_core.module b/contrib/exhibit_core/exhibit_core.module
index 3511dc6..e8b260f 100644
--- a/contrib/exhibit_core/exhibit_core.module
+++ b/contrib/exhibit_core/exhibit_core.module
@@ -1,10 +1,11 @@
 <?php
+// $Id: exhibit_core.module,v 1.3 2008/07/17 11:51:07 arto Exp $
 
 //////////////////////////////////////////////////////////////////////////////
 // Core API hooks
 
 /**
- * Implementation of hook_menu().
+ * Implements hook_menu().
  */
 function exhibit_core_menu() {
   return array(
@@ -29,13 +30,13 @@ function exhibit_core_menu() {
       'page arguments' => array('exhibit_core_get_nodes'),
       'file' => 'exhibit_core.pages.inc',
     ),
-    /*'admin/content/exhibit/add/internal' => array(
-      'title' => 'Add Drupal feed',
-      'type' => MENU_LOCAL_TASK,
-      'page callback' => 'drupal_get_form',
-      'page arguments' => array('exhibit_core_admin_feed_form'),
-      'file' => 'exhibit_core.admin.inc',
-    ),*/
+    'admin/content/exhibit/add/internal' => array(
+ 'title' => 'Add Drupal feed',
+ 'type' => MENU_LOCAL_TASK,
+ 'page callback' => 'drupal_get_form',
+ 'page arguments' => array('exhibit_core_admin_feed_form'),
+ 'file' => 'exhibit_core.admin.inc',
+ ),
   );
 }
 
@@ -44,6 +45,6 @@ function exhibit_core_menu() {
 
 function exhibit_core_callback($callback) {
   $args = array_slice(func_get_args(), 1);
-  require_once drupal_get_path('module', 'exhibit') . '/exhibit.pages.inc';
-  exhibit_output('application/json', drupal_to_js(call_user_func_array($callback, $args)));
+  require_once DRUPAL_ROOT . '/' . drupal_get_path('module', 'exhibit') . '/exhibit.pages.inc';
+  exhibit_output('application/json', drupal_json_encode(call_user_func_array($callback, $args)));
 }
diff --git a/contrib/exhibit_core/exhibit_core.pages.inc b/contrib/exhibit_core/exhibit_core.pages.inc
index 2a92dc2..9ddf40c 100644
--- a/contrib/exhibit_core/exhibit_core.pages.inc
+++ b/contrib/exhibit_core/exhibit_core.pages.inc
@@ -1,4 +1,5 @@
 <?php
+// $Id: exhibit_core.pages.inc,v 1.4 2008/07/17 11:51:07 arto Exp $
 
 //////////////////////////////////////////////////////////////////////////////
 // Exhibit data feeds
@@ -13,17 +14,19 @@ function exhibit_core_get_users($role = NULL, $options = array()) {
   );
 
   // Make sure the current user is allowed to see user profile information.
-  if (!user_access('access user profiles'))
+  if (!user_access('access user profiles')) {
     return exhibit_json(array(), $types, $fields);
+  }
 
   // Retrieve users, filtering by an optional user role limitation, if specified
   $result = $role && $role != 'authenticated user' ?
-    db_query("SELECT u.* FROM {users} u LEFT JOIN {users_roles} ur ON u.uid = ur.uid LEFT JOIN {role} r ON r.rid = ur.rid WHERE r.name = '%s'", $role) :
+    db_query("SELECT u.* FROM {users} u LEFT JOIN {users_roles} ur ON u.uid = ur.uid LEFT JOIN {role} r ON r.rid = ur.rid WHERE r.name = ?", array($role)) :
     db_query('SELECT u.uid FROM {users} u WHERE u.status = 1 ORDER BY u.name');
 
   $items = array();
-  while ($user = db_fetch_object($result)) {
-    $user = user_load($user->uid);
+  $result->fetchObject();
+  foreach ($result as $user) {
+    $user = user_load_multiple($user->uid);
 
     $item = array(
       'type'        => 'user',
@@ -43,7 +46,7 @@ function exhibit_core_get_users($role = NULL, $options = array()) {
     if (module_exists('profile')) {
       $profile_result = db_query('SELECT f.name name, v.value value FROM {profile_values} v, {profile_fields} f WHERE v.fid = f.fid AND v.uid = %d AND f.visibility = 3', $user->uid);
       while ($row = db_fetch_array($profile_result)) {
-        if(!empty($row['name']) && !is_null($row['value'])) {
+        if (!empty($row['name']) && !is_null($row['value'])) {
           $item[$row['name']] = $row['value'];
         }
       }
@@ -62,7 +65,7 @@ function exhibit_core_get_terms($vocabulary, $options = array()) {
     'url'        => array('valueType' => 'url'),
   );
 
-  $result = db_query('SELECT t.* FROM {term_data} t WHERE t.vid = %d ORDER BY t.name', $vocabulary->vid);
+  $result = db_query('SELECT t.* FROM {taxonomy_term_data} t WHERE t.vid = ? ORDER BY t.name', array($vocabulary->vid));
   $items = array();
   while ($term = db_fetch_object($result)) {
     // TODO: take hierarchical term relationships into account.
@@ -91,22 +94,24 @@ function exhibit_core_get_nodes($type = NULL, $options = array()) {
 
   $result = !$type ?
     db_query('SELECT n.nid FROM {node} n WHERE n.status = 1 ORDER BY n.nid') :
-    db_query("SELECT n.nid FROM {node} n WHERE n.status = 1 AND n.type = '%s' ORDER BY n.nid", $type);
+    db_query("SELECT n.nid FROM {node} n WHERE n.status = 1 AND n.type = ? ORDER BY n.nid", array($type));
   $items = array();
-  while ($node = db_fetch_object($result)) {
+  $result->fetchObject();
+  foreach ($result as $node) {
     $node = node_load($node->nid);
 
     // Make sure that the current user actually should be seeing to this node.
     // TODO: double-check interactions with data feed caching.
-    if (!node_access('view', $node))
+    if (!node_access('view', $node)) {
       continue;
+    }
 
     // If this node type has not yet been seen, amend the Exhibit schema.
     // TODO: there's a problem here in that we don't have any means of
     // obtaining plural labels for content types; just appending an 's' will
     // not get us all that far even in English. Good suggestions welcome.
     if (!isset($types[$node->type])) {
-      $type_label = node_get_types('name', $node->type);
+      $type_label = node_type_get_name($node->type);
       $type_label = $type_label ? $type_label : ucwords($node->type);
       $types[$node->type] = array('label' => $type_label);
     }
@@ -118,9 +123,9 @@ function exhibit_core_get_nodes($type = NULL, $options = array()) {
       'author'      => 'user/' . $node->uid,
       'created'     => gmstrftime(EXHIBIT_DATE_FORMAT, $node->created),
       'changed'     => gmstrftime(EXHIBIT_DATE_FORMAT, $node->changed),
-      'body'        => $node->teaser,
+      'body'        => 'body',
       'url'         => url('node/' . $node->nid, array('absolute' => TRUE)),
-      'terms'       => array_values(array_map('_exhibit_core_get_term_name', taxonomy_node_get_terms($node))),
+      //'terms'       => array_values(array_map('_exhibit_core_get_term_name', render($node->field_terms))),
     ));
   }
 
diff --git a/exhibit.admin.inc b/exhibit.admin.inc
index 1839468..d9b2e79 100644
--- a/exhibit.admin.inc
+++ b/exhibit.admin.inc
@@ -1,4 +1,5 @@
 <?php
+// $Id: exhibit.admin.inc,v 1.7 2009/05/01 05:09:27 arto Exp $
 
 //////////////////////////////////////////////////////////////////////////////
 // Exhibit API functions
@@ -25,7 +26,7 @@ function exhibit_admin_feed_types() {
  * @ingroup forms
  * @see system_settings_form()
  */
-function exhibit_admin_settings() {
+function exhibit_admin_settings($form, &$form_state) {
   $form = array();
 
   // Exhibit API
@@ -36,8 +37,8 @@ function exhibit_admin_settings() {
   $form['extensions'] = array('#type' => 'fieldset', '#title' => t('Exhibit extensions'), '#collapsible' => TRUE, '#collapsed' => TRUE, '#description' => 'Select the Exhibit extensions you wish to enable below.  You can also specify an alternate API location for each extension.');
   foreach (exhibit_exhibit_views() as $id => $view) {
     if (isset($view->href)) {
-      $form['extensions']['exhibit_extensions_'. $id] = array('#type' => 'checkbox', '#title' => $view['title'], '#default_value' => variable_get('exhibit_extensions_'. $id, FALSE), '#description' => t(''));
-      $form['extensions']['exhibit_extensions_'. $id .'_api'] = array('#type' => 'textfield', '#title' => t($view['title'] . ' API'), '#default_value' => variable_get('exhibit_extensions_'. $id .'_api', constant('EXHIBIT_'. strtoupper($id) .'_JS_URL')));
+      $form['extensions']['exhibit_extensions_' . $id] = array('#type' => 'checkbox', '#title' => $view['title'], '#default_value' => variable_get('exhibit_extensions_' . $id, FALSE), '#description' => t(''));
+      $form['extensions']['exhibit_extensions_' . $id . '_api'] = array('#type' => 'textfield', '#title' => t($view['title'] . ' API'), '#default_value' => variable_get('exhibit_extensions_' . $id . '_api', constant('EXHIBIT_' . strtoupper($id) . '_JS_URL')));
       if ($id == 'map') {
         $form['extensions']['exhibit_gmap_key'] = array('#type' => 'textfield', '#title' => t('Google Maps API key'), '#default_value' => variable_get('exhibit_gmap_key', ''), '#description' => t('If you have the <a href="http://drupal.org/project/gmap">GMap</a> and/or <a href="http://drupal.org/project/keys">Keys API</a> modules installed and configured, you can leave this blank as Exhibit will pull the Google Maps API key used from <a href="/admin/settings/gmap">that configuration</a>.'));
       }
@@ -65,7 +66,7 @@ function exhibit_admin_feeds() {
       is_numeric($feed->fid) ? check_plain($feed->title) : $feed->title,
       check_plain(isset($types[$feed->type]) ? $types[$feed->type] : $feed->type),
       (!is_null($url_parts) ?
-        l(truncate_utf8($feed->url, 56, TRUE, TRUE), $url_parts['path'], array('query' => $url_parts['query'])) :
+        l(truncate_utf8($feed->url, 56, TRUE, TRUE), $url_parts['path']) :
         l(truncate_utf8($feed->url, 56, TRUE, TRUE), $feed->url)),
       is_numeric($feed->fid) ? l(t('edit'), 'admin/content/exhibit/edit/' . $feed->fid) : '',
       is_numeric($feed->fid) ? l(t('delete'), 'admin/content/exhibit/delete/' . $feed->fid) : '',
@@ -75,7 +76,7 @@ function exhibit_admin_feeds() {
   if (empty($rows)) {
     $rows[] = array(array('data' => t('No data feeds defined.'), 'colspan' => '5'));
   }
-  return theme('table', $head, $rows);
+  return theme('table', array('header' => $head, 'rows' => $rows));
 }
 
 /**
@@ -85,9 +86,9 @@ function exhibit_admin_feeds() {
  * @see exhibit_admin_feed_form_validate()
  * @see exhibit_admin_feed_form_submit()
  */
-function exhibit_admin_feed_form(&$form_state, $edit = array('title' => '', 'type' => 'application/json', 'url' => '')) {
+function exhibit_admin_feed_form($form, &$form_state, $edit = array('title' => '', 'type' => 'application/json', 'url' => '')) {
   $form = array();
-  $form['fid'] = array('#type' => 'hidden', '#value' => !empty($edit['fid']) ? $edit['fid'] : '');
+  $form['fid'] = array('#type' => 'hidden', '#value' => !empty($edit->fid) ? $edit->fid : '');
   $form['module'] = array('#type' => 'hidden', '#value' => '');
 
   $form['title'] = array('#type' => 'textfield', '#title' => t('Title'), '#default_value' => $edit['title'], '#maxlength' => 64, '#description' => t('The human-readable name of this data feed. This text will be displayed as part of the list on the data feed management page. This name must begin with a capital letter and contain only letters, numbers, and spaces. This name must be unique.'), '#required' => TRUE);
@@ -113,12 +114,12 @@ function exhibit_admin_feed_form_submit($form, &$form_state) {
   extract($form_state['values'], EXTR_SKIP | EXTR_REFS);
 
   if (empty($fid)) {
-    db_query("INSERT INTO {exhibit_feeds} (fid, module, title, type, url) VALUES (NULL, '%s', '%s', '%s', '%s')", $module, $title, $type, $url);
+    db_query("INSERT INTO {exhibit_feeds} (fid, module, title, type, url) VALUES (NULL, ?, ?, ?, ?)", array($module, $title, $type, $url));
     watchdog('exhibit', 'Data feed %title created.', array('%title' => $title), WATCHDOG_NOTICE, l(t('view'), 'admin/content/exhibit'));
     drupal_set_message(t('The data feed %title has been created.', array('%title' => $title)));
   }
   else {
-    db_query("UPDATE {exhibit_feeds} SET title = '%s', type = '%s', url = '%s' WHERE fid = %d", $title, $type, $url, $fid);
+    db_query("UPDATE {exhibit_feeds} SET title = ?, type = ?, url = ? WHERE fid = ?", array($title, $type, $url, $fid));
     watchdog('exhibit', 'Data feed %title updated.', array('%title' => $title), WATCHDOG_NOTICE, l(t('view'), 'admin/content/exhibit'));
     drupal_set_message(t('The data feed %title has been updated.', array('%title' => $title)));
   }
@@ -126,12 +127,12 @@ function exhibit_admin_feed_form_submit($form, &$form_state) {
   $form_state['redirect'] = 'admin/content/exhibit';
 }
 
-function exhibit_admin_feed_delete($form_state, $feed) {
-  $form['fid'] = array('#type' => 'value', '#value' => $feed['fid']);
-  $form['title'] = array('#type' => 'value', '#value' => $feed['title']);
+function exhibit_admin_feed_delete($form, $form_state, $feed) {
+  $form['fid'] = array('#type' => 'value', '#value' => $feed->fid);
+  $form['title'] = array('#type' => 'value', '#value' => $feed->title);
 
   return confirm_form($form,
-    t('Are you sure you want to delete the data feed %title?', array('%title' => $feed['title'])),
+    t('Are you sure you want to delete the data feed %title?', array('%title' => $feed->title)),
     isset($_GET['destination']) ? $_GET['destination'] : 'admin/content/exhibit',
     t('This action cannot be undone.'));
 }
@@ -140,7 +141,7 @@ function exhibit_admin_feed_delete_submit($form, &$form_state) {
   extract($form_state['values'], EXTR_SKIP | EXTR_REFS);
 
   if ($form_state['values']['confirm']) {
-    db_query("DELETE FROM {exhibit_feeds} WHERE fid = %d", $fid);
+    db_query("DELETE FROM {exhibit_feeds} WHERE fid = ?", array($fid));
     watchdog('exhibit', 'Data feed %title deleted.', array('%title' => $title));
     drupal_set_message(t('The data feed %title has been deleted.', array('%title' => $title)));
   }
diff --git a/exhibit.info b/exhibit.info
index af015a5..e0ba3ec 100644
--- a/exhibit.info
+++ b/exhibit.info
@@ -1,12 +1,13 @@
 name = Exhibit
 description = Displays structured data in the form of rich visualizations that can be searched, filtered and sorted using faceted browsing.
 package = SIMILE
-core = 6.x
+core = 7.x
 php = 5.2
 
-; Information added by drupal.org packaging script on 2008-06-02
-version = "6.x-1.0-alpha1"
-core = "6.x"
-project = "exhibit"
-datestamp = "1212404706"
+dependencies[] = views_datasource
 
+files[] = exhibit.admin.inc
+files[] = exhibit.install
+files[] = exhibit.module
+files[] = exhibit.pages.inc
+files[] = exhibit.views.inc
\ No newline at end of file
diff --git a/exhibit.js b/exhibit.js
index a8d42ff..5f27f5e 100644
--- a/exhibit.js
+++ b/exhibit.js
@@ -1,8 +1,12 @@
+// $Id: exhibit.js,v 1.2 2008/07/24 13:16:13 arto Exp $
 
 /**
  * Enable auto facet generation based on fields in selected feeds in Exhibit node creation
  */
-Drupal.behaviors.exhibit = function(context) {
+ (function ($) {
+Drupal.behaviors.exhibit = {
+  
+  attach: function(context) {
   
   Drupal.exhibit.buildForm();
   // Loads all feeds, attaches change handler to feed checkboxes,
@@ -16,6 +20,7 @@ Drupal.behaviors.exhibit = function(context) {
         if (this.checked) {
           Drupal.exhibit.selectFeed(this);
         } 
+      
     });
     
     // Bind insert button click event
@@ -35,7 +40,7 @@ Drupal.behaviors.exhibit = function(context) {
     });
     
   });
-
+  }
 };
 
 /**
@@ -490,4 +495,6 @@ Drupal.exhibit = function() {
     
   };
   
-}();
\ No newline at end of file
+}();
+
+})(jQuery);
\ No newline at end of file
diff --git a/exhibit.module b/exhibit.module
index a2e7763..4b78056 100644
--- a/exhibit.module
+++ b/exhibit.module
@@ -1,53 +1,75 @@
 <?php
+// $Id: exhibit.module,v 1.10 2009/05/01 05:09:27 arto Exp $
 
 //////////////////////////////////////////////////////////////////////////////
 // Module settings
 
-define('EXHIBIT_DATE_FORMAT',        '%Y-%m-%dT%H:%M:%SZ');
-define('EXHIBIT_XMLNS_URL',          'http://simile.mit.edu/2006/11/exhibit#');  // TODO:  What's this for? This needs to be updated or removed
-define('EXHIBIT_JS_URL',             variable_get('exhibit_js_url', 'http://api.simile-widgets.org/exhibit/2.2.0/exhibit-api.js'));
-define('EXHIBIT_MAP_JS_URL',         variable_get('exhibit_map_js_url', 'http://api.simile-widgets.org/exhibit/2.2.0/extensions/map/map-extension.js'));
-define('EXHIBIT_BARCHART_JS_URL',    variable_get('exhibit_barchart_js_url', 'http://api.simile-widgets.org/exhibit/2.2.0/extensions/chart/chart-extension.js'));
+define('EXHIBIT_DATE_FORMAT',         '%Y-%m-%dT%H:%M:%SZ');
+define('EXHIBIT_XMLNS_URL',           'http://simile.mit.edu/2006/11/exhibit#'); // TODO:  What's this for? This needs to be updated or removed
+//define('EXHIBIT_JS_URL',              variable_get('exhibit_js_url', 'http://127.0.0.1/exhibit3/scripted/src/exhibit-api.js'));
+define('EXHIBIT_JS_URL',              variable_get('exhibit_js_url', 'http://api.simile-widgets.org/exhibit/2.2.0/exhibit-api.js'));
+define('EXHIBIT_MAP_JS_URL',          variable_get('exhibit_map_js_url', 'http://api.simile-widgets.org/exhibit/2.2.0/extensions/map/map-extension.js'));
+define('EXHIBIT_BARCHART_JS_URL',     variable_get('exhibit_barchart_js_url', 'http://api.simile-widgets.org/exhibit/2.2.0/extensions/chart/chart-extension.js'));
 define('EXHIBIT_SCATTERPLOT_JS_URL', variable_get('exhibit_scatterplot_js_url', 'http://api.simile-widgets.org/exhibit/2.2.0/extensions/chart/chart-extension.js'));
-define('EXHIBIT_TIMELINE_JS_URL',    variable_get('exhibit_timeline_js_url', 'http://api.simile-widgets.org/exhibit/2.2.0/extensions/time/time-extension.js'));
-define('EXHIBIT_CALENDAR_JS_URL',    variable_get('exhibit_calendar_js_url', 'http://api.simile-widgets.org/exhibit/2.2.0/extensions/calendar/calendar-extension.js'));
-define('EXHIBIT_FEED_LIFETIME',      (int)variable_get('timeline_feed_lifetime', 0));
-define('EXHIBIT_FEED_ETAG',          (bool)variable_get('timeline_feed_etag', TRUE));
+define('EXHIBIT_TIMELINE_JS_URL',     variable_get('exhibit_timeline_js_url', 'http://api.simile-widgets.org/exhibit/2.2.0/extensions/time/time-extension.js'));
+define('EXHIBIT_CALENDAR_JS_URL',     variable_get('exhibit_calendar_js_url', 'http://api.simile-widgets.org/exhibit/2.2.0/extensions/calendar/calendar-extension.js'));
+define('EXHIBIT_FEED_LIFETIME',       (int) variable_get('timeline_feed_lifetime', 0));
+define('EXHIBIT_FEED_ETAG',           (bool) variable_get('timeline_feed_etag', TRUE));
 
 
 //////////////////////////////////////////////////////////////////////////////
 // Core API hooks
 
 /**
- * Implementation of hook_help().
+ * Implements hook_help().
  */
 function exhibit_help($path) {
   switch ($path) {
     case 'admin/help#exhibit':
       return '<p>' . t('') . '</p>'; // TODO
-    case 'admin/settings/exhibit':
+    case 'admin/config/exhibit':
       //return '<p>' . t('') . '</p>'; // TODO
   }
 }
 
 /**
- * Implementation of hook_perm().
+ * Implements hook_permission().
  */
-function exhibit_perm() {
+function exhibit_permission() {
   return array(
-    'administer exhibit feeds',
-    //'use external exhibit feeds', // TODO
-    'access exhibits',
-    'create exhibits',
-    'edit exhibits',
-    'edit own exhibits',
-    'delete exhibits',
-    'delete own exhibits',
+    'administer exhibit feeds' => array(
+      'title' => t('administer exhibit feeds'),
+      'description' => t('TODO Add a description for administer exhibit feeds'),
+    ),
+    'access exhibits' => array(
+      'title' => t('access exhibits'),
+      'description' => t('TODO Add a description for access exhibits'),
+    ),
+    'create exhibits' => array(
+      'title' => t('create exhibits'),
+      'description' => t('TODO Add a description for create exhibits'),
+    ),
+    'edit exhibits' => array(
+      'title' => t('edit exhibits'),
+      'description' => t('TODO Add a description for edit exhibits'),
+    ),
+    'edit own exhibits' => array(
+      'title' => t('edit own exhibits'),
+      'description' => t('TODO Add a description for edit own exhibits'),
+    ),
+    'delete exhibits' => array(
+      'title' => t('delete exhibits'),
+      'description' => t('TODO Add a description for delete exhibits'),
+    ),
+    'delete own exhibits' => array(
+      'title' => t('delete own exhibits'),
+      'description' => t('TODO Add a description for delete own exhibits'),
+    ),
   );
 }
 
 /**
- * Implementation of hook_menu().
+ * Implements hook_menu().
  */
 function exhibit_menu() {
   return array(
@@ -79,7 +101,7 @@ function exhibit_menu() {
       'page arguments' => array(2),
       'file' => 'exhibit.pages.inc',
     ),
-    'admin/settings/exhibit' => array(
+    'admin/config/exhibit' => array(
       'title' => 'Exhibits',
       'description' => 'Settings for the Exhibit module.',
       'access arguments' => array('administer site configuration'),
@@ -128,32 +150,41 @@ function exhibit_menu() {
 }
 
 /**
- * Implementation of hook_block().
+ * Implements hook_block_info.
  */
-function exhibit_block($op = 'list', $delta = 0, $edit = array()) {
-  switch ($op) {
-    case 'list':
-      return array('facets' => array('info' => t('Exhibit facets')));
-    case 'view':
-      switch ($delta) {
-        case 'facets':
-          if (arg(0) == 'node' && is_numeric(arg(1)) && arg(2) != 'edit') {
-            $node = node_load(arg(1));
-            $block['content'] = $node->exhibit['facet_definition'];
-          }
-          break;
+function exhibit_block_info() {
+  return array('facets' => array('info' => t('Exhibit facets')));
+}
+
+/**
+ * Implements hook_block_view.
+ */
+function exhibit_block_view($delta) {
+  $block = array();
+  
+  switch ($delta) {
+    case 'facets':
+      if (arg(0) == 'node' && is_numeric(arg(1)) && arg(2) != 'edit') {
+        $node = node_load(arg(1));
+        $block['content'] = $node->exhibit['facet_definition'];
       }
-      return $block;
+      break;
   }
+  return $block;
 }
 
 /**
- * Implementation of hook_theme().
+ * Implements hook_block().
+ */
+function exhibit_block_OLD($op = 'list', $delta = 0, $edit = array()) { }
+
+/**
+ * Implements hook_theme().
  */
 function exhibit_theme() {
   return array(
     'exhibit_definition' => array(
-      'arguments' => array('node' => NULL),
+      'variables' => array('node' => NULL),
     ),
   );
 }
@@ -162,26 +193,25 @@ function exhibit_theme() {
 // Node API hooks
 
 /**
- * Implementation of hook_node_info().
+ * Implements hook_node_info().
  */
 function exhibit_node_info() {
   return array(
     'exhibit' => array(
-      'name'        => t('Exhibit'),
-      'module'      => 'exhibit', //_node',
+      'name'     => t('Exhibit'),
+      'base'      => 'exhibit', //_node',
       'description' => t('An <em>exhibit</em> displays structured data in the form of rich visualizations that can be searched, filtered and sorted using faceted browsing.'),
       'has_title'   => TRUE,
       'title_label' => t('Title'),
-      'has_body'    => TRUE,
-      'body_label'  => t('Description'),
-    ),
+      'has_body' => FALSE,
+      ),
   );
 }
 
 /**
- * Implementation of hook_access().
+ * Implements hook_node_access().
  */
-function exhibit_access($op, $node) {
+function exhibit_node_access($node, $op) {
   switch ($op) {
     case 'view':
       return user_access('access exhibits');
@@ -197,120 +227,204 @@ function exhibit_access($op, $node) {
 }
 
 /**
- * Implementation of hook_load().
+ * Implements hook_load().
  */
-function exhibit_load($node) {
-  $exhibit = db_fetch_array(db_query('SELECT * FROM {exhibit_nodes} WHERE vid = %d', $node->vid));
-  $exhibit['feeds'] = explode(',', $exhibit['feeds']);
-  return (object)array('exhibit' => $exhibit);
+function exhibit_load($nodes) {
+  foreach ($nodes as $nid => &$node) {
+    $exhibit = db_query('SELECT * FROM {exhibit_nodes} WHERE vid = ?', array($node->vid))->fetchAssoc();
+    $exhibit['feeds'] = explode(',', $exhibit['feeds']);
+    $node_additions = (object) array('exhibit' => $exhibit);
+    foreach ($node_additions as $property => &$value) {
+      $node->$property = $value;
+    }
+  }
 }
 
 /**
- * Implementation of hook_validate().
+ * Implements hook_validate().
  */
-function exhibit_validate(&$node) {}
+function exhibit_validate(&$node) { }
 
 /**
- * Implementation of hook_insert().
+ * Implements hook_insert().
  */
 function exhibit_insert($node) {
   $node->exhibit['feeds'] = implode(',', array_filter(array_values($node->exhibit['feeds']), 'trim'));
-  db_query("INSERT INTO {exhibit_nodes} (nid, vid, feeds, definition, facet_definition) VALUES (%d, %d, '%s', '%s', '%s')", $node->nid, $node->vid, $node->exhibit['feeds'], $node->exhibit['definition'], $node->exhibit['facet_definition']);
+  db_query("INSERT INTO {exhibit_nodes} (nid, vid, feeds, definition, facet_definition) VALUES (?, ?, ?, ?, ?)", array($node->nid, $node->vid, $node->exhibit['feeds'], $node->exhibit['definition'], $node->exhibit['facet_definition']));
 }
 
 /**
- * Implementation of hook_update().
+ * Implements hook_update().
  */
 function exhibit_update($node) {
   if ($node->revision) {
     return exhibit_insert($node);
   }
-  $node->exhibit['feeds'] = implode(',', array_filter(array_values($node->exhibit['feeds']), 'trim'));
-  db_query("UPDATE {exhibit_nodes} SET feeds = '%s', definition = '%s', facet_definition = '%s' WHERE vid = %d", $node->exhibit['feeds'], $node->exhibit['definition'], $node->exhibit['facet_definition'], $node->vid);
-}
+  $feeds = implode(',', array_filter(array_values($node->exhibit['feeds']), 'trim'));
+  db_query("UPDATE {exhibit_nodes} SET feeds = ?, definition = ?, facet_definition = ? WHERE vid = ?", array($feeds, $node->exhibit['definition'], $node->exhibit['facet_definition'], $node->vid));
+ }
 
 /**
- * Implementation of hook_delete().
+ * Implements hook_delete().
  */
 function exhibit_delete($node) {
-  db_query('DELETE FROM {exhibit_nodes} WHERE nid = %d', $node->nid);
+  db_query('DELETE FROM {exhibit_nodes} WHERE nid = ?', array($node->nid));
 }
 
 /**
- * Implementation of hook_nodeapi().
+ * Implements hook_node_revision_delete.
  */
-function exhibit_nodeapi(&$node, $op, $teaser, $page) {
-  switch ($op) {
-    case 'delete revision':
-      db_query('DELETE FROM {exhibit_nodes} WHERE vid = %d', $node->vid);
-      break;
-  }
+function exhibit_node_revision_delete($node) {
+  db_query('DELETE FROM {exhibit_nodes} WHERE vid = %d', $node->vid);
 }
 
 /**
- * Implementation of hook_form().
+ * Implements hook_form().
  */
-function exhibit_form(&$node, &$param) {
-  drupal_add_js(drupal_get_path('module', 'exhibit') .'/exhibit.js');
-  drupal_add_js(array('exhibit' => exhibit_get_feeds('url')), 'setting');
-
-  $type = node_get_types('type', $node);
-
-  if ($type->has_title) {
-    $form['title'] = array('#type' => 'textfield', '#title' => check_plain($type->title_label), '#required' => TRUE, '#default_value' => $node->title, '#weight' => -5);
-  }
+function exhibit_form($node, &$form_state) {
+  drupal_add_js(drupal_get_path('module', 'exhibit') . '/exhibit.js');
+  drupal_add_js(array('exhibit' => exhibit_get_feeds('url')), array('type' => 'setting', 'scope' => JS_DEFAULT));
+
+  $type = node_type_get_type($node);
+ 
+  $form['title'] = array(
+    '#type' => 'textfield', 
+    '#title' => check_plain($type->title_label), 
+    '#required' => TRUE, 
+    '#default_value' => $node->title, 
+    '#weight' => -5,
+  );
 
-  if ($type->has_body) {
     // FIXME: this works around a bug in node_submit(), lines 782-793, which
     // causes the body field to be emptied when not using node_body_field()
     // to generate the body and format fieldset. Need to submit a core patch.
-    $form['teaser_include'] = array('#type' => 'hidden', '#value' => '1');
-
-    $form['body_filter'] = array('#type' => 'fieldset', '#title' => check_plain($type->body_label), '#collapsible' => TRUE, '#collapsed' => TRUE);
-    $form['body_filter']['body'] = array('#type' => 'textarea', '#title' => t('Description'), '#default_value' => $node->body, '#required' => ($type->min_word_count > 0), '#rows' => 2);
-    $form['body_filter']['format'] = filter_form($node->format);
-  }
-
-  $form['exhibit'] = array('#type' => 'fieldset', '#title' => t('Exhibit'), '#collapsible' => TRUE, '#collapsed' => FALSE, '#tree' => TRUE);
-  $form['exhibit']['feeds'] = array('#type' => 'checkboxes', '#title' => t('Data feeds'), '#default_value' => !empty($node->exhibit['feeds']) ? $node->exhibit['feeds'] : array(), '#options' => exhibit_get_feeds('title'), '#attributes' => array('class' => 'exhibit-feed-checkbox'), '#prefix' => '<div id="feed-field-selection">', '#suffix' => '</div>');
-  $form['exhibit']['definition'] = array('#type' => 'textarea', '#title' => t('Definition'), '#default_value' => !empty($node->exhibit['definition']) ? $node->exhibit['definition'] : theme('exhibit_definition'), '#rows' => 10);
-  $form['exhibit']['facet_definition'] = array('#type' => 'textarea', '#title' => t('Facet definition'), '#default_value' => @$node->exhibit['facet_definition'], '#rows' => 5);
-  $form['exhibit']['facet-generator-form-wrapper'] = array('#type' => 'fieldset', '#title' => t('Facet Generator'), '#collapsible' => TRUE, '#collapsed' => TRUE, '#tree' => TRUE, '#attributes' => array('id' => 'exhibit-facet-builder', 'style' => 'display:none;'), '#value' => '<div id="facet-generator-form"></div>');
-
+    /*$form['teaser_include'] = array(
+      '#type' => 'hidden', 
+      '#value' => '1',
+    );
+    
+   $form['body_filter'] = array(
+      '#type' => 'fieldset', 
+      '#title' => check_plain($type->body_label), 
+      '#collapsible' => TRUE, 
+      '#collapsed' => TRUE,
+    );
+    $form['body_filter']['body'] = array(
+      '#type' => 'textarea', 
+      '#title' => t('Description'), 
+      '#default_value' => $node->body['und'], 
+      '#required' => ($type->min_word_count > 0), 
+      '#rows' => 2,
+    );*/
+  $form['exhibit'] = array(
+    '#type' => 'fieldset', 
+    '#title' => t('Exhibit'), 
+    '#collapsible' => TRUE, 
+    '#collapsed' => FALSE, 
+    '#tree' => TRUE,
+  );
+  $form['exhibit']['feeds'] = array(
+    '#type' => 'checkboxes', 
+    '#title' => t('Data feeds'), 
+    '#default_value' => !empty($node->exhibit['feeds']) ? $node->exhibit['feeds'] : array(), 
+    '#options' => exhibit_get_feeds('title'), 
+    '#attributes' => array('class' => array('exhibit-feed-checkbox')), 
+    '#prefix' => '<div id="feed-field-selection">', 
+    '#suffix' => '</div>',
+  );
+  // TODO Please change this theme call to use an associative array for the $variables parameter.
+  $form['exhibit']['definition'] = array(
+    '#type' => 'textarea', 
+    '#title' => t('Definition'), 
+    '#default_value' => !empty($node->exhibit['definition']) ? $node->exhibit['definition'] : theme_exhibit_definition(), 
+    '#rows' => 10,
+  );
+  $form['exhibit']['facet_definition'] = array(
+    '#type' => 'textarea', 
+    '#title' => t('Facet definition'), 
+    '#default_value' => @$node->exhibit['facet_definition'], 
+    '#rows' => 5,
+  );
+  /*
+  $form['exhibit']['facet-generator-form-wrapper'] = array(
+    '#type' => 'fieldset', 
+    '#title' => t('Facet Generator'), 
+    '#collapsible' => TRUE, 
+    '#collapsed' => TRUE, 
+    '#tree' => TRUE, 
+    '#attributes' => array('id' => 'exhibit-facet-builder', 'style' => 'display:none;'), '#value' => '<div id="facet-generator-form"></div>',
+  );
+*/
   return $form;
 }
 
 /**
- * Implementation of hook_view().
+ * Implements hook_view().
  */
-function exhibit_view($node, $teaser = FALSE, $page = FALSE) {
-  // Load the SIMILE Exhibit API and any enabled extensions
-  drupal_set_html_head('<script type="text/javascript" src="'. EXHIBIT_JS_URL .'"></script>'."\n");
-
-  // Load any enabled Exhibit extensions
-  foreach (exhibit_exhibit_views() as $id => $view) {
-    if (variable_get('exhibit_extensions_'. $id, FALSE)) {
-      drupal_set_html_head('<script type="text/javascript" src="'. $view['href'] .'"></script>'."\n");
+function exhibit_view($node, $view_mode) {
+  if ($view_mode == 'full') {
+  
+    // Load the SIMILE Exhibit API and any enabled extensions
+    drupal_add_js(EXHIBIT_JS_URL, 'external');
+    //drupal_add_library('exhibit', 'exhibit');
+    
+    //drupal_add_js(drupal_get_path('module', 'exhibit') . '/jquery.exhibit.js');
+    // Load any enabled Exhibit extensions
+    foreach (exhibit_exhibit_views() as $id => $view) {
+      if (variable_get('exhibit_extensions_' . $id, FALSE)) {
+        drupal_add_js('', array('type' => 'file'));
+      }
     }
-  }
-
-  // Insert <LINK> references to all enabled data feeds
-  foreach ($node->exhibit['feeds'] as $fid) {
-    if ($feed = exhibit_feed_load($fid)) {
-      exhibit_add_feed(exhibit_get_feed_url($feed), check_plain($feed['type']));
+    
+    // Insert <LINK> references to all enabled data feeds
+    $feeds = $node->exhibit['feeds'] ;
+   
+    foreach ($feeds as $fid) {
+      if ($feed = exhibit_feed_load($fid)) {
+        exhibit_add_feed(exhibit_get_feed_url($feed), check_plain($feed->type));
+      }
     }
+    
+    //drupal_set_message('<pre>' . print_r($node, TRUE) . '</pre>');
+    $node->content['exhibit'] = array(
+       '#markup' => $node->exhibit['definition'],
+       '#weight' => 1,
+    );
+    
   }
-
-  $node = node_prepare($node, $teaser);
-  $node->content['exhibit'] = array('#value' => $node->exhibit['definition'], '#weight' => 1);
   return $node;
 }
 
+/**
+ * Implements hook_js_alter().
+ */
+function exhibit_js_alter(&$javascript) {
+  if (arg(0) == 'node' && is_numeric(arg(1)) && arg(2) != 'edit') {
+    $nid = arg(1);
+    $node = node_load($nid); 
+  }
+//drupal_set_message(dprint_r($javascript));
+  if (isset($node->type) && $node->type == 'exhibit' ) {
+    unset($javascript['misc/jquery.js']);
+    unset($javascript['misc/jquery.once.js']);
+    unset($javascript['misc/ui/jquery.ui.core.min.js']);
+    unset($javascript['misc/drupal.js']);
+    unset($javascript['misc/jquery.ba-bbq.js']);
+    unset($javascript['modules/overlay/overlay-parent.js']);
+    unset($javascript['misc/jquery.cookie.js']);
+    unset($javascript['misc/jquery.form.js']);
+    unset($javascript['modules/contextual/contextual.js']);
+    unset($javascript['misc/form.js']);
+    unset($javascript['misc/ajax.js']);
+  }
+}
+
+
 //////////////////////////////////////////////////////////////////////////////
 // Views API hooks
 
 /**
- * Implementation of hook_views_api().
+ * Implements hook_views_api().
  */
 function exhibit_views_api() {
   return array(
@@ -323,7 +437,7 @@ function exhibit_views_api() {
 // Exhibit API hooks
 
 /**
- * Implementation of hook_exhibit_views().
+ * Implements hook_exhibit_views().
  */
 function exhibit_exhibit_views() {
   return array(
@@ -338,7 +452,7 @@ function exhibit_exhibit_views() {
     'map'       => array(
       'title'   => t('Map'),
       'class'   => 'Map',
-      'href'    => variable_get('exhibit_extensions_map_api', EXHIBIT_MAP_JS_URL) . '?gmapkey=' . (module_exists('gmap') ?  gmap_get_key() : variable_get('exhibit_gmap_key', '')),
+      'href'    => variable_get('exhibit_extensions_map_api', EXHIBIT_MAP_JS_URL) . '?gmapkey=' . (module_exists('gmap') ?   gmap_get_key() : variable_get('exhibit_gmap_key', '')),
     ),
     'barchart'  => array(
       'title'   => t('Barchart'),
@@ -371,7 +485,7 @@ function exhibit_exhibit_views() {
 // Exhibit API functions
 
 function exhibit_add_link($url) {
-  drupal_add_link(array('rel' => 'meta', 'type' => 'application/json', 'title' => 'Exhibit JSON', 'href' => exhibit_get_url($url)));
+  drupal_add_html_head_link(array('rel' => 'meta', 'type' => 'application/json', 'title' => 'Exhibit JSON', 'href' => exhibit_get_url($url)));
 }
 
 function exhibit_get_url($url) {
@@ -394,23 +508,23 @@ function exhibit_get_url($url) {
 }
 
 function exhibit_is_link_internal($url) {
-  return (bool)!preg_match('!^[\w\d\+\-]+://!', $url);
+  return (bool) !preg_match('!^[\w\d\+\-]+://!', $url);
 }
 
 function exhibit_add_feed($url, $type = 'application/json') {
   switch ($type) {
     case 'application/vnd.google-spreadsheet': // special case
-      drupal_add_link(array('rel' => 'exhibit/data', 'href' => $url, 'type' => 'application/jsonp', 'ex:converter' => 'googleSpreadsheets'));
+      drupal_add_html_head_link(array('rel' => 'exhibit/data', 'href' => $url, 'type' => 'application/jsonp', 'ex:converter' => 'googleSpreadsheets'));
       break;
     default:
-      drupal_add_link(array('rel' => 'exhibit/data', 'href' => $url, 'type' => $type));
+      drupal_add_html_head_link(array('rel' => 'exhibit/data', 'href' => $url, 'type' => $type));
       break;
   }
 }
 
 function exhibit_feed_load($fid) {
   if (is_numeric($fid)) {
-    return db_fetch_array(db_query('SELECT f.* FROM {exhibit_feeds} f WHERE f.fid = %d', $fid));
+    return db_query('SELECT f.* FROM {exhibit_feeds} f WHERE f.fid = ?', array($fid))->fetchObject();
   }
   else {
     if (module_exists('views')) {
@@ -420,23 +534,24 @@ function exhibit_feed_load($fid) {
         if (!empty($view->disabled) || empty($view->display)) {
           continue;
         }
-
-        // Check each display, add those using the Exhibit JSON style plugin
-        foreach (array_keys($view->display) as $id) {
-          $plugin = views_fetch_plugin_data('display', $view->display[$id]->display_plugin);
-          $display_options = $view->display[$id]->display_options;
-          if ($plugin['handler'] == 'views_plugin_display_feed' && $display_options['style_plugin'] == 'exhibit_json') {
-            $view_feed_id = $view->vid . '_' . $id;
-            if ($view_feed_id == $fid) {
-              return array('fid' => $view_feed_id,
-                            'module' => 'views',
-                            'title' => $view->name . ': ' . $view->display[$id]->display_title,
-                            'enabled' => TRUE,
-                            'cache' => FALSE,
-                            'type' => 'application/json',
-                            'url' => $display_options['path']);
-            }
+        
+        // This needs to change so exhibit datasource views will be shown automatically
+        $display_options = $view->display['default']->display_options;
+        $style = $display_options['style_plugin'];
+        $path = $view->display['page']->display_options['path'];    
+
+        if ($style == 'views_json') {
+          $view_feed_id = $view->vid . '_' . $style;
+          if ($view_feed_id == $fid) {
+            return (object) array('fid' => $view_feed_id,
+                          'module' => 'views',
+                          'title' => $view->name,
+                          'enabled' => TRUE,
+                          'cache' => FALSE,
+                          'type' => 'application/json',
+                          'url' => $path);
           }
+        
         }
       }
     }
@@ -446,7 +561,7 @@ function exhibit_feed_load($fid) {
 function exhibit_get_feeds($key = NULL) {
   $feeds = array();
   $result = db_query('SELECT f.* FROM {exhibit_feeds} f ORDER BY f.title ASC');
-  while ($feed = db_fetch_object($result)) {
+  foreach ($result as $feed) {
     $feeds[$feed->fid] = $key ? $feed->$key : $feed;
   }
 
@@ -458,47 +573,46 @@ function exhibit_get_feeds($key = NULL) {
       if (!empty($view->disabled) || empty($view->display)) {
         continue;
       }
-
-      // Check each display, add those using the Exhibit JSON style plugin
-      foreach (array_keys($view->display) as $id) {
-        $plugin = views_fetch_plugin_data('display', $view->display[$id]->display_plugin);
-        $display_options = $view->display[$id]->display_options;
-        if ($plugin['handler'] == 'views_plugin_display_feed' && $display_options['style_plugin'] == 'exhibit_json') {
-          $view_feed_id = $view->vid . '_' . $id;
-          if ($key) {
-            switch ($key) {
-              case 'fid':
-                $feeds[$view_feed_id] = $view_feed_id;
-                break;
-              case 'module':
-                $feeds[$view_feed_id] = 'views';
-                break;
-              case 'title':
-                $feeds[$view_feed_id] = l($view->name . ': ' . $view->display[$id]->display_title, 'admin/build/views/edit/' . $view->name);
-                break;
-              case 'enabled':
-                $feeds[$view_feed_id] = TRUE;
-                break;
-              case 'cache':
-                $feeds[$view_feed_id] = FALSE;
-                break;
-              case 'type':
-                $feeds[$view_feed_id] = 'application/json';
-                break;
-              case 'url':
-                $feeds[$view_feed_id] = $display_options['path'];
-                break;
-            }
-          }
-          else {
-            $feeds[$view_feed_id] = (object)array('fid' => $view_feed_id,
-                                                  'module' => 'views',
-                                                  'title' => l($view->name . ': ' . $view->display[$id]->display_title, 'admin/build/views/edit/' . $view->name),
-                                                  'enabled' => TRUE,
-                                                  'cache' => FALSE,
-                                                  'type' => 'application/json',
-                                                  'url' => $display_options['path']);
+       
+      $display_options = $view->display['default']->display_options;
+      $style = $display_options['style_plugin'];
+      $path = $view->display['page']->display_options['path'];    
+      
+      if ($style == 'views_json') {
+        $view_feed_id = $view->vid . '_' . $style;
+        if ($key) {
+          switch ($key) {
+            case 'fid':
+              $feeds[$view_feed_id] = $view_feed_id;
+              break;
+            case 'module':
+              $feeds[$view_feed_id] = 'views';
+              break;
+            case 'title':
+              $feeds[$view_feed_id] = l($view->name, 'admin/structure/views/view/' . $view->name . '/edit');
+              break;
+            case 'enabled':
+              $feeds[$view_feed_id] = TRUE;
+              break;
+            case 'cache':
+              $feeds[$view_feed_id] = FALSE;
+              break;
+            case 'type':
+              $feeds[$view_feed_id] = 'application/json';
+              break;
+            case 'url':
+              $feeds[$view_feed_id] = $path;
+              break;
           }
+        } 
+        else {
+          $feeds[$view_feed_id] = (object) array('fid' => $view_feed_id,
+                                                'module' => 'views',
+                                                'title' => l($view->name, 'admin/structure/views/edit/' . $view->name),
+                                                'enabled' => TRUE,
+                                                'cache' => FALSE,
+                                                'type' => 'application/json',
+                                                'url' =>  $path);
         }
       }
     }
@@ -508,7 +622,7 @@ function exhibit_get_feeds($key = NULL) {
 }
 
 function exhibit_get_feed_url($feed) {
-  $feed = (object)$feed;
+  $feed = (object) $feed;
   return exhibit_get_url(!empty($feed->cache) ? 'exhibit/feeds/' . $feed->fid : $feed->url);
 }
 
@@ -521,9 +635,9 @@ function exhibit_get_feed_contents($url) {
     if (is_int($result)) {
       switch ($result) {
         case MENU_NOT_FOUND:
-          return die(drupal_not_found());
+          return (drupal_not_found());
         case MENU_ACCESS_DENIED:
-          return die(drupal_access_denied());
+          return (drupal_access_denied());
       }
     }
   }
diff --git a/exhibit.pages.inc b/exhibit.pages.inc
index aed07be..0c39342 100644
--- a/exhibit.pages.inc
+++ b/exhibit.pages.inc
@@ -1,4 +1,5 @@
 <?php
+// $Id: exhibit.pages.inc,v 1.2 2008/07/17 11:51:06 arto Exp $
 
 //////////////////////////////////////////////////////////////////////////////
 // Menu callbacks
@@ -21,12 +22,12 @@ function exhibit_output_convert($url, $callback, $input_format = NULL, $output_f
 
   $output = $callback($response->data);
 
-  exhibit_output($output_format, drupal_to_js($output));
+  exhibit_output($output_format, drupal_json_encode($output));
 }
 
 function exhibit_output_node($node) {
   $function = 'exhibit_output_node_' . $node->type;
-  exhibit_output('application/json', drupal_to_js(is_callable($function) ? call_user_func($function, $node) : array('items' => array())));
+  exhibit_output('application/json', drupal_json_encode(is_callable($function) ? call_user_func($function, $node) : array('items' => array())));
 }
 
 function exhibit_output_feed($feed) {
@@ -35,20 +36,20 @@ function exhibit_output_feed($feed) {
 
 function exhibit_output($type, $body) {
   //$type = 'text/plain'; // DEBUG
-  drupal_set_header('Content-Type: ' . $type . '; charset=utf-8');
-  drupal_set_header('Content-Length: ' . strlen($body));
+  drupal_add_http_header('Content-Type', $type . '; charset=utf-8');
+  drupal_add_http_header('Content-Length', strlen($body));
 
   if (EXHIBIT_FEED_ETAG) {
     $md5 = base64_encode(md5($body, TRUE));
-    drupal_set_header('Content-MD5: ' . $md5);
-    drupal_set_header('ETag: "' . $md5 . '"'); // strong entity tag
+    drupal_add_http_header('Content-MD5', $md5);
+    drupal_add_http_header('ETag', '"' . $md5 . '"'); // strong entity tag
   }
 
   if (EXHIBIT_FEED_LIFETIME > 0) {
-    drupal_set_header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
-    drupal_set_header('Expires: ' . gmdate('D, d M Y H:i:s', time() + EXHIBIT_FEED_LIFETIME) . ' GMT');
-    drupal_set_header('Cache-Control: max-age=' . EXHIBIT_FEED_LIFETIME . ', private, must-revalidate');
-    drupal_set_header('Pragma: cache'); // need to override no-cache set by Drupal.
+    drupal_add_http_header('Last-Modified', gmdate('D, d M Y H:i:s') . ' GMT');
+    drupal_add_http_header('Expires', gmdate('D, d M Y H:i:s', REQUEST_TIME + EXHIBIT_FEED_LIFETIME) . ' GMT');
+    drupal_add_http_header('Cache-Control', 'max-age=' . EXHIBIT_FEED_LIFETIME . ', private, must-revalidate');
+    drupal_add_http_header('Pragma', 'cache'); // need to override no-cache set by Drupal.
   }
 
   print $body;
