/// <reference path="/ss/st/fvterm/web/Scripts/FVTermParent.js" />
/// <reference path="/ss/st/fvterm/web/Scripts/FVTermMsgApi.js" />
(function ()
{
'use strict';
function log(text)
{
/* not active
if (typeof (console) != 'undefined')
console.log(text);
*/
}
/**
* @fileOverview The FVSessions Module contains the FVSessions.Manager class function and the FVSessions.Session class
* @author Inventu Corporation <support@inventu.com">
* @version 1.0.20
*/
var FVSMGR, FVSESS,
enterKeys = 'EC123456789abcdefghijklmnoxyz';
//trim polyfill
if (!String.prototype.trim)
{
String.prototype.trim = function ()
{
return this.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
};
}
/**
* @namespace FVSessions
*/
if (!window.FVSessions)
window.FVSessions = {};
FVSessions.config = {
fvBaseUrl: '/fvterm/',
fvTermPage: 'scterm.html',
fvMacrosMgr: 'macros/FlowMacros.aspx',
fvProfileMgr: 'SCProfile.aspx',
msgAPI:true
};
// #region Manager class
/** The Manager Class is used to initialize the environment and host Session objects
* In September 2023, the FVSessions.config setting msgAPI was added with a default value of true.
* This now assumes that FVTermMsgApi.js instead of FVTermParent.js is the corresponding JS file
* providing the iFrame API management. FVTermMsgApi.js utilizes inter-window messaging instead
* of direct calls that require document.domain to be set in many environments.
* If you are using FVSessions.js with the direct API module FVTermParent.js, you will need to set
* FVSessions.config.msgAPI=false prior to creating a new connection.
* @typedef { FVSessions.Manager } Manager
*/
/** @typedef {Object} Connection
* @description Defines how a Session connects when started--matches all documented properties for the FVTermParent ConnectFVTerm function
* @property {string} application (optional--overrides the SessionControl property of same name if defined) Name of application defined in web.config for screen recognition
* @property {string} hostName Host name defined for the Inventu service that this session connects to
* @property {boolean} autoStart If true the session will automatically connect to the host at start time
* @property {boolean} keepAliveOnClose If true, the session will not be terminated/closed by the browser logic if the user closes the browser at the desktop level
* @property {string} userID Can be set prior to start session--this is the UserID to be associated with the session in the Inventu Service
* @property {Session} fnSessClass Needed at constructor time--defines class for sessions, such as FVSessions.HODSession-default is FVSessions.Session
*/
/** @typedef {Object} SessionControl
* @description Keyed by SessionID -- included in the SessionDef object passed as the control parameter to the Manager Class Constructor
* @property {function(Session, rows, screenName)} onnewscreen Event function called any time a new screen is received from the host
* @property {function(Session)} onclose Event function called when the session is closed
* @property {function(Session, enterKey)} onsend Event function called whenever the user enters a screen
* @property {string} frameId Optional frameID that this session should be opened/started in--if not set the name is 'FVSWin_' + the session id
* @property {Connection} connection Defines how the session will connect during the Manager.StartSession function
*/
/** @typedef {Object} SessionDef
* @property {string} application Default name of application defined in web.config for screen recognition -- can be overridden in session connection property
* @property {function(Session, rows, screenName)} onnewscreen Default Event function called any time a new screen is received from the host--
* can be overridden for each Session in the sessions SessionControl object
* @property {function(Session)} onclose Default Event function called when the session is closed--
* can be overridden for each Session in the sessions SessionControl object
* @property {function(Session, enterKey)} onsend Default Event function called whenever the user enters a screen--
* can be overridden for each Session in the sessions SessionControl object
* @property {SessionControl} sessions One or more session definitions keyed by the sessionID
*/
/** @constructor
* @description Manager Class Constructor function--please ensure that the FVSessions.config.msgAPI is set
* to correspond with the API JS file you are using (see FVSessions.Manager class documentation)
* @param {Object} win The Window object for the environment this Manager will run in
* @param {SessionDef} control Settings for the events and sessions, with objects keyed by sessionID key property for each session is connection
* @param {function(Object)} fnReady Completion function called when ready--includes a reference to the sessions object, indexed by session ids
*/
FVSessions.Manager = function (win, control, fnReady)
{
var key, me = this, session, sessionKey, sessionChecks = [],
sessions = (control && control.sessions) ? control.sessions : null, bindings, sessObj,
fnSessClass = (control.fnSessClass) ? control.fnSessClass : FVSessions.Session;
this.sessions = {};
if (control.application)
this.application = control.application;
this.win = win;
this.doc = win.document;
if (sessions)
{
for (key in sessions)
{
if (sessions.hasOwnProperty(key))
{
bindings = {};
sessObj = sessions[key];
if (control.onalert || sessObj.onalert)
bindings.onalert = (sessObj.onalert) ? sessObj.onalert : control.onalert;
if (control.onsend || sessObj.onsend)
bindings.onsend = (sessObj.onsend) ? sessObj.onsend : control.onsend;
if (control.onclose || sessObj.onclose)
bindings.onclose = (sessObj.onclose) ? sessObj.onclose : control.onclose;
if (control.onnewscreen || sessObj.onnewscreen)
bindings.onnewscreen = (sessObj.onnewscreen) ? sessObj.onnewscreen : control.onnewscreen;
this.sessions[key] = session = new fnSessClass(key, this, sessObj, bindings);
if (session.sessionKey)
sessionChecks.push(session.sessionKey);
}
}
if (sessionChecks.length)
{
this.ServerCall(FVSessions.config.fvBaseUrl + FVSessions.config.fvMacrosMgr + '?action=verifySessions', sessionChecks, { method: 'POST' }, function (statuses)
{
var i, id;
for (i = 0; i < statuses.length; i++)
{
session = me.FindSessionByKey(sessionChecks[i]);
session.SetStatus(statuses[i]);
}
if (fnReady)
fnReady(me.sessions);
});
}
else
{
if (fnReady)
window.setTimeout(function () { fnReady(me.sessions) }, 1);
}
}
};
FVSMGR = FVSessions.Manager.prototype;
/** @memberof! FVSessions.Manager.prototype
* @description Find a Session object based on a sessionKey
* @param {String} sessionKey The SessionKey to use in the search
* @returns {Session} Found session or null
*/
FVSMGR.FindSessionByKey = function (sessionKey)
{
var key;
for (key in this.sessions)
{
if (this.sessions[key].sessionKey == sessionKey)
return this.sessions[key];
}
}
/** @memberof! FVSessions.Manager.prototype
* @description Resize all Sessions
* @param {Integer} width New Width for each Session
* @param {Integer} height New height for each sessions
*/
FVSMGR.ResizeSessions = function (width, height)
{
var key, session;
for (key in this.sessions)
{
if (!this.sessions.hasOwnProperty(key))
continue;
session = this.sessions[key];
if (session.fvWin)
{
session.fvWin.style.width = width + 'px';
session.fvWin.style.height = height + 'px';
}
}
};
/** @memberof! FVSessions.Manager.prototype
* @description Start a Session
* @param {String} id The ID of the session - must match one of the sessions defined in the constructor
* @param {Object} styles (Optional) - If not null, an object with property names matching styles to attach to the new session's iFrame
* @param {Object} parentElem Parent DOM element--if not included, the document.body element will be the parent of the new iFrame
* @param {function(Session)} fnReady Completion function called when the session has been started
*/
FVSMGR.StartSession = function (id, styles, parentElem, fnReady)
{
var key, me = this, session = this.sessions[id], parentDiv,
fvWin = (session.fvWin) ? session.fvWin : this.doc.getElementById(session.frameId),
url = FVSessions.config.fvBaseUrl + FVSessions.config.fvTermPage,
connection = session.connection,
fnConnect = (FVSessions.config.msgAPI) ? FVMsgApi.ConnectMsgFVTerm : ConnectFVTerm;
if (!fvWin)
{
if (!parentElem)
parentElem = this.doc.body;
parentDiv = this.doc.createElement('div');
parentDiv.style.display = 'inline';
parentElem.appendChild(parentDiv);
parentDiv.innerHTML = '<iframe id="' + session.frameId + '" />';
fvWin = this.doc.getElementById(session.frameId);
session.fvWin = fvWin;
}
/* If msgApi, turn fvWin into a proxy and save the real fvWin
*/
if (styles)
{
for (key in styles)
{
if (styles.hasOwnProperty(key))
{
fvWin.style[key] = styles[key];
}
}
}
if (session.status != 'offline')
{
connection = { "sessionKey": session.sessionKey };
if (session.connection.keepAliveOnClose)
connection.keepAliveOnClose = session.connection.keepAliveOnClose;
if (this.application)
connection.application = this.application;
}
//fnConnect(fvWin.id, url, connection, async function (fvApi, sessionKey) need async?
fnConnect(fvWin.id, url, connection, async function (fvApi, sessionKey)
{
if (fvApi)
await session.BindNewSession(fvApi, sessionKey);
else
session.connectError = sessionKey;
if (fnReady)
fnReady(session);
});
};
/** @memberof! FVSessions.Manager.prototype
* @description Call a server function that supports the session manager
* @param {String} url Action portion of the url
* @param {Object} data (Optional) - For a post, the object that will be sent as JSON stringified null value is ignored
* @param {Object} options (optional) properties include method (GET/POST), mimeType, credUser and credPW all optional--null is ignored
* @param {function(Object)} fnReady Completion function called with returned object converted from JSON
* @returns {FVSMGR.ServerCall} object
*/
FVSMGR.ServerCall = function (url, data, options, fnReady)
{
var xmlHttp = null,
me = this, key,
err, method = (options && options.method) ? options.method : 'GET',
mimeType = (options && options.mimeType) ? options.mimeType : 'application/json',
credUser = (options && options.credUser) ? options.credUser : null,
credPW = (options && options.credPW) ? options.credPW : null,
query = [], postData = null;
try
{
if (window.XMLHttpRequest)
{
// If IE7, Mozilla, Safari, etc: Use native object
xmlHttp = new XMLHttpRequest();
if (xmlHttp.overrideMimeType)
xmlHttp.overrideMimeType(mimeType);
}
else if (window.ActiveXObject)
{
// ...otherwise, use the ActiveX control for IE5.x and IE6
xmlHttp = new ActiveXObject('MSXML2.XMLHTTP.3.0');
}
if (data)
{
if ((method == 'GET') ||
(mimeType != 'application/json'))
{
for (key in data)
{
if (data.hasOwnProperty(key))
query.push(encodeURIComponent(key) + '=' + encodeURIComponent(data[key]));
}
}
if (method == 'GET')
{
if (url.indexOf('?') == -1)
url += '?';
url += query.join('&');
}
else
{
if (mimeType == 'application/json')
postData = JSON.stringify(data);
else
postData = query.join('&');
}
}
xmlHttp.open(method, url, true, credUser, credPW);
xmlHttp.onreadystatechange = function ()
{
if (xmlHttp.readyState >= 4)
{
var result;
if (xmlHttp.status == 200)
{
if (mimeType == 'application/json')
result = JSON.parse(xmlHttp.responseText);
else
result = xmlHttp.responseText;
me.httpError = false;
}
else
{
result = { status: 'error', code: xmlHttp.status };
me.httpError = true;
}
if (fnReady)
{
fnReady(result);
}
}
};
if (method == 'POST')
xmlHttp.setRequestHeader('Content-type', 'application/json; charset=utf-8');
xmlHttp.send(postData);
}
catch (e)
{
alert(e.message);
return null;
}
return xmlHttp;
};
// #endregion Manager Class
// #region Session Class
/** The Session class manages an individual FVTerm session and is created using the Manager
* @typedef {FVSessions.Session} Session
*/
/** @description Session Class Constructor function
* @constructor
* @param {String} id The id for this session, used for access and naming
* @param {Object} mgr The owning FVSessions.Manager object
* @param {Object} settings The source properties including connection which has connection details
* @param {Object} bindings Any event/call forwarders
*/
FVSessions.Session = function (id, mgr, settings, bindings)
{
if (!id)
return;
this.id = id;
this.mgr = mgr;
this.settings = settings;
this.connection = settings.connection;
if (!this.connection.application && mgr.application)
this.connection.application = mgr.application;
this.status = 'offline';
this.frameId = (settings.frameId) ? settings.frameId : 'FVSWin_' + id;
this.storeId = 'FVSK_' + id;
this.sessionKey = this.GetSessionKey();
this.bindings = bindings;
if (FVSessions.config.msgAPI)
FVSessions.SetMsgMethods();
else
FVSessions.SetLocalMethods();
};
FVSESS = FVSessions.Session.prototype;
/** @memberof! FVSessions.Session.prototype
* @description Internal function that binds the FVTermParent events to the client's onnewscreen,
* onclose, onsend and onalert (when each handler is present) in support of the FVTermMsgApi.js module
* implemented September of 2023, this function is flagged async as the fvApi.GetCookieEx must run
* with an await to retain synchronicity in the messaging environment.
* @param {Object} fvApi Api Control Object
* @param {String} sessionKey SessionKey if for active session
* */
FVSESS.BindNewSession = async function (fvApi, sessionKey)
{
var me = this,
realSessionKey = (sessionKey && (sessionKey.substr(0, 4) == 'FVC_')) ? await fvApi.GetCookieEx(sessionKey) : sessionKey;
this.fvApi = fvApi;
if (sessionKey)
log('BindNewSession for ' + sessionKey + ' (' + realSessionKey + ')');
else
log('BindNewSession for failed session');
if (sessionKey)
this.SaveSessionKey(realSessionKey);
this.SetStatus('started');
fvApi.onnewscreen = function (rows, screenName)
{
me.screenName = screenName;
if (me.bindings.onnewscreen)
me.bindings.onnewscreen(me, rows, screenName);
};
fvApi.onclose = function (closeType)
{
me.SetStatus('offline'); // clears sessionkey
if (me.bindings.onclose)
me.bindings.onclose(me, closeType);
};
fvApi.onsend = function (enterKey)
{
if (me.bindings.onsend)
return me.bindings.onsend(me, enterKey);
else
return true;
};
fvApi.onalert = function (alertObj, msg, bgColor, fnOnClick, buttons)
{
if (me.bindings.onalert)
return me.bindings.onalert(me, alertObj, msg, bgColor, fnOnClick, buttons);
else
return null; // not handle
};
};
/** @memberof! FVSessions.Session.prototype
* @description Internal use only function used to set functions when FVSessions.config.msgAPI is true
*/
FVSessions.SetMsgMethods = function ()
{
/** @memberof! FVSessions.Session.prototype
* @description Close the Session if active
*/
FVSESS.Close = function ()
{
if (this.status != 'offline')
{
try
{
this.fvApi.CloseTerm();
}
catch (e) { }
}
};
/** @memberof! FVSessions.Session.prototype
* @description Control if the session has focus - Note for MsgAPI need to await this if you want it
* to be synchronous
* @param {boolean} focusOn If true the session will have focus set, if false, focus will be off and locked off until
* @param {boolean} activate If true, when focusOn is true, will also set browser focus into the FVTerm body
* set back on with this call
* @returns {Promise} For MsgAPI returns a Promise
*/
FVSESS.SetFocus = async function (focusOn, activate)
{
var me = this;
return new Promise(async (resolve) =>
{
if (this.status != 'offline')
{
try
{
if (focusOn)
{
await me.fvApi.EmActive(2, 'FVSession');
if (activate)
await me.fvApi.SCSetTermFocus();
}
else
{
await me.fvApi.EmActive(-1, 'FVSession');
}
resolve(true);
}
catch (e)
{
log('Exception during SetFocus=' + e);
resolve(false);
}
}
});
};
/** @memberof! FVSessions.Session.prototype
* @description Read from the active screen--will trim blanks from the text that is read--
* Note that for MsgAPI you need to await this call to get the right value
* @param {Integer} row Row to read from where 1 is the first row
* @param {Integer} column Column to read from where 1 is the first column
* @param {Integer} length Length to read--if row/column is entry field this is ignored
* @returns {String} Text from the screen at row, column for length
*/
FVSESS.GetScreenText = async function (row, column, length)
{
return this.fvApi.GetScnTextEx(row, column, length); // returns a promise
};
/** @memberof! FVSessions.Session.prototype
* @description Send a set of keys to the session, should end with Enter or Function key
* @param {String} transactions Transactions to run separated by the vertical bar (|) -- grammar for each transaction:
* <ul style=list-style:none;">
* <li>F^row^column=move cursor to location;</li>
* <li>H^enterKeys^waitForScreen= enterkeys that end with enter or function key and waitForScreen is a screen in the active application's definition file</li>
* <li>I^keystrokes= keystrokes are a mix of text and @T for tab and so on (default action if no I^ is present at start of the transaction)</li>
* <li>T^text^row^column=Enter text into an unprotected field at row and column where each starts with 1</li>
* <li>S^milliseconds=Sleep for the milliseconds like S^2000 for 2 second sleep</li>
* <li>W^milliseconds^waitForScreen=Sleep for the milliseconds like S^2000 for 2 second sleep but if screen comes in move on</li>
* </ul>
* Example: H^RMIS@E^RMIS|T^123456789^3^23|T^10081958^5^23|H^@E^RMIM will enter the transaction "RMIS" then wait for a screen identified as RMIS;
* then it will key "123456789" at a field at row 3 column 23; then a field "10081958" at row 5, column 23; then will send an ENTER and wait again for RMIS to appear
* @param {function(screenName)} onComplete Optional completion function for when the transactions are completed
* @param {boolean} bubble Set true for screen updates to be bubbled to the onload
*/
FVSESS.Transactions = function (transactions, onComplete, bubble)
{
this.fvApi.Transactions(transactions, onComplete, bubble);
};
/** @memberof! FVSessions.Session.prototype
* @description Set a field's value for MsgAPI use await to ensure synchronous operation
* @param {String} text Text to set into an unprotected entry field on the screen
* @param {integer} row Row to set the text on starting with 1
* @param {integer} column Column to set thet ext on starting with 1
* @returns {Boolean} Function succeeded (MsgAPI only)
*/
FVSESS.SetField = function (text, row, column)
{
var me = this;
return new Promise(async (resolve) =>
{
var ok=await me.fvApi.SetField(row, column, text);
resolve(ok);
});
};
};
/** @memberof! FVSessions.Session.prototype
* @description Internal use only function used to set functions when FVSessions.config.msgAPI is false
*/
FVSessions.SetLocalMethods = function ()
{
/** @memberof! FVSessions.Session.prototype
* @description Split keys so that hllapi enters and function keys break into individual objects --
* NOT SUPPORTED for MsgAPI=true
* @param {String} text Hllapi string with @ mnemonics (not [enter] style for now!)
* @returns {Object} Array of strings where each has keys ending with an AID (enter/function)
*/
FVSESS.SplitKeys = function (text)
{
try
{
var i, ch, parts = [], keys, start = 0, state = 0;
for (i = 0; i < text.length; i++)
{
ch = text.substr(i, 1);
switch (state)
{
case 0:
start = i;
state = 1;
// fall through
case 1:
if (ch == '@')
state = 2;
break;
case 2:
if (enterKeys.indexOf(ch) != -1)
{
parts.push(text.substr(start, (i - start) + 1));
state = 0;
}
else
state = 1;
break;
}
}
return parts;
}
catch (e)
{
log('SplitKeys exception=' + e);
return [text];
}
};
FVSESS.Close = function ()
{
if (this.status != 'offline')
{
try
{
this.fvApi.fvWin.CloseTerm();
}
catch (e) { }
}
};
FVSESS.SetFocus = function (focusOn, activate)
{
if (this.status != 'offline')
{
try
{
if (focusOn)
{
this.fvApi.fvWin.EmActive(2, 'FVSession');
if (activate)
this.fvApi.fvWin.SCSetTermFocus();
}
else
{
this.fvApi.fvWin.EmActive(-1, 'FVSession');
}
}
catch (e) { }
}
};
FVSESS.GetScreenText = async function (row, column, length)
{
return new Promise((resolve) =>
{
resolve(this.fvApi.GetScnTextEx(row, column, length));
});
};
FVSESS.Transactions = function (transactions, onComplete, bubble)
{
var me = this, lastScreen = this.screenName, timeoutHandle = null, atTran = 0, parts, tran, wait = false, waitingFor = '*', trans = transactions.split('|'),
topHasFocus = this.fvApi.fvWin.topHasFocus,
nextTran = function ()
{
atTran++;
if (timeoutHandle)
{
clearTimeout(timeoutHandle);
timeoutHandle = null;
}
if (atTran < trans.length)
{
if (trans[atTran] == '')
nextTran();
else
window.setTimeout(function () { innerExec() }, 1); // let current screen event complete!
}
else
{
fixFocus();
if (onComplete)
onComplete(lastScreen);
}
},
fixFocus = function ()
{
if (me.fvApi.fvWin.topHasFocus != topHasFocus)
me.fvApi.fvWin.EmActive((topHasFocus) ? 1 : 0, 'FVSess.Transactions');
//log('Transactions end topHasfocus=' + me.fvApi.fvWin.topHasFocus);
},
screenWaiter = function (rows, screenName)
{
//log(me.id + ' Transactions screenWaiter waitingFor=' + waitingFor + ' result screenName=' + screenName);
lastScreen = screenName;
if (waitingFor == '*') // any screen
nextTran();
else
{
if (screenName != waitingFor)
me.fvApi.fnNextScreen = screenWaiter;
else
nextTran();
}
return bubble; // determines if next screen is bubbled up
},
innerExec = function ()
{
tran = trans[atTran];
parts = (tran.indexOf('^') == -1) ? ['I', tran] : tran.split('^');
//log(me.id + ' ('+me.sessionKey+') Transactions innerExec atTran=' + atTran + ' trans.length=' + trans.length+' transaction=' + tran);
try
{
switch (parts[0])
{
case 'F': // move cursor to location
me.fvApi.SetCursor(parseInt(parts[1]), parseInt(parts[2]));
nextTran();
break;
case 'H': // send hllapi and wait for screen
waitingFor = parts[2];
//log(me.id + ' Transactions send and wait=' + parts[1] + ', ' + waitingFor);
me.fvApi.SendKeys(parts[1], screenWaiter);
timeoutHandle = window.setTimeout(function ()
{
// If we hit this a wait function went longer than 30 seconds
atTran = trans.length;
fixFocus();
if (onComplete)
onComplete(lastScreen, 'TIMED-OUT waiting for ' + waitingFor);
}, 30000);
break;
case 'W': // wait for screen or timeout
waitingFor = parts[2];
me.fvApi.fnNextScreen = screenWaiter;
timeoutHandle = window.setTimeout(function ()
{
// If we hit this a wait function went longer than wait point
nextTran();
}, parseInt(parts[1]));
break;
case 'I': // just perform keystrokes
waitingFor = '*';
//me.fvApi.SendKeys(parts[1], screenWaiter);
if (me.TypeKeys(parts[1], screenWaiter))
nextTran();
break;
case 'T': // Type text into row column
me.TypeAtRowCol(parts[1], parseInt(parts[2]), parseInt(parts[3]));
nextTran();
break;
case 'S':
window.setTimeout(function () { nextTran(); }, parseInt(parts[1]));
break;
default: // extra | maybe?
nextTran();
break;
}
}
catch (e)
{
log(me.id + ' Transactions innerExec exception=' + e);
}
}
bubble = (typeof (bubble) == 'undefined') ? false : bubble;
//log('Transactions start topHasfocus=' + this.fvApi.fvWin.topHasFocus);
innerExec();
};
/** @memberof! FVSessions.Session.prototype
* @description Type HLLAPI string starting at current row and column
* NOT SUPPORTED for MsgAPI=true
* @param {String} text Text to type into unprotected entry field(s) on the screen, can include @T for tab and end
* with @E or other AID string, which will be sent to the host for processing
* @param {function(screenRows,screenName)} screenWaiter Provides callback instead of onLoad
* @returns {boolean} Keys were typed OK
*/
FVSESS.TypeKeys = function (text, screenWaiter)
{
var me = this, i, ch, keys, state = 0,
ev, kev, em = me.fvApi.emSess,
fvWin = me.fvApi.fvWin,
SetEV = function (chr)
{
ev = {};
if (chr)
ev.keyCode = chr.charCodeAt(0);
kev = fvWin.SCKEV(em, -1, ev);
kev.apiCall = true;
};
try
{
for (i = 0; i < text.length; i++)
{
ch = text.substr(i, 1);
switch (state)
{
case 0:
if (ch == '@')
state = 1;
else
{
// type character
SetEV(ch);
fvWin.SCKeyPress(em, ev, kev);
}
break;
case 1:
if (enterKeys.indexOf(ch) != -1) // AID, end of this!
{
me.fvApi.SendKeys(text.substr(i - 1), screenWaiter);
return false;
}
else
{
state = 0; // assume single character
SetEV();
switch (ch)
{
case 'D':
fvWin.SCDelete(em, kev);
break;
case 'q':
fvWin.SCCursorEnd(em, kev);
break;
case '0':
fvWin.CursorHome(em, kev, true);
break;
case 'A':
state = 2;
break;
case 'C':
state = 3;
break;
case 'F': // FieldExit
fvWin.FieldExit(em, kev, 'NT');
break;
case 'T': // tab
fvWin.SCTab(em, ev, kev);
break;
case 'B':
fvWin.SCBackTab(em, ev, kev);
break;
case 'L':
fvWin.CursorLeft(em, kev);
break;
case 'U':
fvWin.CursorUp(em, kev);
break;
case 'Z':
fvWin.CursorRight(em, kev);
break;
case 'V':
fvWin.CursorDown(em, kev);
break;
default:
log('TypeKeys unknown HLLAPI Code-@' + ch);
break;
}
}
break;
case 2: // first char was 'A'
if (ch == 'E')
fvWin.FieldExit(em, kev, '+');
else
log('TypeKeys unknown HLLAPI Code-@A@' + ch);
state = 0;
break;
case 3: // first char was 'C'
if (ch == 'H')
fvWin.SCBackSp(em, kev);
else
log('TypeKeys unknown HLLAPI Code-@C@' + ch);
state = 0;
break;
}
}
}
catch (e)
{
log('TypeKeys exception=' + e);
}
return true;
};
/** @memberof! FVSessions.Session.prototype
* @description Type text starting at a row and column - if length of text exceeds first field will autoskip to next
* NOT SUPPORTED FOR MsgAPI=true
* @param {String} text Text to type into unprotected entry field(s) on the screen
* @param {integer} row Row to type the text on starting with 1
* @param {integer} column Column to type the text on starting with 1
*/
FVSESS.TypeAtRowCol = function (text, row, column)
{
var ev = {}, kev;
ev.keyCode = 600;
//log('TypeAtRowCol: "' + text + '" @' + row + ',' + column);
this.fvApi.SetCursor(row, column);
kev = this.fvApi.fvWin.SCKEV(this.fvApi.emSess, -1, ev);
kev.apiCall = true;
this.fvApi.fvWin.SCPaste(this.fvApi.emSess, kev, text);
};
FVSESS.SetField = function (text, row, column)
{
this.fvApi.SetField(row, column, text);
};
};
/** @memberof! FVSessions.Session.prototype
* @description Enter the active screen using a hllapi string
* @param {String} enterKeys Should be one or more keys with an enter/function/action key at the end like @E or @C ([enter] or [clear] or @T for Tabbing with ASCII host)
* @param {function(screenName)} onComplete Optional completion function for when the screen has been entered
*/
FVSESS.EnterScreen = function (enterKeys, onComplete)
{
this.fvApi.SendKeys(enterKeys, function (rows, screenName)
{
if (onComplete)
onComplete(screenName);
});
};
/** @memberof! FVSessions.Session.prototype
* @description Set the status of the Session
* @param {String} newStatus Status which includes offline, started (needs logon) and ready (not on any logon screens)
*/
FVSESS.SetStatus = function (newStatus)
{
this.status = newStatus;
switch (newStatus)
{
case 'offline':
this.SaveSessionKey();
break;
}
};
/** @memberof! FVSessions.Session.prototype
* @description Get the current session key from local storage
* @returns {String} Sessionkey or null if not found
*/
FVSESS.GetSessionKey = function ()
{
var sessionKey = localStorage.getItem(this.storeId);
log('GetSessionKey for ' + this.storeId + '=' + sessionKey);
return sessionKey;
};
/** @memberof! FVSessions.Session.prototype
* @description Save a sessionKey for this session to local storage
* @param {String} sessionKey SessionKey to save -- if null, the localstorage will be cleared
*/
FVSESS.SaveSessionKey = function (sessionKey)
{
if (!this.connection.keepAliveOnClose)
return; // only save sessionKey when keepAliveOnClose is true...
if (!sessionKey)
{
this.sessionKey = null;
log('SaveSessionKey deleted key for ' + this.storeId);
localStorage.removeItem(this.storeId);
}
else
{
log('SaveSessionKey saved ' + sessionKey + ' for ' + this.storeId);
this.sessionKey = sessionKey;
localStorage.setItem(this.storeId, sessionKey);
}
};
// #endregion Session Class
}());