Saturday, July 23, 2005

Rotating Testimonials

With the recent re-working of the appearance of this little blog, I decided to do something that I've been wanting to do for a while now. But first, some background.

One of the membership requirements of the Alliance of Free Blogs is to post a fake quote by Glenn Reynolds. Back in February, phin of phin's blog provided the Alliance with a method of rotating multiple quotes.

That gave me an idea.

I've had "testimonials" on this little blog for, gosh, seems like forever. Or since last December, which is close enough. Some of them are actual nice things people said about me or the blog. Some are silly things that people said that may or may not be nice things about me or the blog. And some are mean things that people have said about me or the blog.

Why the mean things? Simple. There's no such thing as bad publicity. Plus, who knows? Maybe it'll come back to haunt them one day. Mwa-ha-ha-ha-ha!

Anyway, I had a bunch of testimonials I had added over time, and it was really too many.

So, inspired by phin's rotation script and idea, I wrote a rotation script for "Testimonials." It's a little different, because there are different requirements.

  • For one thing, they're real. They may be out of context, but they're real. And I wanted to continue offering links to the actual quote in it's real context.
  • Also, I might want to add more or remove some as the need or mood stuck me. So the number in rotation might vary.
  • And, some of the "testimonials" might be from people who don't, to my knowledge, have blogs. So there might not be a link to a blog. Others might have blogs and I'd provide a link to them.

So, with those differences in mind, and because of those differences, I wrote a JavaScript function that was a little different than what phin had.

I'm Game; Let's Do It

The script consists of multiple parts. All but one part should go in the <HEAD> section of your template. You see, the <HEAD> section of a Web page is loaded and run by your browser before the <BODY> section. For that reason, it's always best to put JavaScript, especially functions, in the <HEAD>. So, I'm suggesting you place the first part in the <HEAD>.


This first piece is used to trim any excess characters, such as stray spaces, from the text we'll use.

<script type="text/javascript">
// Trims characters from the beginning or end of a string
function trimText (inputString, removeChar) {
    if (removeChar==null || removeChar=="") removeChar=" ";
    if (inputString==null || inputString=="") inputString="";
    var returnString = inputString;
    if (removeChar.length) {
        while(''+returnString.charAt(0)==removeChar) {
    return returnString;

This code, adapted from a free Macromedia Dreamweaver extension, can be used to return a text string with characters stripped from the beginning and end. If you don't specify a character to remove, it will strip spaces. This is actually a handy script that could be used in many circumstances. We'll use it here.

The next section of code for the <HEAD> is what we'll use to find where a certain character in a string occurs.
<script type="text/javascript">
//    Searches in a given string for the first occurrence of another string.
function checkForCharacters(inputString, checkString, startingIndex) {
    if (!startingIndex) startingIndex = 0;
    return inputString.indexOf(checkString);
We'll talk more about this when we actually use it.

Here's The Beef

The next section, also in the <HEAD>, is the actual JavaScript function that defines the various "testimonials," selects one, and writes it. I'll have comments throughout as might be necessary.
<script type="text/javascript">
//    Function to define and write Testimonial
function showTestimony() {
    // define the number of quotes
    var quoteNum=0;
    // define arrays to contain testimonial information
    var theQuote=new Array();
    var theLink=new Array();
    var theSage=new Array();
    var theSageLink=new Array();

    //    The next few lines are from an actual testimonial I use on this little blog.
    //    Although this one contains a link to a quote on another blog,
    //    this is how a link to a quote on this blog would also be used.
    //    In fact, this is how all links to quotes that are not in HaloScan are used.
    theQuote[quoteNum]="Look at his precious baby face...";
    theSage[quoteNum]="La Shawn Barber";

    //    The next few lines are from another actual testimonial I use.
    //    This one contains a link to a quote on HaloScan.
    //    If you don't use HaloScan, you can ignore this example entirely.
    theQuote[quoteNum]="I'm Beth, and I endorse this blog.";
    theSage[quoteNum]="Beth of MY Vast Right Wing Conspiracy";
    //    Note that it's almost exactly the same as
    //    the "non-HaloScan" comments/quotes

    //    It's only provided so that you can see how to use one

    //    End actual examples

    //    This section explains the next section
    //    Reuse the following create more "testimonials"
    //    Fill in the data as needed
    // Automatically increment the number of actual quotes. Leave as is.
    //    Required for each quote

    // The actual quote.
    //    Place within the quotation marks
    //    Required for each quote (obviously)

    // The link to the quote in its original context.
    //    Place within quotation marks (optional).

    //    The person who made the quote.
    //    Place within quotation marks.
    //    Required for each quote (obviously)

    // The link to the person's blog.
    //    Place within quotation marks (optional).

    //    The following is a blank "template" for use on each "testimonial" that
    //    you want in your rotation.
    //    See the above section for instruction on each of the following lines
    //    DO NOT use the lines with /* or */
    //    Rather, use the lines in-between
    //    I suggest you copy them to where you want to use them so that your original
    //    "template" is still here
    //    Remember to use all lines, even if you leave the area within the quotes blank

    // Select one of the quotes
    var thisQuoteNum=Math.round(getRandom()*quoteNum+.5);

    //    FailSafe. If an error causes Quote number zero to be chosen,
    //    select quote number one instead
    if (thisQuoteNum<1) thisQuoteNum=1;

    //    FailSafe. If an error causes a Quote that doesn't exist to be chosen,
    //    select the last quote
    if (thisQuoteNum>quoteNum) thisQuoteNum=quoteNum;

    //    Trim any excess spaces from the quote
    var thisQuote=trimText (theQuote[thisQuoteNum], " ");

    //    Trim any excess spaces from the name of the person who made the quote
    var thisSage=trimText (theSage[thisQuoteNum], " ");

    //    Trim any excess spaces from the link of the quote in its orginal context
    var thisLink=trimText (theLink[thisQuoteNum], " ");

    //    Trim any excess spaces from the link to the blog/Website of the person
    //    who made the quote
    var thisSageLink=trimText (theSageLink[thisQuoteNum], " ");

    //    The link to my HaloScan code. Modify for yours, if applicable
    //    Leave blank if not
    var HaloScanCheckText="";

    //    How long is that. You'll see why in a minute
    var HaloScanCheckTextLength=HaloScanCheckText.length;

    //    Get the last part of the quote link
    var tmpTxt=thisLink.slice(HaloScanCheckTextLength);

    //    Find the end of the HaloScan comment number, if it exists
    var tmpVar=checkForCharacters(tmpTxt, "/", 0);

    //    Get the HaloScan comment number, if it exists
    var HaloScanNumber=tmpTxt.slice(0,tmpVar);

    //    Get the first part of the link text for HaloScan check
    var tmpHStext=thisLink.slice(0,HaloScanCheckTextLength);

    //    Define quote and Website mouseover texts
    var altTitle1="View testimonial in context";
    var altTitle2="Visit this Web site";

    //    Start writing it
    //    Write the quote
    if (thisLink != "") {
        document.write("&nbsp;<a href='"+thisLink+"' target='_blank' alt='"+altTitle1+"' title='"+altTitle1+"'");
        if (tmpHStext==HaloScanCheckText) {
            document.write(" ");
            document.write("onclick='HaloScan(HaloScanNumber); return false;'");
    //    Write the source of the quote
    document.write("<br /><div align='right'><em>");
    //    If there is a link, write the link open
    if (thisSageLink != "") {
        //    The actual link open
        document.write("<a href='");
        //    The link
        //    Use this to open the link in a separate window
        //    Omit if you want to open in same window
        //    or change _blank to _self
        document.write(" target='_blank'")
        //    Sets the mouseover text
        document.write(" alt='"+altTitle2+"' title='"+altTitle2+"'");
        //    The actual link close
    //    Write the actual name of the source
    //    If there is a link, wrote the link close
    if (thisSageLink != "") document.write("</a>");

    //    Finish writing by close all open HTML tags
So, all this only selects the quote to write. It doesn't really write it.

Wait, There's More

What's that? You see the JavaScript "document.write()" command? Doesn't that write it?

Well, yes. If you call the function. That's the final piece.

In the <BODY> section of your blog template, you need to insert one final piece that calls the function and actually writes the "testimonial" on your page. Here is that piece, that you place wherever you want the quote to appear:
<script type="text/javascript">
// -->
<p>&#8220;Look at his precious baby face...&#8221;&nbsp;<a href="" target="_blank">*</a><br />
<div align="right"><em><a href="" target="_blank">La Shawn Barber</a></em></div>

Okay, let's look at this section. The following piece, as it is, actually writes the quote and is required:
<script type="text/javascript">
// -->
The remaining piece is optional. Why use it? Well, suppose the person visiting your site has JavaScript disabled. Less than 1% of the visitors to this little blog have it disabled. They still see a quote, because of the next section. Again, I'm using a real example:
<p>&#8220;Look at his
precious baby face...&#8221;&nbsp;
target="_blank">*</a><br />
align="right"><em><a href=""
target="_blank">La Shawn Barber</a></em></div>
This is nothing more than one of the quotes I use in rotation, formatted in HTML. And that piece of HTML is inside a <NOSCRIPT> tag. If your browser ignores or otherwise doesn't support JavaScript, the stuff inside the <SCRIPT> tags is ignored. Then, and only then, is stuff inside <NOSCRIPT> executed.

In other words, if the person visiting this little blog don't support JavaScript, they still see a quote. But they all see just the one quote.

Oh, Is That All?

Now, I realize this is a long and complicated piece of script. I have seen shorter, cleaner methods of doing something similar.

If you are familiar enough with JavaScript to write a shorter version, you don't need to read this post anyway. But, if you're new to JavaScript, this will allow you to easily add, modify, or delete random quotes or "testimonials" once you place it in your template. And, perhaps explain some of the things I wish I had understood when I started fooling around with JavaScript.

People who use Blogger will find that they only need to place this in their Blog Template one time.

Not Everybody Uses Blogger

People with other blogging services, or who host their own, will either need to place this in several places (bad idea) or put them in a single file so that changes propogate across the entire site quickly and easily (good idea).

If you have the ability to place files on your server, then take all the JavaScript above that's to go into the <HEAD> section and put all those pieces in one file. Remember to leave off the:
<script type="text/javascript">
and the
parts when you copy it to your new file. Save the file as, oh, say "testimonials.js" and save it in your blog's root directory.

Next, in each template, place
<script src="/testimonials.js" type="text/javascript"></script>
which will read the file. Then, when you need to add, modify, or deleter a quote, you only need to change the "/testimonials.js" file and the changes happen across the board.

And you didn't think this would be simple and easy.


  1. Great idea.

    I'm always impressed by the quality of this blog.

  2. The Mean Sister (who is 5'6")July 24, 2005 at 7:54 PM

    So this is what happens when I stop reading to work on my dissertation? Next time, how about writing in English?? Way too much information for my puny brain!! But I am proud of you for figuring it out!

  3. we have to get together sometime to talk about window treatments and furniture.

    and, i'm not too fond of spiders, myself.

    heh! once again, you have shown me how little i know about computers...but i like to learn!

    keep up the good stuff, funny or nerdy!


Please choose a Profile in "Comment as" or sign your name to Anonymous comments. Comment policy