forked from extern/egroupware
Deal with some IDE warnings
better documentation of things tried
This commit is contained in:
parent
7ab60918f4
commit
4ed888476c
@ -45,6 +45,18 @@ export class Et2SelectReadonly extends Et2Widget(LitElement) implements et2_IDet
|
||||
|
||||
transformAttributes(_attrs)
|
||||
{
|
||||
/*
|
||||
TODO: Check with more / different nextmatch data to see if this becomes faster.
|
||||
Currently it's faster for the nextmatch to re-do transformAttributes() and find_select_options()
|
||||
on every row than it is to use widget.clone()
|
||||
|
||||
// If there's no parent, there's a good chance we're in a nextmatch row so skip the transform
|
||||
if(!this.getParent())
|
||||
{
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
super.transformAttributes(_attrs);
|
||||
|
||||
let sel_options = find_select_options(this, _attrs['select_options'], _attrs);
|
||||
|
@ -41,11 +41,13 @@ const Et2WidgetMixin = (superClass) =>
|
||||
class Et2WidgetClass extends superClass implements et2_IDOMNode
|
||||
{
|
||||
|
||||
/** et2_widget compatability **/
|
||||
protected _mgrs : et2_arrayMgr[] = [];
|
||||
protected _parent : Et2WidgetClass | et2_widget | null = null;
|
||||
private _inst : etemplate2 | null = null;
|
||||
private supportedWidgetClasses = [];
|
||||
|
||||
/** et2_widget compatability **/
|
||||
// @ts-ignore Some legacy widgets check their parent to see whats allowed
|
||||
public supportedWidgetClasses = [];
|
||||
|
||||
/**
|
||||
* If we put the widget somewhere other than as a child of its parent, we need to record that so
|
||||
@ -297,7 +299,6 @@ const Et2WidgetMixin = (superClass) =>
|
||||
*/
|
||||
set id(value)
|
||||
{
|
||||
let oldValue = this._widget_id;
|
||||
this._widget_id = value;
|
||||
let dom_id = "";
|
||||
if(this._widget_id)
|
||||
@ -358,7 +359,7 @@ const Et2WidgetMixin = (superClass) =>
|
||||
if(typeof this.onclick == 'function')
|
||||
{
|
||||
// Make sure function gets a reference to the widget, splice it in as 2. argument if not
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
let args = Array.prototype.slice.call(arguments);
|
||||
if(args.indexOf(this) == -1)
|
||||
{
|
||||
args.splice(1, 0, this);
|
||||
@ -390,10 +391,10 @@ const Et2WidgetMixin = (superClass) =>
|
||||
loadFromXML(_node)
|
||||
{
|
||||
// Load the child nodes.
|
||||
for(var i = 0; i < _node.childNodes.length; i++)
|
||||
for(let i = 0; i < _node.childNodes.length; i++)
|
||||
{
|
||||
var node = _node.childNodes[i];
|
||||
var widgetType = node.nodeName.toLowerCase();
|
||||
let node = _node.childNodes[i];
|
||||
let widgetType = node.nodeName.toLowerCase();
|
||||
|
||||
if(widgetType == "#comment")
|
||||
{
|
||||
@ -430,7 +431,7 @@ const Et2WidgetMixin = (superClass) =>
|
||||
*/
|
||||
createElementFromNode(_node, _name?)
|
||||
{
|
||||
var attributes = {};
|
||||
let attributes = {};
|
||||
|
||||
// Parse the "readonly" and "type" flag for this element here, as they
|
||||
// determine which constructor is used
|
||||
@ -442,7 +443,7 @@ const Et2WidgetMixin = (superClass) =>
|
||||
typeof this.readonly !== "undefined" ? this.readonly : false) : false;
|
||||
|
||||
// Check to see if modifications change type
|
||||
var modifications = this.getArrayMgr("modifications");
|
||||
let modifications = this.getArrayMgr("modifications");
|
||||
if(modifications && _node.getAttribute("id"))
|
||||
{
|
||||
let entry : any = modifications.getEntry(_node.getAttribute("id"));
|
||||
@ -475,12 +476,12 @@ const Et2WidgetMixin = (superClass) =>
|
||||
_nodeName = attributes["type"] = this.getArrayMgr('content').expandName(_nodeName);
|
||||
}
|
||||
|
||||
let widget = null;
|
||||
let widget;
|
||||
if(undefined == window.customElements.get(_nodeName))
|
||||
{
|
||||
// Get the constructor - if the widget is readonly, use the special "_ro"
|
||||
// constructor if it is available
|
||||
var constructor = et2_registry[typeof et2_registry[_nodeName] == "undefined" ? 'placeholder' : _nodeName];
|
||||
let constructor = et2_registry[typeof et2_registry[_nodeName] == "undefined" ? 'placeholder' : _nodeName];
|
||||
if(readonly === true && typeof et2_registry[_nodeName + "_ro"] != "undefined")
|
||||
{
|
||||
constructor = et2_registry[_nodeName + "_ro"];
|
||||
@ -522,6 +523,9 @@ const Et2WidgetMixin = (superClass) =>
|
||||
* and adds the given attributes to the _target associative array. This
|
||||
* function also parses the legacyOptions.
|
||||
*
|
||||
* N.B. This is only used for legacy widgets. WebComponents use transformAttributes() and
|
||||
* do their own handling of attributes.
|
||||
*
|
||||
* @param _attrsObj is the XML DOM attributes object
|
||||
* @param {object} _target is the object to which the attributes should be written.
|
||||
* @param {et2_widget} _proto prototype with attributes and legacyOptions attribute
|
||||
@ -535,22 +539,21 @@ const Et2WidgetMixin = (superClass) =>
|
||||
}
|
||||
|
||||
// Iterate over the given attributes and parse them
|
||||
var mgr = this.getArrayMgr("content");
|
||||
for(var i = 0; i < _attrsObj.length; i++)
|
||||
let mgr = this.getArrayMgr("content");
|
||||
for(let i = 0; i < _attrsObj.length; i++)
|
||||
{
|
||||
var attrName = _attrsObj[i].name;
|
||||
var attrValue = _attrsObj[i].value;
|
||||
let attrName = _attrsObj[i].name;
|
||||
let attrValue = _attrsObj[i].value;
|
||||
|
||||
// Special handling for the legacy options
|
||||
if(attrName == "options" && _proto.constructor.legacyOptions && _proto.constructor.legacyOptions.length > 0)
|
||||
{
|
||||
let legacy = _proto.constructor.legacyOptions || [];
|
||||
let attrs = et2_attribute_registry[Object.getPrototypeOf(_proto).constructor.name] || {};
|
||||
// Check for modifications on legacy options here. Normal modifications
|
||||
// are handled in widget constructor, but it's too late for legacy options then
|
||||
if(_target.id && this.getArrayMgr("modifications").getEntry(_target.id))
|
||||
{
|
||||
var mod : any = this.getArrayMgr("modifications").getEntry(_target.id);
|
||||
let mod : any = this.getArrayMgr("modifications").getEntry(_target.id);
|
||||
if(typeof mod.options != "undefined")
|
||||
{
|
||||
attrValue = _attrsObj[i].value = mod.options;
|
||||
@ -563,9 +566,9 @@ const Et2WidgetMixin = (superClass) =>
|
||||
}
|
||||
|
||||
// Parse the legacy options (as a string, other types not allowed)
|
||||
var splitted = et2_csvSplit(attrValue + "");
|
||||
let splitted = et2_csvSplit(attrValue + "");
|
||||
|
||||
for(var j = 0; j < splitted.length && j < legacy.length; j++)
|
||||
for(let j = 0; j < splitted.length && j < legacy.length; j++)
|
||||
{
|
||||
// Blank = not set, unless there's more legacy options provided after
|
||||
if(splitted[j].trim().length === 0 && legacy.length >= splitted.length)
|
||||
@ -587,7 +590,7 @@ const Et2WidgetMixin = (superClass) =>
|
||||
attrValue = splitted.slice(j);
|
||||
}
|
||||
|
||||
var attr = et2_attribute_registry[_proto.constructor.name][legacy[j]] || {};
|
||||
let attr = et2_attribute_registry[_proto.constructor.name][legacy[j]] || {};
|
||||
|
||||
// If the attribute is marked as boolean, parse the
|
||||
// expression as bool expression.
|
||||
@ -612,7 +615,7 @@ const Et2WidgetMixin = (superClass) =>
|
||||
let attrs = et2_attribute_registry[_proto.constructor.name] || {};
|
||||
if(mgr != null && typeof attrs[attrName] != "undefined")
|
||||
{
|
||||
var attr = attrs[attrName];
|
||||
let attr = attrs[attrName];
|
||||
|
||||
// If the attribute is marked as boolean, parse the
|
||||
// expression as bool expression.
|
||||
@ -673,9 +676,11 @@ const Et2WidgetMixin = (superClass) =>
|
||||
* rest themselves with their normal lifecycle (especially connectedCallback(), which is kind
|
||||
* of the equivalent of doLoadingFinished()
|
||||
*/
|
||||
// @ts-ignore this is not an et2_widget, so getDOMNode(this) is bad
|
||||
if(!this._parent_node && this.getParent() instanceof et2_widget && (<et2_DOMWidget>this.getParent()).getDOMNode(this) != this.parentNode)
|
||||
{
|
||||
this.getParent().getDOMNode(this).append(this);
|
||||
// @ts-ignore this is not an et2_widget, and Et2Widget is not a Node
|
||||
(<et2_DOMWidget>this.getParent()).getDOMNode(this).append(this);
|
||||
}
|
||||
|
||||
// An empty text node causes problems with legacy widget children
|
||||
@ -708,9 +713,9 @@ const Et2WidgetMixin = (superClass) =>
|
||||
|
||||
let check_children = children =>
|
||||
{
|
||||
for(var i = 0; i < children.length; i++)
|
||||
for(let i = 0; i < children.length; i++)
|
||||
{
|
||||
var elem = children[i].getWidgetById(_id);
|
||||
let elem = children[i].getWidgetById(_id);
|
||||
|
||||
if(elem != null)
|
||||
{
|
||||
@ -719,9 +724,9 @@ const Et2WidgetMixin = (superClass) =>
|
||||
}
|
||||
if(this.id && _id.indexOf('[') > -1 && children.length)
|
||||
{
|
||||
var ids = (new et2_arrayMgr()).explodeKey(_id);
|
||||
var widget : Et2WidgetClass = this;
|
||||
for(var i = 0; i < ids.length && widget !== null; i++)
|
||||
let ids = (new et2_arrayMgr()).explodeKey(_id);
|
||||
let widget : Et2WidgetClass = this;
|
||||
for(let i = 0; i < ids.length && widget !== null; i++)
|
||||
{
|
||||
widget = widget.getWidgetById(ids[i]);
|
||||
}
|
||||
@ -746,7 +751,7 @@ const Et2WidgetMixin = (superClass) =>
|
||||
}
|
||||
if(parent)
|
||||
{
|
||||
parent.append(this);
|
||||
parent.append(<Node><unknown>this);
|
||||
this._parent_node = parent;
|
||||
}
|
||||
}
|
||||
@ -763,14 +768,12 @@ const Et2WidgetMixin = (superClass) =>
|
||||
this.checkCreateNamespace();
|
||||
}
|
||||
}
|
||||
// @ts-ignore
|
||||
this._parent.addChild(this);
|
||||
}
|
||||
|
||||
getParent() : Et2WidgetClass | et2_widget
|
||||
{
|
||||
let parentNode = this.parentNode;
|
||||
|
||||
// If parent is an old et2_widget, use it
|
||||
if(this._parent)
|
||||
{
|
||||
return this._parent;
|
||||
@ -787,6 +790,9 @@ const Et2WidgetMixin = (superClass) =>
|
||||
}
|
||||
if(child instanceof et2_widget)
|
||||
{
|
||||
// Type of et2_widget._parent is et2_widget, not Et2Widget. This might cause problems, but they
|
||||
// should be fixed by getting rid of the legacy widget with problems
|
||||
// @ts-ignore
|
||||
child._parent = this;
|
||||
|
||||
// During legacy widget creation, the child's DOM node won't be available yet.
|
||||
@ -794,6 +800,7 @@ const Et2WidgetMixin = (superClass) =>
|
||||
let child_node = null;
|
||||
try
|
||||
{
|
||||
//@ts-ignore Technically getDOMNode() is from et2_DOMWidget
|
||||
child_node = typeof child.getDOMNode !== "undefined" ? child.getDOMNode(child) : null;
|
||||
}
|
||||
catch(e)
|
||||
@ -846,7 +853,7 @@ const Et2WidgetMixin = (superClass) =>
|
||||
}
|
||||
|
||||
// Create the copy
|
||||
var copy = <Et2WidgetClass>this.cloneNode();
|
||||
let copy = <Et2WidgetClass>this.cloneNode();
|
||||
copy.id = this._widget_id;
|
||||
|
||||
if(_parent)
|
||||
@ -870,7 +877,7 @@ const Et2WidgetMixin = (superClass) =>
|
||||
}
|
||||
|
||||
// Create a clone of all child widgets of the given object
|
||||
for(var i = 0; i < this.getChildren().length; i++)
|
||||
for(let i = 0; i < this.getChildren().length; i++)
|
||||
{
|
||||
this.getChildren()[i].clone(copy);
|
||||
}
|
||||
@ -934,7 +941,7 @@ const Et2WidgetMixin = (superClass) =>
|
||||
|
||||
// Add all managers of this object to the result, if they have not already
|
||||
// been set in the result
|
||||
for(var key in this._mgrs)
|
||||
for(let key in this._mgrs)
|
||||
{
|
||||
if(typeof _mgrs[key] == "undefined")
|
||||
{
|
||||
@ -961,11 +968,11 @@ const Et2WidgetMixin = (superClass) =>
|
||||
checkCreateNamespace()
|
||||
{
|
||||
// Get the content manager
|
||||
var mgrs = this.getArrayMgrs();
|
||||
let mgrs = this.getArrayMgrs();
|
||||
|
||||
for(var key in mgrs)
|
||||
for(let key in mgrs)
|
||||
{
|
||||
var mgr = mgrs[key];
|
||||
let mgr = mgrs[key];
|
||||
|
||||
// Get the original content manager if we have already created a
|
||||
// perspective for this node
|
||||
@ -975,7 +982,7 @@ const Et2WidgetMixin = (superClass) =>
|
||||
}
|
||||
|
||||
// Check whether the manager has a namespace for the id of this object
|
||||
var entry = mgr.getEntry(this.id);
|
||||
let entry = mgr.getEntry(this.id);
|
||||
if(typeof entry === 'object' && entry !== null || this.id)
|
||||
{
|
||||
// The content manager has an own node for this object, so
|
||||
@ -1042,7 +1049,7 @@ const Et2WidgetMixin = (superClass) =>
|
||||
*/
|
||||
getPath()
|
||||
{
|
||||
var path = this.getArrayMgr("content")?.getPath() ?? [];
|
||||
let path = this.getArrayMgr("content")?.getPath() ?? [];
|
||||
|
||||
// Prevent namespaced widgets with value from going an extra layer deep
|
||||
if(this.id && this._createNamespace() && path[path.length - 1] == this.id)
|
||||
@ -1066,11 +1073,11 @@ const Et2WidgetMixin = (superClass) =>
|
||||
}
|
||||
|
||||
// Get the window this object belongs to
|
||||
var wnd = null;
|
||||
let wnd = null;
|
||||
// @ts-ignore Technically this doesn't have implements(), but it's mixed in
|
||||
if(this.implements(et2_IDOMNode))
|
||||
{
|
||||
var node = (<et2_IDOMNode><unknown>this).getDOMNode();
|
||||
let node = (<et2_IDOMNode><unknown>this).getDOMNode();
|
||||
if(node && node.ownerDocument)
|
||||
{
|
||||
wnd = node.ownerDocument.parentNode || node.ownerDocument.defaultView;
|
||||
@ -1080,7 +1087,7 @@ const Et2WidgetMixin = (superClass) =>
|
||||
// If we're the root object, return the phpgwapi API instance
|
||||
return typeof egw === "function" ? egw('phpgwapi', wnd) : null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Add some more stuff in
|
||||
applyMixins(Et2WidgetClass, [ClassWithInterfaces]);
|
||||
@ -1093,7 +1100,9 @@ export const Et2Widget = dedupeMixin(Et2WidgetMixin);
|
||||
* Load a Web Component
|
||||
* @param _nodeName
|
||||
* @param _template_node
|
||||
* @param parent Parent widget
|
||||
*/
|
||||
// @ts-ignore Et2Widget is I guess not the right type
|
||||
export function loadWebComponent(_nodeName : string, _template_node, parent : Et2Widget | et2_widget) : HTMLElement
|
||||
{
|
||||
// @ts-ignore
|
||||
@ -1106,7 +1115,6 @@ export function loadWebComponent(_nodeName : string, _template_node, parent : Et
|
||||
throw Error("Unknown or unregistered WebComponent '" + _nodeName + "', could not find class");
|
||||
}
|
||||
widget.setParent(parent);
|
||||
var mgr = widget.getArrayMgr("content");
|
||||
|
||||
// Set read-only. Doesn't really matter if it's a ro widget, but otherwise it needs set
|
||||
widget.readOnly = parent.getArrayMgr("readonlys") ?
|
||||
@ -1222,7 +1230,8 @@ function transformAttributes(widget, mgr : et2_arrayMgr, attributes)
|
||||
* }
|
||||
* `];
|
||||
* }
|
||||
* @param image_name
|
||||
* @param image_name Name of the image
|
||||
* @param app_name Optional, image is from an app instead of api
|
||||
* @returns {CSSResult}
|
||||
*/
|
||||
export function cssImage(image_name : string, app_name? : string)
|
||||
|
@ -26,17 +26,17 @@ import {et2_compilePHPExpression} from "./et2_core_phpExpressionCompiler";
|
||||
*/
|
||||
export class et2_arrayMgr
|
||||
{
|
||||
splitIds: boolean = true;
|
||||
public data: object;
|
||||
splitIds : boolean = true;
|
||||
public data : object;
|
||||
// Holds information about the current perspective
|
||||
public perspectiveData: { owner: et2_widget; row: number; key: string } = {
|
||||
public perspectiveData : { owner : et2_widget; row : number; key : string } = {
|
||||
"owner": null,
|
||||
"key": null,
|
||||
"row": null
|
||||
};
|
||||
protected static compiledExpressions: object = {};
|
||||
private readonly _parentMgr: et2_arrayMgr;
|
||||
protected readOnly: boolean = false;
|
||||
protected static compiledExpressions : object = {};
|
||||
private readonly _parentMgr : et2_arrayMgr;
|
||||
protected readOnly : boolean = false;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
@ -45,8 +45,10 @@ export class et2_arrayMgr
|
||||
* @param _data
|
||||
* @param _parentMgr
|
||||
*/
|
||||
constructor(_data: object = {}, _parentMgr?: et2_arrayMgr) {
|
||||
if (typeof _parentMgr == "undefined") {
|
||||
constructor(_data : object = {}, _parentMgr? : et2_arrayMgr)
|
||||
{
|
||||
if(typeof _parentMgr == "undefined")
|
||||
{
|
||||
_parentMgr = null;
|
||||
}
|
||||
|
||||
@ -55,7 +57,8 @@ export class et2_arrayMgr
|
||||
this._parentMgr = _parentMgr;
|
||||
|
||||
// Hold a reference to the data
|
||||
if (typeof _data == "undefined" || !_data) {
|
||||
if(typeof _data == "undefined" || !_data)
|
||||
{
|
||||
egw.debug("log", "No data passed to content array manager. Probably a mismatch between template namespaces and data.");
|
||||
_data = {};
|
||||
}
|
||||
@ -63,19 +66,24 @@ export class et2_arrayMgr
|
||||
// Expand sub-arrays that have been shmushed together, so further perspectives work
|
||||
// Shmushed keys look like: ${row}[info_cat]
|
||||
// Expanded: ${row}: Object{info_cat: ..value}
|
||||
if (this.splitIds) {
|
||||
if(this.splitIds)
|
||||
{
|
||||
// For each index, we need a key: {..} sub array
|
||||
for (let key in _data) {
|
||||
for(let key in _data)
|
||||
{
|
||||
// Split up indexes
|
||||
const indexes = key.replace(/[/g, "[").split('[');
|
||||
|
||||
// Put data in the proper place
|
||||
if (indexes.length > 1) {
|
||||
if(indexes.length > 1)
|
||||
{
|
||||
const value = _data[key];
|
||||
let target = _data;
|
||||
for (let i = 0; i < indexes.length; i++) {
|
||||
for(let i = 0; i < indexes.length; i++)
|
||||
{
|
||||
indexes[i] = indexes[i].replace(/]/g, '').replace(']', '');
|
||||
if (typeof target[indexes[i]] == "undefined" || target[indexes[i]] === null) {
|
||||
if(typeof target[indexes[i]] == "undefined" || target[indexes[i]] === null)
|
||||
{
|
||||
target[indexes[i]] = i == indexes.length - 1 ? value : {};
|
||||
}
|
||||
target = target[indexes[i]];
|
||||
@ -91,27 +99,33 @@ export class et2_arrayMgr
|
||||
/**
|
||||
* Returns the root content array manager object
|
||||
*/
|
||||
getRoot(): et2_arrayMgr {
|
||||
if (this._parentMgr != null) {
|
||||
getRoot() : et2_arrayMgr
|
||||
{
|
||||
if(this._parentMgr != null)
|
||||
{
|
||||
return this._parentMgr.getRoot();
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
getParentMgr(): et2_arrayMgr {
|
||||
getParentMgr() : et2_arrayMgr
|
||||
{
|
||||
return this._parentMgr;
|
||||
}
|
||||
|
||||
getPerspectiveData(): { owner: et2_widget; row: number; key: string } {
|
||||
getPerspectiveData() : { owner : et2_widget; row : number; key : string }
|
||||
{
|
||||
return this.perspectiveData;
|
||||
}
|
||||
|
||||
setPerspectiveData(new_perspective: { owner: et2_widget; row: number; key: string }) {
|
||||
setPerspectiveData(new_perspective : { owner : et2_widget; row : number; key : string })
|
||||
{
|
||||
this.perspectiveData = new_perspective;
|
||||
}
|
||||
|
||||
setRow(new_row: number) {
|
||||
setRow(new_row : number)
|
||||
{
|
||||
this.perspectiveData.row = new_row;
|
||||
}
|
||||
|
||||
@ -127,21 +141,28 @@ export class et2_arrayMgr
|
||||
*
|
||||
* @return {string[]}
|
||||
*/
|
||||
explodeKey(_key: string): string[] {
|
||||
if(!_key || typeof _key == 'string' && _key.trim() === "") return [];
|
||||
explodeKey(_key : string) : string[]
|
||||
{
|
||||
if(!_key || typeof _key == 'string' && _key.trim() === "")
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
// Parse the given key by removing the "]"-chars and splitting at "["
|
||||
let indexes = [_key];
|
||||
|
||||
if (typeof _key === "string") {
|
||||
if(typeof _key === "string")
|
||||
{
|
||||
_key = _key.replace(/[/g, "[").replace(/]/g, "]");
|
||||
indexes = _key.split('[');
|
||||
}
|
||||
if (indexes.length > 1) {
|
||||
if(indexes.length > 1)
|
||||
{
|
||||
indexes = [indexes.shift(), indexes.join('[')];
|
||||
indexes[1] = indexes[1].substring(0, indexes[1].length - 1);
|
||||
const children = indexes[1].split('][');
|
||||
if (children.length) {
|
||||
if(children.length)
|
||||
{
|
||||
indexes = jQuery.merge([indexes[0]], children);
|
||||
}
|
||||
}
|
||||
@ -154,17 +175,21 @@ export class et2_arrayMgr
|
||||
*
|
||||
* @param _path is used internally, do not supply it manually.
|
||||
*/
|
||||
getPath(_path?: string[]): string[] {
|
||||
if (typeof _path == "undefined") {
|
||||
getPath(_path? : string[]) : string[]
|
||||
{
|
||||
if(typeof _path == "undefined")
|
||||
{
|
||||
_path = [];
|
||||
}
|
||||
|
||||
if (this.perspectiveData.key != null) {
|
||||
if(this.perspectiveData.key != null)
|
||||
{
|
||||
// prepend components of this.perspectiveData.key to path, can be more then one eg. "nm[rows]"
|
||||
_path = this.perspectiveData.key.replace(/]/g, '').split('[').concat(_path);
|
||||
}
|
||||
|
||||
if (this._parentMgr != null) {
|
||||
if(this._parentMgr != null)
|
||||
{
|
||||
_path = this._parentMgr.getPath(_path);
|
||||
}
|
||||
|
||||
@ -182,31 +207,40 @@ export class et2_arrayMgr
|
||||
* @param _skipEmpty returns null if _key is not present in this content array.
|
||||
* Defaults to false.
|
||||
*/
|
||||
getEntry(_key: string, _referenceInto?: boolean, _skipEmpty?: boolean): any {
|
||||
if (typeof _referenceInto == "undefined") {
|
||||
getEntry(_key : string, _referenceInto? : boolean, _skipEmpty? : boolean) : any
|
||||
{
|
||||
if(typeof _referenceInto == "undefined")
|
||||
{
|
||||
_referenceInto = false;
|
||||
}
|
||||
|
||||
if (typeof _skipEmpty == "undefined") {
|
||||
if(typeof _skipEmpty == "undefined")
|
||||
{
|
||||
_skipEmpty = false;
|
||||
}
|
||||
|
||||
// Parse the given key by removing the "]"-chars and splitting at "["
|
||||
const indexes = this.explodeKey(_key);
|
||||
if(indexes.length == 0 && _skipEmpty) return null;
|
||||
if(indexes.length == 0 && _skipEmpty)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
let entry = this.data;
|
||||
for (let i = 0; i < indexes.length; i++) {
|
||||
for(let i = 0; i < indexes.length; i++)
|
||||
{
|
||||
// Abort if the current entry is not an object (associative array) and
|
||||
// we should descend further into it.
|
||||
const isObject = typeof entry === 'object';
|
||||
if (!isObject && !_referenceInto || entry == null || jQuery.isEmptyObject(entry)) {
|
||||
if(!isObject && !_referenceInto || entry == null || jQuery.isEmptyObject(entry))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// Check whether the entry actually exists
|
||||
const idx = indexes[i];
|
||||
if (_skipEmpty && (!isObject || typeof entry[idx] == "undefined")) {
|
||||
if(_skipEmpty && (!isObject || typeof entry[idx] == "undefined"))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -225,16 +259,18 @@ export class et2_arrayMgr
|
||||
* @param {string} _ident Key used to reference into managed array
|
||||
* @return {*}
|
||||
*/
|
||||
expandName(_ident: string): string | object {
|
||||
expandName(_ident : string) : string | object
|
||||
{
|
||||
// Check whether the identifier refers to an index in the content array
|
||||
const is_index_in_content = _ident.charAt(0) == '@';
|
||||
|
||||
// Check whether "$" occurs in the given identifier
|
||||
const pos_var = _ident.indexOf('$');
|
||||
if (pos_var >= 0 && (this.perspectiveData.row != null || !_ident.match(/\$\{?row\}?/))
|
||||
if(pos_var >= 0 && (this.perspectiveData.row != null || !_ident.match(/\$\{?row\}?/))
|
||||
// Avoid messing with regex in validators
|
||||
&& pos_var !== _ident.indexOf("$/")
|
||||
) {
|
||||
)
|
||||
{
|
||||
// Get the content array for the current row
|
||||
const row = typeof this.perspectiveData.row == 'number' ? this.perspectiveData.row : '';
|
||||
const row_cont = this.data[row] || {};
|
||||
@ -245,19 +281,26 @@ export class et2_arrayMgr
|
||||
// Check whether the expression has already been compiled - if not,
|
||||
// try to compile it first. If an error occurs, the identifier
|
||||
// function is set to null
|
||||
if (typeof et2_arrayMgr.compiledExpressions[_ident] == "undefined") {
|
||||
try {
|
||||
if (this.perspectiveData.row == null) {
|
||||
if(typeof et2_arrayMgr.compiledExpressions[_ident] == "undefined")
|
||||
{
|
||||
try
|
||||
{
|
||||
if(this.perspectiveData.row == null)
|
||||
{
|
||||
// No row, compile for only top level content
|
||||
// @ts-ignore
|
||||
et2_arrayMgr.compiledExpressions[_ident] = et2_compilePHPExpression(
|
||||
_ident, ["cont", "_cont"]);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
// @ts-ignore
|
||||
et2_arrayMgr.compiledExpressions[_ident] = et2_compilePHPExpression(
|
||||
_ident, ["row", "cont", "row_cont", "_cont"]);
|
||||
}
|
||||
} catch (e) {
|
||||
}
|
||||
catch(e)
|
||||
{
|
||||
et2_arrayMgr.compiledExpressions[_ident] = null;
|
||||
egw.debug("error", "Error while compiling PHP->JS ", e);
|
||||
}
|
||||
@ -266,15 +309,22 @@ export class et2_arrayMgr
|
||||
// Execute the previously compiled expression, if it is not "null"
|
||||
// because compilation failed. The parameters have to be in the same
|
||||
// order as defined during compilation.
|
||||
if (et2_arrayMgr.compiledExpressions[_ident]) {
|
||||
try {
|
||||
if (this.perspectiveData.row == null) {
|
||||
if(et2_arrayMgr.compiledExpressions[_ident])
|
||||
{
|
||||
try
|
||||
{
|
||||
if(this.perspectiveData.row == null)
|
||||
{
|
||||
// No row, exec with only top level content
|
||||
_ident = et2_arrayMgr.compiledExpressions[_ident](cont, _cont);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
_ident = et2_arrayMgr.compiledExpressions[_ident](row, cont, row_cont, _cont);
|
||||
}
|
||||
} catch (e) {
|
||||
}
|
||||
catch(e)
|
||||
{
|
||||
// only log error, as they are no real errors but missing data
|
||||
egw.debug("log", typeof e == 'object' ? e.message : e);
|
||||
_ident = null;
|
||||
@ -282,12 +332,16 @@ export class et2_arrayMgr
|
||||
}
|
||||
}
|
||||
|
||||
if (is_index_in_content && _ident) {
|
||||
if(is_index_in_content && _ident)
|
||||
{
|
||||
// If an additional "@" is specified, this means that we have to return
|
||||
// the entry from the root element
|
||||
if (_ident.charAt(1) == '@') {
|
||||
if(_ident.charAt(1) == '@')
|
||||
{
|
||||
return this.getRoot().getEntry(_ident.substr(2));
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.getEntry(_ident.substr(1));
|
||||
}
|
||||
}
|
||||
@ -295,10 +349,12 @@ export class et2_arrayMgr
|
||||
return _ident;
|
||||
}
|
||||
|
||||
parseBoolExpression(_expression: string) {
|
||||
parseBoolExpression(_expression : string)
|
||||
{
|
||||
// If the first char of the expression is a '!' this means, that the value
|
||||
// is to be negated.
|
||||
if (_expression.charAt(0) == '!') {
|
||||
if(_expression.charAt(0) == '!')
|
||||
{
|
||||
return !this.parseBoolExpression(_expression.substr(1));
|
||||
}
|
||||
|
||||
@ -310,13 +366,15 @@ export class et2_arrayMgr
|
||||
val = (typeof val == "undefined" || val === null) ? '' : '' + val;
|
||||
|
||||
// If a second expression existed, test that one
|
||||
if (typeof parts[1] != "undefined") {
|
||||
if(typeof parts[1] != "undefined")
|
||||
{
|
||||
// Expand the second value
|
||||
const checkVal = '' + this.expandName(parts[1]);
|
||||
|
||||
// Values starting with / are treated as regular expression. It is
|
||||
// checked whether the first value matches the regular expression
|
||||
if (checkVal.charAt(0) == '/') {
|
||||
if(checkVal.charAt(0) == '/')
|
||||
{
|
||||
return (new RegExp(checkVal.substr(1, checkVal.length - 2)))
|
||||
.test(val);
|
||||
}
|
||||
@ -335,11 +393,15 @@ export class et2_arrayMgr
|
||||
* @param {(string|null|object)} _root string with key, null for whole data or object with data
|
||||
* @param {number?} _row key for into the _root for the desired row
|
||||
*/
|
||||
openPerspective(_owner: et2_widget, _root: (string | null | object), _row: number | null): et2_arrayMgr {
|
||||
openPerspective(_owner : et2_widget, _root : (string | null | object), _row? : number | null) : et2_arrayMgr
|
||||
{
|
||||
// Get the root node
|
||||
let root = typeof _root == "string" ? this.data[_root] :
|
||||
(_root == null ? this.data : _root);
|
||||
if (typeof root == "undefined" && typeof _root == "string") root = this.getEntry(_root);
|
||||
if(typeof root == "undefined" && typeof _root == "string")
|
||||
{
|
||||
root = this.getEntry(_root);
|
||||
}
|
||||
|
||||
// Create a new content array manager with the given root
|
||||
const constructor = this.readOnly ? et2_readonlysArrayMgr : et2_arrayMgr;
|
||||
@ -349,12 +411,14 @@ export class et2_arrayMgr
|
||||
mgr.perspectiveData.owner = _owner;
|
||||
|
||||
// Set the root key
|
||||
if (typeof _root == "string") {
|
||||
if(typeof _root == "string")
|
||||
{
|
||||
mgr.perspectiveData.key = _root;
|
||||
}
|
||||
|
||||
// Set _row parameter
|
||||
if (typeof _row != "undefined") {
|
||||
if(typeof _row != "undefined")
|
||||
{
|
||||
mgr.perspectiveData.row = _row;
|
||||
}
|
||||
|
||||
@ -366,7 +430,8 @@ export class et2_arrayMgr
|
||||
/**
|
||||
* @augments et2_arrayMgr
|
||||
*/
|
||||
export class et2_readonlysArrayMgr extends et2_arrayMgr {
|
||||
export class et2_readonlysArrayMgr extends et2_arrayMgr
|
||||
{
|
||||
|
||||
readOnly : boolean = true;
|
||||
|
||||
@ -379,36 +444,43 @@ export class et2_readonlysArrayMgr extends et2_arrayMgr {
|
||||
* @param _parent
|
||||
* @returns
|
||||
*/
|
||||
isReadOnly(_id: string, _attr: string, _parent?: et2_arrayMgr): boolean | string {
|
||||
isReadOnly(_id : string, _attr : string, _parent? : et2_arrayMgr) : boolean | string
|
||||
{
|
||||
let entry = null;
|
||||
|
||||
if (_id != null) {
|
||||
if (_id.indexOf('$') >= 0 || _id.indexOf('@') >= 0) {
|
||||
if(_id != null)
|
||||
{
|
||||
if(_id.indexOf('$') >= 0 || _id.indexOf('@') >= 0)
|
||||
{
|
||||
_id = this.expandName(_id);
|
||||
}
|
||||
// readonlys was not namespaced in old eTemplate, therefore if we dont find data
|
||||
// under current namespace, we look into parent
|
||||
// (if there is anything namespaced, we will NOT look for parent!)
|
||||
let mgr: et2_arrayMgr = this;
|
||||
while (mgr.getParentMgr() && jQuery.isEmptyObject(mgr.data)) {
|
||||
let mgr : et2_arrayMgr = this;
|
||||
while(mgr.getParentMgr() && jQuery.isEmptyObject(mgr.data))
|
||||
{
|
||||
mgr = mgr.getParentMgr();
|
||||
}
|
||||
entry = mgr.getEntry(_id);
|
||||
}
|
||||
|
||||
// Let the array entry override the read only attribute entry
|
||||
if (typeof entry != "undefined" && !(typeof entry === 'object')) {
|
||||
if(typeof entry != "undefined" && !(typeof entry === 'object'))
|
||||
{
|
||||
return entry;
|
||||
}
|
||||
|
||||
// If the attribute is set, return that
|
||||
if (typeof _attr != "undefined" && _attr !== null) {
|
||||
if(typeof _attr != "undefined" && _attr !== null)
|
||||
{
|
||||
// Accept 'editable', but otherwise boolean
|
||||
return this.expandName(_attr) === 'editable' ? 'editable' : et2_evalBool(_attr);
|
||||
}
|
||||
|
||||
// Otherwise take into accounf whether the parent is readonly
|
||||
if (typeof _parent != "undefined" && _parent) {
|
||||
if(typeof _parent != "undefined" && _parent)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -426,7 +498,8 @@ export class et2_readonlysArrayMgr extends et2_arrayMgr {
|
||||
* @param {string} ident Key for searching into the array.
|
||||
* @returns {*}
|
||||
*/
|
||||
expandName(ident: string): any {
|
||||
expandName(ident : string) : any
|
||||
{
|
||||
return this.perspectiveData.owner.getArrayMgr('content').expandName(ident);
|
||||
}
|
||||
}
|
||||
@ -442,15 +515,18 @@ export class et2_readonlysArrayMgr extends et2_arrayMgr {
|
||||
* existing array managers.
|
||||
* @param _row is the row for which the array managers will be opened.
|
||||
*/
|
||||
export function et2_arrayMgrs_expand(_owner: et2_widget, _mgrs: object, _data: object, _row: number) {
|
||||
export function et2_arrayMgrs_expand(_owner : et2_widget, _mgrs : object, _data : object, _row : number)
|
||||
{
|
||||
// Create a copy of the given _mgrs associative array
|
||||
let result = {};
|
||||
|
||||
// Merge the given data associative array into the existing array managers
|
||||
for (let key in _mgrs) {
|
||||
for(let key in _mgrs)
|
||||
{
|
||||
result[key] = _mgrs[key];
|
||||
|
||||
if (typeof _data[key] != "undefined") {
|
||||
if(typeof _data[key] != "undefined")
|
||||
{
|
||||
// Open a perspective for the given data row
|
||||
let rowData = {};
|
||||
rowData[_row] = _data[key];
|
||||
|
Loading…
Reference in New Issue
Block a user