# -*- coding: utf-8 -*-
'''
MoinMoin 1.6-1.8 - SeeSaw Macro
    @copyright: 2008,2009 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",
                 image="arrow|plumin", speed="slow|normal|fast"|integer,
                 seesaw=True|False)>>
    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
           image selects an image set to use for the links instead of text,
                 with toshow and tohide being ignored, but see just below;
                 it defaults to None;
                 the location of the images must be configured in the
                 Configuration section below, where additional image sets
                 can easily be added;
                 the images provided are embedded in the IMAGES section
                 of this file as a uuencoded .tgz file
           speed specifies the rate at which the section (not inline)
                 should appear or disappear, or provides a number of
                 milliseconds for the animation to last;
                 it defaults to 0
          seesaw SeeSaw will, by default, only toggle sections (i.e. divs)
                 created for it; this option, when set to False, enables
                 other divs to be toggled from a SeeSaw link

    (NB The string arguments don't need to be quoted unless they contain
        special characters)
                 
    '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 
    middle part is ignored if image is used, so can be empty.

    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   or   {{{#!wiki seesaw section
      }}}                             }}}

    where the word 'section' matches the value "section" in the
    corresponding SeeSaw call. This creates a div with the classes
    'seesaw' and 'section' applied.

    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.

    By setting the option 'seesaw' to False it is possible to apply
    SeeSaw to non-SeeSaw sections, e.g. the div created by the
    TableOfContents macro. In such a case, the section name in the
    SeeSaw call should be a class already attached to the div. If the
    section is - more than likely - shown initially, 'show=True'
    should be set in order to get the link text right (or toshow and
    tohide can be reversed).
    NB MoinMoin's CSS for tables of content at versions prior to 1.8.1
    also affects the SeeSaw link, so it will be necessary to do some
    tweaking to counteract its effect.
    
JQUERY
    Implementation requires the following jQuery code:

function seeSaw(section,speed,seesaw) {
    if (seesaw) dotseesaw = ".seesaw"; else dotseesaw = "";

    spandimg = $("span.seesaw." + section + ",img.seesaw." + section);
    spandimg.toggle().not(":hidden").css("display","inline");
    $("div" + dotseesaw + "." + section).toggle(speed);
};

$(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 seesaw code and jQuery would be to place them
    in /moin_static18x/common/js as seesaw.js and jquery.js, say, and
    to add the following to the configuration variable html_head:

<script type="text/javascript" src="/moin_static18x/common/js/jquery.js"></script>
<script type="text/javascript" src="/moin_static18x/common/js/seesaw.js"></script>

EXAMPLES
    See http://seesaw.ncl.ac.uk

IMAGES
begin 644 images.tgz
M'XL(`&*B9$@``\O(3$E-+"K*+]<KR$MGH`TP``(S,P,P;6!BB$H#@1%0SM#0
MP-C`U,C`S-B,P<#0P,3$@$'!@$;N00&EQ26)10H*]+!J,(+.`#]W7BXI+B"3
MU]/#)0A(<X(P!QN0?#"130!(E7NZ.(9(3"T];\AW6(&']4+^R^J/DQHYQ=[-
M4@WNN\Y<XOJ(9S]W9X:T3N6&RDT;G\[9^SUN8\>42](JW`UL#OPW/<0\F!J2
M&_D\&U1V5-?.N'9G[ST/H3-OYDR<.??Z[5ZEI-F!+CGU&7]RY3/^OSI_=,<7
MUTTZ%[=^V_Z=L?M1(X?OMU?5('=ZNOJYK'-*:!K`H!J6(`.8_PMR2G,S\VA7
M`!#*_X8FQHC\;V8"RO]FAL:C^9\>@)C\KP7)_\DI"0D_SCNP*"QY82]LN$Q@
M:4=KP]:>%UT2FIOZ-%Q[+.XT,0&S*:M`\;=#[T%&CV;9(0"*,_++![S^-S1!
MY'\C(U#^-S4P',W_]`#$Y/]@2/Z?.T&1K\&!AT7]9DQPY]K]_@D/'G-4L,P_
M*-+-X"7P6&WV756E63._=F3,/"GK\<J!:?62G9.$+!I<+WU1B[VITCMURH%W
M[PZO7[+I\N==^O9SWP15MW+=[+\'<L-H03%P`)3_![S^-T5J_YL:@^M_4[/1
M_$\/0$S^U\=6_\_:H'F(0<?"IV&C9*%D_T'U4U8Y71(;.05XU!F"#W"Q_[",
MO`XR?S1OCX)1,`I&P2@8!:-@%(R"43`*1L$H&`6C8!2,@E$P"D;!*!@%HV`4
,T!<```N2X?$`*```
`
end

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

HISTORY
    [v0.5] 2009-01-31
    Add seesaw option
    Remove unnecessary HTML if {pre|post}/{show|hide} not used
    Remove examples

    [v0.4] Not released
    Add speed option

    [v0.3] 2008-07-05
    Add image links

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

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


#--- Configuration ----------------------------------------
# 
# Change this to the relative location of the images
#
# img_prefix="/moin_static18x/common"
img_prefix="/img"
#
# Optionally change this (to extend the list of image sets)
#
imageset = {
    "arrow" : ["showarrow.png", "hidearrow.png"],
    "plumin": ["showplumin.png", "hideplumin.png"]
    }
#
#--- End of Configuration ---------------------------------


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

    def escape(x):
        if x is None:
            return x;
        else:
            return wikiutil.escape(x)

    parser = wikiutil.ParameterParser('%(section)s%(toshow)s%(tohide)s%(show)b%(bg)s%(inline)s%(image)s%(speed)s%(seesaw)b')
    (count,dict) = parser.parse_parameters(args)
    (section,toshow,tohide,show,bg,inline,image,speed,seesaw) = (dict[x] for x in ('section','toshow','tohide','show','bg','inline','image','speed', 'seesaw'))

    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()

    showimage = hideimage = ""
    img = False
    if image is not None:
        imagepair = imageset.get(image)
        if imagepair is not None:
            (showimage,hideimage) = (img_prefix.rstrip("/") + "/" + x for x in imagepair)
            img = True
    
    if show is None:
        show = False
    if show:
        toshow,tohide, preshow,prehide, postshow,posthide, showimage,hideimage = tohide,toshow, prehide,preshow, posthide,postshow, hideimage,showimage

    section,preshow,toshow,postshow,prehide,tohide,posthide,bg,inline = (escape(x) for x in (section,preshow,toshow,postshow,prehide,tohide,posthide,bg,inline))

    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()

    showit = '''<span class="seesaw %s" style="display:inline">%s</span>'''
    hideit = '''<span class="seesaw %s" style="display:none">%s</span>'''
    pres = preh = psts = psth = ''
    if preshow != '':
        pres = showit % (section, preshow)
    if prehide != '':
        preh = hideit % (section, prehide)
    if postshow != '':
        psts = showit % (section, postshow)
    if posthide != '':
        psth = hideit % (section, posthide)

    if speed is None:
        speed = 0
    try:
        speed = int(speed)
    except:
        speed = '''"%s"''' % speed

    if seesaw is None or seesaw:
        seesaw = 'true'
    else:
        seesaw = 'false'

    if img:
        html = '''%(pres)s%(preh)s<a href="">%(divstyle)s<img class="seesaw %(section)s" style="display:inline" src="%(showimage)s" onClick='seeSaw("%(section)s",%(speed)s, %(seesaw)s);return false;'></a><a href=""><img class="seesaw %(section)s" style="display:none" src="%(hideimage)s" onClick='seeSaw("%(section)s",%(speed)s,%(seesaw)s);return false;'></a>%(psts)s%(psth)s%(comment)s''' % locals()
    else:
        html = '''%(pres)s%(preh)s<a href="" onClick='seeSaw("%(section)s",%(speed)s,%(seesaw)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>%(psts)s%(psth)s%(comment)s''' % locals()

    return macro.formatter.rawHTML(html)
