Themes in Graffiti are very easy to write or convert from existing themes or templates. The theme on this site is derived from based on the WuCoco theme for Wordpress. I chose this theme because I liked the look of it and it was also very well organized into sections for the layout of the blog. These sections were very easy to convert into Graffiti views.
Here is a list of the .php files included in the 2-column version of the WuCoco theme.
Once this theme was converted for Graffiti, it had the following listing of Graffiti view files. The difference in number of files is based on the number of required views in Graffiti to accomplish the look of the theme in addition to some customizations. You could use more or less views to convert more of the original theme if you like.
Graffiti uses .view files to denote sections or views of the markup for the site. In addition to some standard views that Graffiti recognizes, one can define custom views and then open them from other views using this chalk method.
$macros.LoadThemeView(filename)
The benefit of this method of theme layout becomes clear as you begin the process of building the theme. It becomes obvious where your markup is coming from and you have immediate and seamless control over your each page's HTML output.
So lets begin. First we'll start by examining the Wucoco theme's index.php file to see how we can separate it into Graffiti views.
<?php get_header(); ?>
<div id="page_container">
<?php get_sidebar(); ?>
Other than the page_container div, there appears to be very limited markup in these first few lines. Where are the <head>, <!DOCTYPE>, and <title> tags? Let's dig a little deeper.
The first line in this snippet makes a call to another PHP file to obtain the header markup by calling get_header(). So lets go to the header file and see what this file exposes.
Here are the first few lines of the header.php file.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head profile="http://gmpg.org/xfn/11">
<meta http-equiv="Content-Type" content="<?php bloginfo('html_type'); ?>; charset=<?php bloginfo('charset'); ?>" />
<title><?php bloginfo('name'); ?> <?php if ( is_single() ) { ?> » Blog Archive <?php } ?> <?php wp_title(); ?></title>
<style type="text/css" media="screen">
@import url(<?php bloginfo('stylesheet_directory'); ?>/style-core.css);
@import url(<?php bloginfo('stylesheet_directory'); ?>/style.css);
<?php if (eregi("MSIE",getenv("HTTP_USER_AGENT")) || eregi("Internet Explorer",getenv("HTTP_USER_AGENT"))) { ?>
@import url(<?php bloginfo('stylesheet_directory'); ?>/style-ie.css);
<?php } ?>
</style>
<?php wp_head(); ?>
</head>
Now we're getting somewhere. The index.php file calls the header.php which eventually returns the initial HTML markup needed to build the page. Sounds easy enough. So let's try converting that code over to Graffiti Chalk.
I've decided that I don't like hiding the important tags for defining an XHTML document in an obscure header file and I would rather expose them up front in my initial view. Here's how I would define the first few lines of my Graffiti theme's layout.view.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
$macros.Head()
$macros.LoadThemeView("header.view")
</head>
So far I've got my initial HTML tags defined with a few Chalk methods to build the inside of the <head> tag.
The first macro call to Head() is used to render some of the custom fields that you can set in Graffiti for any custom Javascript, RSD, RSSAutodiscovery, GraffitiJavaScript, and MetaTags. This is absolutely necessary to ensure that your page will get all the necessary Graffiti markup and script in addition to some of custom fields you can set in Graffiti's control panel.
The second macro call to LoadThemeView() actually loads my custom header view that I defined in another file, header.view. Here are the first few lines of that file.
<title>$title - $data.Site.TagLine</title>
$macros.Style("style.css","screen")
$macros.Style("style-core.css","screen")
<!--[if lte IE 7]>
$macros.Style("style-ie.css","screen")
<![endif]-->
The above code allows me to pull in the CSS stylesheets defined by the original theme as well as the site's title and tagline. The theme also requires some custom javascript that can below this code in a <script> tag. For the purposes of this tutorial, I have omitted that code.
At this point, we have defined enough views to load the markup for the <head> tag portion of our Graffiti theme.
So let's move on to defining the views necessary for the <body> portion of the theme. Let's go back to Wucoco's index.php file.
<?php get_header(); ?>
<div id="page_container">
<?php get_sidebar(); ?>
We took care of the header, but its not clear where the <body> tag is defined yet. So let's look a little further down the header.php file.
<body>
<div id="header">
<div class="nav">
<?php /* CUSTOMIZE HEADER LINKS HERE */ ?>
| <a href="<?php echo get_settings('home'); ?>">home</a> |
<a href="">link 1</a> |
<a href="">link 2</a> |
<a href="">link 3</a> |
<a href="">link 4</a> |
<a href="">link 5</a> |
<?php /* END HEADER LINKS */ ?>
</div>
<?php /* UNCOMMENT THE LINE BELOW IF YOU WISH TO SEE YOUR BLOG'S TITLE IN THE HEADER */ ?>
<!-- <div id="blogtitle"><h1><?php echo get_bloginfo ( 'name' ); ?></h1></div> -->
<div class="searchform"><?php include (TEMPLATEPATH . '/searchform.php'); ?></div>
</div>
Now it is clear that the opening tag of <body> actually exists in the header view. Why do this? Well this theme utilizes a "header" div at the top of the site for an image, navigation links, and search. In order to ensure that all this markup is rendered first, the theme author decided to put inside his header view.
I chose to re-organize things a bit for better readability, so I went ahead and moved the <body> tag into my layout.view and the rest of the markup into a separate view for Graffiti which I called page_header.view.
<div id="header">
<div class="nav">
<ul id="nav">
$macros.NavBar()
<li class="rss"><a href="$urls.Rss">RSS</a></li>
</ul>
</div>
<div id="blogtitle">
<h1><a href="$urls.Home" title="$data.Site.Title">$data.Site.Title</a></h1>
<h3>$data.Site.TagLine</h3>
</div>
<div class="searchform">
<form action="$urls.Search" name="searchform" id="searchform" method="get">
<div>
<input alt="search this site" class="search-box" type="text" value="Search..." name="q" id="q" onblur="if (this.value == '') {this.value = 'Search...';}" onfocus="if (this.value == 'Search...') {this.value = '';}" />
<input type="hidden" id="searchsubmit" value="Search" />
</div>
</form>
</div>
</div>
As you can see, I adjusted my markup a little bit to play nicer with Graffiti. I started by converting the static link list into an Unordered List that works with the NavBar() macro. I then added some markup to put in my site's tagline in addition to its title into the top header div.
Finally, I customized the searchform to work with Graffiti. There was an opportunity to convert this form into it's own view, as the Wucoco theme did, but since I'm only keeping search in the page's header I deemed another view unnecessary.
Now let's go back to my Graffiti layout.view file to see how things look.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
$macros.Head()
$macros.LoadThemeView("header.view")
</head>
<body>
$macros.LoadThemeView("page_header.view")
</body>
</html>
Clean and simple. Now we've got the <head> and the <body> tags as well as the beginning markup for the page. Converting the rest of the theme is pretty straight forward from this point on by following the same steps as above for the sidebar and footer elements of the theme.
My completed altair theme is available here. It is licensed under the GPL (as was the Wucoco theme) and you are free to modify it as you will as long as your reference both themes in the comments. This theme is for development and personal usage only. I can't officially provide support for it, but if you have any issues that you can't figure out feel free to leave a comment.
For further reading and information on how to write themes for Graffiti, go to http://docs.graffiticms.com.