Synchronet v3.21e-Win32 (install) has been released (Mar-2026).

You can donate to the Synchronet project using PayPal.

rip_lightbar_menu.js

rip_lightbar_menu.js is a loadable JavaScript file that provides a class, RIPLightbarMenu, which is a lightbar menu class for use in JavaScript scripts for Synchronet on RIP-capable terminals. It uses pixel-based RIP graphics commands rather than ANSI text, drawing the menu and scrollbar using RIPScrip vector drawing primitives.

Some functionality of the RIPLightbarMenu class was modeled after DDLightbarMenu (in dd_lightbar_menu.js) so that it supports many of the same features and is at least somewhat API-compatible with DDLightbarMenu. This means callers can often use the same code to drive either menu class (for example, Digital Distortion File Lister uses DDLightbarMenu for ANSI terminals and RIPLightbarMenu for RIP terminals, sharing much of the same callback and configuration logic). Shared features include the callback functions (OnItemSelect, ValidateSelectItem, OnItemNav), hotkey management, multi-select mode, the exitOnItemSelect flag, and overrideable NumItems()/GetItem() for dynamic item lists.

To create a new RIPLightbarMenu object:

var ripMenu = new RIPLightbarMenu(x, y, width, height, useRIPBorder);

The x, y, width, and height parameters are in RIP pixel coordinates (the RIP graphics viewport is 640×350 pixels). The useRIPBorder parameter is an optional boolean that controls whether a stylized 3D bevel border is drawn around the menu (defaults to true).

The RIPLightbarMenu class requires a RIP-capable terminal (such as SyncTerm). It uses the RIPScrollbar class (in rip_scrollbar.js) for scrollbar widgets:

  • A vertical scrollbar appears automatically on the right side when the number of items exceeds the visible area (i.e., more items than can fit vertically).
  • A horizontal scrollbar appears automatically at the bottom when any item's text is wider than the visible menu area. This allows the user to scroll left/right to see the full text of wide items. When horizontal scrolling is not needed (all items fit within the menu width), no horizontal scrollbar is shown and no space is reserved for it.

Both scrollbars are only shown when needed. When both are present, the menu correctly accounts for the space each scrollbar occupies (the vertical scrollbar narrows the item area, and the horizontal scrollbar reduces the number of visible item rows by one).

The menu supports keyboard navigation (Up, Down, PageUp, PageDown, Home, End, Enter, ESC) as well as Left/Right arrow keys for horizontal scrolling when items are wider than the menu. Mouse interaction is also supported: clicking on menu items to select them, and clicking on either scrollbar's arrow buttons, track areas, and thumb for vertical or horizontal scrolling.

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 exits the menu and returns null. When a scrollbar is needed, users can click the scrollbar's arrow buttons to scroll one item, click the track above/below the thumb for page up/down, or drag the thumb to a new position.

Menu items can have hotkeys set (via Add(), SetItemHotkey(), or AddItemHotkey()) that select the item immediately when the corresponding key is pressed. Hotkeys are case-insensitive by default (controlled by the hotkeyCaseSensitive property).

After showing the menu and getting a value from the user (using the GetVal() function), the lastUserInput property will have the user's last keypress.

Dependencies

rip_lightbar_menu.js requires the following loadable modules:

  • sbbsdefs.js
  • key_defs.js
  • rip_lib.js — for generating RIPScrip command strings
  • rip_scrollbar.js — for the scrollbar widget

RIPLightbarMenu methods

Name Returns Usage Description
Add void RIPLightbarMenu.Add(text, retval, hotkey) Adds an item to the menu with given display text, return value, and optional hotkey character(s). The retval defaults to the current item count if not specified. The hotkey parameter can be a single character or a string of multiple characters — each character is a separate hotkey.
Remove void RIPLightbarMenu.Remove(idx) Removes an item from the menu by its index.
RemoveAllItems void RIPLightbarMenu.RemoveAllItems() Removes all items from the menu.
NumItems number RIPLightbarMenu.NumItems() Returns the number of items in the menu. This function can be replaced for dynamic item lists (see “Replacing NumItems() and GetItem()” below).
GetItem object RIPLightbarMenu.GetItem(idx) Returns the item object at the given index. Can be replaced for dynamic item lists.
MakeItemWithRetval object RIPLightbarMenu.MakeItemWithRetval(retval) Creates and returns a default item object with the specified return value (for use in custom GetItem functions).
MakeItemWithTextAndRetval object RIPLightbarMenu.MakeItemWithTextAndRetval(text, retval) Creates and returns a default item object with the specified text and return value (for use in custom GetItem functions).
SetItemHotkey void RIPLightbarMenu.SetItemHotkey(idx, hotkey) Sets a hotkey for a menu item, replacing any existing hotkeys.
AddItemHotkey void RIPLightbarMenu.AddItemHotkey(idx, hotkey) Adds an additional hotkey for a menu item without removing existing hotkeys.
RemoveItemHotkey void RIPLightbarMenu.RemoveItemHotkey(idx, hotkey) Removes a specific hotkey from a menu item.
RemoveAllItemHotkeys void RIPLightbarMenu.RemoveAllItemHotkeys() Removes all hotkeys from all menu items.
SetSelectedItemIdx void RIPLightbarMenu.SetSelectedItemIdx(idx) Sets the currently selected (highlighted) item index before calling GetVal().
GetVal various RIPLightbarMenu.GetVal(pDefaultRetVal, pSelectedItemIndexes) Draws the menu and enters the input loop. Returns the selected item's return value, or null if the user aborts. In multi-select mode, the selections are stored in the selectedItemIndexes object. The optional pDefaultRetVal specifies an item to pre-select by its return value.
AddAdditionalQuitKeys void RIPLightbarMenu.AddAdditionalQuitKeys(keys) Adds characters from the given string as additional quit keys (in addition to ESC).
ClearAdditionalQuitKeys void RIPLightbarMenu.ClearAdditionalQuitKeys() Clears the list of additional quit keys.
QuitKeysIncludes boolean RIPLightbarMenu.QuitKeysIncludes(key) Returns whether the given key is in the additional quit keys.
AddAdditionalSelectItemKeys void RIPLightbarMenu.AddAdditionalSelectItemKeys(keys) Adds characters as additional select-item keys (in addition to Enter).
ClearAdditionalSelectItemKeys void RIPLightbarMenu.ClearAdditionalSelectItemKeys() Clears the list of additional select-item keys.
SelectItemKeysIncludes boolean RIPLightbarMenu.SelectItemKeysIncludes(key) Returns whether the given key is in the additional select-item keys.
ValidateSelectItem boolean RIPLightbarMenu.ValidateSelectItem(retval) Called before an item is selected. Return false to prevent selection. Override this for custom validation logic.
OnItemSelect void RIPLightbarMenu.OnItemSelect(retval, selected) Called after an item is selected (or toggled in multi-select mode). Override this to perform actions on selection.
OnItemNav void RIPLightbarMenu.OnItemNav(oldIdx, newIdx) Called when the user navigates to a different item. Override this to update detail panes or other UI elements.

RIPLightbarMenu properties

Name Type Description
pos object An object with x and y properties for the upper-left corner position of the menu, in RIP pixel coordinates.
size object An object with width and height properties for the menu dimensions, in RIP pixels.
colors object An object containing RIP color numbers for various parts of the menu. Properties: itemBg, itemFg, selectedBg, selectedFg, borderSurface, bevelBright, bevelDark, scrollTrack, scrollThumb, scrollArrowBg, scrollArrowFg, contentBg. These use the RIP color constants (0-15) defined in rip_lib.js.
useRIPBorder boolean Whether to draw a stylized 3D bevel border around the menu. Defaults to true.
selectedItemIdx number The index of the currently highlighted item (0-based). Can be read after GetVal() returns, or set before calling GetVal().
topItemIdx number The index of the first visible item (vertical scroll position).
leftCharIdx number The index of the first visible character in each item's text (horizontal scroll position). Only meaningful when a horizontal scrollbar is active. Defaults to 0.
itemHeight number Height of each menu item row in pixels. Defaults to 16 (for the 8×8 default RIP font).
textYOffset number Y offset for text within an item row, in pixels. Defaults to 4.
textXOffset number X offset for text from the left edge of the content area, in pixels. Defaults to 4.
exitOnItemSelect boolean When true (default), GetVal returns immediately after the user selects an item. When false, the menu stays visible after selection — useful with OnItemSelect for performing actions without leaving the menu.
lastUserInput string The user's last keypress from the most recent GetVal() call.
multiSelect boolean Whether multi-select mode is enabled. Defaults to false. When true, users can toggle items on/off with Space or mouse click.
maxNumSelections number Maximum number of selections in multi-select mode. -1 or 0 means unlimited. Defaults to -1.
multiSelectItemChar string The character displayed next to selected items in multi-select mode. Defaults to the CP437 check mark.
selectedItemIndexes object Object whose keys are selected item indexes (used in multi-select mode).
enterAndSelectKeysAddsMultiSelectItem boolean When true and in multi-select mode, pressing Enter also adds the current item to the selection before returning. Defaults to false.
hotkeyCaseSensitive boolean Whether hotkeys are case-sensitive. Defaults to false.
callOnItemNavOnStartup boolean Whether to call OnItemNav() when the menu is first displayed (with old index -1). Defaults to false.
noVerticalScrollbar boolean When true, suppresses the vertical scrollbar even if there are more items than can fit vertically. Items beyond the visible area will simply not be reachable by scrolling. Defaults to false (vertical scrollbar is shown when needed).
noHorizontalScrollbar boolean When true, suppresses the horizontal scrollbar even if items are wider than the visible area. Wide item text will be clipped to the menu width. Defaults to false (horizontal scrollbar is shown when needed).
additionalQuitKeys string Characters treated as additional quit keys beyond ESC.
additionalSelectItemKeys string Characters treated as additional select-item keys beyond Enter.

To change the colors used for the menu items and border, modify the properties of the colors object:

ripMenu.colors.itemBg = RIP_COLOR_BLACK;
ripMenu.colors.itemFg = RIP_COLOR_WHITE;
ripMenu.colors.selectedBg = RIP_COLOR_BLUE;
ripMenu.colors.selectedFg = RIP_COLOR_WHITE;
ripMenu.colors.borderSurface = RIP_COLOR_LT_GRAY;

Example usage

load("rip_lightbar_menu.js");
// Create a menu at pixel position (15, 64) with width 611 and height 286, with border
var ripMenu = new RIPLightbarMenu(15, 64, 611, 286, true);
// Add 20 items to the menu
for (var i = 0; i < 20; ++i)
  ripMenu.Add("Item " + +(i+1), i+1);
// Set up hotkey "s" for the 2nd item
ripMenu.SetItemHotkey(1, "s");
// Show the menu and get the chosen item from the user
var val = ripMenu.GetVal();
// val contains the return value of the selected item, or null if the user aborted
// Disabling auto-exit on selection (to use with OnItemSelect callback):
ripMenu.exitOnItemSelect = false;
ripMenu.OnItemSelect = function(pRetval, pSelected) {
  // Do something when an item is selected without leaving the menu
};

Replacing NumItems() and GetItem()

For large or dynamic lists, you can replace NumItems() and GetItem() so the menu references external data without copying it into the menu's internal array. This is the same pattern used by DDLightbarMenu.

Example (assuming ripMenu is a RIPLightbarMenu object and myList is an external data array):

ripMenu.NumItems = function() {
  return myList.length;
};
ripMenu.GetItem = function(pIdx) {
  var item = this.MakeItemWithRetval(pIdx);
  item.text = myList[pIdx].displayText;
  return item;
};

Replacing ValidateSelectItem()

Override ValidateSelectItem() to control whether a user can select a given item:

ripMenu.ValidateSelectItem = function(pItemRetval) {
  if (someCondition(pItemRetval))
    return true;
  else
    return false;
};

Replacing OnItemSelect()

Override OnItemSelect() to perform an action when an item is selected or toggled:

ripMenu.OnItemSelect = function(pItemRetval, pSelected) {
  // pSelected is true when the item is selected, false when de-selected
  // (de-selection only occurs in multi-select mode)
};

Replacing OnItemNav()

Override OnItemNav() to react when the user navigates to a different item (e.g., to update a detail pane):

ripMenu.OnItemNav = function(pOldItemIdx, pNewItemIdx) {
  // Update a description area based on the newly highlighted item
};

Differences from DDLightbarMenu

While RIPLightbarMenu is API-compatible with DDLightbarMenu for many common operations, there are some differences due to the fundamentally different display technology:

  • Coordinates are in RIP pixels (640×350 viewport), not ANSI text cells.
  • No numbered mode — RIPLightbarMenu always uses lightbar-style navigation (since it requires a RIP terminal).
  • No ANSI fallback — DDLightbarMenu can fall back to numbered text input for non-ANSI terminals; RIPLightbarMenu requires RIP.
  • Border is a 3D bevel rendered with RIP graphics, not ANSI box-drawing characters.
  • Scrollbar is a graphical widget using RIPScrollbar, with arrow buttons, a proportional thumb, and mouse support — not a text-based scrollbar.
  • Mouse support is always enabledRIP mouse regions are always registered for menu items and the scrollbar.
  • DDLightbarMenu features such as Draw(), Erase(), DrawPartial(), DrawPartialAbs(), SetBorderChars(), item color arrays, altItemColor/altSelectedItemColor, borderChars, borderEnabled, scrollbarEnabled, numberedMode, allowANSI, wrapNavigation, and ampersandHotkeysInItems are not present in RIPLightbarMenu.

Example code

For a real-world example where RIPLightbarMenu is used, see:

  • Digital Distortion File Lister (ddfilelister.js): Uses RIPLightbarMenu when the terminal supports RIP, with NumItems/GetItem replacement, OnItemNav for updating the file description pane, additional quit keys for menu bar integration, and hotkey support.
  • uselect_rip.js (uselect_rip.js): Synchronet's “Select Item” loadable module for RIP terminals, demonstrating basic RIPLightbarMenu usage with hotkeys.

See Also