openct-tasks/_common/modules/integrationAPI.01/official/task-pr.js

255 lines
8.6 KiB
JavaScript

(function () {
'use strict';
/*
* Same domain task proxy implementation for Bebras task API - v1.0 - 08/2014
*
* Depends on jQuery.
*
*/
var functionsToTrigger = {load: true, unload:true, reloadAnswer:true, showViews: true, reloadState: true};
function taskCaller(task, request, content, error) {
if (!error) {
error = function() {};
}
// TODO: handle case where iframe_loaded is false and caller expects a result...
if (!task.iframe_loaded) {
setTimeout(function() {
taskCaller(task, request, content);
}, 100);
} else {
if (task.distantTask && typeof task.distantTask[request] === 'function') {
if (typeof content === 'string' || (typeof content === 'object' && Object.prototype.toString.call(content) !== '[object Array]')) {
content = [content];
}
var askedCallbackIdx = (typeof content[content.length - 2] === 'function') ? content.length - 2 : content.length - 1;
if (typeof content[askedCallbackIdx] !== 'function') {
error('calls to task must contain a callback');
return;
}
var oldCallback = content[askedCallbackIdx];
var timeout = window.setTimeout(function() {
error('timeout reached for '+request);
}, 15000);
var newCallback = function() {
window.clearTimeout(timeout);
if (functionsToTrigger[request]) {
task.distantPlatform.trigger(request, content);
}
oldCallback(arguments[0], arguments[1], arguments[3]);
};
content[askedCallbackIdx] = newCallback;
if (typeof window.taskPrNoCatch !== 'undefined') {
task.distantTask[request].apply(task.distantTask, content);
} else {
try {
task.distantTask[request].apply(task.distantTask, content);
} catch (e) {
window.clearTimeout(timeout);
error(e);
}
}
} else if (task.distantTask) {
error("Task "+task.Id+" doesn't implement "+request);
} else {
error('call to '+request+' on task with no distant task');
}
}
}
/*
* Task object, created from an iframe DOM element
*/
function Task(iframe, callback) {
this.iframe = iframe;
this.iframe_loaded = false;
this.distantTask = null;
this.Id = iframe.attr('id');
this.elementsLoaded = false;
this.platform = null;
var that = this;
this.setPlatform = function(platform) {
this.platform = platform;
if (this.iframe_loaded) {
this.distantPlatform.setPlatform(platform);
}
};
this.iframeLoaded = function() {
if (that.iframe_loaded) {
return;
}
that.iframe_loaded = true;
that.distantTask = that.iframe[0].contentWindow.task;
that.distantPlatform = that.iframe[0].contentWindow.platform;
that.iframe[0].contentWindow.platform.parentLoadedFlag = true;
if (that.platform) {
that.distantPlatform.setPlatform(that.platform);
}
callback();
};
// checking if platform is already available
var iframeDoc = that.iframe[0].contentDocument || that.iframe[0].contentWindow.document;
if (iframeDoc && iframeDoc.readyState == 'complete' && that.iframe[0].contentWindow.platform && !that.iframe[0].contentWindow.platform.parentLoadedFlag) {
that.iframe[0].contentWindow.platform.initCallback(that.iframeLoaded);
} else {
if(document.addEventListener) { // ie > 8
$(that.iframe).on("load", function() {
that.iframe[0].contentWindow.platform.initCallback(that.iframeLoaded);
});
} else {
setTimeout(function() {
that.iframeLoaded();
}, 100);
}
}
}
Task.prototype.getSourceId = function() {
return this.Id;
};
Task.prototype.getTargetUrl = function() {
return this.iframe.attr('src');
};
Task.prototype.getTarget = function() {
return this.iframe[0].contentWindow;
};
Task.prototype.getDomain = function() {
var url = this.getTargetUrl();
return url.substr(0, url.indexOf('/', 7));
};
/**
* Task API functions
*/
Task.prototype.load = function(views, success, error) {
return taskCaller(this, 'load', [views, success, error], error);
};
Task.prototype.unload = function(success, error) {
return taskCaller(this, 'unload', [success, error], error);
};
Task.prototype.getHeight = function(success, error) {
return taskCaller(this, 'getHeight', [success, error], error);
};
Task.prototype.updateToken = function(token, success, error) {
return taskCaller(this, 'updateToken', [token, success, error], error);
};
Task.prototype.getAnswer = function(success, error) {
return taskCaller(this, 'getAnswer', [success, error], error);
};
Task.prototype.reloadAnswer = function(answer, success, error) {
return taskCaller(this, 'reloadAnswer', [answer, success, error], error);
};
Task.prototype.getState = function(success, error) {
return taskCaller(this, 'getState', [success, error], error);
};
Task.prototype.reloadState = function(state, success, error) {
return taskCaller(this, 'reloadState', [state, success, error], error);
};
Task.prototype.getViews = function(success, error) {
return taskCaller(this, 'getViews', [success, error], error);
};
Task.prototype.getMetaData = function(success, error) {
return taskCaller(this, 'getMetaData', [success, error], error);
};
Task.prototype.showViews = function(views, success, error) {
return taskCaller(this, 'showViews', [views, success, error], error);
};
// TODO: put error back in argument list, for this 2015 tasks must be changed
Task.prototype.gradeAnswer = function(answer, answerToken, success, error) {
return taskCaller(this, 'gradeAnswer', [answer, answerToken, success], error);
};
Task.prototype.getResources = function(success, error) {
return taskCaller(this, 'getResources', [success, error], error);
};
// for grader.gradeTask
// TODO: put error back in argument list, for this 2015 tasks must be changed
Task.prototype.gradeTask = function(answer, answerToken, success, error) {
return taskCaller(this, 'gradeTask', [answer, answerToken, success], error);
};
window.TaskProxyManager = {
tasks: {},
platforms: {},
getTaskProxy: function(idFrame, callback, force) {
if (!force && TaskProxyManager.tasks[idFrame]) {
callback(TaskProxyManager.tasks[idFrame]);
} else {
if (force) {
TaskProxyManager.deleteTaskProxy(idFrame);
}
$('#'+idFrame).each(function() {
TaskProxyManager.tasks[idFrame] = new Task($(this), function() {setTimeout(function() {
if (idFrame in TaskProxyManager.platforms) {
TaskProxyManager.tasks[idFrame].setPlatform(TaskProxyManager.platforms[idFrame]);
}
callback(TaskProxyManager.tasks[idFrame]);
});});
});
}
},
setPlatform: function(task, platform) {
TaskProxyManager.platforms[task.Id] = platform;
TaskProxyManager.tasks[task.Id].setPlatform(platform);
},
deleteTaskProxy: function(idFrame) {
delete(TaskProxyManager.tasks[idFrame]);
delete(TaskProxyManager.platforms[idFrame]);
},
getUrl: function(taskUrl, sToken, sPlatform, prefix) {
return taskUrl+'?sToken='+encodeURIComponent(sToken)+'&sPlatform='+encodeURIComponent(sPlatform);
}
};
window.TaskProxyManager.getGraderProxy = TaskProxyManager.getTaskProxy;
}());
/*
* Platform object definition, created from a Task object (see below)
*/
function Platform(task) {
this.task = task;
}
Platform.prototype.getTask = function() {
return this.task;
};
/*
* Simple prototypes for platform API functions, to be overriden by your
* platform's specific functions (for each platform object)
*/
Platform.prototype.validate = function(mode) {};
Platform.prototype.showView = function(views) {};
Platform.prototype.askHint = function(platformToken) {};
Platform.prototype.updateHeight = function(height) { this.updateDisplay({height: height}); }; // Legacy
Platform.prototype.updateDisplay = function(data) {
if(data.height) {
this.task.iframe.height(parseInt(height)+40);
}
};
Platform.prototype.getTaskParams = function(key, defaultValue, success, error) {
var res = {minScore: -3, maxScore: 10, randomSeed: 0, noScore: 0, readOnly: false, options: {}};
if (key) {
if (key !== 'options' && key in res) {
res = res[key];
} else if (res.options && key in res.options) {
res = res.options[key];
} else {
res = (typeof defaultValue !== 'undefined') ? defaultValue : null;
}
}
success(res);
};
Platform.prototype.openUrl = function(url) {
// TODO
};