Flexible Squares: Multilevel Tags with Catch-All

Feb 05, 2007 00:14

Sidebar

function print_sidebar_tags() {

##### Config #####

# Specify your delimiter. One char only -- extra chars get truncated.
var string delimiter = ":";

# Do you want to show the tag use counts? Set to true or false.
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 = "]";

# Specify the name of your catch-all pseudo-category. If you set this to an empty
# string, top-level tags that have no sub-tags get tagged on to the end of the list
# and sit at the top level instead of sitting under a catch-all category.
var string catchall_title = "miscellaneous";

##### 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 TagDetail[] tag_list = $p->visible_tag_list();
var string[] closing_html;
var string[] prev_tags;
var int tag_list_pos = 0;
var bool list_started = false;
var string tier_code = "";
$closing_html[0] = "";
$prev_tags[0] = "";

# mt:20070204
# vars for new catchall pseudo-category
var TagDetail[] catchall;
var int catch_count = 0;
var string catchall_list = "";

foreach var TagDetail t ($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;

# mt:20070204
# Filter out all top-level tags that have no subtags so they can
# be placed in a catchall pseudo-category.
var bool no_subtags = true;
if ($tag_list_pos < (size $tag_list - 1)) {
var string next_tag = $tag_list[$tag_list_pos + 1].name;
var string tag_top = $tags[0] + $delimiter;
$no_subtags = not ($next_tag->starts_with($tag_top));
}

if (size $tags == 1 and $no_subtags) {
$catchall[$catch_count] = $t;
$catch_count = $catch_count + 1;
}
else {

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 = """ $tier""";
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.
if ($list_started == false) {
# mt:20061216
# The outermost ul is supplied later by print_sidebar_box,
# so omit it from this stage.
$list = $list + """
  • $tier_code""";
    $closing_html[$pos] = "
  • ";
    $list_started = true;
    }
    else {
    $list = $list + """
    • $tier_code""";
      $closing_html[$pos] = "
    ";
    }
    }
    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 = size $closing_html;
    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 + """
    • $tier_code""";
      $closing_html[$pos] = "
    ";
    }
    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 + """
  • $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;

    # mt:20070204
    # Build the catchall list.
    foreach var TagDetail t ($catchall) {
    $catchall_list = $catchall_list + """
  • $t.name""";
    if ($show_count) {
    $catchall_list = $catchall_list + """ ${pre_count}${t.use_count}${post_count}""";
    }
    $catchall_list = $catchall_list + "
  • ";
    }
    if ($catchall_list != "" and $catchall_title != "") {
    $catchall_list = """
  • $catchall_title
      """ + $catchall_list + "
  • ";
    }
    $list = $list + $catchall_list;

    var string list_title = ($*text_sidebar_tags != "") ? "
  • $*text_sidebar_tags
  • " : "";
    print_sidebar_box("""$list_title""", $list, "sidebar_tags");

    }
    }

    Tags Page

    function TagsPage::print_body {

    ##### Config #####

    # Specify your delimiter. One char only -- extra chars get truncated.
    var string delimiter = ":";

    # Do you want to show the tag use counts? Set to true or false.
    var bool show_count = true;

    # Specify the page title. Defaults to the core layer's value for
    # the Tags Page title. Change to your text, surrounded by quotes, eg:
    # var string page_title = "My Tags List";
    var string page_title = $*text_tags_page_header;

    # Specify the name of your catch-all pseudo-category. If you set this to an empty
    # string, top-level tags that have no sub-tags get tagged on to the end of the list
    # and sit at the top level instead of sitting under a catch-all category.
    var string catchall_title = "miscellaneous";

    ##### End Config #####

    var string list = "";

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

    var TagDetail[] tag_list = $this->visible_tag_list();
    var string[] closing_html;
    var string[] prev_tags;
    var int tag_list_pos = 0;
    var bool list_started = false;
    var string tier_code = "";
    $closing_html[0] = "";
    $prev_tags[0] = "";

    # mt:20070204
    # vars for catchall pseudo-category
    var TagDetail[] catchall;
    var int catch_count = 0;
    var string catchall_list = "";

    foreach var TagDetail t ($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;

    # mt:20070204
    # Filter out all top-level tags that have no subtags so they can
    # be placed in a catchall pseudo-category.
    var bool no_subtags = true;
    if ($tag_list_pos < (size $tag_list - 1)) {
    var string next_tag = $tag_list[$tag_list_pos + 1].name;
    var string tag_top = $tags[0] + $delimiter;
    $no_subtags = not ($next_tag->starts_with($tag_top));
    }

    if (size $tags == 1 and $no_subtags) {
    $catchall[$catch_count] = $t;
    $catch_count = $catch_count + 1;
    }
    else {

    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 = """ $tier""";
    if ($show_count) {
    var string uses = get_plural_phrase($t.use_count, "text_tag_uses");
    $tier_code = $tier_code + """ - $uses""";
    }
    }
    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.
    if (($tag_list_pos == 0) and ($pos == 0)) {
    # mt:20061216
    # The outermost ul is supplied later so omit it from this stage.
    $list = $list + """
  • $tier_code""";
    $closing_html[$pos] = "
  • ";
    }
    else {
    $list = $list + """
    • $tier_code""";
      $closing_html[$pos] = "
    ";
    }
    }
    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 = size $closing_html;
    $i = ($i <= 0) ? 0 : $i - 1;
    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 + """
    • $tier_code""";
      $closing_html[$pos] = "
    ";
    }
    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 + """
  • $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;

    # mt:20070204
    # Build the catchall list.
    foreach var TagDetail t ($catchall) {
    $catchall_list = $catchall_list + """
  • $t.name""";
    if ($show_count) {
    var string uses = get_plural_phrase($t.use_count, "text_tag_uses");
    $catchall_list = $catchall_list + """ - $uses""";
    }
    $catchall_list = $catchall_list + "
  • ";
    }
    if ($catchall_list != "" and $catchall_title != "") {
    $catchall_list = """
  • $catchall_title
      """ + $catchall_list + "
  • ";
    }
    $list = $list + $catchall_list;
    }

    #### Print the tag list in an entry-like post ####

    print """

    $page_title

      $list


    """;
    }

    layout:flexiblesquares, code:tagsbox:multi-level

    Previous post Next post
    Up