We've moved!

TechKnack.blogspot.com has officially moved to TechKnack.net. You should be redirected in 3-5 seconds. Thank you.

January 31, 2008

The JS behind "Most Popular Posts"

Add this post to Del.icio.us. Del.icio.us (0 saved)

Original article: Most Popular Posts list for blogger

In my last article "Most Popular Posts list for blogger," I presented my version of Chris Riley's Analytics API workaround. I also promised to go through the JavaScript for those who were interested :)

The JS

Without further ado, the code:
<div id="popularposts"><noscript>Please enable javascript to view the most popular posts list.</noscript></div> <script type="text/javascript"> <!-- function topcontentCallback(obj) { try { var url,title,output; output='<ul>'; for (i=0; i< obj.count; i++) { url = obj.value.items[i].url; try { title = obj.value.items[i].name[0].content; title = title.replace('<title>', ''); title = title.replace('</title>', ''); title = title.replace('Tech Knack: ', ''); } // if we didn't get the title (bad Pipe!), give a pseudo- // title from the URL catch (e) { title = url.substring(url.lastIndexOf("/")+1, url.lastIndexOf(".html")) .replace(/\-/g, " "); } //remove the <title> tags the pipe leaves in. output+= '<li><a href="'+url+ '" title="'+title+'">'+title+'</a></li>'; } output += '</ul>'; document.getElementById("popularposts").innerHTML = output; } catch (e) { var error = "Error fetching data: "+e; if (e.toString().indexOf('i')!=-1) error += "<br />i: "+i; document.getElementById("popularposts").innerHTML=error; } } //--> </script> <script src="http://pipes.yahoo.com/pipes/pipe.run?_id=bi6F5qPK3BGfvuxf1vC6Jw&_render=json&_callback=topcontentCallback" type="text/javascript"> </script>

The Div

<div id="popularposts"><noscript>Please enable javascript to view the most popular posts list.</noscript></div>
The div with id "popularposts" is the div whose content will be replaced with our list. It initially contains some noscript text for those without JS.

The Function

function topcontentCallback(obj) {
The topcontentCallback function is the function used to handle the JSON output by the Yahoo! Pipe. "obj" is the JSON string passed in by the Pipe.

try { ...... } catch (e) { var error = "Error fetching data: "+e; if (e.toString().indexOf('i')!=-1) error += "<br />i: "+i; document.getElementById("popularposts").innerHTML=error; }
We enclose the main processing code in a try block. Firefox2 and IE6 (and presumably 7 and 8) support try blocks in JS. This way, if there is a problem processing the data (a referrenced node is missing, etc) the user gets a nice little error message rather than a JS error thrown by the browser. In te case of an error, the previously mentioned div's content is set to "Error: ". Not useful to visitors, per se, but good for debugging your script. The "if (e.toString().indexOf('i')!=-1)" part simply appends i's value (from within the try block) to the error message. Again, good for debugging.

var url,title,output; output='<ul>';
Declare some variables, initialize the output variable (we use an unordered list for display).

for (i=0; i< obj.count; i++) { url = obj.value.items[i].url;
We loop over the items given by the Pipe. First we pull the url of the popular page.

try { title = obj.value.items[i].name[0].content; title = title.replace('<title>', ''); title = title.replace('</title>', ''); title = title.replace('Tech Knack: ', ''); } // if we didn't get the title (bad Pipe!), give a pseudo- // title from the URL catch (e) { title = url.substring(url.lastIndexOf("/")+1, url.lastIndexOf(".html")) .replace(/\-/g, " "); } //remove the <title> tags the pipe leaves in.
Here we try to pull the page's title, as pulled by the Pipe. I've noticed that, occasionally, the Pipe will have trouble getting the page's title, and so leaves the title blank, which doesn't play well with our script. Within the try block, I get the content of the title; I then try to replace (remove) the title tags and the site's title. If there is no title text from the Pipe, this will throw an error. In the catch block, we use the page's url to "guess" the title, removing the ".html" at the end using url.substring(), and replacing the intermittent dashes which replace punctuation and spaces with .replace(). These two commands are strung together to be url.substring().replace(). The result: if the article titled "CSS trick - two background images" doesn't have a title attribute in our JSON, the title is given as "css trick two background images". For this reason, you should enable "post pages" in your template's preferences.

output+= '<li><a href="'+url+ '" title="'+title+'">'+title+'</a></li>';
Here we append to our ul an li containing a link to the popular page.

} output += '</ul>'; document.getElementById("popularposts").innerHTML = output;
After the for loop, we add the final </ul> and replace the div's contents.

All this is just a function; without calling it, it is no good.

<script src="http://pipes.yahoo.com/pipes/pipe.run?_id=bi6F5qPK3BGfvuxf1vC6Jw&_render=json&_callback=topcontentCallback" type="text/javascript"> </script>
This imports the JSON created by the Pipe, telling it to render in JSON format (&_render=json) and to call our function to handle the JSON (&_callback=topcontentCallback). If you copy and paste the src to a browser window, you'll see that the content is simply a function call with the JSON as the parameter:
topcontentCallback({"count":7,"value":{"title":"TechKnack".......}});

January 29, 2008

Most Popular Posts list for blogger

Add this post to Del.icio.us. Del.icio.us (0 saved)

Last week I was looking for a way to have a "Most Popular Posts" widget here on blogger. The first and only true "widget" I found was Affiliate Brand's Most Popular Posts Widget. The only problems: it has a default color scheme that doesn't really go with that of my blog, and the height is pretty much fixed. It seems that you can change the look-n-feel with an external CSS sheet...but, unless you have another file host, that's a luxury we cheap Blogger bloggers don't have :)

Not satisfied with AffiliateBrand's widget, I kept searching. To no avail; that was simply the only pre-packaged blogger widget out there. Then the thought occurred to me to use my Google Analytics data to roll my own pseudo-widget. Genius, no? Well, it would be, if Analytics had an API :(

Fortunately, there are geniuses out there who have done genius things. In this case, Chris Riley of Blogoscoped has mashed up a combination of Google and Yahoo! offerings in such a way that we poor Blogger users can have a Popular Posts widget!

The basics

The basics are these:
1) Have analytics setup on your blog
2) Setup a Google Group
3) Setup a GMail account
2) Setup email notifications from Analytics' top pages to a GMail account
3) Setup GMail forwarding to your Google Group
5) Setup a Yahoo! pipe to fetch and process your top content report
6) Setup a pseudo-widget script on your blog to display the pipe's results

The pipe

While Chris provides his Yahoo! Pipe for others to clone, I had issues getting it to work with fetching the page's title contents. Here's the pipe that I'm using. Of course, a different pipe means different code for parsing the results.

The javascript

Here's the javascript that I use to display my pseudo-widget:
<div id="popularposts"><noscript>Please enable javascript to view the most popular posts list.</noscript></div> <script type="text/javascript"> <!-- // Robust pipe-output-handling function // as found at http://techknack.blogspot.com/2008/01/most-popular-posts-list-for-blogger.html function topcontentCallback(obj) { try { var url,title,output; output='<ul>'; for (i=0; i< obj.count; i++) { url = obj.value.items[i].url; try { title = obj.value.items[i].name[0].content; title = title.replace('<title>', ''); title = title.replace('</title>', ''); title = title.replace('Tech Knack: ', ''); } // if we didn't get the title (bad Pipe!), give a pseudo- // title from the URL catch (e) { title = url.substring(url.lastIndexOf("/")+1, url.lastIndexOf(".html")) .replace(/\-/g, " "); } //remove the <title> tags the pipe leaves in. output+= '<li><a href="'+url+ '" title="'+title+'">'+title+'</a></li>'; } output += '</ul>'; document.getElementById("popularposts").innerHTML = output; } catch (e) { var error = "Error fetching data: "+e; if (e.toString().indexOf('i')!=-1) error += "<br />i: "+i; document.getElementById("popularposts").innerHTML=error; } } //--> </script> <script src="http://pipes.yahoo.com/pipes/pipe.run?_id=bi6F5qPK3BGfvuxf1vC6Jw&_render=json&_callback=topcontentCallback" type="text/javascript"> </script>

Yes, my JS is admittedly a bit more robust than Chris's. This is mostly because of various issues I either ran into or thought of while trying to implement the widget. For those who are interested, I'll post an explanation of the code in another post.

For this to work, you must enable "post pages" in your template's preferences. There might be a way to get this to work without post pages, but I wouldn't recommend it ;)

If you are going to copy and paste this code (probably after cloning my pipe), be sure to change things appropriately:

Change the pipe ID in the last script element to the ID of your new pipe

In the "title fixup" section:
try { title = obj.value.items[i].name[0].content; title = title.replace('<title>', ''); title = title.replace('</title>', ''); title = title.replace('Tech Knack: ', ''); } The last "title.replace" line removes the site-wide title that is used on every page. Change it according to your Blogger setup (if you leave it as-is, though, it shouldn't hurt anything).

Additional links:
No Google Analytics API? No Problem!
Yahoo! Pipes

January 26, 2008

Cleaning a FireFox profile

Add this post to Del.icio.us. Del.icio.us (0 saved)

I'm an avid user of FireFox. I've set my installation up to sync across dual-boot, mainly as part of the Widows-to-Ubuntu crossover process. I can't pinpoint the exact date I started using FireFox, but it's been years...and in those years, I've certainly gathered a fair bit of junk.

Most of that junk is leftover configuration data and files from extensions that I've tried and subsequently gotten rid of. For some reason, the uninstall process of most (if not all) extensions leaves all the about:config preferences. In the case of GreaseMonkey (yes, I do not use GreaseMonkey), it leaves a gm_scripts directory in your profile, containing all the script files you've installed. At the worst, this is simply developer oversight. "Why would they want to uninstall this great extension?? They don't need an uninstall routine!"

At any rate, I've found a short and simple way to clean your FireFox profile. The only things I did differently was 1) leave my bookmarks.html file behind (I use Netvouz :D ) and 2) copy over various tweaks from my old prefs.js to my new prefs.js. A final note: You don't want to copy the entire prefs.js file over; it'll contain all the about:config junk mentioned earlier. Either open both old and new prefs.js files and copy over specific tweaks, or google them up again and re-apply them in the new profile.

Cleaning a FireFox Profile

January 23, 2008

Time for a redesign!

Add this post to Del.icio.us. Del.icio.us (0 saved)

I chose the dark design for this blog from the default blogger themes...a looong time ago (or so it seems)! Since then, I've taken a usability course in school, read many things on the web concerning usability, and been active at Deviant Art.

I believe it is time for a fresh look :D
The testing grounds: techknack2.blogspot.com ;)

One of the things I've heard recently is that white text on dark backgrounds is not all that usable. Cool, but not usable. As I've gone back and read a couple of my posts, I've realized that it's true, especially for long blocks of text; the text just seems to fade into the background after a rather short amount of time.

Another issue I've had is clutter; the more I look at my blog, the more clutter I see. Whitespace is good; simpler is better. Keep it simple, stupid.

In my search for templates for the new Blogger, I've found but one that I really like: Azul by karan at Skins4Bogger. Unfortunately, the XML download is for a completely different theme...

As per usual, I appreciate any and all feedback. What do you expect to see in a blog's layout? Where do you expect to see these things? Should the comment count be before the post, or after? Etc :)

January 18, 2008

KDE4 - First Impressions of Plasma

Add this post to Del.icio.us. Del.icio.us (0 saved)

The KDE world got noisy last week when KDE4 was released. KDE4 RC2 is easily available to K/Ubuntu Gusty users; simply add the required line to your /etc/apt/sources.list , install the kde4-core package, logout, select KDE4 as your session manager, and log back in to a shiny new desktop. The best part: the KDE4 packages are installed separately from your old KDE3.x packages, so you can switch back and forth between the two with a simple logout/login.

KDE4 is a complete rewrite of the K Desktop Environment: a new hardware abstraction layer (Solid instead of HAL), a new multimedia layer (Phonon instead of aRts), and, with a new desktop shell (Plasma), a radically different desktop experience.

The first thing you'll notice is that all of your icons are suddenly...plasmoided. In Plasma, everything on the desktop is a plasmoid (read: shiny widget). Everything. Well, except for the desktop itself and the panel, which are both plugins. But your icons, clock, taskbar, system tray, even your kicker menu, they're all plasmoids. Unfortunately, this means that deleting a plasmoided icon from your desktop doesn't delete the corresponding file from your desktop directory. To do that, you'll have to fire up the new file manager, Dolphin.
The other change you'll notice, though not as obvious, is a small "icon" in the upper-right of the screen, used for bringing up the "add widgets" dialogue. Strangely enough, the full splendor of plasmoids isn't shown by default; all the default plasmoids (other than your icons) are embedded in a panel at the bottom of the screen.
Oh, yeah, one other thing: the Oxygen theme. The KDE artwork team has come up with a new KWin theme, called Oxygen, which seems to be strangely Vista-esque. The Oxygen icons, however, are very nice and unique. To add a plasmoid to the desktop, open the "Add widgets" dialogue, find your plasmoid from the list, and drag it from the list to your desktop (or to the panel, if you wish). To remove a plasmoid from the desktop, simply hover over it and click the red X that pops up (if you don't see a red X, make sure your plasmoids aren't locked [right-click desktop->unlock widgets]). To remove a plasmoid from the panel, right-click the offending plasmoid and select "Remove this [plasmoid name]".

A right-click on the desktop, though not currently as robust as KDE3.x's, gives you the option to "Configure desktop...". This brings up a fairly simple dialogue that allows you to change wallpapers, wallpaper positioning, background color, and whether or not to show desktop icons. I've found that disabling the "Show icons" option simply closes all currently open icon plasmoids; anytime you add a file to your desktop directory, a trusty plasmoid pops up on your desktop for it.

I've also heard that Plasma has in-built compositing support. I wasn't able to get all the effects to work, and the ones I could get working weren't customizable to my liking. Thankfully, Compiz still works pretty perfectly.

Overall, it's a nice new desktop experience. It's a bit lacking in features at the moment, but that's because it's still in "beta mode"; the 4.0 feature cutoff left "a lot of 90% done stuff". The next release, 4.1, should bring a lot more functionality and customizability.

Additional links:
My January Desktop Screenshot
KDE 4.0.0 Emergency FAQ
KDE4 Visual Guide
Remove the KDE4 panel
LifeHacker: Design Your Own Desktop With KDE4

January 14, 2008

CSS trick - two background images

Add this post to Del.icio.us. Del.icio.us (0 saved)

Download Example

While using what I'm sure is my own idea of progressive enhancement on a web page, I came across an interesting situation: I wanted two background images, rather than one. My first background would be a general tiled image, to give the site's background a nice texture; the second a vertically-repeated image on the left-hand side, to be used in conjunction with a floating nav menu.

Now, while CSS3 is purported to support up to 8 background images -- no doubt to make rounded corners and other fancy borders easier for coders -- the problem is that, to the best of my knowledge, IE and FF don't yet support this feature. Besides that, IE6 and lower never will. And I'm not even sure this feature will be usable for what I want, anyway.

So, I had to have (ok, really, really wanted) the left-hand background, and, IMO, the page looked too bland without some texture on the general background. As I already had the structure of the page decided upon (and, as such, couldn't modify it for presentational purposes), I started looking at what I had to work with. There was obviously the body tag, but there was nothing much else to work with...besides the html tag itself.

I already had the vertical background applied to the body tag, so I started by removing the background color from body (so the html background could show through). I then applied the same background color and the new background image to the html tag:

html { background:#000 url("tiled.png"); } body { background:url("vertical.gif") repeat-y; background-position:75px top; }

And, whaddaya know, it worked! Unfortunately, it seems that declaring the html element's style in my CSS changes the basic behavior of the body element, making it more like a containing div. The result: there's a margin around the content, and the vertical background only goes to the end of the content. Yuck.

So, the first thing to do is fix the ugly margin. Easy enough: set body's margin to 0 , as well as body's padding for good measure. Next, fix body's background. Currently, the background stops at the end of the content area. Not a problem if the content causes the window to scroll, but not pretty if there's not enough content. I figure this should be easy enough to fix, just set body's height to 100%. This works well enough...in IE6. Strangely, FireFox 2 doesn't take so kindly to it. Changing the body's height to "auto" works alright, for both browsers, for overflowing content, but not for short content. A height of "auto" and a min-height of 100% works excellently in FireFox 2...but, again, IE6 doesn't know how to treat min-height. Good grief.

So, I enter the realm of CSS hacks. Using a min-height hack combined with advanced CSS selectors that aren't understood by IE6 and less, I combine the methods that worked for each browser into a series of rules that are "browser-filtered" - one browser uses one method, while another browser uses the next.

html { background:#000 url("tiled.png"); /* Height is 100%, so the body can be 100% */ height:100%; } body { background:url("vertical.gif") repeat-y; background-position:75px top; margin:0; padding:0; /* Height is 100%, so the tiled BG will tile all the way down the page, not just as far down as the page's content (when the content's height is less than the window's height) */ height:100%; } /* Hackety-hack-hack... FF2, with the above code, will only display the repeat-y image for as high as the window's viewport is; higher content (upon scrolling) will not have the bg. This "hack" makes the tiled background work properly in FF2. This type of "advanced selector" is not understood by IE6...dunno 'bout IE7. */ html>body { min-height:100%; height:auto; }

The common html code works fine on both browsers. It's only the body's height issue that needs resolved. The IE6 code is given in the body code; both browsers will see this and understand it. However, when they get to the html>body statement, IE6 says "wha??" and drops the rule, whereas FF2 says "ok..." and applies the appropriate styles to the body tag, overriding the earlier-mentioned height.