? views-ajax.patch Index: views.module =================================================================== RCS file: /cvs/drupal/contributions/modules/views/views.module,v retrieving revision 1.231 diff -u -p -r1.231 views.module --- views.module 18 Mar 2008 15:52:39 -0000 1.231 +++ views.module 19 Mar 2008 05:09:53 -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,72 @@ function views_access($view, $account = } /** + * Menu callback to load a view via AJAX. + */ +function views_ajax() { + $name = $_REQUEST['view_name']; + $display_id = $_REQUEST['view_display_id']; + $path = $_REQUEST['view_path']; + 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. + $_GET['q'] = $path; + + $errors = $view->validate(); + if ($errors === TRUE) { + $object->status = TRUE; + $object->title = $view->get_title(); + $object->display .= $view->preview($display_id); + } + else { + foreach ($errors as $error) { + drupal_set_message($error, 'error'); + } + } + } + } + $messages = theme('status_messages'); + $object->messages = $messages ? '
'. $messages .'
' : ''; + + $data = views_ajax_data(); + $object->scripts = $data['scripts']; + $object->css = $data['css']; + + views_ajax_render($object); +} + +/** + * Return an array of data representing the scripts and CSS files on a page. + */ +function views_ajax_data() { + $return = array(); + $return['scripts'] = array(); + foreach (array('header', 'footer') as $scope) { + $javascript = drupal_add_js(NULL, NULL, $scope); + foreach ($javascript as $type => $data) { + if (!$data) { + unset($javascript[$type]); + } + elseif ($type == 'setting') { + $javascript[$type] = call_user_func_array('array_merge_recursive', $data); + } + } + $return['scripts'] = array_merge_recursive($return['scripts'], $javascript); + } + $return['css'] = drupal_add_css(); + return $return; +} + +/** * Set the current 'page view' that is being displayed so that it is easy * for other modules or the theme to identify. */ @@ -857,6 +931,9 @@ function views_exposed_form(&$form_state $form['#theme'] = views_theme_functions('views_exposed_form', $view, $display); + views_add_js('ajax_view'); + drupal_add_js('misc/jquery.form.js'); + return $form; } Index: js/ajax.js =================================================================== RCS file: /cvs/drupal/contributions/modules/views/js/ajax.js,v retrieving revision 1.9 diff -u -p -r1.9 ajax.js --- js/ajax.js 17 Mar 2008 21:43:04 -0000 1.9 +++ js/ajax.js 19 Mar 2008 05:09:57 -0000 @@ -1,11 +1,11 @@ // $Id: ajax.js,v 1.9 2008/03/17 21:43:04 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 19 Mar 2008 05:09:58 -0000 @@ -0,0 +1,123 @@ +// $Id: ajax.js,v 1.9 2008/03/17 21:43:04 merlinofchaos Exp $ +/** + * @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, data) { + + if (data.debug) { + alert(data.debug); + } + + // See if we have any settings to extend. Do this first so that behaviors + // can access the new settings easily. + + if (data.scripts.settings) { + $.extend(Drupal.settings, data.scripts.settings); + } + + // Check the 'display' for data. + if (data.status && data.display) { + var view = $(target).replaceWith(data.display).get(0); + Drupal.attachBehaviors(view); + Drupal.Views.Ajax.loadFiles(data, view); + } +}; + +/** + * Load JavaScript and CSS files. + */ +Drupal.Views.Ajax.loadFiles = function (data, target) { + // Handle scripts. + // TODO: handle inline scripts. + var types = ['core', 'module', 'theme']; + for (var i in types) { + for (var src in data.scripts[types[i]]) { + // Load scripts. + src = Drupal.settings.basePath + src; + // Test if the script already exists. + if (!$('script[@src*=' + src + ']').size()) { + $.getScript(src, function () { + Drupal.Views.Ajax.loadComplete(target); + }); + Drupal.settings.views.loadPending++; + } + } + } + // Handle stylesheets. + var types = ['module', 'theme']; + for (var media in data.css) { + for (var i in types) { + for (var src in data.css[media][types[i]]) { + src = Drupal.settings.basePath + src; + // Test if the stylesheet already exists. + if (!$('style:contains(' + src + ')').size()) { + $('').appendTo('head'); + } + } + } + } +}; + +/** + * When all scripts have loaded, attach behaviors. + */ +Drupal.Views.Ajax.loadComplete = function(target) { + Drupal.settings.views.loadPending--; + if (Drupal.settings.views.loadPending == 0) { + Drupal.attachBehaviors(target); + } +}; + +/** + * Ajax behavior for views. + */ +Drupal.behaviors.ViewsAjaxView = function() { + + $('form#views-exposed-form:not(.views-processed)') + .addClass('views-processed') + .each(function() { + var name; + var displayId; + var target = $(this).parents('.view').get(0); + // Parse view name and display id from the className. + var className = target.className.split(' '); + for (var i in className) { + if (className[i].indexOf('view-id-') == 0) { + name = className[i].substring(8); + } + if (className[i].indexOf('view-display-id-') == 0) { + displayId = className[i].substring(16); + } + } + if (name && displayId) { + $(this) + .append('') + .append('') + .append('') + .submit(function () { + $(this).ajaxSubmit({ + url: Drupal.settings.views.ajax_path, + type: 'GET', + success: function(data) { + Drupal.Views.Ajax.ajaxViewResponse(target, data); + }, + 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.3 diff -u -p -r1.3 base.js --- js/base.js 13 Feb 2008 06:30:37 -0000 1.3 +++ js/base.js 19 Mar 2008 05:09:58 -0000 @@ -5,9 +5,11 @@ Drupal.Views = {}; */ Drupal.behaviors.viewsTabs = function (context) { - $('#views-tabset:not(.views-processed)').addClass('views-processed').tabs({ - selectedClass: 'active' - }); + if ($.ui && $.ui.tabs) { + $('#views-tabset:not(.views-processed)').addClass('views-processed').tabs({ + selectedClass: 'active' + }); + } $('a.views-remove-link') .addClass('views-processed') Index: theme/theme.inc =================================================================== RCS file: /cvs/drupal/contributions/modules/views/theme/theme.inc,v retrieving revision 1.18 diff -u -p -r1.18 theme.inc --- theme/theme.inc 18 Mar 2008 16:20:38 -0000 1.18 +++ theme/theme.inc 19 Mar 2008 05:09:58 -0000 @@ -26,6 +26,10 @@ 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; + + // TODO: determine the correct display id. + $vars['display_id'] = 'default'; if (!$vars['rows']) { $vars['empty'] = $view->display_handler->render_empty(); @@ -56,6 +60,9 @@ function template_preprocess_views_view( $vars['pager'] = theme('pager', $view->exposed_input, $view->pager['items_per_page'], $view->pager['element']); } + $settings = array('views' => array('ajax_path' => url('views/ajax'), 'q' => $_GET['q'])); + + drupal_add_js($settings, 'setting'); } /** 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 19 Mar 2008 05:09:58 -0000 @@ -16,7 +16,7 @@ * @ingroup views_templates */ ?> -
+