FormTools
Version 1.0 — 4th June 2010
FormTools is a collection of utilities for enhancing the usability of forms:
Each utility is separately controlled, and can be applied to the entire document, a single form or form-field, or to any arbitrary group of fields:
Get the script
Download the zipfile [126K], unpack it into your site directory
and add the main script and stylesheet to the <head>
section of your page:
<link rel="stylesheet" type="text/css" href="formtools.css" />
<script type="text/javascript" src="FormTools.js"></script>
The formtools.css
stylesheet
contains optional rules for styling the generated elements
that some of the methods create (as documented with each method). None of that
CSS is required,
because any critical style properties are set by the script,
but it gives you some useful examples as starting points.
You can happily use whatever styling you like, to match the elements to your design.
FormTools.js
is the main script containing the entire codebase.
But there's also a separate set of scripts for each individual method,
accompanied by a core script which has all the common stuff. So if you're
only using one of the methods, then you only need include the
script for that method, plus the core (which must come first).
For example, for masked password functionality:
<script type="text/javascript" src="library/FormTools.CORE.js"></script>
<script type="text/javascript" src="library/FormTools.addPasswordMasking.js"></script>
You may prefer to merge them together into one file, and if so make sure the core comes first.
All the FormTools
scripts have been aggressively compressed —
all comments and unnecessary whitespace have been removed, and most
of the names of variables, functions and so on have been
minimized to 2 or 3 characters. For your interest and reference,
the archive also includes copies of the original, uncompressed scripts,
which have extensive commenting and friendly names
Once you have the script(s) you need you'll be able to use their methods
(as detailed in the Developer’s Guide below).
Method-calls can come from anywhere on the page and don't have to wait for onload
,
but they obviously will need to be after the form-fields they apply to.
So the simplest thing to do is to put all such scripting at the end of the
<body>
section.
Developer’s Guide
The documentation covers all aspects of using and configuring FormTools
.
It should be straightforward enough that you don't actually need to
read these docs before you can get going, but they're here as a reference
whenever you need more information:
The universal context
argument
All the utility methods have a context
argument, which you can use to specify
the element, elements or document context to which the functionality
should be applied. It works the same way for all:
-
You can specify either a
String
ID
, in the format"#foo"
(a hash-symbol plus the element'sID
), or a directObject
reference to an element or document. - If you specify an element and it's an applicable form-field, then the functionality will apply only to that single element. If you specify any other kind of element, or a document, then the functionality will apply to all the applicable form-fields inside that context.
If you leave this argument empty it will default to the current document
.
Return values
All the utility methods return in the same way:
-
Methods which add functionality
(whose name begins with
"add"
) will return true to indicate successful initialization. Should they fail to initialize because of an error, they won't return at all. -
Methods which remove functionality
(beginning with
"remove"
) will return false to indicate successful removal. (Likewise.) -
Methods which don't initialize because of a browser exclusion
will return null. Currently, the only specific exclusion is for the
addCapsLockWarnings
method in Mac/Webkit browsers (Safari and Chrome), which is not implemented by default because they already have similar functionality built-in (an exclusion you can override with the"capslock-warning-macwebkit"
option). There are also general exclusions for unsupported browsers (all pre-DOM browsers, and Opera 8), and these will return null for all the utility methods.
The define
method does not return a value.
Known issues
This list summarizes the script's known issues, which will
hopefully be fixed in the next version; I say hopefully
because,
right now, I'm not sure that all of these problems actually have a solution
(#2 and #3 for example are deliberate behavior to improve security, and so can only
be fixed if other ways are found to bring these fields up to the same level
of security as ordinary password fields):
- masked-password fields can only be edited from the end, not from the beginning or the middle
- masked-password fields do not support autocomplete
- masked-password and show-password fields cannot have default values
- masked-password fields do not support single-click selection or default-value behaviors
- you can't have masked-password and show-password functionality on the same field
There is also one issue which probably can't be fixed, because it's a symptom of the vulgar code I had to use to make this work in IE!
- pre-existing event listeners on masked-password and show-password fields will be lost
It would be possible to code-fork between
Internet Explorer and others, so that only
IE has that last issue; but that could create
a significant behavioral discrepancy, which is potentially
worse than the problem — at least you know where
you are with this, and if it becomes an issue for you, simply
move the FormTools
method calls so that they come first.
(Listeners which apply via
event delegation
are naturally not affected.)
FormTools.addPasswordMasking([context]);
The addPasswordMasking
method converts ordinary "password"
fields into a special kind of masked-password field, in which
all the characters are obscured except the last one
— so you can see what you just typed, but the bulk of the
password is always obscured. They're like the iPhone's password fields
(also seen on Android and Symbian devices)
which are very popular with users as they strike a good balance between
security and usability.
This method only applies to "password"
inputs
(which are programmatically converted into "text"
fields).
Code example
FormTools.addPasswordMasking(
"#whatever" // context [OPTIONAL String|Object]
);
Arguments
- context [OPTIONAL String|Object]
-
The element, elements or document context to which the functionality should be applied.
Notes
- Forms reset onload
-
The parent form of all masked password fields will
have their
reset
event fired at load time. In addition to deleting the field's default value, this is an attempt to improve security and match the behavior of normal"password"
fields, by preventing residual values from being retained after soft-refresh. - Generated markup
-
This method needs to create a wrapper element around each original password field, so it has a unique output and positioning context. The original field will be removed and replaced by two generated fields — one
"text"
field for user input and display, and one"hidden"
field to contain the real, plain-text password (which is what gets submitted with the form). So to give a complete example, if you started with this HTML:<label for="pword">Password:</label> <input type="password" id="pword" name="pword" />
Then you'd end up with this (including the added
style
properties):<label for="pword">Password:</label> <span class="context-wrapper" style="position:relative;"> <input type="hidden" name="pword" /> <input type="text" id="pword" class="masked-password" autocomplete="off" /> </span>
The
class
name of converted password fields, the masking symbol, and the plain-characters limit, can all be specified via thedefine
method. All the attributes that are specified on the original password field (such as itsclass
andid
) will be copied across to the text field that replaces it, except for itsname
, which only the hidden field will have so that it's the one to get submitted.
Errors
- The context passed to FormTools.addPasswordMasking() is not valid.
-
The specified
context
is not an element or document, or it evaluates tonull
(eg. it doesn't exist)
FormTools.addShowPasswordCheckboxes([context]);
The addShowPasswordCheckboxes
method creates a labelled checkbox
next to each "password"
field,
that lets you toggle between a plain-text version,
and the regular starred-out version. This functionality is particularly
useful where users have to type very long or complicated passwords.
This method only applies to "password"
inputs.
Code example
FormTools.addShowPasswordCheckboxes(
"#whatever" // context [OPTIONAL String|Object]
);
Arguments
- context [OPTIONAL String|Object]
-
The element, elements or document context to which the functionality should be applied.
Notes
- Forms reset onload
-
The parent form of all show-password fields will
have their
reset
event fired at load time. In addition to deleting the field's default value, this is an attempt to improve security and match the behavior of normal"password"
fields, by preventing residual values from being retained after soft-refresh. - Generated markup
-
This method needs to create a wrapper element around each password field, in addition to the extra UI elements after it. The original
"password"
field is supplemented with a"text"
field, that stores the plain password and is hidden by default, so you can toggle between the plain and obfuscated versions at will. So to give a complete example, if you started with this HTML:<label for="pword">Password:</label> <input type="password" id="pword" name="pword" />
Then you'd end up with this (including the added
style
properties):<label for="pword">Password:</label> <span class="context-wrapper" style="position:relative;"> <input type="password" id="pword" name="pword" /> <input type="text" id="pword" class="plain-password" autocomplete="off" style="display:none;" /> <label class="show-password" title="Show the password as plain text" style="display:block;position:static;"> <input type="checkbox" title="Show the password as plain text" /> <span style="display:inline-block;">Show Password</span> </label> </span>
The
class
names, text and tooltips of the created elements can all be specified via thedefine
method. All the attributes that are specified on the original password field (such as itsclass
andid
) will be copied across to the text field that replaces it, except for itsname
, which the password field alone retains so that it's the one to get submitted. - Adding extra user-cues
-
In practice I'd use a longer
title
attribute for the checkbox and label than what's shown in the example above; something along the lines of:Show the password as plain text -- not advisable in a public place,
which is used in the main demo. (The tooltip value is specified with the"show-password-tooltip"
option.) Along with one of those little-yellow warning icons next to the label text, this can help to warn users that there's a risk in displaying their password on the screen.
Errors
- The context passed to FormTools.addShowPasswordCheckboxes() is not valid.
-
The specified
context
is not an element or document, or it evaluates tonull
(eg. it doesn't exist)
FormTools.addCapsLockWarnings([context]);
The addCapsLockWarnings
method creates little warning messages —
positioned next to "password"
fields and hidden by default —
that then appear if the user types into the field with Caps-Lock enabled.
This method only applies to password fields —
either regular "password"
inputs,
or masked password fields.
Code example
FormTools.addCapsLockWarnings(
"#whatever" // context [OPTIONAL String|Object]
);
Arguments
- context [OPTIONAL String|Object]
-
The element, elements or document context to which the functionality should be applied.
Notes
- Browser exceptions
-
By default, this method does not apply to Mac/Webkit browsers (Safari and Chrome), because they already have similar functionality built-in. But you can enable anyway it by changing the
"capslock-warning-macwebkit"
option to"yes"
. One reason to do this might be for masked password fields, which the native warnings won't apply to because they're not really"password"
fields. - Generated markup
-
This method needs to create a wrapper element around each password field, in addition to the extra UI elements after it. So to give a complete example, if you started with this HTML:
<label for="pword">Password:</label> <input type="password" id="pword" name="pword" />
Then you'd end up with this (including the added
style
properties):<label for="pword">Password:</label> <span class="context-wrapper" style="position:relative;"> <input type="password" id="pword" name="pword" /> <span class="capslock-warning hidden" title="Caps-Lock is ON!" style="display:none;position:absolute;left:100%;top:0;> Caps-Lock is ON! </span> </span>
The
class
names, text and tooltips of the created elements can all be specified via thedefine
method.
Errors
- The context passed to FormTools.addCapsLockWarnings() is not valid.
-
The specified
context
is not an element or document, or it evaluates tonull
(eg. it doesn't exist)
FormTools.removeCapsLockWarnings([context]);
The removeCapsLockWarnings
method reverses the effect
of addCapsLockWarnings
, deleting the warning element
and removing the functionality from any elements it's been applied to.
Code example
FormTools.removeCapsLockWarnings(
"#whatever" // context [OPTIONAL String|Object]
);
You don't need to be careful of which elements you call this method on — you can use it in broad brush-strokes to remove the functionality from a whole group of elements, even if only some of them had it applied in the first place.
FormTools.addDefaultValueBehaviors([context]);
The addDefaultValueBehaviors
method adds behaviors to applicable
text fields that clears or restores their default value, as appropriate:
if the field contains the default value, the value is cleared when the field
receives focus;
if the field is empty, the default value is restored when
the field loses focus.
Fields are also given a special class
name
that only applies when the default value is shown, and this can
be used to apply dynamic effects, such as grayed-out text.
This method applies to "text"
inputs, "password"
inputs
and "textarea"
elements.
Code example
FormTools.addDefaultValueBehaviors(
"#whatever" // context [OPTIONAL String|Object]
);
Arguments
- context [OPTIONAL String|Object]
-
The element, elements or document context to which the functionality should be applied.
Notes
- When to use or avoid this method
-
This method should not be used on form fields where the default value is important, such as pre-filled data in a user options form. It's intended for situations where the default value is just a prompt for user input, such as
Enter search terms...
in a search form's query field.If the default value is important pre-filled data, then
addSingleClickSelection
would be more suitable.
Errors
- The context passed to FormTools.addDefaultValueBehaviors() is not valid.
-
The specified
context
is not an element or document, or it evaluates tonull
(eg. it doesn't exist)
FormTools.removeDefaultValueBehaviors([context]);
The removeDefaultValueBehaviors
method reverses the effect
of addDefaultValueBehaviors
, deleting its class
and removing the functionality from any elements it's been applied to.
Code example
FormTools.removeDefaultValueBehaviors(
"#whatever" // context [OPTIONAL String|Object]
);
You don't need to be careful of which elements you call this method on — you can use it in broad brush-strokes to remove the functionality from a whole group of elements, even if only some of them had it applied in the first place.
FormTools.addSingleClickSelection([context]);
The addSingleClickSelection
method adds behavior to applicable
text fields, whereby the whole value is pre-selected whenever the
field receives focus (by tabbing into it with the keyboard,
or clicking into it with the mouse). Conversely, the value is unselected
when the field loses focus, or the cursor is moved internally.
This method applies to "text"
inputs, "password"
inputs
and "textarea"
elements.
Code example
FormTools.addSingleClickSelection(
"#whatever" // context [OPTIONAL String|Object]
);
Arguments
- context [OPTIONAL String|Object]
-
The element, elements or document context to which the functionality should be applied.
Notes
- When to use or avoid this method
-
This method is intended for situations where the default value is pre-filled, editable data, such as values in a user options form. Here the user is mostly likely either to leave the value unedited, or delete it and replace it with a new value, and that's the situation in which pre-selecting the value would be helpful.
If the default value is just a prompt for user input, then
addDefaultValueBehaviors
would be more suitable.
Errors
- The context passed to FormTools.addSingleClickSelection() is not valid.
-
The specified
context
is not an element or document, or it evaluates tonull
(eg. it doesn't exist)
FormTools.removeSingleClickSelection([context]);
The removeSingleClickSelection
method reverses the effect
of addSingleClickSelection
,
removing the functionality from any elements it's been applied to.
Code example
FormTools.removeSingleClickSelection(
"#whatever" // context [OPTIONAL String|Object]
);
You don't need to be careful of which elements you call this method on — you can use it in broad brush-strokes to remove the functionality from a whole group of elements, even if only some of them had it applied in the first place.
FormTools.addTextareaMaxlength(maxlength [, context]);
The addTextareaMaxlength
method implements a size-limit on the input value
of textarea
elements, analogous to the "maxlength"
attribute of input
elements, that prevents the user from entering more
than the specified number of characters.
The processing happens live as data is input, and applies
equally to user input, programmatic input, and default values.
This method only applies to "textarea"
elements.
Code example
FormTools.addTextareaMaxlength(
150, // maxlength [REQUIRED Number|String]
"#whatever" // context [OPTIONAL String|Object]
);
Arguments
- maxlength [OPTIONAL Number|String]
-
Specify a
Number
which is the integer max-length you wish to apply, such as150
characters. You can also define the max-length as a numerical-string like"150"
. - context [OPTIONAL String|Object]
-
The element, elements or document context to which the functionality should be applied.
Notes
- Multiple calls
-
If more than one max-length value is applied to an individual textarea (for example, if you're defining both a global and some individual values), then the last one to be defined will take effect.
Errors
- The maxlength specified in FormTools.addTextareaMaxlength() is not valid.
-
The
maxlength
value is missing or invalid. - The context passed to FormTools.addTextareaMaxlength() is not valid.
-
The specified
context
is not an element or document, or it evaluates tonull
(eg. it doesn't exist)
FormTools.removeTextareaMaxlength([context]);
The removeTextareaMaxlength
method reverses the effect
of addTextareaMaxlength
,
removing the functionality from any elements it's been applied to.
Code example
FormTools.removeTextareaMaxlength(
"#whatever" // context [OPTIONAL String|Object]
);
You don't need to be careful of which elements you call this method on — you can use it in broad brush-strokes to remove the functionality from a whole group of elements, even if only some of them had it applied in the first place.
FormTools.define(name, value);
The define
method is used for modifying the library's global
configuration options. All the options are private and can only
be modified using this method.
Code example
FormTools.define(
"caps-lock-warning-message", // option name [REQUIRED String]
"Caps-Lock is ON!" // option value [REQUIRED String]
);
Arguments / Notes / Errors / Options
Arguments
- option name [REQUIRED String]
-
A
String
that specifies which option you're defining (see the options list below for what's available). - option value [REQUIRED String]
-
The
String
value itself. This method has no defaults, so a value must always be specified.
Notes
- Allowed values
-
All the values are strings, and can only contain plain text (no HTML or entities, except in two cases which are documented in the options list below). But any of the values can contain unicode escape sequences, such as
"\u25CF"
which is the default password masking symbol. Furthermore any quotation-marks must be escaped (or expressed in unicode) — this is not validated by the script, but may result in JavaScript errors if you don't it.Option names which name end with
"-class"
are used forclass
names, and of course there are standard limitations on their syntax — they can't begin with a number, for example, and support a limited range of special characters. The script does not validate this either, so it's up to to make sure you use suitable values. - Using dynamic options
-
You can re-define options at any time, allowing you specify different values for different instances of the same method. But all options are retained for the lifetime of a method/field instance (including transient options, like state-dependent
class
names). So a field will use the values that were in force at the time a method was applied, even if those options are changed later.
Errors
- The option name or value passed to FormTools.define() is not valid.
-
The option name is missing or refers to an option that doesn't exist; or the option value is missing or contains HTML markup or entities when it's not allowed to.
List of available options
- Options table
-
The following table details all the available options, what they're for and their default value.
Name Description Default value context-wrapper-class
The class
name of the wrapper elements created by theaddPasswordMasking
,addShowPasswordCheckboxes
andaddCapsLockWarnings
methods. The wrapper is inserted directly around each applicable form field, so if you're applying structural CSS to that field, then you may need to apply it to the wrapper as well or instead. A complete HTML example is given with each relevant method."context-wrapper"
default-value-class
The class
name that's added to text fields, by theaddDefaultValueBehaviors
method, when their default value is displayed. This can be used as a dynamic styling hook, for example to apply a grayed-out effect."defaultValue"
capslock-warning-class
The class
name of the warning-message element created by theaddCapsLockWarnings
method."capslock-warning"
capslock-warning-macwebkit
Whether to add caps-lock warnings in Mac/Webkit browsers (Safari and Chrome), which is "no"
by default because they already have similar functionality built-in. But you can enable it by changing this option to"yes"
(for example, for masked password fields, which the native warnings won't include)."no"
capslock-warning-message
The content of the caps-lock warning-message. The message element itself is a block-level <span>
, with configurableclass
andtitle
attributes, plus whatever inner content you specify here. This option can contain HTML."Caps-Lock is ON!"
capslock-warning-tooltip
The title
attribute of the caps-lock warning-message, which will appear as a tooltip on the message element whenever it's displayed (but not when it's hidden). The purpose of this option is so you can make the message have purely graphical content, while still having usable information to describe it."Caps-Lock is ON!"
show-password-class
The class
name of the main<label>
element surrounding the group of elements created by theaddShowPasswordCheckboxes
method."show-password"
show-password-plainfield-class
The class
name of the created field used to store the plain-text version of the password. Thisclass
is made available purely as a styling-hook."plain-password"
show-password-text
The text written next to the show-password checkbox. This is a <span>
element directly after the checkbox, with inline-block display, plus whatever inner content you specify here. This option can contain HTML."Show password"
show-password-tooltip
The main <label>
title
attribute, which is also applied to the checkbox<input>
, and which will appear as a tooltip on one or both elements. to provide additional user information, such as the privacy warning included in the default value."Show the password as plain text — not advisable in a public place."
masked-password-class
The class
name of the masked password fields created by theaddPasswordMasking
method (which are converted into"text"
fields from original"password"
inputs)."masked-password"
password-masking-symbol
The symbol which is used to obscure a masked password, in place of the real characters. The default value is a small-round dot (●), which is what most browsers use for regular password fields. You may prefer to use something more esoteric, but do always consider the usability of what you choose — it must be obvious what it's for. "\u25CF"
password-masking-limit
The number of readable characters that are shown at the end of a masked password while it's being edited. This limit only applies while the password field has the focus — once it loses focus the whole value will be masked. "1"