diff --git a/fullcalendar.module b/fullcalendar.module
index fb8c83e..949982d 100644
--- a/fullcalendar.module
+++ b/fullcalendar.module
@@ -131,6 +131,8 @@ function fullcalendar_menu() {
     'description' => 'Get events from views with arguments',
     'page callback' => 'fullcalendar_results',
     'access arguments' => array('access content'),
+    'delivery callback' => 'ajax_deliver',
+    'theme callback' => 'ajax_base_page_theme',
     'type' => MENU_CALLBACK,
   );
 
@@ -234,44 +236,43 @@ function fullcalendar_form_views_ui_edit_display_form_alter(&$form, &$form_state
  * Returns events for FullCalendar.
  */
 function fullcalendar_results($view_name = NULL, $view_display = NULL, $args = NULL) {
-  $content = NULL;
-
   // Bail out if no view_name or view_display is passed.
-  if (empty($view_name) && empty($view_display)) {
+  if (empty($view_name) || empty($view_display) || empty($_POST['dom_id'])) {
     return;
   }
 
-  // Get the view and check access.
-  $view = views_get_view($view_name);
-  if ($view && $view->access($view_display)) {
+  $dom_id = check_plain($_POST['dom_id']);
+  $view_name = check_plain($view_name);
+  $view_display = check_plain($view_display);
 
-    $view->set_display($view_display);
+  // Add all $_POST data, because AJAX is always a post and many things,
+  // such as tablesorts, exposed filters and paging assume $_GET.
+  $_GET += $_POST;
 
-    // Add arguments.
-    if (!empty($args)) {
-      $args = explode('|', $args);
-      $view->set_arguments($args);
-    }
-
-    // Execute the display and render results
-    // if available into $content variable.
-    $view->preview($view_display);
-    if (!empty($view->result)) {
-      $view->fullcalendar_ajax = TRUE;
-      $content = theme('fullcalendar', array('view' => $view, 'rows' => $view->result, 'options' => $view->style_options));
-    }
+  // Get the view and check access.
+  $view = views_get_view($view_name);
+  if (!$view || !$view->access($view_display)) {
+    return;
   }
 
-  drupal_add_http_header('Content-Type', 'text/javascript; charset=utf-8');
-  print drupal_json_encode(array(
-    'status' => TRUE,
-    'content' => $content,
-  ));
+  if (!$view->set_display($view_display)) {
+    return;
+  }
 
-  // Let's call drupal_page_footer(), so even page cache can work.
-  drupal_page_footer();
+  $view->dom_id = str_replace('.view-dom-id-', '', $dom_id);
+  $view->fullcalendar_ajax = TRUE;
+  $view->pre_execute();
+  $view->init_style();
+  $view->execute($view_display);
+  $output = $view->style_plugin->render();
+  $view->post_execute();
 
-  exit();
+  return array(
+    '#type' => 'ajax',
+    '#commands' => array(
+      array('command' => 'fullcalendar_results_response', 'data' => $output),
+    ),
+  );
 }
 
 /**
diff --git a/includes/fullcalendar.fullcalendar.inc b/includes/fullcalendar.fullcalendar.inc
index 288f17e..b45f435 100644
--- a/includes/fullcalendar.fullcalendar.inc
+++ b/includes/fullcalendar.fullcalendar.inc
@@ -500,13 +500,6 @@ function fullcalendar_fullcalendar_options_process(&$variables, &$settings) {
     'view_display' => $view->current_display,
   );
 
-  // Check if there is an argument which is an instance the default
-  // date argument class and create month, year variables as well as next
-  // and previous urls from all arguments.
-  if (!empty($view->argument) && $view->use_ajax) {
-    $settings += fullcalendar_check_arguments($view);
-  }
-
   // Add JS and CSS files.
   $variables['element']['#attached'] = array(
     'library' => array(
@@ -521,6 +514,10 @@ function fullcalendar_fullcalendar_options_process(&$variables, &$settings) {
     ),
   );
 
+  if (!empty($settings['ajax'])) {
+    $variables['element']['#attached']['js'][] = ctools_attach_js('fullcalendar.ajax', 'fullcalendar');
+  }
+
   // Add CSS and JS for each option plugin that provides it.
   fullcalendar_include_api();
   $weights = array();
@@ -656,51 +653,3 @@ function fullcalendar_fullcalendar_options_pre_view(&$settings, &$view) {
   // Change month to zero-based.
   $settings['date']['month']--;
 }
-
-/**
- * Override date settings when using FullCalendar AJAX pager.
- *
- * Check arguments on a view. If a date handler is found, add more
- * info to the $settings array so we know in jQuery we can fetch
- * new data from the view.
- *
- * @param object $view
- *   The current view we're processing.
- *
- * @return array
- *   A collection of extra settings.
- */
-function fullcalendar_check_arguments($view) {
-  $date_handler = NULL;
-  $args = array();
-  $settings = array('ajax' => FALSE);
-
-  $position = 0;
-  foreach ($view->argument as $argument_key => $handler) {
-    if (date_views_handler_is_date($handler, 'argument')) {
-      $date_handler = $handler;
-      $args[] = 'fullcalendar_browse';
-    }
-    else {
-      $args[] = $view->args[$position];
-    }
-    $position++;
-  }
-
-  if ($date_handler) {
-    $date_range = explode('--', $date_handler->argument);
-    $timestamp = strtotime($date_range[0] . " +1 month");
-
-    // Add ajax for date argument.
-    $settings['args'] = implode('|', $args);
-    $settings['ajax'] = TRUE;
-
-    // Settings for FullCalendar.
-    $month = date('n', $timestamp);
-    $year = date('Y', $timestamp);
-    $settings['date']['month'] = $month - 1;
-    $settings['date']['year'] = $year;
-  }
-
-  return $settings;
-}
diff --git a/includes/views/fullcalendar.views.inc b/includes/views/fullcalendar.views.inc
index 3199312..4f14d14 100644
--- a/includes/views/fullcalendar.views.inc
+++ b/includes/views/fullcalendar.views.inc
@@ -89,51 +89,68 @@ function fullcalendar_views_pre_view(&$view, &$display_id, &$args) {
     $function($settings, $view);
   }
 
-  // Set the new view settings.
-  $view->style_plugin->options = $settings;
+  $settings['ajax'] = FALSE;
 
   // If we're not using ajax, we're done.
   if (!$view->display_handler->get_option('use_ajax')) {
+    // Set the new view settings.
+    $view->style_plugin->options = $settings;
     return;
   }
 
-  // If a date is specifed to be the default find the range needed.
-  if (!empty($settings['date'])) {
-    $date_string = $settings['date']['year'] . '-' . $settings['date']['month'];
-    // The month value is zero-based, so use that for start and add 2 for end.
-    $start = date('Y-m', strtotime($date_string));
-    $end = date('Y-m', strtotime($date_string . ' +2 months'));
-    $range = $start . '--' . $end;
-  }
-  else {
-    $range = date('Y-m', strtotime('-1 month')) . '--' . date('Y-m', strtotime('+1 month'));
-  }
-
+  $settings['fullcalendar_fields_count'] = 0;
+  $exposed_input = $view->get_exposed_input();
   // Loop through each date field and provide an argument for it.
-  foreach ($view->display_handler->get_handlers('field') as $field) {
-    if (fullcalendar_field_is_date($field)) {
-      // Add an argument for the date field.
-      $options = array(
-        'default_action' => 'default',
-        'default_argument_type' => 'fixed',
-        'default_argument_options' => array(
-          'argument' => $range,
-        ),
-      );
-      if (!empty($field->options['relationship'])) {
-        $options['relationship'] = $field->options['relationship'];
-      }
-      $view->add_item($display_id, 'argument', 'field_data_' . $field->field, $field->field . '_value', $options);
-      $view->fullcalendar_args++;
+  foreach ($view->display_handler->get_handlers('field') as $field_id => $field) {
+    if (!fullcalendar_field_is_date($field)) {
+      continue;
+    }
+
+    $settings['ajax'] = TRUE;
+    // Add an exposed filter for the date field.
+    $field_value_id = $field->real_field . str_replace($field->field, '', $field_id);
+    if (isset($exposed_input[$field_value_id])) {
+      $timestamp = (strtotime($exposed_input[$field_value_id]['min']['date']) + strtotime($exposed_input[$field_value_id]['max']['date'])) / 2;
+      $min = date('Y-m', $timestamp);
+      $max = date('Y-m', strtotime($min . ' +1 month'));
     }
+    else {
+      $min = $settings['date']['year'] . '-' . ($settings['date']['month'] + 1);
+      $max = $settings['date']['year'] . '-' . ($settings['date']['month'] + 2);
+    }
+    $min = date('Y-m-d', strtotime($min . ' -2 weeks'));
+    $max = date('Y-m-d', strtotime($max . ' +2 weeks'));
+    $options = array(
+      'exposed' => TRUE,
+      'form_type' => 'date_text',
+      'operator' => 'between',
+      'default_date' => $min,
+      'default_to_date' => $max,
+      'group' => 0,
+    );
+    if (!empty($field->options['relationship'])) {
+      $options['relationship'] = $field->options['relationship'];
+    }
+    $option_id = $view->add_item($display_id, 'filter', 'field_data_' . $field->field, $field->field . '_value', $options);
+    $settings['fullcalendar_fields'][$option_id] = drupal_html_class($option_id);
+    $settings['fullcalendar_fields_count']++;
+    $view->set_item_option($display_id, 'filter', $option_id, 'expose', array('identifier' => $option_id, 'operator' => $option_id . '_op'));
+
+  }
+
+  if (isset($timestamp)) {
+    $settings['date']['date'] = date('d', $timestamp);
+    $settings['date']['month'] = date('n', $timestamp) - 1;
+    $settings['date']['year'] = date('Y', $timestamp);
   }
+
+  $view->style_plugin->options = $settings;
 }
 
 /**
  * Implements hook_views_query_alter().
  *
- * Force the query to be distinct. Also, if there are multiple date arguments,
- * group them with 'OR'.
+ * Force the query to be distinct.
  */
 function fullcalendar_views_query_alter(&$view, &$query) {
   if ($view->display_handler->get_option('style_plugin') != 'fullcalendar') {
@@ -141,23 +158,13 @@ function fullcalendar_views_query_alter(&$view, &$query) {
   }
 
   $query->distinct = TRUE;
+}
 
-  if (empty($view->fullcalendar_args) || count($view->args) < $view->fullcalendar_args) {
-    return;
-  }
-
-  // @todo Remove this once http://drupal.org/node/1367304 is resolved.
-  $query->group_operator = 'AND';
-
-  // Remove our arguments from the main set.
-  $arguments = array();
-  for ($i = 0; $i < $view->fullcalendar_args; $i++) {
-    $arguments[] = array_pop($query->where[0]['conditions']);
+/**
+ * Implements hook_views_ajax_data_alter().
+ */
+function fullcalendar_views_ajax_data_alter(&$commands, &$view) {
+  if ($view->display_handler->get_option('style_plugin') == 'fullcalendar') {
+    $commands = array();
   }
-  // Add them as a second set of conditions.
-  $query->where[] = array(
-    'conditions' => $arguments,
-    'args' => array(),
-    'type' => 'OR',
-  );
 }
diff --git a/js/fullcalendar.fullcalendar.js b/js/fullcalendar.fullcalendar.js
index ca959eb..4790a3a 100644
--- a/js/fullcalendar.fullcalendar.js
+++ b/js/fullcalendar.fullcalendar.js
@@ -7,6 +7,10 @@
 
 Drupal.fullcalendar.plugins.fullcalendar = {
   options: function (fullcalendar, settings) {
+    if (settings.ajax) {
+      fullcalendar.submitInit(settings);
+    }
+
     var options = {
       eventClick: function (calEvent, jsEvent, view) {
         if (settings.sameWindow) {
@@ -30,43 +34,19 @@ Drupal.fullcalendar.plugins.fullcalendar = {
         }
       },
       events: function (start, end, callback) {
-        // Fetch new items from Views if possible.
-        if (fullcalendar.navigate && settings.ajax) {
-          var prev_date, next_date, date_argument, argument, fetch_url;
-
-          prev_date = $.fullCalendar.formatDate(start, 'yyyy-MM-dd');
-          next_date = $.fullCalendar.formatDate(end, 'yyyy-MM-dd');
-          date_argument = prev_date + '--' + next_date;
-          argument = settings.args.replace('fullcalendar_browse', date_argument);
-          fetch_url = Drupal.settings.basePath + 'fullcalendar/ajax/results/' + settings.view_name + '/' + settings.view_display + '/' + argument;
-
-          $.ajax({
-            type: 'GET',
-            url: fetch_url,
-            dataType: 'json',
-            beforeSend: function () {
-              // Add a throbber.
-              this.progress = $('<div class="ajax-progress ajax-progress-throbber"><div class="throbber">&nbsp;</div></div>');
-              $(fullcalendar.dom_id + ' .fc-header-title').after(this.progress);
-            },
-            success: function (data) {
-              if (data.status) {
-                // Replace content.
-                $(fullcalendar.dom_id + ' .fullcalendar-content').html(data.content);
-                fullcalendar.parseEvents(callback);
-              }
-              // Remove the throbber.
-              $(this.progress).remove();
-            },
-            error: function (xmlhttp) {
-              alert(Drupal.t('An HTTP error @status occurred.', {'@status': xmlhttp.status}));
-            }
-          });
-        }
-        else {
-          fullcalendar.parseEvents(callback);
-        }
-
+       
+       if (settings.ajax && settings.fullcalendar_fields) {
+         fullcalendar.dateChange(settings.fullcalendar_fields);
+         if (fullcalendar.navigate) {
+           if (!fullcalendar.refetch) {
+             fullcalendar.fetchEvents();
+           }
+           fullcalendar.refetch = false;
+         }
+       }
+  
+       fullcalendar.parseEvents(callback);
+ 
         if (!fullcalendar.navigate) {
           // Add events from Google Calendar feeds.
           for (var entry in settings.gcal) {
diff --git a/js/fullcalendar.library.js b/js/fullcalendar.library.js
index 819e963..9624dad 100644
--- a/js/fullcalendar.library.js
+++ b/js/fullcalendar.library.js
@@ -17,6 +17,7 @@ Drupal.fullcalendar.fullcalendar = function (dom_id) {
   this.$calendar = $(dom_id);
   this.$options = {};
   this.navigate = false;
+  this.refetch = false;
 
   // Hide the failover display.
   $('.fullcalendar-content', this.$calendar).hide();
