jQuery and Views rock my world!

We encourage users to post events happening in the community to the community events group on https://www.drupal.org.
robertDouglass's picture

Sometimes Drupal just makes me sit back and say "wow!" I had one of those moments yesterday when I set about tweaking the theming for the sessions page. I wanted to make it clear which language was going to be spoken in each session. My goal was to change the background color depending on whether the session is in English or German. I have access to the Drupal administration section, but I don't have direct server access. This makes it hard to write CSS for the page. Besides, CSS isn't equipped to look into a table cell, see its contents, and theme accordingly. jQuery is, however, and using Views you can add JavaScript directly to the page! So how'd I do it? Let's look at the HTML, first:

<td>
  <a href="/tag/6%20-%20Community.61/">6 - Community</a>                                                      
  <a href="/node/205">DVC - Introduction</a>
  <a href="/user/43" title="Benutzerprofil anzeigen.">SirFiChi</a>
  Deutsch
</td>

It's slightly simplified from the real code, but the main point is, it's a TD element that contains either the word 'Englisch' or 'Deutsch'. So the trick is to write some jQuery that selects TD's looks inside for either of those words, and sets the CSS styling of the element accordingly.

Here's the jQuery code:

<script>
// This is the jQuery syntax for doing something after
// the HTML is loaded,
// but before the page has rendered.
$(document).ready(function() { 

  // Get each TD in the grid view,
  // and give it some padding.
  $("table.views-view-grid td").css({padding: "0.5em"}); 

  // use td:contains('Englisch') to find TD elements
  // with the word Englisch, and give
  // them a background color.
  $("table.views-view-grid td:contains('Englisch')")
    .css({background: "#FFFFCC"});

  // Do the same for 'Deutsch',
  // but with a different color.
  $("table.views-view-grid td:contains('Deutsch')")
    .css({background: "#CCFFFF"});
});
</script>

With the code in hand, I needed a place to put it. Here's where Views comes to the rescue. Each page View has a header and footer section that can be free text. I used the header to inject the jQuery code into the page. Note that I used the PHP Filter not because any PHP code is executing, but because it doesn't do any other filtering (like line breaks).

Only local images are allowed.

The result? A nice and color-coded sessions page!

Only local images are allowed.

Comments

kinda kills the purpose of

asad.hasan's picture

kinda kills the purpose of having a css file, but nice to see how drupal can do everything lol. Thats why i like calling it a content development framework rather a mere cms.

"If you have to do a sequence of actions more than twice, they are in the wrong abstraction layer :D" - Learned from drupal

hi robert, do u think is

andreap's picture

hi robert,
do u think is possible an integration between this jquery script http://bit.ly/asnHjm and drupal views with an html list formatted style (ul li.views-row)?

I'm trying to include relative js (jquery.ahover.js & jquery.dimensions.min.js) in mytheme.info file and javascript call script in view's intestation (with full-html filter). I'm also activated jquery.ui module with 1.6 release, but doesn't work :-(

Here is the call script code:

<script type="text/javascript">
  <!-- PER IL MENU CON L'EFFETTO HOVER -->
    jQuery(function($) {
   $('.item-list ul li').ahover({toggleEffect: 'height', moveSpeed: 75, toggleSpeed: 250});
   });
</script>

and here is an example of the view html output:

<div class="view-content">
      <div class="item-list">
    <ul>
          <li class="views-row views-row-1 views-row-odd views-row-first"></li>
          <li class="views-row views-row-2 views-row-even"></li>
          <li class="views-row views-row-3 views-row-odd"></li>
          <li class="views-row views-row-4 views-row-even"></li>
          <li class="views-row views-row-5 views-row-odd views-row-last"></li>
      </ul>
</div>
</div>

this is the css:

.item-list ul li:hover {color:#fff;}
.item-list ul div.ahover {background: #cc0000; -webkit-border-radius: 5px; -moz-border-radius: 5px;}

Can u help me?
tnx

Andrea

Hi Andrea, try the following

rcj's picture

Hi Andrea,

try the following changes.

Call to ahover function:

<script type="text/javascript">
  $(document).ready(function() {
    $(".item-list ul li").ahover({toggleEffect: 'height', moveSpeed: 75, toggleSpeed: 250});
  });
</script>

And your CSS:

.item-list ul div.ahover {
  background: #cc0000;
  -webkit-border-radius: 5px;
  -moz-border-radius: 5px;
  position: absolute;
}

Note the position:absolute;

See http://d6.robinjoy.net/ahover_demo

Hope this helps.

yes helps a lot!

andreap's picture

hi robin,
now the script works very fine! i've missed the absolute positioning to div.ahover and relative positioning to "ul" and "ul li".

".item-list ul li" is too generic for me: if you have to stylize a view with a pager at bottom, this will be styled too. I've changed into ".view-content .item-list ul li"

This is the final css:

.view-content .item-list ul {position:relative;}
.view-content .item-list ul li {position:relative; z-index:100;}
.view-content .item-list ul div.ahover {background-color:#eee; -webkit-border-radius: 5px; -moz-border-radius: 5px; position: absolute;}

And this is the final call script in the head of the view:

<script type="text/javascript">$(document).ready(function() {$(".view-content .item-list ul li").ahover({toggleEffect: 'height', moveSpeed: 75, toggleSpeed: 250});});</script>

You have insert call for jquery.ahover.js in the head of the view instead in the theme.info. I work with a zen subtheme, i've just placed the script in theme root folder, then i've call it in theme so:

scripts[] = jquery.ahover.js

I've taken this choice because i'll use this script to work with many views and not with just one :-)
Your help has been so precious for me,
thanks a lot ;-)

regards
Andrea

Hi Andrea, I added the script

rcj's picture

Hi Andrea,

I added the script to the head of the view, as it is only a demo to see if the solution is what you had in mind.
Depending on the percentage of pages using the script, I would place it either in the .info file of the theme,
or in a preprocess function for the views.
Glad it helped.

"Besides, CSS isn't equipped

scottprive's picture

"Besides, CSS isn't equipped to look into a table cell, see its contents, and theme accordingly."

Literally speaking, CSS3 Selectors DO actually target element contents -- see Section 2:
http://www.w3.org/TR/css3-selectors/

Practically speaking, CSS3 would have poorer browser support than relying on jQuery, so I wouldn't suggest changing from your current approach.

I might be having a slow morning, but wouldn't it have been simpler to theme this in Views?
Inside "views-view-unformatted--[your-view-name].tpl.php" or views-view-fields--...
You could conditionally attach a CSS class to cells based on $fields['field_language']->content.

One advantage is the work is done on the server, so there's no question about Javascript or browser support.

Another advantage of theming this only in views is precision: you have access to the language field value. Consider a (possibly improbable in your case) scenario where a language or key word were contained in the Title? In this case it is not clear jQuery would always detect the language properly. [I expect in your case that the event names are decided and not likely to change, but it is something to consider when using this jQuery 'contains' approach... so really this warning is for other users: always know your data]

Germany

Group organizers

Group notifications

This group offers an RSS feed. Or subscribe to these personalized, sitewide feeds: