rip_scrollbar.js is a loadable JavaScript file that provides a class, RIPScrollbar, which is a reusable scrollbar widget for RIP terminals on Synchronet. It renders a graphical scrollbar with arrow buttons, a proportional track, and a draggable thumb, all using RIPScrip vector drawing primitives.
RIPScrollbar supports both vertical and horizontal orientations. By default the scrollbar is vertical (with up/down arrow buttons and a thumb that moves vertically). Setting the horizontal property to true before calling computeLayout() switches to horizontal mode, where the arrow buttons become left/right arrows and the thumb moves horizontally.
RIPScrollbar is a pure rendering/layout component — it does not handle user input directly. Instead, the consumer (such as RIPLightbarMenu or a custom dialog) is responsible for reading keyboard and mouse input and calling the appropriate methods to update the scroll position and redraw the thumb.
To create a new RIPScrollbar object:
var sb = new RIPScrollbar(x, y, width, height);
The x, y, width, and height parameters are in RIP pixel coordinates (the RIP graphics viewport is 640×350 pixels).
rip_scrollbar.js requires the following loadable module:
The scrollbar defaults to vertical mode. To create a horizontal scrollbar, set the horizontal property to true before calling computeLayout():
var sb = new RIPScrollbar(50, 330, 400, 14); sb.horizontal = true; sb.computeLayout();
In horizontal mode:
arrowHeight property controls the width of each arrow button (instead of the height).getThumbGeometry() returns { x, w } (left pixel and width) instead of { y, h } (top pixel and height).$X$ (the mouse X coordinate at release time) instead of $Y$.mouseChars.scrollUp and mouseChars.scrollDn characters correspond to “scroll left” and “scroll right” respectively.mouseChars.trackPgUp and mouseChars.trackPgDn characters correspond to “page left” and “page right” respectively.
The consumer handles the mouse input the same way regardless of orientation — the character codes are identical. The only difference is which coordinate (X or Y) follows the thumbDrag character.
The typical usage pattern is:
horizontal to true for a horizontal scrollbar.computeLayout() to calculate the internal geometry.buildFullRIP() to get the RIP command string for the complete scrollbar, and send it to the terminal.buildMouseRegionsRIP() to get the RIP mouse region commands, and send those as well. This registers clickable areas for the arrow buttons, track areas, and the thumb.buildThumbRIP() and buildMouseRegionsRIP() to efficiently redraw just the thumb and update the mouse regions.The scrollbar's mouse regions send high-byte character codes when clicked (configurable via the mouseChars property). The consumer reads these codes from console input and maps them to scroll actions:
RIPScrollbar methods
| Name | Returns | Usage | Description |
|---|---|---|---|
| computeLayout | void | RIPScrollbar.computeLayout() | Computes the internal geometry (arrow button bounds, track bounds) from the current pos, size, arrowHeight, and orientation. Must be called before any build methods, and again if the scrollbar's position, size, or orientation changes. |
| setScrollState | void | RIPScrollbar.setScrollState(totalItems, visibleCount, topIndex) | Sets the scroll state (total number of items, number of visible items, and the index of the first visible item). Call this before building RIP commands so the thumb size and position are correct. |
| buildFullRIP | string | RIPScrollbar.buildFullRIP() | Returns a RIP command string that draws the complete scrollbar: both arrow buttons (with beveled 3D appearance), the track background, and the thumb. Does NOT include mouse regions — call buildMouseRegionsRIP() separately. |
| buildThumbRIP | string | RIPScrollbar.buildThumbRIP() | Returns a RIP command string that redraws just the track and thumb. Used for efficient updates when only the scroll position has changed (no need to redraw the arrow buttons). |
| buildMouseRegionsRIP | string | RIPScrollbar.buildMouseRegionsRIP() | Returns a RIP command string that defines mouse regions for the scrollbar's clickable areas. In vertical mode: up/down arrows, track above/below thumb, and thumb (with $Y$). In horizontal mode: left/right arrows, track left/right of thumb, and thumb (with $X$). Note: this does NOT call RIPKillMouseFields() — the consumer must kill existing fields before registering new ones if needed. |
| getThumbGeometry | object | RIPScrollbar.getThumbGeometry() | Returns an object describing the current thumb position and size. In vertical mode: { y, h } (top pixel and height). In horizontal mode: { x, w } (left pixel and width). |
RIPScrollbar properties
| Name | Type | Description |
|---|---|---|
| pos | object | An object with x and y properties for the upper-left corner of the scrollbar, in RIP pixel coordinates. |
| size | object | An object with width and height properties for the scrollbar dimensions, in RIP pixels. |
| horizontal | boolean | Orientation of the scrollbar. false (default) for vertical, true for horizontal. Must be set before calling computeLayout(). |
| colors | object | An object containing RIP color numbers (0-15, as defined in rip_lib.js) for the scrollbar's visual components. Properties: track (track background), thumb (thumb body), arrowBg (arrow button background), arrowFg (arrow triangle foreground), bevelBright (bright edge of 3D bevel), bevelDark (dark edge of 3D bevel). |
| arrowHeight | number | Size of each arrow button along the scrollbar's primary axis (pixels). For vertical mode this is the height of each up/down button; for horizontal mode this is the width of each left/right button. Defaults to 14. |
| totalItems | number | Total number of items being scrolled through. Set by the consumer. |
| visibleCount | number | Number of items visible at once. Set by the consumer. |
| topIndex | number | Index of the first visible item (scroll position). Set by the consumer and updated on scroll. |
| mouseChars | object | Object containing the character codes sent when mouse regions are clicked. Properties: scrollUp (default 0xFE), scrollDn (default 0xFD), trackPgUp (default 0xFC), trackPgDn (default 0xFB), thumbDrag (default 0xFA). In horizontal mode, scrollUp/scrollDn correspond to left/right, and trackPgUp/trackPgDn correspond to page-left/page-right. These can be changed to avoid conflicts when multiple scrollbars or other mouse-aware widgets are on screen simultaneously. |
To change the scrollbar colors:
sb.colors.track = RIP_COLOR_BLACK; sb.colors.thumb = RIP_COLOR_LT_CYAN; sb.colors.arrowBg = RIP_COLOR_LT_GRAY; sb.colors.arrowFg = RIP_COLOR_BLACK; sb.colors.bevelBright = RIP_COLOR_WHITE; sb.colors.bevelDark = RIP_COLOR_DK_GRAY;
load("rip_scrollbar.js");
load("rip_lib.js");
// Helper to send a batch of RIP commands
function sendRIP(cmds) {
console.write("\r!" + cmds + RIPGotoXYNumeric(0, 0) + "\r\n");
}
// Create a vertical scrollbar at pixel position (600, 70), 14 pixels wide, 260 pixels tall var sb = new RIPScrollbar(600, 70, 14, 260); sb.setScrollState(100, 20, 0); // 100 total items, 20 visible, starting at item 0 sb.computeLayout();
// Draw the scrollbar and register mouse regions sendRIP(sb.buildFullRIP() + sb.buildMouseRegionsRIP());
// In your input loop, when the user scrolls: sb.topIndex = 5; // User scrolled down to show items 5-24 sendRIP(sb.buildThumbRIP() + sb.buildMouseRegionsRIP());
load("rip_scrollbar.js");
load("rip_lib.js");
function sendRIP(cmds) {
console.write("\r!" + cmds + RIPGotoXYNumeric(0, 0) + "\r\n");
}
// Create a horizontal scrollbar at pixel position (50, 330), 500 pixels wide, 14 pixels tall var sb = new RIPScrollbar(50, 330, 500, 14); sb.horizontal = true; // Switch to horizontal mode sb.setScrollState(200, 50, 0); // 200 total items, 50 visible, starting at item 0 sb.computeLayout();
// Draw and register mouse regions (same API as vertical) sendRIP(sb.buildFullRIP() + sb.buildMouseRegionsRIP());
When the user clicks on the scrollbar's mouse regions, SyncTerm sends the corresponding character code. Here is an example of handling the mouse input in a getkey() loop. The handling code is the same for vertical and horizontal scrollbars — only the coordinate variable (Y vs X) differs for the thumb drag:
var key = console.getkey(K_NOCRLF | K_NOECHO | K_NOSPIN); var ch = key.charCodeAt(0);
if (ch === sb.mouseChars.scrollUp) {
if (topIndex > 0) --topIndex;
}
else if (ch === sb.mouseChars.scrollDn) {
if (topIndex < maxTopIndex) ++topIndex;
}
else if (ch === sb.mouseChars.trackPgUp) {
topIndex = Math.max(0, topIndex - visibleCount);
}
else if (ch === sb.mouseChars.trackPgDn) {
topIndex = Math.min(maxTopIndex, topIndex + visibleCount);
}
else if (ch === sb.mouseChars.thumbDrag) {
// Read the coordinate digits that follow. For vertical scrollbars this is
// the $Y$ value; for horizontal scrollbars this is the $X$ value.
var coordStr = "";
for (var d = 0; d < 4; ++d) {
var dc = console.inkey(0, 500);
if (dc === "") break;
coordStr += dc;
}
var mouseCoord = parseInt(coordStr, 10);
if (!isNaN(mouseCoord)) {
var sbL = sb._layout;
if (sb.horizontal) {
// Horizontal: map X coordinate to scroll position
var thumb = sb.getThumbGeometry();
var thumbRange = sbL.trackWidth - thumb.w;
if (thumbRange > 0) {
var clampedX = Math.max(sbL.trackLeft, Math.min(sbL.trackRight, mouseCoord));
var relX = clampedX - sbL.trackLeft;
topIndex = Math.round(relX * maxTopIndex / thumbRange);
topIndex = Math.max(0, Math.min(maxTopIndex, topIndex));
}
}
else {
// Vertical: map Y coordinate to scroll position
var thumb = sb.getThumbGeometry();
var thumbRange = sbL.trackHeight - thumb.h;
if (thumbRange > 0) {
var clampedY = Math.max(sbL.trackTop, Math.min(sbL.trackBot, mouseCoord));
var relY = clampedY - sbL.trackTop;
topIndex = Math.round(relY * maxTopIndex / thumbRange);
topIndex = Math.max(0, Math.min(maxTopIndex, topIndex));
}
}
}
}
// After updating topIndex, redraw the thumb and mouse regions sb.topIndex = topIndex; sendRIP(sb.buildThumbRIP() + sb.buildMouseRegionsRIP());
For real-world examples where RIPScrollbar is used, see: