From 1c6898fa075b83fb613bf45777df959f97f5a2d9 Mon Sep 17 00:00:00 2001 From: rugk Date: Thu, 6 Jun 2019 14:50:47 +0200 Subject: [PATCH 1/2] Add first implementation of external modifications --- AutomaticSettings.js | 1 + internal/DomModel.js | 41 ++++++++++++++++++++++++++++++++ internal/ExternalModification.js | 39 ++++++++++++++++++++++++++++++ internal/HtmlModification.js | 5 ++-- internal/LoadAndSave.js | 37 +++++++++------------------- 5 files changed, 95 insertions(+), 28 deletions(-) create mode 100644 internal/DomModel.js create mode 100644 internal/ExternalModification.js diff --git a/AutomaticSettings.js b/AutomaticSettings.js index 14c9c01..009c483 100644 --- a/AutomaticSettings.js +++ b/AutomaticSettings.js @@ -9,4 +9,5 @@ // import and expose module parts export { default as Trigger } from "./internal/Trigger.js"; export * from "./internal/LoadAndSave.js"; +export * from "./internal/ExternalModification.js"; export { setDefaultOptionProvider } from "./internal/OptionsModel.js"; diff --git a/internal/DomModel.js b/internal/DomModel.js new file mode 100644 index 0000000..bf6ef89 --- /dev/null +++ b/internal/DomModel.js @@ -0,0 +1,41 @@ +/** + * Get data from the options as specified in the HTML/DOM. + * + * Thus, this is a model that uses the DOM as it's data source. + * + * @public + * @module AutomaticSettings + */ + +/** + * Get the name of the option from an element. + * + * @package + * @param {string} option + * @returns {HTMLElement} + */ +export function getElementFromOptionId(option) { + return document.querySelector(`[name=${option}]`); +} + +/** + * Get the option group from an HTMLElement. + * + * @package + * @param {HTMLElement} elOption + * @returns {string} + */ +export function getOptionGroup(elOption) { + return elOption.dataset.optiongroup || null; +} + +/** + * Get all the HTML elements of an option group.. + * + * @package + * @param {string} optionGroup + * @returns {string} + */ +export function getHtmlElementsOfOptionsGroup(optionGroup) { + return document.querySelectorAll(`[data-optiongroup=${optionGroup}]`); +} diff --git a/internal/ExternalModification.js b/internal/ExternalModification.js new file mode 100644 index 0000000..36b1377 --- /dev/null +++ b/internal/ExternalModification.js @@ -0,0 +1,39 @@ +/** + * Any APIs to allow external modiifications of the internal state of this module. + * + * @public + * @module AutomaticSettings + */ + +import * as HtmlMod from "./HtmlModification.js"; +import * as DomModel from "./DomModel.js"; +import * as LoadAndSave from "./LoadAndSave.js"; + +/** + * Set an option from the outside. + * + * This sets the visible option and saves it, so the state is consistent. + * It also always triggers any registered triggers. + * + * @public + * @param {string} option option to change + * @param {Object} optionValue the value to set + * @param {Object} [optionGroup] the option group of the setting + * @returns {Promise} + */ +export async function setOption(option, optionValue, optionGroup) { + const elOption = DomModel.getElementFromOptionId(option); + optionGroup = optionGroup || DomModel.getOptionGroup(elOption); + + if (optionGroup) { + await DomModel.getHtmlElementsOfOptionsGroup(optionGroup).map((elCurrentOption) => { + const currOption = HtmlMod.getOptionIdFromElement(elCurrentOption); + LoadAndSave.applyOption(currOption, optionGroup, elCurrentOption, { option: optionValue }); + }); + } else { + // apply HTML + await LoadAndSave.applyOption(option, optionGroup, elOption, { option: optionValue }); + // now trihgger saving of modified values + LoadAndSave.saveOption({target: elOption}); + } +} diff --git a/internal/HtmlModification.js b/internal/HtmlModification.js index e5ec0ee..1bdb3c5 100644 --- a/internal/HtmlModification.js +++ b/internal/HtmlModification.js @@ -7,6 +7,7 @@ // common modules import * as OptionsModel from "./OptionsModel.js"; +import * as DomModel from "./DomModel.js"; /** * Applies option to element. @@ -16,7 +17,7 @@ import * as OptionsModel from "./OptionsModel.js"; * * @protected * @function - * @param {string} option string ob object ID + * @param {string} option string ob object ID // TODO. UNUSED OPTION * @param {Object} optionValue the value to set * @param {HTMLElement} elOption where to apply feature * @returns {void} @@ -153,7 +154,7 @@ export function getIdAndOptionsFromElement(elOption, useDatagroup = true) { optionValue = OptionsModel.getOptionGroup(optionGroup); // update data in group with new values from settings HTML page - document.querySelectorAll(`[data-optiongroup=${optionGroup}]`).forEach((elCurrentOption) => { + DomModel.getHtmlElementsOfOptionsGroup(optionGroup).forEach((elCurrentOption) => { const [currentOption, currentOptionValue] = getIdAndOptionFromElement(elCurrentOption); optionValue[currentOption] = currentOptionValue; }); diff --git a/internal/LoadAndSave.js b/internal/LoadAndSave.js index 5f93e6b..086f71a 100644 --- a/internal/LoadAndSave.js +++ b/internal/LoadAndSave.js @@ -14,11 +14,12 @@ import debounce from "../../lodash/debounce.js"; import * as CommonMessages from "../../MessageHandler/CommonMessages.js"; // import internal modules +import * as DomModel from "./DomModel.js"; import * as Trigger from "./Trigger.js"; import * as HtmlMod from "./HtmlModification.js"; import * as OptionsModel from "./OptionsModel.js"; -const DEFAULT_DEBOUNCE_TIME = 250; // 250 ms +const DEFAULT_DEBOUNCE_TIME = 250; // ms // vars let managedInfoIsShown = false; @@ -28,12 +29,12 @@ let lastOptionsBeforeReset; /** * Saves the specific settings that triggered this. * - * @private + * @package * @function * @param {Object} event * @returns {void} */ -async function saveOption(event) { +export async function saveOption(event) { /** @var {HTMLElement} */ let elOption = event.target; @@ -94,31 +95,18 @@ function showManagedInfo() { managedInfoIsShown = true; } -/** - * Get the name of the option from an element.. - * - * @private - * @function - * @param {string} option - * @returns {HTMLElement} - */ -function getElementFromOptionId(option) { - return document.querySelector(`[name=${option}]`); -} - /** * Applies an option to the HTML element. This is the final step, before it goes * into the {@link HtmlMod} module. * - * @private - * @function + * @package * @param {string} option string ob object ID * @param {string|null} optionGroup optiom group, if it is used * @param {HTMLElement} elOption where to apply feature * @param {Object|undefined} optionValues object values * @returns {Promise} */ -async function applyOption(option, optionGroup, elOption, optionValues) { +export async function applyOption(option, optionGroup, elOption, optionValues) { let optionValue = OptionsModel.getOptionValueFromRequestResults(option, optionGroup, optionValues); const overwriteResult = await Trigger.runOverrideLoad(option, optionValue, elOption, optionValues); @@ -152,7 +140,7 @@ async function applyOption(option, optionGroup, elOption, optionValues) { * be autodetected otherwise * @returns {Promise} */ -function setManagedOption(option, optionGroup, elOption = getElementFromOptionId(option)) { +function setManagedOption(option, optionGroup, elOption = DomModel.getElementFromOptionId(option)) { if (optionGroup === undefined && elOption.hasAttribute("data-optiongroup")) { optionGroup = elOption.getAttribute("data-optiongroup"); } @@ -194,7 +182,7 @@ function setManagedOption(option, optionGroup, elOption = getElementFromOptionId * be autodetected otherwise * @returns {Promise} */ -function setSyncedOption(option, optionGroup, elOption = getElementFromOptionId(option)) { +function setSyncedOption(option, optionGroup, elOption = DomModel.getElementFromOptionId(option)) { if (optionGroup === undefined && elOption.hasAttribute("data-optiongroup")) { optionGroup = elOption.getAttribute("data-optiongroup"); } @@ -227,15 +215,12 @@ function setSyncedOption(option, optionGroup, elOption = getElementFromOptionId( export function loadOption(elOption, option) { option = option ? option : HtmlMod.getOptionIdFromElement(elOption); - let optionGroup = null; - if ("optiongroup" in elOption.dataset) { - optionGroup = elOption.dataset.optiongroup; - } + const optionGroup = DomModel.getOptionGroup(elOption); // try to get option ID from input element if needed if (!option && elOption.dataset.type === "radiogroup") { option = elOption.querySelector("input[type=radio]").getAttribute("name"); - } + } // TODO: refactor this if to include in getOptionIdFromElement return setManagedOption(option, optionGroup, elOption).catch((error) => { /* only log warning as that is expected when no manifest file is found */ @@ -256,7 +241,7 @@ export function loadOption(elOption, option) { * be autodetected otherwise * @returns {Promise} */ -export function loadOptionByName(option, elOption = getElementFromOptionId(option)) { +export function loadOptionByName(option, elOption = DomModel.getElementFromOptionId(option)) { return loadOption(elOption, option); } From 2bc739feb39cf5ae17db1e508c93a293c9850885 Mon Sep 17 00:00:00 2001 From: rugk Date: Wed, 17 Jul 2019 18:13:33 +0200 Subject: [PATCH 2/2] fix typo --- internal/ExternalModification.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/ExternalModification.js b/internal/ExternalModification.js index 36b1377..6785af4 100644 --- a/internal/ExternalModification.js +++ b/internal/ExternalModification.js @@ -33,7 +33,7 @@ export async function setOption(option, optionValue, optionGroup) { } else { // apply HTML await LoadAndSave.applyOption(option, optionGroup, elOption, { option: optionValue }); - // now trihgger saving of modified values + // now trigger saving of modified values LoadAndSave.saveOption({target: elOption}); } }