Template:TestSiteTagCloud

    Table of contents
    No headers

     

    // SiteTagCloud template, by neilw and maphew, 2009
    // Versions
    //    1.0.0    10/06/09    neilw    Quick hack based on maphew's TagCloud template
    //    1.0.1    11/05/09    neilw    Small bug fix
    //    1.1.0    11/06/09    neilw    Refactored arguments, added "align" arg and error messages
    //
    // This template is derived from maphew's TagCloud template.  It is optimized (and solely dedicated
    // to) providing a tag cloud for an entire site; performance is reasonable even with a large number
    // of tags on the site.  I have refactored the way the arguments work to my own taste, and also
    // added extensive error checking and reporting on the args.
    //
    // USAGE: SiteTagCloud( order, max, color, size, sizeUnits, exclude, showCount, align );
    //    order: str (valid values: "name" or "count") (default "count")
    //        Specifies how the tags are sorted in the list
    //    max: num (default:50)
    //        Specifies the maximum number of tags to be displayed.  0 ==> show all tags
    //    color: list (default: [ [50,200,50], [50,100,50] ])
    //        Specifies the color range for displayed tags.  May be either a single list of [r,g,b]
    //        (in which case all tags will be that color) or a list of two [r,b,g] lists, where tags
    //        with the fewest occurrences will be shown in the first color, and tags with the most
    //        occurrences will be shown with the second color.  Other numbers of occurrences will be
    //        interpolated between the two.
    //    size: num or list (default: [80,240])
    //        Specifies the size range for displayed tags.  If a single number is specified, all tags
    //        will shown in that size.  If a list of two numbers is specified, then the tags with fewest
    //        occurrences will be shown in the first size, and those with the most will be shown in the 
    //        second.  Others will be interpolated in between.
    //    sizeUnits: str (default: "%")
    //        CSS units for the size argument.
    //    exclude: str or list (default: [])
    //        Tag(s) to exclude from the cloud.  May be either a single tag given as a string, or a
    //        list of tags given as a list of strings.
    //    align: str (default: "left")
    //        Specifies the text alignment for the tag cloud.  Standard CSS values are available.
    
    var errors = [];
    
    //**************
    // Process Args
    //**************
    
    // order
    var defaultOrder = "name";
    var tagOrder = string.tolower($0 ?? $order ?? defaultOrder);
    if (tagOrder != "name" && tagOrder != "count") {
        let errors ..= [ "ORDER must be either 'name' or 'count' (using default)" ];
        let tagOrder = defaultOrder;
    }
    // max
    var defaultMax = 50;
    var tagsLimit = $1 ?? $max ?? defaultMax;
    if (tagsLimit is not num || tagsLimit < 0) {
        let errors ..= [ "MAX must be a number >= 0 (using default)" ];
        let tagsLimit = defaultMax;
    }
    // color
    var defaultColor = [ [50,200,50], [50,100,50] ];
    var color = $2 ?? $color ?? defaultColor;
    if (color is list && #color == 3) let color = [ color,color ];
    if (color is not list || #color != 2 ||
        color[0] is not list || #color[0] != 3 || color[1] is not list || #color[1] != 3 ||
        #list.select(color[0]..color[1], "$ is not num || $ < 0 || $ > 255"))
    {
        let errors ..= [ "COLOR must be a list of 3 numbers, or list of two lists of three numbers;" ..
                       " each number must be in the range 0-255 (using default)" ];
        let color = defaultColor;
    }
    // size and sizeUnits (processing these together)
    var defaultSize = [ 80,240 ];
    var defaultUnits = "%";
    var sizeMinMax = $3 ?? $size      ?? defaultSize ;
    var sizeUnits  = $4 ?? $sizeUnits ?? defaultUnits;
    if (sizeMinMax is num) let sizeMinMax = [ sizeMinMax, sizeMinMax ];
    if (sizeMinMax is not list || sizeMinMax[0] is not num ||sizeMinMax[1] is not num) {
        let errors ..= [ "SIZE must be a number or list of two numbers (using default)" ];
        let sizeMinMax = defaultSize;
        let sizeUnits  = defaultUnits;
    }
    // exclude
    var defaultExclude = [];
    var tagsToExclude = $5 ?? $exclude ?? defaultExclude;
    if (tagsToExclude is str) let tagsToExclude = [ tagsToExclude ];
    if (tagsToExclude is not list) {
        let errors ..= [ "EXCLUDE must be a string or list of strings (using default)" ];
        let tagsToExclude = defaultExclude;
    }
    // showcount
    var hitShow = $6 ?? $showCount ?? false;
    // align
    var align = $7 ?? $align ?? "left";
    
    // bail out if errors, to give quick feedback
    if (#errors)
        <div style="color:red">
            <strong> "SiteTagCloud encountered errors:" </strong>;
            <ul> foreach (var e in errors) <li> e </li>; </ul>;
        </div>;
    else {
    //****************************************
    // Pre-process font size and color values
    //****************************************
    var minSize = sizeMinMax[0];
    var sizeRange = sizeMinMax[1] - minSize;
    var colorMin =   { r:color[0][0], g:color[0][1], b:color[0][2] };
    var colorRange = { r:color[1][0]-colorMin.r, g:color[1][1]-colorMin.g, b:color[1][2]-colorMin.b };
    //******************
    // Process the tags
    //******************
    // convert list of excluded tags into a map (easier to check if tag is excluded)
    let tagsToExclude = { (t): true foreach var t in tagsToExclude };
    // compute map of tags based on site data and excluded tags
    var tagMap = {};
    foreach (var t in site.tags) {
        var tag = string.startswith(t.name, "define:") ? string.substr(t.name, 7) : t.name;
        let tagMap ..= { (tag) : #t.pages + (tagMap[tag] ?? 0) };
    }
    // compute list of tags sorted by occurrence count
    var tagListofMaps = [ { name: string.tocamelcase(t), count: tagMap[t] }
        foreach var t in map.keys(tagMap) where tagMap[t] > 0 ];
    var tagsTotal = #tagListofMaps;
    let tagListofMaps = list.sort(tagListofMaps, 'count', true);
    if ((tagsLimit > 0) && !__request.args.alltags)
        let tagListofMaps = list.splice(tagListofMaps, tagsLimit);
    // pre-calculate some shortcut variables
    var maxValue = tagListofMaps[0].count;
    var minValue = tagListofMaps[#tagListofMaps-1].count;
    var minLog   = num.log(minValue);
    var logRange = num.log(maxValue) - minLog;
    // sort display of tags by frequency or name
    let tagListofMaps = list.sort(tagListofMaps, tagOrder, (tagOrder == "count"));
    //****************
    // emit tag cloud
    //****************
    <div id="tagCloud">
        <div style=("text-align:" .. align)>
            foreach (var tm in tagListofMaps) {
                var tagURI = site.uri & "Special:Tags" & { tag:tm.name };
                var weight = ( num.log(tm.count) - minLog ) / logRange;
                var size   = minSize + num.round(sizeRange * weight);
                var color = "color:rgb(" ..
                    num.min(colorMin.r + num.round(weight*colorRange.r),255) .. "," ..
                    num.min(colorMin.g + num.round(weight*colorRange.g),255) .. "," ..
                    num.min(colorMin.b + num.round(weight*colorRange.b),255) .. ");";
                <span style=("padding-right:5px; font-size:" .. size .. sizeUnits)>
                    <a href=(tagURI) style=(color)> tm.name </a>;
                    if (hitShow)
                        <sup style=(color.."font-size: x-small")> "(" .. tm.count .. ")" </sup>;
                    " ";
                </span>;
            }
        </div>;
        if (!__request.args.alltags && (tagsLimit > 0) && (tagsTotal > tagsLimit)) {
            "Showing top " .. tagsLimit .. " tags. ";
            <a href=((page.uri & { alltags: "_" }).."#tagCloud")> "See all "..tagsTotal.." tags »" </a>;
        }
    </div>;
    }
    
    Tag page
    You must login to post a comment.

    Copyright © 2011 MindTouch, Inc. Powered by