VulpesOS/gaia/apps/clock/js/form_button.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

196 lines
5.2 KiB
JavaScript
Executable file

// outer IIFE
define(function(require) {
'use strict';
var Utils = require('utils');
function createButton(formButton) {
var button = document.createElement(formButton.tagName);
button.className = formButton.className;
if (formButton.id) {
button.id = formButton.id;
}
var input = formButton.input;
input.parentNode.insertBefore(button, input.nextSibling);
formButton.button = button;
}
/**
* A FormButton is a button that triggers an input. The text
* of the currently selected value will display on the buttons's face.
*
* The `config` paramater supports the following optional properties.
* `formatLabel` - A function that is given the current value of the input
* and should return a string which will be used as the textContent of
* the button.
*
* `tagName` - The name of the tag to create and insert into the
* document as the main button used to trigger the input. The default
* value is 'button'
*
* `className` The value of the className property that will be assigned to
* the button element the default value is 'icon icon-dialog'.
*
* `id` - A string that is used as the id of the button element.
*
* @constructor
* @param {HTMLElement} input The input element to trigger.
* @param {Object} config An optional config object.
*
*/
function FormButton(input, config) {
config = config || {};
Utils.extend(this, config);
this.input = input;
createButton(this);
this.input.classList.add('form-button-input');
// hide input
this.input.classList.add('form-button-hide');
// set isSelect
Object.defineProperty(this, 'isSelect', {
value: this.input.nodeName === 'SELECT'
});
this.button.addEventListener('click', this.focus.bind(this), false);
input.addEventListener('change', this.refresh.bind(this), false);
input.addEventListener('blur', this.refresh.bind(this), false);
// Bind this.refresh so that the listener can be easily removed.
this.refresh = this.refresh.bind(this);
// Update the dropdown when the language changes.
window.addEventListener('localized', this.refresh);
window.addEventListener('timeformatchange', this.refresh);
}
FormButton.prototype = {
/** Remove all event handlers. */
destroy: function() {
window.removeEventListener('localized', this.refresh);
},
/**
* focus Triggers a focus event on the input associated with this
* FormButton.
*
* @param {Object} event an event object.
*/
focus: function(event) {
event.preventDefault();
setTimeout(this.input.focus.bind(this.input), 10);
},
/**
* refresh Updates the label text on the button to reflect
* the current value of the input.
*
*/
refresh: function() {
var value = this.value;
var label = this.formatLabel(value);
// In some cases formatLabel returns a Promise that returns l10nId
var labelPromise = label.then ? label : Promise.resolve(label);
return labelPromise.then((l10nId) => {
if (typeof l10nId === 'string') {
this.button.setAttribute('data-l10n-id', l10nId);
} else if (l10nId.raw) {
this.button.removeAttribute('data-l10n-id');
this.button.textContent = l10nId.raw;
} else if (l10nId.id) {
document.l10n.setAttributes(this.button, l10nId.id, l10nId.args);
}
});
},
/**
* value Returns the current value of the input.
*
* @return {String|Object} The value of the input.
*
*/
get value() {
if (this.isSelect) {
if (this.input.multiple) {
var selectedOptions = {};
var options = this.input.options;
for (var i = 0; i < options.length; i++) {
if (options[i].selected) {
selectedOptions[options[i].value] = true;
}
}
return selectedOptions;
}
if (this.input.selectedIndex !== -1) {
return Utils.getSelectedValueByIndex(this.input);
}
return null;
}
// input node
return this.input.value;
},
/**
* value sets the current value of the input and update's the
* button text.
*
* @param {String|Object} value A string of the current values or an
* object with properties that map to input options if the input is
* a multi select.
*
*/
set value(value) {
if (this.isSelect) {
if (this.input.multiple) {
// multi select
var options = this.input.options;
for (var i = 0; i < options.length; i++) {
options[i].selected = value[options[i].value] === true;
}
} else {
// normal select element
Utils.changeSelectByValue(this.input, value);
}
} else {
// input element
this.input.value = value;
}
// Update the text on the button to reflect the new input value
this.refresh();
},
/**
* An overrideable method that is called when updating the textContent
* of the button.
*
* @return {L10nId} The formatted text to display in the label.
*
*/
formatLabel: function(value) {
return { raw: value };
},
/**
* tagName The the name of the tag to insert into the document to use
* as the button element.
*/
tagName: 'button',
/**
* class The value to assign to the className property on the
* generated button element.
*/
className: 'icon icon-dialog'
};
return FormButton;
// end outer IIFE
});