Synchronet v3.19b-Win32 (install) has been released (Jan-2022).

You can donate to the Synchronet project using PayPal.

This is an old revision of the document!


dd_lightbar_menu.js

dd_lightbar_menu.js is a loadable JavaScript file that provides a lightbar menu class for use in JavaScript scripts for Synchronet. The DDLightbarMenu class supports single item selection and multiple item selection. For one example of how to use DDLightbarMenu, you can look at the code for slyvote.

The user can navigate the list using the up & down arrows, PageUp, PageDown, Home, and End keys. The enter key selects an item. The ESC key will exit the menu and return null. This menu library requires the use of an ANSI terminal. By default, this menu library does not display a border around the menu. If you want this library to draw a border around the menu, you can set the borderEnabled property to true. Without a border, the menu gains 2 characters of width and 2 lines of height. Also, a scrollbar can be optionally displayed, which provides a visual indicator for how far the user is through the list of items. The scrollbar is disabled by default.

dd_lightbar_menu.js provides a class, DDLightbarMenu. To create a new DDLightbarMenu object: new DDLightbarMenu(x, y, width, height);

DDLightbarMenu methods

Name Returns Usage Description
Add void DDLightbarMenu.Add(text, retval, hotkey) Adds an item to the menu with a given item text, return value, and hotkey for the item. If the ampersandHotkeysInItems property is set to true before this method is called, then a & can be used in the item text just before the hotkey you want to enable for the item. For example, “Item &1” would display the text “Item 1” with “1” being the hotkey for the item.
Remove void DDLightbarMenu.Remove(idx) Removes an item from the menu by its index
RemoveAllItems void DDLightbarMenu.RemoveAllItems() Removes all items from the menu
SetItemHotkey void DDLightbarMenu.SetItemHotkey(idx, hotkey) Sets a hotkey for a menu item, by index
AddItemHotkey void DDLightbarMenu.AddItemHotkey(idx, hotkey) Adds a hotkey for a menu item (in addition to the item's other hotkeys)
RemoveItemHotkey void DDLightbarMenu.RemoveItemHotkey(idx, hotkey) Removes a specific hotkey from a menu item
RemoveItemHotkeys void DDLightbarMenu.RemoveItemHotkeys(idx) Removes all hotkeys from a menu item
RemoveAllItemHotkeys void DDLightbarMenu.RemoveAllItemHotkeys() Removes all hotkeys from all menu items
GetVal various DDLightbarMenu.GetVal(draw) Waits for user input, then gets the value of the item selected by the user. The 'draw' parameter is a boolean that specifies whether or not to draw the menu first (defaults to true). The return value type will be as follows:
* If in multi-select mode, this method will return an array of the chosen values.
* If in single-select mode, this method will return the single value selected by the user.
* If the user exited the menu without choosing (i.e., with ESC), this method will return null.
SetPos void DDLightbarMenu.SetPos(x, y) Sets the menu's position, by the upper-left corner X and Y coordinates
SetSize void DDLightbarMenu.SetSize(size) Sets the menu's size. The 'size' parameter is an object with the properties 'width' and 'height', specifying the menu's width and height.
SetWidth void DDLightbarMenu.SetWidth(width) Sets the menu's width
SetHeight void DDLightbarMenu.SetHeight(height) Sets the menu's height
Draw void DDLightbarMenu.Draw(selectedItemIndexes) Draws the menu with all (visible) menu items. The selected items will be highlighted. The 'selectedItemIndexes' is an object that can contain multiple indexes of selected items (as properties of the object) - This is only for multi-select mode. These are used for drawing a marking character in the item text.
Erase void DDLightbarMenu.Erase() Erases the menu - Draws black (normal color) where the menu was
SetBorderChars void DDLightbarMenu.SetBorderChars(borderChars) Sets the characters to use for drawing the menu border. The 'borderChars' parameter is an object that contains the following properties: upperLeft, upperRight, lowerLeft, lowerRight, top, bottom, left, right
GetNumItemsPerPage number DDLightbarMenu.GetNumItemsPerPage() Returns the number of (possible) items per page
GetTopItemIdxToTopOfLastPage number DDLightbarMenu.GetTopItemIdxToTopOfLastPage() Gets the top item index of the last page of items
SetTopItemIdxToTopOfLastPage number DDLightbarMenu.SetTopItemIdxToTopOfLastPage() Sets the top item index to the top item of the last page of items
NumItems() number To be used internally Returns the number of items in the list. This function can be replaced if you want to allow the menu object to access a different list of items rather than add a large list of items to the menu, for a speed optimization. See the “Replacing the NumItems() and GetItem() functions” section below.
GetItem() object To be used internally Returns an item object compatible with DDLightbarMenu. This function can be replaced if you want to allow the menu object to access a different list of items rather than add a large list of items to the menu, for a speed optimization. You might also choose to have it specify to use the alternate item colors (specified by colors.altItemColor and colors.altSelectedItemColor) with the returned object. See the “Replacing the NumItems() and GetItem() functions” section below.

DDLightbarMenu properties

Name Type Description
colors object An object that contains color codes (as strings) for various things. Contains the following properties: itemColor, selectedItemColor, altItemColor, altSelectedItemColor, itemTextCharHighlightColor, borderColor. altItemColor and altSelectedItemColor are alternate colors that can be used for the items. Currently, those would only be used if you have replaced the GetItem() function and return an item object with its useAltColors property set to true.
borderEnabled boolean Whether or not to draw a border around the menu items
scrollbarEnabled boolean Whether or not to enable the scrollbar. Defaults to false.
wrapNavigation boolean Whether or not to wrap around to the beginning/end when using the down/up arrows. Defaults to true.
hotkeyCaseSensitive boolean Whether or not hotkeys are case-sensitive. Defaults to false.
ampersandHotkeysInItems boolean Whether or not to allow ampersands (&) to declare hotkeys in item text. Defaults to true.
multiSelect boolean Whether or not to allow multi-select mode (selection of multiple items). Defaults to false.
maxNumSelections number The maximum number of item selections. -1 or 0 means no limit on the number of selections.
multiSelectItemChar string The character to use for displaying which items are selected (for multi-select mode). Defaults to the check-mark character.
numberedMode boolean Whether or not to use 'numbered mode'. Defaults to false. If true, the menu will automatically use number input from the user for selecting the items.

To change the colors used for displaying the items, you can change the values in the colors object within the DDLightbarMenu object. These are the current supported colors (in the 'colors' property of the object):

color property Description
itemColor The color to use for non-selected items (current default is white on blue). This can be either a string (with Synchronet color/attribute codes for the item text) or an array with objects specifying color/attribute codes for different parts of an item's text string displayed on the menu. See the “Item color arrays” section below for more information.
selectedItemColor The color to use for selected items (current default is blue on white). This can be either a string (with Synchronet color/attribute codes for the item text) or an array with objects specifying color/attribute codes for different parts of an item's text string displayed on the menu. See the “Item color arrays” section below for more information.
itemTextCharHighlightColor The color of a highlighted non-space character in an item text (specified by having a & in the item text). It's important not to specify a “\1n” in here in case the item text should have a background color.
borderColor The color for the borders (if borders are enabled)
topBorderText Text to write in the top border (if borders are enabled). This defaults to an empty string. Synchronet color/attribute codes are supported.
bottomBorderText Text to write in the bottom border (if borders are enabled). This defaults to an empty string. Synchronet color/attribute codes are supported.

By default, the menu selection will wrap around to the beginning/end when using the down/up arrows. That behavior can be disabled by setting the wrapNavigation property to false.

This menu object supports adding multiple hotkeys to each menu item. A hotkey can be specified in the Add() method a couple of different ways - By specifying a hotkey as the 3rd parameter and/or by putting a & in the menu item text just before a key you want to use as the hotkey. For example, in the text “E&xit”, “x” would be used as the hotkey for the item. If you want to disable the use of ampersands for hotkeys in menu items (for instance, if you want an item to literally display an ampersand before a character), set the ampersandHotkeysInItems property to false. For instance:

lbMenu.ampersandHotkeysInItems = false;

Note that ampersandHotkeysInItems must be set before adding menu items.

You can call the SetItemHotkey() method to set a single hotkey to be used for a menu item or AddItemHotkey() to add an additional hotkey for an item in addition to any existing hotkeys it might already have.

This menu class also supports an optional “numbered mode”, where each option is displayed with a number to the left (starting at 1), and the user is allowed to choose an option by typing the number of the item. Numbered mode is disabled by default and can be enabled by setting the numberedMode property to true. For example:

lbMenu.numberedMode = true;

When numbered mode is enabled and the user starts typing a number, the menu will prompt the user for an item number. Note that the prompt will be located on the line below the menu, so in addition to the menu's height, you'll also need an extra line on the screen to account for the item prompt. In addition, when the user presses the enter key after the item number, a carriage return/line feed will be outputted, so in numbered mode, the menu's height should not go further than 2 lines below the console height. Otherwise, the display of the menu will not be correct if the user decides not to enter a number.

This menu also supports multiple options selected (by default, that is not enabled). To enable that, set the multiSelect property to true. When enabled, the GetVal() method will return an array of the user's selections rather than a string (or null if the user aborted). You can also set a limit on the number of items selected in multi-select mode by setting the maxNumSelections property. The default value is -1, which means no limit (0 also means no limit). Example, with a limit:

lbMenu.multiSelect = true;
lbMenu.maxNumSelections = 5;

Example usage:

load("dd_lightbar_menu.js");
// Create a menu at position 1, 3 with width 45 and height of 10
var lbMenu = new DDLightbarMenu(1, 3, 45, 10);
// Add 12 items to the menu, each of which will return the text of the item
for (var i = 0; i < 12; ++i)
  lbMenu.Add("Item " + +(i+1), "Item " + +(i+1));
// Set up the hotkey "s" to select the 2nd item
lbMenu.SetItemHotkey(1, "s");
// Show the menu and get the chosen item from the user
var val = lbMenu.GetVal();
// Output the chosen menu item
console.print("\1n\r\n");
console.print("Value:" + val + ":, type: " + typeof(val) + "\r\n");
console.pause();

// Changing the normal item color to green & selected item color to bright green:
lbMenu.colors.itemColor = "\1n\1g";
lbMenu.colors.selectedItemColor = "\1n\1h\1g";

// Disabling the navigation wrap behavior:
lbMenu.wrapNavigation = false;

// If you want a particular character in an item's text highlighted with
// a different color, you can put a & character immediately before it, as
// long as it's not a space.  For instance, to highlight the "x" in "Exit":
lbMenu.Add("E&xit", -1);

// To enable borders and set text to display in the top & bottom borders:
lbMenu.borderEnabled = true;
lbMenu.topBorderText = "Options";
lbMenu.bottomBorderText = "ESC: Quit";

To enable the scrollbar, set the scrollbarEnabled property to true. Example:

lbMenu.scrollbarEnabled = true;

To enable borders, set the borderEnabled property to true. Example:

lbMenu.borderEnabled = true;

If borders are enabled, the scrollbar will appear just inside the right border. Also, if the scrollbar is enabled but all the items would fit in a single “page” in the menu, then the scrollbar won't be displayed.
The scrollbar uses block characters to draw the scrollbar: ASCII character 176 for the background and ASCII 177 for the block that moves on the scrollbar. If you want to change those characters, you can change the scrollbarInfo.BGChar and scrollbarInfo.blockChar properties in the menu object.
By default, the scrollbar colors are high (bright) black for the background and high (bright) white for the moving block character. If desired, those can be changed with the colors.scrollbarBGColor and colors.scrollbarScrollBlockColor properties in the menu object.

The menu object has an object called borderChars, which stores the characters used to draw the border. you can change the characters used to draw the border by setting the following properties of the borderChars object:

  • upperLeft: The character to use for the upper-left corner
  • upperRight: The character to use for the upper-right corner
  • lowerLeft: The character to use for the lower-left corner
  • lowerRight: The character to use for the lower-right corner
  • top: The character to use for the top border
  • bottom: The character to use for the bottom border
  • left: The character to use for the left border
  • right: The character to use for the right border

For example:

lbMenu.borderChars.upperLeft = "\xDA"; // Single-line upper-left character

To set/change any of the border characters, you can also call the SetBorderChars() function and pass an object containing any or all of the above properties to set the border characters in the object. For example (assuming lbMenu is the menu object):

lbMenu.SetBorderChars({
  left: "|",
  right: "|"
});

If you want hotkeys to be case-sensitive, you can set the hotkeyCaseSensitive property to true (it is false by default). For example (assuming lbMenu is the menu object):

lbMenu.hotkeyCaseSensitive = true;

To change the colors, you can directly change the properties of the color object within the DDLightbarMenu, or you can call the SetColors() function to set any or all of the color properties in the colors object in the DDLightbarMenu object. For example (assuming lbMenu is the menu object):

lbMenu.SetColors({
  itemColor: "\1b",
  selectedItemColor: "\1r\1" + "7" // Red with a grey background - This uses 2 strings concatenated because "\17" would be interpreted incorrectly.
});

Item color arrays (for the colors.itemColor and colors.selectedItemColor properties)
The colors.itemColor and colors.selectedItemColor properties can be either a string (containing Synchronet color/attribute codes for the normal & highlighted item text), or they can be an array with objects specifying color/attribute codes for different parts of an item's text string displayed on the menu.
Item color arrays: Currently, colors.itemColor and colors.seletedItemColor within a DDLightbarMenu object can be either a string (containing color/attribute codes) or an array with color/attribute codes for different sections of the item strings to display in the menu. The array is to contain objects with the following properties:

start: The index of the first character in the item string to apply the colors to
end: One past the last character index in the string to apply the colors to
attrs: The Synchronet attribute codes to apply to the section of the item string

For the last item, the 'end' property can be -1, 0, or greater than the length of the item to apply the color/attribute codes to the rest of the string.

Replacing the NumItems() and GetItem() functions
For a speed optimization, it may be desirable to have the menu reference some items that already exist, rather than add a large list of items to the menu object. One instance would be if your script is working with a Synchronet messagebase and already has a list of message headers you want to list in a menu. The NumItems() and GetItems() functions need to replaced together.
The NumItems() function needs to return the number of items in the menu, as a number. This is an example of replacing the NumItems() function, assuming the lbMenu is the menu object:

lbMenu.NumItems = function() {
  // Do your own thing to get the number of items in your list.
  // ...
  // Assuming myNumItems is the number of items in your list:
  return myNumItems;
};

This is an example of replacing the GetItem() function, assuming the lbMenu is the menu object:

lbMenu.GetItem = function(pItemIndex) {
  // Get a default item object from the menu with an initial return value of -1
  var menuItemObj = this.MakeItemWithRetval(-1);
  // Do your own thing to get the item text and return value for the menu.
  // ...
  // Assuming itemText is the text to display in the menu and itemRetval is
  // the return value to return from the menu:
  menuItemObj.text = itemText;
  menuItemObj.retval = itemRetval;
  // You can also choose to have the returned object specify to use the alternate item colors
  // if desired (specified by colors.altItemCor and colors.altSelectedItemColor in the DDLightbarMenu
  // object).  To do so, uncomment the line below.
  //menuItemObj.useAltColors = true;
  return menuItemObj; // The DDLightbarMenu object will use this when displaying the menu
};

See Also