Hello everyone,

I'd like to request some support or advice from the more knowledgeable members of the community regarding an issue with Views 2.

I am trying to build a glossary view to show all the content to the user alphabetically. I started from the default "glossary" view as my starting point, but I have two issues I am unsure how to handle.

First, I would like to output all letters, even those that have no associated content. Instead of:

B (1) | D (1) | F (2) etc.

I would like:

A (0) | B (1) | C (0) | D (1) etc., with only those letters that have associated nodes working as links.

I am not sure whether this functionality is best handled within the view itself, or in a theming template. Advice please?

Second issue. My nodes are titled both in greek and in english. I would like to show each alphabet individually on its own line, something like:

A (0) | B (1) | C (0) | D (1) ...
A (0) | B (0) | Γ (3) | Δ (2) ...

I tried to use a filter to restrict the node titles, but there is no option "starts with one of" [abcdefghijkl...] - any other clever workarounds?

Thanks in advance for your time and any replies!

Comments

khanz’s picture

Can any one answer atleast the first part of the problem..?

------------
Volvo, Video, Velcro. (I came, I saw, I stuck around.)

skourak’s picture

I had almost forgotten about this :)

There sure are better ways of doing this, but I finally ended up theming it in by hand in my view's tpl.php file.

that is the relevant bit of code, in case anyone else has a similar need.

$letters = array('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'); 

// parse the letter list, outputting one element per letter

$counter =0;   //traverses the $rows array as letters with links are processed

for ($i=0; $i<sizeof($letters); $i++){
	print !empty($options['inline']) ? '<span>' : '<div>';
	
	if ($i > 0) { print ' | '; } // separator before all but the first element
	
	if ($letters[$i] == $rows[$counter]->link){

		// this letter has a link, print it
		echo '<a href="'.$rows[$counter]->url.'"><span class="letter">'.$rows[$counter]->link.'</span>';
		echo  ' ('.$rows[$counter]->count.')</a> ';
		
		$counter++;

	} else {

		// this letter does not have a link, print it plain
		echo $letters[$i].' ';
		
	}
	
	 print !empty($options['inline']) ? '</span>' : '</div>';
}

Feel free to suggest better ways of course :)

joaoverissimo’s picture

hi, I'm trying to implement you solution but i cannot get to work it right. All the letters appears but no links to it. I've tried to put on the display and on the style output .tpl.php and neither one worked. For wath I understand the $rows on the display output is already html so i cannot get the variables link nor url. And on the style, it completly ignores and shows the default output. Any suggestions?

Thanks in advance

mikejonesok’s picture

replace what's in views-view-summary-unformatted.tpl with the code above...thanks for the code btw.

WorldFallz’s picture

chak_boss’s picture

Hi all,

Am also facing same problem. I configured glossary correctly, it displays good what i expected.
but i need to display the pager like all the alphabets without any missing character
Now it looks like this
B | C | F | J | N | P | S | V

But I need like this

A | B | C | D | E | F | G | H | I | J .. etc

Thanks

kwerey’s picture

Here's an updated version of Silth's Views 2 template code to Views three and got rid of the Undefined Index error you get when there aren't a full alphabet's worth of nodes on display.

chak_boss, you're most of the way there.

What you need to do now is add a template file in your theme folder. Assuming you're using the default layout for this (the tab called "attachment" in your glossary view should be using "Format: Unformatted list"), this is what you wanna do:

1) Copy the file at: sites/modules/views/templates/views-views-summary-unformatted.tpl.php into your theme folder's templates folders (sites/themes/YOUR-THEME/templates).

2) Replace the content of that file with this code:

<?php

/**
 * Overrides the default Views version (in sites/all/modules) to display the whole alphabet.
 */
?>
<?php 

$letters = array('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z');

// parse the letter list, outputting one element per letter

$counter =0;   //traverses the $rows array as letters with links are processed
$max = count($rows);
for ($i=0; $i<=25; $i++){

 print (!empty($options['inline']) ? '<span' : '<div') . ' class="views-summary views-summary-unformatted">' ; ?>
    <?php if (!empty($row->separator)) { print $row->separator; } ?>

<?php 

if ($counter < $max && $letters[$i] == $rows[$counter]->link){ // works but with 'undefined offset'

	// This letter has a link, print it with a link
	echo '<a href="'. $rows[$counter]->url. '"><span class="letter">'. $rows[$counter]->link .'</span>' . '</a>';

	$counter++;

	} else {
	// this letter does not have a link, print it plain
	echo $letters[$i];
}
print !empty($options['inline']) ? '</span>' : '</div>';
}

And that should sort it.

alex.verhoeven’s picture

The code above worked very well for me. I added a small bit to reinstate the link class so that you can style the "active" state:

echo '<a href="'. $rows[$counter]->url. '" class="'. $row_classes[$counter] .'"><span class="letter">'. $rows[$counter]->link .'</span>' . '</a>';

labboy0276’s picture

Hello,

I know this is old, but we just had a client ask for this on a Glossary of terms we made, etc.

Anywho, I did this through a preprocess in the template.php. It is frowned upon in the best practices circles to add functional php in a tpl, etc.

Anywho, here it is (not the most elegant solution, but it workz):

/**
 * Implements template_preprocess_views_view().
 */
function YOURTHEME_preprocess_views_view(&$vars)) {
if ($vars['view']->name == YOURVIEW' && $vars['view']->current_display == 'YOURATTACHMENTDISPLAY') {
    // Get the current rows of letters for glossary.
    preg_match_all('/<a href="(?:.+)">/', $vars['rows'], $matches);
    foreach ($matches as $match) {
      foreach ($match as $url) {
        // Basically breaking down the a href link into a letter.
        $check = explode('/glossary/', $url);
        if (isset($check[1])) {
          $letters[] = substr($check[1], 0, -2);
        }
      }
    }
    // Take the urls and check them against alphabet
    $alphas = array('a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z');
    $output = '<span class="views-summary views-summary-unformatted alpha"><a href="/glossary/">ALL</a></span>';
    foreach ($alphas as $alpha) {
      if (!in_array($alpha, $letters)) {
        $output .= '<span class="views-summary views-summary-unformatted alpha">' . strtoupper($alpha) . '</span>';
      }
      else {
        $output .= '<span class="views-summary views-summary-unformatted alpha"><a href="/glossary/' . $alpha . '">' . strtoupper($alpha) . '</a></span>';
      }
    }
    $vars['rows'] = $output;
  }
}

John Ouellet
Sales Engineering Manager
https://thinktandem.io/

dzadzen’s picture

But how switch on ajax this code? Standart metod with "enabled ajax" in views not working. Thanks

dzadzen’s picture

How order last name from title ?

dripa’s picture

Here is a version I use in Twig, it has a little modification to be used with anchors:

{% set counter = 0 %}
{% set max = rows|length %}

{% for letter in 'a'..'z' %}
  {{ options.inline ? '<span' : '<div' }} >

  {% if row.separator -%}
    {{ row.separator }}
  {%- endif %}

  {% if (counter < max and rows[counter].link == letter) %}
    <a href="#index_{{ letter }}"{{ row.attributes.addClass(row.active ? 'is-active')|without('href') }}>{{ letter|upper }}</a>
    {% set counter = counter+1 %}
  {% else %}
    {{ letter|upper }}
  {% endif %}

  {% if options.count %}
    ({{ row.count }})
  {% endif %}

  {{ options.inline ? '</span>' : '</div>' }}

{% endfor %}
dzadzen’s picture

How order last name from title ?

devpilot’s picture

Name Field Works pretty well now in 8

dzadzen’s picture

works pretty what? Order last name from title?

mizage@gmail.com’s picture

I had to alter line 11:

% if (counter < max and rows[counter].link == letter|upper) %}

otherwise the condition was never true.

ruslan piskarov’s picture

Thank you, @e.ruiter. You saved my time.

Visit my blog for more info: Make Drupal Easy.

nnevill’s picture

Here is working with D9/D10 solution for glossary attachment template:
 

{% for letter in 'a'..'z' %}
  {% set row = '' %}
  {{ options.inline ? '<span' : '<div' }} class="views-summary views-summary-unformatted">
  {% for loop_row in rows  %}
    {% if (loop_row.link == letter|upper) %}
      {% set row = loop_row %}
    {% endif %}
  {% endfor %}

  {% if row %}
    <a href="{{ row.url }}"{{ row.attributes.addClass(row.active ? 'is-active')|without('href') }}>{{ row.link }}</a>
    {% if options.count %}
      ({{ row.count }})
    {% endif %}
  {% else %}
    {{ letter|upper }}
  {% endif %}

  {{ options.inline ? '</span>' : '</div>' }}

{% endfor %}