Recent Changes - Search:

Cookbook

PmWiki

pmwiki.org

WikiForms Recipes

Summary: Various recipes for the WikiForms recipe
Version:
Prerequisites:
Status:
Maintainer:
Categories: Forms

Leaving without saving

I lost quit a few edits due to sheer stupidity. Leaving the page before saving.

I found a bit of java code to prevent this.

Simply add the code below to your (farm)config.php or create a new file and include_once that one.

I added a language string for English and Dutch, ensure they are on one line in your editor. ( no hidden linefeeds )

BrBrBr


if ($action == 'edit') {

XLSDV('en', array(
  'e_sure' => 'You have attempted to leave this page.  If you have made any chan
ges to the fields without clicking the Save button, your changes will be lost.
Are you sure you want to exit this page?'
  ));
XLSDV('nl', array(
  'e_sure' => 'Je doet een poging deze pagina te verlaten, weet je dat zeker? De
 wijzigingen zijn nog niet opgeslagen!!'
  ));


SDV($InputTags['e_saveeditbutton'][':html'],"<input type='submit' \$InputFormArg
s onclick='needToConfirm = false;'>");
SDV($InputTags['e_previewbutton'][':html'],"<input type='submit' \$InputFormArgs
 onclick='needToConfirm = false;'>");
SDV($InputTags['e_cancelbutton'][':html'],"<input type='submit' \$InputFormArgs
onclick='needToConfirm = false;'>");
SDV($InputTags['e_resetbutton'][':html'],"<input type='submit' \$InputFormArgs o
nclick='needToConfirm = false;'>");
SDV($InputTags['e_savebutton'][':html'],"<input type='submit' \$InputFormArgs on
click='needToConfirm = false;'>
<script language='JavaScript'>
  var needToConfirm = true;
  window.onbeforeunload = confirmExit;
  function confirmExit()
  {
    if (needToConfirm) return \"" . XL('e_sure') . "\";
  }
</script>
"
  );
}

Another alternative is to use Mozilla Firefox with the "Save Text Area" extension. This allows you to save the data in the textarea to a local text file and once linked you can enable autosave--which works even when you inadvertantly close the browser. Then, all your work is saved locally. BenWilson October 28, 2005, at 09:16 PM


Assign and reference titles for numeric page names

This is a 2 part feature: assign titles to pages with numeric names; and reference a numeric page by its title.

To assign a title, declare one of the fields to be type (title). As of version 1.42, WikiForms does 3 things:

  • it wraps the value of the title field in a (:title:) directive
  • it uses the value of the title field as the change summary, unless another field is designated as the summary (remember that you can do this by putting an * against the summary element in the form template)
  • if the title field is used in a wikilist, it makes this a link to the corresponding page number

Now we need a way to reference a page by its title. formtitle.phpΔ answers this requirement. This adds [[?page title]] markup to resolve references to pages that include the page's title in the RecentChanges change summary. You need to tell it the location of a page in your forms group where the new entry form is:

    $NewGlossaryPage = 'Glossary.NewEntry';    //for example
    include_once("$FarmD/cookbook/formtitle.php");

If you now write [[?some title]] anywhere in your wiki, the formtitle script does several things:

  • use Glossary.RecentChanges to look up the title -- this is why the new entry page must be in the forms group and why the (title) is automatically put into the change summary
  • if no title is found, the markup links to Glossary.NewEntry and passes the title as the default value for the field designated as the (title) -- this is why we have to tell it the location of the new entry form
  • if it finds exactly one title match, it links to it
  • if it finds more than one title match (titles, unlike page names, do not need to be unique), it links to each of them in the order found on RecentChanges

Note that this markup assumes you only want to do this for one forms group per wiki. It needed a special and unambiguous markup and I chose [[?some title]] -- the price we pay, like for profiles and categories, is that it limits us to one title-based group. Using wikiforms without assigning a 5 digit name is problematic and would probably require a complete re-write of the recipe. Wikiforms knows to use a form because the page name is numeric.


Pagelist/searchbox template to search through Wikiform groups

Description

I'm using this template to search through multiple Wikiform groups from a searchbox directive. The results are displayed as a table with the following structure (links in example are fakes):

GroupPageTitle
Group n00042:title:Main Document
Group m00252:title:Supplementary Document

The title information is taken from paragraph 9 on my Wikiform pages. It would be cool if I could suppress the :title: markup that precedes the actual document title (documents are stored as attachments of the wikiform pages), but I don't know how to do that.

A slight problem is that pages in the searched groups that are not Wikiform pages are included in the list as well, leading to random lines to be included in the title field. Another slight problem is that the number of titles displayed is limited by $maxincludes, which might not always be enough. (I have set the value to 250, but there are ca. 3200 documents in my application.)

I could exclude the non-document pages as they do not start with a numeric character, but that would load up the searchbox with a rather lengthy string (searching pages 0*, 1*, 2*, 3*, ..., 9*), but I haven't implemented it that way yet because it seems crude. I'll look for a smarter way (if there is any). --Henning October 19, 2006, at 10:27 AM

Template

[[#headerinclude]]
(:if equal {<$Group}:)
(:table cellspacing:5px:)
(:cell:)'''Group'''
(:cell:)'''Page'''
(:cell:)'''Title'''
(:cell:)
(:if:)
(:cellnr:)[[{=$Group}]]
(:cell:)[[{=$FullName}|{=$Title}]]
(:cell:)(:include {=$FullName} lines=9..9:)
(:if equal {>$Group}:)
(:tableend:)
----
(:if:)
[[#headerincludeend]]

authorplain field type

This field type allows you to populate it with the author's name automatically, but without the profile markup.

In EntryForm(), insert the following clause (may need to appear before the one matching "author"):

        } elseif (preg_match('/^authorplain(?:=(\\d+))?$/',$f[$i]['etype'],$m)) {
            $col = ($m[2]) ? $m[2] : 32;
            if ($editing) $author = DeLink($fv[$f[$i]['element']]);
            else $author = FmtPageName('$Author',$pagename);
            $out[] = "<input type='text' size='$col' name='".$f[$i]['element'].
                    "' value='$author' />";

Also, in FormData(), insert the following clause:

        if (preg_match('/^authorplain/',$f[$i]['etype'])) {
            $v = $_REQUEST[$f[$i]['element']];
        }

shi December 20, 2006, at 02:44 PM

Added in version 1.0.52 jr March 22, 2007, at 06:38 PM

buttondate field type

I added this field type to allow the convenience of a button for setting today's date while editing an existing form, e.g. "date closed" of an issue tracking system. Note that the "Today" button is only shown while the date is undefined, to ensure that if the user changes an existing date, s/he really intended to do so.

Insert the following code near the top of wikiform.php:

## Add set date script to Header
$HTMLHeaderFmt['todays_date']= <<<SET_DATE
<script language="JavaScript">
<!-- Begin
function SetDate(elementName, y, m, d)
{
  // NOTE: we require that the Y/M/D elements appear
  //       in that order in the form
  var date = new Array(y, m, d);
  var index = 0;

  elements = document.getElementsByName(elementName);
  len = elements.length;

  for(i = 0; i < len; i++)
  {
    elements[i].value = String(date[index]);
    index += 1;
  }
  return;
}
//  End -->
</script>
SET_DATE;

In EntryForm(), insert the following clause:

        } elseif (preg_match('/^buttondate$/',$f[$i]['etype'],$m)) {
            if ($editing)
                $date = ($fv[$f[$i]['element']]) ? $fv[$f[$i]['element']] : 'yyyy-mm-dd';
            else
                $date = 'yyyy-mm-dd';
            $y = substr($date,0,4);
            $m = substr($date,5,2);
            $d = substr($date,8,2);
            $out[] = "<input type='text' size='5' maxlength='4' name='".
                    $f[$i]['element']."[]' value='$y' /> - ".
                    "<input type='text' size='3' maxlength='2' name='".
                    $f[$i]['element']."[]' value='$m' /> - ".
                    "<input type='text' size='3' maxlength='2' name='".
                    $f[$i]['element']."[]' value='$d' />";

            // only show "today" button if date does not yet have a value
            if ('yyyy' == $y)
            {
              $date = strftime('%Y-%m-%d',time());
              $y = substr($date,0,4);
              $m = substr($date,5,2);
              $d = substr($date,8,2);
              $element_name = $f[$i]['element'] . "[]";
              $out[] .= "<input type=button value='Today' onClick=\"SetDate('$element_name', $y, $m, $d)\">";
            }

Also, in FormData(), insert the following clause:

        elseif (preg_match('/^buttondate$/',$f[$i]['etype'])) 
            $v = str_replace('yyyy-mm-dd','',
                implode('-',$_REQUEST[$f[$i]['element']]));

shi December 20, 2006, at 02:44 PM

Added as a "today's date" checkbox in version 1.0.52 (no Javascript required). jr March 22, 2007, at 06:38 PM

attach field type

This creates a new field type 'attach' which silently adds "Attach:" markup to the input data. This makes attaching files to the page easier, since you don't have to put in the "Attach:" by hand, which is helpful for naieve users.

In EntryForm(), insert the following clause:

        } elseif (preg_match('/^attach(?:=(\\d+))?$/', $f[$i]['etype'], $m)) {
            $col = ($m[1]) ? $m[1] : 54;
            $out[] = "<input type='text' size='$col' name='".
                    $f[$i]['element']."' value='".
                    (($editing) ? DeFile($fv[$f[$i]['element']]) : $default).
                    "' />";
	}

Also, in FormData(), insert the following clause:

        elseif (preg_match('/^attach(?:=(\\d+))?$/',$f[$i]['etype'],$m)) {
            $v = $_REQUEST[$f[$i]['element']];
            if ($v) {
	    	$v = str_replace('Attach:', '', $v);
	    	$v = "Attach:$v";
	    }
	}

Kathryn Andersen February 06, 2007, at 05:39 PM

Something v similar exists at Cookbook:WikiFormsBugs#Attach Francis
If adding this feature to the core recipe, we might want to give forms administrators the option of restricting file types and generating a pick-list of allowed file types. For example, attach:pdf=32 would automatically append .pdf to the file name, with a form field 32 spaces wide. The form line generated might look like this: File name: Attach: [ . . . . . . . . . . . ].pdf (this might also display the "Attach:" prefix for additional clarity) jr March 22, 2007, at 06:38 PM
Attach field type added in version 1.0.57, includes the ability to specify a pick list of file types. jr December 13, 2007, at 09:10 PMjr

query against field values

Here is one way to implement a query to search given field values and return them in the (:wikilist ...:) list. It will result in a query that looks like this with the resulting wikilist after the "submit" is pushed:

Original Author Query:Albanian Author Query:
Original Title Query:Albanian Title Query:
Original Publisher Query:Albanian Publisher Query:
Type Query: Book
Booklet
Tract
Availability:

(Note that this example query form, above, is non-functional without the data and php code to go along with it -- this is just to give you an idea of what it looks like)

As you look at the following example here are some points to give you context:

  • This is a "database" to keep track of books (thus we are dealing with fields such as author, title, publisher, etc.)
  • These are translated books into the Albanian language, thus the opposing "original" and "Albanian" on each field
  • My main page containing the (:wikilist ...:) directive (the "query page") along with the fields to query, etc. is located at http://www.ccl-al.org/pmwiki/pmwiki.php?n=Alb.BookCatalog -- feel free to check that out if you want to see this "live"
  • The definition of the wiki fields can be found at http://www.ccl-al.org/pmwiki/pmwiki.php?n=Alb.FormTemplate -- again, feel free to check it out to see field types, etc.
  • This example is taken when I was dealing with several freeform text fields, one pulldown (where I wanted a checkbox in the query so they could choose any combination of the 3 valid values, and one checkbox where I wanted a pulldown allowing a choice of yes/no/both. The example on the live system may soon go past this...

In the page containing the (:wikilist ...:) directive (the "query page") you will have wiki source following this example:

(:messages:)\\
[+[[Add | Add a new book]]+]

(:input form "http://www.ccl-al.org/pmwiki/pmwiki.php?n=Alb.BookCatalog" method="GET":)
(:input hidden name=n "Alb.BookCatalog":)
|| border=0
|| Original Author Query:||(:input text name=origauthorquery:)|| Albanian Author Query:||(:input text name=albauthorquery:)||
|| Original Title Query:||(:input text name=origtitlequery:)|| Albanian Title Query:||(:input text name=albtitlequery:)||
|| Original Publisher Query:||(:input text name=origpubquery:)|| Albanian Publisher Query:||(:input text name=albpubquery:)||
|| Type Query:||(:input checkbox name=typebookquery value=1:) Book\\
(:input checkbox name=typebookletquery value=1:) Booklet\\
(:input checkbox name=typetractquery value=1:) Tract|| Availability:||(:input select name=availability value=1 label="BOTH in print and out of print":)
(:input select name=availability value=2 label="ONLY books still in print":)
(:input select name=availability value=3 label="ONLY books out of print":) ||

(:input submit Search:)
(:input end:)

All Items matching original author={$origauthorquery} original title={$origtitlequery} type=={$typequery} inprint=={$availablequery}
(:wikilist engauthor="{$origauthorquery}" engtitle="{$origtitlequery}" albauthor="{$albauthorquery}" albtitle="{$albtitlequery}" origpublisher="{$origpubquery}" albpublisher="{$albpubquery}" type="={$typequery}" inprint="={$availablequery}" :)

In the local/ directory create a custom configuration file (named Alb.BookCatalog.php in my case) with this php code:

<?php
foreach ($_GET as $k=>$v) {
   $foo = htmlspecialchars($v);
   # This keeps the field values current with the form from submission to
   # submission, but has nothing to do with PTV
   $InputValues[$k] = $foo;
   # This creates a PTV
   $FmtPV['$'.$k] = "'$foo'";
}
# If all (tract/book/booklet) are blank that's equivalent to all being
# selected -- none doesn't make any sense.
if ($FmtPV['$typebookquery'] != "'1'" && $FmtPV['$typebookletquery'] != "'1'" && $FmtPV['$typetractquery'] != "'1'") {
   $FmtPV['$typebookquery'] = "'1'";
   $FmtPV['$typebookletquery'] = "'1'";
   $FmtPV['$typetractquery'] = "'1'";
   $InputValues['typebookquery'] = 1;
   $InputValues['typebookletquery'] = 1;
   $InputValues['typetractquery'] = 1;
}
# Now from 3 variables ($type . <book|booklet|tract> . query) we need
# to form one variable ($typequery) to be used in the actual query with
# a value such as "book" or "book|tract" or etc
$typequery = '';
if ($FmtPV['$typebookquery'] == "'1'") {
   $typequery = 'Book';
}
if ($FmtPV['$typebookletquery'] == "'1'") {
   if ($typequery != '') {
           $typequery .= '|';
   }
   $typequery .= "Booklet";
}
if ($FmtPV['$typetractquery'] == "'1'") {
   if ($typequery != '') {
           $typequery .= '|';
   }
   $typequery .= "Tract";
}
$FmtPV['$typequery'] = "'$typequery'";

# Now from the $availability variable we need to make a query-able variable
# called $availablequery containing either blank (out of print) or "Yes" (in print
# or "|Yes" (either in print or out of print)
if ($FmtPV['$availability'] == "'3'") {
   $FmtPV['$availablequery'] = "''";
} else {
   if ($FmtPV['$availability'] == "'2'") {
      $FmtPV['$availablequery'] = "'Yes'";
   } else {
      # this is the default - whether the value is "1" (after form submission)
      # or whether it is blank (upon initial form access)
      $FmtPV['$availablequery'] = "'|Yes'";
   }
}

Peter Bowers December 12, 2007

Note the presence of Cookbook:ProcessForm which takes care of the basic creation of PVs as well as maintaining form values between submissions. Once you have that recipe installed you can put forms like this on any page without messing with group-specific or page-specific code. The only time you would need the page-specific code would be to do various validations. Peter Bowers March 06, 2008, at 11:40 AM

Edit - History - Print - Recent Changes - Search
Page last modified on March 06, 2008, at 11:40 AM