2011-08-04 21:08:50 +02:00
|
|
|
/**
|
|
|
|
* eGroupWare eTemplate2 - JS Widget base class
|
|
|
|
*
|
|
|
|
* @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$
|
|
|
|
*/
|
|
|
|
|
2011-08-10 16:36:31 +02:00
|
|
|
/**
|
|
|
|
* IE Fix for array.indexOf
|
|
|
|
*/
|
|
|
|
if (typeof Array.prototype.indexOf == "undefined")
|
|
|
|
{
|
|
|
|
Array.prototype.indexOf = function(_elem) {
|
|
|
|
for (var i = 0; i < this.length; i++)
|
|
|
|
{
|
|
|
|
if (this[i] === _elem)
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* ET2_DEBUGLEVEL specifies which messages are printed to the console. Decrease
|
|
|
|
* the value of ET2_DEBUGLEVEL to get less messages.
|
|
|
|
*/
|
2011-08-10 18:23:02 +02:00
|
|
|
var ET2_DEBUGLEVEL = 4;
|
2011-08-10 16:36:31 +02:00
|
|
|
|
2011-08-15 18:03:53 +02:00
|
|
|
function et2_debug(_level)
|
2011-08-04 21:08:50 +02:00
|
|
|
{
|
|
|
|
if (typeof console != "undefined")
|
|
|
|
{
|
2011-08-15 18:03:53 +02:00
|
|
|
// Get the passed parameters and remove the first entry
|
|
|
|
var args = [];
|
|
|
|
for (var i = 1; i < arguments.length; i++)
|
|
|
|
{
|
|
|
|
args.push(arguments[i]);
|
|
|
|
}
|
|
|
|
|
2011-08-10 16:36:31 +02:00
|
|
|
if (_level == "log" && ET2_DEBUGLEVEL >= 4 &&
|
|
|
|
typeof console.log == "function")
|
2011-08-04 21:08:50 +02:00
|
|
|
{
|
2011-08-15 18:03:53 +02:00
|
|
|
console.log.apply(console, args);
|
2011-08-04 21:08:50 +02:00
|
|
|
}
|
|
|
|
|
2011-08-10 16:36:31 +02:00
|
|
|
if (_level == "info" && ET2_DEBUGLEVEL >= 3 &&
|
|
|
|
typeof console.info == "function")
|
|
|
|
{
|
2011-08-15 18:03:53 +02:00
|
|
|
console.info.apply(console, args);
|
2011-08-10 16:36:31 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (_level == "warn" && ET2_DEBUGLEVEL >= 2 &&
|
|
|
|
typeof console.warn == "function")
|
2011-08-04 21:08:50 +02:00
|
|
|
{
|
2011-08-15 18:03:53 +02:00
|
|
|
console.warn.apply(console, args);
|
2011-08-04 21:08:50 +02:00
|
|
|
}
|
|
|
|
|
2011-08-10 16:36:31 +02:00
|
|
|
if (_level == "error" && ET2_DEBUGLEVEL >= 1 &&
|
|
|
|
typeof console.error == "function")
|
2011-08-04 21:08:50 +02:00
|
|
|
{
|
2011-08-15 18:03:53 +02:00
|
|
|
console.error.apply(console, args);
|
2011-08-04 21:08:50 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-08-05 16:53:54 +02:00
|
|
|
/**
|
2011-08-10 16:36:31 +02:00
|
|
|
* Array with all types supported by the et2_checkType function.
|
2011-08-05 16:53:54 +02:00
|
|
|
*/
|
2011-08-15 11:24:32 +02:00
|
|
|
var et2_validTypes = ["boolean", "string", "float", "integer", "any", "js"];
|
2011-08-10 16:36:31 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Object whith default values for the above types. Do not specify array or
|
|
|
|
* objects inside the et2_typeDefaults object, as this instance will be shared
|
|
|
|
* between all users of it.
|
|
|
|
*/
|
|
|
|
var et2_typeDefaults = {
|
|
|
|
"boolean": false,
|
|
|
|
"string": "",
|
2011-08-15 11:24:32 +02:00
|
|
|
"js": null,
|
2011-08-10 16:36:31 +02:00
|
|
|
"float": 0.0,
|
|
|
|
"integer": 0,
|
|
|
|
"any": null
|
|
|
|
};
|
|
|
|
|
2011-08-16 14:31:18 +02:00
|
|
|
function et2_evalBool(_val)
|
|
|
|
{
|
|
|
|
return _val ? true : false;
|
|
|
|
}
|
|
|
|
|
2011-08-10 16:36:31 +02:00
|
|
|
/**
|
|
|
|
* Checks whether the given value is of the given type. Strings are converted
|
|
|
|
* into the corresponding type. The (converted) value is returned. All supported
|
|
|
|
* types are listed in the et2_validTypes array.
|
|
|
|
*/
|
2011-08-16 15:45:41 +02:00
|
|
|
function et2_checkType(_val, _type, _attr)
|
2011-08-05 16:53:54 +02:00
|
|
|
{
|
2011-08-16 15:45:41 +02:00
|
|
|
if (typeof _attr == "undefined")
|
|
|
|
{
|
|
|
|
_attr = null;
|
|
|
|
}
|
|
|
|
|
2011-08-10 16:36:31 +02:00
|
|
|
function _err() {
|
2011-08-16 15:45:41 +02:00
|
|
|
var res = et2_typeDefaults[_type];
|
|
|
|
|
|
|
|
et2_debug("warn", "'" + _val + "' was not of specified _type '" +
|
|
|
|
_type + (_attr != null ? "' for attribute '" + _attr + "' " : "") +
|
|
|
|
"and is now '" + res + "'");
|
|
|
|
|
|
|
|
return res;
|
2011-08-10 16:36:31 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// If the type is "any" simply return the value again
|
|
|
|
if (_type == "any")
|
|
|
|
{
|
|
|
|
return _val;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the type is boolean, check whether the given value is exactly true or
|
|
|
|
// false. Otherwise check whether the value is the string "true" or "false".
|
|
|
|
if (_type == "boolean")
|
|
|
|
{
|
|
|
|
if (_val === true || _val === false)
|
2011-08-05 16:53:54 +02:00
|
|
|
{
|
2011-08-10 16:36:31 +02:00
|
|
|
return _val;
|
2011-08-05 16:53:54 +02:00
|
|
|
}
|
2011-08-10 16:36:31 +02:00
|
|
|
|
2011-08-16 21:01:45 +02:00
|
|
|
if (typeof _val == "string")
|
2011-08-10 16:36:31 +02:00
|
|
|
{
|
2011-08-16 21:01:45 +02:00
|
|
|
var lcv = _val.toLowerCase();
|
|
|
|
if (lcv === "true" || lcv === "false" || lcv === "")
|
|
|
|
{
|
|
|
|
return _val === "true";
|
|
|
|
}
|
2011-08-10 16:36:31 +02:00
|
|
|
}
|
|
|
|
|
2011-08-16 15:45:41 +02:00
|
|
|
return _err();
|
2011-08-10 16:36:31 +02:00
|
|
|
}
|
|
|
|
|
2011-08-15 11:24:32 +02:00
|
|
|
if (_type == "js")
|
|
|
|
{
|
|
|
|
// Handle the default case
|
|
|
|
if (_val === null)
|
|
|
|
{
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create a new function containing the code
|
|
|
|
if (typeof _val == "string")
|
|
|
|
{
|
|
|
|
if (_val !== "")
|
|
|
|
{
|
|
|
|
// TODO: Parse JS code properly
|
|
|
|
return new Function(_val);
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2011-08-16 15:45:41 +02:00
|
|
|
return _err();
|
2011-08-15 11:24:32 +02:00
|
|
|
}
|
|
|
|
|
2011-08-10 16:36:31 +02:00
|
|
|
// Check whether the given value is of the type "string"
|
|
|
|
if (_type == "string")
|
|
|
|
{
|
|
|
|
if (typeof _val == "string")
|
|
|
|
{
|
|
|
|
return _val;
|
|
|
|
}
|
|
|
|
|
2011-08-16 15:45:41 +02:00
|
|
|
return _err();
|
2011-08-10 16:36:31 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Check whether the value is already a number, otherwise try to convert it
|
|
|
|
// to one.
|
|
|
|
if (_type == "float")
|
|
|
|
{
|
|
|
|
if (typeof _val == "number")
|
|
|
|
{
|
|
|
|
return _val;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!isNaN(_val))
|
|
|
|
{
|
|
|
|
return parseFloat(_val);
|
|
|
|
}
|
|
|
|
|
2011-08-16 15:45:41 +02:00
|
|
|
return _err();
|
2011-08-10 16:36:31 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Check whether the value is an integer by comparing the result of
|
|
|
|
// parseInt(_val) to the value itself.
|
|
|
|
if (_type == "integer")
|
|
|
|
{
|
|
|
|
if (parseInt(_val) == _val)
|
|
|
|
{
|
|
|
|
return parseInt(_val);
|
|
|
|
}
|
|
|
|
|
2011-08-16 15:45:41 +02:00
|
|
|
return _err();
|
2011-08-10 16:36:31 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// We should never come here
|
|
|
|
throw("Invalid type identifier supplied.");
|
|
|
|
}
|
|
|
|
|
2011-08-10 18:23:02 +02:00
|
|
|
/**
|
|
|
|
* If et2_no_init is set as default value, the initAttributes function will not
|
|
|
|
* try to initialize the attribute with the default value.
|
|
|
|
*/
|
|
|
|
var et2_no_init = new Object();
|
|
|
|
|
2011-08-10 16:36:31 +02:00
|
|
|
/**
|
|
|
|
* Validates the given attribute with the given id. The validation checks for
|
|
|
|
* the existance of a human name, a description, a type and a default value.
|
|
|
|
* If the human name defaults to the given id, the description defaults to an
|
|
|
|
* empty string, the type defaults to any and the default to the corresponding
|
|
|
|
* type default.
|
|
|
|
*/
|
|
|
|
function et2_validateAttrib(_id, _attrib)
|
|
|
|
{
|
|
|
|
// Default ignore to false.
|
|
|
|
if (typeof _attrib["ignore"] == "undefined")
|
|
|
|
{
|
|
|
|
_attrib["ignore"] = false
|
|
|
|
}
|
|
|
|
|
|
|
|
// Break if "ignore" is set to true.
|
|
|
|
if (_attrib.ignore)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (typeof _attrib["name"] == "undefined")
|
|
|
|
{
|
|
|
|
_attrib["name"] = _id;
|
|
|
|
et2_debug("log", "Human name ('name'-Field) for attribute '" +
|
|
|
|
_id + "' has not been supplied, set to '" + _id + "'");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (typeof _attrib["description"] == "undefined")
|
|
|
|
{
|
|
|
|
_attrib["description"] = "";
|
|
|
|
et2_debug("log", "Description for attribute '" +
|
|
|
|
_id + "' has not been supplied");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (typeof _attrib["type"] == "undefined")
|
|
|
|
{
|
|
|
|
_attrib["type"] = "any";
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (et2_validTypes.indexOf(_attrib["type"]) < 0)
|
|
|
|
{
|
|
|
|
et2_debug("error", "Invalid type for attribute '" + _id +
|
|
|
|
"' supplied.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set the defaults
|
|
|
|
if (typeof _attrib["default"] == "undefined")
|
|
|
|
{
|
|
|
|
_attrib["default"] = et2_typeDefaults[_attrib["type"]];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Equivalent to the PHP array_values function
|
|
|
|
*/
|
|
|
|
function et2_arrayValues(_arr)
|
|
|
|
{
|
|
|
|
var result = [];
|
|
|
|
for (var key in _arr)
|
|
|
|
{
|
|
|
|
if (parseInt(key) == key)
|
|
|
|
{
|
|
|
|
result.push(_arr[key]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Equivalent to the PHP substr function, partly take from phpjs, licensed under
|
|
|
|
* the GPL.
|
|
|
|
*/
|
|
|
|
function et2_substr (str, start, len) {
|
|
|
|
var end = str.length;
|
|
|
|
|
|
|
|
if (start < 0)
|
|
|
|
{
|
|
|
|
start += end;
|
|
|
|
}
|
|
|
|
end = typeof len === 'undefined' ? end : (len < 0 ? len + end : len + start);
|
|
|
|
|
|
|
|
return start >= str.length || start < 0 || start > end ? "" : str.slice(start, end);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Split a $delimiter-separated options string, which can contain parts with
|
|
|
|
* delimiters enclosed in $enclosure. Ported from class.boetemplate.inc.php
|
|
|
|
*
|
|
|
|
* Examples:
|
|
|
|
* - et2_csvSplit('"1,2,3",2,3') === array('1,2,3','2','3')
|
|
|
|
* - et2_csvSplit('1,2,3',2) === array('1','2,3')
|
|
|
|
* - et2_csvSplit('"1,2,3",2,3',2) === array('1,2,3','2,3')
|
|
|
|
* - et2_csvSplit('"a""b,c",d') === array('a"b,c','d') // to escape enclosures double them!
|
|
|
|
*
|
|
|
|
* @param string _str
|
|
|
|
* @param int _num=null in how many parts to split maximal, parts over this
|
|
|
|
* number end up (unseparated) in the last part
|
|
|
|
* @param string _delimiter=','
|
|
|
|
* @param string _enclosure='"'
|
|
|
|
* @return array
|
|
|
|
*/
|
|
|
|
function et2_csvSplit(_str, _num, _delimiter, _enclosure)
|
|
|
|
{
|
|
|
|
// Default the parameters
|
|
|
|
if (typeof _num == "undefined")
|
|
|
|
{
|
2011-08-15 20:54:13 +02:00
|
|
|
_num = null;
|
2011-08-10 16:36:31 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (typeof _delimiter == "undefined")
|
|
|
|
{
|
|
|
|
_delimiter = ",";
|
|
|
|
}
|
|
|
|
|
|
|
|
if (typeof _enclosure == "undefined")
|
|
|
|
{
|
|
|
|
_enclosure = '"';
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the _enclosure string does not occur in the string, simply use the
|
|
|
|
// split function
|
|
|
|
if (_str.indexOf(_enclosure) == -1)
|
|
|
|
{
|
|
|
|
return _num === null ? _str.split(_delimiter) :
|
|
|
|
_str.split(_delimiter, _num);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Split the string at the delimiter and join it again, when a enclosure is
|
|
|
|
// found at the beginning/end of a part
|
|
|
|
var parts = _str.split(_delimiter);
|
|
|
|
for (var n = 0; typeof parts[n] != "undefined"; n++)
|
|
|
|
{
|
|
|
|
var part = parts[n];
|
|
|
|
|
|
|
|
if (part.charAt(0) === _enclosure)
|
|
|
|
{
|
|
|
|
var m = n;
|
|
|
|
while (typeof parts[m + 1] != "undefined" && parts[n].substr(-1) !== _enclosure)
|
|
|
|
{
|
|
|
|
parts[n] += _delimiter + parts[++m];
|
|
|
|
delete(parts[m]);
|
|
|
|
}
|
|
|
|
parts[n] = et2_substr(parts[n].replace(
|
|
|
|
new RegExp(_enclosure + _enclosure, 'g'), _enclosure), 1 , -1);
|
|
|
|
n = m;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Rebuild the array index
|
|
|
|
parts = et2_arrayValues(parts);
|
|
|
|
|
|
|
|
// Limit the parts to the given number
|
|
|
|
if (_num !== null && _num > 0 && _num < parts.length && parts.length > 0)
|
|
|
|
{
|
|
|
|
parts[_num - 1] = parts.slice(_num - 1, parts.length).join(_delimiter);
|
|
|
|
parts = parts.slice(0, _num);
|
|
|
|
}
|
|
|
|
|
|
|
|
return parts;
|
2011-08-05 16:53:54 +02:00
|
|
|
}
|
|
|
|
|
2011-08-15 14:34:00 +02:00
|
|
|
/**
|
|
|
|
* 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;
|
|
|
|
}
|
2011-08-05 16:53:54 +02:00
|
|
|
|