Hi, I am running into the following problem:

I have a view with rows grouped by a field, which are NOT the accordion header. Clicking on the headers opens and closes the sections all right, but open sections aren't closed automatically when clicking to open closed sections.

When toggling either "Use the group header as the Accordion header" or as grouping field, the accordion works fine.

This may be due to some css styling of my own, but I have tried to reset that as much as possible, and I still can't find the solution.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Manuel Garcia’s picture

Category: bug » support
Status: Active » Closed (works as designed)

If you are using field grouping, and not using the field that's grouping the results, each resulting accordion is independent of the rest of the grouped results.

So if you have in one group an item opened, and you click on an item on another group, this doesn't affect the other group's opened item. this is by design.

If this is what you are seeing, this is not a bug. Again, it's hard to understand from just text what you mean, so if if this is not the case, please submit some screenshots which really help understand what's your problem.

kdebaas’s picture

Category: support » bug

What I meant is that clicking on items in each group does not affect other items in that same group. They stay open or closed. Sorry for being so unclear, I hope this time the description is clear enough?

Manuel Garcia’s picture

Status: Closed (works as designed) » Postponed (maintainer needs more info)

Thanks for clarifying kdebass
This works just fine on my testing install, both using the latest beta3 and the latest dev version. So far I've been unable to replicate your problem.

Please provide a screenshot of the view settings with the accordion settings expanded, so I can attempt to recreate your settings and replicate exactly your situation.

kdebaas’s picture

Status: Postponed (maintainer needs more info) » Active
FileSize
351.34 KB
254.61 KB

The second screenshot is of a page with a view on the right hand side. There are three groups: Lecture, Screening and Exhibition. In the group Screening, I have clicked on the first and then the second item, which leaves them both open. The page loads with only the first item in the first group opened.
Thanks for your time.

(The accordion headers display two fields, because I 'excluded' the first one and rewrote the second one etc... However, the problem with the groups was already there before I applied this 'trick')

Manuel Garcia’s picture

Your settings look ok, the only thing that I can think of that could be causing this, is that perhaps trying to group by Taxonomy: All Terms could cause weird results. Try using the field Taxonomy: Term to group by. Although I have tried your setup, in a block display, using Taxonomy: All Terms as the field to group by, and I still see no problems, so I don't know what's wrong.

Another thing to check out would be if it is also happening if you use the module's default styling.

Have you tried using the latest dev version of the module? -- though for me it's working fine in both beta3 and dev...

kdebaas’s picture

Since you don't seem to encounter the same behaviour in your test install, I went back to doublechecking what might be different between our setups. And I found it! I have wrapped my rows in an extra div, in the views-view-fields.tpl.php template, (i.e. views-view-fields--MyView.tpl.php) like so:

// $Id: views-view-fields.tpl.php,v 1.6 2008/09/24 22:48:21 merlinofchaos Exp $
/**
 * @file views-view-fields.tpl.php
 * Default simple view template to all the fields as a row.
 *
 * - $view: The view in use.
 * - $fields: an array of $field objects. Each one contains:
 *   - $field->content: The output of the field.
 *   - $field->raw: The raw data for the field, if it exists. This is NOT output safe.
 *   - $field->class: The safe class id to use.
 *   - $field->handler: The Views field handler object controlling this field. Do not use
 *     var_export to dump this object, as it can't handle the recursion.
 *   - $field->inline: Whether or not the field should be inline.
 *   - $field->inline_html: either div or span based on the above flag.
 *   - $field->separator: an optional separator that may appear before a field.
 * - $row: The raw result object from the query, with all data it fetched.
 *
 * @ingroup views_templates
 */
$node_type = "node-type-" . $row->node_type;

?>
<div class= "<?php print $node_type; ?>">
  <?php foreach ($fields as $id => $field): ?>
    <?php if (!empty($field->separator)): ?>
      <?php print $field->separator; ?>
    <?php endif; ?>
  
    <<?php print $field->inline_html;?> class="views-field-<?php print $field->class; ?>">
      <?php if ($field->label): ?>
        <label class="views-label-<?php print $field->class; ?>">
          <?php print $field->label; ?>:
        </label>
      <?php endif; ?>
        <?php
        // $field->element_type is either SPAN or DIV depending upon whether or not
        // the field is a 'block' element type or 'inline' element type.
        ?>
        <<?php print $field->element_type; ?> class="field-content"><?php print $field->content; ?></<?php print $field->element_type; ?>>
    </<?php print $field->inline_html;?>>
  <?php endforeach; ?>
</div>

When I take out my <div class="node-type-example> tags, Views-accordion behaves normally. I'm glad to have found the cause, but it isn't entirely clear to me why it should work like that. Is this simply a limitation I will have to work around? (I mean, will I have to try to find another way of tagging my views-rows by node-type?)

Cheers

Manuel Garcia’s picture

Category: bug » support

Right, that could throw off the js selectors in views_accordion...

I suggest you add the class to an existing default div that views prints out, not adding extra divs. Not sure why you want that or how you will use it, but that's the general advice lookin at what you are running into...

Problem lies in that you are wrapping the whole fields inside another div. I think you want to tag each row on its own, so go something like this:

<?php
// $Id: views-view-fields.tpl.php,v 1.6 2008/09/24 22:48:21 merlinofchaos Exp $
/**
* @file views-view-fields.tpl.php
* Default simple view template to all the fields as a row.
*
* - $view: The view in use.
* - $fields: an array of $field objects. Each one contains:
*   - $field->content: The output of the field.
*   - $field->raw: The raw data for the field, if it exists. This is NOT output safe.
*   - $field->class: The safe class id to use.
*   - $field->handler: The Views field handler object controlling this field. Do not use
*     var_export to dump this object, as it can't handle the recursion.
*   - $field->inline: Whether or not the field should be inline.
*   - $field->inline_html: either div or span based on the above flag.
*   - $field->separator: an optional separator that may appear before a field.
* - $row: The raw result object from the query, with all data it fetched.
*
* @ingroup views_templates
*/
$node_type = "node-type-" . $row->node_type;

?>
<?php foreach ($fields as $id => $field): ?>
  <?php if (!empty($field->separator)): ?>
    <?php print $field->separator; ?>
  <?php endif; ?>

  <<?php print $field->inline_html;?> class="views-field-<?php print $field->class; ?> <?php print $node_type; ?>">
    <?php if ($field->label): ?>
      <label class="views-label-<?php print $field->class; ?>">
        <?php print $field->label; ?>:
      </label>
    <?php endif; ?>
      <?php
      // $field->element_type is either SPAN or DIV depending upon whether or not
      // the field is a 'block' element type or 'inline' element type.
      ?>
      <<?php print $field->element_type; ?> class="field-content"><?php print $field->content; ?></<?php print $field->element_type; ?>>
  </<?php print $field->inline_html;?>>
<?php endforeach; ?>

That shouldn't mess with the js selectors when using grouping, and should get you what you want for styling.

kdebaas’s picture

Not really, this way you are tagging each field in a row with the node-type-example class. I need to wrap all fields in one row of a view in a div, so that I can position specific fields inside using absolute positioning.

The existing div that is already available for that is in fact not in views-view-fields.tpl.php, the row style output, but in the style output itself, for example in views-view-accordion.tpl.php, or views-view-unformatted.tpl.php. To be more precise, default Views templates print out each row in something like: <div class="views-row views-row-1 views-row-odd views-row-first">, which you have overridden with <div class="item-list views-accordion views-accordion-MyView">.

Instead of overriding each and every display template, it is more efficient for me to take the custom div down to the level of the row style template, so I can have that custom class both when the view is displayed as an accordion as well as when it is using another display. (I suppose I could also use a preprocessor, but I was hoping to keep things simple).

So, should I call this a feature request ;-)?

Manuel Garcia’s picture

Status: Active » Fixed

The module provides similar classes, like this: views-accordion-item accordion-item-0 accordion-item-odd accordion-item-first
Please use firebug to see what's going on...

You are lucky today that I am feeling generous. The module provides you with all the tools necesary for custom theming, including your request.

You can use this views-accordion.tpl.php in your theme:

// $Id: views-view-accordion.tpl.php,v 1.1.2.3 2009/02/26 20:25:59 manuelgarcia Exp $
/**
 * @file
 * Displays the items of the accordion.
 *
 * @ingroup views_templates
 *
 *  Note that the accordion NEEDS <?php print $row ?> to be wrapped by an element, or it will hide all fields on all rows under the first field.
 *  Also, if you use field grouping and use the headers of the groups as the accordion headers, these NEED to be inside h3 tags exactly as below (though u can add classes)
 *
 *  The current div wraping each row gets two css classes, which should be enough for most cases:
 *     "views-accordion-item"
 *      and a unique per row class like item-0
 *
 */
?>
<div class="item-list views-accordion <?php print $views_accordion_id ?>">
  <?php if (!empty($title)): ?>
    <h3 class="<?php print $views_accordion_id ?>"><?php print $title; ?></h3>
  <?php endif; ?>
  <div id="<?php print $views_accordion_id ?>">
    <?php foreach ($rows as $id => $row): ?>
      <?php $classes[$id] = $classes[$id] .' node-type-'. $variables['view']->result[$id]->node_type; ?>
      <div class="<?php print $classes[$id] ?>"><?php print $row ?></div>
    <?php endforeach; ?>
  </div>
</div>

There is no need for an extra div, use proper css selectors like .views-accordion-item.node-type-story.

kdebaas’s picture

Title: Open sections don't automatically close when clicking closed sections, when grouping fields » Wrapping rows in views-view-fields.tpl.php, when grouping fields, throws off js selectors
Category: support » bug
Status: Fixed » Active

I really appreciate that you have taken the time to look at this issue. So please don't be offended, but I believe you are misunderstanding my point. First of all views-accordion-item accordion-item-0 accordion-item-odd accordion-item-first has nothing to do with the selectors views-row views-row-1 views-row-odd views-row-first. That is because in Views there are rows, and rows are made up of fields. The selectors you mention belong to fields, not to rows.

Secondly, I understand the example code that you have provided. However, as I already pointed out, using it in this way would mean that similar code has to be written for the views-view-unformatted.tpl.php, and any other display template that will be used. In other words, if one chooses to use the views-accordion module, one has to forsake the granular functionality of the Views templates. This may be a minor bug, if you don't need that functionality, but it is still a bug.

kdebaas’s picture

Oops, scratch the first point I made in the last comment, that's obviously wrong. Sorry.
I believe the second point is still valid though.

Manuel Garcia’s picture

Status: Active » Needs review
FileSize
10.35 KB

I insist you don't need an extra div for your case, but I do see your point in that we should try to not depend on standard markup.

I wouldn't still consider this a bug, since you are making modifications and introducing custom code, but I do see the advantage of having the script being smart enough to not care about what extra markup you have there. jQuery selectors can get very tricky with all the possibilities that views offers, and if you throw in custom theming... well, you can get the idea, not very fun to debug.

The day i offered support for field grouping on the module, I opened a can of worms it seems. The js is so much more complex just to account for all the different markup views is spitting out, including several divs with the same ID.

Nevertheless I worked on the problem for some time, and I think we've made some progress. Please do test the patch attached (against the latest dev), and let me know how it goes. I have tried testing several configurations, but no time to test every possible way of configuring views and/or the plugin, so help here is really appreciated. I'm concerned we might introduce new bugs with this approach, so I won't commit it until it's been tested properly and extensively.

kdebaas’s picture

Applied the patch against dev, and tested that the accordion works as expected, even with the extra custom div! Nice. I am preparing for a trip now, but in a week or two I can do some more testing if you want.

I agree with your suggestion that there is a limit to how many obscure problems this module should want to solve. But supporting grouped fields has been quite a nifty feature too...

I'm not sure what you mean by including several divs with the same ID? Are you referring to the classes of the field items in a row, or to the view view-example view-id-example view-dom-id-1 etc... classes of the divs wrapping the whole view?

I'm asking because I did notice that the views-accordion.tpl.php spits out a lot of nested $views_accordion_id classes, which from a css inheritance point of view seems a little redundant. But then again, I don't know much about javascript or jquery, so I can't really tell if that is true.

Manuel Garcia’s picture

True that supporting grouping does offer a lot of nice functionality.

By divs with the same id i mean

, this happens when you group results by a field. Each group ends up having an h3 for the title of the groupped results, followed by a div with an id, which is the same id as the rest of the groupped results. This is a pain in jQuery, because jQuery stops at the first element with that id, unlike finiding classes, that searches the whole document and finds every element.

As far as classes, views accordion follows the example of views itself, in order to have some consistency for the user. I do nothing realy different, except call them a bit different for they are accordion results.

Please do test as much as you can, I will be leaving on Monday to Paris to attend the Drupalcon so I won't have much time during that time for this either.

kdebaas’s picture

The biggest difference between the accordion template and the standard views template is that it adds the $views_accordion_id as a selector no less than three times to different nested elements. On top of that, when grouping, or repeating the same view on a page, it creates duplicate ID's which then fail to comply with the standards that specify that any given ID name can only be referenced once within a page or document.

Couldn't you use the DOM id passed as a class to the view, as documented on line 119 in theme.inc of views, to single out each unique accordion view on a given page?

  // Our JavaScript needs to have some means to find the HTML belonging to this
  // view.
  //
  // It is true that the DIV wrapper has classes denoting the name of the view
  // and its display ID, but this is not enough to unequivocally match a view
  // with its HTML, because one view may appear several times on the page. So
  // we set up a running counter, $dom_id, to issue a "unique" identifier for
  // each view. This identifier is written to both Drupal.settings and the DIV
  // wrapper.

  static $dom_id = 1;
  $vars['dom_id'] = !empty($view->dom_id) ? $view->dom_id : $dom_id++;

My lack of understanding of javascript is a bit of a handicap, so I'm afraid I can't be more helpful with patches yet.

Manuel Garcia’s picture

Any news on this people, we should get this well tested !

Manuel Garcia’s picture

Status: Needs review » Postponed (maintainer needs more info)

Apparently this isn't a priority for anyone, so I'm setting this as postponed.

phelix’s picture

Version: 6.x-1.2-beta3 » 7.x-1.x-dev
Priority: Normal » Major
Issue summary: View changes
Status: Postponed (maintainer needs more info) » Active

I am running into the exact same problem. If I add any other div wrappers inside of this code it breaks the accordion. I need this as I am trying to separate the output of this page into a 2 columns layout. So when I add some additional markup to split this into 2 containers it breaks the accordion right where I add the new div. I tried to patch this but it seems to fail. Is there something I can do to get this to work??

This is inside the root views tpl file.

<?php

/**
 * @file
 * Main view template.
 *
 * Variables available:
 * - $classes_array: An array of classes determined in
 *   template_preprocess_views_view(). Default classes are:
 *     .view
 *     .view-[css_name]
 *     .view-id-[view_name]
 *     .view-display-id-[display_name]
 *     .view-dom-id-[dom_id]
 * - $classes: A string version of $classes_array for use in the class attribute
 * - $css_name: A css-safe version of the view name.
 * - $css_class: The user-specified classes names, if any
 * - $header: The view header
 * - $footer: The view footer
 * - $rows: The results of the view query, if any
 * - $empty: The empty text to display if the view is empty
 * - $pager: The pager next/prev links to display, if any
 * - $exposed: Exposed widget form/info to display
 * - $feed_icon: Feed icon to display, if any
 * - $more: A link to view more, if any
 *
 * @ingroup views_templates
 */


$rows = preg_replace('~>\s+<~', '><', $rows);
$rows = preg_replace('/[\r\n]+/', "\n", $rows);
$rows = preg_replace('/\s+/', ' ', $rows);

$rows = str_replace('<h3 class="views-accordion-clone_of_tax_test-page-header"> Health Care </h3>', '</div><div class="rightcol"><h3 class="views-accordion-clone_of_tax_test-page-header"> Health Care </h3>', $rows);





//print htmlspecialchars($rows);
?>
<div class="leftcol">
<div class="<?php print $classes; ?>">
  <?php print render($title_prefix); ?>
  <?php if ($title): ?>
    <?php print $title; ?>
  <?php endif; ?>
  <?php print render($title_suffix); ?>
  <?php if ($header): ?>
    <div class="view-header">
      <?php print $header; ?>
    </div>
  <?php endif; ?>

  <?php if ($exposed): ?>
    <div class="view-filters">
      <?php print $exposed; ?>
    </div>
  <?php endif; ?>

  <?php if ($attachment_before): ?>
    <div class="attachment attachment-before">
      <?php print $attachment_before; ?>
    </div>
  <?php endif; ?>

  <?php if ($rows): ?>
    <div class="view-content">
      <?php print $rows; ?>
    </div>
  <?php elseif ($empty): ?>
    <div class="view-empty">
      <?php print $empty; ?>
    </div>
  <?php endif; ?>

  <?php if ($pager): ?>
    <?php print $pager; ?>
  <?php endif; ?>

  <?php if ($attachment_after): ?>
    <div class="attachment attachment-after">
      <?php print $attachment_after; ?>
    </div>
  <?php endif; ?>

  <?php if ($more): ?>
    <?php print $more; ?>
  <?php endif; ?>

  <?php if ($footer): ?>
    <div class="view-footer">
      <?php print $footer; ?>
    </div>
  <?php endif; ?>

  <?php if ($feed_icon): ?>
    <div class="feed-icon">
      <?php print $feed_icon; ?>
    </div>
  <?php endif; ?>

</div><?php /* class view */ ?>
</div> <!-- /leftcol -->

This is a screenshot of what it is now doing to my accordion once it sees the new div that I have added.
Only local images are allowed.