quizzer
Version:
Quizzer is a webserver for collaborative writing lab support. Based on a _fail early, fail often? approach to written language, the tool is particularly suited to second-language learners. The workflow (essay - error - quiz - exam) treats mistakes as an o
226 lines (216 loc) • 7.44 kB
JavaScript
var i18nStrings = {};
function i18n (node) {
if (!node) {
node = document;
}
var data = {
value:[],
content:[]
};
var nodes = node.getElementsByClassName('i18n');
for (var i=0,ilen=nodes.length;i<ilen;i++) {
var node = nodes[i];
var nodeName = node.getAttribute('name');
if (nodeName) {
var m = nodeName.match(/^(value|content)-(.*)$/);
if (m) {
data[m[1]].push({
node:node,
string:m[2]
})
i18nStrings[m[2]] = "undefined";
}
}
}
// Send strings to server in a batch
var adminID = getParameterByName('admin');
var roleName = 'admin';
var studentID,studentKey,classID;
// Try for a commenter
if (!adminID) {
adminID = getParameterByName('commenter');
roleName = 'commenter'
}
// Try for a student
if (!adminID) {
studentID = getParameterByName('studentid');
studentKey = getParameterByName('studentkey');
classID = getParameterByName('classid');
}
var roleAndID;
if (adminID) {
roleAndID = roleName + '=' + adminID + '&';
} else if (studentID && studentKey) {
roleAndID = 'studentid=' + studentID + '&studentkey=' + studentKey + '&classid=' + classID + '&';
} else {
// Give up
roleAndID = '';
}
i18nStrings = apiRequest(
'/?' + roleAndID
+ 'page=i18n'
, {
strings:i18nStrings
}
);
if (false === i18nStrings) return;
// Perform substitutions
for (var i=0,ilen=data.value.length;i<ilen;i++) {
data.value[i].node.setAttribute('value',i18nStrings[data.value[i].string]);
}
for (var i=0,ilen=data.content.length;i<ilen;i++) {
data.content[i].node.innerHTML = i18nStrings[data.content[i].string];
}
}
function getParameterByName(name) {
var match = RegExp('[?&]' + name + '=([^&]*)').exec(window.location.search);
return match && decodeURIComponent(match[1].replace(/\+/g, ' '));
}
function fixPath (path) {
var match = RegExp('https?://[^/]*/(.*?)([?#]|$)').exec(window.location.href);
// If a stub exists, assume secure operation, so:
var stub = match && match[1];
if (stub) {
// (1) remove &admin= value from URL
path = path.replace(/(\?)(?:admin=[^&]*)*(.*?)(?:&admin=[^&]*)*/,'$1$2');
// (2) if URL begins with '/?', append stub to '/'
path = path.replace(/^(\/)(\?)/, '$1' + stub + '$2');
// (3) remove any port designation from URL
path = path.replace(/(https?:\/\/[^\/]*):[0-9]+/, '$1');
// (4) if URL carries a commenter key, address to staff.html
if (path.match(/commenter=/)) {
path = path.replace('admin.html', 'staff.html');
}
}
return path;
}
function apiRequest (url, obj, returnAsString) {
url = fixPath(url);
if ("object" === typeof obj) {
obj = JSON.stringify(obj);
} else if (!obj) {
obj = null;
}
var xhr = new XMLHttpRequest();
xhr.open('POST', url, false);
xhr.setRequestHeader("Content-type","application/json");
xhr.send(obj);
if (xhr.getResponseHeader('content-type') === 'text/html') {
document = xhr.responseXML;
}
if (200 != xhr.status) {
return false;
}
var ret = xhr.responseText;
if (!returnAsString) {
ret = JSON.parse(ret);
}
return ret;
}
function markdown (txt) {
if (!txt) return '<p> </p>';
txt = txt.replace(/(:-?\))/g,'(\u0298\u203f\u0298)');
txt = txt.replace(/(:-\/)/g,'_(\u0361\u0e4f\u032f\u0361\u0e4f)_');
txt = txt.replace(/^>>>\s+(.*)/,'__Rule\u21b4__\n\n>>> $1');
txt = txt.replace(/^>>\s+(.*)/,'__Pattern\u21b4__\n\n>> $1');
txt = txt.replace(/^>\s+(.*)/,'__Explanation\u21b4__\n\n> $1');
txt = txt.replace(/\(\(([a-zA-Z1-9])\s+(.*?)\)\)/g, '<span class="quizzer-highlight">(($1)) $2</span>');
txt = txt.replace(/\(\(([a-zA-Z1-9])\)\)/g, function (aChar) {
var c, val, offset;
if (aChar[2].match(/[a-z]/)) {
val = (aChar.charCodeAt(2) - 97)
offset = 9424;
} else if (aChar[2].match(/[A-Z]/)) {
val = (aChar.charCodeAt(2) - 65)
offset = 9398;
} else {
val = (aChar.charCodeAt(2) - 49)
offset = 9312;
}
return String.fromCharCode(val + offset);
});
return marked.parse(txt);
}
function confirmDelete (node,callbackName,message) {
if (!message) {
message = "delete-query";
}
var origValue,origEvent;
if (node.value) {
origValue = node.value;
node.value= i18nStrings[message];
} else {
origValue = node.innerHTML;
node.innerHTML = i18nStrings[message];
}
var origEvent = '' + node.getAttribute('onclick');
var origStyle = node.parentNode.style;
node.style.color = 'red';
node.setAttribute('onclick', callbackName + '(this)');
setTimeout(function() {
if (node.value) {
node.value = origValue;
} else {
node.innerHTML = origValue;
}
node.style = origStyle;
node.setAttribute('onclick',origEvent);
},2000);
}
function getLanguages (ruleGroupID) {
var groupid;
if (ruleGroupID) {
groupid = '&groupid=' + ruleGroupID
} else {
groupid = '';
}
var adminID = getParameterByName('admin');
var languages = apiRequest(
'/?admin='
+ adminID
+ '&page=students'
+ '&cmd=getlanguages'
+ groupid
);
if (false === languages) return [];
return languages;
};
function installLanguages (clickable) {
var languages;
if (clickable) {
var ruleGroupID = getParameterByName('groupid');
languages = getLanguages(ruleGroupID);
} else {
var languages = getLanguages();
}
var languagesNode = document.getElementById('languages');
for (var i=0,ilen=languagesNode.childNodes.length;i<ilen;i+=1) {
languagesNode.removeChild(languagesNode.childNodes[0]);
}
for (var i=0,ilen=languages.length;i<ilen;i+=1) {
var language = languages[i];
var languageNode = document.createElement('span');
if (!clickable) {
languageNode.setAttribute("draggable",'true');
languageNode.setAttribute('ondragstart', 'dragLang(event)');
} else {
// Check each language for completeness
// complete: green background + clickable
// partial: yellow background + clickable
// empty: no background, not clickable
if (language.completeness) {
languageNode.setAttribute("onclick", "downloadRules('" + language.lang + "','" + language.langName + "')");
if (language.completeness === 2) {
languageNode.classList.add("complete");
} else if (language.completeness === 1) {
languageNode.classList.add("partial");
}
}
}
languageNode.id = language.lang;
languageNode.innerHTML = language.langName;
languagesNode.appendChild(languageNode);
var space = document.createTextNode(' ');
languagesNode.appendChild(space);
}
};