(function(){ var jqScreen = $('#screen_problem'), languageCache = {}, // keyed by language identifier: processed data about languages translationCache = [], // keys are autogenerated in ta(), a value is a dictionary of translations of a translation key for every language langs, Nlangs, // constants, set on init chooseTranslation = function (keyword, lang, currentDict, enDict, translations) { var tr = currentDict[keyword], otherLang; if (tr) return tr; // if there is a translation in the current dictionary: return it tr = enDict[keyword]; if (tr) { // if there is a translation in the english dictionary: return it codeq.log.info('Translation for ' + keyword + ' not set for language ' + lang + ', using translation from en'); return tr; } for (otherLang in translations) { if (!translations.hasOwnProperty(otherLang)) continue; tr = (translations[otherLang] || {})[keyword]; if (tr) { // otherwise: return the first available translation in any language codeq.log.info('Translation for ' + keyword + ' not set for language ' + lang + ', using translation from ' + otherLang); return tr; } } return keyword + ' not set for language ' + lang; }, /** * convert the input translations (arg0) for given keys (arg1..argN) * so each keys holds all its translations for ever language */ convertTranslations = function () { var translations = arguments[0] || {}, result = {}, enDict = translations['en'] || {}, lang, dict, i, keyword, l; // initialize result: one lang-dict per keyword for (i = arguments.length - 1; i > 0; i--) result[arguments[i]] = {}; // convert translations: one keyword-dict per lang -> one lang-dict per keyword for (l = Nlangs - 1; l >= 0; l--) { lang = langs[l]; dict = translations[lang] || {}; for (i = arguments.length - 1; i > 0; i--) { keyword = arguments[i]; // result[keyword][lang] = dict[keyword] || keyword + ' not set for language ' + lang; result[keyword][lang] = chooseTranslation(keyword, lang, dict, enDict, translations); } } return result; }, /** * Connect the given translations of a key with the DOM, returning * the string of arguments to use with a HTML tag which will contain * a translation chosen from the given dictionary. */ ta = function (trObj) { // an object of the form: {'en': 'english content', 'sl': 'slovenska vsebina'} var result = ['data-dict="directory" data-tkey="', translationCache.length, '"'].join(''); translationCache.push(trObj); return result; }, /** * Assemble the display structure and translations from the server's * language.json for the given language identifier. */ createLanguageData = function (data, languageIdentifier) { // data is the content of language.json var li = languageIdentifier, // a shorthand groups = data.groups || {}, html = [], problemReferences = [], groupIdentifier, group, problems, problemIdentifier, problem; var langDict = convertTranslations(data.translations, 'name', 'description'), // this will be the resulting dictionary: multi-level keys that lead up to the lang-dict groupDict, problemDict; // title: HTML structure for "name" and "desc" html.push('


'); html.push('
'); // content: problem directory html.push(''); return { 'language': languageIdentifier, 'html': html.join(''), 'refs': problemReferences, 'hints': {} // TODO: prepare common hints for the language }; }, /** * Instantiates the screen from the given processed data. */ createDom = function (data) { var language = data.language; jqScreen.html(data.html); codeq.tr.translateDom(jqScreen); jqScreen.find('a').on('click', function () { var index = +$(this).attr('class').split(' ')[0].split('-')[1], ref = data.refs[index]; if (!ref) { codeq.log.error('Clicked on a problem link having erroneous index: ' + index); return; } // transition codeq.wait( codeq.comms.getProblem(language, ref.g, ref.p) .then(function (data) { if (data.code !== 0) throw new Error('Failed to obtain problem data, code: ' + data.code + ', message: ' + data.message); codeq.globalStateMachine.transition(language, data); }) ) .fail(function (reason) { codeq.log.error('Failed to obtain the problem definition: ' + reason, reason); alert('Failed to obtain the problem definition: ' + reason); }) .done(); }); }, currentLanguage; // the currently active language // ================================================================================ // Initialization, invoked from the boot sequence // ================================================================================ codeq.on('init', function () { codeq.tr.registerDictionary('directory', translationCache); langs = codeq.availableLangs; // cache for easier access Nlangs = langs.length; }); // ================================================================================ // Register with the state machine // ================================================================================ codeq.globalStateMachine.register('problem', { 'enter': function(language){ var data = null; // language data $('#navigation-login').css('display', ''); $('#navigation-language').css('display', ''); $("#navigation-problem").addClass("active").css('display', ''); if (!language) language = currentLanguage; // This happens when we hit this with the back button if (currentLanguage !== language) { jqScreen.empty(); currentLanguage = language; data = languageCache[language]; if (data) { createDom(data); } else { codeq.wait(codeq.comms.getLanguageDef(language).then(function (rawData) { var data = createLanguageData(rawData, language); languageCache[language] = data; createDom(data); })).done(); } } jqScreen.css('display', ''); }, 'exit' : function(){ jqScreen.css('display', 'none'); $('#navigation-login').css('display', 'none'); $('#navigation-language').css('display', 'none'); $('#navigation-problem').css('display', 'none').removeClass("active"); } }); })();