31 January 2007

'Don't-leave-the-page' labels widget

Onset of labels sure did kill off the greatest playground of hackers. No more hacking with Del.icio.us to get a list of posts tagged or 'labelled' under a particular category. So what do we do now? Find ways of making Blogger Labels asynchronous ofcourse. There are quite a few hacks out there that do this nicely, but I just had to do it my way :)

The hack

This little code creates an asynchronously loaded list of the posts classified under a particular label, sorted by last update time, and shows it right below it. You can see it in action in the sidebar on the right. Click on any one of the topics. It also removes the list if it's open, and you can open up more than one category at one time. I was experimenting with a few functions I made and DOM functions, so this should work in all modern browsers without too much hassles (I don't care about IE).

The elements are all lists, so you need to just create a CSS class for postList, and style it as you see fit. I haven't included code to show a 'Loading...' type message because this is quite fast, so many people won't get any lag time. I've managed to integrate it with the Blogger Labels widget, so you just need to make a little change to the widget code. Yes, you'll have to expand the widgets (sorry!).

The code

Wrap the following in <script> tags and put it in your <head> area:

//<![CDATA[
function $(){
  for( var i = 0, node; i < arguments.length; i++ )
    if( node = document.getElementById( arguments[i] ) )
      return node;
}

var _id = '';
function showLabel(name){
    _id = name;
    if($(name+'-expanded')) {
    $(name+'-expanded').parentNode.removeChild($(name+'-expanded'));
    $(name).style.textDecoration = 'none';
        }
    else {
    $(name).style.textDecoration = 'underline';
    var script = document.createElement('script');
    script.src = 'http://<BLOGNAME>.blogspot.com/feeds/posts/summary/-/'+name+'?alt=json-in-script&callback=makeList';
    script.type = 'text/javascript';
    
    document.getElementsByTagName('head')[0].appendChild(script);
    }
}

function makeList(json){
var d = document.getElementById('Label1');
var i=0, j=json.feed.entry[i];
var list = document.createElement('ul');
list.id = _id+'-expanded';
list.setAttribute('class','postList');
var frag = document.createDocumentFragment();

  while(i<json.feed.entry.length){
    j=json.feed.entry[i];
     var t_link = document.createElement('a');
         t_link.href = j.link[0].href;
    if(j.title.$t.length>37)
        t_link.appendChild(document.createTextNode((j.title.$t).slice(0,37)+'...'));
    else 
        t_link.appendChild(document.createTextNode(j.title.$t));

      var title = document.createElement('span');
     title.setAttribute('class','postTitle');
         title.appendChild(t_link);

    var li = document.createElement('li');
    li.appendChild(title);      
    frag.appendChild(li);
    i++;
      }
    list.appendChild(frag);
    $(_id).parentNode.insertBefore(list, $(_id).nextSibling);    
}
//]]>

All you need to do is replace the <BLOGNAME> with the name of your blog. I'll explain the various parts of it at the end, so that you can change it to suit your needs. The next bit of code is where it gets a little ugly. Expand the template, and then go looking for your Labels widget. Once you find it, replace the entire widget with this code:

<b:widget id='Label1' locked='false' title='Topics' type='Label'>
<b:includable id='main'>
  <b:if cond='data:title'>
    <h2><data:title/></h2>
  </b:if>
  <div class='widget-content'>
    <ul class='elegantList'>
    <b:loop values='data:labels' var='label'>
      <li expr:id='data:label.name'>
        <b:if cond='data:blog.url == data:label.url'>
          <data:label.name/>
        <b:else/>
          <a href='#category' onclick='javascript:showLabel(this.innerHTML)'><data:label.name/></a>
        </b:if>
        (<data:label.count/>)
      </li>
    </b:loop>
    </ul>

    <b:include name='quickedit'/>
  </div>
</b:includable>
</b:widget>

Do this only if you're widget hasn't been tinkered away from the default Blogger widget, which should be the case in most of the situations. That's it, you're done! :) Reap the benefits!

Explanation and further tinkering

This uses the dynamic script tag method to get a list of posts from the label feed. It then proceeds to form a list out of the post titles, and then using my home-made method of inserting a node, puts the list after the node specified by the 'id' of the parent node of the clicked link.

It also slices the post title to keep in within 40 characters, so that it doesn't wrap to the next line and take up unnecessary lines in your sidebar. You can change this by changing the '37' in the if statement, and line following it. However, this number should satisfy most cases. To style the list, as I said before, define a CSS class for ul.postList and then proceed to style the lis under this.

Once again, this will not work on a preview page, so you'll have to save it and then test it. I hope you get it working without too many hassles!


15 comments

Unknown said...

Bravo! You managed to use DOM! Now if you just add the "Hierarchy" archives-like expand/collapse arrows...

IE7 aborts and gives up while opening your blog. Maybe you can sense that it is IE and avoid expanding inline.

Anonymous said...

wow, that's nice. But can you add some "loading..." ajax stuff? I mean the one Deepak hass made. That would be nice... ;)

Aditya said...

Why need the arrows? I already underline opened topics :) I think it's aesthetically more pleasing.

I could do that, but making it open up the link rather than the list will take a little more coding. I'm sitting a little lazy after a whole day of coding out two things :P

I'll look into it nonetheless.

Aditya said...

@Cyberbuff: I haven't included code to show a 'Loading...' type message because this is quite fast, so many people won't get any lag time :)

Deepak said...

That's a good place to display the asynchronous results :)

I have a suggestion. You can give a snippet of each post as hovering tooltip in the sidebar. It won't be much of an overhead, since you already acquired the JSON object.

BTW, this is quite fast now. But it will be slower for people with dialup connection (there still are a major chunk of them, if my stats don't lie), and when your number of posts per category grows.

Aditya said...

That's a good suggestion. But there is one tiny problem. Firefox truncates long titles in links, so I'll have to come up with custom tooltips for links to it to work (ala Netvibes). I'll work on it though :)

When it does start to get slow for me (I have a 128 Kbps connection at college), I'll add in the 'Loading...' message. That's the most I can do!

Anonymous said...

Nice job. I was pondering myself whether to load the titles in the sidebar or not, but since I'm stuck with a cloud whether I like it or not, I went ahead and chose to load everything in the main section. So I guess my implementation looks more like Deepak's.

Ah, but isn't it nice having all the json to play with? :-D

Another great hack from the Young Gun.

Aditya said...

It won't be that hard to modify the function to suit your label-cloud-fetish-yet-asynchronous needs. I could do it if you're interested :)

Shoot me a mail if you are!

GG said...

please add the "Hierarchy" archives-like expand/collapse arrows~~it will be good looking more!

and if you the article more than 100,or even more ,it will slow down a lot...can you please add a loading just like the "Hierarchy"s loading?

GG said...

can you make the result shows in the other place?just like deepak's ajax-labels

it will be more useful and more amazing!

please~~please do it!it will be so nice!

Aditya said...

Ok, I've added the zippy-toggly things to the label names. I've also added a loading image.

However, if you would like your labels to show up in a different place, I'll suggest you modify Deepak's hack. Mine was specifically written to show up in the widget, under the label as a list :)

GG said...

Deepak's hack is't work if the lables
are write by chinese word in IE.

and you hack is smaller and faster.

I'm so exciting about you great work,the hack can undoubted to take the place of original blogger function.can't wait to add on all of my blog.

but it seems Deepak's hack at some point more conform peoples habit.so if you can make the lables result shows in a different place it will be so nice:):-$

my english are very pool ,may be hard to understand .sorry:)

Deepak said...

@GG: The Chinese in IE is a known problem which will be fixed in my next version of AJAX Labels. (IE doesn't handle UTF-8 properly.)
I have the fix ready, but it will be at least a week until I release "AJAX Labels Reloaded" :)

I can help you with a quick fix till then, if you want.

Aditya said...

Haha! Deepak's way of loading the labels' posts is actually based off my very first categories hack (as he mentions it in the post). I don't know which method people prefer, but I'm sticking to the core idea behind this hack. This wasn't meant to replaces Deepak's, and it will not.

Deepak's shown up as well! :) So there, your problem will be solved soon! My hack still stands updated though ;)

Cheers!

GG said...

so many thanks for both of you:-D

can't wait to see you excellent work.

both of you:-)

you really make the blogger more and more useful ,attraction~~