/* global debug */ /* exported AutoSettings */ 'use strict'; var AutoSettings = (function() { var OPTION_CONFIGURERS = { 'select': function _selectConfigurer(guiWidget) { var optionName = guiWidget.dataset.option; var span, parent = guiWidget.parentElement; if (parent.classList.contains('fake-select')) { var firstChild = parent.firstChild; if (!firstChild || firstChild.tagName !== 'SPAN') { span = document.createElement('span'); parent.insertBefore(span, parent.firstChild); } } guiWidget.addEventListener('blur', function _onSelectChange() { debug('Value:', guiWidget.value); settings.option(optionName, guiWidget.value); }); settings.observe(optionName, function _onOptionChange(value) { if (value === undefined) { value = settings.defaultValue(optionName); } guiWidget.value = value; if (span) { var selected = guiWidget.options[guiWidget.selectedIndex]; var l10nId = selected.getAttribute('data-l10n-id'); span.textContent = selected.textContent; if (l10nId) { span.setAttribute('data-l10n-id', l10nId); } } }); }, // Select is used to simulate custom combo boxes. It displays a selection // dialog with an ok button and possibly a cancel button. The value is only // changed if ok button is pressed. If cancel provided and clicked then // the former value is restored. 'customselect': function _customselectConfigurer(guiWidget) { var dialog = document.getElementById(guiWidget.dataset.selectdialog); var optionName = guiWidget.dataset.option; // Dialog var okButton = dialog.querySelector('button.recommend'); if (okButton) { okButton.addEventListener('click', function _onDialogOk() { var checked = dialog.querySelector('input[type="radio"]:checked'); settings.option(optionName, checked.value); vmanager.closeCurrentView(); }); } var cancelButton = dialog.querySelector('button.cancel'); if (cancelButton) { cancelButton.addEventListener('click', function _onDialogCancel() { var currentValue = settings.option(optionName); settings.option(optionName, currentValue); vmanager.closeCurrentView(); } ); } guiWidget.addEventListener('click', function _onWidgetClick() { vmanager.changeViewTo(dialog.id); }); // Keep the widget and the dialog synchronized settings.observe(optionName, function _onOptionChange(value) { // Use default value if no value if (value === null || value === undefined) { value = getDefaultValue(optionName); } var radio = dialog.querySelector('input[type="radio"][value="' + value + '"]'); if (!radio) { value = getDefaultValue(optionName); radio = dialog.querySelector('input[type="radio"][value="' + value + '"]'); } radio.checked = true; var textSpan = dialog.querySelector('input:checked + span'); var tagSpan = guiWidget.querySelector('.tag'); tagSpan.textContent = textSpan.textContent; } ); // Keep the UI localized window.addEventListener('localized', function _onLocalized() { var textSpan = dialog.querySelector('input:checked + span'); var tagSpan = guiWidget.querySelector('.tag'); tagSpan.textContent = textSpan.textContent; }); }, // Switch configurer handles an checkbox. When it changes, the checked // state is used as the content for the option. 'switch' : function _switchConfigurer(guiWidget) { var optionName = guiWidget.dataset.option; // Add an observer to keep synchronization settings.observe( optionName, function _onOptionChange(value) { if (value === null || value === undefined) { value = getDefaultValue(optionName); } guiWidget.checked = value; } ); // Add an event listener to switch the option guiWidget.addEventListener('change', function ccapp_onSwitchChange() { settings.option(optionName, guiWidget.checked); }); }, // Input configurer handles an input box. When the content changes, the // content is parsed and sent to the proper option. 'input' : function _inputConfigurer(guiWidget) { var optionName = guiWidget.dataset.option; // Add an observer to keep synchronization settings.observe( optionName, function _onOptionChange(value) { if (value === null || value === undefined) { value = getDefaultValue(optionName); } guiWidget.value = value; } ); // Add an event listener to switch the option guiWidget.addEventListener('change', function _onContentChange() { var value = guiWidget.value; if (guiWidget.type === 'number') { value = parseFloat(value); } settings.option(optionName, value); }); } }; // Add a new type with its configuration function function addType(newType, configFunction) { OPTION_CONFIGURERS[newType] = configFunction; } var customRecognizer; // Add a recognizer to detect new types function setCustomRecognizer(recognizer) { customRecognizer = recognizer; } // Return the
  • wrapping the option function getEntryParent(item) { while (item && item.tagName !== 'LI') { item = item.parentNode; } return item; } // Return the default value for an option function getDefaultValue(optionName) { return settings.defaultValue(optionName); } // Configure the web page var settings, vmanager; function initialize(settingsInterface, viewManager, root) { root = root || 'body'; settings = settingsInterface; vmanager = viewManager; // Return the type of configurer needed based on the properties of // the HTML element marked as the option. function getWidgetType(widget) { if (widget.dataset.widgetType) { return widget.dataset.widgetType; } var customType; if (customRecognizer === 'function') { customType = customRecognizer(widget, settings, vmanager); } if (customType) { return customType; } if (widget.tagName === 'SELECT') { return 'select'; } if (typeof widget.dataset.selectdialog !== 'undefined') { return 'customselect'; } if (widget.type === 'checkbox' || widget.nodeName.toLowerCase() === 'gaia-switch') { return 'switch'; } if (['text', 'number'].indexOf(widget.type) !== -1) { return 'input'; } } // Install a dependency based on an expression. When expression is true // call the callback. function installDependency(expression, callback) { var equality = false; var parsed = expression.split('!='); if (parsed.length === 1) { parsed = expression.split('='); equality = true; } var dependency = parsed[0]; var referenceValue = parsed[1]; settings.observe(dependency, function ccapp_dependencyAction(value) { var test = (('' + value) === referenceValue); callback(equality === test); // or is an equality test and values are // equal or is an inequality test and // values are different. } ); } // Widgets var allGUIWidgets = document.querySelectorAll(root + ' .settings-option'); [].forEach.call(allGUIWidgets, function _forEachWidget(guiWidget) { var type = getWidgetType(guiWidget); var entry = getEntryParent(guiWidget); var configurer = OPTION_CONFIGURERS[type]; if (configurer) { configurer(guiWidget, settings, vmanager, root); } // Simple dependency resolution: // enable / disable some options depending on the values of other var disableOn = guiWidget.dataset.disableOn; if (disableOn) { installDependency(disableOn, function _disable(passed) { guiWidget.disabled = passed; if (entry) { entry.setAttribute('aria-disabled', passed + ''); } }); } // hide / show some options depending on the values of other var hideOn = guiWidget.dataset.hideOn; if (hideOn) { installDependency(hideOn, function _hide(passed) { guiWidget.hidden = passed; if (entry) { entry.hidden = passed; } }); } }); } return { initialize: initialize, setCustomRecognizer: setCustomRecognizer, addType: addType }; }());