murklinstest (murklinstest) wrote,
murklinstest
murklinstest

Flexible Squares: Multilevel Tags with Catch-All

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 = """<a rel="tag" href="$t.url">$tier</a>""";
            if ($show_count) {
              $tier_code = $tier_code + """&nbsp;${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 + """<li class="sbaritem">$tier_code""";                  
              $closing_html[$pos] = "</li>";  
              $list_started = true;
            }
            else {
              $list = $list + """<ul><li class="sbaritem">$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 = 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 + """<ul><li class="sbaritem">$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="sbaritem">$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 + """<li class="sbaritem"><a rel="tag" href="$t.url">$t.name</a>""";
      if ($show_count) {
        $catchall_list = $catchall_list + """&nbsp;${pre_count}${t.use_count}${post_count}""";
      }
      $catchall_list = $catchall_list + "</li>";
    }
    if ($catchall_list != "" and $catchall_title != "") {
      $catchall_list = """<li class="sbaritem">$catchall_title<ul>""" + $catchall_list + "</ul></li>";
    }
    $list = $list + $catchall_list;

    var string list_title = ($*text_sidebar_tags != "") ? "<li class='sbartitle'>$*text_sidebar_tags</li>" : "";
    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 = """<a rel="tag" href="$t.url">$tier</a>""";
            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 + """<li>$tier_code""";                  
              $closing_html[$pos] = "</li>";  
            }
            else {
              $list = $list + """<ul><li>$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 = 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 + """<ul><li>$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>$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 + """<li><a rel="tag" href="$t.url">$t.name</a>""";
      if ($show_count) {
        var string uses = get_plural_phrase($t.use_count, "text_tag_uses");
        $catchall_list = $catchall_list + """ - $uses""";
      }
      $catchall_list = $catchall_list + "</li>";
    }    
    if ($catchall_list != "" and $catchall_title != "") {
      $catchall_list = """<li class="sbaritem">$catchall_title<ul>""" + $catchall_list + "</ul></li>";
    }
    $list = $list + $catchall_list;
  }

#### Print the tag list in an entry-like post ####
			             
	print """
	<div class="subcontent">
                <div class="datesubject">
				<div class="subject">
					$page_title
				</div>
			</div>
		<div class="entry">
			<div class="entry2">
			<div class="entry_text">
			<ul class="ljtaglist">$list</ul>			
                        </div>
                    </div>
		</div>
		<div class="separator"> &nbsp; </div>
		<div class="clear"> &nbsp; </div>
	</div>
	""";
}
Tags: code:tagsbox:multi-level, layout:flexiblesquares
Subscribe

  • Post a new comment

    Error

    default userpic
    When you submit the form an invisible reCAPTCHA check will be performed.
    You must follow the Privacy Policy and Google Terms of use.
  • 4 comments