Replaced loadResource() with the more streamlined getResource(), for all your resource-getting needs (well, except for binary files, which should be coming soon)

This commit is contained in:
Jeff Parsons 2016-02-21 15:51:54 -08:00
commit f032f95611
26 changed files with 3881 additions and 3777 deletions

View file

@ -58,7 +58,7 @@ var cAsyncMachines = 0;
/**
* loadXML(sFile, idMachine, sParms, fResolve, display, done)
*
* This is the preferred way to load all XML and XSL files. It uses loadResource()
* This is the preferred way to load all XML and XSL files. It uses getResource()
* to load them as strings, which parseXML() can massage before parsing/transforming them.
*
* For example, since I've been unable to get the XSLT document() function to work inside any
@ -97,7 +97,7 @@ function loadXML(sXMLFile, idMachine, sParms, fResolve, display, done)
parseXML(sXML, sXMLFile, idMachine, sParms, fResolve, display, done);
};
display("Loading " + sXMLFile + "...");
web.loadResource(sXMLFile, fAsync, null, null, doneLoadXML);
web.getResource(sXMLFile, null, fAsync, doneLoadXML);
}
/**
@ -177,7 +177,7 @@ function parseXML(sXML, sXMLFile, idMachine, sParms, fResolve, display, done)
* Supposedly, the IE XML DOM parser will throw an exception, but I haven't tested that, and unless all other
* browsers do that, that's not helpful.
*
* The best I can do at this stage (assuming web.loadResource() didn't drop any error information on the floor)
* The best I can do at this stage (assuming web.getResource() didn't drop any error information on the floor)
* is verify that the requested resource "looks like" valid XML (in other words, it begins with a '<').
*/
var xmlDoc = null;
@ -308,7 +308,7 @@ function resolveXML(sXML, display, done)
};
display("Loading " + sRefFile + "...");
web.loadResource(sRefFile, fAsync, null, null, doneReadXML);
web.getResource(sRefFile, null, fAsync, doneReadXML);
return;
}
done(sXML, null);

View file

@ -325,35 +325,29 @@ net.downloadFile = function(sURL, sFile, done)
};
/**
* loadResource(sURL, fAsync, data, componentNotify, fnNotify, pNotify)
* getResource(sURL, dataPost, fAsync, done)
*
* Request the specified resource (sURL), and once the request is complete,
* optionally call the specified method (fnNotify) of the specified component (componentNotify).
*
* TODO: Figure out how we can strongly type the fnNotify parameter, because the Closure Compiler has issues with:
*
* {function(this:Component, string, (string|null), number, (number|string|null|Object|Array|undefined))} [fnNotify]
*
* NOTE: This function is a mirror image of the weblib version, for server-side component testing within Node;
* since it is NOT intended for production use, it may make liberal use of synchronous functions, warning messages, etc.
* Request the specified resource (sURL), and once the request is complete, notify done().
*
* @param {string} sURL
* @param {Object|null} [dataPost] for a POST request (default is a GET request)
* @param {boolean} [fAsync] is true for an asynchronous request
* @param {Object|null} [data] for a POST request (default is a GET request)
* @param {Component} [componentNotify]
* @param {function(...)} [fnNotify]
* @param {number|string|null|Object|Array} [pNotify] optional fnNotify parameter
* @return {Array} containing errorCode and responseText (empty array if async request)
* @param {function(string,string,number)} [done]
* @return {Array|null} Array containing [sResource, nErrorCode], or null if no response yet
*/
net.loadResource = function(sURL, fAsync, data, componentNotify, fnNotify, pNotify) {
var nErrorCode = -1;
var sResponse = null;
net.getResource = function(sURL, dataPost, fAsync, done)
{
var nErrorCode = -1, sResource = null, response = null;
if (net.isRemote(sURL)) {
console.log('net.loadResource("' + sURL + '"): unimplemented');
console.log('net.getResource("' + sURL + '"): unimplemented');
} else {
if (!sServerRoot) {
sServerRoot = path.join(path.dirname(fs.realpathSync(__filename)), "../../../");
}
/*
* TODO: Revisit why we pass back sBaseName instead of the original sURL....
*/
var sBaseName = str.getBaseName(sURL);
var sFile = path.join(sServerRoot, sURL);
if (fAsync) {
@ -362,21 +356,14 @@ net.loadResource = function(sURL, fAsync, data, componentNotify, fnNotify, pNoti
* TODO: If err is set, is there an error code we should return (instead of -1)?
*/
if (!err) {
sResponse = s;
sResource = s;
nErrorCode = 0;
}
if (fnNotify) {
if (!componentNotify) {
fnNotify(sBaseName, sResponse, nErrorCode, pNotify);
} else {
fnNotify.call(componentNotify, sBaseName, sResponse, nErrorCode, pNotify);
}
}
if (done) done(sBaseName, sResource, nErrorCode);
});
return [];
} else {
try {
sResponse = fs.readFileSync(sFile, {encoding: "utf8"});
sResource = fs.readFileSync(sFile, {encoding: "utf8"});
nErrorCode = 0;
} catch(err) {
/*
@ -384,16 +371,11 @@ net.loadResource = function(sURL, fAsync, data, componentNotify, fnNotify, pNoti
*/
console.log(err.message);
}
if (fnNotify) {
if (!componentNotify) {
fnNotify(sBaseName, sResponse, nErrorCode, pNotify);
} else {
fnNotify.call(componentNotify, sBaseName, sResponse, nErrorCode, pNotify);
}
}
if (done) done(sBaseName, sResource, nErrorCode);
response = [sResource, nErrorCode];
}
}
return [nErrorCode, sResponse];
return response;
};
if (NODE) module.exports = net;

View file

@ -44,7 +44,7 @@ if (NODE) {
* savePC(idMachine, sPCJSFile)
*
* @param {string} idMachine
* @param {string} [sPCJSFile]
* @param {string} sPCJSFile
* @return {boolean} true if successful, false if error
*/
function savePC(idMachine, sPCJSFile)
@ -61,7 +61,9 @@ function savePC(idMachine, sPCJSFile)
sPCJSFile = "/versions/pcjs/" + (XMLVERSION || APPVERSION) + "/pc" + (dbg? "-dbg" : "") + ".js";
}
}
web.loadResource(sPCJSFile, true, null, null, downloadCSS, [idMachine, str.getBaseName(sPCJSFile, true), sParms, sState]);
web.getResource(sPCJSFile, null, true, function(sURL, sResponse, nErrorCode) {
downloadCSS(sURL, sResponse, nErrorCode, [idMachine, str.getBaseName(sPCJSFile, true), sParms, sState]);
});
return true;
}
web.alertUser("Unable to identify machine '" + idMachine + "'");
@ -94,7 +96,9 @@ function downloadCSS(sURL, sPCJS, nErrorCode, aMachineInfo)
*/
downloadPC(sURL, null, 0, aMachineInfo);
} else {
web.loadResource(sCSSFile, true, null, null, downloadPC, aMachineInfo);
web.getResource(sCSSFile, null, true, function(sURL, sResponse, nErrorCode) {
downloadPC(sURL, sResponse, nErrorCode, aMachineInfo);
});
}
return;
}

View file

@ -171,37 +171,23 @@ web.notice = function(s, fPrintOnly, id)
};
/**
* loadResource(sURL, fAsync, data, componentNotify, fnNotify, pNotify)
* getResource(sURL, dataPost, fAsync, done)
*
* Request the specified resource (sURL), and once the request is complete,
* optionally call the specified method (fnNotify) of the specified component (componentNotify).
*
* TODO: Figure out how we can strongly type the fnNotify parameter, because the Closure Compiler has issues with:
*
* {function(this:Component, string, (string|null), number, (number|string|null|Object|Array|undefined))} [fnNotify]
* Request the specified resource (sURL), and once the request is complete, notify done().
*
* @param {string} sURL
* @param {Object|null} [dataPost] for a POST request (default is a GET request)
* @param {boolean} [fAsync] is true for an asynchronous request
* @param {Object} [data] for a POST request (default is a GET request)
* @param {Component} [componentNotify]
* @param {function(...)} [fnNotify]
* @param {number|string|null|Object|Array} [pNotify] optional fnNotify info parameter
* @return {Array} containing errorCode and responseText (empty array if fAsync is true)
* @param {function(string,string,number)} [done]
* @return {Array|null} Array containing [sResource, nErrorCode], or null if no response yet
*/
web.loadResource = function(sURL, fAsync, data, componentNotify, fnNotify, pNotify)
web.getResource = function(sURL, dataPost, fAsync, done)
{
var nErrorCode = 0;
var sURLData = null;
var nErrorCode = 0, sResource = null, response = null;
if (typeof resources == 'object' && (sURLData = resources[sURL])) {
if (fnNotify) {
if (!componentNotify) {
fnNotify(sURL, sURLData, nErrorCode, pNotify);
} else {
fnNotify.call(componentNotify, sURL, sURLData, nErrorCode, pNotify);
}
}
return [nErrorCode, sURLData];
if (typeof resources == 'object' && (sResource = resources[sURL])) {
if (done) done(sURL, sResource, nErrorCode);
return [sResource, nErrorCode];
}
if (NODE) {
@ -212,7 +198,7 @@ web.loadResource = function(sURL, fAsync, data, componentNotify, fnNotify, pNoti
* if (!Component) Component = require("./component");
*/
var net = require("./netlib");
return net.loadResource(sURL, fAsync, data, componentNotify, fnNotify, pNotify);
return net.getResource(sURL, dataPost, fAsync, done);
}
var xmlHTTP = (window.XMLHttpRequest? new window.XMLHttpRequest() : new window.ActiveXObject("Microsoft.XMLHTTP"));
@ -228,64 +214,52 @@ web.loadResource = function(sURL, fAsync, data, componentNotify, fnNotify, pNoti
*
* xmlHTTP.onreadystatechange = undefined;
*/
sURLData = xmlHTTP.responseText;
sResource = xmlHTTP.responseText;
/*
* The normal "success" case is an HTTP status code of 200, but when testing with files loaded
* from the local file system (ie, when using the "file:" protocol), we have to be a bit more "flexible".
*/
if (xmlHTTP.status == 200 || !xmlHTTP.status && sURLData.length && web.getHostProtocol() == "file:") {
if (MAXDEBUG) web.log("xmlHTTP.onreadystatechange(" + sURL + "): returned " + sURLData.length + " bytes");
if (xmlHTTP.status == 200 || !xmlHTTP.status && sResource.length && web.getHostProtocol() == "file:") {
if (MAXDEBUG) web.log("xmlHTTP.onreadystatechange(" + sURL + "): returned " + sResource.length + " bytes");
}
else {
nErrorCode = xmlHTTP.status || -1;
web.log("xmlHTTP.onreadystatechange(" + sURL + "): error code " + nErrorCode);
}
if (fnNotify) {
if (!componentNotify) {
fnNotify(sURL, sURLData, nErrorCode, pNotify);
} else {
fnNotify.call(componentNotify, sURL, sURLData, nErrorCode, pNotify);
}
}
if (done) done(sURL, sResource, nErrorCode);
}
};
}
if (data) {
var sData = "";
for (var p in data) {
if (!data.hasOwnProperty(p)) continue;
if (sData) sData += "&";
sData += p + '=' + encodeURIComponent(data[p]);
if (dataPost) {
var sDataPost = "";
for (var p in dataPost) {
if (!dataPost.hasOwnProperty(p)) continue;
if (sDataPost) sDataPost += "&";
sDataPost += p + '=' + encodeURIComponent(dataPost[p]);
}
sData = sData.replace(/%20/g, '+');
if (MAXDEBUG) web.log("web.loadResource(POST " + sURL + "): " + sData.length + " bytes");
sDataPost = sDataPost.replace(/%20/g, '+');
if (MAXDEBUG) web.log("web.getResource(POST " + sURL + "): " + sDataPost.length + " bytes");
xmlHTTP.open("POST", sURL, !!fAsync); // ensure that fAsync is a valid boolean (Internet Explorer xmlHTTP functions insist on it)
xmlHTTP.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xmlHTTP.send(sData);
xmlHTTP.send(sDataPost);
} else {
if (MAXDEBUG) web.log("web.loadResource(GET " + sURL + ")");
if (MAXDEBUG) web.log("web.getResource(GET " + sURL + ")");
xmlHTTP.open("GET", sURL, !!fAsync); // ensure that fAsync is a valid boolean (Internet Explorer xmlHTTP functions insist on it)
xmlHTTP.send();
}
var response = [];
if (!fAsync) {
sURLData = xmlHTTP.responseText;
sResource = xmlHTTP.responseText;
if (xmlHTTP.status == 200) {
if (MAXDEBUG) web.log("web.loadResource(" + sURL + "): returned " + sURLData.length + " bytes");
response = sResource;
if (MAXDEBUG) web.log("web.getResource(" + sURL + "): returned " + sResource.length + " bytes");
} else {
nErrorCode = xmlHTTP.status || -1;
web.log("web.loadResource(" + sURL + "): error code " + nErrorCode);
response = nErrorCode = xmlHTTP.status || -1;
web.log("web.getResource(" + sURL + "): error code " + nErrorCode);
}
if (fnNotify) {
if (!componentNotify) {
fnNotify(sURL, sURLData, nErrorCode, pNotify);
} else {
fnNotify.call(componentNotify, sURL, sURLData, nErrorCode, pNotify);
}
}
response = [nErrorCode, sURLData];
if (done) done(sURL, sResource, nErrorCode);
response = [sResource, nErrorCode];
}
return response;
};
@ -305,15 +279,15 @@ web.loadResource = function(sURL, fAsync, data, componentNotify, fnNotify, pNoti
*/
web.sendReport = function(sApp, sVer, sURL, sUser, sType, sReport, sHostName)
{
var data = {};
data[ReportAPI.QUERY.APP] = sApp;
data[ReportAPI.QUERY.VER] = sVer;
data[ReportAPI.QUERY.URL] = sURL;
data[ReportAPI.QUERY.USER] = sUser;
data[ReportAPI.QUERY.TYPE] = sType;
data[ReportAPI.QUERY.DATA] = sReport;
var dataPost = {};
dataPost[ReportAPI.QUERY.APP] = sApp;
dataPost[ReportAPI.QUERY.VER] = sVer;
dataPost[ReportAPI.QUERY.URL] = sURL;
dataPost[ReportAPI.QUERY.USER] = sUser;
dataPost[ReportAPI.QUERY.TYPE] = sType;
dataPost[ReportAPI.QUERY.DATA] = sReport;
var sReportURL = (sHostName? sHostName : "http://" + SITEHOST) + ReportAPI.ENDPOINT;
web.loadResource(sReportURL, true, data);
web.getResource(sReportURL, dataPost, true);
};
/**
@ -596,7 +570,7 @@ web.isMobile = function()
web.getURLParameters = function(sParms)
{
var aParms = {};
if (window) { // an alternative to "if (typeof module === 'undefined')" if require("defines") has been invoked
if (window) { // an alternative to "if (typeof module === 'undefined')" if require("defines") was used
if (!sParms) {
/*
* Note that window.location.href returns the entire URL, whereas window.location.search
@ -605,7 +579,7 @@ web.getURLParameters = function(sParms)
sParms = window.location.search.substr(1);
}
var match;
var pl = /\+/g; // RegExp for replacing addition symbol with a space
var pl = /\+/g; // RegExp for replacing addition symbol with a space
var search = /([^&=]+)=?([^&]*)/g;
var decode = function(s) { return decodeURIComponent(s.replace(pl, " ")); };
@ -616,6 +590,45 @@ web.getURLParameters = function(sParms)
return aParms;
};
/**
* downloadJSON()
*
* @param {string} sJSON
* @param {string} [sFileName]
*/
web.downloadJSON = function(sJSON, sFileName)
{
var link, sAlert;
var fDownload = !!sFileName;
var sURI = "data:application/json,";
if (!web.isUserAgent("Firefox")) {
fDownload = false;
sURI += encodeURI(sJSON);
} else {
sURI += encodeURIComponent(sJSON);
if (fDownload) {
link = document.createElement('a');
if (typeof link.download != 'string') fDownload = false;
}
}
if (fDownload) {
link.href = sURI;
link.download = sFileName;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
sAlert = 'Check your Downloads folder for "' + sFileName + '".';
} else {
window.open(sURI);
sAlert = 'Check your browser for a new window/tab containing the requested data.';
}
web.alertUser(sAlert);
};
/**
* onCountRepeat(n, fn, fnComplete, msDelay)
*