/*
    NAME:    TagListing
    AUTHOR:  Jay Allen, Textura Design
    DATE:    June 6, 2007
    VERSION: 1.0
    LICENSE: This code is licensed under the Artistic License
    
    SUMMARY:
    
        This library was developed to provide an easy method to output
        Movable Type entry tags using Javascript to prevent spiders from
        crawling the tag search links and kicking off CGI processes.
        
        In addition, it provides for customizable output through use of
        the DisplayTemplate library, which is a prerequisite.  See 
        http://texturadesign.com/scripts/displaytemplate.js for more
        information on that library.

    PROPERTIES:

        baseTagSearchURL - This convenience property allows you to specify the
                           base URL for your tag search without having to
                           define it for each tag listing or each tag.  This
                           can be set either directly for the object or anywhere
                           before creating the object (e.g. the <head> section)
                           through the baseTagSearchURL global variable.

        template - This property defines the template to be used in creating each
                   linked tag.  It contains the static markup for a linked tag
                   along with variable sections which are replaced by the value
                   of keys specified in the addtag() method. Alternately, you can
                   predefine this for all listings on a page through use of the
                   tagDisplayTemplate global variable.  The default is
                   '<a href="[baseTagSearchURL]?blog_id=[blogid]&tag=[tagquery]" rel="tag">[tagname]</a>'

        glue - This property defined the glue (if any) to be used between each
               linked tag.  You can predefine this for all listings using the
               tagDisplayGlue global variable.  The default is ", ".

        strict - This controls whether or not the DisplayTemplate "strict" mode
                 is enabled.  Please see that library's documentation for more
                 details.  The default is enabled (1)

        nocase - This controls whether or not the DisplayTemplate "nocase" mode
                 is enabled.  Please see that library's documentation for more
                 details.  The default is disabled (0) meaning case-sensitive keys.

        limit - This optional attribute limits the output of tags to the specified 
                value.  Default is no limit (0)

    METHODS:
    
        addtag - This method allows you to add a tag to a particular listing for
                 display. It takes as an argument a single object whose properties
                 and values define key/value pairs for string replacement in the
                 template in the compile() method.

        compile - This method takes all tags added through the addtag() method,
                  formats them for display using the specified template and
                  concatenates them together using the value of the glue property.
                  It returns the entire formatted string for display on the page.

        write - This convenience method calls the compile() method and then writes
                the result to the page automatically.
                
    EXAMPLE:

        An example using minimal code to achieve the same tag listing as a basic
        Movable Type installation.  This example would be placed within the 
        context of an entry:

            Tagged: 
            <script type="text/javascript" charset="utf-8">
                baseTagSearchURL = 'http://example.com/cgi-bin/mt/mt-search.cgi'
                var listing = new TagListing()
                <MTEntryTags>
                listing.addTag({tagquery:"<$MTTagName normalize="1"$>",tagname:"<$MTTagName encode_php="qq"$>",blogid:<$MTBlogID$>});
                </MTEntryTags>
                listing.write()
            </script>

        Here's a similar one but using MTTags and not within entry context:
        
            <p>Most popular tags on this blog:</p>
            <ul>
            <script type="text/javascript" charset="utf-8">
                var tagDisplayTemplate = '<li><a href="[baseTagSearchURL][tagquery]">[tagname]</a> <span>([count])</span></li>'
                var tagDisplayGlue = ""
                var listing = new TagListing()
                <MTTags sort_by="count">
                listing.addTag({tagquery:"<$MTTagName normalize="1"$>",tagname:"<$MTTagName encode_php="qq"$>",count:<$MTTagCount$>});
                </MTTags>
                listing.write()
            </script>
            </ul>
        
        A slightly longer example, not using any MT tags with some explanation
        and other variables.

            <script type="text/javascript" charset="utf-8">

            // Specify the base URL to use for this and subsequent tag listings
            // Can also be specified on a per-listing basis after the TagListing
            // is instantiated via TagListing.baseTagSearchURL
            var baseTagSearchURL = 'http://texturadesign.com/tag/'

            // Specify the tag link template to use for this and subsequent tag
            // listings.  Can also be specified on a per-listing basis after the
            // TagListing is instantiated via TagListing.template
            // The template below shows that we will be providing three variables
            // (tagquery, tagname and count) for each tag.
            var tagDisplayTemplate = '<li><a href="[baseTagSearchURL][tagquery]">[tagname]</a> <span>([count])</span></li>'

            // Specify the glue to use between the tags.  Because the default is
            // ", ", we must specifically override this if we don't want a
            // delimiter
            var tagDisplayGlue = ""

            // Instantiate the TagListing object
            var listing = new TagListing()

            // Add three arbitrary tags.  They will be output in this order
            listing.addTag({tagquery:"jayallen",tagname:"Jay Allen",count:22});
            listing.addTag({tagquery:"texturadesign",tagname:"Textura Design",count:12});
            listing.addTag({tagquery:"helloworld",tagname:"Hello World",count:8});

            // Just to demonstrate, limit the listing to only the first two
            listing.limit = 2
            
            listing.write()
            </script>

        The previous example put into the context of a stripped down index 
        template:
        
        <html>
        <head>
        <!-- Including the two script libraries -->
        <script type="text/javascript" src="/displaytemplate.js"></script>
        <script type="text/javascript" src="/taglisting.js"></script>

        <!-- Setting the global variables -->
        <script type="text/javascript" charset="utf-8">
            var baseTagSearchURL = 'http://texturadesign.com/tag/'
            var tagDisplayTemplate = '<li><a href="[baseTagSearchURL][tagquery]">[tagname]</a> <span>([count])</span></li>'
            var tagDisplayGlue = ""
        </script>
        </head>
        <body>
            <MTEntries>
            <h1><$MTEntryTitle$></h1>

            <MTEntryIfTagged>
                <p>Tags:</p>
                <ul>
                <script type="text/javascript" charset="utf-8">
                    var listing = new TagListing()
                    <MTEntryTags>
                    listing.addTag({tagquery:"<$MTTagName normalize="1"$>",tagname:"<$MTTagName encode_php="qq"$>",blogid:<$MTBlogID$>});
                    </MTEntryTags>
                    listing.write()
                </script>
                </ul>
            <MTElse>
                <p>Tags: <em>None</em></p>
            </MTElse>
            </MTEntryIfTagged>

            </MTEntries>
        </body>
        </html>
*/
function TagListing() {
    this.template = '<a href="[baseTagSearchURL]?blog_id=[blogid]&tag=[tagquery]" rel="tag">[tagname]</a>'
    this.glue = ", "
    this.strict = 1
    this.nocase = undefined
    this.limit = 0
    this.tags = new Array()


    if (window.baseTagSearchURL)   this.baseTagSearchURL = window.baseTagSearchURL
    if (window.tagDisplayTemplate !== undefined) this.template = window.tagDisplayTemplate
    if (window.tagDisplayGlue !== undefined)     this.glue = window.tagDisplayGlue
}

TagListing.prototype.addTag = function(tag) { this.tags[this.tags.length] = tag; }

TagListing.prototype.format = function(tag) {
    if (tag.baseTagSearchURL == undefined)
        tag.baseTagSearchURL = this.baseTagSearchURL
    dt = new DisplayTemplate(this.template, tag)
    dt.strict = this.strict
    dt.nocase = this.nocase
    return dt.eval()
}

TagListing.prototype.compile = function () {

    if (this.baseTagSearchURL == undefined)
        throw new Error("TagListing property 'baseTagSearchURL' not defined")

    var tagarray = new Array();
    var count = this.limit || this.tags.length
    if (count > this.tags.length) count = this.tags.length
    for (i=0; i<count; i++) {
        tagarray[tagarray.length] = this.format(this.tags[i]);
    }
    glue = this.glue || ""
    var tagstring = tagarray.join(glue);
    return tagstring
}
TagListing.prototype.write = function () { document.write(this.compile()) }

