Skip to content
Snippets Groups Projects
Commit e1512593 authored by Michael Long's avatar Michael Long
Browse files

Custom external program menus mod. Allows making custom external menus that...

Custom external program menus mod. Allows making custom external menus that can point to other custom menus, section menus, or external programs. Adds a number of formatting options and enhancements.
parent 9f967c88
No related branches found
No related tags found
2 merge requests!50Mlong/ddmsgcolor,!41Custom external program menus mod. Allows making custom external menus that...
Pipeline #869 passed
// Custom External Program Menu Library
"use strict";
load("sbbsdefs.js");
/* text.dat entries */
load("text.js");
function ExternalMenus() {
this.options = {};
this.xtrn_custommenu_options = {};
this.menuconfig = {};
this.getOptions();
this.getMenuConfig();
}
ExternalMenus.prototype.getMenuConfig = function() {
var config_file = new File(system.ctrl_dir + "xtrnmenu.cfg");
var config_src;
this.menuconfig = undefined;
if (config_file.open('r+')) {
config_src = config_file.read();
config_file.close();
}
if (typeof config_src !== "undefined") {
this.menuconfig = JSON.parse(config_src.toString());
}
}
ExternalMenus.prototype.getOptions = function(menutype, menuid) {
if (typeof menutype === "undefined") {
menutype = 'custommenu';
}
// Get xtrn_sec options from modopts.ini [xtrn_sec]
if ((this.options = load({}, "modopts.js", "xtrn_sec")) == null) {
this.options = { multicolumn: true, sort: false };
}
// Get xtrn_custommenu options from modopts.ini [xtrn_custommenu]
if ((this.xtrn_custommenu_options = load({}, "modopts.js", "xtrn_custommenu")) == null) {
this.xtrn_custommenu_options = { };
}
// in all cases, we start with the xtrn_sec options as the base and set the defaults
if (this.options.multicolumn === undefined)
this.options.multicolumn = true;
if (this.options.multicolumn_separator === undefined)
this.options.multicolumn_separator = " ";
if ((this.options.multicolumn_fmt === undefined) && (typeof bbs !== "undefined"))
this.options.multicolumn_fmt = bbs.text(XtrnProgLstFmt);
if (this.options.singlecolumn_fmt === undefined)
this.options.singlecolumn_fmt = "\x01h\x01c%3u \xb3 \x01n\x01c%s\x01h ";
if (this.options.singlecolumn_margin == undefined)
this.options.singlecolumn_margin = 7;
if (typeof bbs !== "undefined") {
if (this.options.singlecolumn_height == undefined)
this.options.singlecolumn_height = console.screen_rows - this.options.singlecolumn_margin;
// override and turn off multicolumn if terminal width is less than 80
if (console.screen_columns < 80)
options.multicolumn = false;
}
if (this.options.restricted_user_msg === undefined) {
this.options.restricted_user_msg = typeof bbs !== "undefined" ? bbs.text(R_ExternalPrograms)
: "You do not have access to this program.";
}
if (this.options.no_programs_msg === undefined) {
this.options.no_programs_msg = typeof bbs !== "undefined" ? bbs.text(NoXtrnPrograms)
: "No programs found.";
}
if ((this.options.header_fmt === undefined) && (typeof bbs !== "undefined"))
this.options.header_fmt = bbs.text(XtrnProgLstHdr);
if ((this.options.titles === undefined) && (typeof bbs !== "undefined"))
this.options.titles = bbs.text(XtrnProgLstTitles);
if ((this.options.underline === undefined) && (typeof bbs !== "undefined"))
this.options.underline = bbs.text(XtrnProgLstUnderline);
if ((this.options.which === undefined) && (typeof bbs !== "undefined"))
this.options.which = bbs.text(WhichXtrnProg);
if (this.options.clear_screen === undefined)
this.options.clear_screen = true;
if (this.options.section_fmt === undefined)
this.options.section_fmt = "\x01y\x01g%3d:\x01n\x01g %s"
if (this.options.section_header_fmt === undefined)
this.options.section_header_fmt = "\x01-\x01gSelect \x01hExternal Program Section\x01-\x01g:"
if (this.options.section_which === undefined)
this.options.section_which = "\r\n\x01-\x01gWhich, \x01w\x01h~Q\x01n\x01guit or [1]: \x01h"
// if its a custom menu, then override with custommenu_options
if (menutype == 'custommenu') {
if (typeof this.xtrn_custommenu_options.multicolumn_fmt !== "undefined") {
this.options.multicolumn_fmt = this.xtrn_custommenu_options.multicolumn_fmt;
} else {
// cannot default to xtrn_sec multicolumn_fmt due to use of %u instead of %s
this.options.multicolumn_fmt = "\x01h\x01c%3s \xb3 \x01n\x01c%-32.32s\x01h ";
}
if (typeof this.xtrn_custommenu_options.singlecolumn_fmt !== "undefined") {
this.options.singlecolumn_fmt = this.xtrn_custommenu_options.singlecolumn_fmt;
} else {
// cannot default to xtrn_sec multicolumn_fmt due to use of %u instead of %s
this.options.singlecolumn_fmt = "\x01h\x01c%3s \xb3 \x01n\x01c%s\x01h ";
}
this.options.header_fmt = (typeof this.xtrn_custommenu_options.header_fmt !== "undefined")
? this.xtrn_custommenu_options.header_fmt : this.options.header_fmt;
this.options.titles = (typeof this.xtrn_custommenu_options.titles !== "undefined")
? this.xtrn_custommenu_options.titles : this.options.titles;
this.options.which = (typeof this.xtrn_custommenu_options.which !== "undefined")
? this.xtrn_custommenu_options.which : this.options.which;
this.options.underline = (typeof this.xtrn_custommenu_options.underline !== "undefined")
? this.xtrn_custommenu_options.underline : this.options.underline;
this.options.multicolumn_separator = (typeof this.xtrn_custommenu_options.multicolumn_separator !== "undefined")
? this.xtrn_custommenu_options.multicolumn_separator : this.options.multicolumn_separator;
this.options.multicolumn = (typeof this.xtrn_custommenu_options.multicolumn !== "undefined")
? this.xtrn_custommenu_options.multicolumn : this.options.multicolumn;
this.options.sort = (typeof this.xtrn_custommenu_options.sort !== "undefined")
? this.xtrn_custommenu_options.sort : this.options.sort;
this.options.clear_screen = (typeof this.xtrn_custommenu_options.clear_screen !== "undefined")
? this.xtrn_custommenu_options.clear_screen : this.options.clear_screen;
this.options.singlecolumn_margin = (typeof this.xtrn_custommenu_options.singlecolumn_margin !== "undefined")
? this.xtrn_custommenu_options.singlecolumn_margin : this.options.singlecolumn_margin;
if (typeof bbs !== "undefined") {
this.options.singlecolumn_height = (typeof this.xtrn_custommenu_options.singlecolumn_height !== "undefined")
? this.xtrn_custommenu_options.singlecolumn_height : this.options.singlecolumn_height;
}
// no need to override restricted_user_msg or no_programs_msg - these
// will be the same for both types of menus
// Allow overriding on a per-menu basis
var menuoptions = load({}, "modopts.js", "xtrn_custommenu:" + menuid);
if ((typeof menuid !== "undefined") && (menuoptions != null)) {
for (var m in menuoptions) {
this.options[m] = menuoptions[m];
}
/*
this.options.multicolumn_fmt = (typeof menuoptions.multicolumn_fmt !== "undefined")
? menuoptions.multicolumn_fmt : this.options.multicolumn_fmt;
this.options.singlecolumn_fmt = (typeof menuoptions.singlecolumn_fmt !== "undefined")
? menuoptions.singlecolumn_fmt : this.options.singlecolumn_fmt;
this.options.header_fmt = (typeof menuoptions.header_fmt !== "undefined")
? menuoptions.header_fmt : this.options.header_fmt;
this.options.titles = (typeof menuoptions.titles !== "undefined")
? menuoptions.titles : this.options.titles;
this.options.which = (typeof menuoptions.which !== "undefined")
? menuoptions.which : this.options.which;
this.options.underline = (typeof menuoptions.underline !== "undefined")
? menuoptions.underline : this.options.underline;
this.options.multicolumn_separator = (typeof menuoptions.multicolumn_separator !== "undefined")
? menuoptions.multicolumn_separator : this.options.multicolumn_separator;
this.options.multicolumn = (typeof menuoptions.multicolumn !== "undefined")
? menuoptions.multicolumn : this.options.multicolumn;
this.options.sort = (typeof menuoptions.sort !== "undefined")
? menuoptions.sort : this.options.sort;
this.options.clear_screen = (typeof menuoptions.clear_screen !== "undefined")
? menuoptions.clear_screen : this.options.clear_screen;
this.options.singlecolumn_margin = (typeof menuoptions.singlecolumn_margin !== "undefined")
? menuoptions.singlecolumn_margin : this.options.singlecolumn_margin;
if (typeof bbs !== "undefined") {
this.options.singlecolumn_height = (typeof menuoptions.singlecolumn_height !== "undefined")
? menuoptions.singlecolumn_height : this.options.singlecolumn_height;
}
*/
}
}
// these options only apply to terminals/consoles
// the intention is to obtain all the mod_opts options for xtrn_sec, and
// override if a custom menu global setting is set
//TEMP
//// The following are used for the enhanced custom menu functionality
if (this.options.custom_menu_not_found_msg === undefined) {
this.options.custom_menu_not_found_msg = "Menu %MENUID% not found";
}
if (this.options.custom_menu_program_not_found_msg === undefined) {
this.options.custom_menu_program_not_found_msg = "Program %PROGRAMID% not found";
}
return this.options;
}
//@TODO deprecated
ExternalMenus.prototype.convert_input_literals_to_js = function(val) {
if (val === undefined) {
throw "incorrect configuration, please check modopts.ini";
}
var newString = val.replace(/\\x([0-9A-F][0-9A-F])/g, function(m, g1) {
return String.fromCharCode(parseInt(g1, 16));
});
return newString.replace(/\\u/g, '%u').replace(/\\r/g, "\r").replace(/\\n/g, "\n");
}
// return a custom menu object
ExternalMenus.prototype.getMenu = function(menuid) {
// grab the specified menu, or get the main menu
if ((typeof menuid === "undefined") || !menuid) {
menuid = "main";
} else {
menuid = menuid.toLowerCase();
}
var menu;
if ((typeof this.menuconfig !== "undefined") && (typeof this.menuconfig.menus !== "undefined")) {
this.menuconfig.menus.some(function (indmenu) {
if (indmenu.id.toLowerCase() == menuid) {
menu = indmenu;
}
});
}
if (!menu && (menuid == "main")) {
// no custom menus defined, make one to mimic old behavior
var menuitems = [];
var i;
xtrn_area.sec_list.forEach(function (sec) {
if (sec.can_access) {
menuitems.push({
"input": i,
"target": sec.code,
"type": "xtrnmenu",
"title": sec.name,
"access_string": sec.ars
});
i++;
}
});
menu = {
"id": "main",
"title": "Main Menu",
"items": menuitems
};
}
return menu;
}
// return a section menu object (stock synchronet external door section)
ExternalMenus.prototype.getSectionMenu = function(menuid) {
// grab the specified menu, or get the main menu
if ((typeof menuid === "undefined") || !menuid) {
return false;
}
var menuitems = [];
var menu, title;
xtrn_area.sec_list.some(function (sec) {
if (sec.code.toLowerCase() == menuid.toLowerCase()) {
title = sec.name;
if (!sec.can_access || sec.prog_list.length < 1) {
return false;
}
var i = 1;
sec.prog_list.some(function (prog) {
menuitems.push({
'input' : i,
'target': prog.code,
'title': prog.name,
'type': 'xtrnprog',
'access_string': prog.ars,
'cost': prog.cost
});
i++;
});
if (menuitems.length > 0) {
menu = {
'id': menuid,
'title': title,
'items': menuitems,
};
}
return;
}
});
return menu;
}
// Sort the menu items according to options
ExternalMenus.prototype.getSortedItems = function(menuobj) {
var sort_type;
if ((typeof menuobj.sort_type !== "undefined") && menuobj.sort_type) {
sort_type = menuobj.sort_type; // "name" or "key"
} else {
sort_type = this.options.sort; // bool
}
// first, build a new menu with only options they have access to
var menuitemsfiltered = [];
for (i in menuobj.items) {
switch (menuobj.items[i].type) {
case 'xtrnmenu':
for (j in xtrn_area.sec_list) {
if (xtrn_area.sec_list[j].code.toUpperCase() == menuobj.items[i].target.toUpperCase()) {
if (xtrn_area.sec_list[j].can_access) {
menuitemsfiltered.push(menuobj.items[i]);
}
}
}
break;
case 'xtrnprog':
for (j in xtrn_area.sec_list) {
for (var k in xtrn_area.sec_list[j].prog_list) {
if (xtrn_area.sec_list[j].prog_list[k].code.toUpperCase() == menuobj.items[i].target.toUpperCase()) {
if (xtrn_area.sec_list[j].prog_list[k].can_access) {
menuitemsfiltered.push(menuobj.items[i]);
}
}
}
}
break;
case 'custommenu':
default:
if ((typeof menuobj.items[i].access_string === "undefined") || !menuobj.items[i].access_string) {
// no access string defined, everyone gets access
menuitemsfiltered.push(menuobj.items[i]);
} else {
if (typeof bbs !== "undefined") {
if (bbs.compare_ars(menuobj.items[i].access_string)) {
// they have access
menuitemsfiltered.push(menuobj.items[i]);
}
} else {
if (user.compare_ars(menuobj.items[i].access_string)) {
// they have access
menuitemsfiltered.push(menuobj.items[i]);
}
}
}
break;
}
}
// if no custom input keys are specified for an input, then assign a numeric input
// this would mimic the built-in external section menu functionality
// but this is only assigned on sort_type key because if the sort type is for
// titles, we need to sort by title first before assigning the sequential numbers
var sortind = 0;
// make sure we only use the next available number for automatic assignment
for (i in menuitemsfiltered) {
if (!isNaN(menuitemsfiltered[i].input)) {
if (menuitemsfiltered[i].input > sortind) {
sortind = menuitemsfiltered[i].input;
}
}
}
sortind++;
if (sort_type == "key") {
for (i in menuitemsfiltered) {
if (!menuitemsfiltered[i].input) {
menuitemsfiltered[i].input = sortind;
sortind++;
}
}
}
if (sort_type) {
switch (sort_type) {
case "key":
menuitemsfiltered.sort(this.sort_by_input);
break;
default:
case "title":
case "name":
menuitemsfiltered.sort(this.sort_by_title);
break;
}
}
// if this is a sort by title and the key is empty, it will be assigned the next available number
// this is to support auto-generated inputs like is done on the built-in section menus
// however, to keep the numeric keys in order, the numbers could not be pre-assigned like it done
// on the sort_type key
for (i in menuitemsfiltered) {
if ((sort_type !== "key") && !menuitemsfiltered[i].input) {
menuitemsfiltered[i].input = sortind;
sortind++;
}
}
return menuitemsfiltered;
}
// Original sort function used by external_program_menu and external_section_menu
ExternalMenus.prototype.sort_by_name = function(a, b) {
if(a.name.toLowerCase()>b.name.toLowerCase()) return 1;
if(a.name.toLowerCase()<b.name.toLowerCase()) return -1;
return 0;
}
// Sort by title - used by external_section_menu_custom
ExternalMenus.prototype.sort_by_title = function(a, b) {
if (a.title.toLowerCase() < b.title.toLowerCase()) {
return -1;
}
if (a.title.toLowerCase() > b.title.toLowerCase()) {
return 1;
}
return 0;
}
// Sort by input key - used by external_section_menu_custom
ExternalMenus.prototype.sort_by_input = function(a, b) {
if (a.input.toString().toLowerCase() < b.input.toString().toLowerCase()) {
return -1;
}
if (a.input.toString().toLowerCase() > b.input.toString().toLowerCase()) {
return 1;
}
return 0;
}
// xtrnmenu.js
// Custom External Program Menu Mod
// Menus displayed to users via Terminal Server (Telnet/RLogin/SSH)
// To jump straight to a specific xtrn section, pass the section code as an
// argument
// To set options, add to modopts.ini [xtrn_sec]
// To install, go to scfg, System, Loadable Modules and set Xtrn Section to xtrnmenu
"use strict";
load("sbbsdefs.js");
/* text.dat entries */
load("text.js");
load("xtrnmenulib.js");
var options, menuconfig, xsec = -1;
//// Main
var ExternalMenus = new ExternalMenus();
var menuconfig = ExternalMenus.menuconfig;
var xsec=-1;
{
var i,j;
for(i in argv) {
for(j in xtrn_area.sec_list) {
if(argv[i].toLowerCase()==xtrn_area.sec_list[j].code)
xsec=j;
}
}
}
if (xsec > -1) {
// if its the id of a standard section menu, send it to the
// stock menu
js.exec("xtrn_sec.js", {}, xsec);
} else if (typeof argv[0] !== "undefined") {
// if its not a section menu, assume it is a custom menu
external_section_menu_custom(argv[0]);
} else {
// main custom menu
external_section_menu_custom();
}
// Renders the top-level external menu
function external_section_menu_custom(menuid)
{
var i, menucheck, menuobj, item_multicolumn_fmt, item_singlecolumn_fmt,
cost, multicolumn, menuitemsfiltered = [];
var keylimit = 1; // max chars allowed on menu selection
var options = ExternalMenus.getOptions('custommenu', menuid);
menuobj = ExternalMenus.getMenu(menuid);
// Allow overriding auto-format on a per-menu basis
var multicolumn_fmt = options.multicolumn_fmt;
var singlecolumn_fmt = options.singlecolumn_fmt;
while (bbs.online) {
console.aborted = false;
if (typeof menuobj === "undefined") {
doerror(options.custom_menu_not_found_msg.replace('%MENUID%', menuid));
break;
}
if (options.clear_screen) {
console.clear(LIGHTGRAY);
}
if (user.security.restrictions&UFLAG_X) {
write(options.restricted_user_msg);
break;
}
if (!xtrn_area.sec_list.length) {
write(options.no_programs_msg);
break;
}
var keyin;
system.node_list[bbs.node_num-1].aux = 0; /* aux is 0, only if at menu */
bbs.node_action = NODE_XTRN;
bbs.node_sync();
menuitemsfiltered = ExternalMenus.getSortedItems(menuobj);
if (bbs.menu_exists("xtrn_custom_" + menuid)) {
// if file exists text/menu/xtern_custom_(menuid).[rip|ans|mon|msg|asc], then display that instead
bbs.menu("xtrn_custom_" + menuid);
} else {
// if no custom menu file in text/menu, create a dynamic one
console.crlf();
multicolumn = options.multicolumn && menuitemsfiltered.length > options.singlecolumn_height;
printf(options.header_fmt, menuobj.title);
if(options.titles.trimRight() != '')
write(options.titles);
if(multicolumn) {
write(options.multicolumn_separator);
if (options.titles.trimRight() != '')
write(options.titles);
}
if(options.underline.trimRight() != '') {
console.crlf();
write(options.underline);
}
if(multicolumn) {
write(options.multicolumn_separator);
if (options.underline.trimRight() != '')
write(options.underline);
}
console.crlf();
// n is the number of items for the 1st column
var n;
if (multicolumn) {
n = Math.floor(menuitemsfiltered.length / 2) + (menuitemsfiltered.length & 1);
} else {
n = menuitemsfiltered.length;
}
// j is the index for each menu item on 2nd column
var j = n; // start j at the first item for 2nd column
for (i = 0; i < n && !console.aborted; i++) {
cost = "";
if (menuitemsfiltered[i].type == "xtrnprog") {
// if its an external program, get the cost
cost = xtrn_area.prog[menuitemsfiltered[i].target.toLowerCase()].cost;
}
console.add_hotspot(menuitemsfiltered[i].input.toString());
if (menuitemsfiltered[i].input.toString().length > keylimit) {
keylimit = menuitemsfiltered[i].input.toString().length;
}
// allow overriding format on a per-item basis
// great for featuring a specific game
var checkkey = menuitemsfiltered[i].target + '-multicolumn_fmt';
checkkey = checkkey.toLowerCase();
item_multicolumn_fmt = (typeof options[checkkey] !== "undefined") ?
options[checkkey] : options.multicolumn_fmt;
checkkey = menuitemsfiltered[i].target + '-singlecolumn_fmt'
checkkey = checkkey.toLowerCase();
item_singlecolumn_fmt = (typeof options[checkkey] !== "undefined") ?
options[checkkey] : options.singlecolumn_fmt;
printf(multicolumn ? item_multicolumn_fmt : item_singlecolumn_fmt,
menuitemsfiltered[i].input.toString().toUpperCase(),
menuitemsfiltered[i].title,
cost
);
if (multicolumn) {
if ((typeof(menuitemsfiltered[j]) !== "undefined")) {
// allow overriding format on a per-item basis
// great for featuring a specific game
item_multicolumn_fmt = menuitemsfiltered[j].multicolumn_fmt
? convert_input_literals_to_js(menuitemsfiltered[j].multicolumn_fmt) : multicolumn_fmt;
item_singlecolumn_fmt = menuitemsfiltered[j].singlecolumn_fmt
? convert_input_literals_to_js(menuitemsfiltered[j].singlecolumn_fmt) : singlecolumn_fmt;
if (menuitemsfiltered[j].input.toString().length > keylimit) {
keylimit = menuitemsfiltered[j].input.toString().length;
}
write(options.multicolumn_separator);
console.add_hotspot(menuitemsfiltered[j].input.toString());
printf(item_multicolumn_fmt,
menuitemsfiltered[j].input.toString().toUpperCase(),
menuitemsfiltered[j].title,
cost
);
} else {
write(options.multicolumn_separator);
}
j++;
}
console.crlf();
}
// synchronize with node database, checks for messages,
// interruption, etc. (AKA node_sync), clears the current console
// line if there's a message to print when clearline is true.
bbs.node_sync();
// print a mnemonics string, command keys highlighted with
// tilde (~) characters; prints "Which or Quit"
console.mnemonics(options.which);
}
keyin = console.getkey(K_NONE);
// if there are 2 or 3 letter input options, then give the user a chance to type the 2nd and third chars
// unfortunately, this will introduce latency for the single key options
// and if the typist is slow, they are going to get the single key menu option selected instead if one exists
if (keylimit > 1) {
// check for possible second digit (on 2 and 3 char inputs)
var keyin2 = console.inkey(K_NONE, 1000);
keyin = keyin + keyin2;
} else if (keylimit == 3) {
// check for possible third digit
var keyin3 = console.inkey(K_NONE, 1000);
keyin = keyin + keyin3;
}
keyin = keyin.toLowerCase();
if (keyin) {
// q for quit
if (keyin == "q") {
console.clear();
break;
}
menuitemsfiltered.some(function (menuitemfiltered) {
var menutarget = menuitemfiltered.target.toLowerCase();
var menuinput = menuitemfiltered.input.toString().toLowerCase();
if (menuinput == keyin) {
switch (menuitemfiltered.type) {
// custom menu, defined in xtrnmenu.json
case 'custommenu':
external_section_menu_custom(menutarget);
return true;
// external program section
case 'xtrnmenu':
js.exec("xtrn_sec.js", {}, menutarget);
//js.exec(js.exec_dir + 'xtrn_sec.js ' + menutarget)
return true;
// external program
case 'xtrnprog':
// run the external program
if (typeof xtrn_area.prog[menutarget] !== "undefined") {
bbs.exec_xtrn(menutarget);
return true;
} else {
doerror(options.custom_menu_program_not_found_msg.replace('%PROGRAMID%', menutarget));
}
break;
} //switch
} // if menu item matched keyin
}); // foreach menu item
} // if keyin
} // main bbs.online loop
}
// Display error message to console and save to log
function doerror(msg)
{
console.crlf();
log(LOG_ERR, msg);
console.putmsg('\x01+\x01h\x01r' +msg + ". The sysop has been notified." + '\x01-\r\n');
}
This diff is collapsed.
<!--HIDDEN:Games-->
<?xjs
load("ftelnethelper.js");
load('sbbsdefs.js');
load("xtrnmenulib.js");
load(settings.web_lib + 'ftelnet.js');
load(settings.web_lib + 'request.js');
var ExternalMenus = new ExternalMenus();
if (typeof settings.xtrn_blacklist === 'string') {
settings.xtrn_blacklist = settings.xtrn_blacklist.toLowerCase().split(',');
} else {
settings.xtrn_blacklist = [];
}
var menuitems = [];
?>
<style>.fTelnetStatusBar { display : none; }</style>
<a name="fTelnet"></a>
<div id="fTelnetContainer" class="fTelnetContainer" style="margin-bottom:1em;"></div>
<div id="xtrn-list" class="list-group">
<?xjs
var menuobj;
if ((Request.get_param('type') == 'xtrnmenu') && Request.has_param('target')) {
menuobj = ExternalMenus.getSectionMenu(Request.get_param('target'));
} else {
if (Request.has_param('target')) {
menuobj = ExternalMenus.getMenu(Request.get_param('target'));
} else {
menuobj = ExternalMenus.getMenu('main');
}
}
if ((typeof menuobj === "undefined") || !menuobj
|| (typeof menuobj.items === "undefined") || (menuobj.items.length < 1)) {
writeln("<h4>" + ExternalMenus.options.no_programs_msg + "</h4>");
} else if (user.security.restrictions&UFLAG_X) {
writeln("<h4>" + options.restricted_user_msg + "</h4>");
} else {
// ok to display menu
writeln("<h4>" + menuobj.title + "</h4>");
var menuitemsfiltered = ExternalMenus.getSortedItems(menuobj);
menuitemsfiltered.forEach(function (menuitem) {
if (settings.xtrn_blacklist.indexOf(menuitem.target.toLowerCase()) > -1) {
return;
}
menuitems.push({
'itemtitle': menuitem.title,
'itemtype': menuitem.type,
'itemtarget': menuitem.target
});
});
}
?>
</div>
<script id="fTelnetScript" src="<?xjs write(get_url()); ?>"></script>
<script type="text/javascript">
var wsp = <?xjs write(settings.wsp || GetWebSocketServicePort()); ?>;
var wssp = <?xjs write(settings.wssp || GetWebSocketServicePort(true)); ?>;
var Options = new fTelnetOptions();
Options.BareLFtoCRLF = false;
Options.BitsPerSecond = 57600;
Options.ConnectionType = 'rlogin';
Options.Emulation = 'ansi-bbs';
Options.Enter = '\r';
Options.Font = 'CP437';
Options.ForceWss = false;
Options.Hostname = '<?xjs write(http_request.vhost); ?>';
Options.LocalEcho = false;
Options.Port = location.protocol == 'https:' ? wssp : wsp;
Options.RLoginClientUsername = '<?xjs write(user.security.password); ?>';
Options.RLoginServerUsername = '<?xjs write(user.alias); ?>';
Options.ScreenColumns = 80;
Options.ScreenRows = 25;
Options.SplashScreen = Options.SplashScreen = '<?xjs write(get_splash()); ?>';
Options.WebSocketUrlPath = '?Port=<?xjs write(GetRLoginPort()); ?>';
var fTelnet = new fTelnetClient('fTelnetContainer', Options);
fTelnet.OnConnectionClose = function () {
window.location.reload();
};
async function launchXtrn() {
var code = event.srcElement.id;
await v4_get('./api/system.ssjs?call=set-xtrn-intent&code=' + code);
fTelnet._Options.RLoginTerminalType = 'xtrn=' + code;
fTelnet.Connect();
}
var menuitems = <?xjs write(JSON.stringify(menuitems)); ?>;
var currentTarget = "<?xjs Request.write_param('target'); ?>";
var currentType = "<?xjs Request.write_param('type'); ?>";
var currentTitle = `<?xjs write(menuobj.title) ?>`;
if (currentTitle && !currentTarget) {
// main menu - store title for breadcrumb
sessionStorage.setItem("mainmenu", currentTitle);
}
var div = $('#xtrn-list');
menuitems.forEach(function (menuitem) {
var a = document.createElement('a');
$(a).addClass("list-group-item");
$(a).addClass("striped");
a.text = menuitem.itemtitle;
if (menuitem.itemtype == "xtrnprog") {
a.href = "#fTelnet";
a.id = menuitem.itemtarget;
a.onclick = function () { launchXtrn(); };
} else {
a.href = "/?page=<?xjs Request.write_param('page') ?>&type=" +menuitem.itemtype
+ "&target=" + menuitem.itemtarget;
a.onclick = function () {
sessionStorage.setItem('prev:' + menuitem.itemtarget.toLowerCase(), '<?xjs Request.write_param('target')?>');
sessionStorage.setItem('prevtype:' + menuitem.itemtarget.toLowerCase(), '<?xjs Request.write_param('type')?>');
sessionStorage.setItem('prevtitle:' + menuitem.itemtarget.toLowerCase(), currentTitle);
};
}
$(div).append(a);
});
// breadcrumb
var prevTarget = sessionStorage.getItem('prev:' + currentTarget.toLowerCase());
var prevType = sessionStorage.getItem('prevtype:' + currentTarget.toLowerCase());
var prevTitle = sessionStorage.getItem('prevtitle:' + currentTarget.toLowerCase());
if (prevType && prevTarget && prevTitle) {
$('#xtrn-list').prepend('<ol class="breadcrumb"><a href="/?page=<?xjs Request.write_param('page') ?>&type=' + prevType
+ '&target=' + prevTarget + '">' + prevTitle + '</a></ol>');
} else if (currentTarget) {
// level 2, not main menu
var mainmenuTitle = sessionStorage.getItem('mainmenu');
if (!mainmenuTitle) {
mainmenuTitle = 'Games';
}
$('#xtrn-list').prepend('<ol class="breadcrumb"><a href="/?page=<?xjs Request.write_param('page') ?>">' + mainmenuTitle + '</a></ol>');
}
</script>
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment