1
# Plugin for Foswiki - The Free and Open Source Wiki, http://foswiki.org/
3
# Copyright (C) Michael Daum
4
# Copyright (C) Arthur Clemens, arthur@visiblearea.com
5
# Copyright (C) Rafael Alvarez, soronthar@sourceforge.net
7
# This program is free software; you can redistribute it and/or
8
# modify it under the terms of the GNU General Public License
9
# as published by the Free Software Foundation; either version 2
10
# of the License, or (at your option) any later version.
12
# This program is distributed in the hope that it will be useful,
13
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details, published at
16
# http://www.gnu.org/copyleft/gpl.html
21
---+ package TwistyPlugin
25
package Foswiki::Plugins::TwistyPlugin;
32
qw( $VERSION $RELEASE $pluginName @modes $doneHeader $doneDefaults $twistyCount
33
$prefMode $prefShowLink $prefHideLink $prefRemember);
35
# This should always be $Rev: 3417 (2009-04-12) $ so that Foswiki can determine the checked-in
36
# status of the plugin. It is used by the build automation tools, so
37
# you should leave it alone.
38
$VERSION = '$Rev: 3417 (2009-04-12) $';
40
# This is a free-form string you can use to "name" your own plugin version.
41
# It is *not* used by the build automation tools, but is reported as part
42
# of the version number in PLUGINDESCRIPTIONS.
45
$pluginName = 'TwistyPlugin';
47
my $TWISTYPLUGIN_COOKIE_PREFIX = "TwistyPlugin_";
48
my $TWISTYPLUGIN_CONTENT_HIDDEN = 0;
49
my $TWISTYPLUGIN_CONTENT_SHOWN = 1;
51
#there is no need to document this.
53
my ( $topic, $web, $user, $installWeb ) = @_;
55
# check for Plugins.pm versions
56
if ( $Foswiki::Plugins::VERSION < 1.1 ) {
57
Foswiki::Func::writeWarning(
58
"Version mismatch between $pluginName and Plugins.pm");
66
Foswiki::Func::registerTagHandler( 'TWISTYSHOW', \&_TWISTYSHOW );
67
Foswiki::Func::registerTagHandler( 'TWISTYHIDE', \&_TWISTYHIDE );
68
Foswiki::Func::registerTagHandler( 'TWISTYBUTTON', \&_TWISTYBUTTON );
69
Foswiki::Func::registerTagHandler( 'TWISTY', \&_TWISTY );
70
Foswiki::Func::registerTagHandler( 'ENDTWISTY', \&_ENDTWISTYTOGGLE );
71
Foswiki::Func::registerTagHandler( 'TWISTYTOGGLE', \&_TWISTYTOGGLE );
72
Foswiki::Func::registerTagHandler( 'ENDTWISTYTOGGLE', \&_ENDTWISTYTOGGLE );
78
return if $doneDefaults;
82
Foswiki::Func::getPreferencesValue('TWISTYMODE')
83
|| Foswiki::Func::getPluginPreferencesValue('TWISTYMODE')
86
Foswiki::Func::getPreferencesValue('TWISTYSHOWLINK')
87
|| Foswiki::Func::getPluginPreferencesValue('TWISTYSHOWLINK')
90
Foswiki::Func::getPreferencesValue('TWISTYHIDELINK')
91
|| Foswiki::Func::getPluginPreferencesValue('TWISTYHIDELINK')
94
Foswiki::Func::getPreferencesValue('TWISTYREMEMBER')
95
|| Foswiki::Func::getPluginPreferencesValue('TWISTYREMEMBER')
101
return if $doneHeader;
104
# Untaint is required if use locale is on
105
Foswiki::Func::loadTemplate(
106
Foswiki::Sandbox::untaintUnchecked(lc($pluginName)) );
107
my $header = Foswiki::Func::expandTemplate('twisty:header');
108
Foswiki::Func::addToHEAD( $pluginName, $header );
112
my ( $session, $params, $theTopic, $theWeb ) = @_;
115
my $mode = $params->{'mode'} || $prefMode;
116
my $btn = _twistyBtn( 'show', @_ );
117
return Foswiki::Func::decodeFormatTokens(
118
_wrapInButtonHtml( $btn, $mode ) );
122
my ( $session, $params, $theTopic, $theWeb ) = @_;
124
my $mode = $params->{'mode'} || $prefMode;
125
my $btn = _twistyBtn( 'hide', @_ );
126
return Foswiki::Func::decodeFormatTokens(
127
_wrapInButtonHtml( $btn, $mode ) );
131
my ( $session, $params, $theTopic, $theWeb ) = @_;
134
my $mode = $params->{'mode'} || $prefMode;
135
my $btnShow = _twistyBtn( 'show', @_ );
136
my $btnHide = _twistyBtn( 'hide', @_ );
137
my $prefix = $params->{'prefix'} || '';
138
my $suffix = $params->{'suffix'} || '';
139
my $btn = $prefix . $btnShow . $btnHide . $suffix;
140
return Foswiki::Func::decodeFormatTokens(
141
_wrapInButtonHtml( $btn, $mode ) );
145
my ( $session, $params, $theTopic, $theWeb ) = @_;
149
my $id = $params->{'id'};
150
if ( !defined $id || $id eq '' ) {
151
$params->{'id'} = _createId( $params->{'id'}, $theWeb, $theTopic );
153
return _TWISTYBUTTON(@_) . _TWISTYTOGGLE(@_);
157
my ( $session, $params, $theTopic, $theWeb ) = @_;
158
my $id = $params->{'id'};
159
if ( !defined $id || $id eq '' ) {
163
my $idTag = $id . 'toggle';
164
my $mode = $params->{'mode'} || $prefMode;
165
unshift @modes, $mode;
168
my $cookieState = _readCookie( $session, $idTag );
170
_createHtmlProperties( undef, $idTag, $mode, $params, $isTrigger,
172
my $props = @propList ? " " . join( " ", @propList ) : '';
173
my $modeTag = '<' . $mode . $props . '>';
174
return Foswiki::Func::decodeFormatTokens(
175
_wrapInContentHtmlOpen($mode) . $modeTag );
178
sub _ENDTWISTYTOGGLE {
179
my ( $session, $params, $theTopic, $theWeb ) = @_;
180
my $mode = shift @modes;
183
"<span class='foswikiAlert'>woops, ordering error: got an ENDTWISTY before seeing a TWISTY</span>"
186
my $modeTag = ($mode) ? '</' . $mode . '>' : '';
187
return $modeTag . _wrapInContentHtmlClose($mode);
191
my ( $rawId, $theWeb, $theTopic ) = @_;
193
if ( !defined $rawId || $rawId eq '' ) {
194
return 'twistyId' . $theWeb . $theTopic . $twistyCount;
196
return "twistyId$rawId";
200
my ( $twistyControlState, $session, $params, $theTopic, $theWeb ) = @_;
205
#my $triangle_right = '►';
206
#my $triangle_down = '▼';
208
my $id = $params->{'id'};
209
if ( !defined $id || $id eq '' ) {
212
my $idTag = $id . $twistyControlState if ($twistyControlState) || '';
215
( $twistyControlState eq 'show' ) ? $prefShowLink : $prefHideLink;
217
# link="" takes precedence over showlink="" and hidelink=""
218
my $link = $params->{'link'};
220
if ( !defined $link ) {
222
# if 'link' is not set, try 'showlink' / 'hidelink'
223
$link = $params->{ $twistyControlState . 'link' };
225
if ( !defined $link ) {
226
$link = $defaultLink || '';
228
my $linkClass = $params->{'linkclass'} ? " $params->{'linkclass'}" : '';
230
$params->{ $twistyControlState . 'img' }
234
$params->{ $twistyControlState . 'imgright' }
235
|| $params->{'imgright'}
238
$params->{ $twistyControlState . 'imgleft' }
239
|| $params->{'imgleft'}
242
$imgright =~ s/['\"]//go;
243
$imgleft =~ s/['\"]//go;
245
( $img ne '' ) ? '<img src="' . $img . '" border="0" alt="" />' : '';
248
? '<img src="' . $imgright . '" border="0" alt="" />'
252
? '<img src="' . $imgleft . '" border="0" alt="" />'
258
. '<span class="foswikiLinkLabel foswikiUnvisited' . $linkClass . '">'
262
. $imgRightTag . '</a>';
267
if ( $idTag && $params ) {
268
my $cookieState = _readCookie( $session, $idTag );
270
_createHtmlProperties( $twistyControlState, $idTag, undef, $params,
271
$isTrigger, $cookieState );
272
$props = @propList ? " " . join( " ", @propList ) : '';
274
my $triggerTag = '<span' . $props . '>' . $imgLinkTag . '</span>';
278
sub _createHtmlProperties {
279
my ( $twistyControlState, $idTag, $mode, $params, $isTrigger, $cookie ) =
281
my $class = $params->{'class'} || '';
282
my $firststart = $params->{'firststart'} || '';
283
my $firstStartHidden;
284
$firstStartHidden = 1 if ( $firststart eq 'hide' );
286
$firstStartShown = 1 if ( $firststart eq 'show' );
288
$cookieShow = 1 if defined $cookie && $cookie == 1;
290
$cookieHide = 1 if defined $cookie && $cookie == 0;
291
my $start = $params->{start} || '';
293
$startHidden = 1 if ( $start eq 'hide' );
295
$startShown = 1 if ( $start eq 'show' );
298
my $remember = $params->{'remember'} || $prefRemember;
299
my $noscript = $params->{'noscript'} || '';
301
$noscriptHide = 1 if ( $noscript eq 'hide' );
305
push( @classList, $class ) if $class && !$isTrigger;
306
push( @classList, 'twistyRememberSetting' ) if ( $remember eq 'on' );
307
push( @classList, 'twistyForgetSetting' ) if ( $remember eq 'off' );
308
push( @classList, 'twistyStartHide' ) if $startHidden;
309
push( @classList, 'twistyStartShow' ) if $startShown;
310
push( @classList, 'twistyFirstStartHide' ) if $firstStartHidden;
311
push( @classList, 'twistyFirstStartShow' ) if $firstStartShown;
313
# Mimic the rules in twist.js, function _update()
315
$state = $TWISTYPLUGIN_CONTENT_HIDDEN if $firstStartHidden;
316
$state = $TWISTYPLUGIN_CONTENT_SHOWN if $firstStartShown;
318
# cookie setting may override firstStartHidden and firstStartShown
319
$state = $TWISTYPLUGIN_CONTENT_HIDDEN if $cookieHide;
320
$state = $TWISTYPLUGIN_CONTENT_SHOWN if $cookieShow;
322
# startHidden and startShown may override cookie
323
$state = $TWISTYPLUGIN_CONTENT_HIDDEN if $startHidden;
324
$state = $TWISTYPLUGIN_CONTENT_SHOWN if $startShown;
326
# assume trigger should be hidden
327
# unless explicitly said otherwise
328
my $shouldHideTrigger = 1;
330
push( @classList, 'twistyTrigger foswikiUnvisited' );
332
if ( $state eq $TWISTYPLUGIN_CONTENT_SHOWN
333
&& $twistyControlState eq 'hide' )
335
$shouldHideTrigger = 0;
337
if ( $state eq $TWISTYPLUGIN_CONTENT_HIDDEN
338
&& $twistyControlState eq 'show' )
340
$shouldHideTrigger = 0;
342
push( @classList, 'twistyHidden' ) if $shouldHideTrigger;
345
# assume content should be hidden
346
# unless explicitly said otherwise
347
my $shouldHideContent = 1;
349
push( @classList, 'twistyContent' );
351
if ( $state eq $TWISTYPLUGIN_CONTENT_SHOWN ) {
352
$shouldHideContent = 0;
354
push( @classList, 'foswikiMakeHidden' ) if $shouldHideContent;
358
# should be done by Foswiki template scripts instead
359
if ( !$isTrigger && $noscriptHide ) {
360
if ( $mode eq 'div' ) {
361
push( @classList, 'foswikiMakeVisibleBlock' );
364
push( @classList, 'foswikiMakeVisibleInline' );
368
# let javascript know we have set the state already
369
push( @classList, 'twistyInited' . $state );
372
push( @propList, 'id="' . $idTag . '"' );
373
my $classListString = join( " ", @classList );
374
push( @propList, 'class="' . $classListString . '"' );
380
Reads a setting from the FOSWIKIPREF cookie.
382
* 1 if the cookie has been set (meaning: show content)
383
* 0 if the cookie is '0' (meaning: hide content)
384
* undef if no cookie has been set
389
my ( $session, $idTag ) = @_;
391
return '' if !$idTag;
393
# which state do we use?
395
my $cookie = $cgi->cookie('FOSWIKIPREF');
397
$tag =~ s/^(.*)(hide|show|toggle)$/$1/go;
398
my $key = $TWISTYPLUGIN_COOKIE_PREFIX . $tag;
400
return unless ( defined($key) && defined($cookie) );
403
if ( $cookie =~ m/\b$key\=(.+?)\b/gi ) {
407
return if $value eq '';
408
return ( $value eq '1' ) ? 1 : 0;
411
sub _wrapInButtonHtml {
412
my ( $text, $mode ) = @_;
413
return _wrapInContainerHideIfNoJavascripOpen($mode) . $text
414
. _wrapInContainerDivIfNoJavascripClose($mode);
417
sub _wrapInContentHtmlOpen {
419
return "<$mode class=\"twistyPlugin\">";
422
sub _wrapInContentHtmlClose {
424
return "</$mode><!--/twistyPlugin-->";
427
sub _wrapInContainerHideIfNoJavascripOpen {
429
return '<' . $mode . ' class="twistyPlugin foswikiMakeVisibleInline">';
432
sub _wrapInContainerDivIfNoJavascripClose {
434
return '</' . $mode . '><!--/twistyPlugin foswikiMakeVisibleInline-->';