Advanced FORM

This document discusses how to use NewtonScript in the context of HTML and Newt's Cape. Though eventually it may contain more introductory/tutorial information, currently it assumes at least some NewtonScript experience (via NTK or Newt Development Environment).

FORM_INIT

If you need to do some run-time initialization of a form, e.g., set a field to a different default value for the current user, you can include a :form_init method in your META definitions.

:form_init(fdata,action)
fdata
the default data frame
action
string for form action. (note: there could be multiple forms in a single document, this allows your method to discriminate)
modify form data frame prior to creation of form objects (or after a RESET)

For example:

<META NAME="DATA.form_init" CONTENT="func(fdata,action) ...">

FORM

Note: this is subject to change as we understand CGI scripts better.

When you tap a SUBMIT (tag description) button, Newt's Cape checks/interprets the ACTION URL defined earlier in FORM (tag description) with the following precedence:

1. DATA.<URL> = string

Similar to IMG and HREF, this can be used to map to something else, e.g., a soup name. For document to work on non-Newtons, you should use this rather than specifying a soup name directly.

<META NAME="DATA.someURL" CONTENT="&quot;Notes&quot;">
...
<FORM ACTION="someURL">

2. DATA.<URL> = method

The SUBMIT button invokes your method with four parameters:

  1. the Submit button (object) -- see later example
  2. title: book title (string)
  3. action: (string)
  4. form data: (frame)

During form entry, values are added to a special frame that is stored (temporarily) in a global frame (you can access this at run-time in your form object via :AllData(true). This frame is reinitialized when the Newton is rebooted, when the user performs a RESET, or normally after SUBMIT.

Your method is invoked in the context of the :BookData() frame, so has access to other information and methods that you may have stored there via DATA.. When your method completes, it should return TRUE if the form data should be RESET, i.e., restored to defaults; NIL if not.

For example, to just Print the info, assuming you have Newt, Sloup or NTK Inspector):

<META NAME="DATA.printIt"
	CONTENT="func(submit,title,url,data)
	begin
		Print(URL); Print(title); Print(data); /* print 3 values */
		TRUE; /* reset the data */
	end">
...
<FORM ACTION="printIt">

Other methods available in Submit context:

:RegisterCardSoup(soupName,indexes,appSymbol,items)
soupName
string for name of soup
indexes
array of index specs (must match existing specs, if any)
appSymbol
symbol
items
array of 2 strings, e.g., ["item", "items"]
this is used to create a new soup. to access an old soup, use GetUnionSoup(soupName). If you are creating 2.x-only forms, you could use RegUnionSoup directly.
:UnregisterCardSoup(soupName)
unregister the application's use of the soup. If you are creating 2.x-only forms, you could use UnRegUnionSoup directly.
:makeNote(str,styles, font)
str
text string
styles
array of run-code style info: len1, fontspec1, len2, fontspec2,...
font
frame or integer fontspec
create an entry in Notes from a text string, with styles or single font
:postSoup(btitle,soupname,fdata)
registers the soup, stores the data, unregisters the soup. btitle is ignored.
:postNotes(btitle,pnames,fdata)
btitle
string title of book
pnames
array of string printnames to control order/appearance of field names
fdata
frame of data
formats and creates a Notes entry. (called if ACTION="Notes")
:postMail(btitle,addr,fdata)
btitle
string title of book
addr
string email address
fdata
frame of data
creates an email entry using current mail transport. (called if ACTION="mailto:..." or for WebMail http:)

Here is a more complicated example in which your form decides what to do based on which SUBMIT button was tapped. Note: a Submit button first sets the value of the slot referred to by NAME -- here submitMeth -- before calling your method. The button object has several convenient methods e.g., postNotes and postMail (described above).

<META NAME="DATA.decide"
	CONTENT="func(submitobj,title,action,data)
	begin
		/* Mail button? */
		if StrEqual(data.submitMeth,&quot;Mail&quot;)
		then submitobj:PostMail(title,action,data)

		/* Notes button? */
		else if StrEqual(data.submitMeth,&quot;Notes&quot;)
		then submitobj:PostNotes(title,self.form_printnames.(Intern(action)),data)

		/* otherwise... */
		else begin Print(action); Print(title); Print(data); end;
		TRUE; /* reset the data */
	end">
...
<FORM ACTION="decide@foo.com">
...
<INPUT TYPE=SUBMIT NAME=submitMeth VALUE="Mail">
<INPUT TYPE=SUBMIT NAME=submitMeth VALUE="Notes">
<INPUT TYPE=SUBMIT NAME=submitMeth VALUE="Inspector">

3. appSymbol/methSym

If an application (with appSymbol) exists and has a method defined (methSym), it is invoked with a single (frame) parameter which is the data frame. You could use this, for example, to create a control panel or input form for another Newton application.

4. Notes

If the ACTION is "Notes" (or mapped to Notes), the data is written to the Notepad, as follows:

FORM: book title

slot1: value(s)
slot2: value(s)

5. Print()

If the ACTION begins with "Print()", the data frame is passed to the Newton's Print function. This can be useful for testing. If you have the NTK Inspector connected, the result will appear there. If you have Sloup connected, the result will appear in your terminal emulator. If NewtDevEnv is open (with Print? checked), the result should appear in EvalLog (close the book to see it). If you had multiple ACTIONs in a document, you could use Print()1, Print()2, etc.

6. mailto:

Puts data as text with values delimited for http servers, e.g., ?x=1&y=2 into an email message in your Outbox..

7. http:

If the ACTION begins with http: (or the current document has a BASE to resolve the relative URL), the data will be sent either via NIE or WebMail.

8. soup/soupname

Finally, if preceded by "soup/", Newt's Cape interprets the remainder of the URL as a soup name and adds the data frame to the soup. This assumes you would use Sloup to later "DUMP" the data as tab-delimited text, or use another soup or synchronization utility.

Note about Data frame values. Generally, HIDDEN values should be defined early in the form so that they are available to later fields (possibly for initialization). If a user quits a book (saved package) without RESETting data, the data is preserved until the next system reset.

Adding attributes to FORM objects

The DATA. mechanism provides a flexible, reasonably transparent, mechanism for customizing IMG, HREF, and FORM(SUBMIT) behavior. We would also like to allow customization of individual Newton form objects such as input fields, checkboxes, etc. At the time of this writing, you can add a SCRIPT attribute to individual objects (basically a method that is invoked whenever the field value changes). However, since this is a non-standard HTML extension, we are exploring how this (and other attributes) such as viewFlags can be added using DATA.

VALUE_TYPE

When you double-tap a TEXT field, a alphanumeric keyboard normally pops up. If you specify a VALUE_TYPE attribute that begins with DATE, INT (or NUM), PHONE, TIME, FAX, ADDRESS, NAME, COUNTRY, CITY, STATE, PROVINCE, this provides different recognition defaults for handwriting, and a different, value-specific keyboard may appear when you double-tap. (This assumes that there wasn't a more specific type defined via a prototype). It does no other value checking. In summary, if the VALUE_TYPE equals or begins with

[none] (default)
standard alphanumeric keyboard
int (or num)
numeric keypad
date
date keypad
phone
phone keypad

VALUE_TYPE can also access a user prototype defined earlier via META. There are detailed examples in nformobj.htm. This discusses the implementation, with examples of AZ-picker, date and time pickers/fields, country, city, state, province, latitude&longitude pickers/fields, character edit field, integer picker, name, fax, phone, email, meeting place picker/fields. For example, you could use a new type, e.g., "INTSLIDER" in a standard INPUT object:

<P>
<INPUT TYPE="TEXT" VALUE_TYPE="INTSLIDER" NAME="slider1">

The reason for starting the name with "INT" is that if the object were not created, either because the user did not enable NewtonScript: Compile or the object was based on a undefined prototype (e.g., 2.x proto on 1.x system, it would at least default to using a numeric recognition and keyboard.

Here's how INTSLIDER would have been defined earlier (see nformobj.htm)

<META NAME="DATA.INTSLIDER" CONTENT="{
_proto: @212, /*protoSlider*/
NAME:	nil,
VALUE:	"0",
viewSetupFormScript: func()
begin
	local val := :GetData(NAME);
	viewValue := Floor(StringToNumber(if StrFilled(val) then val else VALUE));
end,
changedSlider: func()
begin
	:SetData(NAME, SPrintObject(viewValue));
end,
/*copy these attributes (if present) directly to the view object and convert to integers*/
copy_Attributes: {MINVALUE: 'INT, MAXVALUE: 'INT},
}">

This frame (and its values) are evaluated at the time the document is processed (not later at run-time). If you have access to Newton Toolkit or NewtDevEnv and can develop and test your prototypes there, you will have the most success and least frustration. You need to be especially careful about HTML vs. NewtonScript quoting conventions. Some slot-by-slot notes:

DATA.xxx
as noted earlier, this name is used to identify the proto later. If the underlying data is an integer, date or phone number, you might begin the proto name with INT, DATE, or PHONE to take advantage of different keyboards in case your protos aren't defined.
_proto (or viewClass)
currently this is required (to avoid accidental use of other frame DATA values). If you do not have NewtDevEnv (or appropriate plugins installed), safest to use the literal "magic pointers" rather than symbolic names. You could also use a proto value that is based on an earlier proto definition in the document (e.g., intslider1 expression later), or an external proto in a library or other application.
NAME
name of the field -- required for a form object. this will be set to a symbol from the NAME attribute
VALUE
optional. defaults to "" usually, but if user includes a VALUE attribute, use that string during initialization
copy_Attributes
optional. somewhat like PARAM for APPLET. you may want to allow the HTML author to provide some additional attributes for initializing (or checking) in your prototype. Here for example, a slider can have a minValue which defaults to 0, and/or maxValue (100). For different sliders, you could create a separate NewtonScript definition for each object, each with its minValue and maxValue slots, e.g., NAME="intslider1" CONTENT="{_proto: INTSLIDER, minValue: 10, maxValue: 230}". But another way is to specify these parameters directly via HTML attributes. copy_Attributes specifies which additional attributes to use and how to convert them at build time. The allowable types are:
int
integer
symbol
symbol
compile
NewtonScript expression/result

For example:

<P>
<INPUT VALUE_TYPE="INTSLIDER" NAME="slider2" VALUE="20" HEIGHT="12" MINVALUE="0" MAXVALUE="200">
viewSetupFormScript
obtain the current (or default) value of the field, do any initialization, and finally complete initialization of the object by calling inherited:?viewSetupFormScript(); (this is not needed for protoSlider, and in fact would cause an error). the :getData method was automatically added to your object's definition by Newt's Cape. getData returns the current value for a given NAME (in current form) as a string. In the example, either that value or the default value is converted to an integer and set to a slider's viewValue slot.
changedSlider
each prototype object usually has a method that's called when "there's been a change" -- however, the name and parameters are not standard. changedSlider takes no parameters; viewValue already contains the new integer value. the :setData method was automatically added to your object's definition by Newt's Cape. setData sets a string (for the current value) for a given NAME (in current form).

Some additional notes. A normal TEXT field may have a non-standard LABEL attribute (which corresponds to the preceding string in the paragraph) added by Newt's Cape. Since a slider does not have a label, in the examples above, the INPUT statements are preceded by <P>. However, there are cases, such as protoDateNTimeTextPicker that do allow a LABEL, in which case it can automatically take advantage of any "label" that Newt's Cape provides.

The HEIGHT of a normal TEXT field defaults to 20 (or to the height of the LABEL). If you want to specify a different height, you can include a HEIGHT attribute (as in the earlier example), though this will be ignored if the object defaults back to a regular TEXT field.

Other fields (unused in this example):

LABEL
string to be used as label. if the prototype does not have a label, it should probably have an explicit <P><INPUT... to prevent loss of info
MAXLENGTH
integer. if useful
HREF
string -- a link reference (URL or destination). If tapping somewhere to follow a link makes sense, then you could include this in source around the label and then do :getURL().

This is new functionality; feedback/suggestions appreciated. Take a look at the examples available -- currently, there are three, but there will be more as time permits, especially if users ask questions or donate source.

For More Info

This document (in all its formats) is © 1995-99. Steve Weyer, Greg Simon. All Rights Reserved Worldwide

Version 2.0. Last updated: Feb 1999


Steve Weyer - weyer@kagi.com
Greg Simon - greg@accesscom.com