From b9cca9c5ff90564109b2d6307f461b830ff07cd5 Mon Sep 17 00:00:00 2001 From: ralf <rb@egroupware.org> Date: Wed, 16 Mar 2022 22:36:23 +0200 Subject: [PATCH] using set/get select_option plus a set_selection_options marked as deprecated - get_select_options seems to be nowhere in use, so I did not implement it - Et2Select* widgets with static options assign them in their constructor (like the r/o ones) - removed a jQuery.proxy call, which we dont want in new code --- api/js/etemplate/Et2Select/Et2Select.ts | 95 ++++++++++++------- .../etemplate/Et2Select/Et2SelectAccount.ts | 15 ++- .../etemplate/Et2Select/Et2SelectReadonly.ts | 32 +++++-- .../Et2Select/Et2WidgetWithSelectMixin.ts | 41 +++++--- api/js/etemplate/Et2Select/StaticOptions.ts | 42 ++++---- 5 files changed, 147 insertions(+), 78 deletions(-) diff --git a/api/js/etemplate/Et2Select/Et2Select.ts b/api/js/etemplate/Et2Select/Et2Select.ts index 0400e953ee..417b25de6a 100644 --- a/api/js/etemplate/Et2Select/Et2Select.ts +++ b/api/js/etemplate/Et2Select/Et2Select.ts @@ -134,7 +134,7 @@ export class Et2Select extends Et2InvokerMixin(Et2WidgetWithSelect) */ get value() : string|string[] { - if (!this._inputNode || !this.select_options?.length) + if (!this._inputNode || !this.select_options.length) { return this.__value || ''; } @@ -155,7 +155,7 @@ export class Et2Select extends Et2InvokerMixin(Et2WidgetWithSelect) set value(value: string|string[]) { // if not yet connected to dom can't change the value - if (this._inputNode && this.select_options?.length) + if (this._inputNode && this.select_options.length) { // split multiple comma-separated values for multiple or expand_multiple_rows if (typeof value === 'string' && (this.multiple || this.expand_multiple_rows) && value.indexOf(',') !== -1) @@ -252,11 +252,11 @@ export class Et2Select extends Et2InvokerMixin(Et2WidgetWithSelect) { const modelValueArr = Array.isArray(this.modelValue) ? this.modelValue : this.modelValue.split(','); // value not in options AND NOT (having an empty label and value) - if(this.get_select_options().length > 0 && this.get_select_options().filter((option) => modelValueArr.find(val => val == option.value)).length === 0 && + if(this.select_options.length > 0 && this.select_options.filter((option) => modelValueArr.find(val => val == option.value)).length === 0 && !(typeof this.empty_label !== 'undefined' && (this.modelValue || "") === "")) { // --> use first option - this.modelValue = "" + this.get_select_options()[0]?.value; // ""+ to cast value of 0 to "0", to not replace with "" + this.modelValue = "" + this.select_options[0]?.value; // ""+ to cast value of 0 to "0", to not replace with "" } // Re-set value, the option for it may have just shown up this.value = this.modelValue || ""; @@ -304,9 +304,11 @@ customElements.define("et2-select", Et2Select); export class Et2SelectApp extends Et2Select { - get_select_options() : SelectOption[] + constructor() { - return so.app(this, {other: this.other || []}); + super(); + + this.select_options = so.app(this, {other: this.other || []}); } } @@ -319,7 +321,7 @@ export class Et2SelectBitwise extends Et2Select { let oldValue = this._value; let expanded_value = []; - let options = this.get_select_options(); + let options = this.select_options; for(let index in options) { let right = parseInt(options[index].value); @@ -339,11 +341,12 @@ customElements.define("et2-select-bitwise", Et2SelectBitwise); export class Et2SelectBool extends Et2Select { - get_select_options() : SelectOption[] + constructor() { - return so.bool(this); - } + super(); + this.select_options = so.bool(this); + } } // @ts-ignore TypeScript is not recognizing that this widget is a LitElement @@ -351,9 +354,11 @@ customElements.define("et2-select-bool", Et2SelectBool); export class Et2SelectCategory extends Et2Select { - get_select_options() : SelectOption[] + constructor() { - return so.cat(this, {other: this.other || []}); + super(); + + this.select_options = so.cat(this, {other: this.other || []}); } } @@ -362,9 +367,11 @@ customElements.define("et2-select-cat", Et2SelectCategory); export class Et2SelectPercent extends Et2Select { - get_select_options() : SelectOption[] + constructor() { - return so.percent(this, {}); + super(); + + this.select_options = so.percent(this, {}); } } @@ -373,9 +380,11 @@ customElements.define("et2-select-percent", Et2SelectPercent); export class Et2SelectCountry extends Et2Select { - get_select_options() : SelectOption[] + constructor() { - return so.country(this, {}); + super(); + + this.select_options = so.country(this, {}); } } @@ -384,9 +393,11 @@ customElements.define("et2-select-country", Et2SelectCountry); export class Et2SelectDay extends Et2Select { - get_select_options() : SelectOption[] + constructor() { - return so.day(this, {other: this.other || []}); + super(); + + this.select_options = so.day(this, {other: this.other || []}); } } @@ -395,9 +406,11 @@ customElements.define("et2-select-day", Et2SelectDay); export class Et2SelectDayOfWeek extends Et2Select { - get_select_options() : SelectOption[] + constructor() { - return so.dow(this, {other: this.other || []}); + super(); + + this.select_options = so.dow(this, {other: this.other || []}); } } @@ -406,9 +419,11 @@ customElements.define("et2-select-dow", Et2SelectDayOfWeek); export class Et2SelectHour extends Et2Select { - get_select_options() : SelectOption[] + constructor() { - return so.hour(this, {other: this.other || []}); + super(); + + this.select_options = so.hour(this, {other: this.other || []}); } } @@ -417,9 +432,11 @@ customElements.define("et2-select-hour", Et2SelectHour); export class Et2SelectMonth extends Et2Select { - get_select_options() : SelectOption[] + constructor() { - return so.month(this); + super(); + + this.select_options = so.month(this); } } @@ -428,9 +445,11 @@ customElements.define("et2-select-month", Et2SelectMonth); export class Et2SelectNumber extends Et2Select { - get_select_options() : SelectOption[] + constructor() { - return so.number(this, {other: this.other || []}); + super(); + + this.select_options = so.number(this, {other: this.other || []}); } } @@ -439,9 +458,11 @@ customElements.define("et2-select-number", Et2SelectNumber); export class Et2SelectPriority extends Et2Select { - get_select_options() : SelectOption[] + constructor() { - return so.priority(this); + super(); + + this.select_options = so.priority(this); } } @@ -450,9 +471,11 @@ customElements.define("et2-select-priority", Et2SelectPriority); export class Et2SelectState extends Et2Select { - get_select_options() : SelectOption[] + constructor() { - return so.state(this, {other: this.other || []}); + super(); + + this.select_options = so.state(this, {other: this.other || []}); } } @@ -461,9 +484,11 @@ customElements.define("et2-select-state", Et2SelectState); export class Et2SelectTimezone extends Et2Select { - get_select_options() : SelectOption[] + constructor() { - return so.timezone(this, {other: this.other || []}); + super(); + + this.select_options = so.timezone(this, {other: this.other || []}); } } @@ -472,9 +497,11 @@ customElements.define("et2-select-timezone", Et2SelectTimezone); export class Et2SelectYear extends Et2Select { - get_select_options() : SelectOption[] + constructor() { - return so.year(this, {other: this.other || []}); + super(); + + this.select_options = so.year(this, {other: this.other || []}); } } diff --git a/api/js/etemplate/Et2Select/Et2SelectAccount.ts b/api/js/etemplate/Et2Select/Et2SelectAccount.ts index 61095ede01..acc916c642 100644 --- a/api/js/etemplate/Et2Select/Et2SelectAccount.ts +++ b/api/js/etemplate/Et2Select/Et2SelectAccount.ts @@ -32,20 +32,25 @@ export class Et2SelectAccount extends Et2Select { super(); - this.account_type = 'accounts'; + this.__account_type = 'accounts'; } - set_account_type(type : AccountType) + set account_type(type : AccountType) { - this.account_type = type; + this.__account_type = type; - this.set_select_options(this.get_select_options()); + super.select_options = this.select_options; + } + + get account_type() : AccountType + { + return this.__account_type; } /** * Get account info for select options from common client-side account cache */ - get_select_options() : Array<SelectOption> + get select_options() : Array<SelectOption> { const type = this.egw().preference('account_selection', 'common'); if (type === 'none' && typeof egw.user('apps').admin === 'undefined') diff --git a/api/js/etemplate/Et2Select/Et2SelectReadonly.ts b/api/js/etemplate/Et2Select/Et2SelectReadonly.ts index 4fd5ff930c..902a1d2a89 100644 --- a/api/js/etemplate/Et2Select/Et2SelectReadonly.ts +++ b/api/js/etemplate/Et2Select/Et2SelectReadonly.ts @@ -55,7 +55,7 @@ li { { super(); this.type = ""; - this.select_options = []; + this.__select_options = <SelectOption[]>[]; } protected find_select_options(_attrs) @@ -63,7 +63,7 @@ li { let sel_options = find_select_options(this, _attrs['select_options']); if(sel_options.length > 0) { - this.set_select_options(sel_options); + this.select_options = sel_options; } } @@ -86,6 +86,10 @@ li { this.find_select_options(_attrs) } + /** + * @deprecated assign to value + * @param value + */ set_value(value) { this.value = value; @@ -117,7 +121,7 @@ li { * * @param {SelectOption[]} new_options */ - set_select_options(new_options : SelectOption[] | { [key : string] : string }) + set select_options(new_options : SelectOption[] | { [key : string] : string }) { if(!Array.isArray(new_options)) { @@ -130,9 +134,25 @@ li { this.select_options = fixed_options; return; } + this.__select_options = new_options; + } + + /** + * Set the select options + * + * @deprecated assign to select_options + * @param new_options + */ + set_select_options(new_options : SelectOption[] | { [key : string] : string }) + { this.select_options = new_options; } + get select_options() : SelectOption[] | { [key : string] : string } + { + return this.__select_options; + } + render() { if(!this.value) @@ -144,7 +164,7 @@ li { <ul> ${repeat(this.value, (val : string) => val, (val) => { - let option = this.select_options.find(option => option.value == val); + let option = (<SelectOption[]>this.select_options).find(option => option.value == val); if(!option) { return ""; @@ -204,7 +224,7 @@ export class Et2SelectAccountReadonly extends Et2SelectReadonly { let account_name = null; let option = <SelectOption>{value: id, label: id + " ..."}; - this.select_options.push(option); + this.select_options = [].concat(this.select_options, option); if(new_value && (account_name = this.egw().link_title('api-accounts', id))) { option.label = account_name; @@ -264,7 +284,7 @@ export class Et2SelectBitwiseReadonly extends Et2SelectReadonly <ul> ${repeat(new_value, (val : string) => val, (val) => { - let option = this.select_options.find(option => option.value == val); + let option = (<SelectOption[]>this.select_options).find(option => option.value == val); if(!option) { return ""; diff --git a/api/js/etemplate/Et2Select/Et2WidgetWithSelectMixin.ts b/api/js/etemplate/Et2Select/Et2WidgetWithSelectMixin.ts index 22e7a8b172..9f9138db1f 100644 --- a/api/js/etemplate/Et2Select/Et2WidgetWithSelectMixin.ts +++ b/api/js/etemplate/Et2Select/Et2WidgetWithSelectMixin.ts @@ -73,7 +73,7 @@ export const Et2widgetWithSelectMixin = dedupeMixin((superclass) => * Select box options * * Will be found automatically based on ID and type, or can be set explicitly in the template using - * <option/> children, or using widget.set_select_options(SelectOption[]) + * <option/> children, or using widget.select_options = SelectOption[] */ select_options: Object, } @@ -83,7 +83,7 @@ export const Et2widgetWithSelectMixin = dedupeMixin((superclass) => { super(); - this.select_options = <StaticOptions[]>[]; + this.__select_options = <StaticOptions[]>[]; } /** @param {import('@lion/core').PropertyValues } changedProperties */ @@ -94,7 +94,8 @@ export const Et2widgetWithSelectMixin = dedupeMixin((superclass) => // If the ID changed (or was just set) find the select options if(changedProperties.has("id")) { - this.set_select_options(find_select_options(this)); + const options = find_select_options(this); + if (options.length) this.select_options = options; } // Add in actual option tags to the DOM based on the new select_options @@ -103,10 +104,8 @@ export const Et2widgetWithSelectMixin = dedupeMixin((superclass) => // Add in options as children to the target node if(this._optionTargetNode) { - // We use this.get_select_options() instead of this.select_options so children can override - // This is how the sub-types with static options (day of week, month, etc.) get their options in render(html`${this._emptyLabelTemplate()} - ${repeat(this.get_select_options(), (option : SelectOption) => option.value, this._optionTemplate.bind(this))}`, + ${repeat(<SelectOption[]>this.select_options, (option : SelectOption) => option.value, this._optionTemplate.bind(this))}`, this._optionTargetNode ); } @@ -143,10 +142,11 @@ export const Et2widgetWithSelectMixin = dedupeMixin((superclass) => /** * Set the select options * - * @param {SelectOption[]} new_options + * @param new_options */ - set_select_options(new_options : SelectOption[] | { [key : string] : string }) + set select_options(new_options : SelectOption[] | { [key : string] : string }) { + const old_options = this.__select_options; if(!Array.isArray(new_options)) { let fixed_options = []; @@ -154,17 +154,29 @@ export const Et2widgetWithSelectMixin = dedupeMixin((superclass) => { fixed_options.push({value: key, label: new_options[key]}); } - this.select_options = fixed_options; + this.__select_options = fixed_options; } else { - this.select_options = new_options; + this.__select_options = new_options; } + this.requestUpdate("select_options", old_options); } - get_select_options() + /** + * Set select options + * + * @deprecated assign to select_options + * @param new_options + */ + set_select_options(new_options : SelectOption[] | { [key : string] : string }) { - return this.select_options; + this.select_options = new_options; + } + + get select_options() + { + return this.__select_options; } /** @@ -245,7 +257,10 @@ export const Et2widgetWithSelectMixin = dedupeMixin((superclass) => { new_options = find_select_options(this, {}, new_options); } - this.set_select_options(new_options); + if (new_options.length) + { + this.select_options = new_options; + } } } return Et2WidgetWithSelect; diff --git a/api/js/etemplate/Et2Select/StaticOptions.ts b/api/js/etemplate/Et2Select/StaticOptions.ts index 641cb2533f..f3e17c4554 100644 --- a/api/js/etemplate/Et2Select/StaticOptions.ts +++ b/api/js/etemplate/Et2Select/StaticOptions.ts @@ -10,7 +10,9 @@ import {sprintf} from "../../egw_action/egw_action_common"; import {Et2SelectReadonly} from "./Et2SelectReadonly"; import {find_select_options, SelectOption} from "./FindSelectOptions"; -import {Et2WidgetWithSelect} from "./Et2Select"; +import {Et2Select, Et2WidgetWithSelect} from "./Et2Select"; + +export type Et2SelectWidgets = Et2Select | Et2WidgetWithSelect | Et2SelectReadonly; /** * Some options change, or are too complicated to have twice, so we get the @@ -25,7 +27,7 @@ import {Et2WidgetWithSelect} from "./Et2Select"; */ export class StaticOptions { - cached_server_side(widget : Et2WidgetWithSelect | Et2SelectReadonly, type : string, options_string) : SelectOption[] + cached_server_side(widget : Et2SelectWidgets, type : string, options_string) : SelectOption[] { // normalize options by removing trailing commas options_string = options_string.replace(/,+$/, ''); @@ -93,14 +95,14 @@ export class StaticOptions { if(widget.value && widget && widget.get_value() !== widget.value) { - egw.window.setTimeout(jQuery.proxy(function() + egw.window.setTimeout(function() { // Avoid errors if widget is destroyed before the timeout if(this.widget && typeof this.widget.id !== 'undefined') { this.widget.set_value(this.widget.options.value); } - }, {widget: widget}), 1); + }.bind({widget: widget}), 1); } } } @@ -108,7 +110,7 @@ export class StaticOptions } } - priority(widget : Et2WidgetWithSelect | Et2SelectReadonly) : SelectOption[] + priority(widget : Et2SelectWidgets) : SelectOption[] { return [ {value: "1", label: 'low'}, @@ -118,7 +120,7 @@ export class StaticOptions ]; } - bool(widget : Et2WidgetWithSelect | Et2SelectReadonly) : SelectOption[] + bool(widget : Et2SelectWidgets) : SelectOption[] { return [ {value: "0", label: 'no'}, @@ -126,7 +128,7 @@ export class StaticOptions ]; } - month(widget : Et2WidgetWithSelect | Et2SelectReadonly) : SelectOption[] + month(widget : Et2SelectWidgets) : SelectOption[] { return [ {value: "1", label: 'January'}, @@ -144,7 +146,7 @@ export class StaticOptions ]; } - number(widget : Et2WidgetWithSelect | Et2SelectReadonly, attrs) : SelectOption[] + number(widget : Et2SelectWidgets, attrs) : SelectOption[] { if(typeof attrs.other != 'object') { @@ -180,7 +182,7 @@ export class StaticOptions return options; } - percent(widget : Et2WidgetWithSelect | Et2SelectReadonly, attrs) : SelectOption[] + percent(widget : Et2SelectWidgets, attrs) : SelectOption[] { if(typeof attrs.other != 'object') { @@ -193,7 +195,7 @@ export class StaticOptions return this.number(widget, attrs); } - year(widget : Et2WidgetWithSelect | Et2SelectReadonly, attrs) : SelectOption[] + year(widget : Et2SelectWidgets, attrs) : SelectOption[] { if(typeof attrs.other != 'object') { @@ -206,13 +208,13 @@ export class StaticOptions return this.number(widget, attrs); } - day(widget : Et2WidgetWithSelect | Et2SelectReadonly, attrs) : SelectOption[] + day(widget : Et2SelectWidgets, attrs) : SelectOption[] { attrs.other = [1, 31, 1]; return this.number(widget, attrs); } - hour(widget : Et2WidgetWithSelect | Et2SelectReadonly, attrs) : SelectOption[] + hour(widget : Et2SelectWidgets, attrs) : SelectOption[] { var options = []; var timeformat = widget.egw().preference('common', 'timeformat'); @@ -228,13 +230,13 @@ export class StaticOptions return options; } - app(widget : Et2WidgetWithSelect | Et2SelectReadonly, attrs) : SelectOption[] + app(widget : Et2SelectWidgets | Et2Select, attrs) : SelectOption[] { var options = ',' + (attrs.other || []).join(','); return this.cached_server_side(widget, 'select-app', options); } - cat(widget : Et2WidgetWithSelect | Et2SelectReadonly, attrs) : SelectOption[] + cat(widget : Et2SelectWidgets, attrs) : SelectOption[] { // Add in application, if not there if(typeof attrs.other == 'undefined') @@ -252,33 +254,33 @@ export class StaticOptions return this.cached_server_side(widget, 'select-cat', options); } - country(widget : Et2WidgetWithSelect | Et2SelectReadonly, attrs) : SelectOption[] + country(widget : Et2SelectWidgets, attrs) : SelectOption[] { var options = ','; return this.cached_server_side(widget, 'select-country', options); } - state(widget : Et2WidgetWithSelect | Et2SelectReadonly, attrs) : SelectOption[] + state(widget : Et2SelectWidgets, attrs) : SelectOption[] { var options = attrs.country_code ? attrs.country_code : 'de'; return this.cached_server_side(widget, 'select-state', options); } - dow(widget : Et2WidgetWithSelect | Et2SelectReadonly, attrs) : SelectOption[] + dow(widget : Et2SelectWidgets, attrs) : SelectOption[] { var options = ',' + (attrs.other || []).join(','); return this.cached_server_side(widget, 'select-dow', options); } - lang(widget : Et2WidgetWithSelect | Et2SelectReadonly, attrs) : SelectOption[] + lang(widget : Et2SelectWidgets, attrs) : SelectOption[] { var options = ',' + (attrs.other || []).join(','); return this.cached_server_side(widget, 'select-lang', options); } - timezone(widget : Et2WidgetWithSelect | Et2SelectReadonly, attrs) : SelectOption[] + timezone(widget : Et2SelectWidgets, attrs) : SelectOption[] { var options = ',' + (attrs.other || []).join(','); return this.cached_server_side(widget, 'select-timezone', options); } -} +} \ No newline at end of file