# -*- coding: utf-8 -*-
'''
MoinMoin 1.6 - SeeSaw Macro
    @copyright: 2008 Jim Wight
    @licence: GNU GPL, see COPYING for details

PURPOSE
    SeeSaw enables sections of a page to be individually see-sawed
    (toggled) between hidden and shown, typically from near their
    locations.

DESCRIPTION
    SeeSaw adds a link for see-sawing a named section of a page. It is
    created by a call of the following form:

        <<SeeSaw(section="section", toshow="toshow", tohide="tohide",
                 show=True|False, bg="background", inline="inline")>>
    where
        section  gives the section a name;
                 it defaults to 'section'
         toshow  specifies the text to display for showing the section
                 it defaults to 'Show' (for block) and '»»' (for inline)
         tohide  specifies the text to display for hiding the section;
                 it defaults to 'Hide' (block) and '««' (inline)
                 if toshow is given, but not tohide, tohide is set to the
                 value of toshow; toshow is undefined if only tohide is
                 provided
           show  specifies whether the section is to be shown initially;
                 it defaults to False
             bg  specifies the background colour to use for the section;
                 it defaults to None
         inline  specifies the text of an inline section;
                 it defaults to None, and non-presence implies the call
                 relates to a block section
                 
    'toshow' and 'tohide' can accommodate the text surrounding the link,
    to allow it to be different in the two cases. The three parts are
    distinguished by enclosing the text of the link between '<<' and '>>',
    e.g. toshow="<<Open>> me up", tohide="Now <<close>> me down"

    The (leading) arguments can also be given positionally, in the
    order of the keyword arguments above, e.g.

        <<SeeSaw("section1", "See-Saw")>>
        <<SeeSaw("section1", show=True)>>

    Block sections require to be set up as follows:

        {{{#!wiki seesaw/section
        }}}

    where the word 'section' after '/' matches the value "section" in
    the corresponding SeeSaw call.

    By default, block sections are hidden initially, but can be shown
    by adding '/show' to the '{{{#!wiki' line. 'show' should be set to
    True in the matching SeeSaw call if its 'tohide' and 'toshow'
    arguments are different (so that the correct one can be shown
    initially)

    If a background colour is specified for a block section,
    '/"section"-bg' needs to be added to the corresponding '{{{#!wiki'
    line to have the colour applied to the section. If there are
    multiple sections with the same name, it is sufficient to use 'bg'
    in just one of the SeeSaw calls, with the first taking precedence
    if multiple, but different, values are given.

    The text of inline sections is embedded in SeeSaw calls. By
    default, inline sections are hidden initially.

    SeeSaw sections behave similarly to MoinMoin comments in that all
    sections with the same name are toggled together. In fact, if the
    section name contains 'comment', it can be toggled on and off by
    the 'Comments' link in the edit bar as well as by its own link,
    along with any others whose names contain 'comment'.

    If '/comment' is added to a '{{{#!wiki' line, the section becomes
    a highlighted MoinMoin comment. However, as the MoinMoin comments
    mechanism doesn't know anything about SeeSaw sections, the text of
    the link doesn't get toggled when 'Comments' is used, so it is
    best if the same text is used for both "tohide" and "toshow" in
    that situation to avoid them getting out of sync.

    Implementation requires the following jQuery code:

function seeSaw(section) {
    $("span.seesaw." + section).toggle().not(":hidden").css("display","inline");
    $("div.seesaw." + section).toggle();
};

$(document).ready(function() {
    $("div.seesaw,span.seesawinline").not(".show").hide();
    $("input.seesaw:hidden").each(function() {
	bg = $(this).attr("value").split(":");
	$("div.seesaw." + bg[0]).css("background-color",bg[1]).removeClass(bg[0]);
    });
});

    jQuery will be required until (if ever) I can be bothered to
    rewrite using pure JavaScript. It can be downloaded from
    http://jquery.com/

    One way to load the local code and jQuery would be to place them
    in /moin_static16x/common/js as local.js and jquery.js, say, and to
    add the following to the configuration variable html_head:

<script type="text/javascript" src="/moin_static16x/common/js/jquery.js"></script>
<script type="text/javascript" src="/moin_static16x/common/js/local.js"></script>

EXAMPLES

<<SeeSaw(section="example1")>> example 1
{{{#!wiki seesaw/example1
This text was hidden initially and the link shown was Show;
it should now be Hide
}}}

<<SeeSaw("example2", show=True)>> example 2
{{{#!wiki seesaw/example2/show
This text is displayed initially and the link shown is Hide
}}}

<<SeeSaw(section="example3")>> example 3
{{{#!wiki seesaw/example3/comment
This is a both a SeeSaw section and a MoinMoin comment.
It (and any other MoinMoin comments) can be toggled on and off via the link
above or by the Comments link in the edit bar, but note that if the Comments
link is used, the text in the link gets out of sync.
}}}

<<SeeSaw(section="comment1")>> example 4
{{{#!wiki seesaw/comment1
This section can be toggled on and off via the link above or by the
Comments link in the edit bar - but it is not subject to MoinMoin
comment highlighting.
}}}

<<SeeSaw(section="example5", toshow="See-Saw", show=True, bg='#FFFFDD')>>
example 5
{{{#!wiki seesaw/example5/show
This is part 1 of example 5; it is displayed initially.<<BR>>
It is hidden and part 2 displayed when See-Saw is clicked
}}}
{{{#!wiki seesaw/example5/example5-bg
This is part 2 of example 5; it has a different background colour and is
displayed when part 1 is hidden.<<BR>>
It is hidden and part 1 displayed again when See-Saw is clicked.
}}}

Example 6 contains some
<<SeeSaw(section="inline1", inline=" hidden", bg='#FFFFDD')>> text.

Example 7 demonstrates toggling a
<<SeeSaw(section="comment", show=True, inline="MoinMoin")>> comment (plus
any other MoinMoin comments)

<<SeeSaw("example8", "<<Show>> example 8", "Use different text for <<hiding>> it")>>
{{{#!wiki seesaw/example8
||The body||of example 8||is a table||
}}}

AUTHOR
    Jim Wight <j.k.wight@ncl.ac.uk>

HISTORY
    [v0.2] 2008-05-12
    Accommodate different text surrounding the link

    [v0.1] 2008-05-01
    Initial version

'''

Dependencies = []
def execute(macro, args):
    import re
    from MoinMoin import wikiutil

    parser = wikiutil.ParameterParser('%(section)s%(toshow)s%(tohide)s%(show)b%(bg)s%(inline)s')
    (count,dict) = parser.parse_parameters(args)
    (section,toshow,tohide,show,bg,inline) = dict['section'], dict['toshow'], dict['tohide'], dict['show'], dict['bg'], dict['inline']
    if section is None:
        section = 'section'
    if tohide is None and toshow is None:
        if inline is None:
            toshow = 'Show'; tohide = 'Hide'
        else:
            toshow = u'»»';  tohide = u'««'
    elif tohide is None and toshow is not None:
        tohide = toshow

    regex = re.compile(r'(.*)<<(.*)>>(.*)')
    preshow = postshow = prehide = posthide = ""
    matches = regex.match(toshow)
    if matches is not None:
        preshow,toshow,postshow = matches.groups()
    matches = regex.match(tohide)
    if matches is not None:
        prehide,tohide,posthide = matches.groups()

    if show is None:
        show = False
    if show:
        toshow,tohide = tohide,toshow
        preshow,prehide = prehide,preshow
        postshow,posthide = posthide,postshow 

    comment = bgstyle = divstyle = shown = ""
    if inline is None:
        if bg is not None:
            divstyle = '''<input class="seesaw" type="hidden" value="%(section)s-bg:%(bg)s">''' % locals()
    else:
        if show:
            shown = "show"
        if section != "comment" and bg is not None:
            bgstyle = '''style="background-color:%(bg)s"''' % locals()
        comment = '''<span class="seesaw seesawinline %(section)s %(shown)s" %(bgstyle)s>%(inline)s</span>''' % locals()

    html = '''<span class="seesaw %(section)s" style="display:inline">%(preshow)s</span><span class="seesaw %(section)s" style="display:none">%(prehide)s</span><a href="#" onClick='seeSaw("%(section)s");return false;'>%(divstyle)s<span class="seesaw %(section)s" style="display:inline">%(toshow)s</span><span class="seesaw %(section)s" style="display:none">%(tohide)s</span></a><span class="seesaw %(section)s" style="display:inline">%(postshow)s</span><span class="seesaw %(section)s" style="display:none">%(posthide)s</span>%(comment)s''' % locals()

    return macro.formatter.rawHTML(html)
