Lately I have been working on a web project called Spanish Borderlands with Raphael Folsom. The basic idea for the project is that students in Raphael’s upper division history course on the Spanish colonial borderlands will read primary sources and take notes into an online web database. Rather than each student creating their own stack of 3×5 note cards on their readings, their notes will collectively pool in a Drupal system that can then be searched by bibliographic or thematic content. Raphael can model good note-taking for his students and the students can share their notes when it comes time to write their analytical papers. For more information on this project, see my earlier post, Digital Note-taking in the History Classroom.
Adding Related Cards to Our Displays
One of the fun parts of working on this project with Raphael is brainstorming desired features for the site and then figuring out whether or not I can actually build them.
One of Raphael’s ideas was that every notecard in our database would include lists of related notecards at the bottom of the screen. Thus all notecards related to the same primary source would be listed. In a second list, all notecards related to the same author of the primary source would be listed. Additional lists might include all notecards by the same notetaker or all notecards related to the same place.
As students are entering notes, they will be able to see what other notecards exist. When it comes time to write their papers, they can either do searches across the database or crawl through the database based on these lists of matching cards.
Drupal Views Contextual Filtering by Field Value
I wanted to document how this works technically, because I couldn’t find a straight-forward statement of how to do this anywhere online. The payoff is two lines of PHP, so if you’re not a Drupal user or a complete nerd, I’d suggest stopping here.
Technically speaking, we wanted to embed a table of nodes on each note-card content display. I’m using Drupal 7, so the Views module is great for generating tables. The challenge was how to filter the table to only show those nodes that match the pertinent field from whatever card I happen to be viewing. Thus I needed to set up a system that would pass the value for the field from the node when I call it, to a filter to produce the desired view table.
Drupal Views has filters that are fairly easy to set up. You can use this to make sure you’re only looking at one type of content, only published records, or only records that match certain criteria. You can then publish these views as a web page or a Drupal block that can be part of a web page. You can also expose a filter so that a visitor to that web page table can filter across a field for their desired results.
The limitation on filters is that you need to set the value of a field or allow the user to set the value of a field. It cannot be used to filter dynamically according to the value of a field in a node. For this functionality, you need to use contextual filters. The common uses of contextual filters are to build a block that can be added into a page including all nodes in a similar taxonomic category or all nodes by the same user. Drupal handles taxonomies and users very well and has these functionalities built into contextual filters in a fairly straight forward way.
Contextual filters does not have similar functionalities for dynamically filtering by a field value. In order to do this, you need to use PHP to generate the value for the filter. In the example below, I have told my view to filter by the field Source Author. If I wanted this to always filter for the value “John Doe,” I could simply type in “John Doe” and the filter would work. But I wanted the table to pull the “Source Author” from the piece of content currently being viewed and filter the table for that value. To do this, I use the following two lines of PHP:
$node = menu_get_object();
The first line of this code tells the system to pull the information for the current node. The second line “returns” the first value of the field “field_author.” The code thus pulls the value of the “field_author” to the contextual filter, which then filters the table to show all matching results. If I wanted to filter by another field, for example to show all cards related to the same bibliographic source, I could change “field_author” to “field_source.”
Using this contextual filter, I produced a view that shows me a table of all nodes that share the given field with the node currently being viewed.
I repeated this process to produce several of these views producing tables matching different fields. Next I used the QuickTabs module to produce something called a QuickTabs block. This allows me to tab between my multiple table views of related cards.
A third module called Display Suite allows me to add my QuickTab block to the content display as a custom dynamic field.
Having built my contextually filtered views, compiled them into a tabbed display, and embedded those tabs into my content display, I now have my Related Cards tables viewable on each note-card in the system: