Difference between revisions of "Widgets"

From Wiki
Jump to navigation Jump to search
(Hints about deprecated logging commands in MkIV, changes of <cmd> to {{cmd|)
(fix errors, enhance formatting)
(25 intermediate revisions by 4 users not shown)
Line 1: Line 1:
< [[Visuals]] | [[Interaction]] >
+
< [[Presentations]] | [[Basics|Text formatting]] | [[Interaction]] >
  
You find more about interactive elements in [http://www.pragma-ade.com/general/manuals/mwidget-s.pdf Widgets uncovered] and [http://source.contextgarden.net/core-fld.tex core-fld.tex].
+
You can find more about interactive form elements in [http://www.pragma-ade.com/general/manuals/mwidget-s.pdf Widgets uncovered]. It’s written for MkII, but still mostly valid.
  
At the moment all of the following examples are from <tt>mwidget</tt> manual. We will cook up our own later.
+
Most of the following examples are from the manual.
 +
 
 +
=Fields=
 +
 
 +
Create a field “class” with {{cmd|setupfield}}, then create single instances with {{cmd|definefield}}, finally typeset it with {{cmd|field}}.
 +
 
 +
That might look complicated, but you can use the same field several times, and the contents will automatically repeat themselves if you need the same content at several places, even on different pages. (Think e.g. of name, location and date in a set of forms.)
 +
 
 +
 
 +
Relevant commands:
 +
* {{cmd|setupfield}}
 +
* {{cmd|definefield|[name][type][setup name][content values][default content]}}
 +
* {{cmd|field|[name]}}
 +
 
 +
Field types:
 +
* line: one line of text
 +
* text: more lines of text
 +
* radio: radiobutton (only one of a group can be active)
 +
* check: checkbox
 +
* signature: electronic signature (since 2016-03-11)
 +
 
 +
===Single fields===
 +
 
 +
Since you often need fields only once, you can define your own shortcut macros:
 +
 
 +
<texcode>
 +
\setupfield[MyFieldSetup][reset,horizontal][... options ...]
 +
\define[1]\MyField{\definefield[#1][line][MyFieldSetup]\field[#1]}
 +
</texcode>
 +
 
 +
==Text Entries==
 +
 
 +
<texcode>
 +
\setupfield[ShortLine][horizontal][width=2cm,height=2em]
 +
\definefield [Email] [line] [ShortLine] [] [sample@contextgarden.net]
 +
\field [Email] [your email]
 +
</texcode>
 +
 
 +
==Checkboxes==
 +
 
 +
<texcode>
 +
\setupfield[setup 3]
 +
        [width=2cm, height=2cm,
 +
        rulethickness=3pt, corner=round, framecolor=red]
 +
 
 +
\definesymbol [yes] [{\externalfigure[mpcont.502]}]
 +
\definesymbol [no] []
 +
\definefield [checkme][check] [setup 3] [yes,no] [no]
 +
\field[checkme]
 +
</texcode>
 +
 
 +
==Radiobuttons==
 +
 
 +
Example from the manual:
 +
 
 +
<texcode>
 +
\setupfield [LogoSetup]
 +
        [width=4cm,
 +
        height=4cm,
 +
        frame=off,
 +
        background=color,
 +
        backgroundcolor=lightgray]
 +
 
 +
\definefield[Logos] [radio] [LogoSetup][ConTeXt,PPCHTEX,TeXUtil] [PPCHTEX]
 +
 
 +
\definesubfield [ConTeXt] [] [ConTeXtLogo]
 +
\definesubfield [PPCHTEX] [] [PPCHTEXLogo]
 +
\definesubfield [TeXUtil] [] [TeXUtilLogo]
 +
 
 +
\definesymbol [ConTeXtLogo] [{\externalfigure[mpcont.502]}]
 +
\definesymbol [PPCHTEXLogo] [{\externalfigure[mpcont.503]}]
 +
\definesymbol [TeXUtilLogo] [{\externalfigure[mpcont.504]}]
 +
 
 +
\hbox to \hsize{\hss\field[ConTeXt]\hss\field[PPCHTEX]\hss\field[TeXUtil]\hss}
 +
</texcode>
 +
 
 +
As usual, first you need to define a class of fields ({{cmd|setupfield}}). Then you define the (invisible) group of radio buttons ({{cmd|definefield}} with "radio"). At last you define the single radio buttons with {{cmd|definesubfield}}.
 +
 
 +
Arguments of {{cmd|definefield}}:
 +
# field name
 +
# field type "radio"
 +
# setup class, as defined by {{cmd|setupfield}}
 +
# list of field names that should be part of the group
 +
# name of default (activated) button
 +
 
 +
Arguments of {{cmd|definesubfield}}:
 +
# field name
 +
# setup class (default is inherited, but you can use a different one)
 +
# content symbol, defined by {{cmd|definesymbol}}
 +
 
 +
===Setup for questionnaire===
 +
 
 +
If you need a lot of similar radiobuttons, like in a questionnaire where you answer every question with a range choice, a meta definition makes sense. Fortunately it’s quite easy:
 +
 
 +
<context source=yes>
 +
\setupinteraction[state=start]
 +
\setupfield [ChoiceSetup][width=1em,height=1em,corner=00]
 +
 
 +
\definesymbol[X][X] % replace with dingbat symbol
 +
 
 +
\def\Choice#1{\definefield[#1:main][radio][ChoiceSetup][#1:1,#1:2,#1:3,#1:4,#1:5,#1:0][#1:0]%
 +
\definesubfield [#1:1][][X]%
 +
\definesubfield [#1:2][][X]%
 +
\definesubfield [#1:3][][X]%
 +
\definesubfield [#1:4][][X]%
 +
\definesubfield [#1:5][][X]%
 +
\definesubfield [#1:0][][X]%
 +
\field[#1:1]\,\field[#1:2]\,\field[#1:3]\,\field[#1:4]\,\field[#1:5]\hskip1em\field[#1:0]}
 +
 
 +
\def\ChoiceTitle{\hfill$-$\hskip4em$+$\hskip1.25em?\ \strut\par}
 +
 
 +
\def\Question{\dosingleempty\doQuestion}
 +
% We need the "optional" parameter as reference
 +
\def\doQuestion[#1]#2{%
 +
\iffirstargument
 +
#2\dotfill\Choice{#1}\par
 +
\else
 +
#2\par
 +
\fi
 +
}
 +
 
 +
\starttext
 +
 
 +
\ChoiceTitle
 +
\Question[q:ctx]{How much do you love \CONTEXT?}
 +
\Question[q:lua]{How are your Lua skills?}
 +
\Question[q:xml]{How often do you dream in XML?}
 +
 
 +
\stoptext
 +
</context>
 +
 
 +
== Fillin fields ==
 +
 
 +
{{cmd|fillinfield}} is meant for clozes (texts with gaps, like in questionnaires) and defined in the {{src|m-fields.mkiv|fields}} module (i.e. you need {{cmd|usemodule|[fields]}}).
 +
 
 +
<texcode>
 +
\fillinfield[name]{text that defines field length}
 +
</texcode>
 +
 
 +
Disable default validation with {{cmd|setupfieldcategory|2=[fillinfield][validate=]}}, because it removes the contents from the field!
 +
 
 +
There are some commands with a similar purpose in the {{src|pack-mrl.mkxl|core}} that don’t use fields:
 +
 
 +
* {{cmd|fillinline}}
 +
* {{cmd|fillintext}}
 +
* {{cmd|fillinrules}}
  
For PDF is only an interface, you need JavaScript to handle interaction (field input etc.).
 
  
 
=JavaScript=
 
=JavaScript=
 +
 +
If you want to check or otherwise process the input of your forms, you need JavaScript to handle interaction. For simple forms without input validation, you don’t need this.
 +
 +
'''Beware:''' JavaScript in PDFs works only in Adobe Acrobat Reader/Professional (Win/Mac only) and very few other PDF editors, e.g. [https://www.qoppa.com Qoppa]’s PDF Studio (also on Linux) supports JS even in the free viewer, but used to crash on all forms created with TeX in the 2019 version, maybe this is fixed now.
  
 
<texcode>
 
<texcode>
Line 37: Line 185:
 
* JS_N keeps the number of arguments
 
* JS_N keeps the number of arguments
  
=Fields=
+
== Documentation ==
 +
 
 +
JavaScript in Acrobat is different than in a web context. Documentation is sparse.
 +
Debugging is only possible in Acrobat Pro, and also there very inconvenient.
 +
Additionally, Acrobat’s possibilities change with every version.
  
{{Explanation}}
+
* [http://www.adobe.com/devnet/acrobat/javascript.html JavaScript documentation at Adobe’s]
 +
* [http://help.adobe.com/livedocs/acrobat_sdk/9.1/Acrobat9_1_HTMLHelp/wwhelp/wwhimpl/js/html/wwhelp.htm?href=JS_Dev_Tools.72.1.html&accessible=true JavaScript API Reference for Acrobat 9]
 +
* [https://acrobatusers.com/tutorials/javascript_console Tutorial on JS in Acrobat 11]
  
==Text Entries==
+
== Examples ==
  
see
+
=== Setting a default value ===
* {{cmd|setupfield}}, {{cmd|setupfields}}
 
* {{cmd|definefield}}
 
* {{cmd|field}}
 
* {{cmd|fillinfield}}
 
* {{cmd|fillinlines}}
 
* {{cmd|fillintext}}
 
* {{cmd|fillinrules}}
 
  
Beware, for fillinfields in MkIV you need {{code|\usemodule[fields]}}!
+
Here we set a date field to the current date on opening the document.
 +
Additionally we have a button that can hide/show a form field.
  
 
<texcode>
 
<texcode>
\fillinfield[name]{text that defines field length}
+
\starttext
% or
+
\setupinteraction [state=start]
\definefield [Email] [line] [ShortLine] [] [sample@contextgarden.net]
+
 
\field [Email] [your email]
+
\startJSpreamble {EXAMPLE} used now
</texcode>
+
var d = new Date();
 +
var df = this.getField("CurDate");
 +
df.value = util.printd("dd.mm.yyyy", d);
 +
 
 +
function toggleField(){
 +
var f = this.getField("CurDate");
 +
f.display = ! f.display;
 +
}
 +
\stopJSpreamble
  
{{cmd|definefield|[name][type][setup name][content values][default content]}}
+
\setupfield[shortString][reset,horizontal][height=5mm, width=50mm, frame=off, bottomframe=on]
 +
\definefield[CurDate][line][shortString][][JavaScript should replace this text with the current date]
  
{{cmd|field|[name]}}
+
Current date: \field[CurDate]
  
==Radiobuttons==
+
\stoptext
 +
</texcode>
  
Sample from the manual:
+
===Setting the current date===
 +
Similar, but more usable than the example above:
  
 
<texcode>
 
<texcode>
\setupfield [LogoSetup]
+
\starttext
        [width=4cm,
+
 
        height=4cm,
+
\setupinteraction [state=start]
        frame=off,
+
 
        background=screen]
+
\startJSpreamble {EXAMPLE} used now
 +
function Dummy(){
 +
return 0;
 +
}
  
\definefield[Logos] [radio] [LogoSetup]
+
function setCurrentDate(fieldname) {
[ConTeXt,PPCHTEX,TeXUtil] [PPCHTEX]
+
var f = this.getField(fieldname);
 +
f.value = util.printd("yyyy-mm-dd", new Date());
 +
}
  
\definesubfield [ConTeXt] [] [ConTeXtLogo]
+
setCurrentDate("myDateField");
\definesubfield [PPCHTEX] [] [PPCHTEXLogo]
+
\stopJSpreamble
\definesubfield [TeXUtil] [] [TeXUtilLogo]
 
  
\definesymbol [ConTeXtLogo] [{\externalfigure[mpcont.502]}]
+
\setupfield[dateString][reset,horizontal][width=5em,option=printable]
\definesymbol [PPCHTEXLogo] [{\externalfigure[mpcont.503]}]
+
\definefield[myDateField][line][dateString][][JavaScript should replace this text with the current date]
\definesymbol [TeXUtilLogo] [{\externalfigure[mpcont.504]}]
 
  
\hbox to \hsize{\hss\field[ConTeXt]\hss\field[PPCHTEX]\hss\field[TeXUtil]\hss}
+
Current date: \field[myDateField]
 +
\stoptext
 
</texcode>
 
</texcode>
  
==Checkboxes==
 
  
<texcode>
+
=Tricks and Traps=
\setupfield[setup 3]
+
 
        [width=2cm, height=2cm,
+
==General==
        rulethickness=3pt, corner=round, framecolor=red]
+
 
 +
* Nothing happens without {{cmd|setupinteraction|2=[state=start]}}! If you need an interactive version and a plain one (e.g. for print), then you must replace your form fields with something else (e.g. {{cmd|framed}}). Use [[Modes]].
 +
 
 +
==MkIV==
 +
 
 +
* JS code was only copied to the PDF if there was a {{cmd|goto}} referencing one of the defined functions! – This is actually a feature, you can get your JS without {{cmd|goto}}, using the magic incantation {{code|used now}}, as in the default value example. (This was fixed.)
 +
 
 +
* JS code for default values doesn’t work (reported 2015-04-01, still true 2015-10-07); default values are always used verbatim. (Unchecked if this is fixed.)
  
\definesymbol [yes] [{\externalfigure[mpcont.502]}]
+
* There is no <s>{{cmd|setupfields}}</s> (plural)!
\definesymbol [no] []
 
\definefield [checkme][check] [setup 3] [yes,no] [no]
 
\field[checkme]
 
</texcode>
 
  
=Tricks=
+
==MkII==
  
This helps debugging (MkII only!):
+
This helps debugging:
  
 
<texcode>
 
<texcode>
 
\tracefieldstrue
 
\tracefieldstrue
 
\showfields  % typeset a table of field relations
 
\showfields  % typeset a table of field relations
\logfields     % logs field descriptions to a file fields.log
+
\logfields   % logs field descriptions to a file fields.log
 
</texcode>
 
</texcode>
 +
 +
=Samples=
 +
 +
* [[Midgard PC sheet]] (RPG character sheet with lots of text fields in tables)
 +
 +
[[Category:Interaction]]
 +
[[Category:PDF]]

Revision as of 11:18, 20 February 2022

< Presentations | Text formatting | Interaction >

You can find more about interactive form elements in Widgets uncovered. It’s written for MkII, but still mostly valid.

Most of the following examples are from the manual.

Fields

Create a field “class” with \setupfield, then create single instances with \definefield, finally typeset it with \field.

That might look complicated, but you can use the same field several times, and the contents will automatically repeat themselves if you need the same content at several places, even on different pages. (Think e.g. of name, location and date in a set of forms.)


Relevant commands:

Field types:

  • line: one line of text
  • text: more lines of text
  • radio: radiobutton (only one of a group can be active)
  • check: checkbox
  • signature: electronic signature (since 2016-03-11)

Single fields

Since you often need fields only once, you can define your own shortcut macros:

\setupfield[MyFieldSetup][reset,horizontal][... options ...]
\define[1]\MyField{\definefield[#1][line][MyFieldSetup]\field[#1]}

Text Entries

\setupfield[ShortLine][horizontal][width=2cm,height=2em]
\definefield [Email] [line] [ShortLine] [] [sample@contextgarden.net]
\field [Email] [your email]

Checkboxes

\setupfield[setup 3]
        [width=2cm, height=2cm,
        rulethickness=3pt, corner=round, framecolor=red]

\definesymbol [yes] [{\externalfigure[mpcont.502]}]
\definesymbol [no] []
\definefield [checkme][check] [setup 3] [yes,no] [no]
\field[checkme]

Radiobuttons

Example from the manual:

\setupfield [LogoSetup]
        [width=4cm,
        height=4cm,
        frame=off,
        background=color,
        backgroundcolor=lightgray]

\definefield[Logos] [radio] [LogoSetup][ConTeXt,PPCHTEX,TeXUtil] [PPCHTEX]

\definesubfield [ConTeXt] [] [ConTeXtLogo]
\definesubfield [PPCHTEX] [] [PPCHTEXLogo]
\definesubfield [TeXUtil] [] [TeXUtilLogo]

\definesymbol [ConTeXtLogo] [{\externalfigure[mpcont.502]}]
\definesymbol [PPCHTEXLogo] [{\externalfigure[mpcont.503]}]
\definesymbol [TeXUtilLogo] [{\externalfigure[mpcont.504]}]

\hbox to \hsize{\hss\field[ConTeXt]\hss\field[PPCHTEX]\hss\field[TeXUtil]\hss}

As usual, first you need to define a class of fields (\setupfield). Then you define the (invisible) group of radio buttons (\definefield with "radio"). At last you define the single radio buttons with \definesubfield.

Arguments of \definefield:

  1. field name
  2. field type "radio"
  3. setup class, as defined by \setupfield
  4. list of field names that should be part of the group
  5. name of default (activated) button

Arguments of \definesubfield:

  1. field name
  2. setup class (default is inherited, but you can use a different one)
  3. content symbol, defined by \definesymbol

Setup for questionnaire

If you need a lot of similar radiobuttons, like in a questionnaire where you answer every question with a range choice, a meta definition makes sense. Fortunately it’s quite easy:

\setupinteraction[state=start]
\setupfield [ChoiceSetup][width=1em,height=1em,corner=00]

\definesymbol[X][X] % replace with dingbat symbol

\def\Choice#1{\definefield[#1:main][radio][ChoiceSetup][#1:1,#1:2,#1:3,#1:4,#1:5,#1:0][#1:0]%
\definesubfield [#1:1][][X]%
\definesubfield [#1:2][][X]%
\definesubfield [#1:3][][X]%
\definesubfield [#1:4][][X]%
\definesubfield [#1:5][][X]%
\definesubfield [#1:0][][X]%
\field[#1:1]\,\field[#1:2]\,\field[#1:3]\,\field[#1:4]\,\field[#1:5]\hskip1em\field[#1:0]}

\def\ChoiceTitle{\hfill$-$\hskip4em$+$\hskip1.25em?\ \strut\par}

\def\Question{\dosingleempty\doQuestion}
% We need the "optional" parameter as reference
\def\doQuestion[#1]#2{%
 \iffirstargument
 #2\dotfill\Choice{#1}\par
 \else
 #2\par
 \fi
}

\starttext

\ChoiceTitle
\Question[q:ctx]{How much do you love \CONTEXT?}
\Question[q:lua]{How are your Lua skills?}
\Question[q:xml]{How often do you dream in XML?}

\stoptext

Fillin fields

\fillinfield is meant for clozes (texts with gaps, like in questionnaires) and defined in the fields module (i.e. you need \usemodule[fields]).

\fillinfield[name]{text that defines field length}

Disable default validation with \setupfieldcategory[fillinfield][validate=], because it removes the contents from the field!

There are some commands with a similar purpose in the core that don’t use fields:


JavaScript

If you want to check or otherwise process the input of your forms, you need JavaScript to handle interaction. For simple forms without input validation, you don’t need this.

Beware: JavaScript in PDFs works only in Adobe Acrobat Reader/Professional (Win/Mac only) and very few other PDF editors, e.g. Qoppa’s PDF Studio (also on Linux) supports JS even in the free viewer, but used to crash on all forms created with TeX in the 2019 version, maybe this is fixed now.

\startJSpreamble {name}
MyCounter = 0 ;
\stopJSpreamble

\startJScode {increment}
MyCounter = MyCounter + 1 ; // or: ++MyCounter ;
\stopJScode

\goto {advance by one} [JS(increment)]

You can pass values to a JS function:

\startJScode {increment}
MyCounter = MyCounter + JS_V_1 ;
\stopJScode

\goto {advance by five} [JS(increment{V{5}})]
  • V{} is verbose, defaults to string
  • S{} = as string
  • R{} = as reference
  • JS_V_n, JS_S_n, JS_R_n are the names of the variables
  • JS_N keeps the number of arguments

Documentation

JavaScript in Acrobat is different than in a web context. Documentation is sparse. Debugging is only possible in Acrobat Pro, and also there very inconvenient. Additionally, Acrobat’s possibilities change with every version.

Examples

Setting a default value

Here we set a date field to the current date on opening the document. Additionally we have a button that can hide/show a form field.

\starttext
\setupinteraction	[state=start]

\startJSpreamble {EXAMPLE} used now
var d = new Date();
var df = this.getField("CurDate");
df.value = util.printd("dd.mm.yyyy", d);

function toggleField(){
	var f = this.getField("CurDate");
	f.display = ! f.display;
}
\stopJSpreamble

\setupfield[shortString][reset,horizontal][height=5mm, width=50mm, frame=off, bottomframe=on]
\definefield[CurDate][line][shortString][][JavaScript should replace this text with the current date]

Current date: \field[CurDate]

\stoptext

Setting the current date

Similar, but more usable than the example above:

\starttext

\setupinteraction [state=start]

\startJSpreamble {EXAMPLE} used now
function Dummy(){
	return 0;
}

function setCurrentDate(fieldname) {
	var f = this.getField(fieldname);
	f.value = util.printd("yyyy-mm-dd", new Date());
}

setCurrentDate("myDateField");
\stopJSpreamble

\setupfield[dateString][reset,horizontal][width=5em,option=printable]
\definefield[myDateField][line][dateString][][JavaScript should replace this text with the current date]

Current date: \field[myDateField]
\stoptext


Tricks and Traps

General

  • Nothing happens without \setupinteraction[state=start]! If you need an interactive version and a plain one (e.g. for print), then you must replace your form fields with something else (e.g. \framed). Use Modes.

MkIV

  • JS code was only copied to the PDF if there was a \goto referencing one of the defined functions! – This is actually a feature, you can get your JS without \goto, using the magic incantation used now, as in the default value example. (This was fixed.)
  • JS code for default values doesn’t work (reported 2015-04-01, still true 2015-10-07); default values are always used verbatim. (Unchecked if this is fixed.)

MkII

This helps debugging:

\tracefieldstrue
\showfields  % typeset a table of field relations
\logfields   % logs field descriptions to a file fields.log

Samples