Where magic lives

Monday, November 13, 2006

Blogger Beta Label Cloud

I have just upgraded to Blogger Beta. I love that they have finally added support for labels, however I cannot get a list of my labels to appear in my template. In fact I am not even getting the new WYSIWYG template editor that they are bragging about. I think it may be because I publish to my own server via FTP.

Anyway, I created a quick solution for the time being and am posting it hear in case anyone else has the same problem and wants to steal it:

This PHP code creates a label cloud (put it anywhere on the server you publish to via FTP and change the obvious constants):

Update 30 April 2007 to remove duplicate entries added by Blogger.

Now setup some mechanism whereby this file is included in your sidebar. A naive way would be to use an include() statement in your template and make your server parse .html files as PHP (e.g. by adding

AddType application/x-httpd-php .html
to a .htaccess file) but you are relying on Blogger correctly escaping any comments so malicious users cannot run arbitrary PHP code on your server. A better way is to introduce some keyword to your template and have code on your server scan for this keyword and overwrite the correct content. That is all beyond the scope of this post though.

You will notice that my code caches the cloud so that the labels directly does not get scanned on every single page view (just once per hour). For this to work your SEARCH_DIR must be writable by your web server. Also I am hoping that Blogger do not paginate label pages, if they do this will break my code, none of mine seem to be paginated though.

Labels:

14 Comments:

  • Hey David,

    I just googled and found your blog.

    I really love your idea and am going to try it.

    I'll let you know how it works out.

    By Anonymous Christoph, At 6:55 am  

  • Hi David!

    I've been working on your solution for displaying New Blogger labels in the sidebar of a PHP-powered blog. I have it up and running here.

    I chose not to use the tag cloud because it made some of my labels too small to read and it sorted them by how many posts I had assigned to each label not how important they are to the reader. I am using this code:

    <ul class="labels">
    <?php
      define('PREFIX', '/labeldirectory/');
      define('SEARCH_DIR',
        '/home/websiteaddress.net/labeldirectory/');
      define('THIS_FILE', 'cloud.php');
    if(file_exists(SEARCH_DIR.'_cloud_include_cache.html') &&
        filemtime(SEARCH_DIR.'_cloud_include_cache.html')>(time()-(60*60)))
          echo file_get_contents(SEARCH_DIR.'_cloud_include_cache.html');
      else
      {
        $output = '';
        $files = array();
        $dir = opendir(SEARCH_DIR);
        $max_size = -1; $min_size = -1;
        while($file = readdir($dir))
        if($file != '.' && $file != '..' && $file != THIS_FILE)
        {
          $files[$file] = filesize(SEARCH_DIR.$file);
          if($max_size==-1 || $max_size<$files[$file])
            $max_size = $files[$file];
          if($min_size==-1 || $min_size>$files[$file])
            $min_size = $files[$file];
        }
        closedir($dir);
        foreach($files as $name=>$size)
          $output .= "<li><span style='color:green'>----{-</span><span class='flower'>@</span>  <a href='".PREFIX.
            htmlentities($name)."'>".
            htmlentities(str_replace('.php','',$name))."</a></li> ";
        echo $output;
        $fp = fopen(SEARCH_DIR.'_cloud_include_cache.html','w');
        fwrite($fp, $output);
        fclose($fp);
      }
    ?>
    </ul>

    I like it a lot and I decided to upgrade to the New Blogger only after seeing your post on placing labels in the sidebar. I'm happy I did so.

    My one remaining concern is to sort the labels alphabetically so it's in a logical order and people can find the data they want easily especially as my label list grows. Plus, I think it looks much more professional.

    I'm very new to PHP and have only modified a few scripts. Do you have any suggestions on what I could do with this code to sort the labels by title?

    Thanks in advance...

    By Anonymous Christoph, At 3:04 am  

  • Christoph, you want something like:

    <ul class="labels">
    <?php
    define('PREFIX', '/labeldirectory/');
    define('SEARCH_DIR',
    '/home/websiteaddress.net/labeldirectory/');
    define('THIS_FILE', 'cloud.php');
    if(file_exists(SEARCH_DIR.'_cloud_include_cache.html') &&
    filemtime(SEARCH_DIR.'_cloud_include_cache.html')>(time()-(60*60)))
    echo file_get_contents(SEARCH_DIR.'_cloud_include_cache.html');
    else
    {
    $output = '';
    $files = array();
    $dir = opendir(SEARCH_DIR);
    while($file = readdir($dir))
    if($file != '.' && $file != '..' && $file != THIS_FILE)
    {
    $files[] = $file;
    }
    closedir($dir);
    asort($files);
    foreach($files as $name)
    $output .= "<li><span style='color:green'>----{-</span><span class='flower'>@</span> <a href='".PREFIX.
    htmlentities($name)."'>".
    htmlentities(str_replace('.php','',$name))."</a></li> ";
    echo $output;
    $fp = fopen(SEARCH_DIR.'_cloud_include_cache.html','w');
    fwrite($fp, $output);
    fclose($fp);
    }
    ?>
    </ul>

    (You are not using any of the filesize details so I removed them, which means the $files array now contains filenames as the values so you can pass it into asort() to sort it.)

    By Blogger David Nicholson, At 11:56 am  

  • Worked like a charm, David.

    Thank you for the elegant solution.

    By Anonymous Christoph, At 2:25 am  

  • Update: I enhanced the output with a bit of CSS to create a pop-out menu.

    I also think I may have found a bug. It seems to work with the original code too, not just my alteration. After leaving the page static for about an hour or more, then refreshing, it shows "cloud_include_cache.html" as one of the results in the Label list.

    That makes sense, I think, because it creates the file in the Labels directory.

    I removed all references to it in the script and it works flawlessly, but of course it must run the script on each page refresh now.

    It's such a lightweight script that I'm not overly concerned about it... just thought I'd let you know.

    By Blogger Christoph Dollis, At 12:26 pm  

  • Well spotted Christoph, I'd actually corrected this already on my blog a while back but forgot to upate the code on the post. I have now changed it above so you can get the caching behaviour back if you like.

    I like your CSS adaption, have you considered adding "display: block" to the style for your <a> tags in that popout? It will mean they will be clickable and the hover effect will work even when the mouse isn't directly over the text.

    By Blogger David Nicholson, At 1:44 pm  

  • Where can I get the correction for the script in the form of your recommendendation after "you want something like". I am still getting the _cloud_include... file appearing in my label list. You can see it at Blogger Guide to FTP Labels

    By Anonymous brauer, At 4:02 am  

  • brauer, you want something like this:

    <ul class="labels">
    <?php
    define('PREFIX', '/labeldirectory/');
    define('SEARCH_DIR', '/home/websiteaddress.net/labeldirectory/');
    define('THIS_FILE', 'cloud.php');
    define('CACHE_FILE', '_cloud_include_cache.html');

    if(file_exists(SEARCH_DIR.'_cloud_include_cache.html') &&
    filemtime(SEARCH_DIR.'_cloud_include_cache.html')>(time()-(60*60)))
    echo file_get_contents(SEARCH_DIR.'_cloud_include_cache.html');
    else
    {
    $output = '';
    $files = array();
    $dir = opendir(SEARCH_DIR);
    while($file = readdir($dir))
    if($file != '.' && $file != '..' && $file != THIS_FILE && $file != CACHE_FILE)
    {
    $files[] = $file;
    }
    closedir($dir);
    asort($files);
    foreach($files as $name)
    $output .= "<li><span style='color:green'>----{-</span><span class='flower'>@</span> <a href='".PREFIX.
    htmlentities($name)."'>".
    htmlentities(str_replace('.php','',$name))."</a></li> ";
    echo $output;
    $fp = fopen(SEARCH_DIR.'_cloud_include_cache.html','w');
    fwrite($fp, $output);
    fclose($fp);
    }
    ?>
    </ul>

    By Blogger David Nicholson, At 12:30 pm  

  • Dude! This is excellent. I had my blog on blogspot, but it is blocked in China, so I put it (back) on my domain. I would have liked a lil bit more info on what to change and how, but I figured it out. The font was a bit small, so I changed 100 -> 115. Simple enough. Check it out at my site. I was really happy to find your site because I love the concept of the tag cloud.

    By Blogger Beuk, At 6:29 am  

  • It appears that blogger has now started 'double publishing' any tags with spaces in them so that a second set is available using %20 rather than the space character. What line of code would you add to not include any labels that include %20 in their filename?

    By Blogger a d r, At 6:49 am  

  • a d r, please see the updated code above.

    By Blogger David Nicholson, At 9:57 pm  

  • Found your blog post and I've tried to enable the script. The file extensions of each label page are appearing in the output of the script. Any idea why this is happening?

    By Blogger Stephen Clark, At 4:53 am  

  • David, any chance you send show how to sort the cloud alphabetically (I see you showed this for a tweak on the code for Christoph previously, but I would need it for the cloud).

    THANKS SO MUCH!!!

    By Blogger Mooki, At 1:25 pm  

  • Hey, no need to post the question about Sorting the Cloud ALPHABETICALLY. Here is the code. Just add this line...

    ksort($files);

    after... closedir($dir);

    <?php

    define('PREFIX', '/labels/');

    define('SEARCH_DIR',

    '/home/httpd/vhosts/da.vidnicholson.com/httpdocs/labels/');

    define('THIS_FILE', 'cloud.php');



    if(file_exists(SEARCH_DIR.'_cloud_include_cache.html') &&

    filemtime(SEARCH_DIR.'_cloud_include_cache.html')>(time()-(60*60)))

    {

    echo file_get_contents(SEARCH_DIR.'_cloud_include_cache.html');

    }

    else

    {

    $output = '';

    $files = array();

    $dir = opendir(SEARCH_DIR);

    $max_size = -1; $min_size = -1;

    while($file = readdir($dir))

    {

    if($file != '.' && $file != '..' && $file != THIS_FILE && $file !=

    '_cloud_include_cache.html')

    {

    $files[$file] = filesize(SEARCH_DIR.$file);

    if($max_size==-1 || $max_size<$files[$file]) $max_size = $files[$file];

    if($min_size==-1 || $min_size>$files[$file]) $min_size = $files[$file];

    }

    }

    closedir($dir);

    ksort($files);

    $displayed = array();

    foreach($files as $name=>$size)

    {

    if(!isset($displayed[urldecode(str_replace('.html','',$name))]))

    {

    $displayed[urldecode(str_replace('.html','',$name))] = true;

    $output .= "<span style='margin: 3px; font-size: ".

    (10+round((1+(($size-((($max_size-$min_size)/2)+$min_size))/($max_size-$min_size)))*100)).

    "%;'><a href='".PREFIX.htmlentities($name)."'>".

    htmlentities(urldecode(str_replace('.html','',$name)))."</a></span> ";

    }

    }

    echo $output;

    $fp = fopen(SEARCH_DIR.'_cloud_include_cache.html','w');

    fwrite($fp, $output);

    fclose($fp);

    }

    ?>

    By Blogger Mooki, At 2:41 pm  

Post a Comment

Subscribe to Post Comments [Atom]



<$I18N$LinksToThisPost>:

Create a Link

<< Home