Blogger Hacks
by Dave Goodman


Introduction

These are some of the hacks I've used in my blog, eMusings. Unfortunately, I don't have a lot of free time, so please don't email asking for help. I hate having to say that, but hopefully now you won't be offended if I don't reply to your email. Blogger forums are a good place to seek assistance (see the links below). I do welcome corrections or suggestions. Be sure to back up your files before entering any hack, and, of course, use at your own risk. Your mileage may vary.



Comments List

This hack gives a list of who has left comments on a post, with the timedate stamp. This is done in your Blogger template. As always, back up your template before you muck with it. It's not for the faint of heart. ;)

Example:

Tuesday, April 19, 2005
this is a post ... blah blah blah

Posted 4/19/2005 02:03:00 PM 3 comments:
On 4/19/2005 5:00 PM, Jack said...
On 4/19/2005 5:21 PM, Jill said...
On 4/19/2005 5:25 PM, Bob said...

Find where your BlogItemComments are and figure out how to merge this in (main part in bold):

<p class="post-footer">
<em>posted <a href="<$BlogItemPermalinkUrl$>" title="permanent link"><$BlogItemDateTime$></a></em>
<BlogItemCommentsEnabled>
<$BlogItemControl$><a class="comment-link" href="<$BlogItemPermalinkURL$>#comments"><$BlogItemCommentCount$> comments</a>:

<!-- comments enhancement by dkgoodman.com -->
<BlogItemComments>
<br><font size="-2">On <a href="<$BlogCommentPermalinkURL$>"><$BlogCommentDateTime$></a>, <$BlogCommentAuthor$> said...</font>
</BlogItemComments>

</BlogItemCommentsEnabled>



Custom # of Comments

This hack lets you display the number of comments with custom descriptions based on the number of comments for that post. It involves changes to the template in two places, and uses Javascript.

Example:

Tuesday, April 19, 2005
this is a post ... blah blah blah

Posted 4/19/2005 02:03:00 PM A whopping 13 comments!

The first part goes near the top of your template, and is shared by all the posts on the page. I'd put it just before the </head>.

<script language="javascript" type="text/javascript">
<!--
function CommentNum(count)
{
var iCount = parseInt(count);
if (iCount > 6)
return "A whopping " + count + " comments!</a>";
switch (iCount)
{
case 0: return "Post a comment!</a>"
case 1: return "1 comment</a>:"
default: return count + " comments</a>:"
}
}
// -->
</script>
</head>

The second part goes in the BlogItemCommentsEnabled section, where the number of comments are currently displayed. The main part is in bold. If you use my comments enhancement, it goes just above that.

<p class="post-footer">
<em>Posted <a href="<$BlogItemPermalinkUrl$>" title="permanent link"><$BlogItemDateTime$></a></em>  
<BlogItemCommentsEnabled><$BlogItemControl$>
<script language="javascript">
<!--
document.writeln('<a class="comment-link" href="<$BlogItemPermalinkURL$>#comments">' + CommentNum('<$BlogItemCommentCount$>'));
// -->
</script>
<noscript><a class="comment-link" href="<$BlogItemPermalinkURL$>#comments"><$BlogItemCommentCount$> comments</a>:</noscript>


<!-- comments enhancement by dkgoodman.com -->


Random Quotes

This hack will display a random quote. You can add as many quotes as you like, but it increases the size of your web page. It's shown here in two parts, but they can be consolidated. I like to put the top part just before the </head> at the top of the Blogger template. You have to be careful with apostrophes and double-quotes inside each line. The second part goes where you want the quote to be displayed. The quote will change each time the page is reloaded (but no faster than once a second).

Example (click Refresh to see another):



First part:
<script language="JavaScript">
<!--
function initArray()
{
this.length = initArray.arguments.length
for (var idx=1; idx<=this.length; idx++)
this[idx] = initArray.arguments[idx-1]
}
function Rand(nMax) { var dDate = new Date(); return (Math.floor(dDate.getTime() / 1000)) % nMax }

var asQuotes = new initArray(
"A candle is not dimmed by lighting another candle.",
"A hen is an egg's way of making more eggs.",
"A horse walks into a bar. The bartender says, 'Why the long face?'",
"A procrastinator's work is never done.",
"Build a man a fire, and he'll be warm for a day.<br>Set him on fire, and he'll be warm the rest of his life.",
"If corn oil is made from corn, what\'s baby oil made from?"
);
// -->
</script>

Second part:
<script language="JavaScript">
<!--
document.write('<b>'+asQuotes[Rand(asQuotes.length) + 1]+'</b>')
// -->
</script>



Skinning

Skinning a blog can be done in different ways. I do it by putting the CSS styles in a file separate from the Blogger template, and using cookies to load the style selected by the user. This requires that you have a server where you can store the style files. Before you do anything, make a backup of your Blogger template.

The first step is to make a style file. I call mine styles.css for the default style, and stylesChina.css and stylesPumpkin.css for my user-selected styles. Note that they all start with styles, so the name of the specific file can just be appended to that with .css to form the filename. styles+China+.css = stylesChina.css Inside this file put the CSS code that's at the top of your Blogger template and take it out of your template. Put everything between <style type="text/css"> and </style> in the file, then take it out of the template, including the start and end tags. To make other styles, just copy styles.css and rename the new file as described, then change the style in that file.

Make a skins.js file that has some javascript code for reading and writing cookies, and put this in it:

// Created by Godels.com using the cookie functions from:
//
//Display Time of last visit script- Mattias Sjoberg
//Modified by JavaScript Kit (http://javascriptkit.com)
//Visit http://javascriptkit.com for this script

var expDays = 90;
var exp = new Date(); 
exp.setTime(exp.getTime() + (expDays*24*60*60*1000));

function getCookieVal (offset) {  
	var endstr = document.cookie.indexOf (";", offset);  
	if (endstr == -1)    
		endstr = document.cookie.length;  
		return unescape(document.cookie.substring(offset, endstr));
}

function GetCookie (name) {  
	var arg = name + "=";  
	var alen = arg.length;  
	var clen = document.cookie.length;  
	var i = 0;  
	while (i < clen) {    
	var j = i + alen;    
	if (document.cookie.substring(i, j) == arg)      
		return getCookieVal (j);    
		i = document.cookie.indexOf(" ", i) + 1;    
		if (i == 0) break;   
	}  
	return null;
}

function SetCookie (name, value) {  
	var argv = SetCookie.arguments;  
	var argc = SetCookie.arguments.length;  
	var expires = (argc > 2) ? argv[2] : null;  
	var path = (argc > 3) ? argv[3] : null;  
	var domain = (argc > 4) ? argv[4] : null;  
	var secure = (argc > 5) ? argv[5] : false;  
	document.cookie = name + "=" + escape (value) + 
	((expires == null) ? "" : ("; expires=" + expires.toGMTString())) + 
	((path == null) ? "" : ("; path=" + path)) +  
	((domain == null) ? "" : ("; domain=" + domain)) +    
	((secure == true) ? "; secure" : "");
}

function DeleteCookie (name) {  
	var exp = new Date();  
	exp.setTime (exp.getTime() - 1);  
	// This cookie is history  
	var cval = GetCookie (name);  
	document.cookie = name + "=" + cval + "; expires=" + exp.toGMTString();
}

var CSSCookieName;
var whichCSSFile;
var defaultCSS;
function whichCSS() {
	whichCSSFile=GetCookie(CSSCookieName);
	if (whichCSSFile == null) whichCSSFile=defaultCSS;
	whichCSSFile="styles"+whichCSSFile;
}

function jump(cookieVal) {
	SetCookie(CSSCookieName,cookieVal);
	document.location.href=document.location;
}

Now we want to use the code in skins.js to determine what styles file to load, and we want to load it. Where your style used to be in the template, put this:

<script language="javascript" type="text/javascript" src="http://yourserver.com/styles/skins.js"></script>
<script language="javascript" type="text/javascript">
<!--
CSSCookieName="dkgStyle";
defaultCSS="";
whichCSS();
document.write("<link rel='stylesheet' href='http://yourserver.com/styles/"+whichCSSFile+".css' type='text/css' />");
//-->
</script>
<noscript>
<link rel='stylesheet' href='http://yourserver.com/styles/styles.css' type='text/css' />
</noscript>

Change the path to the files to match their location on your own server.

Now we just need to give the user a way to select a style. Somewhere in your sidebar, add this:

<script language="javascript" type="text/javascript">
<!--
document.writeln('<center><form name="skinsel">Skin: ')
document.writeln('<select name="skin" OnChange="javascript:jump(this.form.skin.options[this.form.skin.selectedIndex].value)">')
document.writeln('<option value="" selected>[default]')
document.writeln('<option value="">Pumpkin')
document.writeln('<option value="China">China')
document.writeln('</select>')
document.writeln('</form></center>')
// -->
</script>

As always, backup your template first. Use at your own risk. If you should be caught or killed, I will disavow any knowledge of your actions. If you need help, find someone good at CSS and JavaScript. Good luck.



Comment Author Photos

I like the way the photos of comment authors show up in Haloscan comments, and in the popup-window of Blogger comments, and I wanted that feature for my old-style Blogger comments. Since Blogger doesn't give me any Blogger tags I can use for that, I had to roll my own, by using the URL that Blogger does supply for the author.

What my system does is to make a table of URLs and image links for the blog visitors I want to support with photos, and then add an image when it finds a comment author in that table. The first part of the hack builds the table, and it goes in the <BlogItemCommentsEnabled> section of the Blogger template so the code for the table is only published on your pages that have comments. The second part goes in the comment-body part of the template, where it actually calls the table lookup with the URL for the author.

Example:

At 5/8/2005 7:44 PM, John said...
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

You'll need to find the <BlogItemCommentsEnabled> part of your template, back up your template, and figure out how to merge in the code below. Note: Blogger made a small change that required a fix to this code. I added the line url.replace(' rel="nofollow"', '') in the CheckAuthor function.

Blogger template code:

 <div id="comments">
  <BlogItemCommentsEnabled><a name="comments"></a>

  <!-- Comment author profile photo hack Copyright (c) 2005 by David K. Goodman at http://dkgoodman.com -->
  <script language="javascript">
  <!--
    var iAuthors = 0;
    function AddAuthor(id, u, w, h)
    {
        var entry = new Array();
        entry["i"] = id;
        entry["u"] = u;
        entry["w"] = w;
        entry["h"] = h;
        this[iAuthors++] = entry;
    }

    Array.prototype.AddAuthor = AddAuthor;
    authors = new Array();

    // the first argument to AddAuthor is the URL
    // from the CheckAuthor('<$BlogCommentAuthor$>'); call below
    // the second argument is the link to the photo to use
    // the 3rd and 4th are the desired photo width and height
    authors.AddAuthor('www.blogger.com/profile/xxx', 'somedomain.com/author.gif', 66, 72); // dkg
    authors.AddAuthor('www.blogger.com/profile/yyy', 'someplace.com/profile.jpg', 66, 47); // john

    function CheckAuthor(url)
    {
        var sDefault = "yourdomain.com/pen.gif";
        var iXDefault = 82;
        var iYDefault = 39;
        url = url.replace('<a href="http://', '')
        url = url.replace(' rel="nofollow"', '')
        var iEnd = url.indexOf('">')
        if (iEnd != -1)
            url = url.substr(0, iEnd)
        for (var iAuth=0; iAuth<iAuthors; iAuth++)
            if (authors[iAuth]["i"] == url )
            {
                document.writeln('<a href="http://' + url + '"><img src="http://' + authors[iAuth]["u"] + '" width=' + authors[iAuth]["w"] + ' height=' + authors[iAuth]["h"] + ' border=0></a><br>');
                break;
            }
        if (iAuth >= iAuthors)
            document.writeln('<a href="http://' + url + '"><img src="http://' + sDefault + '" width=' + iXDefault + ' height=' + iYDefault + ' border=0></a><br>');
    }
  // -->
  </script>

<h4><$BlogItemCommentCount$> Comments:</h4>
<dl id="comments-block">
<BlogItemComments>
<dt class="comment-data" id="c<$BlogCommentNumber$>"><a name="c<$BlogCommentNumber$>"></a> At <a href="#c<$BlogCommentNumber$>" title="comment permalink"><$BlogCommentDateTime$></a>, <$BlogCommentAuthor$> said...
</dt>
<dd class="comment-body">
<div style="float: left; margin-top: 3px; margin-bottom: 3px; margin-right: 3px;">
<script language="javascript">
<!--
    CheckAuthor('<$BlogCommentAuthor$>');
// -->
</script>
</div>
<p><$BlogCommentBody$></p>
<div style="clear:both;"></div>
<$BlogCommentDeleteIcon$>
</dd>
</BlogItemComments>
</dl>
<p class="comment-data"> <$BlogItemCreate$> </p>
</BlogItemCommentsEnabled>
<p style="padding-left:20px;"> <a href="<$BlogURL$>"><< Home</a> </p>
</div>


Links