Dec 15 2010
Dec 15

Drupal 7 is right around the corner, and my efforts to see how it would work on my existing server made me decide it is time to move to another hosting company. I need more control over my own space, and what is, or is not, installed. After discussions with the inestimable Laura Scott (@lauras), my go-to person for anything Drupal, I've decided on a Linode VPS account.

Linode has attracted a good Drupal community, which is important to me. In addition, it provides an extremely easy to use interface, which makes it quite simple to manage the space. I also like the fact that the company provides a good selection of documentation on how to do things geared to its own environment.

Since I'm making a major Drupal upgrade and moving to a new server, now is the time to look seriously at how my web sites are configured and designed, and make changes. I think this is one of the advantages to major releases—they provide a time to stop, think, and decide if you want to keep what you, or if now is the time to make all those other little changes you've been thinking about.

Since I've designed my own Drupal themes, I need to upgrade them to Drupal 7, as well as incorporate new HTML5/RDFa features. I may even do a re-design, not sure yet. I don't like web site designing, so I may just grab one of the existing Drupal themes, and tweak it.

Several of my sites haven't been updated in a donkey's age, so I need to figure out if I'm going to continue writing at the sites. I probably will keep most, if not all, but I may do some major re-organizing.

I've not been taking many photos this year, as some of you have noticed. I need to re-design my photo pages to incorporate Drupal 7 changes and also my changed photography habits.

I've become much more interested in eBooks and the ePub format this last year. I was looking at creating an ePub module for Drupal, but someone already started this effort(Drupal ePub Module). However, there's been little work on the module, and I'm thinking that an extension to the Print Module is a better approach. Or perhaps the best thing to do is just create an ePub friendly XHTML theme, and do a wget or curl on a book's pages and use one of the many existing ePub publishing tools to create an ePub eBook. It's better to be a smart developer than a clever one, and smart developers use what exists. Plus the same pages can be used to create a Kindle book, a Nook, and others.

I have been thinking of incorporating Disqus into some of my web sites. I've used this service at other sites, and I like how it works. Commenters can edit their comments, track their discussions across many sites, and they don't have to provide a username and password for each web site (*cough* Gawker) to expose to hackers. Plus, if I turn comments off, the people still have access to their own writing. And Drupal has a module for Disqus, though I've not been able to get it to work with my theme (another reason to re-design my pages).

One thing I really like about Drupal 7 is if you don't like the new administration interface, you can turn off all the new bits. You can turn off the overlay (don't like), the page-top toolbar (still considering), and the new Dashboard (a keeper). I also like the fact that all the modules I use now are either incorporated directly into Drupal 7, or the developers have guaranteed a first day Drupal 7 release. Most of the modules have also committed to accessibility—that's something you don't often see with content management systems. Or W3C specifications.

Oct 11 2010
Oct 11

I made my first attempt to use the new Drupal 7 beta to upgrade my existing module experiment site. Unfortunately, I quickly ran into a fatal error:

DatabaseSchemaObjectExistsException: Table cache_path already exists. in DatabaseSchema->createTable() (line 621 of /home/myname/public_html/books/includes/database/schema.inc).

I submitted a bug for the error at the time it happened. Checking back later, though, I couldn't find the bug. I assumed I had mucked it up somehow when submitting, so re-submitted it. However, when I checked a couple of minutes later, I couldn't find the second bug. I noticed then that when you access My Issues, it only shows open bugs. When I adjusted to show all bugs, I found that my bugs had been quickly closed out by someone saying they were duplicates of another.

I can understand the enthusiasm the developers have with wanting to close out bugs quickly, but unfortunately, my bug was not a duplicate of the bug so noted. What caused the problem, though, is known, but the error message I received was inaccurate.

Drupal 7 is dependent on the PHP Data Objects (PDO) extension that is now in PHP core. Previously, we could add PDO via PECL—the PHP Extension Community Library. However, the PECL PDO is out of date and Drupal 7 now only supports the core PDO.

One problem with this, though, is that cPanel, the site management tool popular with many Shared Hosting companies, disabled PHP core PDO because of compatibility issues. It's only been recently that the application has stopped disabling PDO, but hosting companies like mine are still in the process of upgrading to the PHP core PDO. Until these companies make this upgrade, we can't upgrade to Drupal 7.

The problem is further compounded by the fact that the Drupal 7 upgrade doesn't test for the appropriate version of PDO, and we get bizarre errors such as the one I described earlier. Luckily, there is now a patch, which I ended up testing yesterday and that should give people the appropriate error. The problem with it, though, is that it recommends people check out the requirements page for Drupal, which, among other things, informs people that they can install PDO with PECL.

screenshot of Drupal requirements page with PECL PDO instruction highlighted

Hopefully, the disconnects will soon be corrected, and most folks are in environments where the PDO is from PHP core, rather than PECL. I was impressed at how fast everyone did jump on this after the initial duplicate bug mistake was discovered. Once the patch is in place, and the documentation updated, people will at least now know why they can't upgrade and can chat with their hosting provider about the necessary upgrade.

Until my own shared environment is upgraded, though, I'll have to stay in 6.x land. Many thanks to Everett Zufelt for his help in pulling all the Drupal pieces together for me.

Sep 05 2009
Sep 05

Recently, a group of well known web designers issued a "Super Friends" declaration of support or HTML5, with an attached set of concerns. Most of the concerns had to do with the new "semantic markup" elements included in HTML5, such as section, article, and so on. I've not previously discussed these new semantic page markup elements, because I had other fish to fry. However, I decided to take a closer look at the elements, particularly at how I would use them for my Drupal sites.

Current Setup

Currently my page has a header, a footer, one sidebar, and the main content area. I have an H1 title for the page, and use H2 for weblog post titles, and H3 for sidebar titles.

I have a main navigation bar at the top of the page in the header, with a skip link for screenreaders. I also display an exploded view of my site navigation in the footer, in addition to copyright/about links. The sidebar contains additional navigational aids, such as links for monthly archives, recent writings, popular items, images, and so on.

All of the content areas are structured using a variety of unordered list items and DIV elements—all of which is typical, not only for a Drupal site, but also Wordpress sites, and other CMS themed variations. I also use inline SVG for decoration.

Conversions: header, nav, and hgroup

Starting from the top, according to the HTML5 specification, I would use a header element to encapsulate the content that is currently contained within my DIV element given a class name of headwrap. This would include the top-level navigation, as well as the site title, which remains as an H1 header. According to the spec, the header doesn't take part in the web page's outline, which would map to what I would expect, both as a web designer and as a book author. In particular, as a book author, I wouldn't expect the book title and subtitle to be part of the outline, nor would I expect the Table of Contents to actually display as part of the outline given in the TOC, and a book's TOC, and a site's navigation menu are synonymous.

In addition, I would also convert the DIV containing my site's navigation to using the new nav element, wrapping it around the existing list items. From a Drupal perspective, the nav element maps to the Primary Links block that is standard with all Drupal installations. If I used the Secondary Links block, I would wrap also it in a nav element, and place it just below the main navigation menu.

Though I've seen several articles that list the nav element separate from the header, I would embed the nav element within the header, because I consider the main navigation to be part of the introductory text that the page header is supposed to contain. I think you could have them separate, but the key to determining whether they should be combined or separate is if the header part changes separately from the navigation section. If they're not consistent with each other, they probably shouldn't be grouped. If they are, they're grouped. My main navigation and header contents never change, so I'm grouping them within header. Regardless of choice, the HTML5 specification does seem to support both variations of grouped and ungrouped header and nav.

My main navigation menu contains a skip link, which is a link that's intended to take the person to the content area directly. There's no harm in the link, and until screenreaders adapt fully to HTML5, I'll keep the link.

Drupal also provides for a secondary title, or tagline area, which I don't use. If I did, though, I would use the hgroup to group the H1 for the title and the H2 used for the secondary title. I know folks have had problems with hgroup, but as a book author, I'm aware of title and subtitle, and how they're treated as one single entity, though with differing formatting. It really wasn't a stretch to extend this concept to a web page, and the fact that hgroup just allows me to use two different heading element types, but treated as one unit. The element also ranks the headings within the hgroup by highest *header value, which is what I would expect.

Next comes the main content.

Conversion: Main content area, article and section

The main content is a little tricker, but again, I found if I looked at the HTML5 specification more as a book author, and less as a web designer, I felt a little more comfortable with the new elements.

Currently, all of my content, including header, sidebar, and footer, is wrapped in one big DIV element with a class name of rap. I wouldn't change this, primarily because the overall wrapping has nothing to do with semantics, and everything to do with overall structure and presentation. It is actually synonymous with the body element, and used primarily to manage the margins of the content. Since the body element is, by definition, its own semantic element, defining the rap element using semantic markup is redundant.

For the actual content area, currently I have a DIV element wrapping all of the postings, and then list of one or more postings, each with an H2 header, a metadata section, the main content, and an inner footer containing other links, such as those for adding comments, number of page views, and so on.

After careful reading of both the section and article elements, as well as looking at past articles on the elements [1][2][3][4], I decided I would wrap the entire content area in a section element, though I'm ambivalent on this, and think that keeping it wrapped in a DIV would also work. The reason why I could keep the section as a DIV, is there is nothing about this section that is inherently useful, other than being a group of content. For each individual page, it's actually redundant, because the main content area, and the article, would be synonymous. Since, there's nothing semantically useful about the main content, the use of a DIV element would be acceptable, even preferred.

However, I thought about my use of the skip link, and the fact that it goes to the main content area. This, in a way, provides semantic justification to actually use a section element—it's meaning extends beyond styling. The section is, according to the HTML5 spec, a thematic grouping of content, typically with a heading, possibly with a footer. One could even add a header, with "Main Content", and there wouldn't be anything out of the ordinary about it.

Converting the markup for the weblog post was a somewhat simpler task. It's a given that each weblog post would be wrapped in an article element, especially since this type of element is used with content that can be stand alone, or pulled directly from the page and reproduced elsewhere. Think of syndication feeds, and what works for the web page, works for the feed, and hence, using article is a natural choice. How I would mark up the content within the article, though, gets a bit tricker. I had to put my web designer hat away, and put on my book author beanie with the rest of the content conversion.

Within the article element then, I would add a header for the title, and the address element for the author name. Since address is really meant for "contact" information, I would also wrap the author name in a link for the author's contact page, or email address, I'm not sure which at the moment.

I have other material at the beginning of a weblog post that doesn't seem to fit within any element, such as publish date, and taxonomy. And this is where things really get tricky.

Should I continue using a DIV element for this data? Or is this where I would use a new section? There is a time element, but it is described as a machine readable element for adding information to a calendar, and not appropriate for my date, at all. Plus, I use **RDFa for marking up all of my metadata such as this, and I'm not sure how Dublin Core data will work with the time element.

But hold on folks...the time element has a second definition, which is semantically different. There is an attribute, pubdate, associated with time. This is a boolean value. If set to false, then time is a calendar event; if set to false, then time is an actual publication date, if the time element is contained within and article. So I would use time but make sure that pubdate is set to true. I would also add my RDFa annotation to the time element.

I'm not entirely happy about the overloaded semantics of the time element, but grudgingly willing to use it. I'm not so bugged about the overloading to actually protest against the element, or refuse to use it, primarily because I really depend on RDFa to record my meaningful semantics in the web page.

As for the other material, such as the taxonomy items, I decided I would leave them in a DIV element, each with its own RDFa to annotate with the metadata information. I imagine I could use a section element, but frankly, it doesn't feel right. The information really isn't a new section, it's just annotative data about the article. But since it is annotative about the article, I believe it, like the time element should be in the article's header.

HTML Conversion: Aside, Figure and Legend

The rest of the article will be marked up with the usual mix of unordered lists, paragraphs, block quotes, and so on. Another change, though, will be the use of the new aside element. As a book author, I am aware of what a sidebar is, and how it's used: it's used to annotate text that doesn't have to be included within the flow of the page, but could be pulled out and placed elsewhere, depending on page layout. The text itself is related to the main chapter topic, but it's additional information that isn't necessary in order to follow the flow of the main text.

It's unfortunate that sidebar has another meaning in web page design, being use to refer to the a secondary column within the page flow that could contain navigational items, images, ads, and so on. What makes it doubly unfortunate is that the term sidebar is used to describe aside in the HTML5 specification, but the term is used as a book author or publisher would use the term, not a web designer.

Regardless, it could be a handy element, and I have no confusion about how it's meant to be used, though I'm concerned that current discussions will redefine it's use—to that of web design sidebar—in which case I won't use it.

Another main content element impacted by HTML5 is how to annotate images. Currently, I use the img element to mark images. However, HTML5 introduces the figure element, which can be used to wrap the img element, and also a legend element, which provides the image's caption. It's meant to be used when the figure is such that it could be pulled, along with its caption, to a separate space within the web site, such as an appendix.

Again, thinking more like a book author and less like a web design person, figure makes perfect sense. You wouldn't use it to wrap decorative images that you insert into an article to add a bit of color or flair, but you should use it when you reference the image from the text, or it serves an illustrative purpose.

There has been some pushback on figure primarily because legend has been redefined from HTML 4, where it was used with a form fieldset. However, I think of it less as a redefinition, and more of a extension of the same capability to new areas. My main concern is how existing browsers would handle the element when they parse it. That's the real issue when you redefine or extend the purpose of an element in HTML5 that existed in prior HTML versions. Still, unless I find browsers throw a hissy fit, I would probably use figure and legend. I would also continue using the alt attribute to mark up the image for accessibility purposes. Speaking of accessibility...

HTML Conversion: Accessibility and ARIA

I am committed to making my pages as accessible as possible, and that also includes the use of the summary attribute for data tables, as well as using the newly defined ARIA annotation of HTML5 elements [5]. The changes to accommodate the new attributes, role and aria-* are extensive, and will require a careful perusal of their purposes, to ensure I understand how best to use them.

However, it shouldn't be overly difficult to incorporate the ARIA annotation, especially with a tool like Drupal, and especially with Drupal 7, when we'll have a much finer control of the page generation.

HTML Conversion: Article and Footer, Article and Comments

At the end of my weblog posts is more information, such as a link to add comments, comment count, page views, and so on. This data is currently enclosed in a DIV element. From my understanding of the HTML5 description, I should be using footer to encapsulate this information.

In addition, from my understanding of the HTML5 specification, I should use a section element to wrap the entire comment area, and then use article for each comment, each with its own little header and footer. It seems like a lot of elements, but all of these items are currently wrapped in DIV elements, so the number of elements will end up virtually the same after conversion.

This ends the description of the main content area. Other elements will be used in the main content, including SVG, possibly MathML, and video, code, pre, and ***dialog, but I'll leave these for another time. Next up, is a discussion on the remaining two sections of the web page: the sidebar and the main page footer.

HTML Conversion: Sidebar and main page Footer

One thing I would definitely not do, is use aside for the web document's sidebar. Not as it is currently defined, and if it gets redefined, I still wouldn't use it.

The use of section to enclose the sidebar makes sense. If you think on it, my current document isn't main content and sidebar—it's two columns, with different data in each. So, if you use section for one column, you should use section for the other column(s).

Within the sidebar, though, I use DIV elements to manage the different display blocks. Technically I suppose I could use the section element for these, but I use DIV elements specifically to control the spacing, layout, and presentation of the data in the sidebar. To me, this fits the semantic purpose of DIV, which is a perfectly acceptable element. I will continue to use the DIV element when I'm grouping content specifically because I want to group them for a specific reason, and that reason is more to do with styling or ease of access than because of any semantic meaningfulness.

However, I will annotate the contents of the sidebar (or second column, if you will), with ARIA annotations, as well as RDFa, and make use of unordered lists to display lists of items. I'm not throwing semantics to the wind.

As for the page footer, it is odd to have a footer associated with each article, and then have a page footer. However, the content already has class names to mark the differences (including how each is styled), and I will continue with those class names. As a book author, I think of article footer as footnotes for a page, and web page footer as end notes for a chapter, or book. Gets me through the web designer angst with multiple footers in a page.

Currently my web pages have an exploded site menu contained in the footer. I suppose one should wrap this in a nav element also. Originally, the footer was defined in such a way that it couldn't contain a nav element, but I gather that feedback on this item has changed the HTML5 author's mind, and we can now use a nav element in footer. Hard to say, the information isn't readily apparent to a web page author from the HTML5 document.

The footer will contain an address element with contact information, and probably a section to enclose the other data, such as copyright.

The overall page footer does make me wonder, though, whether I shouldn't convert the overall DIV element identified as "rap" to a section because the footer element is associated with sectioned content, which includes article, aside, section, and nav. Actually, the more I think on this one, the more I think I'll convert "rap" to a section element, too.

HTML Conversion: the remaining issues

I still have other content that I need to convert. This includes the page level navigation that's at the end of a Drupal book, or at the bottom of archive and main pages. One would think to use the nav element, but the description of the element seems to preclude its use:

The nav element represents a section of a page that links to other pages or to parts within the page: a section with navigation links. Not all groups of links on a page need to be in a nav element — only sections that consist of major navigation blocks are appropriate for the nav element. In particular, it is common for footers to have a list of links to various key parts of a site, but the footer element is more appropriate in such cases, and no nav element is necessary for those links.

This also makes me wonder about the use of nav to wrap my exploded site map in the footer, as described in the last section. The same goes for the sidebar links for archives, popular content, and recent writings: these are, technically navigation aids. However, they don't seem to fit the constraints surrounding nav. In fact nav seems to be more about a site's main menu than necessarily navigation, provided more as a way of eliminating the skip link than actually annotating navigation. The nav element definitely needs more clarification about its use. Right now, the description of when to use it is too vague.

I'll have to think more on the use of nav, not to mention section, article, header, and so on. But I think I've made a good start on converting to an XHTML5 document. To continue, I would do what others are currently doing, and rename class and identifiers on my DIV elements to what their HTML5 equivalents will be, just to test out how it all works together, and still ensure proper CSS support in all browsers.

I'm not ready to convert to XHTML5 yet, though, not while there are unanswered questions, and unresolved issues. For instance, I did an HTML5 page with an inline SVG graphic served as HTML, which should be valid, though no browser currently renders inline SVG in HTML. However the HTML5 validator throws numerous errors. There are deep gaps in understanding between web page author and implementors, and among web page authors and implementors, about what is "valid" or "conforming" HTML5. Too deep, and too many to roll out for a production site. Perhaps after Last Call.

*The biggest problem I have with the new HTML5 elements is their names. Prior to HTML5, when we talk about header we were talking about a generic entity, page fragment, or concept. Now, when I mention header in context with HTML5, am I mentioning the element? Or am I referencing the concept? The same applies to section, article, and footer. Sometimes using common names is not the best solution when it comes to designing a new markup language. Still, we'll have to hope that the context of use will be enough to differentiate between generic concept and specific element.

**Currently, I serve my pages up as application/xhtml+xml, so it's no problem incorporating RDFa into the content. Contrary to the persistent rumor, XHTML is alive an well in HTML5 (though the encapsulation of XHTML within a document labeled "HTML5" has been caused considerable confusion). However, the RDFa community is currently working on a new draft of RDFa that will allow RDFa annotation in documents served up as plain HTML, too. This is important, because RDFa is incorporated, by default, into Drupal 7, as well as being the format most used for Creative Commons licenses, and some of Google's new metadata search efforts. In many cases the documents involved are served as HTML, not XHTML. Whatever happens, and by whom, RDFa will exist in HTML5, regardless of whether the document is served as HTML or XHTML, and regardless of whether such use is deemed "conforming" or not.

***I dislike the dialog element. I do not like redefining the behavior for the dt and dd elements based on the container element (dialog or definition list element, dl). I understand about issues associated with redefining definition lists for dialogs, but the state isn't improved when you redefine the semantics of dd and dt, depending on their container. Nothing is gained.

Jun 21 2009
Jun 21

I've finished the re-organization of my web site, though I have odds and ends to finish up. I still have two major changes featuring SVG and RDFa that I need to incorporate, but the structure and web site designs are finished.

Thanks to Drupal's non-aggressive use of .htaccess, I've been able to create a top-level Drupal installation to act as "feeder" to all of the sub-sites. I tried this once before with Wordpress, but the .htaccess entries necessary for that CMS made it impossible to have the sub-sites, much less static pages in sub-directories.

Rather than use Planet or Venus software to aggregate feed entries for all of my sites, I'm manually creating an excerpt describing a new entry, and posting it at Burningbird, with a link back to the full article. I also keep a listing of the last few months stories for each sub-site in the sidebar, in addition to random display of images.

There is no longer any commenting directly on a story. One of the drawbacks with XHTML and an unforgiving browser such as Firefox, is that a small error is enough to render the page useless. I incorporate Drupal modules to protect comments, but I also allow people to enter in some markup. This combination handles most of the accidentally bad markup, but not all. And it doesn't protect against those determined to inject invalid markup. The only way to eliminate all problems is not allow any markup, which I find to be too restrictive.

Comments are, however, supported at the Burningbird main site. To allow for discussion on a story, I've embedded a link in every story that leads back to the topmost Burningbird entry, where people can comment. Now, in those infrequent times when a comment causes a problem with a page, the story is still accessible. And there is a single Comment RSS feed that now encompasses all site comments.

The approach may not be ideal, but commentary is now splintered across weblog, twitter, and what not anyway—what's another link among friends?

I call my web site design "Silhouette" and will release it as a Drupal theme as soon as it's fully tested. It's a very simple two column design, with sidebar column either to the right (standard) or easily adjusted to fall to the right. It's an accessible design, with only the top navigation bar coming between the top of the page and the first story. It is valid markup, as is, with the XHTML+RDFa Doctype, because I've embedded RDFa into the design. It is not valid, however, when you also add SVG silhouettes, as I do with all but the top most site.

The design is also valid XHTML 5.0, except for a hard coded meta element that was added to Drupal because of security issues. I don't serve the pages up as HTML 5, though, because the RDFa Doctype triggers certain behaviors in RDFa tools. I'm also not using any of the new HTML 5 structural elements.

The site design is plain, but it suits me and that's what matters. The content is legible and easy to locate, and navigate, and that's my second criteria. I will be adding some accessibility improvements in the next few months, but they won't impact on the overall design.

What differs between all of the sites is the header graphic, and the SVG silhouettes, which I changed to suit the topic or mood of the site. The silhouettes were a lot of fun, but they aren't essential, and you won't be able to see them if you use a browser that doesn't support SVG inline. Which means you IE users will need to use another browser to see the images.

I also incorporate some new CSS features, including some subtle use of text-shadows with headers (to add richness to the stark use of black text on pastel graphics) and background-color: rgba functionality for semi-transparent backgrounds. The effects are not viewable by browsers that don't yet support these newer CSS styles, but loss of functionality does not impact access to the material.

Now, for some implementation basics:

  • *I manually reviewed all my old stories (from the last 8 years), and added 410 status codes for those I decided to permanently remove.
  • For the older stories I kept, I fixed up the markup and links, and added them as new Drupal entries in the appropriate sub-site. I changed the dates to match the older entries, and then added a redirect between the old URL and the new.
  • By using one design for all of the sites, when I make a change for one, it's a snap to make the change for all. The only thing that differs is the inline SVG in the page.tpl.php page, and the background.png image used for the header bar.
  • I use the same set of Drupal modules at all sub-sites, which again makes it very easy to make updates. I can update all of my 7 Drupal sites (including my restricted access book site), with a new Drupal release in less than ten minutes.
  • I use the Drupal Aggregator module to aggregate site entries in the Burningbird sidebar.
  • I manually created menu entries for the sub-site major topic entries in Burningbird. I also created views to display terms and stories by vocabulary, which I use in all of my sub-sites.
  • The site design incorporates a footer that expands the Primary navigation menu to show the secondary topic entries. I've also added back in a monthly archive, as well as recent writings links, to enable easier access of site contents.

The expanded primary menu footer was simple, using Drupal's API:


<?php
$tree = menu_tree_all_data('primary-links');
print menu_tree_output($tree);
?>

To implement the "Comment on this story" link for each story, I installed the Content Construction Kit (CCK), with the additional link module, and expanded the story content type to add the new "comment on this story" field. When I add the entry, I type in the URL for the comment post at Burningbird, which automatically gets linked in with the text "Comment on this story" as the title.

I manually manage the link from the Burningbird site to the sub-site writing, both because the text and circumstance of the link differs, and the CCK field isn't included as part of the feed. I may play around with automating this process, but I don't plan on writing entries so frequently that I find this workflow to be a burden.

The images were tricky. I have implemented both the piclens and mediaRSS Drupal Modules, and if you access any of my image galleries with an application such as Cooliris, you'll get that wonderful image management capability. (I wish more people would use this functionality for their image libraries.)

I also display sub-site specific random images within the sub-site sidebars, but I wanted the additional capability to display random images from across all of the sites in the topmost Burningbird sidebar.

To get this cross-site functionality, I installed Gallery2 at http://burningbird.net/gallery2, and synced it with the images from all of my sub-sites. I then installed the Gallery2 Drupal module at Burningbird (which you can view directly) and used Gallery2 plug-ins to provide random images within the Drupal sidebar blocks.

Drupal prevented direct access from Gallery2 to the image directories, but it was a simple matter to just copy the images and do a bulk upload. When I add a new image, I'll just pull the image directly from the Drupal Gallery page using Gallery2's image extraction functionality. Again, I don't add so many images that I find this workflow to be onerous, but if others have implemented a different approach, I'd enjoy hearing of alternatives.

One problem that arose is that none of the Gallery2 themes is XHTML compliant because of HTML entity use. All I can say is: folks, please stop using &nbsp;. Use &#160; instead, if you're really, really generating XHTML, not just HTML pretending to be XHTML.

To fix the non-compliant XHTML problem, I copied a version of my site to a separate theme, and just removed the PHP that serves the page up as XHTML for XHTML-capable browsers from this "Silhouette for HTML" theme. The Gallery2 Drupal modules allow you to specify a different theme for the Gallery2 pages, and I use the new HTMLated theme for the Gallery2 pages. I use my XHTML compliant theme for the rest of the site. Over time, I can probably add conditional tests to my main theme to test for the presence of Gallery blocks, but what I have is simple and works for now.

Lastly, I redirected the old Planet/Venus based feed locations to the Burningbird feed. You can still access full feeds from all of my sub-sites, and get full entries for all but the larger stories and books, but the entries at Burningbird will be excerpts, except for Burningbird-only posts. Speaking of which, all of my smaller status updates, and general chit-chat will be made directly at Burningbird—I'm leaving the sub-sites for longer, more in-depth, and "stand alone" writings.

As I mentioned earlier, I still have some work with SVG and RDFa to finish before I'm completely done with the redesign. I also have some additional tweaks to make with the existing infrastructure. For instance, I have custom 404, 403, and 410 error pages, but Drupal overrides the 403 and 404 pages. You can redirect the error handling to specific pages, but not to static pages, only to pages within the Drupal system. However, I'm not too worried about this issue, as I'm finding that there's typically a Drupal module for any problem, just waiting to be discovered.

I know I must come across as a Drupal fangirl in this writing, but after using the application for over a year, and especially after this site redesign, I have found that no other piece of software matches my needs so well as Drupal. It's not perfect software—there is no such thing as perfect software—but it works for me.

* This process convinced me to switch fully from using Firefox to using Safari. It was so much more simple to fix pages with XHTML errors using Safari than with Firefox's overly aggressive XHTML error handling.

May 23 2009
May 23

There's been a great deal of discussion about RDFa, HTML5, and microdata the last few days, on email lists and elsewhere. I wanted to write down notes of the discussions here, for future reference. Those working issues with RDFa in Drupal 7 should pay particular attention, but the material is relevant to anyone incorporating RDFa.

Shane McCarron released a proposal for RDFa in HTML4, which is based on creating a DTD that extends support for RDFa in HTML4. He does address some issues related to the differences in how certain data is handled in HTML4 and XHTML, but for the most part, his document refers processing issues to the original RDFaSyntax document.

Philip Taylor responded with some questions, specifically about how xml:lang is handled by HTML5 parsers, as compared to XML parsers. His second concern was how to handle XMLLiteral in HTML5, because the assumption is that RDFa extractors in JavaScript would be getting their data from the DOM, not processing the characters in the page.

"If the object of a triple would be an XMLLiteral, and the input to the processor is not well-formed [XML]" - I don't understand what that means in an HTML context. Is it meant to mean something like "the bytes in the HTML file that correspond to the contents of the relevant element could be parsed as well-formed XML (modulo various namespace declaration issues)"? If so, that seems impossible to implement. The input to the RDFa processor will most likely be a DOM, possibly manipulated by the DOM APIs rather than coming straight from an HTML parser, so it may never have had a byte representation at all.

There's a lively little sub-thread related to this one issue, but the one response I'll focus on is Shane, who replied, RDFa does not pre-suppose a processing model in which there is a DOM. The issue of xml:lang is also still under discussion, but I want to move on to new issues.

While the discussion related to Shane's document was ongoing, Philip released his own first look at RDFa in HTML5. Concern was immediately expressed about Philip's copying of some of Shane's material, in order to create a new processing rule section. The concern wasn't because of any issue to do with copyright, but the problems that can occur when you have two sets of processing rules for the same data and the same underlying data model. No matter how careful you are, at some point the two are likely to diverge, and the underlying data model corrupted.

Rather than spend time on Philip's specification directly at this time, I want to focus, instead, on a note he attached to the email entry providing the link to the spec proposal. In it he wrote:

There are several unresolved design issues (e.g. handling of case-sensitivity, use of xmlns:* vs other mechanisms that cause fewer problems, etc) - I haven't intended to make any decisions on such issues, I've just attempted to define the behaviour with sufficient detail that it should make those issues visible.

More on case sensitivity in a moment.

Returning to Philip's issue with case sensitivity, I took one of Shane's RDFa in HTML test cases, and the rdfquery JavaScript from Philip's test suit, and created pages demonstrating the case sensitivity issue. One such is the following:

<!DOCTYPE HTML PUBLIC "-//ApTest//DTD HTML4+RDFa 1.0//EN" "http://www3.aptest.com/standards/DTD/html4-rdfa-1.dtd">
<html
xmlns:t="http://test1.org/something/"
xmlns:T="http://test2.org/something/"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<head>
<title>Test 0011</title>
</head>
<body>
<div about="">
Author: <span property="dc:creator t:apple T:banana">Albert Einstein</span>
<h2 property="dc:title">E = mc<sup>2</sup>: The Most Urgent Problem of Our Time</h2>
</div>
</body>
</html>

Notice the two namespace declarations, one for "t" and one for "T". Both are used to provide properties for the object being described in the document: t:apple and T:banana. Parsing the document with a RDFa application that applies XML rules, treats the namespaces, "t" and "T" as two different namespaces. It has no problem with the RDFa annotation.

However, using the rdfquery JavaScript library, which treats "t" and "T" the same because of HTML case insensitivity, an exception results: Malformed CURIE: No namespace binding for T in CURIE T:banana. Stripping away the RDFa aspects, and focusing on the namespaces, you can see how browsers handle namespace case in an HTML document and in a document served up as XHTML. To make matter more interesting, check out the two pages using Opera 10, Firefox 3.5, and the latest Safari. Opera preserves the case, while both Safari and Firefox lowercase the prefix. Even within the HTML world, the browsers handle namespace case in HTML differently. However, all handle the prefixes the same, and correctly in XHTML. So does the rdfquery JavaScript library, as this test page demonstrates.

Returning to the discussion, there is some back and forth on how to handle case sensitivity issues related to HTML, with suggestions varying as widely as: tossing the RDFa in XHTML spec out and creating a new one; tossing RDFa out in favor of Microdata; creating a best practices document that details the problem and provides appropriate warnings; creating a new RDFa in HTML document (or modifying existing profile document) specifying that all conforming applications must treat prefix names as case insensitive in HTML, (possibly cross-referencing the RDFa in XHTML document, which allows case sensitive prefixes). I am not in favor of the first two options. I do favor the latter two options, though I think the best practices document should strongly recommend using lowercase prefix names, and definitely not using two prefixes that differ only by case. During the discussion, a new conforming RDFa test case was proposed that tests based on case. This has now started its own discussion.

I think the problem of case and namespace prefixes (not to mention xmlns as compared to XMLNS) is very much an edge issue, not a show stopper. However, until a solution is formalized, be aware that xmlns prefix case is handled differently in XHTML and HTML. Since all things are equal, consider using lowercase prefixes, only, when embedding RDFa (or any other namespace-based functionality). In addition, do not use XMLNS. Ever. If not for yourself, do it for the kittens.

Speaking of RDFa in HTML issues, there is now a new RDFa in HTML issues wiki page. Knock yourselves out.

updateA new version of the RDFa in HTML4 profile has been released. It addresses a some of the concerns expressed earlier, including the issue of case and XMLLiteral. Though HTML5 doesn't support DTDs, as HTML4 does, the conformance rules should still be good for HTML5.

May 03 2009
May 03

I don't know if I'm the only one seeing a white page on the site, but since the upgrade to 6.11 in Drupal, I've had problems accessing all my sites. The problem could also be my hosting, and I'm currently exploring the possibility of moving. However, the problem has become much, much worse with the 6.11 upgrade. If you've had problems accessing the site, let me know.

I now have seven Drupal installations, though two are "stealth". One I'm using to write my new book. I stripped away all styling and then designed a Drupal theme that supports ePub. I'll be adding a second theme that supports Mobi/Amazon, and possibly a third that supports a PDF book. One of the advantages of being comfortable with XHTML is that you can take your mad XHTML markup skillz to the eBook world with only a little effort. Once I've published the book, and know the themes are working 100% I'll upload them to the Drupal theme site, for people who want to use Drupal to write eBooks.

I will say that self-publishing is a different world now. There are so many resources. One wall I hit, though, was getting an ISBN. I could swear these were free at one time, but now, ISBNs in the US have been "contracted out" from the government to a privately owned monopoly.

You don't need an ISBN for an eBook, though some sellers prefer ones. But if you're going hard copy as well as eBook, which I am, you'll have to have one. You can also "borrow" an ISBN from some distribution companies, but they don't recommend this approach, because you're then stuck with them as publisher. You can also buy a single ISBN, but it's a lot cheaper just to buy a block of ten, and then if you need a new ISBN for another edition, or a new book, you have it.

It's just that having to buy an ISBN wasn't a cost I was expecting. Again, these are free throughout the world. Only in America do we contract what should be universally accessible to monopolies. How else to explain our cable systems?

Regardless of the unexpected expenses, there's something very rich, and satisfying, about having some control in all aspects of my book. O'Reilly is a good publisher, and the company has been generous with me, but I've always felt out of the loop with my books. For instance, I didn't know my books were going to be published to the Kindle until after the fact. I didn't know they were all being released as DRM free ebooks on the Kindle until after the fact. I'm happy about the books being offered DRM free, but I sure would have appreciated a quick note before hand.

(Not to mention having some say in the cover, formatting, and subtitles...)

No, the success or failure of a self-published book is really dependent on the author. This is both scary, and wonderful.

Mar 01 2009
Mar 01

I have been focused on OpenID implementations lately, specifically in WordPress and Drupal. The Drupal effort is for my own sites.

Until this weekend, I had turned off new user registration at my Drupal sites, because I get too many junk user registrations. However, to incorporate OpenID into a Drupal site, you have to allow users to register themselves, regardless of whether they use OpenID or not.

I think this all or nothing approach actually limits the incorporation of OpenID within a Drupal site. If you limit registration to administrator's only, then people can't use their OpenIDs unless the administrator gets involved. If you allow people to self-register, there's nothing to stop the spammy registrations.

I believe that OpenID should be an added, optional field attached to the comment form, allowing one to attach one's OpenID directly to a comment, which then creates a limited user account within the site specifically for the purposes of commenting. Rather than just providing options to allow a user to register themselves, or not, add another set of options specific to OpenID, and allow us to filter new registrations based on the use of OpenID.

Currently the new user registration options in Drupal 6x are:

  • Only site administrators can create new user accounts.
  • Visitors can create accounts and no administrator approval is required.
  • Visitors can create accounts but administrator approval is required.

Turn on the latter two options and you'll get spammy registrations within a day. Not many, but annoying. I believe there should be a fourth and fifth option:

  • Visitors can create accounts using OpenID, only, and no administrator approval is required.
  • Visitors can create accounts using OpenID, only, but administrator approval is required.

With these new options, I could then open up new user registration for OpenID, but without having to allow generic new user registration for the account spammers that seem to be so prevalent with Drupal.

To attempt to implement this customized functionality at my sites, I've been playing with Drupal hooks, but the change is a little more extensive than just incorporating a hook handler and a few lines of code, at least for someone who is relatively new to Drupal module development like I am.

Taking the simplest route that I could implement as a stand alone module, what I'm trying now is to modify the new user registration forms so that only the OpenID registration links display. You'll see this, currently, in the sidebar if you access the site and you're not logged in. Unfortunately, you have to click on the OpenID link to open the OpenID field, because I'm still trying to figure out how to remove the OpenID JavaScript that hides the field (there is a function to easily add a JavaScript library, but not one to remove an added library).

With my module-based modifications, rather than a person having to click a link to create a new account, and specify a username and password, they would provide their OpenID, and I would automatically assign them a username via autoregistration. To try my new sidebar module, I decided to turn my Durpal sites into OpenID providers, as well as clients, and use one of them as a test case. Provider functionality is not built in, but there is an OpenID provider module, which I downloaded and activated with my test Drupal installation (MissouriGreen).

I tried my new module and OpenID autoregistration, but ran into a problem: the Drupal client does not like either the username or email provided via the Drupal OpenID provider. Why? Because the OpenID identifier used in the registration consists of the URL of the Provider, which is the URL of the Drupal site I used for my test, and the Drupal client does not like my using a URL. In addition, the provider also didn't provide an email address.

User account | Bb RealTech

Digging into the client side code, I discovered that the Drupal OpenID client supports an OpenID extension, Simple Registration. Simple Registration provides for an exchange of the 9 most requested information between the OpenID client and provider: nickname, email, fullname, dob (date of birth), gender, postcode, country, language, and timezone. With Simple Registration you can specify which of the items is optional and which mandatory, and the current OpenID client wants nickname and email.

By using Simple Registration on the provider, I could then provide the two things that my Drupal OpenID client wanted: nickname and email. Unfortunately, though, the current version of the OpenID provider doesn't support Simple Registration. I was a little surprised by this, as I had made an assumption that the Drupal OpenID provider would work with the Drupal OpenID client. However, OpenID is in a state of flux, so such gaps are to be expected.

Further search among the Drupal Modules turned up another module, the Drupal Simple Registration module, which allows one to set the mandatory and optional fields passed as part of the OpenID authentication exchange. The only problem is that the OpenID Provider also doesn't have any incorporated hooks, which would allow the Simple Registration module to provide the Simple Registration data as part of the response. To add these hooks, the Simple Registration module developer also supplied a patch that can be run against the OpenID Provider code to add the hook.

I applied the patch and opened the module code and confirmed that it had been modified to incorporate the hook. I then tried using the Drupal site as OpenID provider again, but the registration process still failed. Further tests showed that the Simple Registration data still was not being sent.

All I really want to do is test the autoregistration process, so I abandoned the Drupal OpenID provider, and decided to try out some other providers. However, I had no success with either my Yahoo account or my Google GMail account, even though I believed both provided this functionality. The Yahoo account either didn't send the Simple Registration fields, or failed to do so in a manner that the Drupal OpenID client could understand. The Gmail account just failed, completely, with no error message specifying why it failed.

I felt like Barbie: OpenID is hard!

I finally decided to use phpMyID, which is a dirt simple, single user OpenID application that we can host, ourselves. I had this installed at one time, pulled it, and have now re-installed at my base burningbird.net root directory. I added the autodiscovery tags to my main web page, and uncommented the lines in the MyID.config.php file for the nickname, fullname, and email Simple Registration fields. I then tried "http://burningbird.net" for OpenID autoregistration at RealTech. Eureka! Success.

The new user registration is still currently blocked at creation, but the site now supports autoregistration via OpenID. Unfortunately, though, the registration spammers can still access the full account creation page, so I can still get spammy registrations. However, I believe that this page can be blocked in my mandatory OpenID module, with a little additional work; at least until I can see about possibly creating a module that actually does add the OpenID only options I mentioned above. The people who generate spammy user account registrations could use OpenID themselves, but the process is much more complex, and a lot more controlled at the provider end point, so I think this will help me filter out all but the most determined spammy registraters.

Once all of this is working, I'll see about adding the OpenID login field to the comment form, rather than in the sidebar. If one wonders, though, why there isn't more use of OpenID, one doesn't have to search far to find the answers. Luckily for Drupal users, OpenID seems to be an important focus of this week's DrupalCon in Washington DC, including a specialized Code Sprint.

Nov 11 2008
Nov 11

You don't have to wait for Drupal 7 to RDFaificate your Drupal site. I spent yesterday tweaking my space, and if you access the site now with a tool, such as the Semantic Radar Firefox add-on, you'll see all sorts of semantic goodness. I used a combination of plug-ins and theme modifications to make my changes, and will probably add to the overall effect over time.

What simplified my RDFa integration is that my site was already being served up as valid XHTML, via a modification to my page.tpl.php file:

<?php
header("Vary: Accept");
if (stristr($_SERVER["HTTP_ACCEPT"], "application/xhtml+xml"))
    header("Content-Type: application/xhtml+xml; charset=utf-8");
else
    header("Content-Type: text/html; charset=utf-8");
?><!DOCTYPE html PUBLIC
    "-//W3C//DTD XHTML 1.1 plus MathML 2.0 plus SVG 1.1//EN"
    "http://www.w3.org/2002/04/xhtml-math-svg/xhtml-math-svg.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" 
xml:lang="<?php print $language->language ?>">

The PHP code checks with the user agent accessing the page. If the user agent accepts XHTML, the code returns the pages as XHTML; otherwise the pages are returned as HTML. However, the DOCTYPE I had been using was a SVG+MathML DOCTYPE, because of my sometimes use of embedded SVG. To validate as XHTML+RDFa, though, you need to use the RDFa DOCTYPE.


<?php
header("Vary: Accept");
if (stristr($_SERVER["HTTP_ACCEPT"], "application/xhtml+xml"))
    header("Content-Type: application/xhtml+xml; charset=utf-8");
else
    header("Content-Type: text/html; charset=utf-8");
?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML+RDFa 1.0//EN" 
   "http://www.w3.org/MarkUp/DTD/xhtml-rdfa-1.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" dir="ltr"
xmlns:foaf="http://xmlns.com/foaf/0.1/"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<head profile="http://ns.inria.fr/grddl/rdfa/">

The namespaces in the HTML opening tag don't reflect all that I'll use in my pages, just the ones I used for RDFa annotation sprinkled, liberally, throughout the page. When I use embedded SVG, I can just add the SVG namespaces directly into the opening SVG element tag. I could add the namespaces now, but I don't always use embedded SVG.

One unfortunate consequence of switching DOCTYPEs is that when I do use embedded SVG, the page won't validate. However, this won't impact on the user agents and their ability to process the SVG correctly, so I'll just have to live with the invalidation errors. That's the joy of DOCTYPEs.

Another change is to the opening HEAD tag, where I added the GRDDL profile. This lets data consuming agents know that I'm, first of all, using RDFa, then secondly, using the latest transform profile for RDFa. After all, once the data is provided, we assume someone will want to do something with the data.

I'm ready, now, to begin adding RDFa annotation. Some of the changes I can make directly to the theme pages, such as adding an attribute/value pair of property="dc:title" to my header element that references my site's title ("Burningbird's RealTech"). I also added annotation within the node, via node.tpl.php, again adding property="dc:title" to each individual site entry's title.

Other annotation, though, required either the use of a Drupal module, or custom code. For instance, one change I wanted to make was to add a a property="dc:subject" to my vocabulary terms. In my template.php file (used to override and extend the theme templating engine), I added a taxonomy term function that will not only append the vocabulary to each term, but also annotate the result with the RDFa dc:subject notation:

// split out taxonomy terms by vocabulary
function burningbirds_print_terms($nid) {
     $vocabularies = taxonomy_get_vocabularies();
     $output = '<ul class="links inline">';
     foreach($vocabularies as $vocabulary) {
       if ($vocabularies) {
         $terms = taxonomy_node_get_terms_by_vocabulary($nid, $vocabulary->vid);
         if ($terms) {
           $links = array();
           $output .= '<li property="dc:subject">' . $vocabulary->name . ': ';
           foreach ($terms as $term) {
             $links[] = l($term->name, taxonomy_term_path($term), array('rel' => 'tag', 'title' => strip_tags($term->description)));
           }
           $output .= implode(', ', $links);
           $output .= '</li>';
         }
       }
     }
     $output .= '</ul>';
     return $output;
}

In the node.tpl.php file, I then replaced the existing print $terms line with a reference to my custom terms display function:

    <div class="taxonomy">
      Tagged: <?php print burningbirds_print_terms($node); ?>
    </div>

Other areas that can be annotated with RDFa in an entry are the author and date, but I didn't have to code these, or modify the theme template directly. Instead I downloaded and installed the Submitted By module. Once installed and activated, this module provides an "Appearance" field in the content type form, which you can use to modify the "submitted by" line in posts.

By default, the template engine generates a line with the author's user name, linked to their user profile, and the date and time when the entry was created. I modified the field to show the author's name, without linking to the author profile, since I'm the only author. I also modified the post date to just the date. Time, to me, just isn't relevant for my site. Adding the appropriate RDFa annotation results in the following pattern:

<span property="dc:creator">[author-name-raw]</span> on [day], <span property="dc:date">[yyyy]-[mm]-[dd]</span>

Now that I've annotated several elements in the page with RDFa, I went shopping around at various semantic web sites to see what else they were providing by way of semantic markup. At Danny Ayers weblog my Semantic Radar toolbar alerted me to the presence of SIOC (Semantically-Interlinked Online Communities Project) data, one of the recommended data types supported by Yahoo's SearchMonkey. I did a little research and found the SIOC Drupal module, which I downloaded and installed.

The SOIC module automatically generates SIOC, which can be accessed as a direct RDF export. I gather that the module also adds a link to this metadata via the menu system, but I found this only works with a theme like Garland's. I wanted to be able to integrate a link in the header of my web pages, to page specific SIOC exports, wherever applicable. I checked the module's documentation, and elsewhere, but couldn't find anything on automatically adding this link, so decided to add it myself in my theme.

In Drupal, at least 6.x, you can add a preprocess function that will pre-process web page data before the page is displayed. I had such a pre-process function already, to modify my header to a) remove the RSS 2.0 link, and b) modify the content type meta tag to reflect my XHTML content type. It was a simple matter to modify this code to include a conditional check to see if the page being served is the Drupal front page, and if not, whether the page is presenting a node of type story, blog, or user. If the former, I provided a link to the site's main SIOC export URL; the later, one specific to the node:

function burningbirds_preprocess_page(&$vars) {

  $head = $vars['head'];
  $node = $vars['node'];
  $head = str_replace("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />",
              "<meta http-equiv=\"Content-Type\" content=\"application/xhtml+xml; charset=UTF-8\" />", $head);
  
  $head = str_replace("<link rel=\"alternate\" type=\"application/rss+xml\" title=\"Burningbird's RealTech RSS\" href=\"http://realtech.burningbird.net/rss.xml\" />\n","",$head);
    
  if (drupal_is_front_page()) {
    $head .= '<link rel="meta" type="application/rdf+xml" title="SIOC" href="http://realtech.burningbird.net/sioc/site" />';
  } else if ($node->type == 'story' || $node->type == 'blog' || $node->type == 'user') {
    $head .= '<link rel="meta" type="application/rdf+xml" title="SIOC" href="http://realtech.burningbird.net/sioc/node/';
    $head .= $node->nid;
    $head .= '" />';
  }

  $vars['head'] = $head;
}

For the node pages, I check to see if the node type is blog, story, or user, as these are the only node types currently supported by the SIOC module. Once this change was in effect, a header link to the SIOC file now appears with the main site page, and with blog, story, and user pages.

This is a start, as I explore other ways to annotate my site with metadata. I also plan on using metadata annotation when I do reviews and other specific types of writing. In addition, I'll probably add a generic FOAF page, as well as utilize other vocabularies as they present themselves. If you don't have the Semantic Radar toolbar installed, you can use the W3C RDFa extractor to extract the site's RDFa. You can see the SIOC by accessing the exporter for the site or an individual entry, such as this story.

Oct 28 2008
Oct 28

Virginia DeBolt has another Women in Technology series entry, this one on the Drupal community's Addison Berry.

Addison demonstrates something I've noticed: Drupal attracts the women in technology. There's something about the Drupal that has made the Drupal community friendly and encouraging to women. Other applications/companies/organizations should take note.

The interview with Addison is excellent, a lot more positive and upbeat than mine was.

Oct 25 2008
Oct 25

Drupal provides a way to list out postings by taxonomy term, but not necessarily by vocabulary, directly. I've been using a module, vocabindex, to provide a web page that lists out the taxonomy terms for a vocabulary, but it doesn't provide exactly what I'm looking for: a way to display posts by vocabulary, in addition to displaying posts by vocabulary term.

There is another important module, Drupal Views, that does provide ways of displaying data objects such as posts (nodes) in any number of ways. Since Views has now been officially released for Drupal 6, I decided to replace my vocabindex pages with custom pages created using Views. I'm providing the steps in this post, as I thought others of you might also want to give this approach a try. I also demonstrate a second technique, which I'm just now implementing, providing a way to display both a vocabulary terms view and a vocabulary posts view, together, in one page.

One small caveat before I get into the details: I am fairly new to Drupal, as well as the Views module. Though I've had very good luck with my implementations, I'm also open to any recommendations for improvement.

Implementing Vocabulary Posting Pages with Views

To start, you have to download, install, and activate the Views module. Once activated, an entry for Views appears under the Site Building header in the administration page.

views 1

Clicking the Views opens a page listing out all existing Views, including some that are installed with the Views module, but aren't active. None of these pre-existing views provide what I needed, so I clicked the Add button to add a new View.

views 2

The first page in the Add View option that opens is a way of providing both a machine name, and a descriptive name, for the View, as well as selecting which Drupal object the View references. In this example, I want to list out information about posts, so I select the nodes option (the default option).

views 3

The Views editing page is a nicely designed page with several options, including a set defining overall view characteristics, as well as how to options to pick fields, define sort criteria, add View displays, filters, and so on.

views 4

The first thing I did was to add View fields. When you click on the plus sign (+) associated with Fields label, allowable fields (based on picking the Nodes View type, earlier, when the view was named) are displayed. You can check any of the fields present, such as the Node Title, Node Publish date, Taxonomy Term, and Node Teaser I picked for my views.

view add fields and display

Once you've made your selection, the Views application opens a form for each field allowing you to change the field label, define display characteristics for the date, and whether to link node titles with actual posts. If you don't want a label for any field, leave the label field blank.

view link title to post

Once the fields are added, you can sort the field order by selecting the up/down sort order icon next to the Fields label. Either a drag and drop option is provided, or a way to renumber the fields is displayed, depending on your theme's support for Ajax.

After sorting the fields, I next added a Page display. Clicking on the newly created display opens a form to add a URL alias for the display page. I used the same URL that pathauto uses when generating URL aliases for my web posts. Typically, it's the name of the vocabulary, with white space converted to underscores, and extraneous words such as "the" removed.

view associate path with page

After I added fields and a display, the results are previewed below the View defining form. At this time, all posts are displaying, but I only want those for a specific vocabulary, a specific type (Story), and that are published. To fine tune the View, I need to add Filter criteria.

Adding Filters is the same as adding Fields: click the plus sign (+) and you'll be given a list of fields that will be used by the specific filter. For my View, I wanted the Node: Published, Node: Type, and Taxonomy: Vocabulary choices. Once selected, I'm given a form for each selection, allowing me to set the criteria for the filter item. For Published, it's a Boolean value of True, for published posts. For the Taxonomy vocabulary, I picked the taxonomy vocabulary for which the view is defined. Lastly, I set the Node type to Story.

Edit view stories_by_graphics | Burningbird's RealTech Edit view stories_by_graphics | Burningbird's RealTech

Once the fields have been selected and filtered, the remaining task on the data set is to sort the set by publication date, in descending order. Again, clicking on the plus sign (+) for Sort Criteria opens a selection of fields from which to choose. I selected Post date, and when given the form for defining the sort criteria, picked Descending and left the granularity at seconds.

view by date descending

The data set is now defined, and it's time to focus on the display. First, though, a quick peek at the query used to define the View. Note that though the query is intimidating looking, the View is actually efficient, and best of all, cached by default.

view generated query

I added a Page display already, but now I want to add a Page title, as well as fine tune how the page displays. The first column in the View form has several different options that, when you click on each opens up forms for making modifications. For my first run through on creating a View, I set the Style to List (other options are Table, Unformatted, and Grid), and the Row Style to Fields (the default, and necessary to select individual fields for the view). I also added a Title, which displays at the top of the page, set the number of items to display to 5, and added a Full pager (the display of page numbers for navigation below the listing of entries).

Edit view stories_by_javascript | Burningbird's RealTech

I save the View at this point, though technically you should save it at various times when creating the view, or risk loosing your work. The only thing left is to add a menu item for my Primary links for the new view, giving the URL defined for the view, and add some CSS styling for the newly generated list items. (View Source provides the class names used for the new display items).

Currently, you can check out the look of the View with my Ajax/JS topic page, but no guarantees how long this exact view format will last, because I'm in the process of tweaking the views (covered in the next sections). In the meantime, here's a screenshot.

view generated query

Row Style: Node not Fields

In the previous View definition, the Row Type in the Basic Settings was set to Fields, which means that I had to pick out the fields used for the View. Another approach I could have taken was to set Row Type to Node, in which case the fields displayed are defined in the node template. This simplifies creating the View because you don't have to define every View field, nor do you have to add new CSS entries for the new View fields. I currently use this approach with my MisouriGreen Places vocabulary View.

Entries by Place | MissouriGreen

Of course, by using the Node Row Type, you also don't have fine control over which fields are displayed for the View, their order, or the CSS used. However, it cuts the time to create the View considerably.

I like the look of the View page just defined, but there's one thing missing: the original listing of general Vocabulary terms for the Vocabulary that the Vocabindex module provided. I get postings for all terms, and I can click on the Vocabulary term associated with each posting, but there's no way for a person to go to a specific type of posting, directly—or to discover easily what all the terms are for the vocabulary. That led to a little experimentation, and the final change I'm making to my Views.

Adding an embedded Block View within a Page View

What I want is a page that has two display items in it. The first is the listing of posts by vocabulary. The second, though, is a list of vocabulary terms, each linked to a separate page that lists just the posts for that vocabulary term. The logical approach would be to list the terms at the top of the post display pages. That led to the next iteration of my View design.

First, I actually created a new View just for my vocabulary terms, selecting the Taxonomy object in the view name page, rather than Node.

Since the View type is Taxonomy, rather than Node, the field choices differ, and your choice limited to the taxonomy related fields, such as Term and Term Description. Other than that, you can filter and sort, just like with the Node view created earlier. The only other option that differs from my Node page view earlier is that I set the number of items to display to unlimited, and I don't attach any paging.

Lastly, the major difference with this view and the ones previously created is that I'm using the block display, rather than the page display type. This has one interesting impact on the view: when you use the block display, the View is added as an option to the Drupal Blocks page, which means you can use the View anywhere you can use a Block. This is pretty sexy stuff, and one has to hold oneself back before going mad with the possibilities.

Edit view nontech_terms | Burningbird's RealTech

Once the taxonomy term block view is created and saved, I next need to embed it in the Post page View.

I'm going to use embedded PHP to display the terms block view, so first I need to open up the Modules Administration page and check the one labeled "PHP Filter", if I don't already have it selected. Checking this installed module option adds a new Input format type: for PHP code snippets. This means that I can define the Input format for an item to be Filtered HTML, Full HTML, or PHP Code, and for the latter, Drupal processes the PHP code snippet as code, not text.

I then open the page-based view I created earlier, the Graphics vocabulary view for this example. In the View, there's an option to add a Header for the Page display. By default, there is none, but clicking on it opens an input text box for adding whatever you want in the header. In my case, I'm going to be adding a little markup and some PHP.

Edit view stories_by_graphics | Burningbird's RealTech

I did a lot of exploration trying to find the code that would work to involve the block level View in the header of the page. The function that worked for me was module_invoke, a generic module hook function that can be used to invoke the code for any Drupal object. There's some gaps in the documentation of this and other methods, but the following worked with my view:

module_invoke('views','block','view','block-views-delta');

The first three parameters are written out, as is, and don't change. It's the fourth argument that differs based on the block view's name. For instance, my block view listing the terms for the Graphics vocabulary is graphics_terms. However, what you want is the delta for this block, which I found by actually going to the Blocks database table for the Drupal database, and looking for the delta field.

I discovered through experimentation that the general format for the block delta is block machine name-block-1, the machine name being what you gave the block view when you first created it. For instance, my graphics term view is named "graphics_terms" so the delta would be "graphics_terms-block-1".

Once you have the block, returned from the module_invoke function call, you can print out any data associated with it. I'm only printing out the block content. Combined with some formatting markup, the text I added to the header for my Graphics vocabulary page is:

<p>
<?php

$block = module_invoke('views', 'block', 'view', 'graphics_terms-block_1');
print $block['content'];

?>
</p>

<h2 class="page-title">Writings about Web Graphics</h2>

I also changed the Page title to "Web Graphics Categories" so that each section, terms and posts, will be titled appropriately in the page. You can see the result in the currently styled Graphics vocabulary page. Note that the terms are all listed out, and re-appear on each posting page. Since the view is cached, this duplication shouldn't result in another query to the database. However, to simplify the page, I turned Ajax handling on for the pager (another View option). The page is now static, with only the posts updating, as you navigate through the pages.

Following is a screenshot of my non-tech vocabulary page, which demonstrates the combined terms/posting views.

Categories of Writings not related to Technology | Burningbird's RealTech

I'm in the process of converting all my vocabulary pages over to this terms/post format, but as I learn more about Drupal, and as other modules are released, how I achieve this effect may change. If I do adopt another approach, I'll update this page to reflect whatever changes I make.

In the meantime, to simplify the vocabulary creation, I'm using the Views clone capability (available in the Views List Page) to clone the Graphics vocabulary and Graphics terms views, and just making modifications where appropriate to change the text of the titles and the vocabulary item. The time to make these changes is only about 5 minutes for each vocabulary item.

Caveats

There is another module currently in development, the Panels module, which seems to handle multi-dataset pages much more efficiently. For instance, I can create blocks that take arguments, and so create just one taxonomy term block, rather than have to create a separate one for each taxonomy term. I've tried to find out how to pass in arguments for block views using module_invoke, but no luck.

In addition, there are also View API functions, which might be a better fit for loading views. However, I've not had good luck with these, just yet, though I am still experimenting.

In the meantime, I have exactly the page I want when accessing each of my vocabulary menu items. Hopefully this might be useful for your own efforts, and if you have any questions, holler. If you have any refinements, or suggestions, please leave a comment and thanks in advance.

Now, what new Drupal toy should I try playing with next...

Updated

Thanks to a suggestion from Merlin, I'm now using the views_embed_view function to embed the view, passing in the taxonomy identifier as argument. The following screenshot shows the generic block view, which is defined like the block view above, except that rather than filtering on the taxonomy, the taxonomy identifier is passed in as an argument.

Edit view terms_by_vocab | Burningbird's RealTech

The code to use in the header for the Web node view uses the views_embed_view function, passing in the taxonomy identifier of 9 in the argument array, and the name of the view ('terms_by_vocab'), and view display ('Block'):

<p>
<?php>

$arg[0] = 9;
$output = views_embed_view('terms_by_vocab', 'Block', $arg);
print $output;

?>
</p>
<h2>Writings about the Web</h2>

The same generic taxonomy term block view can now be used to list out the taxonomy terms within each of the page views.

About Drupal Sun

Drupal Sun is an Evolving Web project. It allows you to:

  • Do full-text search on all the articles in Drupal Planet (thanks to Apache Solr)
  • Facet based on tags, author, or feed
  • Flip through articles quickly (with j/k or arrow keys) to find what you're interested in
  • View the entire article text inline, or in the context of the site where it was created

See the blog post at Evolving Web

Evolving Web