Implemented usage of mutliple array-manager objects (the object which cares about proper namespacing etc.) for each supplied data manager part (like 'content', 'readonlys' etc.), renamed et2_contentArrayMgr.js to et2_arrayMgr.js, renamed et2_all.js to etemplate2.js and added an top-level object which cares about loading the template, creating the array managers etc.

This commit is contained in:
Andreas Stöckel 2011-08-15 12:34:00 +00:00
parent be34748b32
commit 8c9fd0f636
11 changed files with 231 additions and 154 deletions

View File

@ -92,7 +92,7 @@ class etemplate_new
}
else // first call
*/ {
egw_framework::validate_file('.','et2_all','etemplate');
egw_framework::validate_file('.','etemplate2','etemplate');
egw_framework::includeCSS('/etemplate/js/test/test.css');
common::egw_header();
@ -103,24 +103,8 @@ class etemplate_new
echo '
<div id="container"></div>
<script>
var container = null;
function open_xet(file, content) {
et2_loadXMLFromURL(file,
function(_xmldoc) {
if (container != null)
{
container.destroy();
container = null;
}
container = new et2_container(null);
container.setParentDOMNode(document.getElementById("container"));
container.setContentMgr(new et2_contentArrayMgr(content));
container.loadFromXML(_xmldoc);
});
}
open_xet("'.$GLOBALS['egw_info']['server']['webserver_url'].$this->rel_path.'",'.json_encode(array(
var et2 = new etemplate2(document.getElementById("container"), "");
et2.load("'.$GLOBALS['egw_info']['server']['webserver_url'].$this->rel_path.'",'.json_encode(array(
'content' => $content,
'sel_options' => $sel_options,
'readonlys' => $readonlys,

View File

@ -1,27 +0,0 @@
/**
* eGroupWare eTemplate2 - JS file which contains the complete et2 module
*
* @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$
*/
/**
* Only include the actual widget class files here, all other dependencies are
* included in those files.
*/
/*egw:uses
et2_template;
et2_grid;
et2_box;
// et2_tabs;
et2_button;
et2_description;
et2_textbox;
*/

View File

@ -12,7 +12,7 @@
"use strict";
function et2_contentArrayMgr(_data, _parentMgr)
function et2_arrayMgr(_data, _parentMgr)
{
if (typeof _parentMgr == "undefined")
{
@ -44,7 +44,7 @@ function et2_contentArrayMgr(_data, _parentMgr)
/**
* Returns the root content array manager object
*/
et2_contentArrayMgr.prototype.getRoot = function()
et2_arrayMgr.prototype.getRoot = function()
{
if (this.parentMgr != null)
{
@ -54,7 +54,7 @@ et2_contentArrayMgr.prototype.getRoot = function()
return this;
}
et2_contentArrayMgr.prototype.getValueForID = function(_id)
et2_arrayMgr.prototype.getValueForID = function(_id)
{
if (typeof this.data[_id] != "undefined")
{
@ -70,7 +70,7 @@ et2_contentArrayMgr.prototype.getValueForID = function(_id)
*
* @param _path is used internally, do not supply it manually.
*/
et2_contentArrayMgr.prototype.getPath = function(_path)
et2_arrayMgr.prototype.getPath = function(_path)
{
if (typeof _path == "undefined")
{
@ -101,7 +101,7 @@ et2_contentArrayMgr.prototype.getPath = function(_path)
* @param _skipEmpty returns false if _key is not present in this content array.
* Defaults to false.
*/
et2_contentArrayMgr.prototype.getEntry = function(_key, _referenceInto,
et2_arrayMgr.prototype.getEntry = function(_key, _referenceInto,
_skipEmpty)
{
if (typeof _referenceInto == "undefined")
@ -147,7 +147,7 @@ et2_contentArrayMgr.prototype.getEntry = function(_key, _referenceInto,
* Expands variables inside the given identifier to their values inside the
* content array.
*/
et2_contentArrayMgr.prototype.expandName = function(_ident)
et2_arrayMgr.prototype.expandName = function(_ident)
{
// Check whether the identifier refers to an index in the content array
var is_index_in_content = _ident.charAt(0) == '@';
@ -176,7 +176,7 @@ et2_contentArrayMgr.prototype.expandName = function(_ident)
return _ident;
}
et2_contentArrayMgr.prototype.parseBoolExpression = function(_expression)
et2_arrayMgr.prototype.parseBoolExpression = function(_expression)
{
// If the first char of the expression is a '!' this means, that the value
// is to be negated.
@ -212,14 +212,14 @@ et2_contentArrayMgr.prototype.parseBoolExpression = function(_expression)
return val != '' && (typeof val != "string" || val.toLowerCase() != "false");
}
et2_contentArrayMgr.prototype.openPerspective = function(_owner, _root, _col, _row)
et2_arrayMgr.prototype.openPerspective = function(_owner, _root, _col, _row)
{
// Get the root node
var root = typeof _root == "string" ? this.data[_root] :
(_root == null ? this.data : _root);
// Create a new content array manager with the given root
var mgr = new et2_contentArrayMgr(root, this);
var mgr = new et2_arrayMgr(root, this);
// Set the owner
mgr.perspectiveData.owner = _owner;

View File

@ -353,4 +353,18 @@ function et2_csvSplit(_str, _num, _delimiter, _enclosure)
return parts;
}
/**
* Creates a copy of the given object (non recursive)
*/
function et2_cloneObject(_obj)
{
var result = {};
for (var key in _obj)
{
result[key] = _obj[key];
}
return result;
}

View File

@ -88,7 +88,7 @@ var et2_inputWidget = et2_baseWidget.extend(et2_IInput, {
}
// Set the value for this element
var mgr = this.getContentMgr();
var mgr = this.getArrayMgr("content");
if (_value != '' && mgr != null)
{
var val = mgr.getValueForID(this.id);

View File

@ -16,7 +16,7 @@
et2_xml;
et2_common;
et2_inheritance;
et2_contentArrayMgr;
et2_arrayMgr;
*/
/**
@ -100,7 +100,7 @@ var et2_widget = Class.extend({
}
this.id = "";
this._mgr = null;
this._mgrs = {};
// Copy the parent parameter and add this widget to its parent children
// list.
@ -145,7 +145,7 @@ var et2_widget = Class.extend({
// Delete all references to other objects
this._children = [];
this._parent = null;
this._mgr = null;
this._mgrs = {};
this.onSetParent();
},
@ -188,10 +188,7 @@ var et2_widget = Class.extend({
}
// Copy a reference to the content array manager
if (_obj._mgr)
{
this._mgr = _obj._mgr;
}
this.setArrayMgrs(_obj.mgrs);
},
/**
@ -453,12 +450,12 @@ var et2_widget = Class.extend({
// expression as bool expression.
if (attr.type == "boolean")
{
attrValue = this.getContentMgr()
attrValue = this.getArrayMgr("content")
.parseBoolExpression(attrValue);
}
else
{
attrValue = this.getContentMgr().expandName(attrValue);
attrValue = this.getArrayMgr("content").expandName(attrValue);
}
}
@ -497,23 +494,6 @@ var et2_widget = Class.extend({
}
},
setContentMgr: function(_mgr) {
this._mgr = _mgr;
},
getContentMgr: function() {
if (this._mgr != null)
{
return this._mgr;
}
else if (this._parent)
{
return this._parent.getContentMgr();
}
return null;
},
/**
* Fetches all input element values and returns them in an associative
* array. Widgets which introduce namespacing can use the internal _target
@ -566,6 +546,67 @@ var et2_widget = Class.extend({
return result;
},
/**
* Sets all array manager objects - this function can be used to set the
* root array managers of the container object.
*/
setArrayMgrs: function(_mgrs) {
this._mgrs = et2_cloneObject(_mgrs);
},
/**
* Returns an associative array containing the top-most array managers.
*
* @param _mgrs is used internally and should not be supplied.
*/
getArrayMgrs: function(_mgrs) {
if (typeof _mgrs == "undefined")
{
_mgrs = {};
}
// 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)
{
if (typeof _mgrs[key] == "undefined")
{
_mgrs[key] = this._mgrs[key];
}
}
// Recursively applies this function to the parent widget
if (this._parent)
{
this._parent.getArrayMgrs(_mgrs);
}
return _mgrs;
},
/**
* Sets the array manager for the given part
*/
setArrayMgr: function(_part, _mgr) {
this._mgrs[_part] = _mgr;
},
/**
* Returns the array manager object for the given part
*/
getArrayMgr: function(_part) {
if (typeof this._mgrs[_part] != "undefined")
{
return this._mgrs[_part];
}
else if (this._parent)
{
return this._parent.getArrayMgr(_part);
}
return null;
},
/**
* Checks whether a namespace exists for this element in the content array.
* If yes, an own perspective of the content array is created. If not, the
@ -573,27 +614,32 @@ var et2_widget = Class.extend({
*/
checkCreateNamespace: function() {
// Get the content manager
var mgr = this.getContentMgr();
var mgrs = this.getArrayMgrs();
// Get the original content manager if we have already created a
// perspective for this node
if (this._mgr != null && this._mgr.perspectiveData.owner == this)
for (var key in mgrs)
{
mgr = mgr.parentMgr;
}
var mgr = mgrs[key];
// Check whether the manager has a namespace for the id of this object
if (mgr.getEntry(this.id) instanceof Object)
{
// The content manager has a own node for this object, so create
// an own perspective.
this._mgr = mgr.openPerspective(this, this.id);
}
else
{
// The current content manager does not have an own namespace for
// this element, so use the content manager of the parent.
this._mgr = null;
// Get the original content manager if we have already created a
// perspective for this node
if (typeof this._mgrs[key] != "undefined" && mgr.perspectiveData.owner == this)
{
mgr = mgr.parentMgr;
}
// Check whether the manager has a namespace for the id of this object
if (mgr.getEntry(this.id) instanceof Object)
{
// The content manager has an own node for this object, so
// create an own perspective.
this._mgrs[key] = mgr.openPerspective(this, this.id);
}
else
{
// The current content manager does not have an own namespace for
// this element, so use the content manager of the parent.
delete(this._mgrs[key]);
}
}
}
});

View File

@ -0,0 +1,97 @@
/**
* eGroupWare eTemplate2 - JS file which contains the complete et2 module
*
* @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
// Include all widget classes here
et2_template;
et2_grid;
et2_box;
et2_button;
et2_description;
et2_textbox;
// Requirements for the etemplate2 object
et2_xml;
et2_arrayMgr;
*/
/**
* The etemplate2 class manages a certain etemplate2 instance.
*
* @param _container is the DOM-Node into which the DOM-Nodes of this instance
* should be inserted
* @param _submitURL is the URL to which the form data should be submitted.
*/
function etemplate2(_container, _submitURL)
{
// Copy the given parameters
this.DOMContainer = _container;
this.submitURL = _submitURL;
// Preset the object variable
this.widgetContainer = null;
}
/**
* Clears the current instance.
*/
etemplate2.prototype.clear = function()
{
if (this.widgetContainer != null)
{
this.widgetContainer.destroy();
this.widgetContainer = null;
}
}
/**
* Creates an associative array containing the data array managers for each part
* of the associative data array. A part is something like "content", "readonlys"
* or "sel_options".
*/
etemplate2.prototype._createArrayManagers = function(_data)
{
var result = {};
// Create an array manager object for each part of the _data array.
for (var key in _data)
{
result[key] = new et2_arrayMgr(_data[key]);
}
return result;
}
/**
* Loads the template from the given URL and sets the data object
*/
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) {
this.widgetContainer.loadFromXML(_xmldoc);
}, this);
// Clear any existing instance
this.clear();
// Create the basic widget container and attach it to the DOM
this.widgetContainer = new et2_container(null);
this.widgetContainer.setParentDOMNode(this.DOMContainer);
// Split the given data into array manager objects and pass those to the
// widget container
this.widgetContainer.setArrayMgrs(this._createArrayManagers(_data));
}

View File

@ -1,9 +1,11 @@
var expression_test_data = {
"test": {
"display_text": "true",
"textbox": "And this is the inner textbox."
},
"display_text": "false",
"textbox": "This is the outer textbox."
"content": {
"test": {
"display_text": "true",
"textbox": "And this is the inner textbox."
},
"display_text": "false",
"textbox": "This is the outer textbox."
}
};

View File

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

View File

@ -70,26 +70,6 @@ var timesheet_data = {
"tabs":{
"customfields":true
}
},
"preserv":{
"ts_id":"1",
"ts_project":null,
"ts_title":"Test geschrieben",
"ts_description":null,
"ts_start":1307030400,
"ts_duration":"150",
"ts_quantity":"2.5",
"ts_unitprice":null,
"cat_id":null,
"ts_owner":"5",
"ts_modified":1307039479,
"ts_modifier":"5",
"pl_id":null,
"ts_status":null,
"user_timezone_read":"Europe/Berlin",
"view":false,
"referer":"timesheet.timesheet_ui.index",
"ts_title_blur":null
}
}

View File

@ -6,6 +6,7 @@
<script src="../et2_xml.js"></script>
<script src="../et2_inheritance.js"></script>
<script src="../et2_common.js"></script>
<script src="../et2_arrayMgr.js"></script>
<script src="../et2_widget.js"></script>
<script src="../et2_DOMWidget.js"></script>
<script src="../et2_baseWidget.js"></script>
@ -16,7 +17,9 @@
<script src="../et2_button.js"></script>
<script src="../et2_box.js"></script>
<script src="../et2_textbox.js"></script>
<script src="../et2_contentArrayMgr.js"></script>
<script src="../etemplate2.js"></script>
<!--<script src="../et2_tabs.js"></script>-->
<script src="../lib/tooltip.js"></script>
@ -28,7 +31,7 @@
<h1>EGroupware ETemplate2 Test</h1>
<div class="header">Choose one of the following tests:</div>
<div id="linklist">
<a href="#" onclick="open_xet('et2_test_timesheet_edit.xet', timesheet_data.content);">Timesheet edit dialog</a>
<a href="#" onclick="open_xet('et2_test_timesheet_edit.xet', timesheet_data);">Timesheet edit dialog</a>
<a href="#" onclick="open_xet('et2_test_template.xet');">Template proxy test</a>
<a href="#" onclick="open_xet('et2_test_grid.xet');">Grid test</a>
<a href="#" onclick="open_xet('et2_test_tabbox.xet');">Tabs test</a>
@ -40,33 +43,11 @@
<div id="time"></div>
<div id="container"></div>
<script>
var container = null;
var et2 = new etemplate2(document.getElementById("container"), "");
function open_xet(file, content) {
if (typeof content == "undefined")
{
content = {};
}
et2_loadXMLFromURL(file,
function(_xmldoc) {
if (container != null)
{
container.destroy();
container = null;
}
var t1 = (new Date).getTime();
container = new et2_container(null);
container.setParentDOMNode(document.getElementById("container"));
container.setContentMgr(new et2_contentArrayMgr(content));
container.loadFromXML(_xmldoc);
var t2 = (new Date).getTime();
$j("#time").text("Building the template took " + (t2 - t1) + "ms");
});
}
et2.load(file, content);
}
</script>
</body>
</html>