diff --git a/etemplate/js/et2_DOMWidget.js b/etemplate/js/et2_DOMWidget.js
index 4429e10107..dd23d49573 100644
--- a/etemplate/js/et2_DOMWidget.js
+++ b/etemplate/js/et2_DOMWidget.js
@@ -160,6 +160,10 @@ var et2_DOMWidget = et2_widget.extend(et2_IDOMNode, {
return false;
},
+ isAttached: function() {
+ return this.parentNode != null;
+ },
+
/**
* Set the parent DOM node of this element. If another parent node is already
* set, this widget removes itself from the DOM tree
diff --git a/etemplate/js/et2_baseWidget.js b/etemplate/js/et2_baseWidget.js
index c3e16dc895..3335fceec9 100644
--- a/etemplate/js/et2_baseWidget.js
+++ b/etemplate/js/et2_baseWidget.js
@@ -54,9 +54,18 @@ var et2_baseWidget = et2_DOMWidget.extend(et2_IAligned, {
this.node = null;
this.statustext = "";
+ this._labelContainer = null;
+ this._widgetPlaceholder = null;
+
this._tooltipElem = null;
},
+ destroy: function() {
+ this._super.apply(this, arguments);
+
+ this.node = null;
+ },
+
detatchFromDOM: function() {
// Detach this node from the tooltip node
if (this._tooltipElem)
@@ -69,7 +78,7 @@ var et2_baseWidget = et2_DOMWidget.extend(et2_IAligned, {
},
attachToDOM: function() {
- this._super.apply(this,arguments);
+ this._super.apply(this, arguments);
// Update the statustext
this.set_statustext(this.statustext);
diff --git a/etemplate/js/et2_inputWidget.js b/etemplate/js/et2_inputWidget.js
index e553846932..ff7de4dd62 100644
--- a/etemplate/js/et2_inputWidget.js
+++ b/etemplate/js/et2_inputWidget.js
@@ -59,13 +59,47 @@ var et2_inputWidget = et2_valueWidget.extend(et2_IInput, {
"description": "The label is displayed by default in front (for radiobuttons behind) each widget (if not empty). If you want to specify a different position, use a '%s' in the label, which gets replaced by the widget itself. Eg. '%s Name' to have the label Name behind a checkbox. The label can contain variables, as descript for name. If the label starts with a '@' it is replaced by the value of the content-array at this index (with the '@'-removed and after expanding the variables)."
}
},
+
init: function() {
this._super.apply(this, arguments);
this._oldValue = "";
+ this._labelContainer = null;
+ this._widgetPlaceholder = null;
+ },
+
+ destroy: function() {
+ this._super.apply(this, arguments);
+
+ this._labelContainer = null;
+ this._widgetPlaceholder = null;
},
attachToDOM: function() {
+ if (this._labelContainer)
+ {
+ // Get the DOM Node without the labelContainer - that's why null is
+ // passed here.
+ var node = this.getDOMNode(null);
+
+ if (node)
+ {
+ // Recreate the widget placeholder and return, as the set_label
+ // function will call attachToDOM again
+ if (!this._widgetPlaceholder)
+ {
+ this.set_label(this.label);
+ return;
+ }
+
+ // Insert the widget at the position of the placeholder
+ this._labelContainer.replaceChild(node, this._widgetPlaceholder);
+
+ // Set the widgetPlaceholder to null
+ this._widgetPlaceholder = null;
+ }
+ }
+
this._super.apply(this,arguments);
$j(this.getInputNode()).attr("novalidate","novalidate"); // Stop browser from getting involved
@@ -110,13 +144,60 @@ var et2_inputWidget = et2_valueWidget.extend(et2_IInput, {
}
},
- set_label: function(_label) {
- if(_label != this.label)
+ set_label: function(_value) {
+ // Copy the given value
+ this.label = _value;
+
+ // Detach the current element from the DOM
+ var attached = this.isAttached();
+ if (attached)
{
- this.label = (typeof _label == 'undefined' ? "" : _label);
- var label = et2_csvSplit(_label, 2, '%s');
- if(label[0]) $j(this.getInputNode()).before(""+label[0]+"");
- if(label[1]) $j(this.getInputNode()).after(""+label[1]+"");
+ this.detatchFromDOM();
+ }
+
+ if (_value)
+ {
+ // Create the label container if it didn't exist yet
+ if (this._labelContainer == null)
+ {
+ this._labelContainer = document.createElement("span");
+ }
+
+ // Clear the label container.
+ for (;this._labelContainer.childNodes.length > 0;)
+ {
+ this._labelContainer.removeChild(this._labelContainer.childNodes[0]);
+ }
+
+ // Create the placeholder element
+ this._widgetPlaceholder = document.createElement("span");
+
+ // Split the label at the "%s"
+ var parts = et2_csvSplit(_value, 2, "%s");
+
+ // Create the content of the label container
+ for (var i = 0; i < parts.length; i++)
+ {
+ if (parts[i])
+ {
+ this._labelContainer.appendChild(document.createTextNode(parts[i]));
+ }
+ if (i == 0)
+ {
+ this._labelContainer.appendChild(this._widgetPlaceholder);
+ }
+ }
+ }
+ else
+ {
+ this._labelContainer = null;
+ this._widgetPlaceholder = null;
+ }
+
+ // Attach the current element to the DOM again
+ if (attached)
+ {
+ this.attachToDOM();
}
},
@@ -133,14 +214,23 @@ var et2_inputWidget = et2_valueWidget.extend(et2_IInput, {
},
- get_value: function() {
- return this.getValue();
+ getDOMNode: function(_sender) {
+ if (_sender == this && this._labelContainer)
+ {
+ return this._labelContainer;
+ }
+
+ return this._super.apply(this, arguments);
},
getInputNode: function() {
return this.node;
},
+ get_value: function() {
+ return this.getValue();
+ },
+
getValue: function() {
var node = this.getInputNode();
if (node)
diff --git a/etemplate/js/et2_selectbox.js b/etemplate/js/et2_selectbox.js
index e506f41af9..13173dade4 100644
--- a/etemplate/js/et2_selectbox.js
+++ b/etemplate/js/et2_selectbox.js
@@ -66,7 +66,7 @@ var et2_selectbox = et2_inputWidget.extend({
this.input = null;
},
- parseArrayMgrAttrs: function(_attrs) {
+ transformAttributes: function(_attrs) {
// Try to find the options inside the "sel-options" array
_attrs["select_options"] = this.getArrayMgr("sel_options").getValueForID(this.id);
@@ -193,7 +193,7 @@ var et2_menulist = et2_DOMWidget.extend({
// Just pass the parent DOM node through
getDOMNode: function(_sender) {
- if (_sender != this._parent && _sender != this)
+ if (_sender != this)
{
return this._parent.getDOMNode(this);
}
diff --git a/etemplate/js/et2_valueWidget.js b/etemplate/js/et2_valueWidget.js
index 0fdf35ed81..fd0be0c3bb 100644
--- a/etemplate/js/et2_valueWidget.js
+++ b/etemplate/js/et2_valueWidget.js
@@ -33,7 +33,7 @@ var et2_valueWidget = et2_baseWidget.extend({
}
},
- parseArrayMgrAttrs: function(_attrs) {
+ transformAttributes: function(_attrs) {
this._super.call(this, arguments);
if (this.id != "")
diff --git a/etemplate/js/et2_widget.js b/etemplate/js/et2_widget.js
index 5f5a7647bb..5dd8a29bed 100644
--- a/etemplate/js/et2_widget.js
+++ b/etemplate/js/et2_widget.js
@@ -145,7 +145,7 @@ var et2_widget = Class.extend({
// Add all attributes hidden in the content arrays to the attributes
// parameter
- this.parseArrayMgrAttrs(_attrs);
+ this.transformAttributes(_attrs);
}
// Create a local copy of the options object
@@ -430,7 +430,7 @@ var et2_widget = Class.extend({
}
},
- parseArrayMgrAttrs: function() {
+ transformAttributes: function() {
},
createElementFromNode: function(_node) {
diff --git a/etemplate/js/test/et2_test_basic_widgets.xet b/etemplate/js/test/et2_test_basic_widgets.xet
index ba2a6982a6..5bc7812bb2 100644
--- a/etemplate/js/test/et2_test_basic_widgets.xet
+++ b/etemplate/js/test/et2_test_basic_widgets.xet
@@ -1,33 +1,35 @@