6

Using Drupal 7 and Views, I currently have a view that produces a list of 5 teasers of the content type "News." 5 teasers is a hard rule. I'd like to conditionally format the rows so that when their "created date" is less than 14 days old so that I may styles them as "New" with CSS styles. So if there are 3 "New" rows, the balance are 2 unmarked rows.

How to do so?

Update

I had the idea of using the "time ago" date format to populate the class name. However, the format for "time ago" changes. Unfortunately, I can't set the granularity to "days" which would have allowed me to add the text as a class, i.e., date1 through date24 for the past 2 weeks.

Update #2

My genesis subtheme is ignoring any preprocessor routines, see more here. However, I can add the routine to my base template.php.

Update #3

Thanks to Елин Й. for the working code:

function genesis_preprocess_views_view_list(&$variables) {
  $view = $variables['view'];
  if ($view->name == 'recent_news_widget') {
    foreach ($view->result as $key => $result) {
      if (time() - strtotime($result->node_created_day) < 14 * 24 * 60 * 60) {
        $variables['classes'][$key][] = 'new';
        $variables['classes_array'][$key] = isset($variables['classes'][$key]) ? implode(' ', $variables['classes'][$key]) : '';
      }
    }
  }
}

In an offline discussion, Елин Й. explains why this works; "I took a look in the views theme.inc and found out that, the classes array is flattened to another variable called 'classes_array' you need to do it as well in order to get your new class also added in this array.

2
  • 2
    in UPDATE4 you're overriding row_class completely. You want to append your own class -- not nuke everything to new.
    – tenken
    Jun 18, 2013 at 20:22
  • 1
    was about to say the same thing, pop the value to the row_class array instead of overwriting it.
    – cdmo
    Jun 18, 2013 at 20:23

3 Answers 3

4
+50

You can do that using a preprocessor function for the view you created. You need to preprocess the view and check the creation date of nodes for each row and give them a relating class.

Given that your view's machine name is recent_news_widget, your diplay format is HTML lists, and your theme name is genesis. You need to use template_preprocess_views_view_list() function in /sites/all/themes/genesis/template.php file

genesis_preprocess_views_view_list(&$variables) {
  $view = $variables['view'];
  if ($view->name == 'recent_news_widget') {
    // dpm($view);
    // Here comes your logic
  }
}

In the above code you see 2 lines commented out. First one is a helpful function for developers to print out the given array/object/string etc in a browsable style. This function comes with Devel module, which I would strongly recommend to install it.

After browsing the variables, you will probably find where the results are listed and where the classes for the rows are assigned. You need to browse the variables until you find all values you need to build your logic to assign new classes, for example the 'created date' of the node. After you have all the variables you need, you can loop through the results, check the creation date and add a relating class.

UPDATE: The preprocess functions for other display types than HTML List:

Grid: template_preprocess_views_view_grid() Table: template_preprocess_views_view_table() Unformatted: template_preprocess_views_view_unformatted()

UPDATE #2 (According the discussion on chat and your updates on the question): I find the code in your Update #3 was in the right direction, but with a few mistakes. The corrected version should look like that:

function genesis_preprocess_views_view_list(&$variables) {
  $view = $variables['view'];
  if ($view->name == 'recent_news_widget') {
    foreach ($view->result as $key => $result) {
      if (time() - strtotime($result->node_created_day) < 14 * 24 * 60 * 60) {
        $variables['classes'][$key][] = 'new';
        $variables['classes_array'][$key] = isset($variables['classes'][$key]) ? implode(' ', $variables['classes'][$key]) : '';
      }
    }
  }
}

The 2 mistakes in your code were:

  1. You passed the argument as &$variables to the function, but used $vars to assign classes, $vars is not defined in the function so the class was not added.

  2. You wanted to use the key number of the result but in foreach you loop only through the values, and $result variable is an object. In the corrected version of your code above, I used $key => $result by defining the loop so that I can access the key number as well.

UPDATE #3 I added a new line that flattens the classes into classes_array.

7
  • Thanks, this looks like the correct way to go. However, the code (adapted for my theme's name and view name) isn't working. function ubercompany_preprocess_views_view_list(&$variables) { $view = $variables['view']; if ($view->name == 'recent_news_widget') { dpm($view); // logic } } isn't rendering the variable data? I presume it renders to the message box, but it isn't?
    – Screenack
    Jun 15, 2013 at 11:57
  • 1
    You need to clear cache, at least the theme registry. Yes, it should render it to the messages region. Jun 15, 2013 at 13:02
  • 1
    Oh, and the preprocess function was an example for a view that has a display type of HTML List. If your display type is different, then you need to use its preprocess function. I'll update my answer and list the preprocess functions for each display type. Jun 15, 2013 at 13:04
  • I have set Devel's Rebuild the theme registry on every page load (and routinely use drush cc all) and I presume the view is an HTML List type, i.e., $handler->display->display_options['style_plugin'] = 'list'; but to no avail.
    – Screenack
    Jun 15, 2013 at 13:17
  • 1
    To debug i'd remove the first if condition and try to dpm the view without checking the view name. However if you have too many views on the same page, you could get memory errors. Jun 15, 2013 at 13:24
3

Hope this will help you!!

As you need to add the class to the row, you can achieve by overriding the default view template file

You can achieve this by the following steps

  • Open your view and go to Advance tab + other category you can see the theme - information click Information link.

    enter image description here

  • As per your requirement you need to override the row style. you can see Row style output, the default template file is views-view-fields.tpl.php which is highlighted. Means this template file is active now. And also you see list of tpls will be there, so choose any one of the tpl name (eg.., views-view-fields--comments-recent.tpl.php or views-view-fields--comments-recent--page.tpl.php) for your new template file.

    enter image description here

  • You need to override this template file so navigate to VIEWS module + THEME folder + get the tpl file which you want to override(here views-view-fields.tpl.php)

    enter image description here

  • Copy and paste template file to your theme template folder(sites/themes/your_theme/templates/) and rename it to the choose template name

  • Click Rescan template file to active new template file.

    enter image description here

    • No you can modify the template file and add the class.
1
  • Inizio, that's a stellar effort at documentation, and ought to serve someone looking for how to do so well. One could also add a class to the row via the Views UI if that's all that is needed. Your answer is broader than my question however, though much appreciated.
    – Screenack
    Jun 18, 2013 at 15:35
1
function genesis_preprocess_views_view_list(&$vars) {
  $view = $vars['view'];
  $rows = $vars['rows'];

  if ($view->name == 'recent_news_widget') {
    foreach ($rows as $id => $row) {
      $data = $view->result[$id];
      // Assumption this if condition works and node_created_day exist in row
      if (time() - strtotime($data->node_created_day) < 14 * 24 * 60 * 60) {
       // Add custom class if condition satisfies
       $vars['classes'][$id][] = 'custom-new';
      } 
    }
  }
}

Also can you try replacing the classes line with this one and tell me does it work. $vars['row_classes'][$id][] = 'custom-new';

5
  • I was hoping this was it. However, while the dpm function dutifully fired no classes added. I disabled every module except for views and devel, eliminating (?) the potential for conflict. However, classes not added in the rendered HTML output.
    – Screenack
    Jun 20, 2013 at 1:05
  • 1
    @KyleSkrinak can you check if it is entering the if condition where the time check is made ?
    – junedkazi
    Jun 20, 2013 at 1:09
  • Running dpm($data); within the if block confirms the condition is correctly met.
    – Screenack
    Jun 20, 2013 at 1:16
  • 1
    @KyleSkrinak can you try this and tell me if it works. $vars['row_classes'][$id][] = 'custom-new'; Just replace the old line and clear cache.
    – junedkazi
    Jun 20, 2013 at 1:20
  • Replaced $vars['classes'][$id][] = 'custom-new'; with $vars['row_classes'][$id][] = 'custom-new'; cleared server and browser cache, reloaded page. No classed applied to output, i.e., <ul> <li class=""> (First list item matches the condition)
    – Screenack
    Jun 20, 2013 at 2:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.