diff --git a/etemplate/js/et2_DOMWidget.js b/etemplate/js/et2_DOMWidget.js
index b35e3046ff..4429e10107 100644
--- a/etemplate/js/et2_DOMWidget.js
+++ b/etemplate/js/et2_DOMWidget.js
@@ -52,6 +52,18 @@ var et2_DOMWidget = et2_widget.extend(et2_IDOMNode, {
"type": "boolean",
"description": "Defines whether this widget is visible.",
"default": false
+ },
+ "width": {
+ "name": "Width",
+ "type": "dimension",
+ "default": et2_no_init,
+ "description": "Width of the element in pixels, percentage or 'auto'"
+ },
+ "height": {
+ "name": "Height",
+ "type": "dimension",
+ "default": et2_no_init,
+ "description": "Height of the element in pixels, percentage or 'auto'"
}
},
@@ -59,7 +71,10 @@ var et2_DOMWidget = et2_widget.extend(et2_IDOMNode, {
* When the DOMWidget is initialized, it grabs the DOM-Node of the parent
* object (if available) and passes it to its own "createDOMNode" function
*/
- init: function(_parent, _type) {
+ init: function() {
+ // Call the inherited constructor
+ this._super.apply(this, arguments);
+
this.parentNode = null;
this._attachSet = {
@@ -67,10 +82,7 @@ var et2_DOMWidget = et2_widget.extend(et2_IDOMNode, {
"parent": null
};
- this.disabled = false;
-
- // Call the inherited constructor
- this._super.apply(this, arguments);
+ this._disabled = false;
},
/**
@@ -87,14 +99,16 @@ var et2_DOMWidget = et2_widget.extend(et2_IDOMNode, {
},
/**
- * Automatically tries to attach this node to the parent widget.
+ * Attaches the container node of this widget to the DOM-Tree
*/
- onSetParent: function() {
+ doLoadingFinished: function() {
// Check whether the parent implements the et2_IDOMNode interface. If
// yes, grab the DOM node and create our own.
if (this._parent && this._parent.implements(et2_IDOMNode)) {
this.setParentDOMNode(this._parent.getDOMNode(this));
}
+
+ return true;
},
/**
@@ -192,7 +206,7 @@ var et2_DOMWidget = et2_widget.extend(et2_IDOMNode, {
},
set_disabled: function(_value) {
- var node = this.getDOMNode();
+ var node = this.getDOMNode(this);
if (node)
{
this.disabled = _value;
@@ -206,8 +220,27 @@ var et2_DOMWidget = et2_widget.extend(et2_IDOMNode, {
$j(node).show();
}
}
- }
+ },
+ set_width: function(_value) {
+ this.width = _value;
+
+ var node = this.getDOMNode(this);
+ if (node)
+ {
+ $j(node).css("width", _value);
+ }
+ },
+
+ set_height: function(_value) {
+ this.height = _value;
+
+ var node = this.getDOMNode(this);
+ if (node)
+ {
+ $j(node).css("height", _value);
+ }
+ }
});
diff --git a/etemplate/js/et2_baseWidget.js b/etemplate/js/et2_baseWidget.js
index 3fe711cd8b..c3e16dc895 100644
--- a/etemplate/js/et2_baseWidget.js
+++ b/etemplate/js/et2_baseWidget.js
@@ -128,16 +128,8 @@ var et2_baseWidget = et2_DOMWidget.extend(et2_IAligned, {
}
},
- // XXX I really don't like this - I think I'll move attaching the DOM-Nodes
- // to the loadFinished function - this should also be faster...
set_align: function(_value) {
- if (_value != this.align)
- {
- this.align = _value;
-
- // Reattach this node to the DOM
- this.onSetParent();
- }
+ this.align = _value;
},
get_align: function(_value) {
@@ -171,32 +163,49 @@ var et2_placeholder = et2_baseWidget.extend({
// values of this object
this.attrNodes = {};
+ this.visible = false;
+
// Create the placeholder div
this.placeDiv = $j(document.createElement("span"))
.addClass("et2_placeholder");
var headerNode = $j(document.createElement("span"))
- .text(this.type)
+ .text(this._type)
.addClass("et2_caption")
.appendTo(this.placeDiv);
- this.setDOMNode(this.placeDiv[0]);
- },
+ var attrsCntr = $j(document.createElement("span"))
+ .appendTo(this.placeDiv)
+ .hide();
- loadAttributes: function(_attrs) {
- for (var i = 0; i < _attrs.length; i++)
- {
- var attr = _attrs[i];
-
- if (typeof this.attrNodes[attr.name] == "undefined")
+ headerNode.click(this, function(e) {
+ e.data.visible = !e.data.visible;
+ if (e.data.visible)
{
- this.attrNodes[attr.name] = $j(document.createElement("span"))
- .addClass("et2_attr");
- this.placeDiv.append(this.attrNodes[attr.name]);
+ attrsCntr.show();
}
+ else
+ {
+ attrsCntr.hide();
+ }
+ });
- this.attrNodes[attr.name].text(attr.name + "=" + attr.value);
+ for (var key in this.options)
+ {
+ if (typeof this.options[key] != "undefined")
+ {
+ if (typeof this.attrNodes[key] == "undefined")
+ {
+ this.attrNodes[key] = $j(document.createElement("span"))
+ .addClass("et2_attr");
+ attrsCntr.append(this.attrNodes[key]);
+ }
+
+ this.attrNodes[key].text(key + "=" + this.options[key]);
+ }
}
+
+ this.setDOMNode(this.placeDiv[0]);
}
});
diff --git a/etemplate/js/et2_box.js b/etemplate/js/et2_box.js
index 17ddcc68c1..4ccf97d0dc 100644
--- a/etemplate/js/et2_box.js
+++ b/etemplate/js/et2_box.js
@@ -22,21 +22,16 @@
*/
var et2_box = et2_baseWidget.extend({
- init: function(_parent, _type) {
+ createNamespace: true,
+
+ init: function() {
this._super.apply(this, arguments);
this.div = $j(document.createElement("div"))
- .addClass("et2_" + _type)
+ .addClass("et2_" + this._type)
.addClass("et2_box_widget");
this.setDOMNode(this.div[0]);
- },
-
- set_id: function(_value) {
- this._super.apply(this, arguments);
-
- // Check whether a namespace exists for this element
- this.checkCreateNamespace();
}
});
diff --git a/etemplate/js/et2_checkbox.js b/etemplate/js/et2_checkbox.js
index 50c719ad0f..d29f419582 100644
--- a/etemplate/js/et2_checkbox.js
+++ b/etemplate/js/et2_checkbox.js
@@ -109,9 +109,6 @@ var et2_checkbox_ro = et2_checkbox.extend({
}
},
- init: function(_parent) {
- },
-
init: function() {
this._super.apply(this, arguments);
diff --git a/etemplate/js/et2_common.js b/etemplate/js/et2_common.js
index 0f345ae24b..8a4428b4b1 100644
--- a/etemplate/js/et2_common.js
+++ b/etemplate/js/et2_common.js
@@ -71,7 +71,7 @@ function et2_debug(_level)
/**
* Array with all types supported by the et2_checkType function.
*/
-var et2_validTypes = ["boolean", "string", "float", "integer", "any", "js"];
+var et2_validTypes = ["boolean", "string", "float", "integer", "any", "js", "dimension"];
/**
* Object whith default values for the above types. Do not specify array or
@@ -84,7 +84,8 @@ var et2_typeDefaults = {
"js": null,
"float": 0.0,
"integer": 0,
- "any": null
+ "any": null,
+ "dimension": "auto"
};
function et2_evalBool(_val)
@@ -144,7 +145,7 @@ function et2_checkType(_val, _type, _attr)
if (_type == "js")
{
// Handle the default case
- if (_val === null)
+ if (_val === null || _val instanceof Function)
{
return null;
}
@@ -204,6 +205,32 @@ function et2_checkType(_val, _type, _attr)
return _err();
}
+ // Parse the given dimension value
+ if (_type == "dimension")
+ {
+ // Case 1: The value is "auto"
+ if (_val == "auto")
+ {
+ return _val;
+ }
+
+ // Case 2: The value is simply a number, attach "px"
+ if (!isNaN(_val))
+ {
+ return parseFloat(_val) + "px";
+ }
+
+ // Case 3: The value is already a valid css pixel value or a percentage
+ if (typeof _val == "string" &&
+ ((_val.indexOf("px") == _val.length - 2 && !isNaN(_val.split("px")[0])) ||
+ (_val.indexOf("%") == _val.length - 1 && !isNaN(_val.split("%")[0]))))
+ {
+ return _val;
+ }
+
+ return _err();
+ }
+
// We should never come here
throw("Invalid type identifier supplied.");
}
diff --git a/etemplate/js/et2_grid.js b/etemplate/js/et2_grid.js
index 2e13265808..140f274364 100644
--- a/etemplate/js/et2_grid.js
+++ b/etemplate/js/et2_grid.js
@@ -402,9 +402,6 @@ var et2_grid = et2_DOMWidget.extend({
"widget": cell.widget
});
- // Trigger the "onSetParent" event of the widget
- cell.widget.onSetParent();
-
// Set the span values of the cell
var cs = (x == w - 1) ? w - x : Math.min(w - x, cell.colSpan);
var rs = (y == h - 1) ? h - y : Math.min(h - y, cell.rowSpan);
diff --git a/etemplate/js/et2_hbox.js b/etemplate/js/et2_hbox.js
index 2c5f3932ad..e9419ea6db 100644
--- a/etemplate/js/et2_hbox.js
+++ b/etemplate/js/et2_hbox.js
@@ -22,7 +22,11 @@
*/
var et2_hbox = et2_baseWidget.extend({
- init: function(_parent, _type) {
+ createNamespace: true,
+
+ init: function(_parent) {
+ this._super.apply(this, arguments);
+
this.alignData = {
"hasAlign": false,
"hasLeft": false,
@@ -34,10 +38,8 @@ var et2_hbox = et2_baseWidget.extend({
this.leftDiv = null;
this.rightDiv = null;
- this._super.apply(this, arguments);
-
this.div = $j(document.createElement("div"))
- .addClass("et2_" + _type)
+ .addClass("et2_" + this._type)
.addClass("et2_box_widget");
this.setDOMNode(this.div[0]);
@@ -159,15 +161,7 @@ var et2_hbox = et2_baseWidget.extend({
// Normally simply return the hbox-div
return this._super.apply(this, arguments);
- },
-
- set_id: function(_value) {
- this._super.apply(this, arguments);
-
- // Check whether a namespace exists for this element
- this.checkCreateNamespace();
}
-
});
et2_register_widget(et2_hbox, ["hbox"]);
diff --git a/etemplate/js/et2_inheritance.js b/etemplate/js/et2_inheritance.js
index e053cdcd4e..330c94ea0a 100644
--- a/etemplate/js/et2_inheritance.js
+++ b/etemplate/js/et2_inheritance.js
@@ -261,12 +261,6 @@
{
this.init.apply(this, arguments);
}
-
- // Initialize the attributes
- if (typeof this._attrsInitialized == "undefined")
- {
- this.initAttributes();
- }
}
}
@@ -353,23 +347,67 @@
}
}
+ /**
+ * generateAttributeSet sanitizes the given associative array of attributes
+ * (by passing each entry to "et2_checkType" and checking for existance of
+ * the attribute) and adds the default values to the associative array.
+ *
+ * @param _attrs is the associative array containing the attributes.
+ */
+ Class.prototype.generateAttributeSet = function(_attrs) {
+
+ // Sanity check and validation
+ for (var key in _attrs)
+ {
+ if (typeof this.attributes[key] != "undefined")
+ {
+ if (!this.attributes[key].ignore)
+ {
+ _attrs[key] = et2_checkType(_attrs[key], this.attributes[key].type,
+ key);
+ }
+ }
+ else
+ {
+ // Key does not exist - delete it and issue a warning
+ delete(_attrs[key]);
+ et2_debug("warn", this, "Attribute '" + key +
+ "' does not exist!");
+ }
+ }
+
+ // Include default values or already set values for this attribute
+ for (var key in this.attributes)
+ {
+ if (typeof _attrs[key] == "undefined")
+ {
+ var _default = this.attributes[key]["default"];
+ if (_default == et2_no_init)
+ {
+ _default = undefined;
+ }
+
+ _attrs[key] = _default;
+ }
+ }
+
+ return _attrs;
+ }
+
/**
* The initAttributes function sets the attributes to their default
* values. The attributes are not overwritten, which means, that the
* default is only set, if either a setter exists or this[propName] does
* not exist yet.
*/
- Class.prototype.initAttributes = function() {
- for (var key in this.attributes)
+ Class.prototype.initAttributes = function(_attrs) {
+ for (var key in _attrs)
{
- if (!this.attributes[key].ignore && this.attributes[key]["default"] !== et2_no_init)
+ if (!this.attributes[key].ignore && !(_attrs[key] == undefined))
{
- this.setAttribute(key, this.attributes[key]["default"],
- false);
+ this.setAttribute(key, _attrs[key], false);
}
}
-
- this._attrsInitialized = true;
}
/**
diff --git a/etemplate/js/et2_inputWidget.js b/etemplate/js/et2_inputWidget.js
index 087c95bb51..e553846932 100644
--- a/etemplate/js/et2_inputWidget.js
+++ b/etemplate/js/et2_inputWidget.js
@@ -71,6 +71,7 @@ var et2_inputWidget = et2_valueWidget.extend(et2_IInput, {
$j(this.getInputNode()).attr("novalidate","novalidate"); // Stop browser from getting involved
$j(this.getInputNode()).validator();
},
+
detatchFromDOM: function() {
if(this.getInputNode()) {
$j(this.getInputNode()).data("validator").destroy();
diff --git a/etemplate/js/et2_tabs.js b/etemplate/js/et2_tabs.js
index 84782c5677..b6817a359f 100644
--- a/etemplate/js/et2_tabs.js
+++ b/etemplate/js/et2_tabs.js
@@ -134,18 +134,13 @@ var et2_tabbox = et2_DOMWidget.extend({
entry.contentDiv = $j(document.createElement("div"))
.addClass("et2_tabcntr")
- .hide()
.appendTo(this.tabContainer);
-
- // Let the widget appear on its corresponding page
- entry.widget.onSetParent();
}
this.setActiveTab(0);
},
setActiveTab: function(_idx) {
- console.log(_idx);
// Remove the "active" flag from all tabs-flags
$j(".et2_tabflag", this.flagContainer).removeClass("active");
@@ -175,6 +170,12 @@ var et2_tabbox = et2_DOMWidget.extend({
return null;
}
+ },
+
+ set_height: function(_value) {
+ this.height = _value;
+
+ this.tabContainer.css("height", _value);
}
});
diff --git a/etemplate/js/et2_template.js b/etemplate/js/et2_template.js
index 9ade66ce3b..1820b12d2a 100644
--- a/etemplate/js/et2_template.js
+++ b/etemplate/js/et2_template.js
@@ -44,26 +44,60 @@ var et2_template = et2_DOMWidget.extend({
}
},
+ createNamespace: true,
+
/**
* Initializes this template widget as a simple container.
*/
init: function(_parent) {
+ this._super.apply(this, arguments);
+
this.proxiedTemplate = null;
this.isProxied = false;
this.div = document.createElement("div");
- this.id = "";
- this._super.apply(this, arguments);
+ if (this.id != "")
+ {
+ this.createProxy();
+ }
+ },
+
+ createProxy: function() {
+ // Check whether a template with the given name already exists and
+ // is not a proxy.
+ var tmpl = this.getRoot().getWidgetById(this.id);
+ if (tmpl instanceof et2_template && tmpl.proxiedTemplate == null &&
+ tmpl != this)
+ {
+ // Detatch the proxied template from the DOM to and set its
+ // isProxied property to true
+ tmpl.makeProxied();
+
+ // Do not copy the id when cloning as this leads to infinit
+ // recursion
+ tmpl.options.id = "";
+
+ // Create a clone of the template and add it as child of this
+ // template (done by passing "this" to the clone function)
+ this.proxiedTemplate = tmpl.clone(this);
+
+ // Reset the "ignore" flag and manually copy the id
+ tmpl.options.id = this.id;
+ this.proxiedTemplate.id = tmpl.id;
+ this.proxiedTemplate.isProxied = true;
+
+ // Disallow adding any new node to this template
+ this.supportedWidgetClasses = [];
+ }
},
/**
* If the parent node is changed, either the DOM-Node of the proxied template
* or the DOM-Node of this template is connected to the parent DOM-Node.
*/
- onSetParent: function() {
- // Check whether the parent implements the et2_IDOMNode interface. If
- // yes, grab the DOM node and create our own.
+ doLoadingFinished: function() {
+ // Check whether the parent implements the et2_IDOMNode interface.
if (this._parent && this._parent.implements(et2_IDOMNode)) {
var parentNode = this._parent.getDOMNode(this);
@@ -72,6 +106,8 @@ var et2_template = et2_DOMWidget.extend({
if (this.proxiedTemplate)
{
this.proxiedTemplate.setParentDOMNode(parentNode);
+ this.proxiedTemplate.loadingFinished();
+ return false;
}
else if (!this.isProxied)
{
@@ -79,6 +115,8 @@ var et2_template = et2_DOMWidget.extend({
}
}
}
+
+ return true;
},
makeProxied: function() {
@@ -92,59 +130,7 @@ var et2_template = et2_DOMWidget.extend({
this.isProxied = true;
},
- set_id: function(_value) {
- if (_value != this.id)
- {
- // Check whether a template with the given name already exists and
- // is not a proxy.
- var tmpl = this.getRoot().getWidgetById(_value);
- if (tmpl instanceof et2_template && tmpl.proxiedTemplate == null &&
- tmpl != this)
- {
- // Check whether we still have a proxied template, if yes,
- // destroy it
- if (this.proxiedTemplate != null)
- {
- this.proxiedTemplate.destroy();
- this.proxiedTemplate = null;
- }
-
- // This element does not have a node in the tree
- this.detatchFromDOM();
-
- // Detatch the proxied template from the DOM to and set its
- // isProxied property to true
- tmpl.makeProxied();
-
- // Do not copy the id when cloning as this leads to infinit
- // recursion
- tmpl.attributes["id"].ignore = true;
-
- // Create a clone of the template and add it as child of this
- // template (done by passing "this" to the clone function)
- this.proxiedTemplate = tmpl.clone(this);
-
- // Reset the "ignore" flag and manually copy the id
- tmpl.attributes["id"].ignore = false;
- this.proxiedTemplate.id = tmpl.id;
-
- // Disallow adding any new node to this template
- this.supportedWidgetClasses = [];
-
- // Call the parent change event function
- this.onSetParent();
- }
- else
- {
- this._super(_value);
-
- // Check whether a namespace exists for this element
- this.checkCreateNamespace();
- }
- }
- },
-
- getDOMNode: function(_fromProxy) {
+ getDOMNode: function() {
return this.div;
},
diff --git a/etemplate/js/et2_textbox.js b/etemplate/js/et2_textbox.js
index b6074fa4bb..e9fd98bc9a 100644
--- a/etemplate/js/et2_textbox.js
+++ b/etemplate/js/et2_textbox.js
@@ -41,13 +41,13 @@ var et2_textbox = et2_inputWidget.extend({
"rows": {
"name": "Rows",
"type": "integer",
- "default": et2_no_init,
+ "default": 1,
"description": "Multiline field height - better to use CSS"
},
"cols": {
"name": "Size",
"type": "integer",
- "default": et2_no_init,
+ "default": 1,
"description": "Multiline field width - better to use CSS"
},
},
@@ -56,16 +56,16 @@ var et2_textbox = et2_inputWidget.extend({
this._super.apply(this, arguments);
this.input = null;
- this.id = "";
this.createInputWidget();
-
},
createInputWidget: function() {
- if (this.multiline)
+ if (this.options.multiline || this.options.rows > 1 || this.options.cols > 1)
{
- this.input = $j(document.createElement("textarea"));
+ this.input = $j(document.createElement("textarea"))
+ .attr("rows", this.options.rows)
+ .attr("cols", this.options.cols);
}
else
{
@@ -80,44 +80,6 @@ var et2_textbox = et2_inputWidget.extend({
this.setDOMNode(this.input[0]);
},
- set_multiline: function(_value) {
- if (_value != this.multiline)
- {
- this.multiline = _value;
-
- this.createInputWidget();
-
- // Write all settings again
- this.update();
- }
- },
-
- set_rows: function(_value) {
- if (_value != this.rows)
- {
- this.rows = _value;
- if(this.rows > 1)
- {
- this.set_multiline(true);
- this.input.attr("rows", this.rows);
- } else {
- this.set_multiline(false);
- }
- }
- },
- set_cols: function(_value) {
- if (_value != this.cols)
- {
- this.cols = _value;
- if(this.cols > 1)
- {
- this.set_multiline(true);
- this.input.attr("cols", this.cols);
- } else {
- this.set_multiline(false);
- }
- }
- },
/**
* Set input widget size
diff --git a/etemplate/js/et2_valueWidget.js b/etemplate/js/et2_valueWidget.js
index 778a970017..0fdf35ed81 100644
--- a/etemplate/js/et2_valueWidget.js
+++ b/etemplate/js/et2_valueWidget.js
@@ -33,18 +33,18 @@ var et2_valueWidget = et2_baseWidget.extend({
}
},
- loadingFinished: function() {
+ parseArrayMgrAttrs: function(_attrs) {
this._super.call(this, arguments);
if (this.id != "")
{
// Set the value for this element
var contentMgr = this.getArrayMgr("content");
- if(contentMgr != null) {
+ if (contentMgr != null) {
var val = contentMgr.getValueForID(this.id);
if (val !== null)
{
- this.setAttribute("value", val)
+ _attrs["value"] = val;
}
}
}
diff --git a/etemplate/js/et2_widget.js b/etemplate/js/et2_widget.js
index 3bd3507954..af7884fadf 100644
--- a/etemplate/js/et2_widget.js
+++ b/etemplate/js/et2_widget.js
@@ -89,6 +89,11 @@ var et2_widget = Class.extend({
// attribute defines.
legacyOptions: [],
+ /**
+ * Set this variable to true if this widget can have namespaces
+ */
+ createNamespace: false,
+
/**
* The init function is the constructor of the widget. When deriving new
* classes from the widget base class, always call this constructor unless
@@ -97,37 +102,54 @@ var et2_widget = Class.extend({
* @param _parent is the parent object from the XML tree which contains this
* object. The default constructor always adds the new instance to the
* children list of the given parent object. _parent may be NULL.
- * @param _type is the node name with which the widget has been created. This
- * is usefull if a single widget class implements multiple XET-Node widgets.
+ * @param _attrs is an associative array of attributes.
*/
- init: function(_parent, _type, _readonly) {
+ init: function(_parent, _attrs) {
- if (typeof _type == "undefined")
+ // Check whether all attributes are available
+ if (typeof _parent == "undefined")
{
- _type = "widget";
+ _parent = null;
}
- this.id = "";
+ if (typeof _attrs == "undefined")
+ {
+ _attrs = {};
+ }
+
+ // Initialize all important parameters
this._mgrs = {};
this._inst = null;
+ this._children = [];
+ this._type = _attrs["type"];
+ this.id = _attrs["id"];
- // Copy the parent parameter and add this widget to its parent children
- // list.
+ // Add this widget to the given parent widget
this._parent = _parent;
- this.onSetParent();
-
if (_parent != null)
{
this._parent.addChild(this);
}
- this._children = [];
- this.type = _type;
- this.readonly = _readonly;
-
// The supported widget classes array defines a whitelist for all widget
// classes or interfaces child widgets have to support.
this.supportedWidgetClasses = [et2_widget];
+
+ if (_attrs["id"])
+ {
+ // Create a namespace for this object
+ if (this.createNamespace)
+ {
+ this.checkCreateNamespace();
+ }
+
+ // Add all attributes hidden in the content arrays to the attributes
+ // parameter
+ this.parseArrayMgrAttrs(_attrs);
+ }
+
+ // Create a local copy of the options object
+ this.options = et2_cloneObject(_attrs);
},
/**
@@ -156,7 +178,6 @@ var et2_widget = Class.extend({
this._children = [];
this._parent = null;
this._mgrs = {};
- this.onSetParent();
},
/**
@@ -164,7 +185,7 @@ var et2_widget = Class.extend({
* constructor of the copied object. If the parameters are omitted, _parent
* is defaulted to null
*/
- clone: function(_parent, _type) {
+ clone: function(_parent) {
// Default _parent to null
if (typeof _parent == "undefined")
@@ -173,7 +194,7 @@ var et2_widget = Class.extend({
}
// Create the copy
- var copy = new (this.constructor)(_parent, _type, this.readonly);
+ var copy = new (this.constructor)(_parent, this.options);
// Assign this element to the copy
copy.assign(this);
@@ -185,22 +206,7 @@ var et2_widget = Class.extend({
// Create a clone of all child elements of the given object
for (var i = 0; i < _obj._children.length; i++)
{
- _obj._children[i].clone(this, _obj._children[i].type);
- }
-
- // Copy all properties
- for (var key in _obj.attributes)
- {
- if (!_obj.attributes[key].ignore)
- {
- var value = _obj.getAttribute(key);
-
- // Check whether the attribute is undefined
- if (typeof value != "undefined")
- {
- this.setAttribute(key, value);
- }
- }
+ _obj._children[i].clone(this);
}
// Copy a reference to the content array manager
@@ -214,14 +220,6 @@ var et2_widget = Class.extend({
return this._parent;
},
- /**
- * The set parent event is called, whenever the parent of the widget is set.
- * Child classes can overwrite this function. Whe onSetParent is called,
- * the change of the parent has already taken place.
- */
- onSetParent: function() {
- },
-
/**
* Returns the list of children of this widget.
*/
@@ -269,7 +267,7 @@ var et2_widget = Class.extend({
}
else
{
- throw("_node is not supported by this widget class!");
+ throw(_node, " is not supported by this widget class!");
}
},
@@ -284,7 +282,6 @@ var et2_widget = Class.extend({
{
// This element is no longer parent of the child
_node._parent = null;
- _node.onSetParent();
this._children.splice(idx, 1);
}
@@ -375,46 +372,103 @@ var et2_widget = Class.extend({
return false;
},
- createElementFromNode: function(_node, _nodeName) {
+ /**
+ * The parseXMLAttrs function takes an XML DOM attributes object
+ * and adds the given attributes to the _target associative array. This
+ * function also parses the legacyOptions.
+ *
+ * @param _attrsObj is the XML DOM attributes object
+ * @param _target is the object to which the attributes should be written.
+ */
+ parseXMLAttrs: function(_attrsObj, _target, _proto) {
- // Check whether the type attribute exists - if yes pass it instead of
- // the nodeName
- if (_node.getAttribute("type"))
+ // Check whether the attributes object is really existing, if not abort
+ if (typeof _attrsObj == "undefined")
{
- _nodeName = _node.getAttribute("type");
+ return;
}
- if (typeof _nodeName == "undefined")
+ // Iterate over the given attributes and parse them
+ for (var i = 0; i < _attrsObj.length; i++)
{
- _nodeName = _node.nodeName.toLowerCase();
- }
+ var attrName = _attrsObj[i].name;
+ var attrValue = _attrsObj[i].value;
- // Get the constructor for that widget
+ // Special handling for the legacy options
+ if (attrName == "options")
+ {
+ // Parse the legacy options
+ var splitted = et2_csvSplit(attrValue);
+
+ for (var j = 0; j < splitted.length && j < _proto.legacyOptions.length; j++)
+ {
+ _target[_proto.legacyOptions[j]] = splitted[j];
+ }
+ }
+ else
+ {
+ var mgr = this.getArrayMgr("content");
+ if (mgr != null && typeof _proto.attributes[attrName] != "undefined")
+ {
+ var attr = _proto.attributes[attrName];
+
+ // If the attribute is marked as boolean, parse the
+ // expression as bool expression.
+ if (attr.type == "boolean")
+ {
+ attrValue = mgr.parseBoolExpression(attrValue);
+ }
+ else
+ {
+ attrValue = mgr.expandName(attrValue);
+ }
+ }
+
+ // Set the attribute
+ _target[attrName] = attrValue;
+ }
+ }
+ },
+
+ parseArrayMgrAttrs: function() {
+ },
+
+ createElementFromNode: function(_node) {
+
+ // Fetch all attributes for this element from the XML node
+ var attributes = {};
+
+ // Parse the "readonly" and "type" flag for this element here, as they
+ // determine which constructor is used
+ var _nodeName = attributes["type"] = _node.getAttribute("type") ?
+ _node.getAttribute("type") : _node.nodeName.toLowerCase();
+ var readonly = attributes["readonly"] =
+ this.getArrayMgr("readonlys").isReadOnly(
+ _node.getAttribute("id"), _node.getAttribute("readonly"),
+ this.readonly);
+
+ // Get the constructor - if the widget is readonly, use the special "_ro"
+ // constructor if it is available
var constructor = typeof et2_registry[_nodeName] == "undefined" ?
et2_placeholder : et2_registry[_nodeName];
-
- // Check whether the widget is marked as readonly and whether a special
- // readonly type (suffixed with "_ro") is registered
- var mgr = this.getArrayMgr("readonlys");
- var readonly = false;
- if(mgr != null) {
- readonly = mgr.isReadOnly(
- _node.getAttribute("id"), _node.getAttribute("readonly"), this.readonly);
- }
if (readonly && typeof et2_registry[_nodeName + "_ro"] != "undefined")
{
constructor = et2_registry[_nodeName + "_ro"];
}
+ // Parse the attributes from the given XML attributes object
+ this.parseXMLAttrs(_node.attributes, attributes, constructor.prototype);
+
+ // Do an sanity check for the attributes
+ constructor.prototype.generateAttributeSet(attributes);
+
// Creates the new widget, passes this widget as an instance and
// passes the widgetType. Then it goes on loading the XML for it.
- var widget = new constructor(this, _nodeName, readonly);
+ var widget = new constructor(this, attributes);
+ // Load the widget itself from XML
widget.loadFromXML(_node);
- // Call the "loadFinished" function of the widget
- widget.loadingFinished();
-
return widget;
},
@@ -422,12 +476,6 @@ var et2_widget = Class.extend({
* Loads the widget tree from an XML node
*/
loadFromXML: function(_node) {
- // Try to load the attributes of the current node
- if (_node.attributes)
- {
- this.loadAttributes(_node.attributes);
- }
-
// Load the child nodes.
for (var i = 0; i < _node.childNodes.length; i++)
{
@@ -453,51 +501,6 @@ var et2_widget = Class.extend({
}
},
- /**
- * Loads the widget attributes from the passed DOM attributes array.
- */
- loadAttributes: function(_attrs) {
- for (var i = 0; i < _attrs.length; i++)
- {
- // Special handling for the legacy options
- if (_attrs[i].name == "options")
- {
- // Parse the legacy options
- var splitted = et2_csvSplit(_attrs[i].value);
-
- for (var j = 0; j < splitted.length && j < this.legacyOptions.length; j++)
- {
- this.setAttribute(this.legacyOptions[j], splitted[j]);
- }
- }
- else
- {
- var attrName = _attrs[i].name;
- var attrValue = _attrs[i].value;
-
- var mgr = this.getArrayMgr("content");
- if (mgr != null && typeof this.attributes[attrName] != "undefined")
- {
- var attr = this.attributes[attrName];
-
- // If the attribute is marked as boolean, parse the
- // expression as bool expression.
- if (attr.type == "boolean")
- {
- attrValue = mgr.parseBoolExpression(attrValue);
- }
- else
- {
- attrValue = mgr.expandName(attrValue);
- }
- }
-
- // Set the attribute
- this.setAttribute(attrName, attrValue);
- }
- }
- },
-
/**
* Called whenever textNodes are loaded from the XML tree
*/
@@ -505,34 +508,28 @@ var et2_widget = Class.extend({
},
/**
- * Called when loading of the widget from XML node is finished. This
- * function can be used to load the data from the data arrays (content,
- * readonlys, sel_options etc.)
+ * Called when loading the widget (sub-tree) is finished. First when this
+ * function is called, the DOM-Tree is created. loadingFinished is
+ * recursively called for all child elements. Do not directly override this
+ * function but the doLoadingFinished function which is executed before
+ * descending deeper into the DOM-Tree
*/
loadingFinished: function() {
- },
+ // Call all availble setters
+ this.initAttributes(this.options);
- /**
- * Calls the setter of each property with its current value, calls the
- * update function of all child nodes.
- */
- update: function() {
-
- // Go through every property of this object and check whether a
- // corresponding setter function exists. If yes, it is called.
- for (var key in this.attributes)
+ if (this.doLoadingFinished())
{
- if (!this.attributes[key].ignore)
+ // Descend recursively into the tree
+ for (var i = 0; i < this._children.length; i++)
{
- this.setAttribute(key, this.getAttribute(key));
+ this._children[i].loadingFinished();
}
}
+ },
- // Call the update function of all children.
- for (var i = 0; i < this._children.length; i++)
- {
- this._children[i].update();
- }
+ doLoadingFinished: function() {
+ return true;
},
/**
diff --git a/etemplate/js/etemplate2.js b/etemplate/js/etemplate2.js
index c30b5c7c77..b5203bddc6 100644
--- a/etemplate/js/etemplate2.js
+++ b/etemplate/js/etemplate2.js
@@ -20,7 +20,7 @@
et2_description;
et2_textbox;
et2_number;
- et2_selectbox;
+// et2_selectbox;
et2_checkbox;
et2_radiobox;
et2_styles;
@@ -64,7 +64,7 @@ etemplate2.prototype.clear = function()
{
if (this.widgetContainer != null)
{
- $j(':input',this.DOMContainer).validator().data("validator").destroy();
+// $j(':input',this.DOMContainer).validator().data("validator").destroy();
this.widgetContainer.destroy();
this.widgetContainer = null;
}
@@ -121,7 +121,10 @@ etemplate2.prototype.load = function(_url, _data)
// Asynchronously load the XET file (code below is executed ahead of the
// code in the callback function)
et2_loadXMLFromURL(_url, function(_xmldoc) {
+ // Read the XML structure
this.widgetContainer.loadFromXML(_xmldoc);
+ // Inform the widget tree that it has been successfully loaded.
+ this.widgetContainer.loadingFinished();
}, this);
// Clear any existing instance
@@ -152,13 +155,13 @@ etemplate2.prototype.load = function(_url, _data)
etemplate2.prototype.submit = function()
{
// Validator
- var valid = true;
+ /*var valid = true;
var inputs = $j(':input',this.DOMContainer).each(function() {
if(typeof $j(this).data("validator") == "undefined") return true;
valid = valid && $j(this).data("validator").checkValidity();
return true;
});
- if(!valid) return false;
+ if(!valid) return false;*/
// Get the form values
var values = this.widgetContainer.getValues();
@@ -263,7 +266,7 @@ function etemplate2_handle_response(_type, _response)
throw("Error while parsing et2_load response");
} else if (_type == "et2_validation_error") {
// Display validation errors
- $j(':input',this.DOMContainer).data("validator").invalidate(_response.data);
+// $j(':input',this.DOMContainer).data("validator").invalidate(_response.data);
}
return false;
diff --git a/etemplate/js/test/et2_test_tabbox.xet b/etemplate/js/test/et2_test_tabbox.xet
index aa310f721b..cc6eb75b03 100644
--- a/etemplate/js/test/et2_test_tabbox.xet
+++ b/etemplate/js/test/et2_test_tabbox.xet
@@ -1,6 +1,6 @@
-
+
@@ -8,10 +8,18 @@
-
+
+
+
+
+
+
+
+
+
diff --git a/etemplate/js/test/test.css b/etemplate/js/test/test.css
index 7960d0359b..cfe6cf1e38 100644
--- a/etemplate/js/test/test.css
+++ b/etemplate/js/test/test.css
@@ -86,6 +86,7 @@ div.et2_hbox_right {
margin: 0 0 5px 0;
font-weight: bold;
color: #2E2E2E;
+ cursor: pointer;
text-shadow: rgba(255, 255, 255, 0.5) 0 1px 0;
}
diff --git a/etemplate/js/test/test_xml.html b/etemplate/js/test/test_xml.html
index b7fedc28b7..b2b24ec75e 100644
--- a/etemplate/js/test/test_xml.html
+++ b/etemplate/js/test/test_xml.html
@@ -20,7 +20,7 @@
-
+