The MLS platform utilizes the Nodequeue and Views modules to create blocks of content that can be curated by our editors. The nodequeue can be configured to hold a number of nodes limited by maximum count or node type. The nodequeue itself is populated based on an autocomplete node reference fields and can be re-ordered or edited. This gives editors a simple interface to curate multiple blocks on our site. Once configured, a view’s content can be controlled by a nodequeue relationship.

Nodequeue and Views Configuration

Controlling the output of the view can be difficult, since you can only set a maximum number of nodes allowed in the queue, but not a minimum. We solved this issue and gave site editors the freedom to dynamically change the layout based on the number of items. This allows us to build one template that works for a variety of use cases.

In this post, we will use several examples to demonstrate how to use a “block” display from a view driven by a nodequeue relationship.

Nodequeue Layouts

Adding a Count Class

Adding a class to the container div of the view will allow us to style the elements inside. This is accomplished fairly easily. You can create a view override template suggestion for the parent container (views-view.tpl.php); we used the views-view-nodequeue.tpl.php. Don’t forget to scan for files once you create your override.

Adding the following code to the top of your newly created override will add the nq-count-X class to the view output container, where X is the number of nodes in the queue.

$row_content = $variables['view']->result;
$nq_count = count($row_content);
$classes .= ' nq-count-' . $nq_count;

This will allow for customization of the children elements. However, we want to use different image presets based on the item count and that involves a little more code.

Modifying Image Presets Based on Count

First thing we want to do is create a view override template suggestion for the image we are manipulating (views-view-field.tpl.php). In our example the override will be for the “primary-image” field used in our post content type. The contents of the field override are simple–we just output the themed image from our field based on the view settings:

print $output;

We will be excluding that field from our view display and handling the output via our custom function:

$output = nodequeue_process_nq_image($row, $view);
print $output;

The function that this code is referencing can live either in the template.php file or in a custom module. We wrote a custom module that handles some other nodequeue manipulation, so our function lives there:

/**
 * nodequeue_process_nq_image().
 * Determine which image preset to use via count.
 * @param $row: The raw SQL result of the image field.
 * @param $view: View object.
 *
 * @return The processed themed image.
 */
function nodequeue_process_nq_image($row, $view) {
  $file_uri = '';
  $row_count = count($view->result);
  $row_index = $view->row_index;
  $image_map = 'count-' . $row_count;
  $nq_image_styles = array(
    'count-1' => array(
      'image_landscape',
    ),
    'count-2' => array(
      'image_default',
      'image_thumbnail',
    ),
    'count-3' => array(
      'image_landscape',
      'image_thumbnail',
      'image_thumbnail',
    ),
  );
  // Check to ensure we have a mapping.
  if (isset($nq_image_styles[$image_map][$row_index])) {
    $image_nid = node_load($row->field_field_post_primary_image[0]['raw']['nid']);
    $file_uri = $image_nid->field_image_image[LANGUAGE_NONE][0]['uri'];
  }
  $image_output = ($file_uri) ? theme('image_style', array('path' => $file_uri, 'style_name' => $nq_image_styles[$image_map][$row_index])) : '';
  return $image_output;
}

Now our image presets can be changed dynamically via queue count. But what if we want to do multiple layouts?

Creating More Dynamic Nodequeue Count Layouts

The above example will work fine for just one layout for the block chosen. We wanted to have more than just one layout available to our editors. The issue that we encountered is that we need a way to determine which block we are processing in order to determine which image presets to use. The machine name of the block from the view is available for us to use in our code. It is important to note that the id must be unique PER VIEW. When you clone a view, the ids will remain in place. This allows site moderators to clone these views and still allow our code to determine which view we are modifying.

Note: when you create a new view and then create a block display, the machine name will be “block”. You need to alter this value. It is under the advanced tab in the view display (Other->machine name)

For our example we have two layouts, primary_dl and post_callout. This could be extended this to as many presets as you like.

We created a view block and modified the machine name to primary_dl and another view display block with a machine name of post_callout. Now we modify our code to look at the machine name and map according to which view display is being processed.

Now we can extend our existing function:

$file_uri = '';
$row_count = count($view->result);

// Machine name for view display id.
$block_name = $view->current_display;
$row_index = $view->row_index;
$image_map = $block_name . '-count-' . $row_count;
$nq_image_styles = array(
  'primary_dl-count-1' => array(
    'image_landscape',
  ),
  'primary_dl-count-2' => array(
    'image_default',
    'image_thumbnail',
  ),
  'primary_dl-count-3' => array(
    'image_landscape',
    'image_thumbnail',
    'image_thumbnail',
  ),
  'post_callout-count-1' => array(
    'image_default',
  ),
  'post_callout-count-2' => array(
    'image_default',
    'image_default',
  ),
  'post_callout-count-3' => array(
    'image_thumbnail',
    'image_thumbnail',
    'image_thumbnail',
  ),
);

We also want to account for our site maintainers cloning the display. When you clone a display in views, it increments the machine name (i.e. primary_dl_1, primary_dl_2, etc.). To account for that we can just look at the base machine name, disregarding the _* (via cloning):

$available_nqs = array(
  0 => 'primary_dl',
  1 => 'post_callout',
);
foreach ($available_nqs as $key => $nq_name) {
  if (strpos($block_name, $nq_name) !== false) {
    $block_name = $nq_name;
    break;
  }
}

And now we are all set to theme it properly using our base machine names.

Here is the complete function for reference:

/**
 * nodequeue_process_nq_image().
 * Determine which image preset to use via count.
 * @param $row: The raw SQL result of the image field.
 * @param $view: View object.
 *
 * @return The processed themed image.
 */
function nodequeue_process_nq_image($row, $view) {
  $file_uri = '';
  $row_count = count($view->result);
  // Machine name for view display id.
  $block_name = $view->current_display;
  $row_index = $view->row_index;
  $available_nqs = array(
    0 => 'primary_dl',
    1 => 'post_callout',
  );
  foreach ($available_nqs as $key => $nq_name) {
    if (strpos($block_name, $nq_name) !== false) {
      $block_name = $nq_name;
      break;
    }
  }
  $image_map = $block_name . '-count-' . $row_count;
  $nq_image_styles = array(
    'primary_dl-count-1' => array(
      'image_landscape',
    ),
    'primary_dl-count-2' => array(
      'image_default',
      'image_thumbnail',
    ),
    'primary_dl-count-3' => array(
      'image_landscape',
      'image_thumbnail',
      'image_thumbnail',
    ),
    'post_callout-count-1' => array(
      'image_default',
    ),
    'post_callout-count-2' => array(
      'image_default',
      'image_default',
    ),
    'post_callout-count-3' => array(
      'image_thumbnail',
      'image_thumbnail',
      'image_thumbnail',
    ),
  );
  // Check to ensure we have a mapping.
  if (isset($nq_image_styles[$image_map][$row_index])) {
    $image_nid = node_load($row->field_field_post_primary_image[0]['raw']['nid']);
    $file_uri = $image_nid->field_image_image[LANGUAGE_NONE][0]['uri'];
  }
  $image_output = ($file_uri) ? theme('image_style', array('path' => $file_uri, 'style_name' => $nq_image_styles[$image_map][$row_index])) : '';
  return $image_output;
}

Like all things Drupal, there are many ways to solve these kinds of problems. Feel free to reach out to me with questions and comments.

Hans Gutknecht - @hansyg

New MLS Mobile App for 2015

January 12, 2015

Open beta for new MLSsoccer.com

December 04, 2014 Hans Gutknecht

Standings Visualizations

October 30, 2014 Tom Youds