Mister Baltimore (av8rmike) wrote in s2expressive,
Mister Baltimore
av8rmike
s2expressive

Multi-level Tags in Sidebar

This function changes the display of tags in the sidebar into a hierarchical table. In order for it to work, tags must have one or more delimiter in them. For example, you will have to have entries tagged like "animals:pets:cats", "animals:pets:dogs", "cars:toyota", "icons:buffy", "fanfic:harry potter" and so forth. This code will display the tags in a nested unordered list. Original code for Flexible Squares by murklins, so if something isn't working, talk to her. ;)

Instructions: First create your theme layer, if you don't have one already. Copy and paste the code into the layer, and add the following into the Custom CSS section of the Customization area:
.categories-widget .widget-list .item {margin: 0 0 0 20px;}
The variables in blue can be customized to change the delimiter in the tags or to display the tag count.

function print_module_tags(string title) {

#####   Config   #####
  # Specify your delimiter.  One char only -- extra chars get truncated.
  var string delimiter = ":";
  # Do you want to show the tag use counts?
  var bool show_count = true;
  # Specify the text to show just before the use count, if any
  var string pre_count = "[";
  # Specify the text to show just after the use count, if any
  var string post_count = "]";
##### End Config #####

  var Page p = get_page();
  var string list = "";

  if (size $p->visible_tag_list() > 0) {
    if ($delimiter->length() > 1) {
      $delimiter = $delimiter->substr(0, 1);
    }

    var string[] closing_html;
    var string[] prev_tags;
    var int tag_list_pos = 0;
    var string tier_code = "";
    $closing_html[0] = "";
    $prev_tags[0] = "";
    foreach var TagDetail t ($p->visible_tag_list()) {
      var string[] tags;

      if ($t.name) {
        # mt:20050623
        # Split tags into array on delimiter. Oh god, my kingdom
        # for a function.  Stolen shamelessly from lj-user rane500.
        var int array_counter = 0;
        var string buffer = "";
        foreach var string char ($t.name) {
          if($char == $delimiter) {
            $tags[$array_counter] = $buffer;
            $array_counter = $array_counter + 1;
            $buffer = "";
          }
          else {
            $buffer = $buffer + $char;
          }
        }
        $tags[$array_counter] = $buffer;

        var int pos = 0;
        foreach var string tier($tags) {
          if (size $closing_html <= $pos) {
            # mt:20050623
            # $closing_html keeps track of html that is used to close off open
            # lists.  Its length must be kept >= to that of the current tag.
            $closing_html[$pos] = "";
          }

          if (size $prev_tags <= $pos) {
            # mt:20050625
            # The current tag has more tiers than the previous tag.  To avoid array
            # ref errors when comparing the current tier to the previous one (which
            # is non-existent, of course) add empty string to $prev_tags.
            $prev_tags[$pos] = "";
          }

          # mt:20050623
          # If we're on a tag's last tier, we need to return a link to the tag,
          # otherwise plain text is returned.
          if (size $tags == ($pos + 1)) {
            $tier_code = """<a href="$t.url">$tier</a>""";
            if ($show_count) {
              $tier_code = $tier_code + """ ${pre_count}${t.use_count}${post_count}""";
            }
          }
          else {
            $tier_code = """$tier""";
          }

          # mt:20050625
          # $prev_tags stuffed with dummy empty string when it has fewer tiers than
          # current tag.
          if ($prev_tags[$pos] == "") {
            # mt:20050623
            # The current tag has more tiers than the previous tag, so a new
            # list must be opened.
            $list = $list + """<ul class="widget-list"><li class="item">$tier_code""";
            $closing_html[$pos] = "</li></ul>";
          }
          elseif ($tags[$pos] != $prev_tags[$pos]) {
            # mt:20050623
            # The current tag's tier is not the same as the previous tag's tier of
            # the same level.  This means we may need to close some lists.
            var int i = 0;
            foreach var string html ($closing_html) {
              if ($i > $pos) {
                $list = $list + $closing_html[$i];
                # mt:20050623: As we append the closing code, pop it off the array.
                $closing_html[$i] = "";
              }
              $i++;
            }

            if ($closing_html[$pos] == "") {
              # mt:20050623
              # This is the first tier at this level, so open list.
              $list = $list + """<ul class="widget-list"><li class="item">$tier_code""";
              $closing_html[$pos] = "</li></ul>";
            }
            else {
              # mt:20050623
              # There have already been tiers added at this level, so just close the previous
              # list item before adding the new tier.
              $list = $list + """</li><li class="item">$tier_code""";
            }
          }
          else {
            # mt:20050623
            # The current tag's tier is exactly the same as the previous tag's tier at
            # this same level.  It has already been included in the list, so do nothing.
          }
          # mt:20050623: Moving on to next tier in this tag!
          $pos++;
        }
        $prev_tags = $tags;
      }
      # mt:20050623: Next tag in the list!
      $tag_list_pos++;
    }

    # mt:20050623
    # All the tags have been added so close all outstanding lists.
    var int i = 0;
    var string remaining_html = "";
    foreach var string html ($closing_html) {
      if ($html != "") {
        $remaining_html = $html + $remaining_html;
        $closing_html[$i] = "";
      }
      $i++;
    }
    $list = $list + $remaining_html;
  }

  open_module("categories", $title, "");
  print """$list""";
  var string tags_url = $p.journal->base_url() + "/tag/"; # TODO: Need Page.view_url{"tags"} which doesn't exist yet.
  print """<div class="widget-footer"><a href="$tags_url" title="$*text_sidebar_tags">$*text_sidebar_tags</a></div>\n""";
  close_module();
}
Hit "Save and Compile", ensuring that the code compiles correctly (i.e., without errors).
Set your just-compiled theme layer to be the active one from the Choose Journal Style page by clicking on "Your Custom Layers" in the left sidebar, then selecting "Apply Theme" under the appropriate layer.

Here is a sample image, using grrliz_icons's journal as an example:

A worthwhile modification to the function would be to print the tag tree in the tags page instead of (or in addition to) in the sidebar. The method would be similar to this one for a tag cloud on the tags page.
Tags: !tutorial, $acct level:paid or perm, advanced, how to:instructions, s2:theme layer, sidebar:tags
Subscribe
  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your reply will be screened

  • 45 comments