Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
288 lines
8.8 KiB
JavaScript
Executable file
288 lines
8.8 KiB
JavaScript
Executable file
/* 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 <li> 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
|
|
};
|
|
|
|
}());
|