您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Configuration management and related UI creation module
当前为
此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.cn-greasyfork.org/scripts/418665/942026/Brazen%20Configuration%20Manager.js
// ==UserScript== // @name Brazen Configuration Manager // @namespace brazenvoid // @version 2.1.1 // @author brazenvoid // @license GPL-3.0-only // @description Configuration management and related UI creation module // ==/UserScript== const CONFIG_TYPE_CHECKBOXES_GROUP = 'checkboxes' const CONFIG_TYPE_FLAG = 'flag' const CONFIG_TYPE_NUMBER = 'number' const CONFIG_TYPE_RADIOS_GROUP = 'radios' const CONFIG_TYPE_RANGE = 'range' const CONFIG_TYPE_RULESET = 'ruleset' const CONFIG_TYPE_SELECT = 'select' const CONFIG_TYPE_TEXT = 'text' const SELECTOR_CONFIG_TRACKER_TOTAL = '#brazen-config-tracker-total' class BrazenConfigurationManager { /** * @typedef {{key: string, title: string, type: string, element: null|JQuery, value: *, maximum: int, minimum: int, optimized: *, options: string[], * helpText: string, unit: string, onFormatForUI: ConfigurationManagerRulesetCallback, onTranslateFromUI: ConfigurationManagerRulesetCallback, * onOptimize: ConfigurationManagerRulesetCallback, createElement: Function, setFromUserInterface: Function, track: boolean, trackerValue: number, * updateUserInterface: Function}} ConfigurationField */ /** * @callback ConfigurationManagerRulesetCallback * @param {*} values */ /** * @callback ExternalConfigurationChangeCallback * @param {BrazenConfigurationManager} manager */ /** * @param {BrazenUIGenerator} uiGenerator * @return {BrazenConfigurationManager} */ static create (uiGenerator) { return new BrazenConfigurationManager(uiGenerator) } /** * @param {ConfigurationField} field * @returns {string} */ static generateIdForTrackerGroup (field) { return field.key + '-stat' } constructor (uiGenerator) { /** * @type {{}} * @private */ this._config = {} /** * @type {ExternalConfigurationChangeCallback|null} * @private */ this._onExternalConfigurationChange = null /** * @type {LocalStore} * @private */ this._localStore = null /** * @type {LocalStore} * @private */ this._localStoreId = null /** * @type {number} * @private */ this._syncedLocalStoreId = 0 /** * @type BrazenUIGenerator * @private */ this._uiGen = uiGenerator } /** * @param {string} type * @param {string} name * @param {*} value * @param {string|null} helpText * @param {boolean} enableTracking * @return {ConfigurationField} * @private */ _createField (type, name, value, helpText, enableTracking) { let fieldKey = this._formatFieldKey(name) let field = this._config[fieldKey] if (!field) { field = { key: fieldKey, element: null, helpText: helpText, title: name, type: type, value: value, createElement: null, setFromUserInterface: null, track: enableTracking, trackerValue: 0, updateUserInterface: null, } this._config[fieldKey] = field } else { if (helpText) { field.helpText = helpText } field.value = value } return field } /** * @param {string} name * @return {string} * @private */ _formatFieldKey (name) { return Utilities.toKebabCase(name.replaceAll('&', 'and')) } /** * @param {boolean} ignoreIfDefaultsSet * @private */ _syncLocalStore (ignoreIfDefaultsSet) { let field let storeObject = this._localStore.get() if (!ignoreIfDefaultsSet || !this._localStore.wereDefaultsSet()) { for (let key in this._config) { field = this._config[key] if (typeof storeObject[key] !== 'undefined') { field.value = storeObject[key] if (field.type === CONFIG_TYPE_RULESET) { field.optimized = Utilities.callEventHandler(field.onOptimize, [field.value]) } } } this.updateInterface() } return this } /** * @return {{}} * @private */ _toStoreObject () { let storeObject = {} for (let key in this._config) { storeObject[key] = this._config[key].value } return storeObject } /** * @private */ _regenerateStoreId () { this._localStoreId.save({id: Utilities.generateId()}) } /** * @param {string} name * @param {string[]} options * @param {string} helpText * @param {boolean} enableTracking * @returns {BrazenConfigurationManager} */ addCheckboxesGroup (name, options, helpText, enableTracking = true) { let field = this._createField(CONFIG_TYPE_CHECKBOXES_GROUP, name, [], helpText, enableTracking) field.options = options field.createElement = () => this._uiGen.createFormConfigSwitchesGroup(field) field.setFromUserInterface = () => { field.value = [] field.element.find('input:checked').each((index, element) => field.value.push($(element).val())) } field.updateUserInterface = () => { let elements = field.element.find('input').prop('checked', false) for (let checkboxIndex of field.value) { elements.eq(checkboxIndex).prop('checked', true) } } return this } /** * @param {string} name * @param {string} helpText * @param {boolean} enableTracking * @returns {BrazenConfigurationManager} */ addFlagField (name, helpText, enableTracking = true) { let field = this._createField(CONFIG_TYPE_FLAG, name, false, helpText, enableTracking) field.createElement = () => this._uiGen.createFormConfigSwitch(field) field.setFromUserInterface = () => field.value = field.element.find('input').prop('checked') field.updateUserInterface = () => field.element.find('input').prop('checked', field.value) return this } /** * @param {string} name * @param {string} unit * @param {number} minimum * @param {number} maximum * @param {string} helpText * @param {boolean} enableTracking * @returns {BrazenConfigurationManager} */ addNumberField (name, unit, minimum, maximum, helpText, enableTracking = true) { let field = this._createField(CONFIG_TYPE_NUMBER, name, minimum, helpText, enableTracking) field.minimum = minimum field.maximum = maximum field.unit = unit field.createElement = () => this._uiGen.createFormConfigNumberInput(field) field.setFromUserInterface = () => field.value = field.element.find('input').val() field.updateUserInterface = () => field.element.find('input').val(field.value) return this } /** * @param {string} name * @param {string} unit * @param {number} minimum * @param {number} maximum * @param {string} helpText * @param {boolean} enableTracking * @returns {BrazenConfigurationManager} */ addRangeField (name, unit, minimum, maximum, helpText, enableTracking = true) { let field = this._createField(CONFIG_TYPE_RANGE, name, {minimum: minimum, maximum: minimum}, helpText, enableTracking) field.minimum = minimum field.maximum = maximum field.unit = unit field.createElement = () => this._uiGen.createFormConfigRangeInput(field) field.setFromUserInterface = () => field.value = { minimum: field.element.find('.range-min').val(), maximum: field.element.find('.range-max').val(), } field.updateUserInterface = () => { field.element.find('.range-min').val(field.value.minimum) field.element.find('.range-max').val(field.value.maximum) } return this } /** * @param {string} name * @param {string|null} helpText * @param {boolean} enableTracking * @return {ConfigurationField} */ addRulesetField (name, helpText, enableTracking = true) { let field = this._createField(CONFIG_TYPE_RULESET, name, [], helpText, enableTracking) field.optimized = null field.onTranslateFromUI = null field.onFormatForUI = null field.onOptimize = null field.createElement = () => this._uiGen.createFormConfigRulesetAccordion(field) field.setFromUserInterface = () => { let value = Utilities.trimAndKeepNonEmptyStrings(field.element.find('.ruleset-input').val().split(REGEX_LINE_BREAK)) field.value = Utilities.callEventHandler(field.onTranslateFromUI, [value], value) field.optimized = Utilities.callEventHandler(field.onOptimize, [field.value]) } field.updateUserInterface = () => field.element .find('.ruleset-input') .val(Utilities.callEventHandler(field.onFormatForUI, [field.value], field.value).join('\n')) return field } /** * @param {string} name * @param {string[]} options * @param {string} helpText * @param {boolean} enableTracking * @returns {BrazenConfigurationManager} */ addSelectField (name, options, helpText, enableTracking = true) { let field = this._createField(CONFIG_TYPE_SELECT, name, 0, helpText, enableTracking) field.options = options field.createElement = () => this._uiGen.createFormConfigSelect(field) field.setFromUserInterface = () => field.value = field.element.find('select').val() field.updateUserInterface = () => field.element.find('select').val(field.value).trigger('change') return this } /** * @param {string} name * @param {string} helpText * @param {boolean} enableTracking * @returns {BrazenConfigurationManager} */ addTextField (name, helpText, enableTracking = true) { let field = this._createField(CONFIG_TYPE_TEXT, name, '', helpText, enableTracking) field.createElement = () => this._uiGen.createFormConfigInput(field) field.setFromUserInterface = () => field.value = field.element.find('input').val() field.updateUserInterface = () => field.element.find('input').val(field.value) return this } backup () { let backupConfig = this._toStoreObject() backupConfig.id = this._syncedLocalStoreId return Utilities.objectToJSON(backupConfig) } /** * @param {string} configName * @returns {JQuery} */ createElement (configName) { let field = this.getFieldOrFail(configName) if (field.track) { this._uiGen.createFormStatGroup(field) } return field.createElement() } /** * @param {string} configName * @return {ConfigurationField|null} */ getField (configName) { return this._config[this._formatFieldKey(configName)] } /** * @param {string} configName * @return {ConfigurationField} */ getFieldOrFail (configName) { let field = this._config[this._formatFieldKey(configName)] if (field) { return field } throw new Error('Field named "' + configName + '" could not be found') } /** * @param {string|ConfigurationField} configName * @return {*} */ getValue (configName) { let field = typeof configName === 'string' ? this.getFieldOrFail(configName) : configName return field.optimized ?? field.value } /** * @param {string} configName * @return {boolean} */ hasField (configName) { return typeof this.getField(configName) !== 'undefined' } /** * @return {BrazenConfigurationManager} */ initialize (scriptName) { let scriptKey = this._formatFieldKey(scriptName) this._localStore = new LocalStore(scriptKey + '-settings', this._toStoreObject()) this._localStore.onChange(() => this.updateInterface()) this._localStoreId = new LocalStore(scriptKey + '-settings-id', {id: Utilities.generateId()}) $(document).on('visibilitychange', () => { if (!document.hidden && this._syncedLocalStoreId !== this._localStoreId.get().id) { Utilities.callEventHandler(this._onExternalConfigurationChange, [this]) } }) return this._syncLocalStore(true) } /** * @param {ExternalConfigurationChangeCallback} eventHandler * @return {BrazenConfigurationManager} */ onExternalConfigurationChange (eventHandler) { this._onExternalConfigurationChange = eventHandler return this } /** * @param {string} backedUpConfiguration */ restore (backedUpConfiguration) { let backupConfig = Utilities.objectFromJSON(backedUpConfiguration) if (typeof backupConfig.id !== 'undefined') { this._syncedLocalStoreId = backupConfig.id this._localStoreId.save({id: backupConfig.id}) delete backupConfig.id } else { this._regenerateStoreId() } this._localStore.save(backupConfig) this._syncLocalStore(false) return this } revertChanges () { return this._syncLocalStore(false) } save () { this.update()._localStore.save(this._toStoreObject()) this._regenerateStoreId() return this } /** * @param {ConfigurationField} field * @param {number|boolean} value */ trackState (field, value = 1) { if (field.track) { field.trackerValue += value } } update () { let field for (let fieldName in this._config) { field = this._config[fieldName] if (field.element) { field.setFromUserInterface() } } return this } resetTrackers () { let field for (const fieldName in this._config) { field = this._config[fieldName] field.trackerValue = 0 } } updateInterface () { let field for (let fieldName in this._config) { field = this._config[fieldName] if (field.element) { field.updateUserInterface() } } return this } updateTrackersInterface () { let field let total = 0; for (const fieldName in this._config) { field = this._config[fieldName] if (field.track) { $('#' + this.constructor.generateIdForTrackerGroup(field)).text(field.trackerValue) total += field.trackerValue } } $(SELECTOR_CONFIG_TRACKER_TOTAL).text(total) } }