egroupware/etemplate/js/et2_core_arrayMgr.js
2011-08-24 10:18:07 +00:00

287 lines
6.2 KiB
JavaScript

/**
* eGroupWare eTemplate2 - JS content array manager
*
* @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$
*/
"use strict";
/*egw:uses
et2_core_inheritance;
*/
var et2_arrayMgr = Class.extend({
splitIds: true,
init: function(_data, _parentMgr) {
if (typeof _parentMgr == "undefined")
{
_parentMgr = null;
}
// Copy the parent manager which is needed to access relative data when
// being in a relative perspective of the manager
this.parentMgr = _parentMgr;
// Hold a reference to the data
if (typeof _data == "undefined" || !_data)
{
et2_debug("error", "Invalid data passed to content array manager!");
_data = {};
}
this.data = _data;
// Holds information about the current perspective
this.perspectiveData = {
"owner": null,
"key": null,
"col": 0,
"row": 0
}
},
/**
* Returns the root content array manager object
*/
getRoot : function() {
if (this.parentMgr != null)
{
return this.parentMgr.getRoot();
}
return this;
},
getValueForID : function(_id) {
if (typeof this.data[_id] != "undefined")
{
return this.data[_id];
}
return null;
},
/**
* Returns the path to this content array manager perspective as an array
* containing the key values
*
* @param _path is used internally, do not supply it manually.
*/
getPath : function(_path) {
if (typeof _path == "undefined")
{
_path = [];
}
if (this.perspectiveData.key != null)
{
_path.push(this.perspectiveData.key);
}
if (this.parentMgr != null)
{
this.parentMgr.getPath(_path);
}
return _path;
},
/**
* Get array entry is the equivalent to the boetemplate get_array function.
* It returns a reference to the (sub) array with the given key. This also works
* for keys using the ETemplate referencing scheme like a[b][c]
*
* @param _key is the string index, may contain sub-indices like a[b]
* @param _referenceInto if true none-existing sub-arrays/-indices get created
* to be returned as reference, else false is returned. Defaults to false
* @param _skipEmpty returns false if _key is not present in this content array.
* Defaults to false.
*/
getEntry : function(_key, _referenceInto, _skipEmpty) {
if (typeof _referenceInto == "undefined")
{
_referenceInto = false;
}
if (typeof _skipEmpty == "undefined")
{
_skipEmpty = false;
}
// Parse the given key by removing the "]"-chars and splitting at "["
var indexes = [_key];
if (this.splitIds)
{
indexes = _key.replace(/]/g,'').split('[');
}
var entry = this.data;
for (var i = 0; i < indexes.length; i++)
{
// Abort if the current entry is not an object (associative array) and
// we should descend further into it.
var isObject = entry instanceof Object;
if (!isObject && !_referenceInto)
{
return null;
}
// Check whether the entry actually exists
var idx = indexes[i];
if (_skipEmpty && (!isObject || typeof entry[idx] == "undefined"))
{
return null;
}
entry = entry[idx];
}
return entry;
},
/**
* Equivaltent to the boetemplate::expand_name function.
*
* Expands variables inside the given identifier to their values inside the
* content array.
*/
expandName : function(_ident) {
// Check whether the identifier refers to an index in the content array
var is_index_in_content = _ident.charAt(0) == '@';
// Check whether "$" occurs in the given identifier
var pos_var = _ident.indexOf('$');
if (pos_var >= 0)
{
// TODO
}
if (is_index_in_content)
{
// If an additional "@" is specified, this means that we have to return
// the entry from the root element
if (_ident.charAt(1) == '@')
{
_ident = this.getRoot().getEntry(_ident.substr(2));
}
else
{
_ident = this.getEntry(_ident.substr(1));
}
}
return _ident;
},
parseBoolExpression: function(_expression) {
// If the first char of the expression is a '!' this means, that the value
// is to be negated.
if (_expression.charAt(0) == '!')
{
return !this.parseBoolExpression(_expression.substr(1));
}
// Split the expression at a possible "="
var parts = _expression.split('=');
// Expand the first value
var val = this.expandName(parts[0]);
// If a second expression existed, test that one
if (typeof parts[1] != "undefined")
{
// Expand the second value
var 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) == '/')
{
return (new RegExp(checkVal.substr(1, checkVal.length - 2)))
.match(val) ? true : false;
}
// Otherwise check for simple equality
return val == checkVal;
}
return et2_evalBool(val);
},
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_arrayMgr(root, this);
// Set the owner
mgr.perspectiveData.owner = _owner;
// Set the root key
if (typeof _root == "string")
{
mgr.perspectiveData.key = _root;
}
// Set the _col and _row parameter
if (typeof _col != "undefined" && typeof _row != "undefined")
{
mgr.perspectiveData.col = _col;
mgr.perspectiveData.row = _row;
}
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");
}
});