Introduction

The TagDirectory template creates a multi-column display of a list of pages based on their tags.  The directory can include all non-prefixed tag or only those with a given prefix (e.g. "category:dog").  The TagDirectory uses the ListPages template to list each tag group.  The caller can specify the options used by ListPages for full control on how the results are displayed.

History

Version Date Author Description
1.0 6/09/2009 SteveB first version
1.1 9/29/2009 SteveB fixed an issue with not showing untagged pages as "(unclassified)"

Requirements

  • This template requires MindTouch version 9.02
  • This template requires the ListPages template

How do I install it?

  1. Create a template, call it "Template:TagDirectory" (or rename as you desire).  You must have UNSAFECONTENT permission for this to work.
  2. Create a "DekiScript" block on the template page (use the "Style" menu in the editor")
  3. Copy the code from the end of this page and paste it into the DekiScript block.  To copy, click "expand source", then mouse over the top right corner of the source code, and click the "view source" button.  This will pop up a window with the source code.  Select all, then copy to clipboard.
  4. Make sure there isn't an extra blank paragraph after the DekiScript block! Do this every time you edit!!!  
  5. Save.

 

A quick note about the examples on this page

For all the examples on this page, the code is shown before the working example.  The code is shown with the syntax extension, and looks like this:

TagDirectory()

This means that the actual code on the page should be enclosed in a DekiScript block.  If you want to copy the code from this page, then use the same procedure as described in steps 2-4 above. 

How do I use it?

 

Arguments

Name
Type
Default
Description
pages map/list/str subpages of current page List or map of pages to show in the list.  If the parameter is of type str, then it is used as the parent page of the pages to list.
tagPrefix str only unprefixed tags Only use tags with given prefix (e.g. 'category:dog').  The prefix is automatically stripped.
columnCount num 2 Number of columns to display.
listPagesOptions map { sort: 'viewcount', reverse: true, style: 'bullets' } Options passed into the ListPages template for listing each column entry.

Examples

Show the 10 most popular pages for each tag prefixed with "type:".

TagDirectory{ pages: 'Deki/Extensions', tagPrefix: 'type', columnCount: 3, listPagesOptions: { limit: 10 }}
App
Php
Script
(Unclassified)
Native
Embed
Template

 

Reference(s)

 

Credits/Special Thanks

 

Template/Extension Source Code

/***
    USAGE:

    TagDirectory(pages, tagPrefix, columnCount, listPagesOptions) 
        build a multi-column tag directory for a list of pages

    PARAMETERS:

    (optional) pages : list/map/str
        list/map of pages to list; if pages is a str, then it is used as a path to a parent page to list all subpages; 
        defaults to list of subpages of current page

    (optional) tagPrefix : str
        only use tags with given prefix (e.g. 'category:dog'); defaults to using only unprefixed tags

    (optional) columnCount : num
        number of columns to display; defaults to 2

    (optional) listPagesOptions : map
        options passed into the ListPages template for listing each column entry; 
        defaults to { sort: 'viewcount', reverse: true, style: 'bullets' }

***/

var pages = $0 ?? $pages ?? page.subpages;
if(pages is str) let pages = wiki.getpage(pages).subpages;
if(pages is map) let pages = map.values(pages);
var tagprefix = $1 ?? $tagprefix;
var columns = num.max($2 ?? $columnCount ?? 2, 1);
var listPagesOptions = { sort: 'viewcount', reverse: true, style: 'bullets' } .. ($4 ?? $listPagesOptions ?? { });

// build map of all tags in pages
var tagmap = { }; 
foreach(var p in pages) { 
    var tags = p.tags; 

    // check if page has no tags; if so make up a default list
    if(!#tags) {
        let tags = [ { name: (tagprefix ? tagprefix .. ':' : '') .. '(unclassified)', type: 'text' } ];
    }

    // for each tag on the page, append the page to that tag's list
    foreach(var t in tags where t.type == 'text') {

        // check if either the tag prefix matches or there is no tag prefix
        var parts = string.split(t.name, ':', 2);
        if(tagprefix && (#parts == 2) && (string.compare(parts[0], tagprefix, true) == 0)) {
            let tagmap ..= { (parts[1]) : tagmap[parts[1]] .. [ p ] };
        } else if(!tagprefix && (#parts == 1)) {
            let tagmap ..= { (parts[0]) : tagmap[parts[0]] .. [ p ] };
        }
    } 
}

if(#tagmap) {

    // count how many pages each tag has
    var tag_count = [ { tag: tag, count: #tagmap[tag] } foreach var tag in map.keys(tagmap) ]; 

    // balance columns so that their heights are as equal as possible
    var column_tags = list.new(columns, [ ]);
    var column_sums = list.new(columns, 0);

    foreach(var t in list.sort(tag_count, 'count', true)) { 

        // find shortest column
        var column = list.indexof(column_sums, list.min(column_sums));

        // update column
        let column_tags = list.splice(column_tags, column) .. [ column_tags[column] .. [ t.tag ] ] .. list.splice(column_tags, 0, column + 1);
        let column_sums = list.splice(column_sums, column) .. [ column_sums[column] + (listPagesOptions.limit ?? t.count) + 2 ] .. list.splice(column_sums, 0, column + 1);
    }

    // emit the table with N columns
    <table width="100%" cellspacing="0" cellpadding="5" border="0" style="table-layout: fixed;">
        <tr valign="top">

            // loop over each column
            foreach(var column in column_tags) {
                <td style="padding-right: 20px;">

                    // loop over all tags in column, sorted alphabetically
                    foreach(var tag in list.sort(column)) {
                        <h5> string.tocamelcase(tag) </h5>
                        template("ListPages", listPagesOptions .. { pages: tagmap[tag] });
                    }
                </td>
            }
        </tr>
    </table>
}

 

Disclaimers

None.

Tag page (Edit tags)
Viewing 5 of 5 comments: view all
Hello,

Thanks for this feature :-)

How can I get a list of all tags on my site ? Take all tags (all recursive)

Thanks
Posted 08:52, 18 Feb 2010
@dranakan This template doesn't support that. You'd have use to modify it to use site.tags, which gives a list of all tags without needing to load all pages ahead of time (much, much faster).
Posted 12:26, 18 Feb 2010
Thanks SteveB,

Bad but fast : replace line 34 "foreach(var p in pages) { " by " foreach(var p in wiki.getsearch('type:wiki',10000)) {"
This is bad code (using site.tags should be better)
Posted 13:22, 18 Feb 2010
so is it possible to simply create a list that shows pages with a specific tag? edited 03:05, 5 Mar 2010
Posted 03:04, 5 Mar 2010
@kochm yes, you can feed in an arbitrary list of pages using wiki.getsearch()
Posted 12:14, 5 Mar 2010
Viewing 5 of 5 comments: view all
You must login to post a comment.