NestedText

Question

How can I create a page that allows the reader to expand or collapse the text to reveal or hide certain text?

Answer

The core includes a ConditionalMarkup directive for showing and hiding text, but the existing conditions focus on environmental values (names, date, etc) rather than values that the user can be prompted to provide.

The ViewModes recipe, which is implemented in this group, provides an opportunity to test the concept of user prompted conditional markup because it provides both a variable whose value can be reset by a link and a corresponding Conditional Markup condition that can test for the value of that variable.

Update! Two new recipes are now available. Jump ahead to the discussion of Show Hide and Page Variable Extensions.

Show Me

Here are some examples of different ways to prompt users to decide whether to expand or collapse the text of this page to show or hide additional text that is wrapped in conditional markup. In each case, the additional text discusses the method used to prompt the user.

Example 1 (simple links):
expand / collapse

For this first example, the following links are placed before the conditional markup:
[[{$Name}?view=display| expand]] / [[{$Name}?view=standard| collapse]]

These are the simplest links, because they do not require conditional markup to determine which link to display when.

Example 2 (toggled links)):
collapse

For this second example, the same links used above are now placed within conditional markup directives, to give the effect of the link toggling on, or off:
(:if view display :) 
[[{$Name}?view=standard| collapse]]
(:if view standard :) 
[[{$Name}?view=display| expand]]
(:if:)

Placing both links before the conditional markup makes it simpler, because then the conditional markup can focus on the text, without having to also deal with the links, as is the case with the following examples.

Example 3 (toggled InputForms buttons):

For this third example, the following InputForms are used to provide buttons instead of links, and they are placed conditional markup directives, to give the effect of the link toggling on, or off:
(:if view display :) 
(:input form "{$Name}?view=standard":)
(:input submit value="Collapse":)
(:input end:)
(:if view standard :) 
(:input form "{$Name}?view=display":)
(:input submit value="Expand":)
(:input end:)
(:if:)

Right now, these InputForms don't do anything more than what ordinary links do -- they post the specified url -- but they may have greater potential. The default action is to Post a url, but an optional argument called "method" can specify different actions. I can't find any documentation on what those are. (I have found an example that incorporates an accesskey). At the very least, InputForms seem to have potential simply because they are already focused on obtaining and acting on user input.

Notes

Don't use ViewModes. I am using ViewModes just to test this concept. Using ViewModes for anything more would not be a good idea because resetting the views to expand and collapse text will change the views in skins that use ViewModes, and visa-versa.

Limitations. The current test using ViewModes reveals some limitations that would be nice to avoid.

  • All or nothing expansion
    • No provision for selectively expanding certain sections, or levels
  • Changes return the reader to the top of the page expand / collapse
  • The current ViewModes link does not work with page location markers, e.g
[[{$Name}#showme]] is a simple link that would take you to the section called showme. Try it: NestedText#showme
[[{$Name}?view=display| expand]] would render the current page in the display view. Try it: expand
[[{$Name}#showme?view=display| expand and return]] would not do anything. Try it: expand and return

Other approaches

JavaScript: Show Hide

The most visually pleasing approaches, in my opinion, are those that use JavaScript, because they avoid the delay that results from reposting. For example, take a look at how nicely HansB makes sidebars snap in and out of the page on Triad (with the small links in the corners that toggle between "hide" and "show").

This recipe uses java script to create toggle buttons (and links) which will show/hide sections (divs) on a page. Thanks for your encouragement to develop this! I expanded the concept used for Triad skin's toggle buttons and generalised it to work with multiple buttons for multiple sections. Note that pmwiki does not allow nesting of divs, so there is a limitation. ~HansB

On the other hand, those solutions are dependent on users having JavaScript enabled and, as Hagan points out in his post to the forum here, reposting "isn't necessarily bad. For one thing, it provides feedback in the logs about which content is being sought."

I just thought of another advantage of reposting: resources. For example, if I want to let the reader toggle between different include and pagelist directives, a solution that uses conditional markup and requires reposting will only run one (of the alternate sets) of include or pagelist directives. By contrast, a solution that does not require reposting necessarily must process both sets of directive in order to have either be available. If we use a pagelist whose template uses an include to display selected protions of structured pages, the PmWiki's limit of 50 includes will be reached twice as fast if reposting is not required between toggles. Finally, if we want to toggle between different searchresult directives, a solution that does not require reposting may simply fail, because both directives will be processed, which may result in only one of them having any effect, or in some unexpected effect (I would need to test this out to say which is for certain).

New markup: Page Variable Extensions

Note: This page was a proof of concept that was confined to using the currently available features of ViewModes, which is enabled for this group, to supply variables that can be set by actions and used by ConditionalMarkup. If we break free of this limited testing context, then many more possibilities arise, including the creation of new markup, see PM's reply to Pierre's thread in the PmWiki forum here

Dfaure's new Page Variable Extensions recipe allows you to set new page variables that can be set by action links and tested by Conditional Markup. While this has many applications, it can clearly be used for a show hide function and, because it uses reposting and conditional markup, it can make more efficient use of limited resources when used to toggle between directives (as noted above).

The default setup for this recipe does not have the action links enabled. To allow users to set variables using links, you will need to set the $EnableUrlSetVar by adding the following line to you rconfig.php (or farmconfig.php) before the include line for the recipe:

   $EnableUrlSetVar = 1;
   include_once("$FarmD/cookbook/extendvars.php");

With that addition, you can use a link to create a new page variable. For example, if we want to create a new page variable called {$Choice} and assign it a value of "hide", we can use an action that combines ?set_ with the desired name and value of the new page variable, which, in this case, would be: ?set_Choice=hide.

To use that with a link, append it to the end of the link, which you can do programatically by using the existing Page Variable {$PageUrl}, like this: [[{$PageUrl}?set_Choice=hide]] That creates a page variable called {$Choice} and assigns a value of "hide". To reassign a different value, just substitute the new value, like this [[{$PageUrl}?set_Choice=hide]]. Use multiple links to set and display different values, like this: [[({$PageUrl}?set_Choice=)show]] or [[({$PageUrl}?set_Choice=)hide]]

At that point, you can use conditions to test for the values, including a condition to test for no value (the default before either link is clicked):

(:if equal {$Choice} "":)
Default: no choice has been selected

(:if equal {$Choice} "show":)
Show: The show link was selected

(:if equal {$Choice} "hide":)
Hide: The hide link was selected

(:if end:)

As with the earlier examples, a toggle effect can be created by placing different links inside of conditions, so that a "show" state includes a "hide" link, and a "hide" state includes a "show" link, like this:

(:if equal {$Choice} "":)
Show state (default)  [[({$PageUrl}?set_Choice=)hide]] (displayed link)

(:if equal {$Choice} "show":)
Show state (selected)  [[({$PageUrl}?set_Choice=)hide]] (displayed link)

(:if equal {$Choice} "hide":)
Hide state (selected) [[({$PageUrl}?set_Choice=)show]] (displayed link)

(:if end:)

To simplify this, the condition for the default state can be combined with the show (or hide) state using boolean conditions, available on more recent versions of PmWiki, as follows:

(:if expr equal {$Choice} "" || equal {$Choice} "show" :)
Show state (by default or choice)  [[({$PageUrl}?set_Choice=)hide]] (displayed link)

(:if equal {$Choice} "hide":)
Hide state (selected) [[({$PageUrl}?set_Choice=)show]] (displayed link)

(:if end:)

Or, even easier, condition the show state on the negative of the hide state, like this:

(:if !equal {$Choice} "hide":)
Show state (by default or choice)  [[({$PageUrl}?set_Choice=)hide]] (displayed link)

(:if equal {$Choice} "hide":)
Hide state (selected) [[({$PageUrl}?set_Choice=)show]] (displayed link)

(:if end:)

Comments

From PmWikiForum

See Also

PmWiki recipes using conditions or variables set by links, or both

JavaScript use in PmWiki to toggle solected text between show and hide

PmWiki forum threads

Solutions in other WikiWorlds

CSS and JavaScript examples in the wild

JavaScript examples with workarounds for script disabled browers

  • webtips.dan.info/graceful.html
    • General article about graceful degradation, with specific tips
  • tjkdesign.com
    • Claims to degrade well without java; but did not work when I tested with Netscape 7 (but did with Safari)
  • bobbyvandersluis.com
    • Proposal for "unobtrusive" show hide, requires separate CSS
  • webmasterworld.com
    • Forum comment: skip DISPLAY: none styling; let javascript hide on page load
  • developer.apple.com
    • Lots of suggestions, e.g. return opposite values (swap false to true) so that link is followed on failure)
  • holovaty.com
    • Used wrapping each link with a valid link and onclick event handlers returning false

Some general JavaScript articles

Contributors