Index: views.module
===================================================================
RCS file: /cvs/drupal/contributions/modules/views/views.module,v
retrieving revision 1.235
diff -u -p -r1.235 views.module
--- views.module	24 Mar 2008 20:26:23 -0000	1.235
+++ views.module	25 Mar 2008 17:57:07 -0000
@@ -107,6 +107,14 @@ function views_menu() {
     list($view, $display_id) = $data;
     $items += $view->execute_hook_menu($display_id);
   }
+  $items['views/ajax'] = array(
+    'title' => t('Views'),
+    'page callback' => 'views_ajax',
+    'access callback' => 'user_access',
+    'access arguments' => array('access content'),
+    'description' => t('Ajax callback for view loading.'),
+    'type' => MENU_CALLBACK,
+  );
   return $items;
 }
 
@@ -243,6 +251,55 @@ function views_access($view, $account = 
 }
 
 /**
+ * Menu callback to load a view via AJAX.
+ */
+function views_ajax() {
+  if (isset($_REQUEST['view_name']) && isset($_REQUEST['view_display_id'])) {
+    $name = $_REQUEST['view_name'];
+    $display_id = $_REQUEST['view_display_id'];
+    $args = isset($_REQUEST['view_args']) ? explode('/', $_REQUEST['view_args']) : array();
+    $path = isset($_REQUEST['view_path']) ? $_REQUEST['view_path'] : NULL;
+    views_include('ajax');
+    $object = new stdClass();
+
+    $object->status = FALSE;
+    $object->display = '';
+
+    // Load the view.
+    if ($v = views_get_view($name)) {
+      $view = drupal_clone($v);
+      if ($view->access($display_id)) {
+  
+        // Fix 'q' for paging.
+        if (!empty($path)) {
+          $_GET['q'] = $path;
+        }
+      
+        $errors = $view->validate();
+        if ($errors === TRUE) {
+          $object->status = TRUE;
+          $object->title = $view->get_title();
+          $object->display .= $view->preview($display_id, $args);
+        }
+        else {
+          foreach ($errors as $error) {
+            drupal_set_message($error, 'error');
+          }
+        }
+        // Register the standard JavaScript callback.
+        $object->__callbacks = array('Drupal.Views.Ajax.ajaxViewResponse');
+        // Allow other modules to extend the data returned.
+        drupal_alter('ajax_data', $object, 'views', $view);
+      }
+    }
+    $messages = theme('status_messages');
+    $object->messages = $messages ? '<div class="views-messages">'. $messages .'</div>' : '';
+
+    views_ajax_render($object);
+  }
+}
+
+/**
  * Set the current 'page view' that is being displayed so that it is easy
  * for other modules or the theme to identify.
  */
@@ -908,6 +965,10 @@ function views_exposed_form(&$form_state
 
   $form['#theme'] = views_theme_functions('views_exposed_form', $view, $display);
 
+  // If using AJAX, we need the form plugin.
+  if ($view->use_ajax) {
+    drupal_add_js('misc/jquery.form.js');
+  }
   views_add_js('dependent');
   return $form;
 }
Index: includes/plugins.inc
===================================================================
RCS file: /cvs/drupal/contributions/modules/views/includes/plugins.inc,v
retrieving revision 1.40
diff -u -p -r1.40 plugins.inc
--- includes/plugins.inc	21 Mar 2008 09:24:12 -0000	1.40
+++ includes/plugins.inc	25 Mar 2008 17:57:11 -0000
@@ -21,6 +21,7 @@ function views_views_plugins() {
         'no ui' => TRUE,
         'no remove' => TRUE,
         'js' => array('misc/collapse.js', 'misc/textarea.js', 'misc/tabledrag.js', "$path/dependent.js"),
+        'use ajax' => TRUE,
         'use pager' => TRUE,
       ),
       'page' => array(
@@ -28,6 +29,7 @@ function views_views_plugins() {
         'help' => t('Display the view as a page, with a URL and menu links.'),
         'handler' => 'views_plugin_display_page',
         'uses hook menu' => TRUE,
+        'use ajax' => TRUE,
         'use pager' => TRUE,
       ),
       'block' => array(
@@ -35,6 +37,7 @@ function views_views_plugins() {
         'help' => t('Display the view as a block.'),
         'handler' => 'views_plugin_display_block',
         'uses hook block' => TRUE,
+        'use ajax' => TRUE,
       ),
     ),
     'style' => array(
@@ -178,6 +181,16 @@ class views_plugin_display extends views
   }
 
   /**
+   * Does the display use AJAX?
+   */
+  function use_ajax() {
+    if (!empty($this->definition['use ajax'])) {
+      return $this->get_option('use_ajax');
+    }
+    return FALSE;
+  }
+
+  /**
    * Does the display have a pager enabled?
    */
   function use_pager() {
@@ -198,6 +211,7 @@ class views_plugin_display extends views
       'header' => array('header', 'header_format', 'header_empty'),
       'footer' => array('footer', 'footer_format', 'footer_empty'),
       'empty' => array('empty', 'empty_format'),
+      'use_ajax' => array('use_ajax'),
       'items_per_page' => array('items_per_page', 'offset', 'use_pager', 'pager_element'),
       'use_pager' => array('items_per_page', 'offset', 'use_pager', 'pager_element'),
       'link_display' => array('link_display'),
@@ -249,6 +263,7 @@ class views_plugin_display extends views
       'empty' => TRUE,
       'empty_format' => TRUE,
 
+      'use_ajax' => TRUE,
       'items_per_page' => TRUE,
       'offset' => TRUE,
       'use_pager' => TRUE,
@@ -442,6 +457,13 @@ class views_plugin_display extends views
         $options['row_plugin']['links']['row_options'] = t('Settings');
       }
     }
+    if (!empty($this->definition['use ajax'])) {
+      $options['use_ajax'] = array(
+        'category' => 'basic',
+        'title' => t('Use AJAX'),
+        'value' => $this->get_option('use_ajax') ? t('Yes') : t('No'),
+      );
+    }
 
     if (!empty($this->definition['use pager'])) {
       $options['use_pager'] = array(
@@ -575,6 +597,14 @@ class views_plugin_display extends views
           '#default_value' => $this->get_option('title'),
         );
         break;
+      case 'use_ajax':
+        $form['#title'] .= t('Use AJAX when available to load this view');
+        $form['use_ajax'] = array(
+          '#type' => 'radios',
+          '#options' => array(1 => t('Yes'), 0 => t('No')),
+          '#default_value' => $this->get_option('use_ajax'),
+        );
+        break;
       case 'use_pager':
         $form['#title'] .= t('Use a pager for this view');
         $form['use_pager'] = array(
@@ -793,6 +823,7 @@ class views_plugin_display extends views
       case 'access':
       case 'link_display':
       case 'php_arg_code':
+      case 'use_ajax':
         $this->set_option($section, $form_state['values'][$section]);
         break;
       case 'use_pager':
@@ -997,6 +1028,9 @@ class views_plugin_display extends views
    * overridden on an individual display.
    */
   function pre_execute() {
+    $this->view->set_use_ajax($this->use_ajax());
+    // TODO: remove this.
+    $this->view->set_use_ajax(1);
     // Copy pager information from the display.
     $this->view->set_use_pager($this->use_pager());
     $this->view->set_pager_element($this->get_option('pager_element'));
Index: includes/view.inc
===================================================================
RCS file: /cvs/drupal/contributions/modules/views/includes/view.inc,v
retrieving revision 1.56
diff -u -p -r1.56 view.inc
--- includes/view.inc	24 Mar 2008 20:26:24 -0000	1.56
+++ includes/view.inc	25 Mar 2008 17:57:14 -0000
@@ -27,6 +27,8 @@ class view extends views_db_object {
   var $args = array();
   var $build_info = array();
 
+  var $use_ajax = FALSE;
+
   // pager variables
   var $pager = array(
     'use_pager' => FALSE,
@@ -85,6 +87,13 @@ class view extends views_db_object {
   }
 
   /**
+   * Whether or not AJAX should be used.
+   */
+  function set_use_ajax($use_ajax) {
+    $this->use_ajax = $use_ajax;
+  }
+
+  /**
    * Whether or not the pager should be used.
    */
   function set_use_pager($use_pager) {
Index: js/ajax.js
===================================================================
RCS file: /cvs/drupal/contributions/modules/views/js/ajax.js,v
retrieving revision 1.10
diff -u -p -r1.10 ajax.js
--- js/ajax.js	21 Mar 2008 23:20:06 -0000	1.10
+++ js/ajax.js	25 Mar 2008 17:57:14 -0000
@@ -1,11 +1,11 @@
 // $Id: ajax.js,v 1.10 2008/03/21 23:20:06 merlinofchaos Exp $
 /**
-* @file ajax.inc
-*
-* Handles AJAX submission and response in Views UI.
-*/
+ * @file ajax_admin.js
+ *
+ * Handles AJAX submission and response in Views UI.
+ */
 
-Drupal.Views.Ajax = {};
+Drupal.Views.Ajax = Drupal.Views.Ajax || {};
 
 /**
  * Handles the simple process of setting the ajax form area with new data.
Index: js/ajax_view.js
===================================================================
RCS file: js/ajax_view.js
diff -N js/ajax_view.js
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ js/ajax_view.js	25 Mar 2008 17:57:15 -0000
@@ -0,0 +1,102 @@
+// $Id: $
+
+/**
+ * @file ajaxView.js
+ *
+ * Handles AJAX fetching of views, including filter submission and response.
+ */
+
+Drupal.Views.Ajax = Drupal.Views.Ajax || {};
+
+/**
+ * An ajax responder that accepts a packet of JSON data and acts appropriately.
+ *
+ * The following fields control behavior.
+ * - 'display': Display the associated data in the view area.
+ */
+Drupal.Views.Ajax.ajaxViewResponse = function(target, response) {
+
+  if (response.debug) {
+    alert(response.debug);
+  }
+
+  // Check the 'display' for data.
+  if (response.status && response.display) {
+    var view = $(target).replaceWith(response.display).get(0);
+    Drupal.attachBehaviors(view);
+  }
+};
+
+/**
+ * Ajax behavior for views. 
+ */
+Drupal.behaviors.ViewsAjaxView = function() {
+
+  if (Drupal.settings && Drupal.settings.views && Drupal.settings.views.ajaxViews) {
+    $.each(Drupal.settings.views.ajaxViews, function(i, settings) {
+      var target;
+      $('.view-id-'+ settings.view_name +'.view-display-id-'+ settings.view_display_id +':not(.views-processed)')
+        .addClass('views-processed')
+        .each(function () {
+          target = $(this).get(0);
+        })
+        // Process exposed filter forms.
+        .find('form#views-exposed-form')
+        .each(function () {
+          var form = this;
+          // ajaxSubmit doesn't accept a data argument, so we have to
+          // pass additional fields this way.
+          $.each(settings, function(key, setting) {
+            $(form).append('<input type="hidden" name="'+ key + '" value="'+ setting +'"/>');
+          });
+        })
+        .submit(function () {
+          $(this).ajaxSubmit({
+            url: Drupal.settings.views.ajax_path,
+            type: 'GET',
+            success: function(response) {
+              // Call all callbacks.
+              if (response.__callbacks) {
+                $.each(response.__callbacks, function(i, callback) {
+                  eval(callback)(target, response);
+                });
+              }
+            },
+            error: function() { alert("An error occurred"); },
+            dataType: 'json'
+          });
+  
+          return false;
+        })
+        .end()
+        // Process pager links.
+        .find('ul.pager > li > a')
+        .each(function () {
+          var viewData = Drupal.Views.parseQueryString($(this).attr('href'));
+          $.each(settings, function (key, setting) {
+            viewData.key = setting;
+          });
+          $(this)
+            .click(function () {
+              $.ajax({
+                url: Drupal.settings.views.ajax_path,
+                type: 'GET',
+                data: viewData,
+                success: function(response) {
+                  // Call all callbacks.
+                  if (response.__callbacks) {
+                    $.each(response.__callbacks, function(i, callback) {
+                      eval(callback)(target, response);
+                    });
+                  }
+                },
+                error: function() { alert("An error occurred"); },
+                dataType: 'json'
+              });
+
+              return false;
+            });
+        });
+    });
+  }
+};
\ No newline at end of file
Index: js/base.js
===================================================================
RCS file: /cvs/drupal/contributions/modules/views/js/base.js,v
retrieving revision 1.4
diff -u -p -r1.4 base.js
--- js/base.js	21 Mar 2008 23:20:06 -0000	1.4
+++ js/base.js	25 Mar 2008 17:57:15 -0000
@@ -3,7 +3,6 @@ Drupal.Views = {};
 /**
  * jQuery UI tabs, Views integration component
  */
-
 Drupal.behaviors.viewsTabs = function (context) {
   if ($.ui && $.ui.tabs) {
     $('#views-tabset:not(.views-processed)').addClass('views-processed').tabs({
@@ -20,3 +19,36 @@ Drupal.behaviors.viewsTabs = function (c
       return false;
     });
 }
+
+/**
+ * Helper function to parse a querystring.
+ */
+Drupal.Views.parseQueryString = function (query) {
+  var args = {};
+  var pos = query.indexOf('?');
+  if (pos != -1) {
+    query = query.substring(pos + 1);
+  }
+  var pairs = query.split('&');
+  for(var i in pairs) {
+    var pair = pairs[i].split('=');
+    // Ignore the 'q' path argument, if present.
+    if (pair[0] != 'q') {
+      args[pair[0]] = unescape(pair[1].replace(/\+/g, ' '));
+    }
+  }
+  return args;
+};
+
+/**
+ * Helper function to return the last portion of a class.
+ */
+Drupal.Views.getClassSuffix = function (elt, prefix) {
+  var className = elt.className.split(' ');
+  for (var i in className) {
+    if (className[i].indexOf(prefix) == 0) {
+      return className[i].substring(prefix.length);
+    }
+  }
+  return false;
+};
\ No newline at end of file
Index: theme/theme.inc
===================================================================
RCS file: /cvs/drupal/contributions/modules/views/theme/theme.inc,v
retrieving revision 1.19
diff -u -p -r1.19 theme.inc
--- theme/theme.inc	21 Mar 2008 23:20:06 -0000	1.19
+++ theme/theme.inc	25 Mar 2008 17:57:15 -0000
@@ -26,6 +26,8 @@ function template_preprocess_views_view(
 
   $vars['rows']       = $view->style_handler->render($view->result);
   $vars['css_name']   = views_css_safe($view->name);
+  $vars['name']       = $view->name;
+  $vars['display_id'] = $view->current_display;
 
   if (!$vars['rows']) {
     $vars['empty']    = $view->display_handler->render_empty();
@@ -56,6 +58,25 @@ function template_preprocess_views_view(
     $vars['pager']    = theme('pager', $view->exposed_input, $view->pager['items_per_page'], $view->pager['element']);
   }
 
+  // If using AJAX, send identifying data about this view.
+  if ($view->use_ajax) {
+    $settings = array(
+      'views' => array(
+        'ajax_path' => url('views/ajax'),
+        'ajaxViews' => array(
+          array(
+            'view_name' => $view->name,
+            'view_display_id' => $view->current_display,
+            'view_args' => implode('/', $view->args),
+            'view_path' => $_GET['q'],
+          ),
+        ),
+      ),
+    );
+
+    drupal_add_js($settings, 'setting');
+    views_add_js('ajax_view');
+  }
 }
 
 /**
Index: theme/views-view.tpl.php
===================================================================
RCS file: /cvs/drupal/contributions/modules/views/theme/views-view.tpl.php,v
retrieving revision 1.5
diff -u -p -r1.5 views-view.tpl.php
--- theme/views-view.tpl.php	20 Feb 2008 01:08:25 -0000	1.5
+++ theme/views-view.tpl.php	25 Mar 2008 17:57:15 -0000
@@ -16,7 +16,7 @@
  * @ingroup views_templates
  */
 ?>
-<div class="view view-<?php print $css_name; ?>">
+<div class="view view-<?php print $css_name; ?> view-id-<?php print $name; ?> view-display-id-<?php print $display_id; ?>">
   <?php if ($header): ?>
     <div class="view-header">
       <?php print $header; ?>
