Top 10 Blogger widgets, scripts and modifications

Blogger has come a long way since its humble beginnings. Quite a few improvements have been introduced –first in draft- since Google took over, but the pressure to innovate has been diluted partially through the rising profile of the Wordpress self-hosted platform, where most serious bloggers reside. Yet lately, Blogger has been giving signs that some improvements may be coming. We are looking at the latest and best tips we could find for this platform:

1. Webkit compatible Readmore

2. Numbering comments (simpler)

3. Tabbed navigation system

4. Add TwitThis (4 ways)

5. Add text2speech

6. Add Zoom Image effect

7. Add Floating “Subscribe" button

8. Related posts widget

9. Yahoo Smileys in Comments

10. Scrolling links with Marquee

The first signs of upcoming changes was a request for suggestion of the product-ideas blog, as reported by amanda (blogbuster-hear). Recent news and improvements suggest that Google wants to crowdsource the requested improvements and rely on outside developers to introduce them via gadgets (gadgets-request-draft, gadgets-howto1, gadgets-howto2, gadgets-howto3). Even if you plan to create gadgets, it’s a good idea to look at existing ones so that you don’t duplicate other people’s work, or perhaps gadgetize existing scripts. The following is different from and in addition to the scripts and hacks previously described.

 

1. Webkit-compatible ReadMore

The most important hack to appear lately is undoubtedly the fixed length ReadMore, which displays on the front page only the first n characters of a post, n being a variable that can be configured. This hack is honoured by browsers based on Webkit: Chrome, Chormium, Safari, iPhone (amanda-readmore, qr-readmore).

The following goes before </head>:

<script src='http://quiterandom.com/js/summary/summary-posts.js' type='text/javascript'/>
<script type='text/javascript'>
var thumbnail_mode = "float" ;
summary_noimg = 250;
summary_img = 250;
img_thumb_height = 120;
img_thumb_width = 120;
</script>

Change the variables above to suit your own taste, as follows:

var thumbnail_mode = "float" ; — With this you can decide if you want the thumbnail to float to the left (float), or just display it unformatted (no-float).
summary_noimg = 250; — Defines how many characters will be displayed in posts with no images/thumbnail.
summary_img = 250; — Defines how many characters will be displayed in posts with images/thumbnail.
img_thumb_height = 120; — Thumbnails’ height in pixels.
img_thumb_width = 120; — Thumbnails’ width in pixels.

The .js file contains the following:

// <!-- JavaScript hosted by JavaScriptHost.com -->
// <!-- File link: http://www.javascripthost.com/s3/bin/bloggersphera-summary-posts-v3.js -->
// <!-- Summary Posts with thumbnails for Blogger/Blogspot version 3.0 (C)2008 by Anhvo -->
// <!-- http://www.vietwebguide.com/ -->
// <!-- See the tutorial (in portuguese) to install on http://bloggersphera.blogspot.com -->

function removeHtmlTag(strx,chop){
    if(strx.indexOf("<")!=-1)
    {
        var s = strx.split("<");
        for(var i=0;i<s.length;i++){
            if(s[i].indexOf(">")!=-1){
                s[i] = s[i].substring(s[i].indexOf(">")+1,s[i].length);
            }
        }
        strx =  s.join("");
    }
    chop = (chop < strx.length-1) ? chop : strx.length-2;
    while(strx.charAt(chop-1)!=' ' && strx.indexOf(' ',chop)!=-1) chop++;
    strx = strx.substring(0,chop-1);
    return strx+'...';
}

function createSummaryAndThumb(pID){
    var div = document.getElementById(pID);
    var imgtag = "";
    var img = div.getElementsByTagName("img");
    var summ = summary_noimg;
    if(img.length>=1) {   
        if(thumbnail_mode == "float") {
            imgtag = '<img src="'+img[0].src+'" class="post-thumbnail" width="'+img_thumb_width+'" height="'+img_thumb_height+'" alt=""/>';
            summ = summary_img;
        } else {
            imgtag = '<img class="aligncenter" style="max-width:'+img_thumb_width+'px; max-height:'+img_thumb_height+'px;" src="'+img[0].src+'" alt=""/>';
            summ = summary_img;
        }
    }
    var summary = imgtag + '<div>' + removeHtmlTag(div.innerHTML,summ) + '</div>';
    div.innerHTML = summary;
}

You may copy it and save it so that you can host it yourself.

Next, you need to search for <data:post.body/> and replace it with

<b:if cond='data:blog.pageType != "item"'>
      <div expr:id='"summary-" + data:post.id'><data:post.body/></div>
      <script type='text/javascript'>createSummaryAndThumb("summary-<data:post.id/>");</script>
      <a class='readmore' expr:href='data:post.url'>Read more »</a>
    </b:if>
    <b:if cond='data:blog.pageType == "item"'><data:post.body/></b:if>

If you would like to apply a particular style to the Read more link, add the following before </b:skin>:

a.readmore {
/* CSS properties go here */
}

This is an excellent hack, but Amanda has also spotted codes in a fresh Minima template that suggest that Google might be implementing a proper, native Read More function, that would prevent the rest of the code in the front page from loading, reducing the loading time:

Amanda's capture

 

2. Numbering comments

In our previous article we showed one hack for numbering comments, but this is simpler. In your template (with widgets expanded), search for the code governing comments and modify it as follows (add what’s blue):

<b:includable id='comments' var='post'>

........

<dl id='comments-block'>

<script type='text/javascript'>var CommentsCounter=0;</script>

<b:loop values='data:post.comments' var='comment'>

<dt style='clear: both;' class='comment-author' expr:id='"comment-" + data:comment.id'>
<a expr:name='"comment-" + data:comment.id'/>
<b:if cond='data:comment.authorUrl'>
<a expr:href='data:comment.authorUrl' rel='nofollow'>
<data:comment.author/>
</a>
<b:else/>
<data:comment.author/>
</b:if>
<data:commentPostedByMsg/>

<span class='numberingcomments' style='float: right; font-size: 20px;'>
<a expr:href='data:comment.url' title='Comment Link'>
<script type='text/javascript'>
CommentsCounter=CommentsCounter+1;
document.write(CommentsCounter)
</script>
</a>
</span>

</dt>

<dd class='comment-body'>
.......
</dd>

</b:loop>
</dl>

Further styling can be achieved in the skin section with

.numberingcomments {
/* add the CSS properties here */
}

 

3. Tabbed navigation system

This makes use of the domtab.js script, which can be called as:

<script src='http://quiterandom.com/js/domtab/domtab.js' type='text/javascript'> </script>

or

<script src='http://bloggerbuster.com/scripts/domtab/domtab.js type='text/javascript'> </script>

alternatively, you can copy its contents into a new file:

/*
    DOMtab Version 3.1415927
    Updated March the First 2006
    written by Christian Heilmann
    check blog for updates: http://www.wait-till-i.com
    free to use, not free to resell
*/

domtab={
    tabClass:'domtab', // class to trigger tabbing
    listClass:'domtabs', // class of the menus
    activeClass:'active', // class of current link
    contentElements:'div', // elements to loop through
    backToLinks:/#top/, // pattern to check "back to top" links
    printID:'domtabprintview', // id of the print all link
    showAllLinkText:'show all content', // text for the print all link
    prevNextIndicator:'doprevnext', // class to trigger prev and next links
    prevNextClass:'prevnext', // class of the prev and next list
    prevLabel:'previous', // HTML content of the prev link
    nextLabel:'next', // HTML content of the next link
    prevClass:'prev', // class for the prev link
    nextClass:'next', // class for the next link
    init:function(){
        var temp;
        if(!document.getElementById || !document.createTextNode){return;}
        var tempelm=document.getElementsByTagName('div');       
        for(var i=0;i<tempelm.length;i++){
            if(!domtab.cssjs('check',tempelm[i],domtab.tabClass)){continue;}
            domtab.initTabMenu(tempelm[i]);
            domtab.removeBackLinks(tempelm[i]);
            if(domtab.cssjs('check',tempelm[i],domtab.prevNextIndicator)){
                domtab.addPrevNext(tempelm[i]);
            }
            domtab.checkURL();
        }
        if(document.getElementById(domtab.printID)
           && !document.getElementById(domtab.printID).getElementsByTagName('a')[0]){
            var newlink=document.createElement('a');
            newlink.setAttribute('href','#');
            domtab.addEvent(newlink,'click',domtab.showAll,false);
            newlink.onclick=function(){return false;} // safari hack
            newlink.appendChild(document.createTextNode(domtab.showAllLinkText));
            document.getElementById(domtab.printID).appendChild(newlink);
        }
    },
    checkURL:function(){
        var id;
        var loc=window.location.toString();
        loc=/#/.test(loc)?loc.match(/#(\w.+)/)[1]:'';
        if(loc==''){return;}
        var elm=document.getElementById(loc);
        if(!elm){return;}
        var parentMenu=elm.parentNode.parentNode.parentNode;
        parentMenu.currentSection=loc;
        parentMenu.getElementsByTagName(domtab.contentElements)[0].style.display='none';
        domtab.cssjs('remove',parentMenu.getElementsByTagName('a')[0].parentNode,domtab.activeClass);
        var links=parentMenu.getElementsByTagName('a');
        for(i=0;i<links.length;i++){
            if(!links[i].getAttribute('href')){continue;}
            if(!/#/.test(links[i].getAttribute('href').toString())){continue;}
            id=links[i].href.match(/#(\w.+)/)[1];
            if(id==loc){
                var cur=links[i].parentNode.parentNode;
                domtab.cssjs('add',links[i].parentNode,domtab.activeClass);
                break;
            }
        }
        domtab.changeTab(elm,1);
        elm.focus();
        cur.currentLink=links[i];
        cur.currentSection=loc;
    },
    showAll:function(e){
        document.getElementById(domtab.printID).parentNode.removeChild(document.getElementById(domtab.printID));
        var tempelm=document.getElementsByTagName('div');       
        for(var i=0;i<tempelm.length;i++){
            if(!domtab.cssjs('check',tempelm[i],domtab.tabClass)){continue;}
            var sec=tempelm[i].getElementsByTagName(domtab.contentElements);
            for(var j=0;j<sec.length;j++){
                sec[j].style.display='block';
            }
        }
        var tempelm=document.getElementsByTagName('ul');       
        for(i=0;i<tempelm.length;i++){
            if(!domtab.cssjs('check',tempelm[i],domtab.prevNextClass)){continue;}
            tempelm[i].parentNode.removeChild(tempelm[i]);
            i--;
        }
        domtab.cancelClick(e);
    },
    addPrevNext:function(menu){
        var temp;
        var sections=menu.getElementsByTagName(domtab.contentElements);
        for(var i=0;i<sections.length;i++){
            temp=domtab.createPrevNext();
            if(i==0){
                temp.removeChild(temp.getElementsByTagName('li')[0]);
            }
            if(i==sections.length-1){
                temp.removeChild(temp.getElementsByTagName('li')[1]);
            }
            temp.i=i; // h4xx0r!
            temp.menu=menu;
            sections[i].appendChild(temp);
        }
    },
    removeBackLinks:function(menu){
        var links=menu.getElementsByTagName('a');
        for(var i=0;i<links.length;i++){
            if(!domtab.backToLinks.test(links[i].href)){continue;}
            links[i].parentNode.removeChild(links[i]);
            i--;
        }
    },
    initTabMenu:function(menu){
        var id;
        var lists=menu.getElementsByTagName('ul');
        for(var i=0;i<lists.length;i++){
            if(domtab.cssjs('check',lists[i],domtab.listClass)){
                var thismenu=lists[i];
                break;
            }
        }
        if(!thismenu){return;}
        thismenu.currentSection='';
        thismenu.currentLink='';
        var links=thismenu.getElementsByTagName('a');
        for(i=0;i<links.length;i++){
            if(!/#/.test(links[i].getAttribute('href').toString())){continue;}
            id=links[i].href.match(/#(\w.+)/)[1];
            if(document.getElementById(id)){
                domtab.addEvent(links[i],'click',domtab.showTab,false);
                links[i].onclick=function(){return false;} // safari hack
                domtab.changeTab(document.getElementById(id),0);
            }
        }
        id=links[0].href.match(/#(\w.+)/)[1];
        if(document.getElementById(id)){
            domtab.changeTab(document.getElementById(id),1);
            thismenu.currentSection=id;
            thismenu.currentLink=links[0];
            domtab.cssjs('add',links[0].parentNode,domtab.activeClass);
        }
    },
    createPrevNext:function(){
        // this would be so much easier with innerHTML, darn you standards fetish!
        var temp=document.createElement('ul');
        temp.className=domtab.prevNextClass;
        temp.appendChild(document.createElement('li'));
        temp.getElementsByTagName('li')[0].appendChild(document.createElement('a'));
        temp.getElementsByTagName('a')[0].setAttribute('href','#');
        temp.getElementsByTagName('a')[0].innerHTML=domtab.prevLabel;
        temp.getElementsByTagName('li')[0].className=domtab.prevClass;
        temp.appendChild(document.createElement('li'));
        temp.getElementsByTagName('li')[1].appendChild(document.createElement('a'));
        temp.getElementsByTagName('a')[1].setAttribute('href','#');
        temp.getElementsByTagName('a')[1].innerHTML=domtab.nextLabel;
        temp.getElementsByTagName('li')[1].className=domtab.nextClass;
        domtab.addEvent(temp.getElementsByTagName('a')[0],'click',domtab.navTabs,false);
        domtab.addEvent(temp.getElementsByTagName('a')[1],'click',domtab.navTabs,false);
        // safari fix
        temp.getElementsByTagName('a')[0].onclick=function(){return false;}
        temp.getElementsByTagName('a')[1].onclick=function(){return false;}
        return temp;
    },
    navTabs:function(e){
        var li=domtab.getTarget(e);
        var menu=li.parentNode.parentNode.menu;
        var count=li.parentNode.parentNode.i;
        var section=menu.getElementsByTagName(domtab.contentElements);
        var links=menu.getElementsByTagName('a');
        var othercount=(li.parentNode.className==domtab.prevClass)?count-1:count+1;
        section[count].style.display='none';
        domtab.cssjs('remove',links[count].parentNode,domtab.activeClass);
        section[othercount].style.display='block';
        domtab.cssjs('add',links[othercount].parentNode,domtab.activeClass);
        var parent=links[count].parentNode.parentNode;
        parent.currentLink=links[othercount];
        parent.currentSection=links[othercount].href.match(/#(\w.+)/)[1];
        domtab.cancelClick(e);
    },
    changeTab:function(elm,state){
        do{
            elm=elm.parentNode;
        } while(elm.nodeName.toLowerCase()!=domtab.contentElements)
        elm.style.display=state==0?'none':'block';
    },
    showTab:function(e){
        var o=domtab.getTarget(e);
        if(o.parentNode.parentNode.currentSection!=''){
            domtab.changeTab(document.getElementById(o.parentNode.parentNode.currentSection),0);
            domtab.cssjs('remove',o.parentNode.parentNode.currentLink.parentNode,domtab.activeClass);
        }
        var id=o.href.match(/#(\w.+)/)[1];
        o.parentNode.parentNode.currentSection=id;
        o.parentNode.parentNode.currentLink=o;
        domtab.cssjs('add',o.parentNode,domtab.activeClass);
        domtab.changeTab(document.getElementById(id),1);
        document.getElementById(id).focus();
        domtab.cancelClick(e);
    },
/* helper methods */
    getTarget:function(e){
        var target = window.event ? window.event.srcElement : e ? e.target : null;
        if (!target){return false;}
        if (target.nodeName.toLowerCase() != 'a'){target = target.parentNode;}
        return target;
    },
    cancelClick:function(e){
        if (window.event){
            window.event.cancelBubble = true;
            window.event.returnValue = false;
            return;
        }
        if (e){
            e.stopPropagation();
            e.preventDefault();
        }
    },
    addEvent: function(elm, evType, fn, useCapture){
        if (elm.addEventListener)
        {
            elm.addEventListener(evType, fn, useCapture);
            return true;
        } else if (elm.attachEvent) {
            var r = elm.attachEvent('on' + evType, fn);
            return r;
        } else {
            elm['on' + evType] = fn;
        }
    },
    cssjs:function(a,o,c1,c2){
        switch (a){
            case 'swap':
                o.className=!domtab.cssjs('check',o,c1)?o.className.replace(c2,c1):o.className.replace(c1,c2);
            break;
            case 'add':
                if(!domtab.cssjs('check',o,c1)){o.className+=o.className?' '+c1:c1;}
            break;
            case 'remove':
                var rep=o.className.match(' '+c1)?' '+c1:c1;
                o.className=o.className.replace(rep,'');
            break;
            case 'check':
                var found=false;
                var temparray=o.className.split(' ');
                for(var i=0;i<temparray.length;i++){
                    if(temparray[i]==c1){found=true;}
                }
                return found;
            break;
        }
    }
}
domtab.addEvent(window, 'load', domtab.init, false);

The following goes before ]]</b:skin>:

/*main container*/
div.domtab {margin: 0; padding: 0;}

/*tabs*/
ul.domtabs {float: left; margin: 0; padding: 0;}

ul.domtabs li {
background: #999;
float: left;
margin: 0 2px 0 0;
padding: 2px 3px;
text-align: center;
}

ul.domtabs li:hover, ul.domtabs li.active {background: #CCC;}
  ul.domtabs li a {color: #333; font-weight: bold; text-decoration: none;}

/*tabs containers*/
div.domtab div.tab-container {
border: 3px solid #ccc;
clear: both;
display: block;
padding: 10px;
}

The tabs can be called using the following code:

<div class='domtab'>

<ul class='domtabs'>
  <li><a href='#tab1'>TAB 1</a></li>
  <li><a href='#tab2'>TAB 2</a></li>
  <li><a href='#tab3'>TAB 3</a></li>
</ul>

<div class='tab-container'>
  <a id='tab1' name='tab1'></a>
Content for TAB 1.
</div>

<div class='tab-container'>
  <a id='tab2' name='tab2'></a>
Content for TAB 2.
</div>

<div class='tab-container'>
  <a id='tab3' name='tab4'></a>
Content for TAB 3.
</div>

</div>

..following these constraints:

1. The main container (<div>) should have the class domtab.
2. The list (<ul>) with the tabs should have the class domtabs, and each link (<a>) in the list should point to the ID of each tab container.
3. Each container should have the class tab-container and an identifier (anchor) inside of it, with a unique name and ID.

Also, the colours should be:

#CCC (light grey) — Used as background when the tabs are hovered and/or active, and as the border color for the containers.
#999 (dark grey)  — Used as the default tab background color.
#333 (black)        — Used as the default tab text color.

For example, to set Recent Posts, Labels and Archive Widget, paste right before

<b:section class='sidebar' id='sidebar' preferred='yes'>

this code:

<div class='domtab'>

<ul class='domtabs'>
  <li><a href='#recent'>Recent</a></li>
  <li><a href='#cat'>Categories</a></li>
  <li><a href='#arc'>Archives</a></li>
</ul>

<div class='tab-container'>
  <a id='recent' name='recent'></a>
  <b:section class='sidebar-tab' id='sidebar-tabs-1' preferred='yes'>
    <b:widget id='Feed99' locked='false' title='' type='Feed'/>
  </b:section>
</div>

<div class='tab-container'>
  <a id='cat' name='cat'></a>
  <b:section class='sidebar-tab' id='sidebar-tabs-2' preferred='yes'>
    <b:widget id='Label99' locked='false' title='' type='Label'/>
  </b:section>
</div>

<div class='tab-container'>
  <a id='arc' name='arc'></a>
  <b:section class='sidebar-tab' id='sidebar-tabs-3' preferred='yes'>
    <b:widget id='BlogArchive99' locked='false' title='' type='BlogArchive'/>
  </b:section>
</div>

</div>

Once you edit the Feed with your feed URL, it should be working.

 

4. Add “Twit This” to your articles

There are essentially 4-5 ways to add this functionality.

A good place to add any of the following is right after the post-footer-line-1 or even after the <p><data:post.body/></p> line.

Firstly, you can add a general “Add This” code which will include Twitter, among others. Such scriptlets can be found at addthis.com, sharethis.com, addtoany.com with instructions to implement on several platforms. A second possibility is to implement it via Site FeedFlare, if you are using Feedburner (instructions on Feedburner site).

Thirdly, you can use tweetmeme:

<script type='text/javascript'>
tweetmeme_style = &#39;compact&#39;;
tweetmeme_url = &#39;<data:post.url/>&#39;;
tweetmeme_source = &#39;inbonobo&#39;;
</script>
<script src='http://tweetmeme.com/i/scripts/button.js' type='text/javascript'/>

The above will add the green tweetmeme icon which also shows how many times your URL has be RT’d. To have the full square, remove the “compact” line. Replace inbonobo with your own twitter name, or, if you want @tweetmeme to appear instead, remove the line altogether.

A fourth option uses only the bit.ly API instead:

<b:if cond='data:blog.pageType == "item"'><span style='float: left; background: url(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLYtVmZKCi23DBrF1jg430gpnfIJM9k5wLTZWfGBxbEVf91mIoS0FKn_vJkIpKxg9G27ZoBrwFjHMZY0Yuy1xfZJnJLhvXLooyUTWQlQQUSbC4_TSQxLFWMRk-OYhccZ5ixhe3_f473MfZ/s128/twitter-16x16.png) left no-repeat; padding-left: 20px;'><script charset='utf-8' src='http://bit.ly/javascript-api.js?version=latest&amp;login=tweettrackjs&amp;apiKey=R_7e9987b2fd13d7e4e881f9cbb168f523' type='text/javascript'/>
<script charset='utf-8' src='http://s.bit.ly/TweetAndTrack.js?v=1.01' type='text/javascript'/>
<a expr:onclick='"return TweetAndTrack.open(this, \"" + data:post.url + "\");"' href='#'>
<span style='display:none;'>I'm reading: <data:post.title/></span>Tweet this!</a></span></b:if>

Amanda posted this on March 19 (bb-twit-this), while labnol posted it March 17 (ln-twit-this).

 

5. Add text to speech functionality to your articles

When your eyes get tired or you’re busy doing something else, wouldn’t it be nice if the computer could read the browser page to you? Some browsers, such as Opera, come with such functionality included, but few people use it. To have it, add the following code in the same place as in the previous script:

using a text only link using image + text
<script src='http://vozme.com/get_text.js' type='text/javascript'/><a expr:onclick='"get_blogger(\"" + data:post.id + "\",\"en\",\"ml\");"' href='javascript:void(0);' style='margin-left:1.5em;'>((&#8226;)) Hear this post</a>

<div id='voice'>
<script src='http://vozme.com/get_text.js' type='text/javascript'/> <a expr:onclick='"get_blogger(\"" + data:post.id + "\",\"en\",\"ml\");"' href='javascript:void(0);'><img src='http://vozme.com/img/paper_sound32x32.gif' align='left' alt='' border='0' style='margin-right:0.4em;'/></a>
<a expr:onclick='"get_blogger(\"" + data:post.id + "\",\"en\",\"ml\");"' href='javascript:void(0);' style='font-size:10px;'>Hear<br/>this post</a>
</div>

 

6. Add zoom image effect

To add this Zoom Effect, you need to include the following two scripts in the <head> section:

<script src='http://wam8387.110mb.com/FancyZoom.js' type='text/javascript'/>
<script src='http://wam8387.110mb.com/FancyZoomHTML.js' type='text/javascript'/>

They are as follows:

FancyZoom.js FancyZoomHTML.js

// FancyZoom.js - v1.1 - http://www.fancyzoom.com
//
// Copyright (c) 2008 Cabel Sasser / Panic Inc
// All rights reserved.
//
//     Requires: FancyZoomHTML.js
// Instructions: Include JS files in page, call setupZoom() in onLoad. That's it!
//               Any <a href> links to images will be updated to zoom inline.
//               Add rel="nozoom" to your <a href> to disable zooming for an image.
//
// Redistribution and use of this effect in source form, with or without modification,
// are permitted provided that the following conditions are met:
//
// * USE OF SOURCE ON COMMERCIAL (FOR-PROFIT) WEBSITE REQUIRES ONE-TIME LICENSE FEE PER DOMAIN.
//   Reasonably priced! Visit www.fancyzoom.com for licensing instructions. Thanks!
//
// * Non-commercial (personal) website use is permitted without license/payment!
//
// * Redistribution of source code must retain the above copyright notice,
//   this list of conditions and the following disclaimer.
//
// * Redistribution of source code and derived works cannot be sold without specific
//   written prior permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

var includeCaption = true; // Turn on the "caption" feature, and write out the caption HTML
var zoomTime       = 5;    // Milliseconds between frames of zoom animation
var zoomSteps      = 15;   // Number of zoom animation frames
var includeFade    = 1;    // Set to 1 to fade the image in / out as it zooms
var minBorder      = 90;   // Amount of padding between large, scaled down images, and the window edges
var shadowSettings = '0px 5px 25px rgba(0, 0, 0, '; // Blur, radius, color of shadow for compatible browsers

var zoomImagesURI   = '/images-global/zoom/'; // Location of the zoom and shadow images

// Init. Do not add anything below this line, unless it's something awesome.

var myWidth = 0, myHeight = 0, myScroll = 0; myScrollWidth = 0; myScrollHeight = 0;
var zoomOpen = false, preloadFrame = 1, preloadActive = false, preloadTime = 0, imgPreload = new Image();
var preloadAnimTimer = 0;

var zoomActive = new Array(); var zoomTimer  = new Array();
var zoomOrigW  = new Array(); var zoomOrigH  = new Array();
var zoomOrigX  = new Array(); var zoomOrigY  = new Array();

var zoomID         = "ZoomBox";
var theID          = "ZoomImage";
var zoomCaption    = "ZoomCaption";
var zoomCaptionDiv = "ZoomCapDiv";

if (navigator.userAgent.indexOf("MSIE") != -1) {
    var browserIsIE = true;
}

// Zoom: Setup The Page! Called in your <body>'s onLoad handler.

function setupZoom() {
    prepZooms();
    insertZoomHTML();
    zoomdiv = document.getElementById(zoomID); 
    zoomimg = document.getElementById(theID);
}

// Zoom: Inject Javascript functions into hrefs pointing to images, one by one!
// Skip any href that contains a rel="nozoom" tag.
// This is done at page load time via an onLoad() handler.

function prepZooms() {
    if (! document.getElementsByTagName) {
        return;
    }
    var links = document.getElementsByTagName("a");
    for (i = 0; i < links.length; i++) {
        if (links[i].getAttribute("href")) {
            if (links[i].getAttribute("href").search(/(.*)\.(jpg|jpeg|gif|png|bmp|tif|tiff)/gi) != -1) {
                if (links[i].getAttribute("rel") != "nozoom") {
                    links[i].onclick = function (event) { return zoomClick(this, event); };
                    links[i].onmouseover = function () { zoomPreload(this); };
                }
            }
        }
    }
}

// Zoom: Load an image into an image object. When done loading, function sets preloadActive to false,
// so other bits know that they can proceed with the zoom.
// Preloaded image is stored in imgPreload and swapped out in the zoom function.

function zoomPreload(from) {

    var theimage = from.getAttribute("href");

    // Only preload if we have to, i.e. the image isn't this image already

    if (imgPreload.src.indexOf(from.getAttribute("href").substr(from.getAttribute("href").lastIndexOf("/"))) == -1) {
        preloadActive = true;
        imgPreload = new Image();

        // Set a function to fire when the preload is complete, setting flags along the way.

        imgPreload.onload = function() {
            preloadActive = false;
        }

        // Load it!
        imgPreload.src = theimage;
    }
}

// Zoom: Start the preloading animation cycle.

function preloadAnimStart() {
    preloadTime = new Date();
    document.getElementById("ZoomSpin").style.left = (myWidth / 2) + 'px';
    document.getElementById("ZoomSpin").style.top = ((myHeight / 2) + myScroll) + 'px';
    document.getElementById("ZoomSpin").style.visibility = "visible";   
    preloadFrame = 1;
    document.getElementById("SpinImage").src = zoomImagesURI+'zoom-spin-'+preloadFrame+'.png'; 
    preloadAnimTimer = setInterval("preloadAnim()", 100);
}

// Zoom: Display and ANIMATE the jibber-jabber widget. Once preloadActive is false, bail and zoom it up!

function preloadAnim(from) {
    if (preloadActive != false) {
        document.getElementById("SpinImage").src = zoomImagesURI+'zoom-spin-'+preloadFrame+'.png';
        preloadFrame++;
        if (preloadFrame > 12) preloadFrame = 1;
    } else {
        document.getElementById("ZoomSpin").style.visibility = "hidden";   
        clearInterval(preloadAnimTimer);
        preloadAnimTimer = 0;
        zoomIn(preloadFrom);
    }
}

// ZOOM CLICK: We got a click! Should we do the zoom? Or wait for the preload to complete?
// todo?: Double check that imgPreload src = clicked src

function zoomClick(from, evt) {

    var shift = getShift(evt);

    // Check for Command / Alt key. If pressed, pass them through -- don't zoom!
    if (! evt && window.event && (window.event.metaKey || window.event.altKey)) {
        return true;
    } else if (evt && (evt.metaKey|| evt.altKey)) {
        return true;
    }

    // Get browser dimensions
    getSize();

    // If preloading still, wait, and display the spinner.
    if (preloadActive == true) {
        // But only display the spinner if it's not already being displayed!
        if (preloadAnimTimer == 0) {
            preloadFrom = from;
            preloadAnimStart();   
        }
    } else {
        // Otherwise, we're loaded: do the zoom!
        zoomIn(from, shift);
    }
    return false;
}

// Zoom: Move an element in to endH endW, using zoomHost as a starting point.
// "from" is an object reference to the href that spawned the zoom.

function zoomIn(from, shift) {

    zoomimg.src = from.getAttribute("href");

    // Determine the zoom settings from where we came from, the element in the <a>.
    // If there's no element in the <a>, or we can't get the width, make stuff up

    if (from.childNodes[0].width) {
        startW = from.childNodes[0].width;
        startH = from.childNodes[0].height;
        startPos = findElementPos(from.childNodes[0]);
    } else {
        startW = 50;
        startH = 12;
        startPos = findElementPos(from);
    }

    hostX = startPos[0];
    hostY = startPos[1];

    // Make up for a scrolled containing div.
    // TODO: This HAS to move into findElementPos.
    if (document.getElementById('scroller')) {
        hostX = hostX - document.getElementById('scroller').scrollLeft;
    }

    // Determine the target zoom settings from the preloaded image object

    endW = imgPreload.width;
    endH = imgPreload.height;

    // Start! But only if we're not zooming already!

    if (zoomActive[theID] != true) {

        // Clear everything out just in case something is already open

        if (document.getElementById("ShadowBox")) {
            document.getElementById("ShadowBox").style.visibility = "hidden";
        } else if (! browserIsIE) {
            // Wipe timer if shadow is fading in still
            if (fadeActive["ZoomImage"]) {
                clearInterval(fadeTimer["ZoomImage"]);
                fadeActive["ZoomImage"] = false;
                fadeTimer["ZoomImage"] = false;           
            }
            document.getElementById("ZoomImage").style.webkitBoxShadow = shadowSettings + '0.0)';           
        }
        document.getElementById("ZoomClose").style.visibility = "hidden";    

        // Setup the CAPTION, if existing. Hide it first, set the text.

        if (includeCaption) {
            document.getElementById(zoomCaptionDiv).style.visibility = "hidden";
            if (from.getAttribute('title') && includeCaption) {
                // Yes, there's a caption, set it up
                document.getElementById(zoomCaption).innerHTML = from.getAttribute('title');
            } else {
                document.getElementById(zoomCaption).innerHTML = "";
            }
        }

        // Store original position in an array for future zoomOut.

        zoomOrigW[theID] = startW;
        zoomOrigH[theID] = startH;
        zoomOrigX[theID] = hostX;
        zoomOrigY[theID] = hostY;

        // Now set the starting dimensions

        zoomimg.style.width = startW + 'px';
        zoomimg.style.height = startH + 'px';
        zoomdiv.style.left = hostX + 'px';
        zoomdiv.style.top = hostY + 'px';

        // Show the zooming image container, make it invisible

        if (includeFade == 1) {
            setOpacity(0, zoomID);
        }
        zoomdiv.style.visibility = "visible";

        // If it's too big to fit in the window, shrink the width and height to fit (with ratio).

        sizeRatio = endW / endH;
        if (endW > myWidth - minBorder) {
            endW = myWidth - minBorder;
            endH = endW / sizeRatio;
        }
        if (endH > myHeight - minBorder) {
            endH = myHeight - minBorder;
            endW = endH * sizeRatio;
        }

        zoomChangeX = ((myWidth / 2) - (endW / 2) - hostX);
        zoomChangeY = (((myHeight / 2) - (endH / 2) - hostY) + myScroll);
        zoomChangeW = (endW - startW);
        zoomChangeH = (endH - startH);
        // Shift key?
        if (shift) {
            tempSteps = zoomSteps * 7;
        } else {
            tempSteps = zoomSteps;
        }

        // Setup Zoom

        zoomCurrent = 0;

        // Setup Fade with Zoom, If Requested

        if (includeFade == 1) {
            fadeCurrent = 0;
            fadeAmount = (0 - 100) / tempSteps;
        } else {
            fadeAmount = 0;
        }

        // Do It!
        zoomTimer[theID] = setInterval("zoomElement('"+zoomID+"', '"+theID+"', "+zoomCurrent+", "+startW+", "+zoomChangeW+", "+startH+", "+zoomChangeH+", "+hostX+", "+zoomChangeX+", "+hostY+", "+zoomChangeY+", "+tempSteps+", "+includeFade+", "+fadeAmount+", 'zoomDoneIn(zoomID)')", zoomTime);       
        zoomActive[theID] = true;
    }
}

// Zoom it back out.

function zoomOut(from, evt) {

    // Get shift key status.
    // IE events don't seem to get passed through the function, so grab it from the window.

    if (getShift(evt)) {
        tempSteps = zoomSteps * 7;
    } else {
        tempSteps = zoomSteps;
    }   

    // Check to see if something is happening/open
    if (zoomActive[theID] != true) {

        // First, get rid of the shadow if necessary.

        if (document.getElementById("ShadowBox")) {
            document.getElementById("ShadowBox").style.visibility = "hidden";
        } else if (! browserIsIE) {
            // Wipe timer if shadow is fading in still
            if (fadeActive["ZoomImage"]) {
                clearInterval(fadeTimer["ZoomImage"]);
                fadeActive["ZoomImage"] = false;
                fadeTimer["ZoomImage"] = false;           
            }
            document.getElementById("ZoomImage").style.webkitBoxShadow = shadowSettings + '0.0)';           
        }

        // ..and the close box...

        document.getElementById("ZoomClose").style.visibility = "hidden";

        // ...and the caption if necessary!

        if (includeCaption && document.getElementById(zoomCaption).innerHTML != "") {
            // fadeElementSetup(zoomCaptionDiv, 100, 0, 5, 1);
            document.getElementById(zoomCaptionDiv).style.visibility = "hidden";
        }

        // Now, figure out where we came from, to get back there

        startX = parseInt(zoomdiv.style.left);
        startY = parseInt(zoomdiv.style.top);
        startW = zoomimg.width;
        startH = zoomimg.height;
        zoomChangeX = zoomOrigX[theID] - startX;
        zoomChangeY = zoomOrigY[theID] - startY;
        zoomChangeW = zoomOrigW[theID] - startW;
        zoomChangeH = zoomOrigH[theID] - startH;

        // Setup Zoom

        zoomCurrent = 0;

        // Setup Fade with Zoom, If Requested

        if (includeFade == 1) {
            fadeCurrent = 0;
            fadeAmount = (100 - 0) / tempSteps;
        } else {
            fadeAmount = 0;
        }

        // Do It!

        zoomTimer[theID] = setInterval("zoomElement('"+zoomID+"', '"+theID+"', "+zoomCurrent+", "+startW+", "+zoomChangeW+", "+startH+", "+zoomChangeH+", "+startX+", "+zoomChangeX+", "+startY+", "+zoomChangeY+", "+tempSteps+", "+includeFade+", "+fadeAmount+", 'zoomDone(zoomID, theID)')", zoomTime);   
        zoomActive[theID] = true;
    }
}

// Finished Zooming In

function zoomDoneIn(zoomdiv, theID) {

    // Note that it's open
    zoomOpen = true;
    zoomdiv = document.getElementById(zoomdiv);

    // Position the table shadow behind the zoomed in image, and display it

    if (document.getElementById("ShadowBox")) {

        setOpacity(0, "ShadowBox");
        shadowdiv = document.getElementById("ShadowBox");

        shadowLeft = parseInt(zoomdiv.style.left) - 13;
        shadowTop = parseInt(zoomdiv.style.top) - 8;
        shadowWidth = zoomdiv.offsetWidth + 26;
        shadowHeight = zoomdiv.offsetHeight + 26;
        shadowdiv.style.width = shadowWidth + 'px';
        shadowdiv.style.height = shadowHeight + 'px';
        shadowdiv.style.left = shadowLeft + 'px';
        shadowdiv.style.top = shadowTop + 'px';

        document.getElementById("ShadowBox").style.visibility = "visible";
        fadeElementSetup("ShadowBox", 0, 100, 5);
    } else if (! browserIsIE) {
        // Or, do a fade of the modern shadow
        fadeElementSetup("ZoomImage", 0, .8, 5, 0, "shadow");
    }
    // Position and display the CAPTION, if existing
    if (includeCaption && document.getElementById(zoomCaption).innerHTML != "") {
        // setOpacity(0, zoomCaptionDiv);
        zoomcapd = document.getElementById(zoomCaptionDiv);
        zoomcapd.style.top = parseInt(zoomdiv.style.top) + (zoomdiv.offsetHeight + 15) + 'px';
        zoomcapd.style.left = (myWidth / 2) - (zoomcapd.offsetWidth / 2) + 'px';
        zoomcapd.style.visibility = "visible";
        // fadeElementSetup(zoomCaptionDiv, 0, 100, 5);
    }  
    // Display Close Box (fade it if it's not IE)

    if (!browserIsIE) setOpacity(0, "ZoomClose");
    document.getElementById("ZoomClose").style.visibility = "visible";
    if (!browserIsIE) fadeElementSetup("ZoomClose", 0, 100, 5);

    // Get keypresses
    document.onkeypress = getKey;
}

// Finished Zooming Out

function zoomDone(zoomdiv, theID) {

    // No longer open
    zoomOpen = false;

    // Clear stuff out, clean up

    zoomOrigH[theID] = "";
    zoomOrigW[theID] = "";
    document.getElementById(zoomdiv).style.visibility = "hidden";
    zoomActive[theID] == false;

    // Stop getting keypresses

    document.onkeypress = null;

}

// Actually zoom the element

function zoomElement(zoomdiv, theID, zoomCurrent, zoomStartW, zoomChangeW, zoomStartH, zoomChangeH, zoomStartX, zoomChangeX, zoomStartY, zoomChangeY, zoomSteps, includeFade, fadeAmount, execWhenDone) {

    // console.log("Zooming Step #"+zoomCurrent+ " of "+zoomSteps+" (zoom " + zoomStartW + "/" + zoomChangeW + ") (zoom " + zoomStartH + "/" + zoomChangeH + ")  (zoom " + zoomStartX + "/" + zoomChangeX + ")  (zoom " + zoomStartY + "/" + zoomChangeY + ") Fade: "+fadeAmount);
    // Test if we're done, or if we continue

    if (zoomCurrent == (zoomSteps + 1)) {
        zoomActive[theID] = false;
        clearInterval(zoomTimer[theID]);

        if (execWhenDone != "") {
            eval(execWhenDone);
        }
    } else {
        // Do the Fade!
        if (includeFade == 1) {
            if (fadeAmount < 0) {
                setOpacity(Math.abs(zoomCurrent * fadeAmount), zoomdiv);
            } else {
                setOpacity(100 - (zoomCurrent * fadeAmount), zoomdiv);
            }
        }
        // Calculate this step's difference, and move it!
        moveW = cubicInOut(zoomCurrent, zoomStartW, zoomChangeW, zoomSteps);
        moveH = cubicInOut(zoomCurrent, zoomStartH, zoomChangeH, zoomSteps);
        moveX = cubicInOut(zoomCurrent, zoomStartX, zoomChangeX, zoomSteps);
        moveY = cubicInOut(zoomCurrent, zoomStartY, zoomChangeY, zoomSteps);
        document.getElementById(zoomdiv).style.left = moveX + 'px';
        document.getElementById(zoomdiv).style.top = moveY + 'px';
        zoomimg.style.width = moveW + 'px';
        zoomimg.style.height = moveH + 'px';
        zoomCurrent++;
        clearInterval(zoomTimer[theID]);
        zoomTimer[theID] = setInterval("zoomElement('"+zoomdiv+"', '"+theID+"', "+zoomCurrent+", "+zoomStartW+", "+zoomChangeW+", "+zoomStartH+", "+zoomChangeH+", "+zoomStartX+", "+zoomChangeX+", "+zoomStartY+", "+zoomChangeY+", "+zoomSteps+", "+includeFade+", "+fadeAmount+", '"+execWhenDone+"')", zoomTime);
    }
}

// Zoom Utility: Get Key Press when image is open, and act accordingly

function getKey(evt) {
    if (! evt) {
        theKey = event.keyCode;
    } else {
        theKey = evt.keyCode;
    }

    if (theKey == 27) { // ESC
        zoomOut(this, evt);
    }
}

////////////////////////////
//
// FADE Functions
//

function fadeOut(elem) {
    if (elem.id) {
        fadeElementSetup(elem.id, 100, 0, 10);
    }
}

function fadeIn(elem) {
    if (elem.id) {
        fadeElementSetup(elem.id, 0, 100, 10);   
    }
}

// Fade: Initialize the fade function

var fadeActive = new Array();
var fadeQueue  = new Array();
var fadeTimer  = new Array();
var fadeClose  = new Array();
var fadeMode   = new Array();

function fadeElementSetup(theID, fdStart, fdEnd, fdSteps, fdClose, fdMode) {

    // alert("Fading: "+theID+" Steps: "+fdSteps+" Mode: "+fdMode);

    if (fadeActive[theID] == true) {
        // Already animating, queue up this command
        fadeQueue[theID] = new Array(theID, fdStart, fdEnd, fdSteps);
    } else {
        fadeSteps = fdSteps;
        fadeCurrent = 0;
        fadeAmount = (fdStart - fdEnd) / fadeSteps;
        fadeTimer[theID] = setInterval("fadeElement('"+theID+"', '"+fadeCurrent+"', '"+fadeAmount+"', '"+fadeSteps+"')", 15);
        fadeActive[theID] = true;
        fadeMode[theID] = fdMode;
        if (fdClose == 1) {
            fadeClose[theID] = true;
        } else {
            fadeClose[theID] = false;
        }
    }
}

// Fade: Do the fade. This function will call itself, modifying the parameters, so
// many instances can run concurrently. Can fade using opacity, or fade using a box-shadow.

function fadeElement(theID, fadeCurrent, fadeAmount, fadeSteps) {

    if (fadeCurrent == fadeSteps) {

        // We're done, so clear.

        clearInterval(fadeTimer[theID]);
        fadeActive[theID] = false;
        fadeTimer[theID] = false;

        // Should we close it once the fade is complete?

        if (fadeClose[theID] == true) {
            document.getElementById(theID).style.visibility = "hidden";
        }

        // Hang on.. did a command queue while we were working? If so, make it happen now

        if (fadeQueue[theID] && fadeQueue[theID] != false) {
            fadeElementSetup(fadeQueue[theID][0], fadeQueue[theID][1], fadeQueue[theID][2], fadeQueue[theID][3]);
            fadeQueue[theID] = false;
        }
    } else {

        fadeCurrent++;
        // Now actually do the fade adjustment.
        if (fadeMode[theID] == "shadow") {

            // Do a special fade on the webkit-box-shadow of the object
            if (fadeAmount < 0) {
                document.getElementById(theID).style.webkitBoxShadow = shadowSettings + (Math.abs(fadeCurrent * fadeAmount)) + ')';
            } else {
                document.getElementById(theID).style.webkitBoxShadow = shadowSettings + (100 - (fadeCurrent * fadeAmount)) + ')';
            }
        } else {
            // Set the opacity depending on if we're adding or subtracting (pos or neg)
            if (fadeAmount < 0) {
                setOpacity(Math.abs(fadeCurrent * fadeAmount), theID);
            } else {
                setOpacity(100 - (fadeCurrent * fadeAmount), theID);
            }
        }

        // Keep going, and send myself the updated variables
        clearInterval(fadeTimer[theID]);
        fadeTimer[theID] = setInterval("fadeElement('"+theID+"', '"+fadeCurrent+"', '"+fadeAmount+"', '"+fadeSteps+"')", 15);
    }
}

////////////////////////////
//
// UTILITY functions
//

// Utility: Set the opacity, compatible with a number of browsers. Value from 0 to 100.

function setOpacity(opacity, theID) {

    var object = document.getElementById(theID).style;

    // If it's 100, set it to 99 for Firefox.

    if (navigator.userAgent.indexOf("Firefox") != -1) {
        if (opacity == 100) { opacity = 99.9999; } // This is majorly awkward
    }

    // Multi-browser opacity setting

    object.filter = "alpha(opacity=" + opacity + ")"; // IE/Win
    object.opacity = (opacity / 100);                 // Safari 1.2, Firefox+Mozilla

}

// Utility: Math functions for animation calucations - From http://www.robertpenner.com/easing/
//
// t = time, b = begin, c = change, d = duration
// time = current frame, begin is fixed, change is basically finish - begin, duration is fixed (frames),

function linear(t, b, c, d)
{
    return c*t/d + b;
}

function sineInOut(t, b, c, d)
{
    return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
}

function cubicIn(t, b, c, d) {
    return c*(t/=d)*t*t + b;
}

function cubicOut(t, b, c, d) {
    return c*((t=t/d-1)*t*t + 1) + b;
}

function cubicInOut(t, b, c, d)
{
    if ((t/=d/2) < 1) return c/2*t*t*t + b;
    return c/2*((t-=2)*t*t + 2) + b;
}

function bounceOut(t, b, c, d)
{
    if ((t/=d) < (1/2.75)){
        return c*(7.5625*t*t) + b;
    } else if (t < (2/2.75)){
        return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
    } else if (t < (2.5/2.75)){
        return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
    } else {
        return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
    }
}

// Utility: Get the size of the window, and set myWidth and myHeight
// Credit to quirksmode.org

function getSize() {

    // Window Size

    if (self.innerHeight) { // Everyone but IE
        myWidth = window.innerWidth;
        myHeight = window.innerHeight;
        myScroll = window.pageYOffset;
    } else if (document.documentElement && document.documentElement.clientHeight) { // IE6 Strict
        myWidth = document.documentElement.clientWidth;
        myHeight = document.documentElement.clientHeight;
        myScroll = document.documentElement.scrollTop;
    } else if (document.body) { // Other IE, such as IE7
        myWidth = document.body.clientWidth;
        myHeight = document.body.clientHeight;
        myScroll = document.body.scrollTop;
    }

    // Page size w/offscreen areas

    if (window.innerHeight && window.scrollMaxY) {   
        myScrollWidth = document.body.scrollWidth;
        myScrollHeight = window.innerHeight + window.scrollMaxY;
    } else if (document.body.scrollHeight > document.body.offsetHeight) { // All but Explorer Mac
        myScrollWidth = document.body.scrollWidth;
        myScrollHeight = document.body.scrollHeight;
    } else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
        myScrollWidth = document.body.offsetWidth;
        myScrollHeight = document.body.offsetHeight;
    }
}

// Utility: Get Shift Key Status
// IE events don't seem to get passed through the function, so grab it from the window.

function getShift(evt) {
    var shift = false;
    if (! evt && window.event) {
        shift = window.event.shiftKey;
    } else if (evt) {
        shift = evt.shiftKey;
        if (shift) evt.stopPropagation(); // Prevents Firefox from doing shifty things
    }
    return shift;
}

// Utility: Find the Y position of an element on a page. Return Y and X as an array

function findElementPos(elemFind)
{
    var elemX = 0;
    var elemY = 0;
    do {
        elemX += elemFind.offsetLeft;
        elemY += elemFind.offsetTop;
    } while ( elemFind = elemFind.offsetParent )

    return Array(elemX, elemY);
}

// FancyZoomHTML.js - v1.0
// Used to draw necessary HTML elements for FancyZoom
//
// Copyright (c) 2008 Cabel Sasser / Panic Inc
// All rights reserved.

function insertZoomHTML() {

    // All of this junk creates the three <div>'s used to hold the closebox, image, and zoom shadow.
    var inBody = document.getElementsByTagName("body").item(0);
    // WAIT SPINNER
    var inSpinbox = document.createElement("div");
    inSpinbox.setAttribute('id', 'ZoomSpin');
    inSpinbox.style.position = 'absolute';
    inSpinbox.style.left = '10px';
    inSpinbox.style.top = '10px';
    inSpinbox.style.visibility = 'hidden';
    inSpinbox.style.zIndex = '525';
    inBody.insertBefore(inSpinbox, inBody.firstChild);
    var inSpinImage = document.createElement("img");
    inSpinImage.setAttribute('id', 'SpinImage');
    inSpinImage.setAttribute('src', zoomImagesURI+'zoom-spin-1.png');
    inSpinbox.appendChild(inSpinImage);
    // ZOOM IMAGE
    //
    // <div id="ZoomBox">
    //   <a href="javascript:zoomOut();"><img src="/images/spacer.gif" id="ZoomImage" border="0"></a> <!-- THE IMAGE -->
    //   <div id="ZoomClose">
    //     <a href="javascript:zoomOut();"><img src="/images/closebox.png" width="30" height="30" border="0"></a>
    //   </div>
    // </div>
    var inZoombox = document.createElement("div");
    inZoombox.setAttribute('id', 'ZoomBox');
    inZoombox.style.position = 'absolute';
    inZoombox.style.left = '10px';
    inZoombox.style.top = '10px';
    inZoombox.style.visibility = 'hidden';
    inZoombox.style.zIndex = '499';
    inBody.insertBefore(inZoombox, inSpinbox.nextSibling);
    var inImage1 = document.createElement("img");
    inImage1.onclick = function (event) { zoomOut(this, event); return false; };   
    inImage1.setAttribute('src',zoomImagesURI+'spacer.gif');
    inImage1.setAttribute('id','ZoomImage');
    inImage1.setAttribute('border', '0');
    // inImage1.setAttribute('onMouseOver', 'zoomMouseOver();')
    // inImage1.setAttribute('onMouseOut', 'zoomMouseOut();')
    // This must be set first, so we can later test it using webkitBoxShadow.
    inImage1.setAttribute('style', '-webkit-box-shadow: '+shadowSettings+'0.0)');
    inImage1.style.display = 'block';
    inImage1.style.width = '10px';
    inImage1.style.height = '10px';
    inImage1.style.cursor = 'pointer'; // -webkit-zoom-out?
    inZoombox.appendChild(inImage1);

    var inClosebox = document.createElement("div");
    inClosebox.setAttribute('id', 'ZoomClose');
    inClosebox.style.position = 'absolute';
    // In MSIE, we need to put the close box inside the image.
    // It's 2008 and I'm having to do a browser detect? Sigh.
    if (browserIsIE) {
        inClosebox.style.left = '-1px';
        inClosebox.style.top = '0px';   
    } else {
        inClosebox.style.left = '-15px';
        inClosebox.style.top = '-15px';
    }
    inClosebox.style.visibility = 'hidden';
    inZoombox.appendChild(inClosebox);
    var inImage2 = document.createElement("img");
    inImage2.onclick = function (event) { zoomOut(this, event); return false; };   
    inImage2.setAttribute('src',zoomImagesURI+'closebox.png');       
    inImage2.setAttribute('width','30');
    inImage2.setAttribute('height','30');
    inImage2.setAttribute('border','0');
    inImage2.style.cursor = 'pointer';       
    inClosebox.appendChild(inImage2);
    // SHADOW
    // Only draw the table-based shadow if the programatic webkitBoxShadow fails!
    // Also, don't draw it if we're IE -- it wouldn't look quite right anyway.
    if (! document.getElementById('ZoomImage').style.webkitBoxShadow && ! browserIsIE) {

        // SHADOW BASE
        var inFixedBox = document.createElement("div");
        inFixedBox.setAttribute('id', 'ShadowBox');
        inFixedBox.style.position = 'absolute';
        inFixedBox.style.left = '50px';
        inFixedBox.style.top = '50px';
        inFixedBox.style.width = '100px';
        inFixedBox.style.height = '100px';
        inFixedBox.style.visibility = 'hidden';
        inFixedBox.style.zIndex = '498';
        inBody.insertBefore(inFixedBox, inZoombox.nextSibling);   
        // SHADOW
        // Now, the shadow table. Skip if not compatible, or irrevelant with -box-shadow.
        // <div id="ShadowBox"><table border="0" width="100%" height="100%" cellpadding="0" cellspacing="0"> X
        //   <tr height="25">
        //   <td width="27"><img src="/images/zoom-shadow1.png" width="27" height="25"></td>
        //   <td background="/images/zoom-shadow2.png">&nbsp;</td>
        //   <td width="27"><img src="/images/zoom-shadow3.png" width="27" height="25"></td>
        //   </tr>
        var inShadowTable = document.createElement("table");
        inShadowTable.setAttribute('border', '0');
        inShadowTable.setAttribute('width', '100%');
        inShadowTable.setAttribute('height', '100%');
        inShadowTable.setAttribute('cellpadding', '0');
        inShadowTable.setAttribute('cellspacing', '0');
        inFixedBox.appendChild(inShadowTable);

        var inShadowTbody = document.createElement("tbody");    // Needed for IE (for HTML4).
        inShadowTable.appendChild(inShadowTbody);
        var inRow1 = document.createElement("tr");
        inRow1.style.height = '25px';
        inShadowTbody.appendChild(inRow1);
        var inCol1 = document.createElement("td");
        inCol1.style.width = '27px';
        inRow1.appendChild(inCol1); 
        var inShadowImg1 = document.createElement("img");
        inShadowImg1.setAttribute('src', zoomImagesURI+'zoom-shadow1.png');
        inShadowImg1.setAttribute('width', '27');
        inShadowImg1.setAttribute('height', '25');
        inShadowImg1.style.display = 'block';
        inCol1.appendChild(inShadowImg1);
        var inCol2 = document.createElement("td");
        inCol2.setAttribute('background', zoomImagesURI+'zoom-shadow2.png');
        inRow1.appendChild(inCol2);
        // inCol2.innerHTML = '<img src=';
        var inSpacer1 = document.createElement("img");
        inSpacer1.setAttribute('src',zoomImagesURI+'spacer.gif');
        inSpacer1.setAttribute('height', '1');
        inSpacer1.setAttribute('width', '1');
        inSpacer1.style.display = 'block';
        inCol2.appendChild(inSpacer1);
        var inCol3 = document.createElement("td");
        inCol3.style.width = '27px';
        inRow1.appendChild(inCol3); 
        var inShadowImg3 = document.createElement("img");
        inShadowImg3.setAttribute('src', zoomImagesURI+'zoom-shadow3.png');
        inShadowImg3.setAttribute('width', '27');
        inShadowImg3.setAttribute('height', '25');
        inShadowImg3.style.display = 'block';
        inCol3.appendChild(inShadowImg3);
        //   <tr>
        //   <td background="/images/zoom-shadow4.png">&nbsp;</td>
        //   <td bgcolor="#ffffff">&nbsp;</td>
        //   <td background="/images/zoom-shadow5.png">&nbsp;</td>
        //   </tr>
        inRow2 = document.createElement("tr");
        inShadowTbody.appendChild(inRow2);
        var inCol4 = document.createElement("td");
        inCol4.setAttribute('background', zoomImagesURI+'zoom-shadow4.png');
        inRow2.appendChild(inCol4);
        // inCol4.innerHTML = '&nbsp;';
        var inSpacer2 = document.createElement("img");
        inSpacer2.setAttribute('src',zoomImagesURI+'spacer.gif');
        inSpacer2.setAttribute('height', '1');
        inSpacer2.setAttribute('width', '1');
        inSpacer2.style.display = 'block';
        inCol4.appendChild(inSpacer2);
        var inCol5 = document.createElement("td");
        inCol5.setAttribute('bgcolor', '#ffffff');
        inRow2.appendChild(inCol5);
        // inCol5.innerHTML = '&nbsp;';
        var inSpacer3 = document.createElement("img");
        inSpacer3.setAttribute('src',zoomImagesURI+'spacer.gif');
        inSpacer3.setAttribute('height', '1');
        inSpacer3.setAttribute('width', '1');
        inSpacer3.style.display = 'block';
        inCol5.appendChild(inSpacer3);
        var inCol6 = document.createElement("td");
        inCol6.setAttribute('background', zoomImagesURI+'zoom-shadow5.png');
        inRow2.appendChild(inCol6);
        // inCol6.innerHTML = '&nbsp;';
        var inSpacer4 = document.createElement("img");
        inSpacer4.setAttribute('src',zoomImagesURI+'spacer.gif');
        inSpacer4.setAttribute('height', '1');
        inSpacer4.setAttribute('width', '1');
        inSpacer4.style.display = 'block';
        inCol6.appendChild(inSpacer4);
        //   <tr height="26">
        //   <td width="27"><img src="/images/zoom-shadow6.png" width="27" height="26"</td>
        //   <td background="/images/zoom-shadow7.png">&nbsp;</td>
        //   <td width="27"><img src="/images/zoom-shadow8.png" width="27" height="26"></td>
        //   </tr> 
        // </table>
        var inRow3 = document.createElement("tr");
        inRow3.style.height = '26px';
        inShadowTbody.appendChild(inRow3);
        var inCol7 = document.createElement("td");
        inCol7.style.width = '27px';
        inRow3.appendChild(inCol7);
        var inShadowImg7 = document.createElement("img");
        inShadowImg7.setAttribute('src', zoomImagesURI+'zoom-shadow6.png');
        inShadowImg7.setAttribute('width', '27');
        inShadowImg7.setAttribute('height', '26');
        inShadowImg7.style.display = 'block';
        inCol7.appendChild(inShadowImg7);
        var inCol8 = document.createElement("td");
        inCol8.setAttribute('background', zoomImagesURI+'zoom-shadow7.png');
        inRow3.appendChild(inCol8); 
        // inCol8.innerHTML = '&nbsp;';
        var inSpacer5 = document.createElement("img");
        inSpacer5.setAttribute('src',zoomImagesURI+'spacer.gif');
        inSpacer5.setAttribute('height', '1');
        inSpacer5.setAttribute('width', '1');
        inSpacer5.style.display = 'block';
        inCol8.appendChild(inSpacer5);
        var inCol9 = document.createElement("td");
        inCol9.style.width = '27px';
        inRow3.appendChild(inCol9); 
        var inShadowImg9 = document.createElement("img");
        inShadowImg9.setAttribute('src', zoomImagesURI+'zoom-shadow8.png');
        inShadowImg9.setAttribute('width', '27');
        inShadowImg9.setAttribute('height', '26');
        inShadowImg9.style.display = 'block';
        inCol9.appendChild(inShadowImg9);
    }

    if (includeCaption) {
        // CAPTION
        //
        // <div id="ZoomCapDiv" style="margin-left: 13px; margin-right: 13px;">
        // <table border="1" cellpadding="0" cellspacing="0">
        // <tr height="26">
        // <td><img src="zoom-caption-l.png" width="13" height="26"></td>
        // <td rowspan="3" background="zoom-caption-fill.png"><div id="ZoomCaption"></div></td>
        // <td><img src="zoom-caption-r.png" width="13" height="26"></td>
        // </tr>
        // </table>
        // </div>
        var inCapDiv = document.createElement("div");
        inCapDiv.setAttribute('id', 'ZoomCapDiv');
        inCapDiv.style.position = 'absolute';        
        inCapDiv.style.visibility = 'hidden';
        inCapDiv.style.marginLeft = 'auto';
        inCapDiv.style.marginRight = 'auto';
        inCapDiv.style.zIndex = '501';

        inBody.insertBefore(inCapDiv, inZoombox.nextSibling);
        var inCapTable = document.createElement("table");
        inCapTable.setAttribute('border', '0');
        inCapTable.setAttribute('cellPadding', '0');    // Wow. These honestly need to
        inCapTable.setAttribute('cellSpacing', '0');    // be intercapped to work in IE. WTF?
        inCapDiv.appendChild(inCapTable);
        var inTbody = document.createElement("tbody");    // Needed for IE (for HTML4).
        inCapTable.appendChild(inTbody);
        var inCapRow1 = document.createElement("tr");
        inTbody.appendChild(inCapRow1);
        var inCapCol1 = document.createElement("td");
        inCapCol1.setAttribute('align', 'right');
        inCapRow1.appendChild(inCapCol1);
        var inCapImg1 = document.createElement("img");
        inCapImg1.setAttribute('src', zoomImagesURI+'zoom-caption-l.png');
        inCapImg1.setAttribute('width', '13');
        inCapImg1.setAttribute('height', '26');
        inCapImg1.style.display = 'block';
        inCapCol1.appendChild(inCapImg1);
        var inCapCol2 = document.createElement("td");
        inCapCol2.setAttribute('background', zoomImagesURI+'zoom-caption-fill.png');
        inCapCol2.setAttribute('id', 'ZoomCaption');
        inCapCol2.setAttribute('valign', 'middle');
        inCapCol2.style.fontSize = '14px';
        inCapCol2.style.fontFamily = 'Helvetica';
        inCapCol2.style.fontWeight = 'bold';
        inCapCol2.style.color = '#ffffff';
        inCapCol2.style.textShadow = '0px 2px 4px #000000';
        inCapCol2.style.whiteSpace = 'nowrap';
        inCapRow1.appendChild(inCapCol2);
        var inCapCol3 = document.createElement("td");
        inCapRow1.appendChild(inCapCol3);
        var inCapImg2 = document.createElement("img");
        inCapImg2.setAttribute('src', zoomImagesURI+'zoom-caption-r.png');
        inCapImg2.setAttribute('width', '13');
        inCapImg2.setAttribute('height', '26');
        inCapImg2.style.display = 'block';
        inCapCol3.appendChild(inCapImg2);
    }
}

Replace <body> tag with <body onload='setupZoom()'> and use it with <a href="Image link"><img src="Image link" width="200" border="0" height="200" />.

 

7. Add a Floating ‘Subscribe to” bar

Add the following before ]]></b:skin> Add the following between ]]></b:skin> and </head>
#mta_bar {
background:#003366;
border-top: 3px solid #6699ff;
margin: 0;
padding: 7px 0;
z-index: 100;
bottom:0px;
right:0px;
width: 100%;
overflow: auto;
position: fixed;
}
* html #mta_bar{
/*IE6 hack*/
position: absolute;
width: expression(document.compatMode=="CSS1Compat"? document.documentElement.clientWidth+"px" : body.clientWidth+"px");
}
#mta_bar .left { float: left; text-align: center; font-family: Arial; font-size: 13px; font-weight: bold; font-style: normal; color: #0000FF; width:92%;}
#mta_bar .right {font-family: Arial, Helvetica, sans-serif; float: right; text-align: center; font-weight: normal; font-size: 10px;letter-spacing: 0; width: 30px; white-space: nowrap;}
#mta_bar .right a {font-size: 10px; color: #0000FF; text-decoration: underline;}
#mta_bar .right a:hover {font-size: 10px; color: #0000FF; text-decoration: none;}
#left_bar a {background: url('http://img229.imageshack.us/img229/3826/icorsstransthumb1bj4.png?imgmax=800') no-repeat; text-decoration: none; color: #fff; padding:5px 0px 5px 30px;}
#left_bar a:hover { text-decoration: underline; color: #fff; }

<script type='text/javascript'>
//<![CDATA[
var mta_arr = new Array();
var mta_clear = new Array();
function mtaFloat(mta) {
mta_arr[mta_arr.length] = this;
var mtapointer = eval(mta_arr.length-1);
this.pagetop = 0;
this.cmode = (document.compatMode && document.compatMode!="BackCompat") ? document.documentElement : document.body;
this.mtasrc = document.all? document.all[mta] : document.getElementById(mta);
this.mtasrc.height = this.mtasrc.offsetHeight;
this.mtaheight = this.cmode.clientHeight;
this.mtaoffset = mtaGetOffsetY(mta_arr[mtapointer]);
var mtabar = 'mta_clear['+mtapointer+'] = setInterval("mtaFloatInit(mta_arr['+mtapointer+'])",1);';
mtabar = mtabar;
eval(mtabar);
}
function mtaGetOffsetY(mta) {
var mtaTotOffset = parseInt(mta.mtasrc.offsetTop);
var parentOffset = mta.mtasrc.offsetParent;
while ( parentOffset != null ) {
mtaTotOffset += parentOffset.offsetTop;
parentOffset = parentOffset.offsetParent;
}
return mtaTotOffset;
}
function mtaFloatInit(mta) {
mta.pagetop = mta.cmode.scrollTop;
mta.mtasrc.style.top = mta.pagetop - mta.mtaoffset + "px";
}
function closeTopAds() {
document.getElementById("mta_bar").style.visibility = "hidden";
}
//]]>

</script>

Add the following before </body>, replacing YOURBLOGNAME and YOUR-FEED-BURNER-ADDRESS with the pertinent values:

<div id='mta_bar'>
<div id='left_bar'><span class='left'><a href='YOUR-FEED-BURNER-ADDRESS' target='_blank'>To Get Latest Update Subscribe Now !!!</a></span></div>
<span class='right' onmouseout='self.status=&apos;&apos;' onmouseover='self.status=&apos;YOURBLOGNAME.blogspot.com.com&apos;;return true;'> <img align='absmiddle' border='0' onClick='closeTopAds();return false;' src='https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhU7NxOKvzspnTVGO9gmRS3K6CXpCndjxuOFbEXHSA4HPIuNrTTfXs8w441xwZkeMYKfEVqmvRTVE8_bmIReC5_2y8ISKotSz7_efMBRidTx32RiOM7-bDKCsEu3Lt60JtgSaLfCiOGeRs/?imgmax=800' style='cursor:hand;cursor:pointer;'/></span></div>

 

8. Related post widget (no categories)

You may have noticed that this blog uses such a widget, but the related posts are divided by categories. The following script achieves the same end, without separating the related articles on categories.

Add the following before </head>, changing font type, font size, width to suit your taste:

<style>

#related-posts {
float : left;
width : 540px;
margin-top:20px;
margin-left : 5px;
margin-bottom:20px;
font : 10px Verdana;
margin-bottom:10px;
}
#related-posts .widget {
list-style-type : none;
margin : 5px 0 5px 0;
padding : 0;
}
#related-posts .widget h2, #related-posts h2 {
color : #940f04;
font-size : 15px;
font-weight : normal;
margin : 5px 7px 0;
padding : 0 0 5px;
}
#related-posts a {
color : #054474;
font-size : 10px;
text-decoration : none;
}
#related-posts a:hover {
color : #054474;
text-decoration : none;
}
#related-posts ul {
border : medium none;
margin : 10px;
padding : 0;
}
#related-posts ul li {
display : block;
background : url("http://www.dogphilosophy.net/graphics/sample1.jpg") no-repeat 0 0;
margin : 0;
padding-top : 0;
padding-right : 0;
padding-bottom : 1px;
padding-left : 16px;
margin-bottom : 5px;
line-height : 2em;
border-bottom:1px dotted #cccccc;
}

</style>

<script type='text/javascript'>
//<![CDATA[
var relatedTitles = new Array();
var relatedTitlesNum = 0;
var relatedUrls = new Array();
function related_results_labels(json) {
for (var i = 0; i < json.feed.entry.length; i++) {
var entry = json.feed.entry[i];
relatedTitles[relatedTitlesNum] = entry.title.$t;
for (var k = 0; k < entry.link.length; k++) {
if (entry.link[k].rel == 'alternate') {
relatedUrls[relatedTitlesNum] = entry.link[k].href;
relatedTitlesNum++;
break;
}
}
}
}
function removeRelatedDuplicates() {
var tmp = new Array(0);
var tmp2 = new Array(0);
for(var i = 0; i < relatedUrls.length; i++) {
if(!contains(tmp, relatedUrls[i])) {
tmp.length += 1;
tmp[tmp.length - 1] = relatedUrls[i];
tmp2.length += 1;
tmp2[tmp2.length - 1] = relatedTitles[i];
}
}
relatedTitles = tmp2;
relatedUrls = tmp;
}
function contains(a, e) {
for(var j = 0; j < a.length; j++) if (a[j]==e) return true;
return false;
}
function printRelatedLabels() {
var r = Math.floor((relatedTitles.length - 1) * Math.random());
var i = 0;
document.write('<ul>');
while (i < relatedTitles.length && i < 20) {
document.write('<li><a href="' + relatedUrls[r] + '">' + relatedTitles[r] + '</a></li>');
if (r < relatedTitles.length - 1) {
r++;
} else {
r = 0;
}
i++;
}
document.write('</ul>');
}
//]]>
</script>

Add the following before <p><data:post.body/></p> changing max-results to a suitable number:

<b:if cond='data:blog.pageType == "item"'>
<div id="related-posts">
<h2>Other Recommended Posts on <b:loop values='data:post.labels' var='label'><data:label.name/><b:if cond='data:label.isLast != &quot;true&quot;'>,</b:if><b:if cond='data:blog.pageType == &quot;item&quot;'>
<script expr:src='&quot;/feeds/posts/default/-/&quot; + data:label.name + &quot;?alt=json-in-script&amp;callback=related_results_labels&amp;max-results=10&quot;' type='text/javascript'/></b:if></b:loop> </h2>

<script type='text/javascript'> removeRelatedDuplicates(); printRelatedLabels(); </script>

</div></b:if>

 

9. Add Yahoo Smileys Emoticons to your Comments

Search and replace:

<p class='comment-footer'>
<b:if cond='data:post.embedCommentForm'>
<b:include data='post' name='comment-form'/>
<b:else/>
<b:if cond='data:post.allowComments'>
<h3><a expr:href='data:post.addCommentUrl'
expr:onclick='data:post.addCommentOnclick'>
<data:postCommentMsg/></a></h3>
</b:if>
</b:if>
</p>
</b:if>

with

<p class='comment-footer'>
<b:if cond='data:post.embedCommentForm'>
<div style='-moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; width: 369; text-align: left; border: 1px solid #cccccc; padding: 5px; background: #eeeddf; height:86'>
<b>
<img border='0' height='18' src='http://us.i1.yimg.com/us.yimg.com/i/mesg/emoticons7/21.gif' width='18'/> :))
<img border='0' height='18' src='http://us.i1.yimg.com/us.yimg.com/i/mesg/emoticons7/71.gif' width='18'/> ;))
<img border='0' height='18' src='http://us.i1.yimg.com/us.yimg.com/i/mesg/emoticons7/5.gif' width='18'/> ;;)
<img border='0' height='18' src='http://us.i1.yimg.com/us.yimg.com/i/mesg/emoticons7/4.gif' width='18'/> :D
<img border='0' height='18' src='http://us.i1.yimg.com/us.yimg.com/i/mesg/emoticons7/3.gif' width='18'/> ;)
<img border='0' height='18' src='http://us.i1.yimg.com/us.yimg.com/i/mesg/emoticons7/10.gif' width='18'/> :p
<img border='0' height='18' src='http://us.i1.yimg.com/us.yimg.com/i/mesg/emoticons7/20.gif' width='22'/> :((
<img border='0' height='18' src='http://us.i1.yimg.com/us.yimg.com/i/mesg/emoticons7/1.gif' width='18'/> :)
<img border='0' height='18' src='http://us.i1.yimg.com/us.yimg.com/i/mesg/emoticons7/2.gif' width='18'/> :(
<img border='0' height='18' src='http://us.i1.yimg.com/us.yimg.com/i/mesg/emoticons7/8.gif' width='18'/> :X
<img border='0' height='18' src='http://us.i1.yimg.com/us.yimg.com/i/mesg/emoticons7/12.gif' width='18'/> =((
<img border='0' height='18' src='http://us.i1.yimg.com/us.yimg.com/i/mesg/emoticons7/13.gif' width='18'/> :-o
<img border='0' height='18' src='http://us.i1.yimg.com/us.yimg.com/i/mesg/emoticons7/7.gif' width='20'/> :-/
<img border='0' height='18' src='http://us.i1.yimg.com/us.yimg.com/i/mesg/emoticons7/11.gif' width='18'/> :-*
<img border='0' height='18' src='http://us.i1.yimg.com/us.yimg.com/i/mesg/emoticons7/22.gif' width='18'/> :|
<img border='0' height='18' src='http://us.i1.yimg.com/us.yimg.com/i/mesg/emoticons7/35.gif' width='24'/> 8-}
<img border='0' height='18' src='http://us.i1.yimg.com/us.yimg.com/i/mesg/emoticons7/100.gif' width='31'/> :)]
<img border='0' height='18' src='http://us.i1.yimg.com/us.yimg.com/i/mesg/emoticons7/102.gif' width='44'/> ~x(
<img border='0' height='18' src='http://us.i1.yimg.com/us.yimg.com/i/mesg/emoticons7/104.gif' width='30'/> :-t
<img border='0' height='18' src='http://us.i1.yimg.com/us.yimg.com/i/mesg/emoticons7/66.gif' width='18'/> b-(
<img border='0' height='18' src='http://us.i1.yimg.com/us.yimg.com/i/mesg/emoticons7/62.gif' width='18'/> :-L
<img border='0' height='18' src='http://us.i1.yimg.com/us.yimg.com/i/mesg/emoticons7/14.gif' width='34'/> x(
<img border='0' height='18' src='http://us.i1.yimg.com/us.yimg.com/i/mesg/emoticons7/24.gif' width='30'/> =))
</b>
</div>
<b:include data='post' name='comment-form'/>
<b:else/>
<b:if cond='data:post.allowComments'>
<a expr:href='data:post.addCommentUrl' expr:onclick='data:post.addCommentOnclick'><data:postCommentMsg/></a>
</b:if>
</b:if>
</p>
</b:if>

 

10. Creating a Scrolling Links List using Marquee

Add the following in a HTML/Javascript gadget, substituting your links for what you want:

<marquee bgcolor="#dff6ff" height="100px" width="300px" direction="up" scrollamount="2">
<ul type="circle">
<li><a href="YOUR-LINK-1" target="_blank">LINK-NAME-1</a></li>
<li><a href="YOUR-LINK-2" target="_blank">LINK-NAME-2</a></li>
<li><a href="YOUR-LINK-3" target="_blank">LINK-NAME-3</a></li>
<li><a href="YOUR-LINK-4" target="_blank">LINK-NAME-4</a></li>
<li><a href="YOUR-LINK-5" target="_blank">LINK-NAME-5</a></li>
<li><a href="YOUR-LINK-6" target="_blank">LINK-NAME-6</a></li>
<li><a href="YOUR-LINK-7" target="_blank">LINK-NAME-7</a></li>
<li><a href="YOUR-LINK-8" target="_blank">LINK-NAME-8</a></li>
<li><a href="YOUR-LINK-9" target="_blank">LINK-NAME-9</a></li>
<li><a href="YOUR-LINK-10" target="_blank">LINK-NAME-10</a></li>
</ul>
</marquee>

 

Bonus. Split Header or Footer into 3 or 4 sections respectively

If the tabbed navigation hack (see above) is not sufficient for you, consider splitting the header and footer in several sections.

a) Header

Replace

#header {
margin: 5px;
border: 1px solid $bordercolor;
text-align: center;
color:$pagetitlecolor;
}

div id='header-wrapper'>
<b:section class='header' id='header' maxwidgets='1' showaddelement='no'>
<b:widget id='Header1' locked='true' title='YOUR-BLOG-TITLE (Header)' type='Header'/>
</b:section>
</div>

with

#header {
float:left;
width:30%;
height:200px;
margin: 0px;
border: 0px solid $bordercolor;
text-align: center;
color:$pagetitlecolor;
}

#header2{float:left; width:30%; height:200px}

#header3{float:left; width:39%; height:200px}

<div id='header-wrapper'>
<b:section class='header' id='header' maxwidgets='1' showaddelement='no'>
<b:widget id='Header1' locked='true' title='YOUR-BLOG-TITLE (Header)' type='Header'/>
</b:section>

<b:section class='header' id='header2' maxwidgets='4' showaddelement='yes'/>
<b:section class='header' id='header3' maxwidgets='4' showaddelement='yes'/>
<div style='clear:both;'/>
</div><!-- end header-wrapper -->

b) Footer

Search for <b:section class='footer' id='footer'/> (should be enclosed in a div with id ‘footer-wrapper’) and replace with:

<div id='footer-column-container'>
<div id='footer1' style='width: 225px; float: left; margin:0; '>
<b:section class='footer-column' id='footer-column-1' preferred='yes' style='float:left;'>
<b:widget id='Text1' locked='false' title='About B-G' type='Text'/>

</b:section>
</div>
<div id='footer2' style='width: 225px; float: left; margin:0; '>
<b:section class='footer-column' id='footer-column-2' preferred='yes' style='float:left;'>
<b:widget id='Text4' locked='false' title='About Author' type='Text'/>
</b:section>
</div>

<div id='footer3' style='width: 225px; float: right; margin:0; '>
<b:section class='footer-column' id='footer-column-3' preferred='yes' style='float:right;'>
<b:widget id='Text3' locked='false' title='Subscribe in Reader' type='Text'/>
</b:section>
</div>

<div id='footer4' style='width: 225px; float: right; margin:0; '>
<b:section class='footer-column' id='footer-column-4' preferred='yes' style='float:right;'>
<b:widget id='Text2' locked='false' title='Access B-G on Go' type='Text'/>
</b:section>
</div>
<div style='clear:both;'/>
</div>

also, add the following before ]]></b:skin>

#footer-column-container { border: .3px dotted #cccccc;}

.footer-column { margin: 0 10px 0 10px; padding:5px;
color: #666666; line-height: 1.5em; font-size:12px;}

.footer-column h2 {
padding-bottom:.15em; text-align:center;
font:"normal normal 80% 'Comic Sans MS','Lucida Sans Unicode','Trebuchet MS',Sans-serif";
color:#333333;
line-height:1em; letter-spacing:.1em;
border-bottom: 1px solid #cccccc;}

.footer-column ul { list-style:none; margin:0 0 0; padding:0 0 0;}

.footer-column ul li {
background: url(http://i421.photobucket.com/albums/pp296/rnbutpur/bullet-1.gif) no-repeat;
margin:0 0 0; padding-left: 16px;
padding-bottom: 0.5em; line-height:1.2em;}

.footer-column .widget {margin:0 0 .5em; padding:0 0 1em;}

 

I hope you’ve found all this helpful.

Sources / More info: product-ideas, pi-blog, blogbuster-hear, gadgets-howto1, gadgets-howto2, gadgets-howto3, amanda-readmore, qr-readmore, vozme, qr-#-comments, qr-tabbed-nav, bb-twit-this, ln-twit-this, gadgets-request-draft

Comments

Popular posts from this blog