Reference »

How to create access toggle buttons (on OborWiki)

Say you have a wiki that others use. Some pages should be totally private, some visible but un-editable, some totally public. One wiki group might have one set of default permissions, another group, another set.

Editing page attributes page-by-page is awfully tedious. Even using the (very convenient) Auth Control Panel (SiteAdmin/AuthControl) is still an inconvenience (if a small one).

Wouldn’t it be great to be able to hide or reveal a page, or lock/unlock it, right from the page itself, with a single click (or a single keystroke1)?

This page shows you how to do just that.

(The instructions below work for wikis here on OborWiki; if you’ve got a pmwiki installation elsewhere, you’ll have to adapt some of the steps below for your own install. For example, the Configurator is an OborWiki-specific feature; pmwiki administrators elsewhere will have to install/enable recipes the old-fashioned way, i.e. by editing config.php.)

Contents

First, a warning

Do not, repeat: do not, use actual passwords with this technique. Use only password references (such as @_side_edit, @editors, id:johndoe, etc.).

Optional Step 0: enable Font Awesome

This lets you have nice vector icons for your access toggle buttons. You can enable Font Awesome via the Configurator (SiteAdmin/Configurator).

(If you skip this step, then you’ll have to find your own icons, or simple have ordinary buttons with appropriate text labels (“Hide”/“Reveal” and “Lock”/“Unlock”, perhaps). Otherwise, the instructions below still apply.)

Note on webfont blocking

Font Awesome is a webfont, so if you block webfonts, you won’t see the icons in the instructions below (nor, of course, will you be able to use the icons when implementing the access toggle buttons on your own wiki).

To properly view these instructions, turn off your webfont blocking, or whitelist this domain. If you want to use icons from Font Awesome but want to have them work for people who block webfonts, you’ll have to do something like exporting the glyphs to SVG (and, probably, base-64 encoding them in your CSS). (Figuring out how to do this is left as an exercise for the reader.)

Step 1: Map the state space

This simply means “figure out what toggle buttons you want to have, and what states, exactly, do they toggle between”.

Example

On one of my wikis, I have a group Darklands/. This group has (via its GroupAttributes page) its read password set to  (blank) and edit password set to @_site_read (i.e., whatever the site-wide read password is—which also happens to be blank in this case, though that’s irrelevant to the example).

Thus, by default, anyone anyone can view pages in Darklands/; also, anyone [with read access to the site as a whole] can edit pages and create new pages.

However, I also want some pages in Darklands/ to be viewable, but not editable, by visitors; and some pages should be entirely hidden (not even viewable).

Thus there are the following possible states:

  1. Page is hidden (not viewable) and locked (not editable).
  2. Page is visible but locked.
  3. Page is hidden but unlocked.
    • This state is technically possible, but makes no sense; a page shouldn’t be editable if it’s not viewable. (Such unintuitive scenarios confuse users, and can create security holes.) So I’d like to make sure state #3 never happens, no matter what buttons I click, in what order, etc.
  4. Page is visible and unlocked.

I decide that I want two buttons: one to toggle visibility (switch between visible and hidden) and one to toggle editability (switch between locked and unlocked). They should look something like this:


The left button () toggles visibility; it current shows that the page is visible (it would show if the page were hidden).
The right button () toggles editability; it currently shows that the page is unlocked (it would show if the page were locked).

How should these buttons work?

First, each button ought to show the current state (rather than showing what the state will be if the button is clicked). Let’s see what our possible states would look like:

  1. Page is hidden (not viewable) and locked (not editable):      
  2. Page is visible but locked:      
  3. Page is hidden but unlocked:       (We should never see this state!)
  4. Page is visible and unlocked:      

Second, here’s how the buttons should behave when clicked:

  1. The left button () should behave as follows:
    1. If clicked when the page is hidden, toggle the page to visible. Do nothing else.
      • This transitions from state #1 (hidden/locked, i.e.   ) to state #2 (visible/locked, i.e.   ). (If we want to get to state #4 (visible/unlocked, i.e.   ), we then also have to click the right button ()).
    2. If clicked when the page is visible, toggle the page to hidden. Additionally, if the page is unlocked, toggle it to locked.
      • This transitions from either state #2 (visible/locked, i.e.   ) or state #4 (visible/unlocked, i.e.   ), to state #1 (hidden/locked, i.e.   ) (avoiding state #3—hidden/unlocked).
  2. The right button () should behave as follows:
    1. If clicked when the page is unlocked, toggle the page to locked. Do nothing else.
      • This transitions from state #4 (visible/unlocked, i.e.   ) to state #2 (visible/locked, i.e.   ). (If we want to get to state #1 (hidden/locked, i.e.   ), we then also have to click the left button ()).
    2. If clicked when the page is locked, toggle the page to unlocked. Additionally, if the page is hidden, toggle it to visible.
      • This transitions from either state #2 (visible/locked, i.e.   ) or state #1 (hidden/locked, i.e.   ), to state #4 (visible/unlocked, i.e.   ) (avoiding state #3—hidden/unlocked).

(Note that you can go from state #1 (hidden/locked, i.e.   ) to state #4 (visible/unlocked, i.e.   ), and vice-versa, with one click (by clicking or , respectively).)

Third, it goes without saying that these access toggle buttons should only be shown to a user who has the privileges to alter the current page’s attributes (permissions). Users without those privileges should not see the buttons at all.

Step 2: Write the code

Where should the code go?

I recommend placing it in the GroupHeader of any group where you want to use these buttons. (That is what I did, in the example I described above.)

The reason for doing it that way, rather than putting the code in Site.AllGroupHeader, or Site.DefaultGroupHeader, is that different wikigroups are likely to have quite different defaults, access needs, and so on; you would have to make code more complex, and/or create more buttons, and thus have to consider more (possibly many more!) states, etc.

(If this is not true for your use case—that is, if the pattern of permissions is uniform across your whole wiki—then it’s possible that putting the code for the access toggle buttons into a site-wide header may work for you.)

Code sample

This is the code that I placed into the Darklands/GroupHeader page, in the example described above. (I’ve divided the code into two parts for clarity, but you would simply put it all on the page, the second part right after the first.)

(:VISIBLE_STATE_READ_PASSWORD_CONDITION::)
(:HIDDEN_STATE_READ_PASSWORD:@_site_edit:)
(:HIDDEN_STATE_EDIT_PASSWORD:@_site_edit:)
(:VISIBLE_STATE_READ_PASSWORD:clear:)

(:UNLOCKED_STATE_EDIT_PASSWORD_CONDITION:(set by group) @_site_read:)
(:LOCKED_STATE_EDIT_PASSWORD:@_site_edit:)
(:UNLOCKED_STATE_READ_PASSWORD:clear:)
(:UNLOCKED_STATE_EDIT_PASSWORD:clear:)

Here we define some parameters:

VISIBLE_STATE_READ_PASSWORD_CONDITION (here set to —i.e., blank)
If a page’s read password is set to this value, the page counts as “visible”.
HIDDEN_STATE_READ_PASSWORD (here set to @_site_edit)
When toggling a page to the hidden state, set its read password to this value.
HIDDEN_STATE_EDIT_PASSWORD (here set to @_site_edit)
When toggling a page to the hidden state, set its edit password to this value.
VISIBLE_STATE_READ_PASSWORD (here set to clear2)
When toggling a page to the visible state, set its read password to this value.
UNLOCKED_STATE_EDIT_PASSWORD_CONDITION (here set to (set by group) @_site_read3)
If a page’s edit password is set to this value, the page counts as “unlocked”.
LOCKED_STATE_EDIT_PASSWORD (here set to @_site_edit)
When toggling a page to the locked state, set its edit password to this value.
UNLOCKED_STATE_READ_PASSWORD (here set to clear)
When toggling a page to the unlocked state, set its read password to this value.
UNLOCKED_STATE_EDIT_PASSWORD (here set to clear)
When toggling a page to the unlocked state, set its edit password to this value.

The parameters are defined as page text variables (PTVs). (Note that in the code below, we refer to these PTVs as {$:VARIABLE_NAME}, not {*$:VARIABLE_NAME}, because we want to use their valuaes as defined in the GroupHeader, where all this code is—we do not want to try to take the values of these PTVs from the page actually being displayed!)

The values of these parameters will, of course, have to depend on your actual setup (specifically, on the site-wide and group-wide default read and edit passwords, and any other relevant aspects of your wiki’s auth setup.)

Warning: As stated above, but bears repeating: do not use actual passwords here; use only password references. (See Passwords and PasswordsAdmin for more information on passwords and password references.)

(:if auth attr:)
>>id=access-control-quickbar<<

(:input form:)
(:input hidden action "postattr":)
(:if2 equal "{$:VISIBLE_STATE_READ_PASSWORD_CONDITION}" "{*$PasswdRead}":)
(:input hidden passwdread "{$:HIDDEN_STATE_READ_PASSWORD}":)
(:input hidden passwdedit "{$:HIDDEN_STATE_EDIT_PASSWORD}":)
(:input submit submit "&#xf06e;" accesskey=$[ak_vis_toggle] title="Hide page":)
(:else2:)
(:input hidden passwdread "{$:VISIBLE_STATE_READ_PASSWORD}":)
(:input submit submit "&#xf070;" accesskey=$[ak_vis_toggle] title="Reveal page":)
(:if2end:)
(:input end:)

(:input form:)
(:input hidden action "postattr":)
(:if2 equal "{$:UNLOCKED_STATE_EDIT_PASSWORD_CONDITION}" "{*$PasswdEdit}":)
(:input hidden passwdedit "{$:LOCKED_STATE_EDIT_PASSWORD}":)
(:input submit submit "&#xf09c;" accesskey=$[ak_lock_toggle] title="Lock page":)
(:else2:)
(:input hidden passwdread "{$:UNLOCKED_STATE_READ_PASSWORD}":)
(:input hidden passwdedit "{$:UNLOCKED_STATE_EDIT_PASSWORD}":)
(:input submit submit "&#xf023;" accesskey=$[ak_lock_toggle] title="Unlock page":)
(:if2end:)
(:input end:)

>><<
(:ifend:)

The actual buttons are standard PmWiki forms. They trigger the postattr action (the same action that gets triggered when modifying a page’s permissions via its Attributes view). The markup used to generate these forms should be mostly self-explanatory; there are no big surprises here.

Note the button labels; in this example, they are HTML entity codes, which refer to the appropriate characters in Font Awesome (for example, &#xf06e; becomes ). (Of course, this won’t work if the buttons aren’t styled appropriately—for one thing, we must set the buttons’ font to Font Awesome! See below for the CSS required to do this.)

(If you’re not using Font Awesome, simply set the buttons’ labels to something appropriate; see step 0, above, for suggestions.)

The (:if auth attr:) condition that wraps the entire block ensures that the buttons will only be seen by a logged-in user with the authority to modify the attributes of the current page.

Styling the buttons

What specific CSS you will need depends partly on your wiki’s setup (e.g., what skin you’re using, what other styles are active, etc.). The CSS code I used, in example described above, is given below. (I placed it right on the Darklands/GroupHeader page, wrapped in a (:css:) / (:cssend:) block; I could also have put it in Site.LocalCSS (scoped to Darklands.*), or into a custom stylepage, etc.)

div#access-control-quickbar form, #access-control-quickbar p { display: inline-block; }
div#access-control-quickbar { text-align: right; }
div#access-control-quickbar .inputbutton { font-size: inherit; font-family: FontAwesome; border: none; background-color: transparent; width: 32px; }

Optional Step 3: Access keys

Clicking buttons is all well and good, but real pros4 do everything with key combos. In PmWiki, the secret to mouse-less interaction is Access Keys.

In the code above, note that the buttons (the (:input submit:) elements) have attributes accesskey=$[ak_vis_toggle] and accesskey=$[ak_lock_toggle]. For these to work properly, you must add corresponding entries to your Site/Preferences page. (See Access Keys page, and the Site/Preferences page, for more information on configuring access keys.)

Finding how to use access keys in your browser of choice is left as an exercise for the reader. (In Chrome on the Mac, for example, you hold Control + Option to use access keys.)

1 On browsers that support access keys (which is most modern browsers).

2 Remember that setting a password to clear means “remove whatever custom password this page had for the given auth level, reverting it back to the group-wide (if present) or site-wide default

3 Yes, that (set by group) part is necessary, because—in this case—that is what the default value of the password is reported as! If I omitted that part, the code wouldn’t work; it would compare @_site_read to (set by group) @_site_read, and find no match.

4 Also, Linux users.