MGCheckListPrompt Documentation

MGCheckListPrompt is a custom list picker dialog for Drafts version 21 or later, intended for use by Actions developers. It allows choosing any number of items from a list; the items may be drafts, or arbitrary objects. Various configuration options are available.

The latest version of this documentation is available here.

Note: MGCheckListPrompt also supports a single-selection (radio-button) mode — see the .singleSelectionMode property. This replaces the now-deprecated separate MGListPrompt project.


Download

Available from the Drafts Actions repository.

Appearance

Screenshots of MGCheckListPrompt in use are shown below.

MGCheckListPrompt on iPad, light mode.
MGCheckListPrompt on iPad, light mode.
MGCheckListPrompt on iPhone, dark mode.
MGCheckListPrompt on iPhone, dark mode.

Background

Drafts 21 introduced the ability to execute JavaScript within the built-in HTMLPreview window, and to return values from that window to the calling context. This makes it possible to construct custom user interfaces using HTML, CSS, and JavaScript, and to use them within Action scripts. MGCheckListPrompt is such a construct.

Author

MGCheckListPrompt was created by Matt Gemmell.

Please send any feedback via email, instead of social media.

Supported Platforms

All current Drafts platforms are supported: iPadOS, iOS, and macOS.

Functionality

Note: On macOS only, keyboard control of the prompt may first require focusing its content area. Depending on your “Use keyboard navigation to move focus between controls” setting (in System Preferences ► Keyboard ► Shortcuts), this can be accomplished by pressing either Tab or Option-Tab until the keyboard focus moves into the prompt’s content. This is not necessary on iPadOS or iOS.

How to Use

  1. Ensure that you’ve installed the MGCheckListPrompt Library action (part of the MGCheckListPrompt Action Group), and that you have Drafts 21 or later.

  2. Within your own action, add an Include Action step, and set the name value to “MGCheckListPrompt Library”.

  3. You can now use MGCheckListPrompt in your own subsequent script steps.

Example JavaScript

Some example Actions are included with the MGCheckListPrompt Action Group. The following code is a trivial example of MGCheckListPrompt’s use.

// Get most recently modified drafts in the Inbox.
var drafts = Draft.query("", "inbox", [], [], 
									"accessed", true, false)
									.slice(0, 15);

// Create an MGCheckListPrompt to choose some drafts.
var prompt = new MGCheckListPrompt();
prompt.message = "Pick one or more drafts:";
prompt.addDrafts(drafts);

// Show the prompt.
var selectedItems = prompt.show();

// Report the result.
if (prompt.didShow) {
	if (selectedItems != null) {
		var numItemsChosen = selectedItems.length;
		app.displaySuccessMessage(numItemsChosen + " item(s) were chosen.");
		
	} else {
		app.displayInfoMessage("Prompt was cancelled.");
	}
} else {
	app.displayErrorMessage("Something went wrong.");
}

API

The following properties and methods are available on an MGCheckListPrompt object.

Properties

.title

String. The title of the prompt, as shown in its titlebar.

Note: The titlebar is not shown by default. It can be shown via .showWindowControls if required.

To provide instructional text to the user at the top of the prompt, see the .message property below.

Default value: "Select"

.message

String. A brief explanatory message shown at the top of the prompt.

Note: If the value is an empty string, the message area will not be shown.

Default value: "Select one or more options:"

.okButtonTitle

String. The title of the OK button, which confirms the chosen options and dismisses the dialog. If the value is an empty string, “OK” will be used.

Default value: "OK"

.choices

Array of dictionaries. The choices (list items to choose from) shown in the prompt. It’s best to use this property only as a getter; to add choices either individually or in bulk, use the various add… methods detailed below instead. See the addItem(dict) method for details of the dictionary keys.

Note: If there are no choices, the dialog will not actually be shown when show() is called. This situation can be detected by checking the value of .didShow afterwards.

Default value: []

.selectedItems

Array of integers. The indices of the items that were chosen in the prompt, if any.

Default value: []

.didShow

Boolean. After the show() method has been called, this indicates whether the prompt did indeed show or not (regardless of whether any items were chosen, or the prompt was subsequently cancelled).

In particular, .didShow will be false if there are no items to display; it will not be shown in this situation.

Default value: false

.escapeHTML

Boolean. Determines whether HTML tags and entities within the prompt’s choices will be escaped (i.e. converted to plain text) before being displayed. Enabled by default.

For example, when enabled, the HTML tag <strong> will be displayed as plain text in the prompt. When disabled, the tag will be “injected” into the prompt as HTML, and will thus affect subsequent content. Take care to avoid unintended consequences.

Note: If enabled, this takes effect before .processMarkdown.

Default value: true

.processMarkdown

Boolean. Determines whether Markdown within the prompt’s choices will be converted to HTML before being displayed. Disabled by default.

For example, when enabled, the string _hello_ will be converted to the HTML <em>hello</em> before being added to the prompt.

Note: If enabled, this takes effect after .escapeHTML.

Default value: false

.allowsTypeToSelect

Boolean. Determines whether the user can type to select choices, using partial matching of their entire content. If enabled, this will disable the ability to use the number keys to directly select the first ten choices.

Type to Select
Type to Select

This feature is mutually exclusive with .allowsTypeToFilter, and will be disabled if .allowsTypeToFilter is enabled.

Note: By default, the user’s typed query is visually highlighted within the matching items in the list. To disable the highlight feature, see the .showQueryHighlight property.

Default value: false

.allowsTypeToFilter

Boolean. Determines whether the user can type to filter the list of choices, using partial matching of their entire content. See the .allowsTypeToSelect feature for how this alters the keyboard shortcuts that are available.

This feature overrides .allowsTypeToSelect, and will disable it if both are used together. See the addItem(dict) method for how to add a hidden metadata field to choices which will be used when filtering.

Note: By default, the user’s typed query is visually highlighted within the matching items in the list. To disable the highlight feature, see the .showQueryHighlight property.

Default value: false

.showQueryHighlight

Boolean. If .allowsTypeToSelect is enabled, this determines whether the user’s typed query is visually highlighted within the matching item in the list. Enabled by default.

Default value: true

.includedDraft

String. The title (or portion of the title) of a draft to include inline within the prompt. This works as follows.

A possible use of this functionality is to override the prompt’s CSS to create custom appearances, without needing to edit the MGCheckListPrompt Library action itself. See also .includedContent.

Default value: ""

.includedContent

String. Similar to .includedDraft, this is optional content to include inline within the prompt’s HTML. See the .includedDraft property for details on where the content will be inserted.

The two properties can be used together, in which case .includedDraft precedes .includedContent.

This feature can be useful for embedding custom CSS via a <STYLE> tag, or including external JavaScript libraries online via a <SCRIPT> tag. An example of overriding the prompt’s CSS (making the light-theme highlight colour be purple instead of blue) is shown below.

prompt.includedContent = `
<style>
:root {
	--highlight-color-light: #90f;
}
</style>
`

Note: To override CSS on a per-choice basis, see also the addItem(dict) method.

Default value: ""

.showWindowControls

Boolean. Determines whether the usual HTMLPreview window controls will be shown. Disabled by default. Re-enabling the window controls (for example, the Share button which will export the prompt’s HTML) can be useful for debugging.

Default value: false

.showHelp

Boolean. Determines whether the Help button will be shown at the top-right of the prompt (on larger screens). Enabled by default. When tapped or clicked, the Help button shows an overlay with details of the various keyboard shortcuts currently available (which vary depending on whether .allowsTypeToSelect is enabled).

Help overlay
Help overlay

Note: The help overlay can also be summoned or dismissed with Ctrl-/, regardless of the status of this setting.

Default value: true

.showSelectionCounter

Boolean. Determines whether a live count of the number of selected items will be shown. Disabled by default.

Selection counter
Selection counter

Default value: false

.roundedCheckboxes

Boolean. Determines whether checkboxes have a circular background, instead of the usual rectangular shape. Disabled by default.

Rounded checkboxes
Rounded checkboxes

Default value: false

.showNumericShortcuts

Boolean. Determines whether the numeric shortcut keys 1–0 (to immediately select items 1–10 respectively) are shown within the corresponding checkboxes when unchecked. Disabled by default. This has no effect when .allowsTypeToSelect is enabled.

Numeric shortcuts
Numeric shortcuts

Default value: false

.singleSelectionMode

Boolean. Determines whether the prompt behaves as a single-selection (i.e. radio-button) list, rather than the usual multiple-selection checkbox list. Disabled by default. When enabled, the following features behave differently:

The remaining settings and functions behave as normal.

Note: There are two settings which pertain specifically to single-selection mode: see .allowsDoubleClickToSelect and .selectsImmediately.

Single-selection mode
Single-selection mode

Default value: false

.allowsDoubleClickToSelect

Boolean. When .singleSelectionMode is enabled, this property determines whether choices can be double-clicked (or double-tapped) to immediately select them — i.e. to choose them and confirm the choice all in one action, immediately dismissing the prompt. Enabled by default.

Note: This only takes effect if .singleSelectionMode is enabled. It will also be ignored if .selectsImmediately is enabled.

Default value: true

.selectsImmediately

Boolean. Determines the interaction mode of the prompt when .singleSelectionMode is enabled, as follows.

Note: This only takes effect if .singleSelectionMode is enabled. Even though the OK button is hidden, the Return key can still be used to accept the user’s choice and dismiss the prompt. As a convenience, if there’s no current choice but there is a keyboard selection, the selected item will automatically be chosen when the Return key is pressed.

Default value: false

.preprocessingFunction

Function. An optional JavaScript function which will be used to preprocess the list content, before it is displayed in the prompt. The function can have any name, but should accept three parameters, and return a string. The parameters are as follows.

  1. Integer. The index (zero-based) of the choice currently being processed.

  2. String. The name of the property currently being processed for this choice: title, description, or info.

  3. String. The content of the corresponding property.

An example function is shown below.

function myProcessContent(itemIndex, propertyName, content) {
	// ...
	return content;
}

// ...
prompt.preprocessingFunction = myProcessContent;

Note: The preprocessing phase happens before either .escapeHTML or .processMarkdown are applied. In particular, if your preprocessing function inserts HTML content, you may wish to disable .escapeHTML (on by default). Conversely, if your preprocessing function inserts Markdown content, you may wish to enable .processMarkdown (off by default).

Default value: null

.validationFunction

See the Validation section.

Methods

addDraft(draft)

Parameters: draft (Draft object)

Adds a Draft object to the prompt’s choices by extracting the following information to create an item dictionary (see the addItem(dict) method below).

Return value: None

addDrafts(draftsArray)

Parameters: draftsArray (Array of Draft objects)

Adds an array of Draft objects to the prompt’s choices. See the addDraft(draft) method for more information.

Return value: None

addItem(dict)

Parameters: dict (Dictionary)

Adds an item dictionary to the prompt’s choices. The available keys are as follows.

Flagged status
Flagged status

See also the setSelectedItems(indexArray) method to set several pre-selected items at once.

Return value: None

addItems(dictsArray)

Parameters: dictsArray (Array of Dictionaries)

Adds an array of item dictionaries to the prompt’s choices. See the addItem(dict) method for dictionary keys.

Return value: None

addSeparator(title)

Parameters: title (String)

Adds a visual separator to the displayed list of choices. The title parameter is optional.

Return value: None

setSelectedItems(indexArray)

Parameters: indexArray (Array of Integers)

Sets which items will already be selected (checked) when the prompt is shown. Indices are zero-based, and need not be in any particular order. Indices which are out of range will be ignored.

Note: As a convenience, you can pass a string instead of an array: all will select all items, and none (or anything else) will select none.

Return value: None

escapeHTMLString(html)

Parameters: html (String)

Convenience method to escape the given string’s HTML tags and entities, causing them to be shown as plain text.

Return value: String

loadDraftWithTitle(draftTitle)

Parameters: draftTitle (String)

Convenience method to load the body (without title line) of the first draft whose title contains the given string. This method is primarily for private use. If successful, the return value is the body content of the relevant draft. If unsuccessful, an empty string is returned.

Return value: String

show()

Parameters: None

Shows the prompt, if at least one choice is available, and returns an array of the indices of the selected choices (if any). If the prompt is not shown due to insufficient choices, .didShow will be false.

Return value: .selectedItems (Array of Integers)


Validation

For advanced customisation of a prompt’s behaviour, it is possible to specify a .validationFunction which will be injected into the prompt’s JavaScript context, and will be called whenever the state (the checked or unchecked status) of any choice is changed by the user.

Note: The validation function is defined within the script which creates the MGCheckListPrompt (i.e. an Action’s Script step), but it will be executed within the prompt itself (i.e. an HTMLPreview window). As such, it will not have access to the script context, but it will have access to anything within the HTMLPreview window’s JavaScript environment. To incorporate external JavaScript libraries online, see the .includedContent property.

The following is an example of a validation function (included with MGCheckListPrompt as the Demo: Validation action), specified when instantiating and configuring an MGCheckListPrompt object. In this case, the function ensures that the user has selected no more than three of the choices in the prompt. If this number is exceeded, the prompt’s submit button is disabled until sufficient options are once again unchecked. An in-prompt alert is shown to explain the situation to the user.

var prompt = new MGCheckListPrompt();
// ...
prompt.validationFunction = myValidation;

function myValidation(itemIndex, isChecked, theCheckbox) {
	var tooManyChecked = (numberOfItemsChecked() > 3);
	setSubmitButtonEnabled(!tooManyChecked);
	if (tooManyChecked) {
		showAlert("You can't choose more than 3 items!");
	} else {
		hideAlert();
	}
}

A validation function takes three parameters:

Note: If multiple items were simultaneously affected by the change (for example, if the user invoked the Select All or Invert Selection functions), then the calls to the validation function will be coalesced into a single call. In this situation, the parameters will be (-1, false, null) respectively.

To make validation behaviour more flexible and useful, a number of additional helper functions are available, as detailed below. There is also global data storage available via the validatorData dictionary, which is initially empty.

Note: In the event of errors occurring during execution of a validation function, an error description will be shown within the prompt in a closable alert panel. The prompt itself will continue to operate as normal.