You are here

class views_accordion_style_plugin in Views Accordion 7

Same name and namespace in other branches
  1. 6 views_accordion_style_plugin.inc \views_accordion_style_plugin

Implements views_plugin_style().

Hierarchy

Expanded class hierarchy of views_accordion_style_plugin

1 string reference to 'views_accordion_style_plugin'
views_accordion_views_plugins in ./views_accordion.views.inc
Implements hook_views_plugin().

File

./views_accordion_style_plugin.inc, line 10
Provide an accordion style plugin for Views. This file is autoloaded by views.

View source
class views_accordion_style_plugin extends views_plugin_style {

  /**
   * Whether or not jquery is higher than 1.9.
   *
   * Accordion options format changed for jquery >= 1.9
   *
   * @var bool
   */
  public $newoptions;

  /**
   * {@inheritdoc}
   */
  public function init(&$view, &$display, $options = NULL) {
    parent::init($view, $display, $options);
    $this->newoptions = FALSE;
    if (module_exists('jquery_update')) {
      $this->newoptions = version_compare(variable_get('jquery_update_jquery_version', '1.10'), '1.9', '>=');
    }
  }

  /**
   * Set default options.
   */
  public function option_definition() {
    $options = parent::option_definition();
    $options['use-grouping-header'] = array(
      'default' => 0,
    );
    $options['collapsible'] = array(
      'default' => 0,
    );
    $options['row-start-open'] = array(
      'default' => 0,
    );
    $options['animated'] = array(
      'default' => 'slide',
    );
    $options['animation_time'] = array(
      'default' => 300,
    );
    $options['autoheight'] = array(
      'default' => 1,
    );
    $options['event'] = array(
      'default' => 'click',
    );
    $options['fillspace'] = array(
      'default' => 0,
    );
    $options['navigation'] = array(
      'default' => 0,
    );
    $options['clearstyle'] = array(
      'default' => 0,
    );
    $options['disableifone'] = array(
      'default' => 0,
    );

    /*
     * @TODO:
     * 1. Figure out if/how to provide support for jQuery UI themes
     *    See http://drupal.org/node/388384 perhaps
     * 2. Provide support for missing accordion options:
     *    disabled
     *    icons
     *    navigationFilter
     * See http://jqueryui.com/demos/accordion/
     */
    return $options;
  }

  /**
   * {@inheritdoc}
   */
  public function options_form(&$form, &$form_state) {
    parent::options_form($form, $form_state);
    $form['grouping']['#prefix'] = '<div class="form-item">' . t('<strong>IMPORTANT:</strong> The <em>first field</em> in order of appearance <em>will</em> be the one used as the "header" or "trigger" of the accordion action.') . '</div>';

    // Available valid options for grouping (used for use-grouping-header
    // #dependency).
    $options = array();
    foreach ($this->display->handler
      ->get_handlers('field') as $field => $handler) {
      $options[] = $field;
    }

    // Find out how many items the display is currently configured to show
    // (row-start-open).
    $maxitems = $this->display->handler
      ->get_option('items_per_page');

    // If items_per_page is set to unlimitted (0), 10 rows will be what the user
    // gets to choose from.
    $maxitems = $maxitems == 0 ? 10 : $maxitems;

    // Setup our array of options for choosing which row should start opened
    // (row-start-open).
    $rsopen_options = array();
    for ($i = 1; $i <= $maxitems; $i++) {
      $rsopen_options[] = t('Row') . $i;
    }
    $rsopen_options['none'] = t('None');
    $rsopen_options['random'] = t('Random');

    // The easing effects from jQuery UI.
    $animated_options = array(
      'none' => t('None'),
      'slide' => t('Slide'),
      'swing' => t('Swing'),
      'linear' => t('Linear'),
      'bounceslide' => t('Bounceslide'),
      'easeInQuart' => t('easeInQuart'),
      'easeOutQuart' => t('easeOutQuart'),
      'easeInOutQuart' => t('easeInOutQuart'),
      'easeInExpo' => t('easeInExpo'),
      'easeOutExpo' => t('easeOutExpo'),
      'easeInOutExpo' => t('easeInOutExpo'),
      'easeInBack' => t('easeInBack'),
      'easeOutBack' => t('easeOutBack'),
      'easeInOutBack' => t('easeInOutBack'),
      'easeInQuad' => t('easeInQuad'),
      'easeOutQuad' => t('easeOutQuad'),
      'easeInOutQuad' => t('easeInOutQuad'),
      'easeInQuint' => t('easeInQuint'),
      'easeOutQuint' => t('easeOutQuint'),
      'easeInOutQuint' => t('easeInOutQuint'),
      'easeInCirc' => t('easeInCirc'),
      'easeOutCirc' => t('easeOutCirc'),
      'easeInOutCirc' => t('easeInOutCirc'),
      'easeInBounce' => t('easeInBounce'),
      'easeOutBounce' => t('easeOutBounce'),
      'easeInOutBounce' => t('easeInOutBounce'),
      'easeInCubic' => t('easeInCubic'),
      'easeOutCubic' => t('easeOutCubic'),
      'easeInOutCubic' => t('easeInOutCubic'),
      'easeInSine' => t('easeInSine'),
      'easeOutSine' => t('easeOutSine'),
      'easeInOutSine' => t('easeInOutSine'),
      'easeInElastic' => t('easeInElastic'),
      'easeOutElastic' => t('easeOutElastic'),
      'easeInOutElastic' => t('easeInOutElastic'),
    );
    if ($this->newoptions) {

      // Slide easing was removed from jQuery UI.
      unset($animated_options['slide']);
      unset($animated_options['bounceslide']);
    }
    $form['use-grouping-header'] = array(
      '#type' => 'checkbox',
      '#title' => t('Use the group header as the Accordion header'),
      '#default_value' => $this->options['use-grouping-header'],
      '#description' => t("If checked, the Group's header will be used to open/close the accordion."),
      '#dependency' => array(
        'edit-style-options-grouping' => $options,
      ),
    );
    $form['row-start-open'] = array(
      '#type' => 'select',
      '#title' => t('Row to display opened on start'),
      '#default_value' => $this->options['row-start-open'],
      '#description' => t('Choose which row should start opened when the accordion first loads. If you want all to start closed, choose "None", and make sure to have "Allow for all rows to be closed" on below.'),
      '#options' => $rsopen_options,
    );
    $form['collapsible'] = array(
      '#type' => 'checkbox',
      '#title' => t('Allow for all rows to be closed'),
      '#default_value' => $this->options['collapsible'],
      '#description' => t('If you check this on, when the user clicks on an opened item, it will close.'),
    );
    $form['animated'] = array(
      '#type' => 'select',
      '#title' => t('Animation effect'),
      '#default_value' => $this->options['animated'],
      '#description' => t('Choose what animation effect you would like to see, or "None" to disable it.'),
      '#options' => $animated_options,
    );

    // Animate duration only available from jquery >= 1.9.
    if ($this->newoptions) {
      $form['animation_time'] = array(
        '#type' => 'textfield',
        '#title' => t('Animation time'),
        '#default_value' => $this->options['animation_time'],
        '#description' => t('The animation duration in milliseconds'),
        '#element_validate' => array(
          'views_element_validate_integer',
        ),
      );
    }
    $form['autoheight'] = array(
      '#type' => 'checkbox',
      '#title' => t('Autoheight'),
      '#default_value' => $this->options['autoheight'],
      '#description' => t('If set, the highest content part is used as height reference for all other parts. Provides more consistent animations.'),
    );
    $form['event'] = array(
      '#type' => 'select',
      '#title' => t('Event'),
      '#default_value' => $this->options['event'],
      '#description' => t('The event on which to trigger the accordion.'),
      '#options' => array(
        'click' => t('Click'),
        'mouseover' => t('Mouseover'),
      ),
    );
    $form['fillspace'] = array(
      '#type' => 'checkbox',
      '#title' => t('Fillspace'),
      '#default_value' => $this->options['fillspace'],
      '#description' => t('If set, the accordion completely fills the height of the parent element. Overrides autoheight.'),
    );
    $form['navigation'] = array(
      '#type' => 'checkbox',
      '#title' => t('Navigation'),
      '#default_value' => $this->options['navigation'],
      '#description' => t('If set, looks for the anchor that matches location.href and activates it. Great for href-based state-saving. Use navigationFilter to implement your own matcher.'),
    );
    $form['clearstyle'] = array(
      '#type' => 'checkbox',
      '#title' => t('Clearstyle'),
      '#default_value' => $this->options['clearstyle'],
      '#description' => t("If set, clears height and overflow styles after finishing animations. This enables accordions to work with dynamic content. Won't work together with autoHeight."),
    );
    $form['disableifone'] = array(
      '#type' => 'checkbox',
      '#title' => t('Disable if only one result'),
      '#default_value' => $this->options['disableifone'],
      '#description' => t("If set, the accordion will not be shown when there are less than 2 results."),
    );
  }

  /**
   * Necessary to prevent markup mayhem.
   */
  public function pre_render($result) {
    drupal_add_library('system', 'ui.accordion');
    drupal_add_js(drupal_get_path('module', 'views_accordion') . '/views-accordion.js');

    // No need do anything if we are using the grouped field as the header.
    if ($this->options['use-grouping-header']) {
      return;
    }

    // Find out about the header field options.
    $fields = array_values($this->display->handler
      ->get_option('fields'));
    $header_class = 'views-accordion-header';

    // Add header class to first not-excluded field.
    foreach ($fields as $field) {
      if (!isset($field['exclude']) || $field['exclude'] == 0) {

        // Setup our wrapper class.
        // If the user configured its own class, set that up with our own class.
        if (!empty($field['element_wrapper_class'])) {
          $header_wrapper_class = $field['element_wrapper_class'] . ' ' . $header_class;
        }
        else {
          $header_wrapper_class = $header_class;
        }

        // Setup the view to use our processed wrapper class.
        $this->view->field[$field['id']]->options['element_wrapper_class'] = $header_wrapper_class;

        // Make sure we are using a div for markup at least.
        if (empty($field['element_wrapper_type'])) {
          $this->view->field[$field['id']]->options['element_wrapper_type'] = 'div';
        }
        break;
      }
    }
  }

  /**
   * Render the display in this style.
   */
  public function render() {
    $output = parent::render();
    if ($this->options['disableifone'] == '1') {
      if (count($this->rendered_fields) < 2) {
        return $output;
      }
    }

    // Add the appropriate effect library if necessary.
    $effect = $this->options['animated'];
    if ($effect !== 'none' && $effect !== 'slide') {

      // For now we only use ui core effects library, which provides the easing
      // effects.This switch is left here in case we actualy need to load any
      // other libraries.
      switch ($effect) {
        default:
          $library = 'effects';
          break;
      }
      if (isset($library)) {
        drupal_add_library('system', 'effects');
      }
    }

    // Preparing the js variables and adding the js to our display
    // we do it here so we dont have it run once every group.
    $view_settings['collapsible'] = $this->options['collapsible'];
    if ($this->options['row-start-open'] == 'random') {
      $view_settings['rowstartopen'] = 'random';
    }
    else {
      $view_settings['rowstartopen'] = $this->options['row-start-open'] == 'none' ? FALSE : (int) $this->options['row-start-open'];
    }
    $view_settings['animated'] = $this->options['animated'] == 'none' ? FALSE : $this->options['animated'];
    $view_settings['duration'] = (int) $this->options['animation_time'];
    $view_settings['autoheight'] = $this->options['autoheight'];
    $view_settings['event'] = $this->options['event'];
    $view_settings['fillspace'] = $this->options['fillspace'];
    $view_settings['navigation'] = $this->options['navigation'];
    $view_settings['clearstyle'] = $this->options['clearstyle'];
    $view_settings['grouping'] = $this->options['grouping'] ? 1 : 0;
    $view_settings['display'] = $this->view->current_display;
    $view_settings['viewname'] = $this->view->name;
    $view_settings['usegroupheader'] = $view_settings['grouping'] ? $this->options['use-grouping-header'] : 0;
    $accordion_id = 'views-accordion-' . $this->view->name . '-' . $this->view->current_display;
    if ($view_settings['usegroupheader'] == 1) {
      $view_settings['header'] = 'h3.' . $accordion_id . '-header';
    }

    // Used to get the first field to be used as the accordion header.
    if ($view_settings['usegroupheader'] == 0) {
      $view_settings['header'] = '.views-accordion-header';
    }

    // Use new options format if jquery_update has installed a version >= 1.9.
    $view_settings['newoptions'] = $this->newoptions;
    drupal_add_js(array(
      'views_accordion' => array(
        $accordion_id => $view_settings,
      ),
    ), 'setting');
    return $output;
  }

  /**
   * {@inheritdoc}
   */
  public function validate() {
    $errors = parent::validate();
    if ($this->display->handler
      ->get_option('row_plugin') !== 'fields') {
      $row_plugin = $this->display->handler
        ->get_plugin('row');
      $errors[] = t('Views accordion requires Fields as row style, but the view <em>@view_name</em> is configured with <em>@row_plugin_title</em> as a row style.', array(
        '@view_name' => $this->view->name,
        '@row_plugin_title' => $row_plugin->definition['title'],
      ));
    }
    return $errors;
  }

}

Members

Namesort descending Modifiers Type Description Overrides
views_accordion_style_plugin::$newoptions public property Whether or not jquery is higher than 1.9.
views_accordion_style_plugin::init public function Initialize a style plugin. Overrides views_plugin_style::init
views_accordion_style_plugin::options_form public function Provide a form to edit options for this plugin. Overrides views_plugin_style::options_form
views_accordion_style_plugin::option_definition public function Set default options. Overrides views_plugin_style::option_definition
views_accordion_style_plugin::pre_render public function Necessary to prevent markup mayhem. Overrides views_plugin_style::pre_render
views_accordion_style_plugin::render public function Render the display in this style. Overrides views_plugin_style::render
views_accordion_style_plugin::validate public function Validate that the plugin is correct and can be saved. Overrides views_plugin_style::validate
views_object::$definition public property Handler's definition.
views_object::$options public property Except for displays, options for the object will be held here. 1
views_object::altered_option_definition function Collect this handler's option definition and alter them, ready for use.
views_object::construct public function Views handlers use a special construct function. 4
views_object::export_option public function 1
views_object::export_options public function
views_object::export_option_always public function Always exports the option, regardless of the default value.
views_object::options Deprecated public function Set default options on this object. 1
views_object::set_default_options public function Set default options.
views_object::set_definition public function Let the handler know what its full definition is.
views_object::unpack_options public function Unpack options over our existing defaults, drilling down into arrays so that defaults don't get totally blown away.
views_object::unpack_translatable public function Unpack a single option definition.
views_object::unpack_translatables public function Unpacks each handler to store translatable texts.
views_object::_set_option_defaults public function
views_plugin::$display public property The current used views display.
views_plugin::$plugin_name public property The plugin name of this plugin, for example table or full.
views_plugin::$plugin_type public property The plugin type of this plugin, for example style or query.
views_plugin::$view public property The top object of a view. Overrides views_object::$view 1
views_plugin::additional_theme_functions public function Provide a list of additional theme functions for the theme info page.
views_plugin::options_submit public function Handle any special handling on the validate form. 9
views_plugin::plugin_title public function Return the human readable name of the display.
views_plugin::summary_title public function Returns the summary of the settings in the display. 8
views_plugin::theme_functions public function Provide a full list of possible theme templates used by this style.
views_plugin_style::$row_plugin public property The row plugin, if it's initialized and the style itself supports it.
views_plugin_style::$row_tokens public property Store all available tokens row rows.
views_plugin_style::build_sort public function Called by the view builder to see if this style handler wants to interfere with the sorts. If so it should build; if it returns any non-TRUE value, normal sorting will NOT be added to the query. 1
views_plugin_style::build_sort_post public function Called by the view builder to let the style build a second set of sorts that will come after any other sorts in the view. 1
views_plugin_style::destroy public function Destructor. Overrides views_object::destroy
views_plugin_style::even_empty public function Should the output of the style plugin be rendered even if it's empty. 1
views_plugin_style::get_field public function Get a rendered field.
views_plugin_style::get_field_value public function Get the raw field value.
views_plugin_style::get_row_class public function Return the token replaced row class for the specified row.
views_plugin_style::options_validate public function Validate the options form. Overrides views_plugin::options_validate
views_plugin_style::query public function Add anything to the query that we might need to. Overrides views_plugin::query 2
views_plugin_style::render_fields public function Render all of the fields for a given style and store them on the object.
views_plugin_style::render_grouping public function Group records as needed for rendering.
views_plugin_style::render_grouping_sets public function Render the grouping sets.
views_plugin_style::tokenize_value public function Take a value and apply token replacement logic to it.
views_plugin_style::uses_fields public function Return TRUE if this style also uses fields.
views_plugin_style::uses_row_class public function Return TRUE if this style also uses a row plugin.
views_plugin_style::uses_row_plugin public function Return TRUE if this style also uses a row plugin.
views_plugin_style::uses_tokens public function Return TRUE if this style uses tokens.