VulpesOS/gaia/apps/costcontrol/js/settings/autosettings.js
OverSu b38dea0597 Publish Vulpes Preview 15 sources for desktop, Android and Tundra
Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
2026-09-30 23:13:03 +02:00

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
};
}());