Posts tagged with 'theme'

Quickie Chalk extension for the tags issue

I mentioned in my previous blog post that the workaround I had for displaying the tags for a post vertically, rather than as a horizontal, comma-separated list, was flawed.

There are in fact two issues at play. First of all here's a magnified view of the tag list in Firefox 3.0:

image

As you can see, the biggest problem is that the clever CSS hackery I used means that the commas are still displayed in a line after the title, like an ellipsis with tails. At normal size this isn't really visible, but it's there nevertheless.

The second, bigger, issue is that in Chrome and Safari (they use the same rendering engine), the vertical tag list looks like this:

image

Which is just nasty. Now, I could just fiddle with the CSS again, but it's time to write a bit of C# and create a Chalk extension.

The basic idea is simple: write a class with one or more methods, decorate the class with ChalkAttribute, compile, and deploy.

I'll start off with the shell. Since I intend writing more "one-shot" Chalk methods, I'll arrange them all in a class called JmbChalk.

   1: using System;
   2: using System.Web;
   3: using Graffiti.Core;
   4:  
   5: namespace JmbChalk {
   6:   [Chalk("JmbChalk")]
   7:   public class JmbChalk {
   8:  
   9:     public string TagList(string tagList, string preTag, string postTag, string linkClass) {
  10:  
  11:       return string.Empty;
  12:     }
  13:   }
  14: }

From this you can see a couple of things in the boilerplate. First you must add Graffiti.Core as a reference and into the using list. It is this assembly that contains the ChalkAttribute class. I'm also adding System.Web because I'll be accessing a class there that will help me set up the url for each tag.

The Chalk method is called TagList. It takes four parameters: the taglist itself, some value before each tag (for example, <li> although it doesn't have to be an HTML element tag), some value after (for me, </li>) and then the class name to apply to the <a> element.

The method is pretty easy: split the taglist into individual tags, and then construct the HTML snippet for each tag, by concatenating everything together:

   1: public string TagList(string tagList, string preTag, string postTag, string linkClass) {
   2:   string result = string.Empty;
   3:  
   4:   if (string.IsNullOrEmpty(tagList)) 
   5:     return result;
   6:  
   7:   var separators = new char[]{',', ';'};
   8:   string[] tags = tagList.Split(separators, StringSplitOptions.RemoveEmptyEntries);
   9:   if (tags.Length == 0)
  10:     return result;
  11:  
  12:   string absolutePath = VirtualPathUtility.ToAbsolute("~/tags/");
  13:   string format = string.IsNullOrEmpty(linkClass) ? 
  14:     "{3}<a href=\"{0}{1}/\">{2}</a>{4}" :
  15:     "{3}<a class=\"linkClass\" href=\"{0}{1}/\">{2}</a>{4}";     
  16:   foreach (string tag in tags) {
  17:     string cleanUrl = Util.CleanForUrl(tag);
  18:     result += string.Format(format, absolutePath, cleanUrl, tag, preTag, postTag);
  19:   }
  20:   return result;
  21: }

As you can see the tags folder for Graffiti is off the root and called tags (so we need to calculate the absolute path for it), and the Util.CleanForUrl method is a utility function found in Graffiti.Core.

A quick compile, and then I added the JmbChalk dll to the /bin folder for the website.

The change to postheader.view was pretty simple after that:

   1: <li class="tags">
   2:     Tags:
   3:     <ul>
   4:     $JmbChalk.TagList($post.TagList, "<li>", "</li>", "taglink")
   5:     </ul>
   6: </li>

Once that was uploaded, I could remove the hackery from the CSS file and the tags list now renders the same across all browsers I test against (Firefox, IE7, Chrome, and Safari).

image

Share it: Digg It!  StumbleUpon  Reddit  Del.icio.us  NewsVine  Furl  BlinkList  Ma.gnolia  Technorati

So I get bored easily...

No sooner do I finish my quick series on customizing a Wordpress theme for Graffiti (I, II, III, IV) than I throw it all away for a — gasp — hand-written one. Yes, I got bored with the browns and went with the grays.

There were two reasons for this: first, I wanted to use the entire wide-screen browser window and avoid the dead space on either side, yet still have a non-cluttered look, and, second, I wanted to use the visual ideas present in Adobe Lightroom in doing so.

image Adobe Lightroom is an application that is geared to the photographer's workflow where the image is king. Everything on the screen is deferential to that idea. So the entire display is built of shades of (dark) grays so that the image you're working on stands out. And even with those grays, it has been designed so that only the important textual information is in light grays or white, the rest blends in with the background so that it doesn't distract from the job in hand: manipulating your photos.

So I wanted that kind of behavior. For the blog, it's the content that is king, the blog posts. And so it's those that should stand out in the display, not the widgets on the side, not even when the metadata about the posts. That stuff can be there, sure, but it shouldn't distract from the real meat of the blog.

Going along with all that, I wanted to make the theme image-free. No little gradient PNGs here, no fancy-schmancy rounded corner GIFs there. Images that are displayed as part of the theme (like my photo of the Castlerigg stone circle) had to blend into the background: they're there for decoration, but should not distract.

After that, it was a case of finding the right layout for the blog. I spent an hour or so, trawling the Wordpress themes, but there was nothing there that (a) were plain enough, or (b) that were wide-screen enough.

In my travels, I came across Eric Meyer's blog. and it had the kind of layout I was looking for where, sure, there is a sidebar, but the content column filled the remaining space.

That was my layout inspiration, and with my palette of grays from Lightroom, I spent the last three evenings building and tweaking the CSS file and view files.

The hardest part was the damn tag list for each post. $post.TagList is a comma-separated string of tag names. $macros.TagList takes that string and creates a comma-separated lists of URLs to the various tag queries. I wanted a vertical list of tag URLs created as a bunch of <li> elements, but it seemed that the only way I could do this was write my own plug-in. Since I've not done this before yet, I put that idea on the back shelf. I had another idea that I fleshed out in my mind: write a javascript function that parses the taglist and creates the required list of URLs, but that was discarded in favor of a bit of CSS jiggery-pokery that styles the <a> elements in the <li> to be float:left and clear:left. As a workaround, it works very nicely as you can see, with only one small bug left, which, because of my underlying vision for the theme, is all but hidden.

Last night, just before midnight I "flipped the switch" and it went live.

There are still a few bugs, but I'll be fixing those this evening.

Now playing:
Moby - First Cool Hive
(from Everything Is Wrong)


Share it: Digg It!  StumbleUpon  Reddit  Del.icio.us  NewsVine  Furl  BlinkList  Ma.gnolia  Technorati

Customizing Graffiti CMS, part IV

(In which I continue taking apart a Wordpress theme to make it work with Graffiti. Part I. Part II. Part III.)

We're finally ready for the last piece of the jigsaw. I've created the layout.view file that determines the common look-n-feel for the site based on the Chronicles theme, and the index.view file that determines what a list of posts looks like. It's now time for the post.view file, the view that determines how to display a single blog post.

Apart from the comments, in effect this is much the same as a single post in a list of posts, so we can reuse the HTML/Chalk code we have from index.view. Of course, there's no list of posts, and we use $post.Body and not $post.Excerpt  but that's pretty obvious.

Onto the comments section, then. Here's the PHP code for that.

<?php comments_template(); ?>

Yeah, well, that's brilliant, that. There's no analog in Graffiti, so we're just going to have to roll our own. The best way to do this is to go to the Chronicles webpage, and click on the Test Run link. You'll get an example blog with the theme. Click on the comments link on one of the fake posts, and you'll get an example single post with a comments section. From this you can "view page as source" in your browser, and copy/paste the comment HTML into your post.view file.

From this, and viewing one of the supplied Graffiti themes (so you can get the loop code and the names of the comments properties) it's a piece of cake to roll up the loop again into a chunk o' Chalk. Here's what I got:

   1: #foreach($comment in $comments)
   2:     #beforeall
   3:         #if($comments.Count == 0)
   4:             <h3 id="comments">No responses to $post.title</h3>
   5:         #elseif($comments.Count == 1) 
   6:             <h3 id="comments">1 response to $post.title</h3>
   7:         #else 
   8:             <h3 id="comments">$comments.Count responses to $post.title</h3>
   9:        #end
  10:        <dl class="commentlist">
  11:    #nodata
  12:        #if($post.EnableNewComments)
  13:            <div class="entry">
  14:                <p>Feel free to add a comment...</p>
  15:            </div>
  16:        #else
  17:            <div class="entry">
  18:                <p>No new comments allowed.</p>
  19:            </div>
  20:        #end
  21:    #each
  22:        <dt id="comment-$comment.Id" #if($comment.CreatedBy == $post.CreatedBy) class="author" #end>
  23:            <span class="comment_num">
  24:                <a href="#comment-$comment.Id" title="Permalink to this comment">#$count</a>
  25:            </span>
  26:  
  27:            <strong>
  28:                <a href="$comment.WebSite">$comment.Name</a>
  29:            </strong>
  30:  
  31:            on $comment.Published.ToString("MMM dd yyyy") at $comment.Published.ToString("h:mm tt")
  32:        </dt>
  33:  
  34:        <dd id="comment-body-$comment.Id" class="entry#if($comment.CreatedBy == $post.CreatedBy) author#end">
  35:            $comment.Body 
  36:            #if($isUser)
  37:                <a href="javascript:void(0);" 
  38:                    onclick="Comments.deleteComment('$urls.AdminAjax', $comment.Id,'comment-$comment.Id','comment-body-$comment.Id'); return false">
  39:                    Delete Comment
  40:                </a>
  41:            #end
  42:        </dd>
  43:    #afterall
  44:        </dl>
  45: end
  46:  
  47: if($post.EnableNewComments)
  48:    <h3 id="respond">Leave a Comment</h3>
  49:    <form action="$url" method="post" id="comment_form">
  50:  
  51:        #if($isUser)
  52:            <p class="unstyled">
  53:                Logged in as $user.ProperName <a href="$urls.Logout">[Logout]</a>
  54:            </p>
  55:        #else
  56:            <p>
  57:                <input class="text_input" type="text" name="author" id="author" value="" tabindex="1" />
  58:                <label for="author"><small>Name (required)</small></label>
  59:            </p>
  60:            <p>
  61:                <input class="text_input" type="text" name="email" id="email" value="" tabindex="2" />
  62:                <label for="email"><small>Mail (will not be published) (required)</small></label>
  63:            </p>
  64:            <p>
  65:                <input class="text_input" type="text" name="url" id="url" value="" tabindex="3" />
  66:                <label for="url"><small>Website</small></label>
  67:            </p>
  68:        #end
  69:  
  70:        <p>
  71:            <textarea class="text_input text_area" name="comment" id="comment" rows="7" tabindex="4"></textarea>
  72:        </p>
  73:        <p>
  74:            $macros.CommentButton("%{id='submit', tabindex='5', value='Submit'}") 
  75:            <div style="display:none;" id="comment_status"></div>
  76:            <input type="hidden" name="comment_post_ID" value="$post.Id" />                
  77:        </p>
  78:    </form>
  79: end

This code also contains the comment form, should the post allow further comments.

Actually, I discovered after a week or so that this code had a bug that I'd copied directly from one of the supplied Graffiti themes. If you look carefully, it attempts to identify whether a comment was written by the author of the post or not, and displays the comment differently.

#if($comment.CreatedBy == $post.CreatedBy)

Although $post.CreatedBy is the correct property on the post, $comment.CreatedBy does not exist for the comment. It's obvious from reading the rest of the code that it should be $comment.Name, but it did cause me a couple of anxious minutes. With this change in place, my comments get highlighted in a contrasting background color.

And with that, I've come to the end of my small set of posts on how to change a Wordpress theme into Graffiti. I'll admit to having made more changes than just those I've described here (I've widened the basic theme display — it suits posts with code better), but once you have the basics, you can tweak to your heart's content.

 

Now playing:
Everything But the Girl - The Heart Remains a Child
(from Walking Wounded)


Share it: Digg It!  StumbleUpon  Reddit  Del.icio.us  NewsVine  Furl  BlinkList  Ma.gnolia  Technorati

Writing and debugging CSS

Part of the job of altering the theme for this site, or indeed writing the "theme" for an ordinary page (here's my résumé, for example), is writing or modifying the CSS file (Cascading Style Sheet) to make it look good. I've used three main resources to help me do this as efficiently as I can.

Cascading Style Sheets: The Definitive Guide by Eric A. Meyer. Yep, my copy of this is so old, it still has the old name (it's now called CSS: The Definitive Guide), No matter what it's called, Meyer does a bang-up job in explaining the nitty-gritty of the Box Model — don't leave home before you understand this in all its glory — and all of the various CSS properties and attributes. You may start reading this and get disillusioned with all the gotchas in the CSS support amongst the various browsers, but I've had great success in following Meyer's explanations and recommendations.

TopStyle 3.5. Written by Nick Bradbury, currently owned by Newsgator, but just sold to Stefan van As to ensure its further development. I've been using this product since Nick brought it out, and it really does make creating stylesheets very easy. Although it's great for static HTML pages, it's not so good for dynamic ones, and so the changes to the CSS file for the Chronicles theme were a bit hit and miss. I did get to the point where I saved off the current view of a webpage from Graffiti, just so I could fine-tune the CSS in TopStyle.

Firebug. If you are developing HTML and CSS and and indeed javascript, stop what you are doing right now and install this add-in into Firefox. (I won't even slow down to say, whaddya mean you're not using Firefox?) Firebug is great at showing you the "cascading" bit of CSS, live on a web page. You can point to an element and Firebug shows you the CSS that is being used to style that element, displaying the inheritance from the outer scope to the most inner scope. The nice thing is the padding and margins are shown in different colors, meaning to hone in on box issues straightaway. Brilliant. The javascript debugger is pretty good too, although I haven't used it that much.

And finally, to ensure my website has the latest files (and vice versa, for backup purposes)...

FireFTP. Neat-o visual FTP client implemented as a Firefox add-in. I love the visual syncing of local and remote folders (drill down through the folders in one pane and the other pane follows suit), and the drag-and-drop between panes. Nicely done.

Now playing:
Ferry, Bryan - The Name of the Game
(from Bête Noire)


Share it: Digg It!  StumbleUpon  Reddit  Del.icio.us  NewsVine  Furl  BlinkList  Ma.gnolia  Technorati

Still playing with look 'n' feel

As you can see when you view my blog in your browser (versus viewing it in your RSS reader, for example), I'm still playing around with the look of the new website. I've added a fixed background image (a chain link fence after a night of freezing sleet) for visual contrast.

Now playing:
Haircut 100 - Love Plus One
(from The Best of Nick Heyward & Haircut 100)


Share it: Digg It!  StumbleUpon  Reddit  Del.icio.us  NewsVine  Furl  BlinkList  Ma.gnolia  Technorati

Customizing Graffiti CMS, part III

(In which I continue taking apart a Wordpress theme to make it work with Graffiti. Part I. Part II. Part IV. )

Last time I'd set up the layout.view file and completed it by adding the @childcontent statement. Now I need to think about the other two main view files, index.view and post.view, the ones that will supply the child content.

The index.view file is possibly the easiest at this stage, since we started out with analyzing the equivalent PHP file from the Chronicles theme.

The index.view file is meant to display a list of posts. This list could come from a search, from a category list, from a tag list, and so on. No matter what the source, the view must display the post title, date, author, category, tags, and the first few words from each post. The way Graffiti works is that the list will have a maximum of 10 posts in it, and so we shall need to consider the paging facilities in Garffiti since after a while it's likely that there will be more than 10 posts to display.

So, all in all, there's a lot to consider.

The way I constructed the layout.view file, the content view files are responsible for deciding whether they want to display none, one, or both sidebars, and then displaying them. The sidebars are rendered by Chronicles as

<?php include (TEMPLATEPATH . '/sidebar1.php'); ?>

So, all we need to do is (roughly) the same for Graffiti:

$macros.LoadThemeView("sidebarleft.view")

After changing the PHP code in sidebar1.php to sidebarleft.view I had this:

   1: <div id="sidebar1">
   2:     <div id="sidebar1_top"><!-- Hack for IE --></div>
   3:     <ul>
   4:         $macros.LeftSideBar("%{beforeWidget='<li class=\"widget\">', afterWidget='</li>', beforeTitle='<h2>', afterTitle='</h2>'}")
   5:     </ul>
   6:     <div id="sidebar1_bottom"><!-- Hack for IE --></div>
   7: </div><!--end of sidebar1 -->

Similarly for the right sidebar:

   1: <div id="sidebar2">
   2:     <div id="sidebar2_top"><!-- Hack for IE --></div>
   3:     <ul>
   4:         $macros.RightSideBar("%{beforeWidget='<li class=\"widget\">', afterWidget='</li>', beforeTitle='<h2>', afterTitle='</h2>'}")
   5:     </ul>
   6:     <div id="sidebar2_bottom"><!-- Hack for IE --></div>
   7: </div><!--end of sidebar2 -->  

The nice thing about the $macros methods that render the sidebar is that you can specify the HTML tags that go around the widget "content" and around the widget titles. I'll talk at another stage how to write a sidebar widget.

Now we have some PHP code that iterates through the posts:

   1: <?php if (have_posts()) : ?>
   2: <?php while (have_posts()) : the_post(); ?>

Graffiti's Chalk language has a foreach loop construct which will nicely replace this. The loop has the following syntax:

   1: #foreach($post in $posts)
   2:   #each (this is optional since it’s the default section)
   3:        <!--text which appears for each item-->
   4:   #before
   5:        <!--text which appears before each item-->
   6:   #after
   7:        <!--text which appears after each item-->
   8:   #between
   9:        <!--text which appears between each two items-->
  10:   #odd
  11:        <!--text which appears for every other item, including the first-->
  12:   #even
  13:        <!--text which appears for every other item, starting with the second-->
  14:   #nodata
  15:        <!--Content rendered if $items evaluated to null or empty-->
  16:   #beforeall
  17:        <!--text which appears before the loop, only if there are items matching condition-->
  18:   #afterall
  19:        <!--text which appears after the loop, only of there are items matching condition-->
  20: #end

As you can see, this a very rich for loop, geared to producing rich visual displays of lists.

The $posts list id provided by Graffiti when the view is rendered. The $post variable is defined by us, and we can call it what we want. It'll be used within the loop to expose the various interesting properties of the post itself.

   1: $post.Body -- the body of the post
   2: $post.CreatedBy -- the user who created the post
   3: $post.Url -- the site's url to the post
   4: $post.Title - the title of the post
   5: $post.Published -- the date/time that the post was published
   6: $post.CommentCount -- the number of comments for the post

From these properties and from the Chalk foreach loop we can convert the PHP code and HTML formatting to a Graffiti view.

   1: #foreach($post in $posts)
   2:   #each
   3:     <div class="post" id="$post.id">
   4:  
   5:       <div class="date">
   6:         $post.Published.ToString("MMM dd yyyy")
   7:       </div><!--end of date -->
   8:  
   9:       <div class="post_title">
  10:         <h2><a href="$post.Url" rel="bookmark" title="$post.Title">$post.Title</a></h2>
  11:         <div class="posted">
  12:           Posted by $post.CreatedBy at $post.Published.ToString("h:mm tt")
  13:         </div><!--end of posted -->
  14:       </div><!--end of post_title -->
  15:  
  16:       <br clear="all" />
  17:  
  18:       <div class="tags">$macros.TagList($post.TagList)</div><!--end of tags -->
  19:  
  20:       $post.Excerpt("<p>", "</p>" ,"Read more...", 300)
  21:       
  22:       <div class="meta">
  23:         Filed under : $macros.CategoryLink($post.Category) | $macros.CommentUrl($post, "%{anchor='comments'}")
  24:       </div><!--end of meta -->
  25:     </div><!--end of post -->
  26:  
  27:   #nodata
  28:     <div class="post">
  29:       Sorry, there are no posts matching your request.
  30:     </div>
  31:   
  32:   #end

The code to add paging is simplicity itself, although to my taste a little too simple since we cannot change the text that will be shown when there is a previous or next page of posts (the text is hard-coded in Graffiti.Core.dll). The one and only parameter is the CSS class name for the div that contains the previous/next paging links.

$macros.Pager("navigation")

(UPDATE: Scott Watermasysk informs me in the comments below that there is an overload that does allow you to set the previous/next paging link text:

$macros.Pager(CssStyle, PreviousText, NextText)

I've altered the calls to paging in my view files.)

Next time, we'll look at the final piece of the theme conversion puzzle.

Share it: Digg It!  StumbleUpon  Reddit  Del.icio.us  NewsVine  Furl  BlinkList  Ma.gnolia  Technorati

Customizing Graffiti CMS, part II

(In which I continue taking apart a Wordpress theme to make it work with Graffiti. Part I. Part III. Part IV.)

Unpacking the downloaded zip file for Chronicles gave me this set of files:

image

OK, so I recognize the css file, but the rest are PHP files, and nothing like "layout". Oh well, time to investigate. index.php looks like it could be the equivalent of index.view, so let's take a look:

   1: <?php get_header(); ?>
   2:  
   3: <div id="main">
   4: <?php include (TEMPLATEPATH . '/sidebar1.php'); ?>
   5:  
   6:     <div id="blog">
   7:      <div class="entry">
   8:  
   9: <?php if (have_posts()) : ?>
  10: <?php while (have_posts()) : the_post(); ?>
  11:  
  12: <div class="post" id="post-&lt;?php the_ID(); ?>">
  13:  
  14: <div class="date">
  15: <?php the_time('M d Y'); ?>
  16: </div><!--end of date -->
  17:  
  18: <div class="post_title">
  19: <h2><a href="&lt;?php the_permalink() ?>" rel="bookmark" title="Permanent Link to <?php the_title(); ?>"><?php the_title(); ?></a></h2>
  20: <div class="posted">Posted by <?php the_author_posts_link(); ?> </div><!--end of posted -->
  21: </div><!--end of post_title -->
  22:  
  23: <br clear="all" />
  24:  
  25: <div class="tags"><?php the_tags('Tags: ', ', ', '&lt;br />'); ?></div><!--end of tags -->
  26:  
  27: <?php the_content('Read more &raquo;'); ?>
  28:  
  29: <div class="meta">
  30: Filed under : <?php the_category(', ') ?> | <?php edit_post_link('Edit', '', ' | '); ?>  <?php comments_popup_link('No Comments &#187;', '1 Comment &#187;', '% Comments &#187;'); ?>
  31: </div><!--end of meta -->
  32:  
  33: </div><!--end of post -->
  34:  
  35:     <?php endwhile; ?>
  36:         <div class="navigation">
  37:             <div class="alignleft"><?php next_posts_link('&laquo; Older Entries') ?></div>
  38:             <div class="alignright"><?php previous_posts_link('Newer Entries &raquo;') ?></div>
  39:         </div>
  40:     <?php else : ?>
  41:     <?php endif; ?>
  42:  
  43: </div><!--end of entry -->
  44: </div><!--end of blog -->
  45:  
  46: <?php include (TEMPLATEPATH . '/sidebar2.php'); ?>
  47:  
  48: <br clear="all" />
  49: </div><!--end of main -->
  50:  
  51: <?php get_footer(); ?>

The thing I took away here is that there's a loop getting and displaying posts (the while loop) -- not that I fully understood it straight away --, there's a call to get the header at the top, and a call to get the footer at the bottom, and there are some calls to get the two sidebars. In other words, there's no equivalent to layout.view, the PHP file generates the whole page to display a list of posts.

All right, no problem. Let's build the layout.view. I'm going to guess the preamble to the layout will be found in header.php:

   1: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
   2: <html xmlns="http://www.w3.org/1999/xhtml">
   3: <head profile="http://gmpg.org/xfn/11">
   4: <meta http-equiv="Content-Type" content="&lt;?php bloginfo('html_type'); ?>; charset=<?php bloginfo('charset'); ?>" />
   5: <title><?php bloginfo('name'); ?> <?php if ( is_single() ) { ?> &raquo; Blog Archive <?php } ?> <?php wp_title(); ?></title>
   6: <meta name="generator" content="WordPress &lt;?php bloginfo('version'); ?>" /> <!-- leave this for stats -->
   7: <link rel="stylesheet" href="&lt;?php bloginfo('stylesheet_url'); ?>" type="text/css" media="screen" />
   8: <link rel="alternate" type="application/rss+xml" title="&lt;?php bloginfo('name'); ?> RSS Feed" href="<?php bloginfo('rss2_url'); ?>" />
   9: <link rel="pingback" href="&lt;?php bloginfo('pingback_url'); ?>" />
  10: <?php wp_head(); ?>
  11: </head>
  12: <body>
  13: <div id="wrapper">
  14:  
  15: <div id="searchbar">
  16: Search this blog...
  17: <div id="searchtext"><?php include (TEMPLATEPATH . '/searchform.php'); ?></div>
  18: </div><!--end of searchbar -->
  19:  
  20: <div id="header">
  21: <div id="header_left_top"><!-- Hack for IE --></div>
  22: <div id="header_left">
  23:  
  24: <div id="subscribe">
  25: <a href="&lt;?php bloginfo('rss2_url'); ?>"><img src="&lt;?php bloginfo('template_directory'); ?>/images/subscribe.gif" border="0" alt="Subscribe to RSS Feed!"/></a>
  26: </div><!--end of subscribe -->
  27:  
  28:     <div id="navigation">
  29:     <div id="menu">
  30:         <ul>
  31:         <li class="&lt;?php if (((is_home()) &amp;amp;&amp;amp; !(is_paged())) or (is_archive()) or (is_single()) or (is_paged()) or (is_search())) { ?>current_page_item<?php } else { ?>page_item<?php } ?>"><span><a href="&lt;?php echo get_settings('home'); ?>">Home<?php echo $langblog;?></a></span></li>
  32:                 <?php $params = wp_list_pages('sort_column=menu_order&depth=1&title_li='); ?>
  33:            </ul>
  34:     </div><!--end of menu -->
  35:     </div><!--end of navigation -->
  36:     
  37: </div><!--end of header_left -->
  38:  
  39: <div id="header_right"><br />
  40: <h1><a href="&lt;?php echo get_option('home'); ?>/"><?php bloginfo('name'); ?></a></h1>
  41: </div><!--end of header_right -->
  42:  
  43:  
  44: <br clear="all" />
  45: </div><!--end of header -->

This is more like it. Lots of headery type stuff. I copied this into a new file called layout.view, and looking at a real layout.view that came with Graffiti, converted the calls to the PHP interpreter to calls to Graffiti's Chalk markup.

   1: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
   2: <html xmlns="http://www.w3.org/1999/xhtml">
   3:     <head>
   4:         <title>$title</title>
   5:         $macros.Style("style.css","screen")
   6:         <!--[if lte IE 7]>
   7:         $macros.Style("ie7.css","screen")
   8:         <![endif]-->
   9:         <!--[if lte IE 6]>
  10:         $macros.Style("ie6","screen")
  11:         <![endif]-->        
  12:         
  13:         $macros.Head()
  14:     </head>
  15:  
  16:     <body>
  17:         <img src='$macros.ThemeFile("images/CastleriggBrownTone.jpg")' border="0" class="centered" style="margin-bottom:0;"/>
  18:     
  19:         <div id="wrapper">
  20:             <div id="header">
  21:  
  22:                 <div id="header_left_top"><!-- Hack for IE --></div>
  23:                 <div id="header_left">
  24:  
  25:                     <div id="searchbar"><br />
  26:                         Search this blog...
  27:                         <div id="searchtext">
  28:                             <form action="$urls.Search" method="get" >
  29:                                 <input type="text" alt="search this site" class="search-box" value="Search..." name="q" id="ls" 
  30:                                     onblur="if (this.value == '') {this.value = 'Search...';}" 
  31:                                     onfocus="if (this.value == 'Search...') {this.value = '';}" />
  32:                                 <input type="hidden" id="searchsubmit" value="Search" />
  33:                             </form>
  34:                         </div><!--end of searchtext -->
  35:                     </div><!--end of searchbar -->
  36:  
  37:                     <div id="navigation">
  38:                         <div id="menu">
  39:                             <ul>
  40:                                 $macros.NavBar()           
  41:                                 <li><a href="$urls.rss">Subscribe</a></li>
  42:                            </ul>
  43:                         </div><!--end of menu -->
  44:                     </div><!--end of navigation -->
  45:     
  46:                 </div><!--end of header_left -->
  47:  
  48:                 <div id="header_right"><br />
  49:                     <h1><a href="http://blog.boyet.com">blog.boyet.com</a></h1>
  50:                 </div><!--end of header_right -->
  51:  
  52:                 <br clear="all" />
  53:              </div><!--end of header -->

image(As you can see I indented the code an awful lot and moved a couple of things around: the subscribe link was too big, so I made it part of the menu at the top, and I added my own image to the top of the page.)

The interesting Graffiti bits are the calls to the $macros Chalk object. $macros is a "library of tools to build a view" and here I've used the Style, Head, ThemeFile, and NavBar methods. These make use of the configuration of Graffiti on my website to embed the right URLs and to render the navigation bar setup in the Graffiti control panel.

You'll also see calls to $title, which is replaced by the main title for the site from the Graffiti control panel, and $urls, which renders various special URLs for the site (here,the RSS feed).

Converting the footer was even simpler.

Control panel - Title fieldFinally I completed the layout.view file by adding a call to $childContent. It's this magic method that renders the content of the page, and will include index.view or post.view accordingly. We'll talk about them next time.

Share it: Digg It!  StumbleUpon  Reddit  Del.icio.us  NewsVine  Furl  BlinkList  Ma.gnolia  Technorati

Customizing Graffiti CMS, part I

There were several reasons for choosing Graffiti as the CMS for my blog, but I suppose two were at the forefront: first, it was written in ASP.NET, and second it was very customizable, even to the point of writing plug-ins in C#. Since, in theory, I know this platform, this made it an attractive choice.

But, and what a big but, the documentation for all this is pretty bad. Ugly I'd say. All of the help is written with and displayed in Graffiti, and there doesn't seen to be any rhyme or reason to it. Also the basic documentation is at one end of the spectrum ("you know nothing") and the advanced at the other end ("we assume you know an awful lot, but we aren't really going to tell you what you do know"). It also doesn't help that the topics are in descending order of being posted.

Since I disliked the themes that came with Graffiti, the first port of my customization call was simple theming.

To create a theme you need at least four files. The first is the obvious one, a CSS (Cacading Style Sheet) file. The other three define the three basic views of a Graffiti site: layout.view, index.view, and post.view. Actually that isn't quite right: the layout.view file defines the basic layout of each page on your site, and the other two are refinements. index.view defines the layout for a list of posts, and post.view defines the layout for a single post. The views are in fact HTML documents with some special markup that causes Graffiti to inject other views into the HTML.

In other words, layout.view shows the common parts of every single web site rendered by Graffiti. It will generally include the <head> element, and the beginning/ending <body> tags. The basic plumbing, if you like.

I'm getting old these days, and I never was a great designer, so I'd rather use someone else's theme than write my own from scratch. I was never really fond of my "theme" for the old web site (it looked pretty good, but it feels very brittle underneath), so I went out looking for themes to use and/or modify.

Don't bother with Graffiti themes, there just aren't that many. (With one caveat: collect them so you can look at how the author used the special Graffiti markup in the views. I've learned a lot from looking at how the markup is used. Oh, another thing: the special markup is known as "Chalk".)

Chronicles theme You don't have to look very far to see that there are a bazillion Wordpress themes out there. You can get free ones; you can pay for commercial ones that are more polished. The authors of the free ones generally ask you to mention them if you use their theme on your site.

After some looking, I found one called Chronicles. It's a very nice looking three column theme in shades of brown, a color I hadn't used before. I downloaded it and unzipped it. Yikes, PHP everywhere.

(To be continued in part II, part III, and part IV.)

Share it: Digg It!  StumbleUpon  Reddit  Del.icio.us  NewsVine  Furl  BlinkList  Ma.gnolia  Technorati

About Me

I'm Julian M Bucknall, the M because it's my middle initial and because I and the other Julian Bucknall (the movie guy) would like to differentiate ourselves.

I'm a programmer by trade, an actor by ambition, and an algorithms guy by osmosis. I write articles for PCPlus in my spare time, not that there's much of that.

Julian M Bucknall Apart from that, an ex-pat Brit, atheist, microbrew enthusiast, Pet Shop Boys fanboy, slide rule and HP calculator collector, amateur photographer, Altoids muncher.

DevExpress

I'm Chief Technology Officer at Developer Express, a software company that writes some great controls and tools for .NET and Delphi. I'm responsible for the technology oversight and vision of the company.

The OUT Campaign

The OUT Campaign

Validation

Valid XHTML 1.0 Transitional     Valid CSS!

Bottom swirl

Archives

September 2010 (1)
SMTWTFS
« Aug  
1234
567891011
12131415161718
19202122232425
2627282930

Like this Archive Calendar widget? Download it here.

Search

Google ads

My Tweets

Bottom swirl