Index: plugins/radioactivity_node-admin-ui.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/radioactivity/plugins/Attic/radioactivity_node-admin-ui.inc,v
retrieving revision 1.1.2.2
diff -u -p -r1.1.2.2 radioactivity_node-admin-ui.inc
--- plugins/radioactivity_node-admin-ui.inc	24 Jan 2010 21:32:51 -0000	1.1.2.2
+++ plugins/radioactivity_node-admin-ui.inc	21 Jun 2010 09:46:21 -0000
@@ -20,6 +20,27 @@ function radioactivity_node_admin_form()
           '#required' => TRUE,
           '#default_value' => _radioactivity_node_get_click_duration());
 
+  $form['radioactivity_node_anon_hook_mode'] = array(
+    '#type' => 'radios',
+    '#title' => t('Anonymous node view callback mode'),
+    '#default_value' => variable_get('radioactivity_node_anon_hook_mode', 'normal'),
+    '#options' => array('normal' => t('Normal'), 'ajax' => t('AJAX'), 'external' => t('External')),
+    '#description' =>
+    t('This setting controls how node view information is collected.').
+    '<ul><li>'.
+    t('<em>Normal</em> mode uses the standard Drupal page generation process (by hook_exit) and works with page cache modes <em>Disabled</em> '.
+      'and <em>Normal</em>. No further configuration is needed. This should be used if aggressive caching or external cache providers are not used.').
+    '</li><li>'.
+    t('<em>AJAX</em> mode inserts JavaScript code and an IMG-tag in the HTML. This makes browsers generate an extra call per page view to '.
+      'collect the information. '.
+      'This mode should work with all page cache modes and with static page cache providers such as Boost and Varnish. You have to enable '.
+      'block "Radioactivity Node: AJAX update" which contains the dynamic callback.').
+    '</li><li>'.
+    t('<em>External</em> mode disables information collection by Radioactivity Node altogether. Use this '.
+      'if you obtain the information by, e.g., parsing accelerator logs. Only for very busy sites.').
+    '</li></ul>'.
+    t('<strong>Note</strong>: Every time you change this setting the page caches must be cleared.'));
+
   return system_settings_form($form);
 }
 
Index: plugins/radioactivity_node.install
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/radioactivity/plugins/radioactivity_node.install,v
retrieving revision 1.3.4.2
diff -u -p -r1.3.4.2 radioactivity_node.install
--- plugins/radioactivity_node.install	24 Jan 2010 21:32:51 -0000	1.3.4.2
+++ plugins/radioactivity_node.install	21 Jun 2010 09:46:21 -0000
@@ -76,6 +76,7 @@ function radioactivity_node_install() {
 function radioactivity_node_uninstall() {
   drupal_uninstall_schema('radioactivity_node');
   variable_del('radioactivity_node_click_duration');
+  variable_del('radioactivity_node_anon_hook_mode');
   if (db_table_exists('radioactivity')) {
     db_query("DELETE FROM {radioactivity} WHERE class='node'");
   }
Index: plugins/radioactivity_node.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/radioactivity/plugins/radioactivity_node.module,v
retrieving revision 1.4.4.6
diff -u -p -r1.4.4.6 radioactivity_node.module
--- plugins/radioactivity_node.module	24 Jan 2010 21:32:51 -0000	1.4.4.6
+++ plugins/radioactivity_node.module	21 Jun 2010 09:46:21 -0000
@@ -61,6 +61,11 @@ function radioactivity_node_menu() {
           'weight'  => 10,
           'type'    => MENU_LOCAL_TASK,
           'file'    => 'radioactivity_node-admin-ui.inc');
+  $items['radioactivity_node.php'] = array(
+    'page callback' => 'radioactivity_node_ajax_callback',
+    'type' => MENU_CALLBACK,
+    'access arguments' => array('access content')
+  );
   return $items;
 }
 
@@ -165,6 +170,12 @@ function radioactivity_node_comment(&$a1
 function radioactivity_node_exit() {
   drupal_bootstrap(DRUPAL_BOOTSTRAP_PATH);
 
+  global $user;
+
+  // We don't use this hook for anonymous users if hook_mode is not 'normal'. In other modes,
+  // other hooks are used, e.g., AJAX-hook for statically cached pages.
+  if ($user->uid == 0 && variable_get('radioactivity_node_anon_hook_mode', 'normal') != 'normal') return;
+
   // we're only interested in full page views
   if ((arg(0) == 'node') && is_numeric(arg(1)) && arg(2) == '') {
     radioactivity_node_user_node_view(arg(1));
@@ -180,3 +191,104 @@ function radioactivity_node_views_handle
                array('radioactivity_node_views_handler_sort_left_or_inner' =>
                      array('parent' => 'views_handler_sort')));
 }
+
+/**
+ * Implementation of hook_block().
+ *
+ * @see boost_block()
+ */
+function radioactivity_node_block($op = 'list', $delta = 0, $edit = array()) {
+  global $user;
+
+  switch ($op) {
+    case 'list':
+      return array(
+        0 => array(
+          'info'   => t('Radioactivity Node: AJAX update'),
+          'cache'  => BLOCK_NO_CACHE,
+        ),
+      );
+
+    case 'view':
+      switch ($delta) {
+        case 0:
+          if (!( strpos($_SERVER['SCRIPT_FILENAME'], 'index.php') === FALSE
+              || variable_get('site_offline', 0)
+              || ($_SERVER['REQUEST_METHOD'] != 'GET' && $_SERVER['REQUEST_METHOD'] != 'HEAD')
+              || $_SERVER['SERVER_SOFTWARE'] === 'PHP CLI'
+              || isset($_GET['nocache'])
+              || !empty($user->uid)
+              || variable_get('radioactivity_node_anon_hook_mode', '') != 'ajax'
+              )) {
+            $block = array();
+            $block['subject'] = '';
+            $block['content'] = '<div id="node-radioactivity-update"></div>' . radioactivity_node_ajax_code();
+            return $block;
+          }
+          break;
+      }
+  }
+}
+
+/**
+ * AJAX Menu Callback.
+ */
+function radioactivity_node_ajax_callback() {
+  if (!isset($_GET['nid'])) {
+    return drupal_not_found();
+  }
+  $nid = isset($_GET['nid']) ? $_GET['nid'] : NULL;
+
+  if (!isset($_GET['js'])) {
+    header('Content-type: image/gif');
+    header('Expires: Sun, 19 Nov 1978 05:00:00 GMT');
+    header('Cache-Control: no-cache');
+    header('Cache-Control: must-revalidate');
+    header('Content-Length: 0');
+    header('Connection: close');
+  }
+
+  // Silent ignore if the mode is not ajax. Also, check that nid is numeric and >0.
+  if (variable_get('radioactivity_node_anon_hook_mode', '') == 'ajax' &&
+      is_numeric($nid) && $nid) {
+    radioactivity_node_user_node_view($nid);
+  }
+}
+
+/**
+ * Generate js/html for radioactivity counter.
+ *
+ * NOTE HTML code could be added to the $buffer directly. Would prevent 2x
+ * counts on first view. Would be hard to do though.
+ *
+ * @see boost_stats_generate()
+ */
+function radioactivity_node_ajax_code() {
+  global $base_path;
+
+  // is node & node count enabled.
+  if (arg(0) == 'node' && is_numeric(arg(1)) && arg(2) == '') {
+    $nid = arg(1);
+  }
+  else {
+    $nid = 'NULL';
+  }
+
+  $page_js = array(
+    'radioactivity_node' => array(
+      'nid' => $nid
+    )
+  );
+  $site_js = <<<ETO
+$.get(Drupal.settings.basePath + "radioactivity_node.php", {nocache: "1", js: "1", nid: Drupal.settings.radioactivity_node.nid}, function(response) {});
+ETO;
+
+  // page specific variables
+  drupal_add_js($page_js, 'setting', 'header');
+  // site-wide code
+  drupal_add_js($site_js, 'inline', 'footer');
+  // no script code
+  $page_ns = '<noscript><div style="display:inline;"><img src="' . $base_path . 'radioactivity_node.php' . '?nocache=1' . '&amp;nid='. $nid .'" alt="" /></div></noscript>';
+
+  return $page_ns;
+}
