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.
Available from the Drafts Actions repository.
Screenshots of MGCheckListPrompt in use are shown below.
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.
MGCheckListPrompt was created by Matt Gemmell.
Please send any feedback via email, instead of social media.
All current Drafts platforms are supported: iPadOS, iOS, and macOS.
Choose one or more items from a list. Items can be either drafts, or arbitrary choices. Both multiple-selection (checkboxes) and single-selection (radio-buttons) modes are supported. See the API section below.
Interface adapts to small screen sizes.
Each choice has a title, description, ancillary info (for example, a draft’s tags), and flagged status. All except the title are optional.
Supports light and dark modes automatically.
Full keyboard control:
Cursor keys move between options in the list, including wrap-around.
Number keys from 1 to 0 (for 10) directly select the first ten options.
Escape
or Ctrl-Backspace
cancels the dialog.
Return confirms the selection and closes the dialog.
Ctrl-A
triggers the Select All / Select None button.
Ctrl-I
triggers the Invert Selection button.
Optionally, type-to-select or type-to-filter can be enabled, matching the options' titles.
Keyboard shortcuts help overlay can be toggled within the prompt, or disabled entirely.
Supports optional Markdown processing of list options.
Supports optional HTML injection in list options.
Dialog title, message, and OK button title can be specified.
Optionally, a live counter of the number of selected items can be shown.
Supports embedding additional content within the prompt, for example to override CSS, customise JavaScript functionality, and so on.
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.
Ensure that you’ve installed the MGCheckListPrompt Library action (part of the MGCheckListPrompt Action Group), and that you have Drafts 21 or later.
Within your own action, add an Include Action step, and set the name value to “MGCheckListPrompt Library”.
You can now use MGCheckListPrompt in your own subsequent script steps.
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.");
}
The following properties and methods are available on an MGCheckListPrompt
object.
.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.
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.
The included draft will have its title line stripped before inclusion. This allows, for example, keeping HTML, CSS, or JavaScript snippets in a draft for inclusion but still giving those drafts a meaningful title in the drafts list.
The draft will be inserted into the prompt after all built-in CSS and JavaScript, and just before the closing </body>
tag.
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
.prefersFullScreen
Boolean. When enabled and when running on iPad, the prompt will try to use the full screen. Disabled by default.
Note: This property requires Drafts 21.5 or later. It will have no effect on earlier versions.
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).
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.
Default value: false
.roundedCheckboxes
Boolean. Determines whether checkboxes have a circular background, instead of the usual rectangular shape. Disabled by default.
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.
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:
Radio-buttons are shown instead of checkboxes.
Only one choice can be chosen at a time.
.showSelectionCounter
has no effect. The selection counter is not shown.
The help overlay, if enabled (see .showHelp
), will show appropriate keyboard shortcut information for single-selection mode.
The default .message
for the prompt is slightly different, to indicate single-selection mode is in effect.
The Select All
and Invert Selection
buttons are not shown, and their functionality is not available.
The .roundedCheckboxes
option has no effect. Radio-buttons are shown instead of checkboxes.
If the setSelectedItems(indexArray)
method is used to specify items to pre-select, only the first index in the array will be pre-selected.
When the user clicks the OK button to confirm their choice and dismiss the prompt, .selectedItems
will contain (at most) one item.
The remaining settings and functions behave as normal.
Note: There are two settings which pertain specifically to single-selection mode: see .allowsDoubleClickToSelect
and .selectsImmediately
.
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.
False: The default behaviour. Choosing an item will activate its radio-button, and the prompt will remain on screen. The choice is only confirmed when the OK button is pressed, which dismisses the prompt.
True: Immediate selection mode. Choosing an item will confirm the choice immediately, and dismiss the prompt. The OK button is not shown at all, but the Cancel button remains available.
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.
Integer. The index (zero-based) of the choice currently being processed.
String. The name of the property currently being processed for this choice: title
, description
, or info
.
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.
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).
title
: The draft’s .displayTitle
.
description
: The first non-blank line of the draft’s body (not including the title line).
info
: A comma-separated list of the draft’s .tags
, sorted alphabetically.
flagged
: The draft’s .isFlagged
status.
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.
title
: String. The primary title of the choice, in a larger font size. One line.
description
: String. Descriptive text shown below the choice’s title. Multi-line.
info
: String. Ancillary text shown below the choice’s description, in a highlighted colour. One line.
flagged
: Boolean. If true, the choice displays a flagged marker.
selected
: Boolean. If true, the choice will already be selected (checked) when the prompt is shown.
disabled
: Boolean. If true, the choice will be disabled. It will be shown in the prompt, but it cannot be visually highlighted, and its initial value cannot be changed (the exception is for pre-selected items in .singleSelectionMode
: they will be deselected if another enabled item is chosen, but they cannot be re-selected).
metadata
: String. Arbitrary text which will not be displayed in the prompt, but which is available for search purposes when using the .allowsTypeToFilter
and .allowsTypeToSelect
features. The content will not be preprocessed in any way; in particular, any HTML will not be escaped before injection into the prompt.
css_classes
: Dictionary. Custom CSS classes to apply to elements of the choice, as follows. See also .includedContent
.
item
: String. CSS classes (space-separated) to apply to the overall item. This is a LABEL
element.
title
: String. CSS classes (space-separated) to apply to the item’s title. This is a DIV
element with class .item-title
.
Note: The item’s flagged
status is applied as a background color on a :before
pseudo-element on its title: .item-title.flagged:before
.
description
: String. CSS classes (space-separated) to apply to the item’s description. This is a DIV
element with class .item-description
. Will only be applied if the item has a non-empty description.
info
: String. CSS classes (space-separated) to apply to the item’s info. This is a DIV
element with class .item-info
. Will only be applied if the item has non-empty info.
checkbox
: String. CSS classes (space-separated) to apply to the item’s checkbox. This is a SPAN
element with class .checkbox
.
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)
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:
Integer. The zero-based index of the item most recently changed.
Boolean. Whether the item was just checked (true) or unchecked (false).
INPUT element. The checkbox control of the item in question.
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.
allCheckboxes() : Array of INPUT elements
checkboxForIndex(index) : INPUT or null
indexForCheckbox(checkbox) : Integer
titleForIndex(index) : String
descriptionForIndex(index) : String
infoForIndex(index) : String
metadataForIndex(index) : String
setTitleForIndex(index, content) : String
setDescriptionForIndex(index, content) : String
setInfoForIndex(index, content) : String
setMetadataForIndex(index, content) : String
isCheckedAtIndex(index) : Boolean
isDisabledAtIndex(index) : Boolean
isFlaggedAtIndex(index) : Boolean
setChecked(index, checked)
setDisabled(index, disabled)
setFlagged(index, flagged)
isIndexValid(index) : Boolean
numberOfItems() : Integer
numberOfItemsChecked() : Integer
numberOfItemsUnchecked() : Integer
showAlert(text)
appendAlert(text)
hideAlert()
setAlertVisible(visible)
setSubmitButtonEnabled(enabled)
submitButtonEnabled() : Boolean
submitPrompt()
cancelPrompt()
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.