diff --git a/includes/view.inc b/includes/view.inc index 4960cfe1484c7deebc24dcfdef0b825cf9bdf9e2..3837ffbfea13e5930a23c0cd07185935ca2dfde9 100644 --- a/includes/view.inc +++ b/includes/view.inc @@ -370,6 +370,42 @@ class view extends views_db_object { } } + /** + * Render the exposed filter form. + * + * This actually does more than that; because it's using FAPI, the form will + * also assign data to the appropriate handlers for use in building the + * query. + */ + function render_exposed_form($block = FALSE) { + // Deal with any exposed filters we may have, before building. + $form_state = array( + 'view' => &$this, + 'display' => &$this->display_handler->display, + 'method' => 'get', + 'rerender' => TRUE, + 'no_redirect' => TRUE, + ); + + // Some types of displays (eg. attachments) may wish to use the exposed + // filters of their parent displays instead of showing an additional + // exposed filter form for the attachment as well as that for the parent. + if (!$this->display_handler->displays_exposed() || (!$block && $this->display_handler->get_option('exposed_block'))) { + unset($form_state['rerender']); + } + + if (!empty($this->ajax)) { + $form_state['ajax'] = TRUE; + } + + $output = drupal_build_form('views_exposed_form', $form_state); + if (!empty($form_state['js settings'])) { + $this->js_settings = $form_state['js settings']; + } + + return $output; + } + /** * Build all the arguments. */ @@ -511,31 +547,9 @@ class view extends views_db_object { $this->_pre_query(); if ($this->display_handler->uses_exposed()) { - // Deal with any exposed filters we may have, before building. - $form_state = array( - 'view' => &$this, - 'display' => &$this->display_handler->display, - 'method' => 'get', - 'rerender' => TRUE, - 'no_redirect' => TRUE, - ); - - // Some types of displays (eg. attachments) may wish to use the exposed - // filters of their parent displays instead of showing an additional - // exposed filter form for the attachment as well as that for the parent. - if (!$this->display_handler->displays_exposed()) { - unset($form_state['rerender']); - } - - if (!empty($this->ajax)) { - $form_state['ajax'] = TRUE; - } - - $this->exposed_widgets = drupal_build_form('views_exposed_form', $form_state); - if (!empty($form_state['js settings'])) { - $this->js_settings = $form_state['js settings']; - } + $this->exposed_widgets = $this->render_exposed_form(); } + // Build all the relationships first thing. $this->_build('relationship'); diff --git a/js/ajax_view.js b/js/ajax_view.js index 1548a1cf7dd47929f587d8eaac84878a9ccbf584..fe08c739e6dcb3ec1ebfa74841444676abb5dea0 100644 --- a/js/ajax_view.js +++ b/js/ajax_view.js @@ -47,51 +47,56 @@ Drupal.behaviors.ViewsAjaxView = function() { } if (Drupal.settings && Drupal.settings.views && Drupal.settings.views.ajaxViews) { $.each(Drupal.settings.views.ajaxViews, function(i, settings) { - var $view = $('.view-dom-id-' + settings.view_dom_id); - if (!$view.size()) { + var view = '.view-dom-id-' + settings.view_dom_id; + if (!$(view).size()) { // Backward compatibility: if 'views-view.tpl.php' is old and doesn't // contain the 'view-dom-id-#' class, we fall back to the old way of // locating the view: - $view = $('.view-id-' + settings.view_name + '.view-display-id-' + settings.view_display_id); + view = '.view-id-' + settings.view_name + '.view-display-id-' + settings.view_display_id; } - $view.filter(':not(.views-processed)').each(function() { + + // Process exposed filter forms. + $('form#views-exposed-form-' + settings.view_name + '-' + settings.view_display_id) + .filter(':not(.views-processed)') + .each(function () { + // remove 'q' from the form; it's there for clean URLs + // so that it submits to the right place with regular submit + // but this method is submitting elsewhere. + $('input[name=q]', this).remove(); + 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(''); + }); + }) + .addClass('views-processed') + .submit(function () { + $('input[@type=submit]', this).after(' '); + var object = this; + $(this).ajaxSubmit({ + url: ajax_path, + type: 'GET', + success: function(response) { + // Call all callbacks. + if (response.__callbacks) { + $.each(response.__callbacks, function(i, callback) { + eval(callback)(view, response); + }); + $('.views-throbbing', object).remove(); + } + }, + error: function() { alert(Drupal.t("An error occurred at ") + ajax_path); $('.views-throbbing', object).remove(); }, + dataType: 'json' + }); + + return false; + }); + + $(view).filter(':not(.views-processed)').each(function() { var target = this; $(this) .addClass('views-processed') - // Process exposed filter forms. - .find('form#views-exposed-form') - .each(function () { - // remove 'q' from the form; it's there for clean URLs - // so that it submits to the right place with regular submit - // but this method is submitting elsewhere. - $('input[name=q]', this).remove(); - 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(''); - }); - }) - .submit(function () { - $('input[@type=submit]', this).after(' '); - $(this).ajaxSubmit({ - url: 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(Drupal.t("An error occurred at ") + ajax_path); }, - dataType: 'json' - }); - - return false; - }) - .end() // Process pager links. .find('ul.pager > li > a') .each(function () { diff --git a/modules/comment.views.inc b/modules/comment.views.inc index faa514ffb322fb6255c3cf0e2059ae3dac9c1d76..d5faa9e98d62d71dafecbb3f7e8c2dfef399edb2 100644 --- a/modules/comment.views.inc +++ b/modules/comment.views.inc @@ -469,7 +469,7 @@ function comment_views_handlers() { // argument handlers 'views_handler_filter_node_comment' => array( - 'parent' => 'views_handler_argument', + 'parent' => 'views_handler_filter_in_operator', ), 'views_handler_argument_comment_user_uid' => array( 'parent' => 'views_handler_argument', diff --git a/plugins/views_plugin_display.inc b/plugins/views_plugin_display.inc index 5dcb2a4f04f8eb6ce43d186f16f1156ee2e856f7..042594fed326ac89af151e91e583176b226b0912 100644 --- a/plugins/views_plugin_display.inc +++ b/plugins/views_plugin_display.inc @@ -158,6 +158,7 @@ class views_plugin_display extends views_plugin { 'use_more' => array('use_more'), 'link_display' => array('link_display'), 'distinct' => array('distinct'), + 'exposed_block' => array('exposed_block'), // Force these to cascade properly. 'style_plugin' => array('style_plugin', 'style_options', 'row_plugin', 'row_options'), @@ -228,6 +229,7 @@ class views_plugin_display extends views_plugin { 'pager_element' => TRUE, 'use_more' => TRUE, 'distinct' => TRUE, + 'exposed_block' => TRUE, 'link_display' => TRUE, @@ -336,6 +338,10 @@ class views_plugin_display extends views_plugin { 'row_options' => array( 'default' => array(), ), + + 'exposed_block' => array( + 'default' => FALSE, + ), ); if ($this->is_default_display()) { @@ -705,6 +711,13 @@ class views_plugin_display extends views_plugin { } } + $options['exposed_block'] = array( + 'category' => 'basic', + 'title' => t('Exposed form in block'), + 'value' => $this->get_option('exposed_block') ? t('Yes') : t('No'), + 'desc' => t('Allow the exposed form to appear in a block instead of the view.'), + ); + foreach (array('header' => t('Header'), 'footer' => t('Footer'), 'empty' => t('Empty text')) as $type => $name) { if (!$this->get_option($type)) { $field = t('None'); @@ -788,7 +801,7 @@ class views_plugin_display extends views_plugin { $form['use_ajax'] = array( '#type' => 'radios', '#options' => array(1 => t('Yes'), 0 => t('No')), - '#default_value' => $this->get_option('use_ajax'), + '#default_value' => $this->get_option('use_ajax') ? 1 : 0, ); break; case 'use_pager': @@ -1181,6 +1194,20 @@ class views_plugin_display extends views_plugin { ); $form_state['ok_button'] = TRUE; break; + + case 'exposed_block': + $form['#title'] .= t('Put the exposed form in a block'); + $form['description'] = array( + '#prefix' => '
', + '#suffix' => '
', + '#value' => t('If set, any exposed widgets will not appear with this view. Instead, a block will be made available to the Drupal block administration system, and the exposed form will appear there. Note that this block must be enabled manually, Views will not enable it for you.'), + ); + $form['exposed_block'] = array( + '#type' => 'radios', + '#options' => array(1 => t('Yes'), 0 => t('No')), + '#default_value' => $this->get_option('exposed_block') ? 1 : 0, + ); + break; } } @@ -1346,6 +1373,9 @@ class views_plugin_display extends views_plugin { $this->set_option($section . '_empty', $form_state['values'][$section . '_empty']); } break; + case 'exposed_block': + $this->set_option($section, (bool) $form_state['values'][$section]); + break; } } @@ -1614,6 +1644,37 @@ class views_plugin_display extends views_plugin { } return $errors; } + + /** + * Provide the block system with any exposed widget blocks for this display. + */ + function get_special_blocks() { + $delta = '$exp-' . $this->view->name . '-' . $this->display->id; + $desc = t('Exposed form: @view-@display_id', array('@view' => $this->view->name, '@display_id' => $this->display->id)); + + return array( + $delta => array( + 'info' => $desc, + ) + ); + } + + /** + * Render any special blocks provided for this display. + */ + function view_special_blocks($type) { + if ($type == '$exp') { + // avoid interfering with the admin forms. + if (arg(0) == 'admin' && arg(1) == 'build' && arg(2) == 'views') { + return; + } + $this->view->init_handlers(); + return array( + 'content' => $this->view->render_exposed_form(TRUE), + ); + } + } + } diff --git a/views.module b/views.module index d93c3d31c9d94c686633a89061c734c7bbaa5f7f..bbbdec920871466ac5181eccff95d8b4fb0b1146 100644 --- a/views.module +++ b/views.module @@ -280,12 +280,23 @@ function views_block($op = 'list', $delta = 0, $edit = array()) { switch ($op) { case 'list': $items = array(); - $views = views_get_applicable_views('uses hook block'); - foreach ($views as $data) { - list($view, $display_id) = $data; - $result = $view->execute_hook_block($display_id); - if (is_array($result)) { - $items = array_merge($items, $result); + $views = views_get_all_views(); + foreach ($views as $view) { + $view->init_display(); + foreach ($view->display as $display_id => $display) { + if (isset($display->handler) && !empty($display->handler->definition['uses hook block'])) { + $result = $display->handler->execute_hook_block(); + if (is_array($result)) { + $items = array_merge($items, $result); + } + } + + if (isset($display->handler) && $display->handler->get_option('exposed_block')) { + $result = $display->handler->get_special_blocks(); + if (is_array($result)) { + $items = array_merge($items, $result); + } + } } } @@ -308,8 +319,7 @@ function views_block($op = 'list', $delta = 0, $edit = array()) { variable_set('views_block_hashes', $hashes); // Save memory: Destroy those views. - foreach ($views as $data) { - list($view, $display_id) = $data; + foreach ($views as $view) { $view->destroy(); } @@ -324,6 +334,20 @@ function views_block($op = 'list', $delta = 0, $edit = array()) { } } + // This indicates it's a special one. + if (substr($delta, 0, 1) == '$') { + list($type, $name, $display_id) = explode('-', $delta); + if ($view = views_get_view($name)) { + if ($view->access($display_id)) { + $view->set_display($display_id); + if (isset($view->display_handler)) { + $output = $view->display_handler->view_special_blocks($type); + return $output; + } + } + } + } + list($name, $display_id) = explode('-', $delta); // Load the view if ($view = views_get_view($name)) { @@ -894,6 +918,8 @@ function views_exposed_form(&$form_state) { $form['#action'] = url($view->get_url()); $form['#theme'] = views_theme_functions('views_exposed_form', $view, $display); + $form['#id'] = views_css_safe('views_exposed_form-' . check_plain($view->name) . '-' . check_plain($display->id)); +// $form['#attributes']['class'] = array('views-exposed-form'); // If using AJAX, we need the form plugin. if ($view->use_ajax) {