UNPKG

nodegame-widgets

Version:

Collections of useful and reusable javascript / HTML snippets for nodeGame

440 lines (383 loc) 14.7 kB
/** * # LanguageSelector * Copyright(c) 2017 Stefano Balietti <ste@nodegame.org> * MIT Licensed * * Manages and displays information about languages available and selected * * @TODO: bubble event in case of buttons (now there are many listeners). * * www.nodegame.org */ (function(node) { "use strict"; node.widgets.register('LanguageSelector', LanguageSelector); // ## Meta-data LanguageSelector.version = '0.6.2'; LanguageSelector.description = 'Display information about the current ' + 'language and allows to change language.'; LanguageSelector.title = 'Language'; LanguageSelector.className = 'languageselector'; LanguageSelector.texts.loading = 'Loading language information...'; // ## Dependencies LanguageSelector.dependencies = { JSUS: {} }; /** * ## LanguageSelector constructor * * Manages the setting and display of the language used * * @param {object} options Optional. Configuration options * * @see Player.lang */ function LanguageSelector(options) { var that = this; this.options = options; /** * ### LanguageSelector.availableLanguages * * Object containing an object per availble language. * * The language object contains at least the following properties: * * - `name`: Name of the language in English. * - `nativeName`: Native name of the language * - `shortName`: An abbreviation for the language, also determines the * path to the context files for this language. * * The key for each language object is its `shortName`. * * @see Player.lang */ this.availableLanguages = { en: { name: 'English', nativeName: 'English', shortName: 'en' } }; /** * ### LanguageSelector.currentLanguageIndex * * A reference to the currently used language * * @see LanguageSelector.availableLanguages */ this.currentLanguage = null; /** * ### LanguageSelector.buttonListLength * * Specifies maximum number of radio buttons used in selection tool */ this.buttonListLength = null; /** * ### LanguageSelector.displayForm * * The form in which the widget displays the language information */ this.displayForm = null; /** * ### LanguageSelector.optionsLabel * * Array containing the labels for the language selection optionsDisplay */ this.optionsLabel = {}; /** * ### LanguageSelector.optionsDisplay * * Array containing the optionsDisplay for the language selection */ this.optionsDisplay = {}; /** * ### LanguageSelector.loadingDiv * * Div displaying information on whether the languages have been loaded */ this.loadingDiv = null; /** * ### LanguageSelector.languagesLoaded * * Flag indicating whether languages have been loaded from server */ this.languagesLoaded = false; /** * ## LanguageSelector.usingButtons * * Flag indicating if the interface should have buttons * * Default: TRUE. */ this.usingButtons = true; /** * ## LanguageSelector.updatePlayer * * Specifies when updating the player * * Available options: * * - false: alias for 'never', * - 'never': never notifies, * - 'onselect': each time a selection is made, * - 'ondone': when current step is done. * * Default: 'ondone' */ this.updatePlayer = 'ondone'; /** * ## LanguageSelector.setUriPrefix * * If TRUE, the Window URI prefix is updated when the player is updated * * Default: TRUE. * * @see GameWindow.setUriPrefix */ this.setUriPrefix = true; /** * ## LanguageSelector.notifyServer * * If TRUE, a message is sent to the server when the player is updated * * Default: TRUE. */ this.notifyServer = true; /** * ### LanguageSelector.onLangCallback * * Function to be called when languages have been loaded * * Initializes form displaying the information as well * as the optionsDisplay and their labels. * Initializes language to English. * Forwards to `LanguageSelector.onLangCallbackExtension` at the very * end. * * @param {object} msg GameMsg * * @see LanguageSelector.setLanguage */ this.onLangCallback = function(msg) { var language; // Clear display. while (that.displayForm.firstChild) { that.displayForm.removeChild(that.displayForm.firstChild); } // Initialize widget. that.availableLanguages = msg.data; if (that.usingButtons) { // Creates labeled buttons. for (language in msg.data) { if (msg.data.hasOwnProperty(language)) { that.optionsLabel[language] = W.get('label', { id: language + 'Label', 'for': language + 'RadioButton' }); that.optionsDisplay[language] = W.get('input', { id: language + 'RadioButton', type: 'radio', name: 'languageButton', value: msg.data[language].name }); that.optionsDisplay[language].onclick = makeSetLanguageOnClick(language); that.optionsLabel[language].appendChild( that.optionsDisplay[language]); that.optionsLabel[language].appendChild( document.createTextNode( msg.data[language].nativeName)); W.add('br', that.displayForm); that.optionsLabel[language].className = 'unselectedButtonLabel'; that.displayForm.appendChild( that.optionsLabel[language]); } } } else { that.displaySelection = W.get('select', 'selectLanguage'); for (language in msg.data) { that.optionsLabel[language] = document.createTextNode(msg.data[language].nativeName); that.optionsDisplay[language] = W.get('option', { id: language + 'Option', value: language }); that.optionsDisplay[language].appendChild( that.optionsLabel[language]); that.displaySelection.appendChild( that.optionsDisplay[language]); } that.displayForm.appendChild(that.displaySelection); that.displayForm.onchange = function() { that.setLanguage(that.displaySelection.value, that.updatePlayer === 'onselect'); }; } that.loadingDiv.style.display = 'none'; that.languagesLoaded = true; // Initialize with current value inside player object, // or default to English. Does not update the player object yet. that.setLanguage(node.player.lang.shortName || 'en', false); // Extension point. if (that.onLangCallbackExtension) { that.onLangCallbackExtension(msg); that.onLangCallbackExtension = null; } function makeSetLanguageOnClick(langStr) { return function() { that.setLanguage(langStr, that.updatePlayer === 'onselect'); }; } }; /** * ### LanguageSelector.onLangCallbackExtension * * Extension point to `LanguageSelector.onLangCallback` * * @see LanguageSelector.onLangCallback */ this.onLangCallbackExtension = null; } // ## LanguageSelector methods /** * ### LanguageSelector.init * * Initializes the widget * * @param {object} options Optional. Configuration options * * @see LanguageSelector.onLangCallback */ LanguageSelector.prototype.init = function(options) { J.mixout(options, this.options); this.options = options; if ('undefined' !== typeof this.options.usingButtons) { this.usingButtons = !!this.options.usingButtons; } if ('undefined' !== typeof this.options.notifyServer) { if (false === this.options.notifyServer) { this.options.notifyServer = 'never'; } else if ('string' === typeof this.options.notifyServer) { if ('never' === this.options.notifyServer || 'onselect' === this.options.notifyServer || 'ondone' === this.options.notifyServer) { this.notifyServer = this.options.notifyServer; } else { throw new Error('LanguageSelector.init: invalid value ' + 'for notifyServer: "' + this.options.notifyServer + '". Valid ' + 'values: "never","onselect", "ondone".'); } } else { throw new Error('LanguageSelector.init: options.notifyServer ' + 'must be ' + this.options.notifyServer); } } if ('undefined' !== typeof this.options.setUriPrefix) { this.setUriPrefix = !!this.options.setUriPrefix; } // Register listener. // TODO: should it be moved into the listeners method? // TODO: calling init twice will add it twice. node.on.lang(this.onLangCallback); // Display initialization. this.displayForm = W.get('form', 'radioButtonForm'); this.loadingDiv = W.add('div', this.displayForm); this.loadingDiv.innerHTML = this.getText('loading'); this.loadLanguages(); }; LanguageSelector.prototype.append = function() { this.bodyDiv.appendChild(this.displayForm); }; /** * ### LanguageSelector.setLanguage * * Sets language within the widget and globally and updates the display * * @param {string} langName shortName of language to be set * @param {boolean} updatePlayer If FALSE, the language is set only * inside the widget, and no changes are made to the player object. * Default: TRUE * * @see NodeGameClient.setLanguage */ LanguageSelector.prototype.setLanguage = function(langName, updatePlayer) { if (this.usingButtons) { // Uncheck current language button and change className of label. if (this.currentLanguage !== null && this.currentLanguage !== this.availableLanguages[langName] ) { this.optionsDisplay[this.currentLanguage].checked = 'unchecked'; this.optionsLabel[this.currentLanguage].className = 'unselectedButtonLabel'; } } // Set current language index. this.currentLanguage = langName; if (this.usingButtons) { // Check language button and change className of label. this.optionsDisplay[this.currentLanguage].checked = 'checked'; this.optionsLabel[this.currentLanguage].className = 'selectedButtonLabel'; } else { this.displaySelection.value = this.currentLanguage; } // Update node.player. if (updatePlayer !== false) { node.setLanguage(this.availableLanguages[this.currentLanguage], this.setUriPrefix, this.notifyServer); } }; /** * ### LanguageSelector.updateAvailableLanguages * * Updates available languages asynchronously * * @param {object} options Optional. Configuration options */ LanguageSelector.prototype.updateAvalaibleLanguages = function(options) { if (options && options.callback) { this.onLangCallbackExtension = options.callback; } node.socket.send(node.msg.create({ target: "LANG", to: "SERVER", action: "get" })); }; /** * ### LanguageSelector.loadLanguages * * Loads languages once from server * * @param {object} options Optional. Configuration options * * @see LanguageSelector.updateAvalaibleLanguages */ LanguageSelector.prototype.loadLanguages = function(options) { if (!this.languagesLoaded) this.updateAvalaibleLanguages(options); else if (options && options.callback) options.callback(); }; /** * ### LanguageSelector.listeners * * Implements Widget.listeners */ LanguageSelector.prototype.listeners = function() { var that; that = this; node.events.step.on('REALLY_DONE', function() { if (that.updatePlayer === 'ondone') { node.setLanguage(that.availableLanguages[that.currentLanguage], that.setUriPrefix, that.notifyServer); } }); }; })(node);