Showing posts with label css. Show all posts
Showing posts with label css. Show all posts

Saturday, December 30, 2006

Blogger Tag Cloud

One good thing about the blogger beta is that it supports Labels a.k.a. Categories/Tags (at last!), so one can categorize his posts. Blogger also allows showing the list of labels from your blogs and allows user to filter posts based on the labels. The problem is that the layout of labels is not customizable or is it? Actually, with some (not so elegant) lines of javascript and css, we can make these labels display as a tag-cloud pretty much what other blog platforms support. Here's what we need to do:
Preamble: Edit 2: Edit the template to give the ul tag (which displays the labels) an Id (for e.g. labelUl), this can be done by clicking on "Expand Widget Template" checkbox and scrolling to the code in template which has a div with ID: "Label1". The UL would be contained within this. Enclose the (<data:label.count/>) within a span and save the template.

1) Firstly we'll make the list appear horizontally instead of vertically, that way we can free up some screen real-estate. So we add the respective styles for the ul and li elements within the style tag under head:
#Label1 {display:none;word-wrap:break-word;}
#labelUL {list-style:none;margin:0px;padding:0px;}
#labelUL li{padding:0px 3px 0px 0px;margin:0px;display:inline;}
Add the noscript tag to display the label div, in case user has js turned off
<noscript>
<style type='text/css'>
#Label1 {display:block;}
</style&g;
</noscript>
So at least we've got the list to display horizontally instead of vertically.
2) Now we need to change the font sizes of the labels based on their weights (i.e. the larger the number of posts tagged to a label, the bigger the text size for that).
For that we hook our DOM walk-through javascript to window.load, this is what I've done:


<script type='text/javascript'>
window.onload = function(){
var labelDiv = document.getElementById("Label1");
var ul= document.getElementById("labelUL");

try{
if(ul.childNodes.length>=0)
{
var weights = new Array();
//should be a div
var li,text, re;
var textNode;

var lis = ul.getElementsByTagName("li");
for(var i=0;i<lis.length;i++)
{
li = lis[i];
textNode = li.getElementsByTagName('span')[0];
text = textNode.innerHTML;
re = new RegExp("[^0-9]", "g");
text = text.replace(re,"");
li.title = text + " posts";
weights.push(new category(text,li));
textNode.innerHTML = "";
}
weights.sort(sortNumber);
var mean = Math.floor((parseInt(weights[0].weight)+parseInt(weights[weights.length-1].weight))/2);
//lets go
var weightFactor = 1;
for(i=0;i<weights.length;i++)
{
weightFactor = parseInt(weights[i].weight)*100/mean;
if(weightFactor<80)
weightFactor = 80 + weightFactor*.1;
else if(weightFactor>250)
weightFactor = 250;

weights[i].li.style.fontSize = weightFactor + "%";
}
weights = null;
labelDiv.style.display = "block";
};
}
catch(e){
if(labelDiv!=null)
labelDiv.style.display = "block";
}
}

function category(weightParam,e)
{
this.li = e;
this.weight = weightParam;

}

function sortNumber(a,b)
{
return a.weight - b.weight;
}
<script>


I don't let any tag to be less than 80% of normal text size, you don't want any label to be illegible due to it's size. The js is simple enough to understand and as I said it isn't the most elegant piece of code that you'd come across but hey it works for me. I tested this out on IE 7 and Fx and I'd guess it should either work or downgrade silently on other browsers, worst case the Labels section would look a little whacko but I promise it wouldn't steal your credit card information or conduct any phishing attacks :-).

Edit:Just figured out that in the template if you click on "Expand Widgets.." checkbox, you can set the Id for the ul element and even perhaps write a javascript inline without having to resort to a onload function. I am too lazy to change the code on my page though (don't fix it if it ain't broke).

Tuesday, November 21, 2006

AJAX and noscript

One of the evil of AJAX sites is that if the user has javascript turned off, the site stops functioning all together. Since I use NoScript extension all the time on Firefox, I really hate sites which don't even tell you that javascript needs to be turned on for the site's functionality to work and when it takes just a <noscript> tag to display a message to the user about js bit:
<noscript>
<div>This site requires javascript to be turned on...blah blah blah.</div>
</noscript>

You can get a bit more enterprising with the noscript tag, for instance what if you don't want the user to even access the page w.o. javascript turned on? Well, in that case you can put noscript tag in the head section and do a meta refresh:
<head>
...
<noscript>
<meta equiv="Refresh" content="0; URL=nojs.html"></noscript>
...
</head>


Ok, what if you don't want to redirect the user but hide all the elements on the page except the no js error message? You can achieve that too by using CSS:
Step 1) Add this div within the body where you want the error message to show up in case the js is turned off:
<div class="ns">
Ouch! No JS
</div>
Step 2) Hide the "ns" div by default:
.ns{display:none;}
Step 3) Hide all the elements on the page and display ns div if js is turned off:
<noscript>
<style type="text/css">
* {visibility:hidden;}
.ns {visibility:visible;margin:0px auto;width:60%;display:block}
</style>
</noscript>

Friday, March 24, 2006

Google maps prototype live again

Some time back my free hosted website was auto-deleted by somee.com due to "cpu overuse", now given that I don't have many high-end background procceses running on my site; it was quite a surprise but as they say you get what you pay for! Nevertheless, I've got the site back up and running and reuploading the entire chunk took me some time to figure out as I would get real bizarre configuration errors on the live site.
The Fx page transition e.g. is also back where it originally was and so is the Google Maps prototype, by the way I'd updated the prototype long time back to integrate it with MapPoint, Flickr and Fotolia...and yes, please don't use way too much bandwidth while checking them out :)

Friday, January 27, 2006

Implementing page transitions in Firefox using AJAX and CSS

Page is a feature in IE which allows you to add visual effects on your site using filters when a user enters or exits a page, the problem is that filters are IE-only. What if you want to add same transitions on your site for users who are visiting on Fx? You can emulate some filters of IE by using and CSS on to achieve the same results, here is a simple way to achieve fade-in transition in Fx for page exit:
Instead of redirecting user to second page directly (using links or JS:location.href), retrieve the second page contents using XmlHttpRequest, once the httpRequest has retrieved the contents of page 2, add a timeout function where in you reduce the opacity of the page by steps. Once the opacity falls below a certain value, do a document.write of page 2's response text. Here is the piece of JS code:

var xmlhttp;
var timerId = 0;
var op = 1;
function getPageFx()
{
url = "/transpage2.html";
if (window.XMLHttpRequest)
{
xmlhttp=new XMLHttpRequest()
xmlhttp.onreadystatechange=xmlhttpChange
xmlhttp.open("GET",url,true)
xmlhttp.send(null)
}
else
getPageIE();
}

function xmlhttpChange()
{
// if xmlhttp shows "loaded"
if (xmlhttp.readyState==4)
{
// if "OK"
if (xmlhttp.status==200)
{
if(timerId!=0)
window.clearTimeout(timerId);
timerId = window.setTimeout("trans();",100);
}
else
{
alert(xmlhttp.status)
}
}
}

function trans(){
op -= .1;
document.body.style.opacity = op;
if(op<.4){ window.clearTimeout(timerId); timerId = 0; document.body.style.opacity = 1; document.open(); document.write(xmlhttp.responseText); document.close(); return; } timerId = window.setTimeout("trans();",100); } function getPageIE(){ window.location.href = "transpage2.html"; }

You can see this code in action here.