From Kolmafia
Jump to navigation Jump to search

Attention KoLmafia Users!

This page details the use of functions in a script library. The information here is only useful to those who have followed the included steps to make use of these functions; they are not built-in to KoLmafia.

About jasonharper's Form Library

HTMLform is a code library for building relay browser scripts that accept user input.


The purpose of HTMLform is to allow you to write relay scripts without necessarily having a deep knowledge of HTML forms (although you will need to know at least a bit about HTML formatting if you want your scripts to look nice). It is designed to make the process of gathering input from the user look like a simple sequence of prompts, when in fact the script is being reloaded multiple times in order to present and validate the user's choices.


There are two global variables defined by the library that you'll need to know about: string [string] fields is a map holding the result of a call to form_fields(). The current value of any input element can be retrieved as fields[name], although you probably won't have to do that very often as the functions that actually write the elements to the page will return the current value of that element. You can also modify values in the map, prior to writing the corresponding element, to change their value - for example, to change the default values of certain fields based on the user's input in other fields. The global boolean success is true when a valid page submission has occurred - the fields map will be non-empty (unlike the initial run of the script in which the choices are initially shown in the browser), and none of the fields have a validation failure. Button actions should generally be conditional on this variable being true (and will automatically be so, if you use the test_button() function).

All other internal global variables, and functions for internal use, have names starting with an underscore, to minimize the chance of a name collision with your script.


Every HTML form element requires a distinguishing name, which for maximum compatibility should be chosen with the same basic rules as ASH variables - start with a letter, use only numbers and letters. Take care if you're generating names automatically; for example, if you were generating a field for each item in a list, it would be a bad idea to use the actual item names as (part of) the fields' names, since items may have arbitrarily weird characters in their names. The items' ID numbers (retrievable with to_int()) would be a much safer basis for making field names.

For the most part, element names must be distinct (and strange things will happen if you violate that). There are two exceptions:

  • Radio buttons normally come in mutually-exclusive groups, all of which must share the same name - in fact, that's the only thing that relates them as a group (there's no requirement for them to be physically grouped, although of course that would usually be good style).
  • Submit buttons can share a name if they do the same thing - for example, you might want to have a "Save changes" button at both the top and bottom of a tall form. If a button has no action at all (it just updates the form), its name can be left blank.


There is a large and ever-growing set of optional attributes that can be specified to customize the appearance and behavior of HTML form elements. It would be utterly impractical for htmlform to have optional parameters for every possible attribute, or even for every particularly useful attribute. Instead, you can supply arbitrary attributes by preceding the call that writes an element with one or more calls to: void attr( string attribute ) The string will be inserted at the appropriate place in the HTML tag being written. If called multiple times, the strings will be separated by spaces.


attr("title='TEXT'" ) will add a tooltip to any element. Advanced users may want to use style & class attributes for fine control over element appearance. A complete list of attributes is entirely beyond the scope of this documentation (see any HTML reference, instead), but the most useful ones will be pointed out in blocks like this.


The functions that produce a field for the user to type in (both write_field() and write_textarea()) can be passed the name of a validator function that can check (and possibly modify) the field value. Any validation failure is shown in red to the right of the field, and blocks submission of the form until the user corrects the problem. Validator functions are provide for all the datatypes for which typed-in values make sense: intvalidator, floatvalidator, itemvalidator, locationvalidator, skillvalidator, effectvalidator, familiarvalidator, monstervalidator (They AREN'T provided for types like 'class' and 'slot' that have only a few possible values; other input elements are more appropriate in those cases). None of these accept the 'none' value; there is a separate itemnonevalidator that will accept items or 'none' (similar validators for other types didn't seem likely to be as useful). There is also a nonemptyvalidator that simply requires the entered string to not be blank.

Additionally, intvalidator and floatvalidator support bounds checking via the function:


void range(float min ,float max )

Pace this just before the call to write_field().

The provided validators only check that the entered text is something understandable to KoLmafia - not that you (for example) actually have the named familiar, or that the item goes in some specific slot. If you want to perform such checks, you'll need to write your own validator, which is just a function with one string parameter (the element name), that returns a string. Any non-empty string is treated as a validation error. Returning an empty string indicates success, in which case the function is allowed to modify the value in the fields[] map, which will update the value shown in the browser. (That's why the function is passed the field name, rather than the field value. All of the built-in validators that allow fuzzy matching use this feature, in order to replace an abbreviated user entry with the full, proper name of the object.) Here's a simple example that verifies that the entered text is a valid item (duplicating the function of itemvalidator), which furthermore is a hat that you own:

string hatvalidator(string name) 
    item it = to_item(fields[name]);
    if (it == $item[none]) {
        return "A valid hat is required.";
    fields[name] = to_string(it);    // normalize
    if (item_type(it) != "hat") {
        return "That's not a hat.";
    if (available_amount(it) == 0) {
        return "You don't have that hat.";
    return "";    // success!

You'd then pass "hatvalidator" as the 4th parameter to write_field().

Top-Level Functions


void write_header()


void finish_header()


void write_page()

write_page() is equivalent to write_header() followed by finish_header(), but the separate functions may be preferred so that you can add information into the page header such as a script or stylesheet.


void finish_page()

This must be used at the end of the form.


void write_box(string label )


void finish_box()

These can be used in matched pairs around a group of elements to enclose them in a box. The label will be at the top of the box.
attr("align=center") or attr("align=right") will change the position of the label.


boolean test_button()

Making use of HTMLform

To include this library in your script, first you must download it from the location provided below and make sure it is in your /scripts directory (or a sub-directory thereof). Then, simply add the following towards the top any script in which you wish to have access to these functions:

import "htmlform.ash";

Then all these functions will be available in your script. Have fun! Note that most of these functions are intended for use in relay info scripts, which must be placed in the /relay directory (top-level only, no sub-directories) and must begin with "relay_" to show in the user's relay browser.

More Information

See the thread for HTMLform on the KoLmafia forum here.