Skip to content
Snippets Groups Projects
Commit 738f4918 authored by Kayz's avatar Kayz Committed by Rob Swindell
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 8a64acdd
No related branches found
No related tags found
No related merge requests found
/**
* Custom External Program Menu Library for Custom External Program Menus
* by Michael Long mlong innerrealmbbs.us
*
* This provides common functionality for retrieving menus used by
* the loadable module xtrnmenu.js and by the web interface
* 099-xtrnmenu-games.xjs
*/
"use strict";
load("sbbsdefs.js", "K_NONE");
/* text.dat entries */
require("text.js", "XtrnProgLstFmt");
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", "xtrnmenu")) == 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)
this.options.multicolumn_fmt = system.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 = system.text(R_ExternalPrograms);
if (this.options.no_programs_msg === undefined)
this.options.no_programs_msg = system.text(NoXtrnPrograms);
if (this.options.header_fmt === undefined)
this.options.header_fmt = system.text(XtrnProgLstHdr);
if (this.options.titles === undefined)
this.options.titles = system.text(XtrnProgLstTitles);
if (this.options.underline === undefined)
this.options.underline = system.text(XtrnProgLstUnderline);
if (this.options.which === undefined)
this.options.which = system.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", "xtrnmenu:" + menuid);
if ((typeof menuid !== "undefined") && (menuoptions != null)) {
for (var m in menuoptions) {
this.options[m] = menuoptions[m];
}
}
}
// 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
//// 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;
}
// 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 (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;
}
/**
* Xtrn Menu Mod
* Custom External Program Menus
* by Michael Long mlong innerrealmbbs.us
*
* This is the loadable module that displays the custom external menus
* in terminal server (telnet/rlogin/ssh)
*
* To jump to a specific menu, pass the ID as an argument
*
* To set options, add to modopts.ini [xtrnmenu]
*
* See instructions at http://wiki.synchro.net/module:xtrnmenu
*/
"use strict";
require("sbbsdefs.js", "K_NONE");
load("xtrnmenulib.js");
var options, xsec = -1;
//// Main
var ExternalMenus = new ExternalMenus();
const menuconfig = ExternalMenus.menuconfig;
{
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 validkeys = []; // valid chars on menu selection
var keymax = 0; // max integer 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("xtrnmenu_head_" + menuid, P_NOERROR) && !bbs.menu("xtrnmenu_head", P_NOERROR)) {
bbs.menu("xtrn_head", P_NOERROR);
}
// if file exists text/menu/xtrnmenu_(menuid).[rip|ans|mon|msg|asc],
// then display that, otherwise dynamiic
if (!bbs.menu("xtrnmenu_" + menuid, P_NOERROR)) {
// if no custom menu file in text/menu, create a dynamic one
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());
validkeys.push(menuitemsfiltered[i].input.toString());
var intCheck = Number(menuitemsfiltered[i].input);
if (!intCheck.isNaN) {
if (intCheck > keymax) {
keymax = menuitemsfiltered[i].input;
}
}
// 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")) {
validkeys.push(menuitemsfiltered[j].input.toString());
var intCheck = Number(menuitemsfiltered[j].input);
if (!intCheck.isNaN) {
if (intCheck > keymax) {
keymax = menuitemsfiltered[j].input;
}
}
// allow overriding format on a per-item basis
// great for featuring a specific game
var checkkey = menuitemsfiltered[j].target + '-multicolumn_fmt';
checkkey = checkkey.toLowerCase();
item_multicolumn_fmt = (typeof options[checkkey] !== "undefined") ?
options[checkkey] : options.multicolumn_fmt;
checkkey = menuitemsfiltered[j].target + '-singlecolumn_fmt'
checkkey = checkkey.toLowerCase();
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();
}
if (!bbs.menu("xtrnmenu_tail_" + menuid, P_NOERROR) && !bbs.menu("xtrnmenu_tail", P_NOERROR)) {
bbs.menu("xtrn_tail", P_NOERROR);
}
bbs.node_sync();
console.mnemonics(options.which);
}
validkeys.push('q');
keyin = console.getkeys(validkeys, keymax, K_NONE);
keyin = keyin.toString().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
/**
* Web Display for Custom External Program Menus
* by Michael Long mlong innerrealmbbs.us
*
* See wiki at http://wiki.synchro.net/module:xtrnmenumod
*/
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.
Finish editing this message first!
Please register or to comment