Quicktags for Comments

Note: The seperate Quicktags toolbar is not supported. Please use the full toolbox script, or hack it any way you like. The remainder of this post remains for posterity only.

•

This was easier than I thought.  Alex King has done most of the work by having the Quicktags info already in a JavaScript file. I just grabbed my copy of the file (from /wp-admin/quicktags.js) and tweaked it.  To upload to the Blogsome server I had to call it quicktags.jpg, but that is allowed, since you tell the browser explicitly that it is a text/javascript file. So, you can get my quicktags.js file (Right-click and download it!), and upload it to your server, and use the following code in your comments.html. Where you want the toolbar to appear, insert this:

1
2
    <script src="/images/quicktags.jpg" type="text/javascript"></script> 
    <script type="text/javascript">edToolbar();</script> 

After the <textarea>, insert the following code:

1
2
3
    <script type="text/javascript"> 
        <!-- edCanvas = document.getElementById('comment'); //--> 
    </script>

Note: you may need to chage the argument of getElementById to whatever your textarea id is. I’ve also tweaked the JavaScript file so it includes abbr, acronym and strike tags, and doesn’t include the tags that aren’t valid for comments.  And I’ve added a button for inserting < and >, but I’m not totally happy with this.  If anyone wants to edit it so it works better (try it out to see what I mean), then feel free.

I’ve also created another version that uses links instead of buttons (since Camino doesn’t render buttons with style, only as Mac-buttons), but it’s not quite as nice: the labels don’t update. Still, if anyone wants to play around with it, you can get it here. Remember to right-click and download it, it’s not really an image!

Next task: Live Preview.

Smarty: Insert / Comment Tags

Smarty This may have some use: {insert}. I noticed it when backing up my templates tonight… • Also, I’d like to make buttons that act like the quicktags in the Blogsome backend for commenting: so it inserts the relevant tags in. Will require some JavaScript, I assume…

Seperating Trackbacks and Comments

I can’t recall if this came up on the Blogsome forums or not, but some people are keen to seperate Trackbacks and Comments in the comment list. Sometimes, and especially for people new to blogs, Trackbacks don’t seem to make that much sense, so I thought I would try doing this on Blogsome. Googling seperate trackbacks comments wordpress turned up several sites, the first one I visited was from way back in July 2004, and was way to complicated to bother with.

The second one was better, and gave me the idea of how to do it. Then I remembered that there is a Template Tag called comment_type. I duplicated the main comment: the commentlist and the {foreach} that cycles through each comment, and used the following bit of code to get the {comment_type} into a variable (so I can test it):

1
    {capture name=comment_type}{comment_type}{/capture}

It’s a simple matter to test this against a known value:

1
    {if $smarty.capture.comment_type != 'Comment'}

And you know that you are working with a Trackback or Pingback. The first iteration of the commentlist only displays non-comments, the second only displays comments (it uses == 'Comment' instead). The last tricky bit was to figure out how to show Trackbacks from my own site in the class='owner' format (on here, in a reddish box rather than green). This required a little trick I had discovered earlier today:

1
    {capture name=author_trackback}trackback@{bloginfo show='url'}{/capture}

And then the test is:

1
    {if $smarty.capture.reader == $smarty.capture.author_trackback|replace:'http://':''}

(This assumes you have used my previous method for styling your own comments differently). The full text of my comments.html template then:

    <div id="commentarea">
    {if $post->ping_status}
        <p class='indented'>{_e text='The <acronym title="Uniform Resource Identifier">URI</acronym> to TrackBack this entry is:'} <em>{trackback_url}</em></p>
    {/if}
    
    <p class='indented'>{comments_rss_link link_text='<span class="rss"><abbr title="Really Simple Syndication">RSS</abbr></span> feed for comments on this post.'}</p>
    
    <h3 class="comments">{comments_number zero="Responses" one="1 Response" more="% Responses"} to &#8220;{the_title}&#8221;
    {if $post->comment_status == 'open'}
    <a href="#postcomment" title="{_e text='Leave a comment';}">&raquo;</a>
    {/if}
    </h3>
    
    {if $comments != ''}
      {capture name=author}{the_author_email}{/capture}
      {capture name=author_trackback}trackback@{bloginfo show='url'}{/capture}
    
      <h3 class="comments">Trackbacks / Pingbacks</h3>
      <ol class="commentlist">
      {foreach from=$comments key=key item=comment}
        {globalvar var='comment' value=$comment}
        {capture name=comment_type}{comment_type}{/capture}
        {if $smarty.capture.comment_type != 'Comment'}
            {capture name=reader}{comment_author_email}{/capture}
            {if $smarty.capture.reader == $smarty.capture.author_trackback|replace:'http://':''}
            <li class="owner" id="comment-{comment_ID}">
            {else}
            <li class="alt" id="comment-{comment_ID}">
            {/if}
            From the site {comment_author_link}:
        {comment_text}
            Posted on {comment_date} at {comment_time}.
            {edit_comment_link text="Edit this trackback", before='<span class="button">' after="</span>"}
        </li>
        {/if}
      {/foreach}
      </ol>
    
      <h3 class="comments">Comments</h3>
      <ol class="commentlist">
      {foreach from=$comments key=key item=comment}
        {globalvar var='comment' value=$comment}
        {capture name=comment_type}{comment_type}{/capture}
        {if $smarty.capture.comment_type == 'Comment'}
            {capture name=reader}{comment_author_email}{/capture}
            {if $smarty.capture.reader == $smarty.capture.author}
        <li class="owner" id="comment-{comment_ID}">
            {else}
        <li class="alt" id="comment-{comment_ID}">
            {/if}
                <script type="text/javascript">document.write('<div class="right"><img src="http://www.gravatar.com/avatar.php?gravatar_id='); document.write(hex_md5("{comment_author_email}")); document.write('&size=50" /><\/div>'); </script>
                On <a href="#comment-{comment_ID}">{comment_date} at {comment_time}</a>, {comment_author_link} said: 
              {comment_text}
                {edit_comment_link text="Edit this comment", before='<span class="button">' after="</span>"}
        </li>
         {/if}
      {/foreach}
      </ol>
    
    {else} _<!-- this is displayed if there are no comments so far -->_
        <p class='indented'>{_e text="No comments yet."}</p>
    {/if}
    
    <h3  class="comments">{_e text="Leave a Reply"}</h3>
    {if 'open' == $post->comment_status}
         <form action="{$siteurl}/wp-comments-post.php" method="post" id="commentform">
        <p>
          <input type="text" name="author" id="author" class="textarea" value="{insert name=var var=comment_author}" size="28" tabindex="1" />
           <label for="author">{_e text="Name"}</label> {if $req != ''} {_e text='(required)'} {/if}
        <input type="hidden" name="comment_post_ID" value="{$post->ID}" />
        <input type="hidden" name="redirect_to" value="{$redirect_to}" />
        </p>
    
        <p>
          <input type="text" name="email" id="email" value="{insert name=var var=comment_author_email}" size="28" tabindex="2" />
           <label for="email">{_e text="E-mail"}</label> {if $req != ''} {_e text='(required)'}{/if}
        </p>
    
        <p>
          <input type="text" name="url" id="url" value="{insert name=var var=comment_author_url}" size="28" tabindex="3" />
           <label for="url">{_e text="<acronym title='Uniform Resource Identifier'>URI</acronym>"}</label>
        </p>
    
        <p>
          <label for="comment">{_e text="Your Comment"}</label>
        <br />
          <textarea name="comment" id="comment" cols="60" rows="12" tabindex="4"></textarea>
              <input type="hidden" id="textarea_next_time" name="textarea_next_time" value="60,12" />
        </p>
    
        <p>
          _<!--input disabled name="preview" type="image" tabindex="5" src="/images/preview.png" size="75%" /-->_
          <input name="submit" type="image" tabindex="6" src="/images/post_comment.png" size="75%" />
        </p>
    
    <p>{_e text="Line and paragraph breaks automatic, e-mail address never displayed, <acronym title='Hypertext Markup Language'>HTML</acronym> allowed:"} <code>{allowed_tags}</code>, 'Smart' Smileys.</p>
    
    
    </form>
    {else} _<!-- comments are closed -->_
    <p>{_e text="Sorry, the comment form is closed at this time."}</p>
    {/if}
    </div>

Archive and Links Pages

It would be nice to be able to have a links and/or archive page under blogsome: that just had a list of all links, or a list of all posts/months/days (whatever). The problem is that Pages cannot use template tags, and it is not much fun to update these pages by hand. A solution presented itself to me today, and it goes like this:

    {if $smarty.server.REQUEST_URI == '/links/'}
        {get_links_list}
    {elseif $smarty.server.REQUEST_URI == '/archives/'}
        {get_archives type='postbypost' limit='' format='html'}
    {/if}

This code can go into the Main Page template, just after {content}, or into the post.html template if you’ve used my previous hack to get Pages processed by the post template. You’ll also need to create Pages: Links and Archives (if you use different names, be sure to ensure the page-slug is the one that is listed in the code above). I had to put a <br /> into each Page in order to get rid of all errors. You can see the results here: Archives, Links. It’s more than likely that a similar solution exists for categories: I’ll do that too. Update: Categories, Pages. Note: Make sure you have the slash following the URL when you try to access them. It may be possible to have a double {if} clause (with slash and without), but I’m not sure yet… later works a treat:

     {if $smarty.server.REQUEST_URI == '/links/' || $smarty.server.REQUEST_URI == '/links'}
        {get_links_list}

And so on…

Blogsome Themes, Part 2.

In the last post in this series, we learned how to upload images, and modify the StyleSheet so that these images were referenced by that. What we need to do now is to start putting the rest of the files into the right places. Before we can do this, we need to learn two things:

  • How the WordPress Template system and Loop ‘work’.
  • How Smarty Tags are created from a PHP function call.

We might start with the second one, just to be creative!

Smarty and PHP

PHP is a language used mainly in web page design and layout. It provides the ability to have complex, dynamic pages that are generated on-the-go. It is, however, a fully fledged language, and if someone has unfettered access to it on a server, they could do stuff that could bring the whole server down. This is usually not a problem for a blog, where you host your own server, or pay someone to host it for you. However, services that offer free blog hosting are perhaps more likely to be targetted, perhaps accidentally, perhaps deliberately, bu badly formed or malicious PHP code. Smarty Tags are a way to get around this. Basically, it’s a different way to write PHP code, designed to be used in template files. The syntax is very simple to understand: mostly you’ll come across things such as {bloginfo show='description'}. This was the last thing in my clipboard, it would, when placed in a template, display the Description (or Tagline, as Blogsome calls it) in the page. The first thing you’ll notice is that it is wrapped in curly brackets. Any Smarty Code must be wrapped in these for it to be interpreted: otherwise it will just be displayed as text. The second notable part is the function name. In this case, bloginfo. You can almost always find out more about a function call from the WordPress Codex. The final part is the argument. In this example, there is one argument, called show, with the value 'description'. This is where Smarty and PHP diverge: Smarty parameters or arguments must be named. Most of the pages in the Codex on Template Tags will give you a list of the arguments and their possible values. Lets see a couple more examples: One tag you will certainly need to use in your template is the_content. This will insert the text from an entry into the page. According to the Codex, it’s form is:

1
    <?php the_content('more_link_text', strip_teaser, 'more_file'); ?>

Now, because we are going to be using Smarty, we can make it look much nicer. The simplest version will be: {the_content} But, if we want to change the

text, we’ll need to pass a value to the more_link_text argument: {the_content more_link_text='<BR /><BR />Read More' (Two line breaks, followed by the text Read More… will appear whenever the quicktag is used in any entry: this will only apply on an index page, the full entry will be shown on the individual page). Our last example will be to use the the_time tag. This will display the time and/or date of the post, depending on the argument that is given.

1
    <?php the_time('format'); ?>

You can see that the argument name appears to be format, however, it’s really d. This took me some time to figure out, and I only discovered it because I was using a previous Blogsome template to crib from. The value needs to be a valid PHP date format string. {the_time d='D j M Y'} Will give Mon 7 Jul 2020, or whatever the post date is. If you put a value in, and get only the time back (ie, 2:36pm), and this was not what you asked for, the argument or value may be incorrect. Okay, that’s all I’m going to write about how to get from PHP to Smarty: by all means read the Smarty Documentation if you don’t yet understand!

WordPress Templates

WordPress is pretty flexible in terms of template filenames, but generally there will be seven or so:

  • index.php • The main template file. Gets called when an index page is requested (such as the main page of the site).
  • sidebar.php • Contains the data that will go into the menu that usually appears on the side of a blog. Will be inserted when get_sidebar(); is called in PHP code.
  • header.php, footer.php • Contains the data that tells the top or bottom of the page what to look like.
  • post.php • The specific layout instructions for a post view.
  • comments.php • Will only be included if comments are active on the post.
  • page.php • For Page layout, rather than Posts. New to WordPress 1.5

The reason the files are split up is that this means they can be re-used: header and footer will be used at the top/bottom of post and page, as well as index, and sidebar will probably be used in several places as well. The problem with Blogsome is that there are only four files that can be edited: and one of them is the StyleSheet, which we have already done! So, we need to squeeze six or seven files into three. The easiest way to go is to understand that post.php needs to be placed into post.html, and comments.php needs to go into comments.html, and everything else needs to go into index.html. However, we cannot just copy and paste the data, we need to convert it. Before you start, it’s a good idea to make a copy of the data in each of the Blogsome files, so you can see how the theme that was there was doing it, and that should give you some ideas as to how might be a good way to do it yourself. We’ll start with post.html: it’s probably the simplest.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
    <p class="post-date"><?php the_time('D j M Y'); ?></p>
    <div class="post-info"><h2 class="post-title"><a href="<?php the_permalink() ?>" rel="bookmark" title="Permanent Link: <?php the_title(); ?>"><?php the_title(); ?></a></h2>
    Posted by <?php the_author(); ?> under <?php the_category(' , '); ?><?php edit_post_link('(edit this)'); ?><br/><?php comments_popup_link('No Comments', '1 Comment', '[%] Comments'); ?>&nbsp;</div>
    <div class="post-content">
        <?php the_content(); ?>
        <div class="post-info">
            <?php wp_link_pages(); ?>                                           
        </div>
        <!--
            <?php trackback_rdf(); ?>
        -->
        <div class="post-footer">&nbsp;</div>
    </div>

This is the code that Patricia created for Connections, the theme I use. Let us try to understand the code so we can Smarty-fy it. The first line is the post date, using one of the tags we looked at before. The next two lines contain all of the post meta-data: it’s permalink, categories and so on. From there we have some layout tags (everything with a div is an HTML construct to divide the page up nicely), and then the actual content. This is followed by the link pages (Next/Previous Pages of a multi-page post), and then the Trackback info. Then we have the post footer (different to the footer.php I mentioned above!), and that’s about it. Do notice that the div tags that are opened on this page are all closed on this page: that makes it much easier to validate code. I also tend to indent my code so it’s clearer to follow, but that’s probably because I’d rather be coding in python. Convert all of your PHP function calls to the relevant Smarty Code: basically replace <?php by {, and ?> by }, and the arguments as discussed above. Remember to check the Codex if you run into trouble. Here’s what I changed mine into:

    <p class="post-date">{the_time d= 'D j M Y'}</p>
    <div class="post-info"><h2 class="post-title"><a href="{the_permalink}" rel="bookmark" title="Permanent Link: {the_title}">{the_title}</a></h2>
    Posted by {the_author} under {the_category}{php edit_post_link}<br/>{comments_popup_link zero='No Comments' one='1 Comment' more='[%] Comments'}&nbsp;</div>
    <div class="post-content">
        {the_content}
        <div class="post-info">
            {wp_link_pages}                                         
        </div>
        <!--
            {trackback_rdf}
        -->
        <div class="post-footer">&nbsp;</div>
    </div>

You can repeat these instructions with comments.php. There is some more stuff there that might require a bit of explanation, but have a crack. You should now be able to see some of your handiwork on any posts that are already in your blog. Now is a chance to check that out, and see if there are any inconsistencies that need to be ironed out.

Enclosures

Podcasting is what all of the kids are doing now: basically, from what I can tell, you just have an enclosure that is part of the post, and RSS readers can automatically download them. Blogsome doesn’t really have the ability to upload non-image filetypes (other than by renaming them to have an image-like extension), and anyway file sizes are limited to 300k, but it is possible to have enclosures that are files hosted elsewhere. Anyway, I found a page detailing how to set up enclosures, but it wouldn’t work for me. It turns out there is an array of arrays, and these need to be stepped through. The code I added to display a link to the enclosure after the post is as follows:

    {custom_fields}
    {if $enclosure != ''}
        <div class="enclosures">
            {foreach from=$enclosure item=enc}
                <div class="enclosure"><b>Attached Enclosure</b><br />
                    File: <a href="{$enc.0}">{$enc.0}</a><br />
                    Length: {$enc.1} bytes<br />
                    Type: {$enc.2}<br />
                </div>
            {/foreach}
        </div>
        {assign var='enclosure' value=''} <!-- reset enclosure variable again! -->
    {/if}

The only part I haven’t got working yet is the Length and Type fields: they are both blank. I’ll work harder….

Blogsome Page Templates

(This is an extension on the previous post). One of the major drawbacks of Blogsome is the handling of _Pages _is not complete. You can create and manage Pages, but the display of them is sub-standard: there is no page.html template file as there is for _Posts _(post.html). However, I have figured out a stop-gap method of running pages through a template. I tried first to do this by adding a Custom Field, as noted in the WordPress Codex, called _wp_page_template, and setting this value to post.html. This did not work, mainly (as far as I could tell) because the value did not ‘stick’. This seems to be a known issue with WordPress 1.5.1. I was able to get enclosure Custom Fields to work (almost: they only ever appeared to be an Array). The next way I figured out how to do it was by finding a variable that has a different value when a Page is being rendered, as opposed to a Post or Index, or Category, or Archive. The variable I discovered is {$smarty.server.SCRIPT_NAME}. This appears as '/wp-inst/pages' or '/wp-inst/index.php' under Blogsome. Fantastic! My next step was to have the following code where {$content} used to be in the Main Page Template:

    {if $smarty.server.SCRIPT_NAME == '/wp-inst/pages'}
        {assign var=page value=true}
        {capture name=the_content}{$content} {/capture}
        {include file='post.html'}
    {else}
        {assign var=page value=false}
        {$content}	
    {/if}

The first line, the {if} clause, finds out if it is indeed a page. The second line assigns ’true’ to the variable {$page}, just as a way of making it less cumbersome to test again later. The third line stores the text that would normally appear in the body of the Page into the variable {$smarty.capture.the_content}. This will be used in place of {$the_content} in the post.html template. The fourth line puts the contents of the post.html file into the HTML stream. Just to be safe, I set the value of {$page} to false before the post.html file gets called normally by the {$content} tag. Then, in the post.html template file, I added the following code:

  • Where the content needs to go: {if $page == 'true'}{$smarty.capture.the_content}{$content}{/if}{the_content} There is no {else} required here, as {the_content} has no value.
  • Where the Post Title normally is, I made it: <a href="{if $page == 'true'}{$Smarty.server.PHP_SELF}{else}{permalink_link}{/if}" rel="bookmark" title="Permanent Link: {if $page == 'true'}{single_post_title}{/if}{the_title_rss}">{if $page == 'true'}{single_post_title}{/if}{the_title}</a> Basically, this replaces {permalink_link} by the URL of the current Page. I’ll have a bit of a think about how multi-page documents work if I can get them working. It replaces the {the_title} value by {single_post_title}, which works quite nicely.
  • I also made it so that the Date information is replaced by a Non-Breaking Space - in my template this means that a nice coloured box appears where the Date normally goes: this box is too small otherwise. {if $page == 'true'}&nbsp;{/if} The date data will be empty, so this should work okay.
  • Finally, I used {if $page != 'true'} ... {/if} to remove information that was not pertinant to a Page, such as the Post time, number of comments, category and so on. I also needed to have the {edit_post_link} skipped in this manner.

I have not yet made comments work properly: I’m not sure that this can be done with this hack, but they will not appear if you just do the things I’ve shown above. If you {include file=comments.html}, you will get the Comment Closed Notification.

Blogsome Pages

It’s no secret the Blogsome doesn’t have working Page Templates. The following code snippet is a starter on formatting of Pages like Posts:

    {if $smarty.server.SCRIPT_NAME == '/wp-inst/pages'}
        <!-- Do Stuff Here -->
    {/if}

At the moment, I’ve only figured out how to get the content to appear twice (!), but it’s a start: it only occurs with Pages! Update: I’ve got it working. It’s a bit ugly at the moment, and I’ll probably redo it with a function, but, still it works. See the Contact and About Pages in the Menubar for examples!

Converting Themes to Blogsome, Part 1

This is the first post in a series that will deal with Blogsome theme conversions. Part 2 can be found at Blogsome Themes, part 2. To begin with, you will need the following things:

  • A blog created with Blogsome. I suggest that if you already have a blog that has posts on it, you create a new one, just to tweak until the theme is just right. That way, your real blog will continue to work, no matter what. I’ll assume you have a Blogsome blog to test on, and know a bit about the backend (Dashboard, and where to find the various options/tools).
  • The files required for your theme. Alex King has a great list of themes, and runs competitions occasionally, so go visit there if you want to find one, and don’t have one already.
  • Firefox, with the EditCSS extension installed, or the EditCSS bookmark
  • Patience

You should also bookmark the following sites:

I will use the following conventions in this document:

  • Button: a button that you click on. Will look different in each browser - usually it looks like the buttons in your Operating System, but not always.
  • Links that you need to click on will be bold.
  • Code that you modify will either look like this or this
  • Filenames will look like this.
  • Important, or unusual terms will be italic.

Converting a WordPress theme to Blogsome is not always easy, but is very rewarding, and you may learn something along the way. Finally, whilst I have gone to a lot of effort to ensure everything in this document is correct, I take no responsibility for any data loss. You should not have been working on your ‘proper’ blog anyway;).

Starting: Upload Image Files

Okay, let’s get started. The first thing you will want to do is upload all of your image files to your Blogsome blog. This is a much more time consuming process on Blogsome, as there is no automated way to do it. Under normal WordPress installations, you can usually FTP into the server, and dump all of the files you need. We need to click on the Upload button in the backend, and then on the Browse… button. Navigate to where the images you have as part of the theme are on your computer, and select the first one. Click the Upload button. When the page loads, record the information it gives you in a place you won’t lose it. Blogsome doesn’t provide the ability to look at lists of images, so if you forget it, you’ll need to try by trial and error to find it. Most of the images will have names that aren’t mangled by Blogsome’s server, so you should end up with a list of files like: /images/header.jpg /images/search.png /images/logo.gif What files you have will really depend on the theme you are using. There are some standard file names, but don’t expect them to be the same as everywhere else!

Update Style Sheet

You now are ready to insert your Style Sheet data. In the backend, click on Manage, and then on Files. Scroll down to the bottom of the page, and click on Site Style Sheet. After a few seconds, your Style Sheet will appear in the text editing box. We need to replace the entire contents of the text view with the contents of the theme’s stylesheet. This could have one of several names: typically it will end in .css, and more than likely it will be the only one. wp-layout.css, stylesheet.css and style.css are all likely candidates. We now need to examine the Style Sheet, and replace all instances of image filenames with their equivalent URL on your server. You can use relative URLs, so if you find something that looks like:

1
        background:url(img/content_bg.gif) repeat;

You will want to make it look like:

1
        background:url(/images/content_bg.gif) repeat;

You need to ensure you get every filename - otherwise the correct images will not appear! When you are done, you must save your changes. The Update Template! button will do this nicely. Righto! That’s the easy parts done. Next time, you will learn which template files Blogsome uses, and what data needs to go into each of them. You will also learn how to convert a PHP function to Smarty Tags. The next part of this article can be found at Blogsome Themes, part 2.

Search issues

Bug: if you search on this blog, it only searches within the currently active ‘group’, whether that’s a category, day or post, or the whole blog. The code in question is:

1
2
3
4
5
6
    <form id="searchform" method="post" action="{$Smarty.server.PHP_SELF}">
        <div style="text-align:center">
            <p><input type="text" name="s" id="s" size="20" /></p>
            <p><input type="image" src="/images/search.png" name="submit" value="Search" /></p>
        </div>
    </form>

Obviously, the important part is the {$Smarty.server.PHP_SELF} section. Setting it to {$Smarty.server.SERVER_NAME} or several other things seems to make no difference!