mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-11-22 07:53:39 +01:00
Change Et2Checkbox to behave closer to legacy et2_widget_checkbox and thereby fixing all sorts of errors with it.
Fix vfsSelectUI to be able to select files again with click on the row and only submit selected files. Also change Et2Widget.iterateOver and legacy et2_widget.interateOver to be called with new web-component classes like Et2Checkbox. Also make Et2Widget matching all widgets by default like et2_widget. Remove legacy et2_widget_checkbox code.
This commit is contained in:
parent
35cff9c978
commit
ba35be1d86
@ -17,6 +17,11 @@ import shoelace from "../Styles/shoelace";
|
||||
|
||||
export class Et2Checkbox extends Et2InputWidget(SlCheckbox)
|
||||
{
|
||||
/**
|
||||
* Value to set checkbox in (third) indeterminate state
|
||||
*/
|
||||
static readonly INDETERMINATE = '***undefined***';
|
||||
|
||||
static get styles()
|
||||
{
|
||||
return [
|
||||
@ -53,6 +58,9 @@ export class Et2Checkbox extends Et2InputWidget(SlCheckbox)
|
||||
constructor()
|
||||
{
|
||||
super();
|
||||
|
||||
this.selectedValue = 'true';
|
||||
this.unselectedValue = '';
|
||||
}
|
||||
|
||||
connectedCallback()
|
||||
@ -81,40 +89,40 @@ export class Et2Checkbox extends Et2InputWidget(SlCheckbox)
|
||||
}
|
||||
}
|
||||
|
||||
get value()
|
||||
get value() : string | boolean
|
||||
{
|
||||
if(this.checked && this.selectedValue)
|
||||
{
|
||||
return this.selectedValue;
|
||||
}
|
||||
if(!this.checked && this.unselectedValue)
|
||||
{
|
||||
return this.unselectedValue;
|
||||
}
|
||||
return this.checked + "";
|
||||
return this.indeterminate ? undefined :
|
||||
(this.checked ? this.selectedValue : this.unselectedValue);
|
||||
}
|
||||
|
||||
set value(new_value : string | boolean)
|
||||
{
|
||||
this.requestUpdate("checked");
|
||||
this.indeterminate = false;
|
||||
if(typeof new_value === "boolean" || !this.selectedValue)
|
||||
|
||||
if(typeof new_value === "boolean")
|
||||
{
|
||||
this.checked = <boolean>new_value;
|
||||
return;
|
||||
this.checked = new_value;
|
||||
}
|
||||
if(this.selectedValue && new_value == this.selectedValue)
|
||||
else if(new_value == this.selectedValue)
|
||||
{
|
||||
this.checked = true;
|
||||
}
|
||||
else if(this.unselectedValue && new_value == this.unselectedValue)
|
||||
else if(new_value == this.unselectedValue)
|
||||
{
|
||||
this.checked = false;
|
||||
}
|
||||
else
|
||||
// concept of an indeterminate value did not exist in eT2 and set value gets called with all kind of truthy of falsy values
|
||||
// therefore we can NOT set everything not matching our (un)selectedValue to indeterminate!
|
||||
// For now, we only do that for an explicit Et2Checkbox.INDETERMINATE value
|
||||
else if (new_value === Et2Checkbox.INDETERMINATE)
|
||||
{
|
||||
this.indeterminate = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.checked = !!new_value;
|
||||
}
|
||||
}
|
||||
|
||||
private get _labelNode()
|
||||
|
@ -799,7 +799,9 @@ const Et2WidgetMixin = <T extends Constructor>(superClass : T) =>
|
||||
|
||||
iterateOver(_callback : Function, _context, _type)
|
||||
{
|
||||
if(typeof _type == "undefined" || _type == et2_widget || et2_implements_registry[_type] && et2_implements_registry[_type](this))
|
||||
if (typeof _type === "undefined" || _type === et2_widget || _type === Et2Widget ||
|
||||
typeof _type === 'function' && this instanceof _type ||
|
||||
et2_implements_registry[_type] && et2_implements_registry[_type](this))
|
||||
{
|
||||
_callback.call(_context, this);
|
||||
}
|
||||
|
@ -15,6 +15,7 @@
|
||||
import {egw, IegwAppLocal} from "../jsapi/egw_global";
|
||||
import {et2_checkType, et2_no_init, et2_validateAttrib} from "./et2_core_common";
|
||||
import {et2_implements_registry} from "./et2_core_interfaces";
|
||||
import {Et2Widget} from "./Et2Widget/Et2Widget";
|
||||
|
||||
export class ClassWithInterfaces
|
||||
{
|
||||
@ -49,6 +50,10 @@ export class ClassWithInterfaces
|
||||
{
|
||||
return this.implements(_class_or_interfacename);
|
||||
}
|
||||
if (_class_or_interfacename === Et2Widget)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return this instanceof _class_or_interfacename;
|
||||
}
|
||||
}
|
||||
@ -273,5 +278,4 @@ export class ClassWithAttributes extends ClassWithInterfaces
|
||||
|
||||
return attributes;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -9,286 +9,9 @@
|
||||
* @copyright Nathan Gray 2011
|
||||
*/
|
||||
|
||||
/*egw:uses
|
||||
/vendor/bower-asset/jquery/dist/jquery.js;
|
||||
et2_core_inputWidget;
|
||||
et2_core_valueWidget;
|
||||
*/
|
||||
|
||||
import {et2_register_widget, WidgetConfig} from "./et2_core_widget";
|
||||
import {et2_inputWidget} from "./et2_core_inputWidget";
|
||||
import {ClassWithAttributes} from "./et2_core_inheritance";
|
||||
import {et2_IDetachedDOM} from "./et2_core_interfaces";
|
||||
import {Et2Checkbox} from "./Et2Checkbox/Et2Checkbox";
|
||||
|
||||
/**
|
||||
* Class which implements the "checkbox" XET-Tag
|
||||
*
|
||||
* @augments et2_inputWidget
|
||||
* @deprecated use Et2Checkbox
|
||||
*/
|
||||
export class et2_checkbox extends et2_inputWidget
|
||||
{
|
||||
static readonly _attributes : any = {
|
||||
"selected_value": {
|
||||
"name": "Set value",
|
||||
"type": "string",
|
||||
"default": "true",
|
||||
"description": "Value when checked"
|
||||
},
|
||||
"unselected_value": {
|
||||
"name": "Unset value",
|
||||
"type": "string",
|
||||
"default": "",
|
||||
"description": "Value when not checked"
|
||||
},
|
||||
"ro_true": {
|
||||
"name": "Read only selected",
|
||||
"type": "string",
|
||||
"default": "X ",
|
||||
"description": "What should be displayed when readonly and selected"
|
||||
},
|
||||
"ro_false": {
|
||||
"name": "Read only unselected",
|
||||
"type": "string",
|
||||
"default": "",
|
||||
"description": "What should be displayed when readonly and not selected"
|
||||
},
|
||||
"value": {
|
||||
// Stop framework from messing with value
|
||||
"type": "any"
|
||||
},
|
||||
"toggle_on": {
|
||||
"name": "Toggle on caption",
|
||||
"type": "string",
|
||||
"default": "",
|
||||
"description": "String caption to show for ON status",
|
||||
"translate": true
|
||||
},
|
||||
"toggle_off": {
|
||||
"name": "Toggle off caption",
|
||||
"type": "string",
|
||||
"default": "",
|
||||
"description": "String caption to show OFF status",
|
||||
"translate": true
|
||||
}
|
||||
};
|
||||
|
||||
public static readonly legacyOptions : string[] = ["selected_value", "unselected_value", "ro_true", "ro_false"];
|
||||
input : JQuery = null;
|
||||
toggle : JQuery = null;
|
||||
value : string | boolean;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @memberOf et2_checkbox
|
||||
*/
|
||||
constructor(_parent, _attrs? : WidgetConfig, _child? : object)
|
||||
{
|
||||
// Call the inherited constructor
|
||||
super(_parent, _attrs, ClassWithAttributes.extendAttributes(et2_checkbox._attributes, _child || {}));
|
||||
this.input = null;
|
||||
this.createInputWidget();
|
||||
}
|
||||
|
||||
createInputWidget()
|
||||
{
|
||||
this.input = jQuery(document.createElement("input")).attr("type", "checkbox");
|
||||
|
||||
this.input.addClass("et2_checkbox");
|
||||
|
||||
if (this.options.toggle_on || this.options.toggle_off)
|
||||
{
|
||||
let self = this;
|
||||
// checkbox container
|
||||
this.toggle = jQuery(document.createElement('span'))
|
||||
.addClass('et2_checkbox_slideSwitch')
|
||||
.append(this.input);
|
||||
// update switch status on change
|
||||
this.input.change(function(){
|
||||
self.getValue();
|
||||
return true;
|
||||
});
|
||||
// switch container
|
||||
let area = jQuery(document.createElement('span')).addClass('slideSwitch_container').appendTo(this.toggle);
|
||||
// on span tag
|
||||
let on = jQuery(document.createElement('span')).addClass('on').appendTo(area);
|
||||
// off span tag
|
||||
let off = jQuery(document.createElement('span')).addClass('off').appendTo(area);
|
||||
on.text(this.options.toggle_on);
|
||||
off.text(this.options.toggle_off);
|
||||
|
||||
// handle a tag
|
||||
jQuery(document.createElement('a')).appendTo(area);
|
||||
this.setDOMNode(this.toggle[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.setDOMNode(this.input[0]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Override default to place checkbox before label, if there is no %s in the label
|
||||
*
|
||||
* @param {string} label
|
||||
*/
|
||||
set_label(label) {
|
||||
if(label.length && label.indexOf('%s') < 0)
|
||||
{
|
||||
label = '%s'+label;
|
||||
}
|
||||
super.set_label(label);
|
||||
jQuery(this.getSurroundings().getWidgetSurroundings()).addClass('et2_checkbox_label');
|
||||
}
|
||||
|
||||
/**
|
||||
* Override default to match against set/unset value
|
||||
*
|
||||
* @param {string|boolean} _value
|
||||
*/
|
||||
set_value(_value : string | boolean)
|
||||
{
|
||||
// in php, our database storage and et2_checkType(): "0" == false
|
||||
if (_value === "0" && this.options.selected_value != "0")
|
||||
{
|
||||
_value = false;
|
||||
}
|
||||
if(_value != this.value) {
|
||||
if(_value == this.options.selected_value ||
|
||||
_value && this.options.selected_value == this.attributes["selected_value"]["default"] &&
|
||||
_value != this.options.unselected_value) {
|
||||
if (this.options.toggle_on || this.options.toggle_off) this.toggle.addClass('switchOn');
|
||||
this.input.prop("checked", true);
|
||||
} else {
|
||||
this.input.prop("checked", false);
|
||||
if (this.options.toggle_on || this.options.toggle_off) this.toggle.removeClass('switchOn');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable checkbox on runtime
|
||||
*
|
||||
* @param {boolean} _ro
|
||||
*/
|
||||
set_readonly(_ro)
|
||||
{
|
||||
jQuery(this.getDOMNode()).attr('disabled', _ro);
|
||||
this.input.prop('disabled', _ro);
|
||||
}
|
||||
|
||||
/**
|
||||
* Override default to return unchecked value
|
||||
*/
|
||||
getValue()
|
||||
{
|
||||
if(this.input.prop("checked")) {
|
||||
if (this.options.toggle_on || this.options.toggle_off) this.toggle.addClass('switchOn');
|
||||
return this.options.selected_value;
|
||||
} else {
|
||||
if (this.options.toggle_on || this.options.toggle_off) this.toggle.removeClass('switchOn');
|
||||
return this.options.unselected_value;
|
||||
}
|
||||
}
|
||||
|
||||
set_disabled(_value)
|
||||
{
|
||||
let parentNode = jQuery(this.getDOMNode()).parent();
|
||||
if (parentNode[0] && parentNode[0].nodeName == "label" && parentNode.hasClass('.et2_checkbox_label'))
|
||||
{
|
||||
if (_value)
|
||||
{
|
||||
parentNode.hide();
|
||||
}
|
||||
else
|
||||
{
|
||||
parentNode.show();
|
||||
}
|
||||
}
|
||||
super.set_disabled(_value);
|
||||
}
|
||||
}
|
||||
et2_register_widget(et2_checkbox, ["checkbox"]);
|
||||
|
||||
/**
|
||||
* et2_checkbox_ro is the dummy readonly implementation of the checkbox
|
||||
* @augments et2_checkbox
|
||||
*/
|
||||
export class et2_checkbox_ro extends et2_checkbox implements et2_IDetachedDOM
|
||||
{
|
||||
/**
|
||||
* Ignore unset value
|
||||
*/
|
||||
static readonly _attributes : any = {
|
||||
"unselected_value": {
|
||||
"ignore": true
|
||||
}
|
||||
};
|
||||
|
||||
span : JQuery = null;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @memberOf et2_checkbox_ro
|
||||
*/
|
||||
constructor(_parent, _attrs? : WidgetConfig, _child? : object)
|
||||
{
|
||||
// Call the inherited constructor
|
||||
super(_parent, _attrs, ClassWithAttributes.extendAttributes(et2_checkbox_ro._attributes, _child || {}));
|
||||
|
||||
this.value = "";
|
||||
this.span = jQuery(document.createElement("span"))
|
||||
.addClass("et2_checkbox_ro");
|
||||
|
||||
this.setDOMNode(this.span[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* note: checkbox is checked if even there is a value but not only if the _value is only "true"
|
||||
* it's an exceptional validation for cases that we pass non boolean values as checkbox _value
|
||||
*
|
||||
* @param {string|boolean} _value
|
||||
*/
|
||||
set_value(_value)
|
||||
{
|
||||
if(_value == this.options.selected_value ||_value && this.options.selected_value == this.attributes["selected_value"]["default"] &&
|
||||
_value != this.options.unselected_value) {
|
||||
this.span.text(this.options.ro_true);
|
||||
this.value = _value;
|
||||
} else {
|
||||
this.span.text(this.options.ro_false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Code for implementing et2_IDetachedDOM
|
||||
*
|
||||
* @param {array} _attrs
|
||||
*/
|
||||
getDetachedAttributes(_attrs)
|
||||
{
|
||||
_attrs.push("value", "class");
|
||||
}
|
||||
|
||||
getDetachedNodes()
|
||||
{
|
||||
return [this.span[0]];
|
||||
}
|
||||
|
||||
setDetachedAttributes(_nodes, _values)
|
||||
{
|
||||
// Update the properties
|
||||
if (typeof _values["value"] != "undefined")
|
||||
{
|
||||
this.span = jQuery(_nodes[0]);
|
||||
this.set_value(_values["value"]);
|
||||
}
|
||||
|
||||
if (typeof _values["class"] != "undefined")
|
||||
{
|
||||
_nodes[0].setAttribute("class", _values["class"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
et2_register_widget(et2_checkbox_ro, ["checkbox_ro"]);
|
||||
export class et2_checkbox extends Et2Checkbox {}
|
@ -15,10 +15,9 @@
|
||||
*/
|
||||
|
||||
import {et2_DOMWidget} from "./et2_core_DOMWidget";
|
||||
import {et2_createWidget, et2_register_widget, WidgetConfig} from "./et2_core_widget";
|
||||
import {et2_register_widget, WidgetConfig} from "./et2_core_widget";
|
||||
import {ClassWithAttributes} from "./et2_core_inheritance";
|
||||
import {egw_getObjectManager, egwActionObject, egwActionObjectManager} from '../egw_action/egw_action.js';
|
||||
import {et2_checkbox} from "./et2_widget_checkbox";
|
||||
import {et2_IInput} from "./et2_core_interfaces";
|
||||
import {egw} from "../jsapi/egw_global";
|
||||
import {egwIsMobile} from "../egw_action/egw_action_common.js";
|
||||
@ -26,7 +25,6 @@ import {Et2Dialog} from "./Et2Dialog/Et2Dialog";
|
||||
import {Et2DropdownButton} from "./Et2DropdownButton/Et2DropdownButton";
|
||||
import {loadWebComponent} from "./Et2Widget/Et2Widget";
|
||||
import interact from "@interactjs/interactjs";
|
||||
import Sortable from "sortablejs/modular/sortable.complete.esm.js";
|
||||
import {Et2Button} from "./Et2Button/Et2Button";
|
||||
import {Et2Checkbox} from "./Et2Checkbox/Et2Checkbox";
|
||||
|
||||
|
@ -110,7 +110,6 @@ import './et2_widget_textbox';
|
||||
import './et2_widget_number';
|
||||
import './et2_widget_url';
|
||||
import './et2_widget_selectbox';
|
||||
import './et2_widget_checkbox';
|
||||
import './et2_widget_radiobox';
|
||||
import './et2_widget_date';
|
||||
import './et2_widget_dialog';
|
||||
|
@ -16,11 +16,10 @@ import {EgwApp} from "../jsapi/egw_app";
|
||||
import {et2_vfs, et2_vfsPath, et2_vfsSelect} from "./et2_widget_vfs";
|
||||
import {egw} from "../jsapi/egw_global";
|
||||
import {et2_file} from "./et2_widget_file";
|
||||
import {Et2Textbox} from "./Et2Textbox/Et2Textbox";
|
||||
import {Et2Button} from "./Et2Button/Et2Button";
|
||||
import {Et2Select} from "./Et2Select/Et2Select";
|
||||
import {et2_checkbox} from "./et2_widget_checkbox";
|
||||
import {Et2Dialog} from "./Et2Dialog/Et2Dialog";
|
||||
import {Et2Checkbox} from "./Et2Checkbox/Et2Checkbox";
|
||||
|
||||
|
||||
/**
|
||||
@ -266,11 +265,11 @@ export class vfsSelectUI extends EgwApp
|
||||
let file = widget.value.name;
|
||||
widget.getParent().iterateOver(function(widget)
|
||||
{
|
||||
if(widget.options.selected_value == file)
|
||||
if(widget.options.selectedValue === file)
|
||||
{
|
||||
widget.set_value(widget.get_value() == file ? widget.options.unselected_value : file);
|
||||
widget.set_value(widget.get_value() === file ? widget.options.unselectedValue : file);
|
||||
}
|
||||
}, null, et2_checkbox);
|
||||
}, null, Et2Checkbox);
|
||||
|
||||
}
|
||||
// Stop event or it will toggle back off
|
||||
|
Loading…
Reference in New Issue
Block a user