- Reading readonly properties

- Added system for readonlys: Readonly is passed in constructor as third parameter. If a widget class is registerd with "[type]_ro" (see et2_textbox for example) this one is created
- Added new 'valueWidget' base class which introduces the 'value' attribute and implements auto loading from the content array
- Implemented readonly attribute for buttons and textboxes
This commit is contained in:
Andreas Stöckel 2011-08-16 12:31:18 +00:00
parent 697a113171
commit 41787c36f3
15 changed files with 398 additions and 257 deletions

View File

@ -10,10 +10,17 @@
* @version $Id$ * @version $Id$
*/ */
/*egw:uses
et2_inheritance;
*/
"use strict"; "use strict";
function et2_arrayMgr(_data, _parentMgr) var et2_arrayMgr = Class.extend({
{
splitIds: true,
init: function(_data, _parentMgr) {
if (typeof _parentMgr == "undefined") if (typeof _parentMgr == "undefined")
{ {
_parentMgr = null; _parentMgr = null;
@ -39,30 +46,28 @@ function et2_arrayMgr(_data, _parentMgr)
"col": 0, "col": 0,
"row": 0 "row": 0
} }
} },
/** /**
* Returns the root content array manager object * Returns the root content array manager object
*/ */
et2_arrayMgr.prototype.getRoot = function() getRoot : function() {
{
if (this.parentMgr != null) if (this.parentMgr != null)
{ {
return this.parentMgr.getRoot(); return this.parentMgr.getRoot();
} }
return this; return this;
} },
et2_arrayMgr.prototype.getValueForID = function(_id) getValueForID : function(_id) {
{
if (typeof this.data[_id] != "undefined") if (typeof this.data[_id] != "undefined")
{ {
return this.data[_id]; return this.data[_id];
} }
return null; return null;
} },
/** /**
* Returns the path to this content array manager perspective as an array * Returns the path to this content array manager perspective as an array
@ -70,8 +75,7 @@ et2_arrayMgr.prototype.getValueForID = function(_id)
* *
* @param _path is used internally, do not supply it manually. * @param _path is used internally, do not supply it manually.
*/ */
et2_arrayMgr.prototype.getPath = function(_path) getPath : function(_path) {
{
if (typeof _path == "undefined") if (typeof _path == "undefined")
{ {
_path = []; _path = [];
@ -88,7 +92,7 @@ et2_arrayMgr.prototype.getPath = function(_path)
} }
return _path; return _path;
} },
/** /**
* Get array entry is the equivalent to the boetemplate get_array function. * Get array entry is the equivalent to the boetemplate get_array function.
@ -101,9 +105,7 @@ et2_arrayMgr.prototype.getPath = function(_path)
* @param _skipEmpty returns false if _key is not present in this content array. * @param _skipEmpty returns false if _key is not present in this content array.
* Defaults to false. * Defaults to false.
*/ */
et2_arrayMgr.prototype.getEntry = function(_key, _referenceInto, getEntry : function(_key, _referenceInto, _skipEmpty) {
_skipEmpty)
{
if (typeof _referenceInto == "undefined") if (typeof _referenceInto == "undefined")
{ {
_referenceInto = false; _referenceInto = false;
@ -115,7 +117,12 @@ et2_arrayMgr.prototype.getEntry = function(_key, _referenceInto,
} }
// Parse the given key by removing the "]"-chars and splitting at "[" // Parse the given key by removing the "]"-chars and splitting at "["
var indexes = _key.replace(/]/g,'').split('['); var indexes = [_key];
if (this.splitIds)
{
indexes = _key.replace(/]/g,'').split('[');
}
var entry = this.data; var entry = this.data;
for (var i = 0; i < indexes.length; i++) for (var i = 0; i < indexes.length; i++)
@ -125,21 +132,21 @@ et2_arrayMgr.prototype.getEntry = function(_key, _referenceInto,
var isObject = entry instanceof Object; var isObject = entry instanceof Object;
if (!isObject && !_referenceInto) if (!isObject && !_referenceInto)
{ {
return false; return null;
} }
// Check whether the entry actually exists // Check whether the entry actually exists
var idx = indexes[i]; var idx = indexes[i];
if (_skipEmpty && (!isObject || typeof entry[idx] == "undefined")) if (_skipEmpty && (!isObject || typeof entry[idx] == "undefined"))
{ {
return false; return null;
} }
entry = entry[idx]; entry = entry[idx];
} }
return entry; return entry;
} },
/** /**
* Equivaltent to the boetemplate::expand_name function. * Equivaltent to the boetemplate::expand_name function.
@ -147,8 +154,7 @@ et2_arrayMgr.prototype.getEntry = function(_key, _referenceInto,
* Expands variables inside the given identifier to their values inside the * Expands variables inside the given identifier to their values inside the
* content array. * content array.
*/ */
et2_arrayMgr.prototype.expandName = function(_ident) expandName : function(_ident) {
{
// Check whether the identifier refers to an index in the content array // Check whether the identifier refers to an index in the content array
var is_index_in_content = _ident.charAt(0) == '@'; var is_index_in_content = _ident.charAt(0) == '@';
@ -174,10 +180,9 @@ et2_arrayMgr.prototype.expandName = function(_ident)
} }
return _ident; return _ident;
} },
et2_arrayMgr.prototype.parseBoolExpression = function(_expression) parseBoolExpression: function(_expression) {
{
// If the first char of the expression is a '!' this means, that the value // If the first char of the expression is a '!' this means, that the value
// is to be negated. // is to be negated.
if (_expression.charAt(0) == '!') if (_expression.charAt(0) == '!')
@ -210,9 +215,9 @@ et2_arrayMgr.prototype.parseBoolExpression = function(_expression)
} }
return val != '' && (typeof val != "string" || val.toLowerCase() != "false"); return val != '' && (typeof val != "string" || val.toLowerCase() != "false");
} },
et2_arrayMgr.prototype.openPerspective = function(_owner, _root, _col, _row) openPerspective: function(_owner, _root, _col, _row)
{ {
// Get the root node // Get the root node
var root = typeof _root == "string" ? this.data[_root] : var root = typeof _root == "string" ? this.data[_root] :
@ -240,3 +245,42 @@ et2_arrayMgr.prototype.openPerspective = function(_owner, _root, _col, _row)
return mgr; return mgr;
} }
});
var et2_readonlysArrayMgr = et2_arrayMgr.extend({
splitIds: false,
isReadOnly: function(_id, _attr, _parent) {
var entry = null;
if (_id != null)
{
entry = this.getEntry(_id);
}
// Let the array entry override the read only attribute entry
if (typeof entry != "undefined" && !(entry instanceof Object))
{
return entry;
}
// If the attribute is set, return that
if (typeof _attr != "undefined" && _attr !== null)
{
return et2_evalBool(_attr);
}
// Otherwise take into accounf whether the parent is readonly
if (typeof _parent != "undefined" && _parent)
{
return true;
}
// Otherwise return the default value
return (typeof this.getEntry("__ALL__") != "undefined");
}
});

View File

@ -37,17 +37,21 @@ var et2_button = et2_baseWidget.extend(et2_IInput, {
} }
}, },
init: function(_parent) { init: function(_parent, _type, _readonly) {
this._super.apply(this, arguments); this._super.apply(this, arguments);
this.label = ""; this.label = "";
this.clicked = false; this.clicked = false;
this.btn = null;
if (!_readonly)
{
this.btn = $j(document.createElement("button")) this.btn = $j(document.createElement("button"))
.addClass("et2_button") .addClass("et2_button")
.click(this, function(e) {e.data.buttonClick()}); .click(this, function(e) {e.data.buttonClick()});
this.setDOMNode(this.btn[0]); this.setDOMNode(this.btn[0]);
}
}, },
buttonClick: function() { buttonClick: function() {
@ -65,7 +69,7 @@ var et2_button = et2_baseWidget.extend(et2_IInput, {
}, },
set_label: function(_value) { set_label: function(_value) {
if (_value != this.value) if (this.btn)
{ {
this.label = _value; this.label = _value;

View File

@ -87,6 +87,11 @@ var et2_typeDefaults = {
"any": null "any": null
}; };
function et2_evalBool(_val)
{
return _val ? true : false;
}
/** /**
* Checks whether the given value is of the given type. Strings are converted * Checks whether the given value is of the given type. Strings are converted
* into the corresponding type. The (converted) value is returned. All supported * into the corresponding type. The (converted) value is returned. All supported

View File

@ -88,24 +88,18 @@ var et2_description = et2_baseWidget.extend({
this.setDOMNode(this.span[0]); this.setDOMNode(this.span[0]);
}, },
set_value: function(_value, _force) { set_value: function(_value) {
if (_value != this.value || _force)
{
this.value = _value; this.value = _value;
this.span.text(_value); this.span.text(_value);
}
}, },
set_font_style: function(_value) { set_font_style: function(_value) {
if (_value != this.font_style)
{
this.font_style = _value; this.font_style = _value;
this.span.toggleClass("et2_bold", _value.indexOf("b") >= 0); this.span.toggleClass("et2_bold", _value.indexOf("b") >= 0);
this.span.toggleClass("et2_italic", _value.indexOf("i") >= 0); this.span.toggleClass("et2_italic", _value.indexOf("i") >= 0);
} }
}
}); });

View File

@ -48,6 +48,8 @@ var et2_grid = et2_DOMWidget.extend({
// Delete all references to cells or widgets // Delete all references to cells or widgets
this.cells = null; this.cells = null;
this.managementArray = null; this.managementArray = null;
this.table = null;
this.tbody = null;
}, },
_initCells: function(_colData, _rowData) { _initCells: function(_colData, _rowData) {

View File

@ -314,7 +314,7 @@
} }
else else
{ {
et2_error("error", this, "Attribute '" + _name + "' does not exist!"); et2_debug("error", this, "Attribute '" + _name + "' does not exist!");
} }
} }

View File

@ -14,7 +14,7 @@
/*egw:uses /*egw:uses
jquery.jquery; jquery.jquery;
et2_baseWidget; et2_valueWidget;
*/ */
/** /**
@ -43,16 +43,7 @@ var et2_IInput = new Interface({
* interface. When derriving from this class, call setDOMNode with an input * interface. When derriving from this class, call setDOMNode with an input
* DOMNode. * DOMNode.
*/ */
var et2_inputWidget = et2_baseWidget.extend(et2_IInput, { var et2_inputWidget = et2_valueWidget.extend(et2_IInput, {
attributes: {
"value": {
"name": "Value",
"description": "The value of the widget",
"type": "string",
"default": et2_no_init
}
},
init: function() { init: function() {
this._super.apply(this, arguments); this._super.apply(this, arguments);
@ -60,21 +51,6 @@ var et2_inputWidget = et2_baseWidget.extend(et2_IInput, {
this._oldValue = ""; this._oldValue = "";
}, },
loadingFinished: function() {
this._super.call(this, arguments);
if (this.id != "")
{
// Set the value for this element
var contentMgr = this.getArrayMgr("content");
var val = contentMgr.getValueForID(this.id);
if (val !== null)
{
this.set_value(val);
}
}
},
set_value: function(_value) { set_value: function(_value) {
this._oldValue = _value; this._oldValue = _value;

View File

@ -15,6 +15,7 @@
/*egw:uses /*egw:uses
jquery.jquery; jquery.jquery;
et2_inputWidget; et2_inputWidget;
et2_valueWidget;
*/ */
/** /**
@ -71,3 +72,37 @@ var et2_textbox = et2_inputWidget.extend({
et2_register_widget(et2_textbox, ["textbox", "int", "float"]); et2_register_widget(et2_textbox, ["textbox", "int", "float"]);
/**
* et2_textbox_ro is the dummy readonly implementation of the textbox.
*/
var et2_textbox_ro = et2_valueWidget.extend({
/**
* Ignore all more advanced attributes.
*/
attributes: {
"multiline": {
"ignore": true
}
},
init: function() {
this._super.apply(this, arguments);
this.value = "";
this.span = $j(document.createElement("span"))
.addClass("et2_textbox_ro");
this.setDOMNode(this.span[0]);
},
set_value: function(_value) {
this.value = _value;
this.span.text(_value);
}
});
et2_register_widget(et2_textbox_ro, ["textbox_ro", "int_ro", "float_ro"]);

View File

@ -0,0 +1,50 @@
/**
* eGroupWare eTemplate2 - JS widget class with value attribute and auto loading
*
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package etemplate
* @subpackage api
* @link http://www.egroupware.org
* @author Andreas Stöckel
* @copyright Stylite 2011
* @version $Id$
*/
/*egw:uses
jquery.jquery;
et2_baseWidget;
*/
/**
* et2_valueWidget is the base class for et2_inputWidget - valueWidget introduces
* the "value" attribute and automatically loads it from the "content" array
* after loading from XML.
*/
var et2_valueWidget = et2_baseWidget.extend({
attributes: {
"value": {
"name": "Value",
"description": "The value of the widget",
"type": "string",
"default": et2_no_init
}
},
loadingFinished: function() {
this._super.call(this, arguments);
if (this.id != "")
{
// Set the value for this element
var contentMgr = this.getArrayMgr("content");
var val = contentMgr.getValueForID(this.id);
if (val !== null)
{
this.setAttribute("value", val)
}
}
}
});

View File

@ -74,6 +74,14 @@ var et2_widget = Class.extend({
*/ */
"type": { "type": {
"ignore": true "ignore": true
},
/**
* Ignore the readonly tag by default - its also read by the
* "createElementFromNode" function.
*/
"readonly": {
"ignore": true
} }
}, },
@ -92,7 +100,7 @@ var et2_widget = Class.extend({
* @param _type is the node name with which the widget has been created. This * @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. * is usefull if a single widget class implements multiple XET-Node widgets.
*/ */
init: function(_parent, _type) { init: function(_parent, _type, _readonly) {
if (typeof _type == "undefined") if (typeof _type == "undefined")
{ {
@ -115,6 +123,7 @@ var et2_widget = Class.extend({
this._children = []; this._children = [];
this.type = _type; this.type = _type;
this.readonly = _readonly;
// The supported widget classes array defines a whitelist for all widget // The supported widget classes array defines a whitelist for all widget
// classes or interfaces child widgets have to support. // classes or interfaces child widgets have to support.
@ -164,7 +173,7 @@ var et2_widget = Class.extend({
} }
// Create the copy // Create the copy
var copy = new (this.constructor)(_parent, _type); var copy = new (this.constructor)(_parent, _type, this.readonly);
// Assign this element to the copy // Assign this element to the copy
copy.assign(this); copy.assign(this);
@ -374,13 +383,24 @@ var et2_widget = Class.extend({
_nodeName = _node.nodeName.toLowerCase(); _nodeName = _node.nodeName.toLowerCase();
} }
// Check whether a widget with the given type is registered. // Get the constructor for that widget
var constructor = typeof et2_registry[_nodeName] == "undefined" ? var constructor = typeof et2_registry[_nodeName] == "undefined" ?
et2_placeholder : et2_registry[_nodeName]; 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 readonly = this.getArrayMgr("readonlys").isReadOnly(
_node.getAttribute("id"), _node.getAttribute("readonly"), this.readonly);
et2_debug("log", _node.getAttribute("id"), readonly);
if (readonly && typeof et2_registry[_nodeName + "_ro"] != "undefined")
{
constructor = et2_registry[_nodeName + "_ro"];
}
// Creates the new widget, passes this widget as an instance and // Creates the new widget, passes this widget as an instance and
// passes the widgetType. Then it goes on loading the XML for it. // passes the widgetType. Then it goes on loading the XML for it.
var widget = new constructor(this, _nodeName) var widget = new constructor(this, _nodeName, readonly);
widget.loadFromXML(_node); widget.loadFromXML(_node);
// Call the "loadFinished" function of the widget // Call the "loadFinished" function of the widget

View File

@ -86,8 +86,14 @@ etemplate2.prototype._createArrayManagers = function(_data)
// Create an array manager object for each part of the _data array. // Create an array manager object for each part of the _data array.
for (var key in _data) for (var key in _data)
{ {
switch (key) {
case "readonlys":
result[key] = new et2_readonlysArrayMgr(_data[key]);
break;
default:
result[key] = new et2_arrayMgr(_data[key]); result[key] = new et2_arrayMgr(_data[key]);
} }
}
return result; return result;
} }

View File

@ -6,6 +6,9 @@ var expression_test_data = {
}, },
"display_text": "false", "display_text": "false",
"textbox": "This is the outer textbox." "textbox": "This is the outer textbox."
},
"readonlys": {
"__ALL__": true
} }
}; };

View File

@ -3,7 +3,7 @@
<template id="test"> <template id="test">
<vbox> <vbox>
<description disabled="!@@display_text" value="Dies ist nur ein test!" /> <description disabled="!@@display_text" value="Dies ist nur ein test!" />
<textbox id="textbox" /> <textbox id="textbox" value="Test"/>
</vbox> </vbox>
</template> </template>
<textbox id="textbox" /> <textbox id="textbox" />

View File

@ -3,7 +3,7 @@ var timesheet_data = {
"ts_id":"1", "ts_id":"1",
"ts_project":null, "ts_project":null,
"ts_title":"Test geschrieben", "ts_title":"Test geschrieben",
"ts_description":null, "ts_description":"This is just a test description",
"ts_start":1307030400, "ts_start":1307030400,
"ts_duration":"150", "ts_duration":"150",
"ts_quantity":"2.5", "ts_quantity":"2.5",
@ -69,7 +69,8 @@ var timesheet_data = {
"ts_owner":true, "ts_owner":true,
"tabs":{ "tabs":{
"customfields":true "customfields":true
} },
"ts_description": true
} }
} }

View File

@ -10,6 +10,7 @@
<script src="../et2_widget.js"></script> <script src="../et2_widget.js"></script>
<script src="../et2_DOMWidget.js"></script> <script src="../et2_DOMWidget.js"></script>
<script src="../et2_baseWidget.js"></script> <script src="../et2_baseWidget.js"></script>
<script src="../et2_valueWidget.js"></script>
<script src="../et2_inputWidget.js"></script> <script src="../et2_inputWidget.js"></script>
<script src="../et2_template.js"></script> <script src="../et2_template.js"></script>
<script src="../et2_description.js"></script> <script src="../et2_description.js"></script>