diff options
Diffstat (limited to 'js')
-rw-r--r-- | js/codeq/comms.js | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/js/codeq/comms.js b/js/codeq/comms.js index b04a2fc..140e48e 100644 --- a/js/codeq/comms.js +++ b/js/codeq/comms.js @@ -1,4 +1,8 @@ (function () { + // ================================================================================ + // Errors generated in this module + // ================================================================================ + var BinaryMessageError = function (message) { var e = new Error(message); this.message = message; @@ -22,6 +26,10 @@ MessageParseError.prototype = new Error(); MessageParseError.prototype.name = 'MessageParseError'; + // ================================================================================ + // engine.io communication support functions (long polling / websocket communication) + // ================================================================================ + var currentTID = 0, // transaction ID of the next message sid = null, // session ID, changes after each successful initial login socket = null, @@ -152,6 +160,57 @@ } }; + // ================================================================================ + // AJAX communication support functions (loading of static web resources) + // ================================================================================ + + var languageCache = {},// language defs, keyed by language identifier + problemCache = {},// problem cache, 3-level, keyed by: language, problem group, and problem identifier + ajaxGet = function (url) { + return Q.Promise(function (resolve, reject, notify) { + $.ajax({ + dataType: 'application/json', + type: 'GET', + url: url, + error: function (jqXHR, textStatus, errorThrown) { + codeq.log.error('AJAX to ' + url + ' failed with status ' + textStatus, errorThrown); + reject(errorThrown || new Error(textStatus)); + }, + success: function (data, textStatus, jqXHR) { + var s; + if ((typeof data === 'object') && (data !== null)) { + // got a JSON + resolve(data); + } + else { + s = 'AJAX to ' + url + ' did not result in a JSON object'; + if (typeof data === 'string') { + s += ', the response was:\n' + data; + } + else if (typeof textStatus === 'string') { + s += ', status was: ' + textStatus; + } + codeq.log.error(s); + reject(new Error(s)); + } + } + }); + }); + }, + ajaxPrefix; + + ajaxPrefix = location.pathname; + if (!ajaxPrefix) ajaxPrefix = '/'; + else if (ajaxPrefix[ajaxPrefix.length - 1] !== '/') { + ajaxPrefix = ajaxPrefix.split('/'); + ajaxPrefix[ajaxPrefix.length - 1] = ''; + ajaxPrefix = ajaxPrefix.join('/'); + } + + // ================================================================================ + // This module's API methods + // ================================================================================ + codeq.comms = { 'connect': function () { var deferred = Q.defer(); @@ -320,6 +379,33 @@ } } } + }, + + 'getLanguageDef': function (identifier) { + var x = languageCache[identifier]; + if ((typeof x === 'object') && (x !== null)) { + // already defined + if (typeof x.then === 'function') { + // it's a promise, it means it's not resolved yet + return x; + } + else { + // return a resolved promise with the cached value + return Q(x); + } + } + x = ajaxGet(ajaxPrefix + identifier + '/language.json').then( + function getLanguageDefSuccess(data) { + languageCache[identifier] = data; + return data; // proxy further + }, + function getLanguageDefFail(exception) { + delete languageCache[identifier]; + throw exception || new Error('Could not load language ' + identifer); // proxy further + } + ); + languageCache[identifier] = x; + return x; } }; })(); |