2011-02-23 19:24:16 +01:00
|
|
|
/**
|
|
|
|
* eGroupWare egw_action framework - egw action framework
|
|
|
|
*
|
|
|
|
* @link http://www.egroupware.org
|
|
|
|
* @author Andreas Stöckel <as@stylite.de>
|
|
|
|
* @copyright 2011 by Andreas Stöckel
|
|
|
|
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
|
|
|
* @package egw_action
|
2011-02-23 21:18:56 +01:00
|
|
|
* @version $Id$
|
2011-02-23 19:24:16 +01:00
|
|
|
*/
|
|
|
|
|
2011-08-03 16:04:30 +02:00
|
|
|
/*egw:uses
|
|
|
|
egw_action_common;
|
|
|
|
*/
|
|
|
|
|
2011-06-02 16:48:03 +02:00
|
|
|
/**
|
|
|
|
* Getter functions for the global egwActionManager and egwObjectManager objects
|
|
|
|
*/
|
|
|
|
|
|
|
|
var egw_globalActionManager = null;
|
|
|
|
var egw_globalObjectManager = null;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the action manager for the given application - each application has its
|
|
|
|
* own sub-ActionManager in the global action manager object to prevent collisions
|
|
|
|
* from happening
|
|
|
|
*
|
|
|
|
* @param _id is the name of the sub-actionManager which should be returned.
|
|
|
|
* If the action manager does not exist right now, it is created. If the
|
|
|
|
* parameter is ommited or null, the global action manager is returned.
|
2014-01-18 12:21:53 +01:00
|
|
|
* @param {boolean} [_create=true] If an objectManager with the given id is not
|
|
|
|
* found, it will be created at the top level.
|
|
|
|
* @param {number} [_search_depth=Infinite] How deep into existing action children
|
|
|
|
* to search.
|
2011-06-02 16:48:03 +02:00
|
|
|
*/
|
2014-01-18 12:21:53 +01:00
|
|
|
function egw_getActionManager(_id, _create,_search_depth) {
|
2011-06-02 16:48:03 +02:00
|
|
|
if (typeof _create == 'undefined') {
|
|
|
|
_create = true;
|
|
|
|
}
|
2014-01-18 12:21:53 +01:00
|
|
|
if (typeof _search_depth == "undefined") {
|
|
|
|
_search_depth = Number.MAX_VALUE;
|
|
|
|
}
|
2011-06-02 16:48:03 +02:00
|
|
|
|
|
|
|
// Check whether the global action manager had been created, if not do so
|
|
|
|
var res = egw_globalActionManager;
|
|
|
|
if (egw_globalActionManager == null) {
|
|
|
|
res = egw_globalActionManager = new egwActionManager();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check whether the sub-action manager exists, if not, create it
|
|
|
|
if (typeof _id != 'undefined' && _id != null) {
|
2014-01-18 12:21:53 +01:00
|
|
|
res = egw_globalActionManager.getActionById(_id,_search_depth);
|
2011-06-02 16:48:03 +02:00
|
|
|
if (res == null && _create) {
|
|
|
|
res = egw_globalActionManager.addAction("actionManager", _id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the object manager for the given application - each application may
|
|
|
|
* have its own object manager where it can place action objects or containers.
|
|
|
|
*
|
|
|
|
* @param _id is the name of the sub-object manager should be returned. If the
|
|
|
|
* object manager does not exists right now, it is created. If the parameter
|
|
|
|
* is ommited or null, the global object manager is returned.
|
2014-01-18 12:21:53 +01:00
|
|
|
* @param {boolean} [_create=true] If an objectManager with the given id is not
|
|
|
|
* found, it will be created at the top level.
|
|
|
|
* @param {number} [_search_depth=Infinite] How deep into existing action children
|
|
|
|
* to search.
|
2011-06-02 16:48:03 +02:00
|
|
|
*/
|
2014-01-18 12:21:53 +01:00
|
|
|
function egw_getObjectManager(_id, _create, _search_depth) {
|
2011-06-02 16:48:03 +02:00
|
|
|
if (typeof _create == "undefined") {
|
|
|
|
_create = true;
|
|
|
|
}
|
2014-01-18 12:21:53 +01:00
|
|
|
if (typeof _search_depth == "undefined") {
|
|
|
|
_search_depth = Number.MAX_VALUE;
|
|
|
|
}
|
2011-06-02 16:48:03 +02:00
|
|
|
|
|
|
|
// Check whether the global object manager exists
|
|
|
|
var res = egw_globalObjectManager;
|
|
|
|
if (res == null) {
|
|
|
|
res = egw_globalObjectManager =
|
|
|
|
new egwActionObjectManager("_egwGlobalObjectManager",
|
|
|
|
egw_getActionManager());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check whether the sub-object manager exists, if not, create it
|
|
|
|
if (typeof _id != 'undefined' && _id != null) {
|
2014-01-18 12:21:53 +01:00
|
|
|
res = egw_globalObjectManager.getObjectById(_id, _search_depth);
|
2011-06-02 16:48:03 +02:00
|
|
|
if (res == null && _create) {
|
|
|
|
res = new egwActionObjectManager(_id,
|
2015-03-16 21:17:55 +01:00
|
|
|
egw_getActionManager(_id,true,_search_depth));
|
2011-06-02 16:48:03 +02:00
|
|
|
egw_globalObjectManager.addObject(res);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2011-06-15 22:54:58 +02:00
|
|
|
/**
|
|
|
|
* Returns the object manager for the current application
|
2014-02-25 16:03:13 +01:00
|
|
|
*
|
|
|
|
* @param {boolean} _create
|
|
|
|
* @return {egwActionObjectManager}
|
2011-06-15 22:54:58 +02:00
|
|
|
*/
|
|
|
|
function egw_getAppObjectManager(_create) {
|
2014-01-18 12:21:53 +01:00
|
|
|
return egw_getObjectManager(egw_getAppName(), _create,1);
|
2011-06-15 22:54:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the action manager for the current application
|
2014-02-25 16:03:13 +01:00
|
|
|
*
|
|
|
|
* @param {boolean} _create
|
|
|
|
* @return {egwActionManager}
|
2011-06-15 22:54:58 +02:00
|
|
|
*/
|
|
|
|
function egw_getAppActionManager(_create) {
|
2014-01-18 12:21:53 +01:00
|
|
|
return egw_getActionManager(egw_getAppName(), _create,1);
|
2011-06-15 22:54:58 +02:00
|
|
|
}
|
|
|
|
|
2011-06-02 16:48:03 +02:00
|
|
|
|
|
|
|
|
2011-02-23 19:24:16 +01:00
|
|
|
/** egwActionHandler Interface **/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Constructor for the egwActionHandler interface which (at least) should have the
|
|
|
|
* execute function implemented.
|
2014-02-25 16:03:13 +01:00
|
|
|
*
|
|
|
|
* @param {function} _executeEvent
|
|
|
|
* @return {egwActionHandler}
|
2011-02-23 19:24:16 +01:00
|
|
|
*/
|
|
|
|
function egwActionHandler(_executeEvent)
|
|
|
|
{
|
|
|
|
//Copy the executeEvent parameter
|
|
|
|
this.execute = _executeEvent;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** egwAction Object **/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Associative array where action classes may register themselves
|
|
|
|
*/
|
2011-02-26 19:04:28 +01:00
|
|
|
if (typeof window._egwActionClasses == "undefined")
|
2013-07-20 15:45:22 +02:00
|
|
|
window._egwActionClasses = {};
|
2011-02-23 19:24:16 +01:00
|
|
|
|
2011-02-26 19:04:28 +01:00
|
|
|
_egwActionClasses["default"] = {
|
|
|
|
"actionConstructor": egwAction,
|
|
|
|
"implementation": null
|
|
|
|
};
|
2011-06-02 16:48:03 +02:00
|
|
|
_egwActionClasses["actionManager"] = {
|
|
|
|
"actionConstructor": egwActionManager,
|
|
|
|
"implementation": null
|
|
|
|
};
|
2011-02-26 19:04:28 +01:00
|
|
|
|
2014-02-25 16:03:13 +01:00
|
|
|
/**
|
|
|
|
* Constructor for egwAction object
|
|
|
|
*
|
|
|
|
* @param {egwAction} _parent
|
|
|
|
* @param {string} _id
|
|
|
|
* @param {string} _caption
|
|
|
|
* @param {string} _iconUrl
|
|
|
|
* @param {(string|function)} _onExecute
|
|
|
|
* @param {boolean} _allowOnMultiple
|
|
|
|
* @returns {egwAction}
|
|
|
|
*/
|
2011-03-23 15:05:39 +01:00
|
|
|
function egwAction(_parent, _id, _caption, _iconUrl, _onExecute, _allowOnMultiple)
|
2011-02-23 19:24:16 +01:00
|
|
|
{
|
|
|
|
//Default and check the values
|
2011-06-02 16:48:03 +02:00
|
|
|
if (_parent && (typeof _id != "string" || !_id) && _parent.type != "actionManager")
|
2011-02-23 19:24:16 +01:00
|
|
|
throw "egwAction _id must be a non-empty string!";
|
2011-03-09 23:16:41 +01:00
|
|
|
if (typeof _caption == "undefined")
|
|
|
|
_caption = "";
|
2011-02-26 19:04:28 +01:00
|
|
|
if (typeof _iconUrl == "undefined")
|
|
|
|
_iconUrl = "";
|
2011-02-23 19:24:16 +01:00
|
|
|
if (typeof _onExecute == "undefined")
|
|
|
|
_onExecute = null;
|
|
|
|
if (typeof _allowOnMultiple == "undefined")
|
|
|
|
_allowOnMultiple = true;
|
|
|
|
|
|
|
|
this.id = _id;
|
|
|
|
this.caption = _caption;
|
2011-02-26 19:04:28 +01:00
|
|
|
this.iconUrl = _iconUrl;
|
2011-02-23 19:24:16 +01:00
|
|
|
this.allowOnMultiple = _allowOnMultiple;
|
Fixed problems with executeActionImplementation when called from a container object, fixed problem with popup menu which did not open in some cases, added the ability to use the 'enabled' property of an action as an callback function (actionObject is passed as parameter), introduced egwFnct-class which consistently handles 'javaScript:fnct' strings, added 'allowOnMultiple':'only' setting, added 'hint', 'checkbox', 'checked', 'radioGroup' properties to popup actions, added 'setDefaultExecute' function to egwAction objects, which applies an handler to all objects which don't have a handler yet
2011-04-17 17:38:46 +02:00
|
|
|
this.enabled = new egwFnct(this, true);
|
2011-03-23 21:08:33 +01:00
|
|
|
this.hideOnDisabled = false;
|
2013-07-20 15:45:22 +02:00
|
|
|
this.data = {}; // Data which can be freely assigned to the action
|
2011-03-23 15:05:39 +01:00
|
|
|
|
2011-02-23 19:24:16 +01:00
|
|
|
this.type = "default"; //All derived classes have to override this!
|
2011-03-23 15:05:39 +01:00
|
|
|
this.canHaveChildren = false; //Has to be overwritten by inherited action classes
|
|
|
|
this.parent = _parent;
|
|
|
|
this.children = [];
|
2011-02-23 19:24:16 +01:00
|
|
|
|
Fixed problems with executeActionImplementation when called from a container object, fixed problem with popup menu which did not open in some cases, added the ability to use the 'enabled' property of an action as an callback function (actionObject is passed as parameter), introduced egwFnct-class which consistently handles 'javaScript:fnct' strings, added 'allowOnMultiple':'only' setting, added 'hint', 'checkbox', 'checked', 'radioGroup' properties to popup actions, added 'setDefaultExecute' function to egwAction objects, which applies an handler to all objects which don't have a handler yet
2011-04-17 17:38:46 +02:00
|
|
|
this.onExecute = new egwFnct(this, null, []);
|
2012-08-25 16:40:48 +02:00
|
|
|
if(_onExecute !== null)
|
|
|
|
{
|
|
|
|
this.set_onExecute(_onExecute);
|
|
|
|
}
|
2016-02-03 14:12:37 +01:00
|
|
|
this.hideOnMobile = false;
|
2011-02-23 19:24:16 +01:00
|
|
|
}
|
|
|
|
|
2012-03-29 16:11:22 +02:00
|
|
|
/**
|
|
|
|
* Clears the element and removes it from the parent container
|
|
|
|
*/
|
|
|
|
egwAction.prototype.remove = function () {
|
|
|
|
// Remove all references to the child elements
|
|
|
|
this.children = [];
|
|
|
|
|
|
|
|
// Remove this element from the parent list
|
|
|
|
if (this.parent)
|
|
|
|
{
|
|
|
|
var idx = this.parent.children.indexOf(this);
|
|
|
|
if (idx >= 0)
|
|
|
|
{
|
|
|
|
this.parent.children.splice(idx, 1);
|
|
|
|
}
|
|
|
|
}
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2012-03-29 16:11:22 +02:00
|
|
|
|
2011-03-23 15:05:39 +01:00
|
|
|
/**
|
|
|
|
* Searches for a specific action with the given id
|
2014-02-25 16:03:13 +01:00
|
|
|
*
|
|
|
|
* @param {(string|number)} _id ID of the action to find
|
2014-01-18 12:21:53 +01:00
|
|
|
* @param {number} [_search_depth=Infinite] How deep into existing action children
|
|
|
|
* to search.
|
|
|
|
*
|
2014-02-25 16:03:13 +01:00
|
|
|
* @return {(egwAction|null)}
|
2011-03-23 15:05:39 +01:00
|
|
|
*/
|
2014-01-18 12:21:53 +01:00
|
|
|
egwAction.prototype.getActionById = function(_id,_search_depth)
|
2011-03-23 15:05:39 +01:00
|
|
|
{
|
|
|
|
// If the current action object has the given id, return this object
|
|
|
|
if (this.id == _id)
|
|
|
|
{
|
|
|
|
return this;
|
|
|
|
}
|
2014-01-18 12:21:53 +01:00
|
|
|
if (typeof _search_depth == "undefined") {
|
|
|
|
_search_depth = Number.MAX_VALUE;
|
|
|
|
}
|
2011-03-23 15:05:39 +01:00
|
|
|
|
|
|
|
// If this element is capable of having children, search those for the given
|
|
|
|
// action id
|
|
|
|
if (this.canHaveChildren)
|
|
|
|
{
|
2014-01-18 12:21:53 +01:00
|
|
|
for (var i = 0; i < this.children.length && _search_depth > 0; i++)
|
2011-03-23 15:05:39 +01:00
|
|
|
{
|
2014-01-18 12:21:53 +01:00
|
|
|
var elem = this.children[i].getActionById(_id,_search_depth-1);
|
2011-03-23 15:05:39 +01:00
|
|
|
if (elem)
|
|
|
|
{
|
|
|
|
return elem;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-03-23 15:05:39 +01:00
|
|
|
|
2011-04-27 09:49:46 +02:00
|
|
|
/**
|
|
|
|
* Searches for actions having an attribute with a certain value
|
2014-01-16 17:49:26 +01:00
|
|
|
*
|
2011-04-27 09:49:46 +02:00
|
|
|
* Example: actionManager.getActionsByAttr("checkbox", true) returns all checkbox actions
|
2014-01-16 17:49:26 +01:00
|
|
|
*
|
2014-02-25 16:03:13 +01:00
|
|
|
* @param {string} _attr attribute name
|
|
|
|
* @param _val attribute value
|
2011-04-27 09:49:46 +02:00
|
|
|
* @return array
|
|
|
|
*/
|
|
|
|
egwAction.prototype.getActionsByAttr = function(_attr, _val)
|
|
|
|
{
|
|
|
|
var _actions = [];
|
2014-01-16 17:49:26 +01:00
|
|
|
|
2011-04-27 09:49:46 +02:00
|
|
|
// If the current action object has the given attr AND value, return it
|
|
|
|
if (typeof this[_attr] != "undefined" && this[_attr] === _val)
|
|
|
|
{
|
|
|
|
_actions.push(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
// If this element is capable of having children, search those too
|
|
|
|
if (this.canHaveChildren)
|
|
|
|
{
|
|
|
|
for (var i = 0; i < this.children.length; i++)
|
|
|
|
{
|
|
|
|
_actions = _actions.concat(this.children[i].getActionsByAttr(_attr, _val));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return _actions;
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-04-27 09:49:46 +02:00
|
|
|
|
2011-03-23 15:05:39 +01:00
|
|
|
/**
|
|
|
|
* Adds a new action to the child elements.
|
2014-02-25 16:03:13 +01:00
|
|
|
*
|
|
|
|
* @param {string} _type
|
|
|
|
* @param {string} _id
|
|
|
|
* @param {string} _caption
|
|
|
|
* @param {string] _iconUrl
|
|
|
|
* @param {(string|function)} _onExecute
|
|
|
|
* @param {boolean} _allowOnMultiple
|
2011-03-23 15:05:39 +01:00
|
|
|
*/
|
|
|
|
egwAction.prototype.addAction = function(_type, _id, _caption, _iconUrl,
|
|
|
|
_onExecute, _allowOnMultiple)
|
|
|
|
{
|
|
|
|
//Get the constructor for the given action type
|
|
|
|
if (!_type)
|
|
|
|
{
|
2011-04-17 21:10:46 +02:00
|
|
|
_type = "popup";
|
2011-03-23 15:05:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Only allow adding new actions, if this action class allows it.
|
|
|
|
if (this.canHaveChildren)
|
|
|
|
{
|
|
|
|
var constructor = _egwActionClasses[_type].actionConstructor;
|
|
|
|
|
|
|
|
if (typeof constructor == "function")
|
|
|
|
{
|
|
|
|
var action = new constructor(this, _id, _caption, _iconUrl, _onExecute,
|
|
|
|
_allowOnMultiple);
|
|
|
|
this.children.push(action);
|
|
|
|
|
|
|
|
return action;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
throw "Given action type not registered.";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2013-07-20 15:45:22 +02:00
|
|
|
throw "This action does not allow child elements!";
|
2011-03-23 15:05:39 +01:00
|
|
|
}
|
2013-07-20 15:45:22 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Default icons for given id
|
|
|
|
*/
|
|
|
|
egwAction.prototype.defaultIcons = {
|
|
|
|
view: 'view',
|
|
|
|
edit: 'edit',
|
|
|
|
open: 'edit', // does edit if possible, otherwise view
|
|
|
|
add: 'new',
|
|
|
|
"new": 'new',
|
|
|
|
"delete": 'delete',
|
|
|
|
cat: 'attach', // add as category icon to api
|
|
|
|
document: 'etemplate/merge',
|
|
|
|
print: 'print',
|
|
|
|
copy: 'copy',
|
|
|
|
move: 'move',
|
|
|
|
cut: 'cut',
|
2014-03-06 19:33:27 +01:00
|
|
|
paste: 'editpaste',
|
|
|
|
save: 'save',
|
|
|
|
apply: 'apply',
|
|
|
|
cancel: 'cancel',
|
|
|
|
'continue': 'continue',
|
|
|
|
next: 'continue',
|
|
|
|
finish: 'finish',
|
|
|
|
back: 'back',
|
|
|
|
previous: 'back',
|
|
|
|
close: 'close'
|
2013-07-20 15:45:22 +02:00
|
|
|
};
|
2011-03-23 15:05:39 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Updates the children of this element
|
2014-01-16 17:49:26 +01:00
|
|
|
*
|
2014-02-25 16:03:13 +01:00
|
|
|
* @param {object} _actions { id: action, ...}
|
|
|
|
* @param {string} _app defaults to egw_getAppname()
|
2011-03-23 15:05:39 +01:00
|
|
|
*/
|
2013-07-20 15:45:22 +02:00
|
|
|
egwAction.prototype.updateActions = function(_actions, _app)
|
2011-03-23 15:05:39 +01:00
|
|
|
{
|
|
|
|
if (this.canHaveChildren)
|
|
|
|
{
|
2013-07-20 15:45:22 +02:00
|
|
|
if (typeof _app == "undefined") _app = egw_getAppName(); // this can probably be queried from actionObjectManager ...
|
|
|
|
var egw = window.egw(_app);
|
|
|
|
|
|
|
|
if (jQuery.isArray(_actions))
|
|
|
|
{
|
|
|
|
_actions = jQuery.extend({}, _actions);
|
|
|
|
}
|
|
|
|
for (var i in _actions)
|
2011-03-23 15:05:39 +01:00
|
|
|
{
|
|
|
|
var elem = _actions[i];
|
2013-07-20 15:45:22 +02:00
|
|
|
|
2014-03-06 19:33:27 +01:00
|
|
|
if (typeof elem == "string")
|
|
|
|
{
|
|
|
|
_actions[i] = elem = { caption: elem };
|
|
|
|
}
|
2013-07-20 15:45:22 +02:00
|
|
|
if (typeof elem == "object")
|
2011-03-23 15:05:39 +01:00
|
|
|
{
|
2013-07-20 15:45:22 +02:00
|
|
|
// use attr name as id, if none given
|
|
|
|
if (typeof elem.id != "string") elem.id = i;
|
|
|
|
|
|
|
|
// if no iconUrl given, check icon and default icons
|
|
|
|
if (typeof elem.iconUrl == "undefined")
|
|
|
|
{
|
|
|
|
if (typeof elem.icon == "undefined") elem.icon = this.defaultIcons[elem.id];
|
|
|
|
if (typeof elem.icon != "undefined")
|
|
|
|
{
|
2014-01-16 17:49:26 +01:00
|
|
|
elem.iconUrl = egw.image(elem.icon);
|
2013-07-20 15:45:22 +02:00
|
|
|
}
|
|
|
|
delete elem.icon;
|
|
|
|
}
|
2014-01-16 17:49:26 +01:00
|
|
|
|
2013-07-20 15:45:22 +02:00
|
|
|
// allways add shortcut for delete
|
|
|
|
if (elem.id == "delete" && typeof elem.shortcut == "undefined")
|
|
|
|
{
|
|
|
|
elem.shortcut = { keyCode: 46, shift: false, ctrl: false, alt: false, caption: egw.lang('Del') };
|
|
|
|
}
|
2014-01-16 17:49:26 +01:00
|
|
|
|
2013-07-20 15:45:22 +02:00
|
|
|
// translate caption
|
2014-01-11 12:51:46 +01:00
|
|
|
if (elem.caption && (typeof elem.no_lang == "undefined" || !elem.no_lang))
|
2013-07-20 15:45:22 +02:00
|
|
|
{
|
|
|
|
elem.caption = egw.lang(elem.caption);
|
|
|
|
if (typeof elem.hint == "string") elem.hint = egw.lang(elem.hint);
|
|
|
|
}
|
|
|
|
delete elem.no_lang;
|
|
|
|
|
|
|
|
// translate confirm messages
|
|
|
|
for(var attr in {confirm: '', confirm_multiple: ''})
|
|
|
|
{
|
|
|
|
if (typeof elem[attr] == "string")
|
|
|
|
{
|
|
|
|
elem[attr] = egw.lang(elem[attr])+(elem[attr].substr(-1) != '?' ? '?' : '');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-26 10:24:50 +02:00
|
|
|
// set certain enabled functions (if enabled is on it's default of true)
|
2013-10-04 13:18:50 +02:00
|
|
|
if (typeof elem.enabled == 'undefined' || elem.enabled === true)
|
2013-07-20 15:45:22 +02:00
|
|
|
{
|
|
|
|
if (typeof elem.enableClass != "undefined")
|
|
|
|
{
|
|
|
|
elem.enabled = this.enableClass;
|
|
|
|
}
|
|
|
|
else if (typeof elem.disableClass != "undefined")
|
|
|
|
{
|
|
|
|
elem.enabled = this.not_disableClass;
|
|
|
|
}
|
|
|
|
else if (typeof elem.enableId != "undefined")
|
|
|
|
{
|
|
|
|
elem.enabled = this.enableId;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-03-23 15:05:39 +01:00
|
|
|
//Check whether the action already exists, and if no, add it to the
|
|
|
|
//actions list
|
|
|
|
var action = this.getActionById(elem.id);
|
|
|
|
if (!action)
|
|
|
|
{
|
|
|
|
if (typeof elem.type == "undefined")
|
2011-04-17 21:10:46 +02:00
|
|
|
elem.type = "popup";
|
2011-03-23 15:05:39 +01:00
|
|
|
|
|
|
|
var constructor = null;
|
|
|
|
|
|
|
|
// Check whether the given type is inside the "canHaveChildren"
|
|
|
|
// array
|
|
|
|
if (this.canHaveChildren !== true && this.canHaveChildren.indexOf(elem.type) == -1)
|
|
|
|
{
|
2013-07-20 15:45:22 +02:00
|
|
|
throw "This child type '" + elem.type + "' is not allowed!";
|
2011-03-23 15:05:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (typeof _egwActionClasses[elem.type] != "undefined")
|
|
|
|
constructor = _egwActionClasses[elem.type].actionConstructor;
|
|
|
|
|
|
|
|
if (typeof constructor == "function" && constructor)
|
|
|
|
action = new constructor(this, elem.id);
|
|
|
|
else
|
|
|
|
throw "Given action type \"" + elem.type + "\" not registered.";
|
|
|
|
|
|
|
|
this.children.push(action);
|
|
|
|
}
|
|
|
|
|
|
|
|
action.updateAction(elem);
|
|
|
|
|
|
|
|
// Add sub-actions to the action
|
|
|
|
if (elem.children)
|
|
|
|
{
|
2013-07-20 15:45:22 +02:00
|
|
|
action.updateActions(elem.children, _app);
|
2011-03-23 15:05:39 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
throw "This action element cannot have children!";
|
|
|
|
}
|
2013-07-20 15:45:22 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Callback to check if none of _senders rows has disableClass set
|
2014-01-16 17:49:26 +01:00
|
|
|
*
|
2013-07-20 15:45:22 +02:00
|
|
|
* @param _action egwAction object, we use _action.data.disableClass to check
|
|
|
|
* @param _senders array of egwActionObject objects
|
|
|
|
* @param _target egwActionObject object, get's called for every object in _senders
|
|
|
|
* @returns boolean true if none has disableClass, false otherwise
|
|
|
|
*/
|
|
|
|
egwAction.prototype.not_disableClass = function(_action, _senders, _target)
|
|
|
|
{
|
2018-07-17 18:16:35 +02:00
|
|
|
if(_target.iface.getDOMNode())
|
|
|
|
{
|
|
|
|
return !jQuery(_target.iface.getDOMNode()).hasClass(_action.data.disableClass);
|
|
|
|
}
|
|
|
|
else if (_target.id)
|
|
|
|
{
|
|
|
|
// Checking on a something that doesn't have a DOM node, like a nm row
|
|
|
|
// that's not currently rendered
|
|
|
|
var data = egw.dataGetUIDdata(_target.id);
|
|
|
|
if(data && data.data && data.data.class)
|
|
|
|
{
|
|
|
|
return -1 === data.data.class.split(' ').indexOf(_action.data.disableClass);
|
|
|
|
}
|
|
|
|
}
|
2013-07-20 15:45:22 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Callback to check if all of _senders rows have enableClass set
|
2014-01-16 17:49:26 +01:00
|
|
|
*
|
2013-07-20 15:45:22 +02:00
|
|
|
* @param _action egwAction object, we use _action.data.enableClass to check
|
|
|
|
* @param _senders array of egwActionObject objects
|
|
|
|
* @param _target egwActionObject object, get's called for every object in _senders
|
|
|
|
* @returns boolean true if none has disableClass, false otherwise
|
|
|
|
*/
|
|
|
|
egwAction.prototype.enableClass = function(_action, _senders, _target)
|
|
|
|
{
|
2018-07-30 11:20:54 +02:00
|
|
|
if (typeof _target == 'undefined')
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
} else
|
2018-07-17 18:16:35 +02:00
|
|
|
if(_target.iface.getDOMNode())
|
|
|
|
{
|
|
|
|
return jQuery(_target.iface.getDOMNode()).hasClass(_action.data.enableClass);
|
|
|
|
}
|
|
|
|
else if (_target.id)
|
|
|
|
{
|
|
|
|
// Checking on a something that doesn't have a DOM node, like a nm row
|
|
|
|
// that's not currently rendered. Not as good as an actual DOM node check
|
|
|
|
// since things can get missed, but better than nothing.
|
|
|
|
var data = egw.dataGetUIDdata(_target.id);
|
|
|
|
if(data && data.data && data.data.class)
|
|
|
|
{
|
|
|
|
return -1 !== data.data.class.split(' ').indexOf(_action.data.enableClass);
|
|
|
|
}
|
|
|
|
}
|
2013-07-20 15:45:22 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Enable an _action, if it matches a given regular expresstion in _action.data.enableId
|
2014-01-16 17:49:26 +01:00
|
|
|
*
|
2013-07-20 15:45:22 +02:00
|
|
|
* @param _action egwAction object, we use _action.data.enableId to check
|
|
|
|
* @param _senders array of egwActionObject objects
|
|
|
|
* @param _target egwActionObject object, get's called for every object in _senders
|
|
|
|
* @returns boolean true if _target.id matches _action.data.enableId
|
|
|
|
*/
|
|
|
|
egwAction.prototype.enableId = function(_action, _senders, _target)
|
|
|
|
{
|
|
|
|
if (typeof _action.data.enableId == 'string')
|
|
|
|
_action.data.enableId = new RegExp(_action.data.enableId);
|
2014-01-16 17:49:26 +01:00
|
|
|
|
2013-07-20 15:45:22 +02:00
|
|
|
return _target.id.match(_action.data.enableId);
|
|
|
|
};
|
2011-03-23 15:05:39 +01:00
|
|
|
|
Fixed problems with executeActionImplementation when called from a container object, fixed problem with popup menu which did not open in some cases, added the ability to use the 'enabled' property of an action as an callback function (actionObject is passed as parameter), introduced egwFnct-class which consistently handles 'javaScript:fnct' strings, added 'allowOnMultiple':'only' setting, added 'hint', 'checkbox', 'checked', 'radioGroup' properties to popup actions, added 'setDefaultExecute' function to egwAction objects, which applies an handler to all objects which don't have a handler yet
2011-04-17 17:38:46 +02:00
|
|
|
/**
|
|
|
|
* Applys the same onExecute handler to all actions which don't have an execute
|
|
|
|
* handler set.
|
2014-02-25 16:03:13 +01:00
|
|
|
*
|
|
|
|
* @param {(string|function)} _value
|
Fixed problems with executeActionImplementation when called from a container object, fixed problem with popup menu which did not open in some cases, added the ability to use the 'enabled' property of an action as an callback function (actionObject is passed as parameter), introduced egwFnct-class which consistently handles 'javaScript:fnct' strings, added 'allowOnMultiple':'only' setting, added 'hint', 'checkbox', 'checked', 'radioGroup' properties to popup actions, added 'setDefaultExecute' function to egwAction objects, which applies an handler to all objects which don't have a handler yet
2011-04-17 17:38:46 +02:00
|
|
|
*/
|
|
|
|
egwAction.prototype.setDefaultExecute = function(_value)
|
|
|
|
{
|
|
|
|
// Check whether the onExecute handler of this action should be set
|
|
|
|
if (this.type != "actionManager" && !this.onExecute.hasHandler())
|
|
|
|
{
|
2014-03-11 17:25:18 +01:00
|
|
|
this.onExecute.isDefault = true;
|
Fixed problems with executeActionImplementation when called from a container object, fixed problem with popup menu which did not open in some cases, added the ability to use the 'enabled' property of an action as an callback function (actionObject is passed as parameter), introduced egwFnct-class which consistently handles 'javaScript:fnct' strings, added 'allowOnMultiple':'only' setting, added 'hint', 'checkbox', 'checked', 'radioGroup' properties to popup actions, added 'setDefaultExecute' function to egwAction objects, which applies an handler to all objects which don't have a handler yet
2011-04-17 17:38:46 +02:00
|
|
|
this.onExecute.setValue(_value);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Apply the value to all children
|
|
|
|
if (this.canHaveChildren)
|
|
|
|
{
|
|
|
|
for (var i = 0; i < this.children.length; i++)
|
|
|
|
{
|
|
|
|
this.children[i].setDefaultExecute(_value);
|
|
|
|
}
|
|
|
|
}
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
Fixed problems with executeActionImplementation when called from a container object, fixed problem with popup menu which did not open in some cases, added the ability to use the 'enabled' property of an action as an callback function (actionObject is passed as parameter), introduced egwFnct-class which consistently handles 'javaScript:fnct' strings, added 'allowOnMultiple':'only' setting, added 'hint', 'checkbox', 'checked', 'radioGroup' properties to popup actions, added 'setDefaultExecute' function to egwAction objects, which applies an handler to all objects which don't have a handler yet
2011-04-17 17:38:46 +02:00
|
|
|
|
2011-02-23 19:24:16 +01:00
|
|
|
/**
|
|
|
|
* Executes this action by using the method specified in the onExecute setter.
|
|
|
|
*
|
2014-02-25 16:03:13 +01:00
|
|
|
* @param {array} _senders array with references to the objects which caused the action
|
|
|
|
* @param {object} _target is an optional parameter which may represent e.g. an drag drop target
|
2011-02-23 19:24:16 +01:00
|
|
|
*/
|
2011-03-24 18:06:44 +01:00
|
|
|
egwAction.prototype.execute = function(_senders, _target)
|
2011-02-23 19:24:16 +01:00
|
|
|
{
|
2011-03-24 18:06:44 +01:00
|
|
|
if (typeof _target == "undefined")
|
|
|
|
{
|
2013-04-11 14:22:34 +02:00
|
|
|
_target = null;
|
2011-03-24 18:06:44 +01:00
|
|
|
}
|
|
|
|
|
2013-07-20 15:45:22 +02:00
|
|
|
// check if actions needs to be confirmed first
|
2014-01-15 15:59:42 +01:00
|
|
|
if (this.data && (this.data.confirm || this.data.confirm_multiple) && this.onExecute.fcnt != window.nm_action &&
|
2013-08-26 09:36:51 +02:00
|
|
|
typeof et2_dialog != 'undefined') // let old eTemplate run it's own confirmation from nextmatch_action.js
|
2013-07-20 15:45:22 +02:00
|
|
|
{
|
2014-01-15 16:18:23 +01:00
|
|
|
var msg = this.data.confirm || '';
|
2013-10-03 17:30:27 +02:00
|
|
|
if (_senders.length > 1)
|
|
|
|
{
|
|
|
|
if (this.data.confirm_multiple) msg = this.data.confirm_multiple;
|
|
|
|
// check if we have all rows selected
|
|
|
|
var obj_manager = egw_getObjectManager(this.getManager().parent.id, false);
|
|
|
|
if (obj_manager && obj_manager.getAllSelected())
|
|
|
|
{
|
|
|
|
msg += "\n\n"+egw().lang('Attention: action will be applied to all rows, not only visible ones!');
|
|
|
|
}
|
|
|
|
}
|
2013-07-20 15:45:22 +02:00
|
|
|
var self = this;
|
2014-01-15 16:18:23 +01:00
|
|
|
if(msg.trim().length > 0)
|
2013-07-20 15:45:22 +02:00
|
|
|
{
|
2014-01-15 16:18:23 +01:00
|
|
|
et2_dialog.show_dialog(function(_button)
|
2013-07-20 15:45:22 +02:00
|
|
|
{
|
2014-01-15 16:18:23 +01:00
|
|
|
if (_button == et2_dialog.YES_BUTTON)
|
|
|
|
{
|
|
|
|
return self.onExecute.exec(self, _senders, _target);
|
|
|
|
}
|
|
|
|
}, msg, self.data.hint, {}, et2_dialog.BUTTONS_YES_NO, et2_dialog.QUESTION_MESSAGE);
|
|
|
|
return;
|
|
|
|
}
|
2013-07-20 15:45:22 +02:00
|
|
|
}
|
2011-04-17 19:42:04 +02:00
|
|
|
return this.onExecute.exec(this, _senders, _target);
|
2013-07-20 15:45:22 +02:00
|
|
|
};
|
2011-02-23 19:24:16 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* The set_onExecute function is the setter function for the onExecute event of
|
|
|
|
* the egwAction object. There are three possible types the passed "_value" may
|
|
|
|
* take:
|
|
|
|
* 1. _value may be a string with the word "javaScript:" prefixed. The function
|
|
|
|
* which is specified behind the colon and which has to be in the global scope
|
|
|
|
* will be executed.
|
|
|
|
* 2. _value may be a boolean, which specifies whether the external onExecute handler
|
|
|
|
* (passed as "_handler" in the constructor) will be used.
|
2012-08-14 14:02:47 +02:00
|
|
|
* 3. _value may be a JS function which will then be called.
|
2011-02-23 19:24:16 +01:00
|
|
|
* In all possible situation, the called function will get the following parameters:
|
|
|
|
* 1. A reference to this action
|
|
|
|
* 2. The senders, an array of all objects (JS)/object ids (PHP) which evoked the event
|
2014-02-25 16:03:13 +01:00
|
|
|
*
|
|
|
|
* @param {(string|function|boolean)} _value
|
2014-01-16 17:49:26 +01:00
|
|
|
*/
|
2011-02-24 20:00:47 +01:00
|
|
|
egwAction.prototype.set_onExecute = function(_value)
|
2011-02-23 19:24:16 +01:00
|
|
|
{
|
Fixed problems with executeActionImplementation when called from a container object, fixed problem with popup menu which did not open in some cases, added the ability to use the 'enabled' property of an action as an callback function (actionObject is passed as parameter), introduced egwFnct-class which consistently handles 'javaScript:fnct' strings, added 'allowOnMultiple':'only' setting, added 'hint', 'checkbox', 'checked', 'radioGroup' properties to popup actions, added 'setDefaultExecute' function to egwAction objects, which applies an handler to all objects which don't have a handler yet
2011-04-17 17:38:46 +02:00
|
|
|
this.onExecute.setValue(_value);
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-02-23 19:24:16 +01:00
|
|
|
|
2011-02-24 20:00:47 +01:00
|
|
|
egwAction.prototype.set_caption = function(_value)
|
2011-02-23 19:24:16 +01:00
|
|
|
{
|
|
|
|
this.caption = _value;
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-02-23 19:24:16 +01:00
|
|
|
|
2011-02-26 19:04:28 +01:00
|
|
|
egwAction.prototype.set_iconUrl = function(_value)
|
2011-02-23 19:24:16 +01:00
|
|
|
{
|
2011-02-26 19:04:28 +01:00
|
|
|
this.iconUrl = _value;
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-02-23 19:24:16 +01:00
|
|
|
|
2011-03-21 17:12:28 +01:00
|
|
|
egwAction.prototype.set_enabled = function(_value)
|
|
|
|
{
|
Fixed problems with executeActionImplementation when called from a container object, fixed problem with popup menu which did not open in some cases, added the ability to use the 'enabled' property of an action as an callback function (actionObject is passed as parameter), introduced egwFnct-class which consistently handles 'javaScript:fnct' strings, added 'allowOnMultiple':'only' setting, added 'hint', 'checkbox', 'checked', 'radioGroup' properties to popup actions, added 'setDefaultExecute' function to egwAction objects, which applies an handler to all objects which don't have a handler yet
2011-04-17 17:38:46 +02:00
|
|
|
this.enabled.setValue(_value);
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-03-21 17:12:28 +01:00
|
|
|
|
Fixed problems with executeActionImplementation when called from a container object, fixed problem with popup menu which did not open in some cases, added the ability to use the 'enabled' property of an action as an callback function (actionObject is passed as parameter), introduced egwFnct-class which consistently handles 'javaScript:fnct' strings, added 'allowOnMultiple':'only' setting, added 'hint', 'checkbox', 'checked', 'radioGroup' properties to popup actions, added 'setDefaultExecute' function to egwAction objects, which applies an handler to all objects which don't have a handler yet
2011-04-17 17:38:46 +02:00
|
|
|
/**
|
|
|
|
* The allowOnMultiple property may be true, false or "only"
|
2014-02-25 16:03:13 +01:00
|
|
|
*
|
|
|
|
* @param {(boolean|string)} _value
|
Fixed problems with executeActionImplementation when called from a container object, fixed problem with popup menu which did not open in some cases, added the ability to use the 'enabled' property of an action as an callback function (actionObject is passed as parameter), introduced egwFnct-class which consistently handles 'javaScript:fnct' strings, added 'allowOnMultiple':'only' setting, added 'hint', 'checkbox', 'checked', 'radioGroup' properties to popup actions, added 'setDefaultExecute' function to egwAction objects, which applies an handler to all objects which don't have a handler yet
2011-04-17 17:38:46 +02:00
|
|
|
*/
|
2011-02-24 20:00:47 +01:00
|
|
|
egwAction.prototype.set_allowOnMultiple = function(_value)
|
2011-02-23 19:24:16 +01:00
|
|
|
{
|
|
|
|
this.allowOnMultiple = _value;
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-02-23 19:24:16 +01:00
|
|
|
|
2011-03-23 21:08:33 +01:00
|
|
|
egwAction.prototype.set_hideOnDisabled = function(_value)
|
|
|
|
{
|
|
|
|
this.hideOnDisabled = _value;
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-03-23 21:08:33 +01:00
|
|
|
|
2016-02-03 14:12:37 +01:00
|
|
|
egwAction.prototype.set_hideOnMobile = function(_value)
|
|
|
|
{
|
|
|
|
this.hideOnMobile = _value;
|
|
|
|
};
|
|
|
|
|
2011-03-23 21:08:33 +01:00
|
|
|
egwAction.prototype.set_data = function(_value)
|
|
|
|
{
|
|
|
|
this.data = _value;
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-03-23 21:08:33 +01:00
|
|
|
|
2011-02-26 19:04:28 +01:00
|
|
|
egwAction.prototype.updateAction = function(_data)
|
|
|
|
{
|
2013-07-20 15:45:22 +02:00
|
|
|
egwActionStoreJSON(_data, this, "data");
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-02-26 19:04:28 +01:00
|
|
|
|
2011-03-23 15:05:39 +01:00
|
|
|
function _egwActionTreeContains(_tree, _elem)
|
|
|
|
{
|
|
|
|
for (var i = 0; i < _tree.length; i++)
|
|
|
|
{
|
|
|
|
if (_tree[i].action == _elem)
|
|
|
|
{
|
|
|
|
return _tree[i];
|
|
|
|
}
|
2011-02-23 19:24:16 +01:00
|
|
|
|
2011-03-23 15:05:39 +01:00
|
|
|
if (typeof _tree[i].children != "undefined")
|
|
|
|
{
|
|
|
|
var elem = _egwActionTreeContains(_tree[i].children, _elem);
|
|
|
|
if (elem)
|
|
|
|
{
|
|
|
|
return elem;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
2011-02-23 19:24:16 +01:00
|
|
|
|
|
|
|
/**
|
2011-03-23 15:05:39 +01:00
|
|
|
* The appendToGraph function generates an action tree which automatically contains
|
2014-01-16 17:49:26 +01:00
|
|
|
* all parent elements. If the appendToGraph function is called for a
|
2011-03-23 15:05:39 +01:00
|
|
|
*
|
2014-02-25 16:03:13 +01:00
|
|
|
* @param {array} _tree contains the tree structure - pass an object containing
|
2011-03-23 15:05:39 +01:00
|
|
|
* the empty array "root" to this function {"root": []}. The result will be stored in
|
|
|
|
* this array.
|
2014-02-25 16:03:13 +01:00
|
|
|
* @param {boolean} _addChildren is used internally to prevent parent elements from
|
2011-03-23 15:05:39 +01:00
|
|
|
* adding their children automatically to the tree.
|
2011-02-23 19:24:16 +01:00
|
|
|
*/
|
2011-03-23 15:05:39 +01:00
|
|
|
egwAction.prototype.appendToTree = function(_tree, _addChildren)
|
2011-02-23 19:24:16 +01:00
|
|
|
{
|
2011-03-23 15:05:39 +01:00
|
|
|
if (typeof _addChildren == "undefined")
|
|
|
|
{
|
|
|
|
_addChildren = true;
|
|
|
|
}
|
2011-02-23 19:24:16 +01:00
|
|
|
|
2011-03-23 15:05:39 +01:00
|
|
|
if (typeof _addParent == "undefined")
|
|
|
|
{
|
|
|
|
_addParent = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Preset some variables
|
|
|
|
var root = _tree.root;
|
|
|
|
var parent_cntr = null;
|
|
|
|
var cntr = {
|
|
|
|
"action": this,
|
|
|
|
"children": []
|
|
|
|
};
|
2011-02-23 19:24:16 +01:00
|
|
|
|
|
|
|
|
2011-06-02 16:48:03 +02:00
|
|
|
if (this.parent && this.type != "actionManager")
|
2011-02-23 19:24:16 +01:00
|
|
|
{
|
2011-03-23 15:05:39 +01:00
|
|
|
// Check whether the parent container has already been added to the tree
|
|
|
|
parent_cntr = _egwActionTreeContains(root, this.parent);
|
2011-02-23 19:24:16 +01:00
|
|
|
|
2011-03-23 15:05:39 +01:00
|
|
|
if (!parent_cntr)
|
|
|
|
{
|
|
|
|
parent_cntr = this.parent.appendToTree(_tree, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check whether this element has already been added to the parent container
|
|
|
|
var added = false;
|
|
|
|
for (var i = 0; i < parent_cntr.children.length; i++)
|
|
|
|
{
|
|
|
|
if (parent_cntr.children[i].action == this)
|
|
|
|
{
|
|
|
|
cntr = parent_cntr.children[i];
|
|
|
|
added = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!added)
|
|
|
|
{
|
|
|
|
parent_cntr.children.push(cntr);
|
|
|
|
}
|
2011-02-23 19:24:16 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-03-23 15:05:39 +01:00
|
|
|
var added = false;
|
|
|
|
for (var i = 0; i < root.length; i++)
|
2011-02-23 19:24:16 +01:00
|
|
|
{
|
2011-03-23 15:05:39 +01:00
|
|
|
if (root[i].action == this)
|
2011-02-23 19:24:16 +01:00
|
|
|
{
|
2011-03-23 15:05:39 +01:00
|
|
|
cntr = root[i];
|
|
|
|
added = true;
|
|
|
|
break;
|
2011-02-23 19:24:16 +01:00
|
|
|
}
|
2011-03-23 15:05:39 +01:00
|
|
|
}
|
2011-02-23 19:24:16 +01:00
|
|
|
|
2011-03-23 15:05:39 +01:00
|
|
|
if (!added)
|
|
|
|
{
|
|
|
|
// Add this element to the root if it has no parent
|
|
|
|
root.push(cntr);
|
2011-02-23 19:24:16 +01:00
|
|
|
}
|
|
|
|
}
|
2011-03-23 15:05:39 +01:00
|
|
|
|
|
|
|
if (_addChildren)
|
|
|
|
{
|
|
|
|
for (var i = 0; i < this.children.length; i++)
|
|
|
|
{
|
|
|
|
this.children[i].appendToTree(_tree, true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return cntr;
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-02-23 19:24:16 +01:00
|
|
|
|
2011-06-02 16:48:03 +02:00
|
|
|
/**
|
|
|
|
* Returns the parent action manager
|
|
|
|
*/
|
|
|
|
egwAction.prototype.getManager = function() {
|
|
|
|
if (this.type == "actionManager") {
|
|
|
|
return this;
|
|
|
|
} else if (this.parent) {
|
|
|
|
return this.parent.getManager();
|
|
|
|
} else {
|
|
|
|
return null;
|
|
|
|
}
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-06-02 16:48:03 +02:00
|
|
|
|
2011-03-23 15:05:39 +01:00
|
|
|
|
|
|
|
/** egwActionManager Object **/
|
|
|
|
|
2011-03-21 17:12:28 +01:00
|
|
|
/**
|
2011-03-23 15:05:39 +01:00
|
|
|
* egwActionManager manages a list of actions - it overwrites the egwAction class
|
|
|
|
* and allows child actions to be added to it.
|
2014-02-25 16:03:13 +01:00
|
|
|
*
|
|
|
|
* @param {egwAction} _parent
|
|
|
|
* @param {string} _id
|
|
|
|
* @return {egwActionManager}
|
2011-03-21 17:12:28 +01:00
|
|
|
*/
|
2011-06-02 16:48:03 +02:00
|
|
|
function egwActionManager(_parent, _id)
|
2011-02-23 19:24:16 +01:00
|
|
|
{
|
2011-06-02 16:48:03 +02:00
|
|
|
if (typeof _parent == 'undefined') {
|
|
|
|
_parent = null;
|
|
|
|
}
|
|
|
|
if (typeof _id == 'undefined') {
|
|
|
|
_id = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
var action = new egwAction(_parent, _id);
|
2011-02-23 19:24:16 +01:00
|
|
|
|
2011-03-23 15:05:39 +01:00
|
|
|
action.type = "actionManager";
|
|
|
|
action.canHaveChildren = true;
|
|
|
|
|
|
|
|
return action;
|
2011-02-23 19:24:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** egwActionImplementation Interface **/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Abstract interface for the egwActionImplementation object. The egwActionImplementation
|
|
|
|
* object is responsible for inserting the actual action representation (context menu,
|
|
|
|
* drag-drop code) into the DOM Tree by using the egwActionObjectInterface object
|
|
|
|
* supplied by the object.
|
|
|
|
* To write a "class" which derives from this object, simply write a own constructor,
|
|
|
|
* which replaces "this" with a "new egwActionImplementation" and implement your
|
|
|
|
* code in "doRegisterAction" und "doUnregisterAction".
|
|
|
|
* Register your own implementation within the _egwActionClasses object.
|
2014-02-25 16:03:13 +01:00
|
|
|
*
|
|
|
|
* @return {egwActionImplementation}
|
2011-02-23 19:24:16 +01:00
|
|
|
*/
|
2011-02-26 19:04:28 +01:00
|
|
|
function egwActionImplementation()
|
2011-02-23 19:24:16 +01:00
|
|
|
{
|
2011-02-26 19:04:28 +01:00
|
|
|
this.doRegisterAction = function() {throw "Abstract function call: registerAction"};
|
|
|
|
this.doUnregisterAction = function() {throw "Abstract function call: unregisterAction"};
|
|
|
|
this.doExecuteImplementation = function() {throw "Abstract function call: executeImplementation"};
|
|
|
|
this.type = "";
|
2011-02-23 19:24:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2014-01-16 17:49:26 +01:00
|
|
|
* Injects the implementation code into the DOM tree by using the supplied
|
2011-02-23 19:24:16 +01:00
|
|
|
* actionObjectInterface.
|
|
|
|
*
|
2014-02-25 16:03:13 +01:00
|
|
|
* @param {object} _actionObjectInterface is the AOI in which the implementation
|
2011-02-26 19:04:28 +01:00
|
|
|
* should be registered.
|
2014-02-25 16:03:13 +01:00
|
|
|
* @param {function} _triggerCallback is the callback function which will be triggered
|
2011-02-26 19:04:28 +01:00
|
|
|
* when the user triggeres this action implementatino (e.g. starts a drag-drop or
|
|
|
|
* right-clicks on an object.)
|
2014-02-25 16:03:13 +01:00
|
|
|
* @param {object} _context in which the triggerCallback should get executed.
|
2011-02-23 19:24:16 +01:00
|
|
|
* @returns true if the Action had been successfully registered, false if it
|
|
|
|
* had not.
|
|
|
|
*/
|
2011-02-26 19:04:28 +01:00
|
|
|
egwActionImplementation.prototype.registerAction = function(_actionObjectInterface, _triggerCallback, _context)
|
2011-02-23 19:24:16 +01:00
|
|
|
{
|
2011-02-26 19:04:28 +01:00
|
|
|
if (typeof _context == "undefined")
|
|
|
|
_context = null;
|
|
|
|
|
|
|
|
return this.doRegisterAction(_actionObjectInterface, _triggerCallback, _context);
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-02-23 19:24:16 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Unregister action will be called before an actionObjectInterface is destroyed,
|
|
|
|
* which gives the egwActionImplementation the opportunity to remove the previously
|
|
|
|
* injected code.
|
|
|
|
*
|
2014-02-25 16:03:13 +01:00
|
|
|
* @param {egwActionObjectInterface} _actionObjectInterface
|
2011-02-23 19:24:16 +01:00
|
|
|
* @returns true if the Action had been successfully unregistered, false if it
|
|
|
|
* had not.
|
|
|
|
*/
|
2011-02-26 19:04:28 +01:00
|
|
|
egwActionImplementation.prototype.unregisterAction = function(_actionObjectInterface)
|
2011-02-23 19:24:16 +01:00
|
|
|
{
|
2011-02-26 19:04:28 +01:00
|
|
|
return this.doUnregisterAction(_actionObjectInterface);
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-02-26 19:04:28 +01:00
|
|
|
|
|
|
|
egwActionImplementation.prototype.executeImplementation = function(_context, _selected, _links)
|
|
|
|
{
|
|
|
|
return this.doExecuteImplementation(_context, _selected, _links);
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-02-23 19:24:16 +01:00
|
|
|
|
|
|
|
|
|
|
|
/** egwActionLink Object **/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The egwActionLink is used to interconnect egwActionObjects and egwActions.
|
|
|
|
* This gives each action object the possibility to decide, whether the action
|
|
|
|
* should be active in this context or not.
|
|
|
|
*
|
|
|
|
* @param _manager is a reference to the egwActionManager whic contains the action
|
|
|
|
* the object wants to link to.
|
|
|
|
*/
|
|
|
|
function egwActionLink(_manager)
|
|
|
|
{
|
|
|
|
this.enabled = true;
|
2011-02-26 19:04:28 +01:00
|
|
|
this.visible = true;
|
2011-02-23 19:24:16 +01:00
|
|
|
this.actionId = "";
|
|
|
|
this.actionObj = null;
|
|
|
|
this.manager = _manager;
|
|
|
|
}
|
|
|
|
|
|
|
|
egwActionLink.prototype.updateLink = function (_data)
|
|
|
|
{
|
|
|
|
egwActionStoreJSON(_data, this, true);
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-02-23 19:24:16 +01:00
|
|
|
|
|
|
|
egwActionLink.prototype.set_enabled = function(_value)
|
|
|
|
{
|
|
|
|
this.enabled = _value;
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-02-23 19:24:16 +01:00
|
|
|
|
2011-02-26 19:04:28 +01:00
|
|
|
egwActionLink.prototype.set_visible = function(_value)
|
|
|
|
{
|
|
|
|
this.visible = _value;
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-02-26 19:04:28 +01:00
|
|
|
|
2011-02-23 19:24:16 +01:00
|
|
|
egwActionLink.prototype.set_actionId = function(_value)
|
|
|
|
{
|
|
|
|
this.actionId = _value;
|
2011-03-21 17:12:28 +01:00
|
|
|
this.actionObj = this.manager.getActionById(_value);
|
2011-02-23 19:24:16 +01:00
|
|
|
|
|
|
|
if (!this.actionObj)
|
2011-06-24 12:26:46 +02:00
|
|
|
throw "Action object with id '"+_value+"' does not exist!"
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-02-23 19:24:16 +01:00
|
|
|
|
|
|
|
/** egwActionObject Object **/
|
|
|
|
|
2011-02-24 17:10:11 +01:00
|
|
|
//State bitmask (only use powers of two for new states!)
|
2011-02-26 19:04:28 +01:00
|
|
|
var EGW_AO_STATE_NORMAL = 0x00;
|
|
|
|
var EGW_AO_STATE_SELECTED = 0x01;
|
|
|
|
var EGW_AO_STATE_FOCUSED = 0x02;
|
2011-03-02 22:18:20 +01:00
|
|
|
var EGW_AO_STATE_VISIBLE = 0x04; //< Can only be set by the AOI, means that the object is attached to the DOM-Tree and visible
|
2011-02-24 17:10:11 +01:00
|
|
|
|
2011-02-26 19:04:28 +01:00
|
|
|
var EGW_AO_EVENT_DRAG_OVER_ENTER = 0x00;
|
|
|
|
var EGW_AO_EVENT_DRAG_OVER_LEAVE = 0x01;
|
2011-02-24 17:10:11 +01:00
|
|
|
|
2011-02-24 20:00:47 +01:00
|
|
|
// No shift key is pressed
|
2011-02-26 19:04:28 +01:00
|
|
|
var EGW_AO_SHIFT_STATE_NONE = 0x00;
|
2011-02-24 20:00:47 +01:00
|
|
|
// A shift key, which allows multiselection is pressed (usually CTRL on a PC keyboard)
|
2011-02-26 19:04:28 +01:00
|
|
|
var EGW_AO_SHIFT_STATE_MULTI = 0x01;
|
2011-02-24 20:00:47 +01:00
|
|
|
// A shift key is pressed, which forces blockwise selection (SHIFT on a PC keyboard)
|
2011-02-26 19:04:28 +01:00
|
|
|
var EGW_AO_SHIFT_STATE_BLOCK = 0x02;
|
2011-02-24 17:10:11 +01:00
|
|
|
|
|
|
|
// If this flag is set, this object will not be returned as "focused". If this
|
|
|
|
// flag is not applied to container objects, it may lead to some strange behaviour.
|
2011-02-26 19:04:28 +01:00
|
|
|
var EGW_AO_FLAG_IS_CONTAINER = 0x01;
|
2011-02-24 17:10:11 +01:00
|
|
|
|
2011-06-15 22:54:58 +02:00
|
|
|
// If this flag is set, the object will gets its focus when no other object is
|
|
|
|
// selected and e.g. a key is pressed.
|
|
|
|
var EGW_AO_FLAG_DEFAULT_FOCUS = 0x02;
|
|
|
|
|
2011-02-23 19:24:16 +01:00
|
|
|
/**
|
|
|
|
* The egwActionObject represents an abstract object to which actions may be
|
|
|
|
* applied. Communication with the DOM tree is established by using the
|
|
|
|
* egwActionObjectInterface (AOI), which is passed in the constructor.
|
|
|
|
* egwActionObjects are organized in a tree structure.
|
|
|
|
*
|
2014-02-25 16:03:13 +01:00
|
|
|
* @param {string} _id is the identifier of the object which
|
|
|
|
* @param {egwActionObject} _parent is the parent object in the hirachy. This may be set to NULL
|
|
|
|
* @param {egwActionObjectInterface} _iface is the egwActionObjectInterface which connects the object
|
2011-02-24 20:00:47 +01:00
|
|
|
* to the outer world.
|
2014-02-25 16:03:13 +01:00
|
|
|
* @param {egwActionManager} _manager is the action manager this object is connected to
|
2011-02-24 20:00:47 +01:00
|
|
|
* this object to the DOM tree. If the _manager isn't supplied, the parent manager
|
|
|
|
* is taken.
|
2014-02-25 16:03:13 +01:00
|
|
|
* @param {number} _flags a set of additional flags being applied to the object,
|
2011-02-24 20:00:47 +01:00
|
|
|
* defaults to 0
|
2011-02-23 19:24:16 +01:00
|
|
|
*/
|
2011-02-24 20:00:47 +01:00
|
|
|
function egwActionObject(_id, _parent, _iface, _manager, _flags)
|
2011-02-23 19:24:16 +01:00
|
|
|
{
|
2011-02-24 20:00:47 +01:00
|
|
|
//Preset some parameters
|
|
|
|
if (typeof _manager == "undefined" && typeof _parent == "object" && _parent)
|
|
|
|
_manager = _parent.manager;
|
|
|
|
if (typeof _flags == "undefined")
|
|
|
|
_flags = 0;
|
|
|
|
|
2011-02-23 19:24:16 +01:00
|
|
|
this.id = _id;
|
|
|
|
this.parent = _parent;
|
|
|
|
this.children = [];
|
|
|
|
this.actionLinks = [];
|
|
|
|
this.manager = _manager;
|
2011-02-24 20:00:47 +01:00
|
|
|
this.flags = _flags;
|
2011-03-14 21:11:08 +01:00
|
|
|
this.data = null;
|
2011-03-30 16:28:49 +02:00
|
|
|
this.setSelectedCallback = null;
|
2011-02-24 17:10:11 +01:00
|
|
|
|
2011-03-02 22:18:20 +01:00
|
|
|
this.registeredImpls = [];
|
|
|
|
|
|
|
|
// Two variables which help fast travelling through the object tree, when
|
|
|
|
// searching for the selected/focused object.
|
|
|
|
this.selectedChildren = [];
|
|
|
|
this.focusedChild = null;
|
|
|
|
|
2011-03-09 23:16:41 +01:00
|
|
|
this.setAOI(_iface);
|
2011-02-24 17:10:11 +01:00
|
|
|
}
|
|
|
|
|
2011-03-09 23:16:41 +01:00
|
|
|
/**
|
|
|
|
* Sets the action object interface - if "NULL" is given, the iface is set
|
|
|
|
* to a dummy interface which is used to store the temporary data.
|
2014-02-25 16:03:13 +01:00
|
|
|
*
|
|
|
|
* @param {egwActionObjectInterface} _aoi
|
2011-03-09 23:16:41 +01:00
|
|
|
*/
|
|
|
|
egwActionObject.prototype.setAOI = function(_aoi)
|
|
|
|
{
|
|
|
|
if (_aoi == null)
|
|
|
|
{
|
|
|
|
_aoi = new egwActionObjectDummyInterface();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Copy the state from the old interface
|
|
|
|
if (this.iface)
|
|
|
|
{
|
|
|
|
_aoi.setState(this.iface.getState());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Replace the interface object
|
|
|
|
this.iface = _aoi;
|
2011-03-10 21:58:35 +01:00
|
|
|
this.iface.setStateChangeCallback(this._ifaceCallback, this);
|
|
|
|
this.iface.setReconnectActionsCallback(this._reconnectCallback, this);
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-03-09 23:16:41 +01:00
|
|
|
|
2011-02-24 20:00:47 +01:00
|
|
|
/**
|
|
|
|
* Returns the object from the tree with the given ID
|
2014-02-25 16:03:13 +01:00
|
|
|
*
|
|
|
|
* @param {string} _id
|
|
|
|
* @param {number} _search_depth
|
|
|
|
* @return {egwActionObject} description
|
|
|
|
* @todo Add search function to egw_action_commons.js
|
2011-02-24 20:00:47 +01:00
|
|
|
*/
|
2014-01-18 12:21:53 +01:00
|
|
|
egwActionObject.prototype.getObjectById = function(_id, _search_depth)
|
2011-02-24 20:00:47 +01:00
|
|
|
{
|
|
|
|
if (this.id == _id)
|
|
|
|
{
|
|
|
|
return this;
|
|
|
|
}
|
2014-01-18 12:21:53 +01:00
|
|
|
if (typeof _search_depth == "undefined") {
|
|
|
|
_search_depth = Number.MAX_VALUE;
|
|
|
|
}
|
2011-02-24 20:00:47 +01:00
|
|
|
|
2014-01-18 12:21:53 +01:00
|
|
|
for (var i = 0; i < this.children.length && _search_depth > 0; i++)
|
2011-02-24 20:00:47 +01:00
|
|
|
{
|
2014-01-18 12:21:53 +01:00
|
|
|
var obj = this.children[i].getObjectById(_id, _search_depth - 1);
|
2011-02-24 20:00:47 +01:00
|
|
|
if (obj)
|
|
|
|
{
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-02-24 20:00:47 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Adds an object as child to the actionObject and returns it - if the supplied
|
|
|
|
* parameter is a object, the object will be added directly, otherwise an object
|
|
|
|
* with the given id will be created.
|
|
|
|
*
|
2014-02-25 16:03:13 +01:00
|
|
|
* @param {(string|object)} _id Id of the object which will be created or the object
|
2011-02-24 20:00:47 +01:00
|
|
|
* that will be added.
|
2014-02-25 16:03:13 +01:00
|
|
|
* @param {object} _interface if _id was an string, _interface defines the interface which
|
2011-02-24 20:00:47 +01:00
|
|
|
* will be connected to the newly generated object.
|
2014-02-25 16:03:13 +01:00
|
|
|
* @param {number} _flags are the flags will which be supplied to the newly generated
|
2011-02-24 20:00:47 +01:00
|
|
|
* object. May be omitted.
|
|
|
|
* @returns object the generated object
|
|
|
|
*/
|
|
|
|
egwActionObject.prototype.addObject = function(_id, _interface, _flags)
|
|
|
|
{
|
|
|
|
return this.insertObject(false, _id, _interface, _flags);
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-02-24 20:00:47 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Inserts an object as child to the actionObject and returns it - if the supplied
|
|
|
|
* parameter is a object, the object will be added directly, otherwise an object
|
|
|
|
* with the given id will be created.
|
|
|
|
*
|
2014-02-25 16:03:13 +01:00
|
|
|
* @param {number} _index Position where the object will be inserted, "false" will add it
|
2011-02-24 20:00:47 +01:00
|
|
|
* to the end of the list.
|
2014-02-25 16:03:13 +01:00
|
|
|
* @param {string}/object _id Id of the object which will be created or the object
|
2011-02-24 20:00:47 +01:00
|
|
|
* that will be added.
|
2014-02-25 16:03:13 +01:00
|
|
|
* @param {object} _iface if _id was an string, _iface defines the interface which
|
2011-02-24 20:00:47 +01:00
|
|
|
* will be connected to the newly generated object.
|
2014-02-25 16:03:13 +01:00
|
|
|
* @param {number} _flags are the flags will which be supplied to the newly generated
|
2011-02-24 20:00:47 +01:00
|
|
|
* object. May be omitted.
|
|
|
|
* @returns object the generated object
|
|
|
|
*/
|
|
|
|
egwActionObject.prototype.insertObject = function(_index, _id, _iface, _flags)
|
|
|
|
{
|
|
|
|
if (_index === false)
|
|
|
|
_index = this.children.length;
|
|
|
|
|
|
|
|
var obj = null;
|
|
|
|
|
|
|
|
if (typeof _id == "object")
|
|
|
|
{
|
|
|
|
obj = _id;
|
|
|
|
|
|
|
|
// Set the parent to null and reset the focus of the object
|
|
|
|
obj.parent = null;
|
|
|
|
obj.setFocused(false);
|
|
|
|
|
|
|
|
// Set the parent to this object
|
|
|
|
obj.parent = this;
|
|
|
|
}
|
|
|
|
else if (typeof _id == "string")
|
|
|
|
{
|
2014-02-25 16:03:13 +01:00
|
|
|
obj = new egwActionObject(_id, this, _iface, this.manager, _flags);
|
2011-02-24 20:00:47 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (obj)
|
|
|
|
{
|
|
|
|
// Add the element to the children
|
|
|
|
this.children.splice(_index, 0, obj);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
throw "Error while adding new element to the ActionObjects!"
|
|
|
|
}
|
|
|
|
|
|
|
|
return obj;
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-02-24 20:00:47 +01:00
|
|
|
|
2011-05-28 17:24:31 +02:00
|
|
|
/**
|
|
|
|
* Deletes all children of the egwActionObject
|
|
|
|
*/
|
|
|
|
egwActionObject.prototype.clear = function() {
|
2011-06-26 16:57:05 +02:00
|
|
|
// Remove all children
|
|
|
|
while (this.children.length > 0) {
|
|
|
|
this.children[0].remove();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Delete all other references
|
2011-05-28 17:24:31 +02:00
|
|
|
this.selectedChildren = [];
|
|
|
|
this.focusedChild = null;
|
2013-05-29 00:08:17 +02:00
|
|
|
|
|
|
|
// Remove links
|
|
|
|
this.actionLinks = [];
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-05-28 17:24:31 +02:00
|
|
|
|
2011-06-16 19:03:39 +02:00
|
|
|
/**
|
|
|
|
* Deletes this object from the parent container
|
|
|
|
*/
|
|
|
|
egwActionObject.prototype.remove = function() {
|
|
|
|
// Remove focus and selection from this element
|
|
|
|
this.setFocused(false);
|
|
|
|
this.setSelected(false);
|
|
|
|
this.setAllSelected(false);
|
|
|
|
|
2011-06-26 16:57:05 +02:00
|
|
|
// Unregister all registered action implementations
|
|
|
|
this.unregisterActions();
|
|
|
|
|
2011-06-16 19:03:39 +02:00
|
|
|
// Clear the child-list
|
|
|
|
this.clear();
|
|
|
|
|
|
|
|
// Remove this element from the parent list
|
|
|
|
if (this.parent != null)
|
|
|
|
{
|
|
|
|
var idx = this.parent.children.indexOf(this);
|
|
|
|
|
2011-09-09 16:03:18 +02:00
|
|
|
if (idx >= 0)
|
|
|
|
{
|
|
|
|
this.parent.children.splice(idx, 1);
|
|
|
|
}
|
2011-06-16 19:03:39 +02:00
|
|
|
}
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-06-16 19:03:39 +02:00
|
|
|
|
2011-02-24 17:10:11 +01:00
|
|
|
/**
|
|
|
|
* Searches for the root object in the action object tree and returns it.
|
|
|
|
*/
|
|
|
|
egwActionObject.prototype.getRootObject = function()
|
|
|
|
{
|
|
|
|
if (this.parent === null)
|
|
|
|
{
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return this.parent.getRootObject();
|
|
|
|
}
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-02-24 17:10:11 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns a list with all parents of this object.
|
|
|
|
*/
|
|
|
|
egwActionObject.prototype.getParentList = function()
|
|
|
|
{
|
|
|
|
if (this.parent === null)
|
|
|
|
{
|
|
|
|
return [];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
var list = this.parent.getParentList();
|
|
|
|
list.unshift(this.parent);
|
|
|
|
return list;
|
|
|
|
}
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-02-24 17:10:11 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the first parent which has the container flag
|
|
|
|
*/
|
|
|
|
egwActionObject.prototype.getContainerRoot = function()
|
|
|
|
{
|
|
|
|
if (egwBitIsSet(this.flags, EGW_AO_FLAG_IS_CONTAINER) || this.parent === null)
|
|
|
|
{
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return this.parent.getContainerRoot();
|
|
|
|
}
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-02-24 17:10:11 +01:00
|
|
|
|
2011-02-26 19:04:28 +01:00
|
|
|
/**
|
2011-03-02 22:18:20 +01:00
|
|
|
* Returns all selected objects which are in the current subtree.
|
|
|
|
*
|
2014-02-25 16:03:13 +01:00
|
|
|
* @param {function} _test is a function, which gets an object and checks whether
|
2011-03-02 22:18:20 +01:00
|
|
|
* it will be added to the list.
|
2014-02-25 16:03:13 +01:00
|
|
|
* @param {array} _list is internally used to fetch all selected elements, please
|
2011-03-02 22:18:20 +01:00
|
|
|
* omit this parameter when calling the function.
|
2011-02-26 19:04:28 +01:00
|
|
|
*/
|
2011-03-02 22:18:20 +01:00
|
|
|
egwActionObject.prototype.getSelectedObjects = function(_test, _list)
|
2011-02-26 19:04:28 +01:00
|
|
|
{
|
|
|
|
if (typeof _test == "undefined")
|
|
|
|
_test = null;
|
|
|
|
|
2011-03-02 22:18:20 +01:00
|
|
|
if (typeof _list == "undefined")
|
2011-02-26 19:04:28 +01:00
|
|
|
{
|
2014-02-25 16:03:13 +01:00
|
|
|
_list = {"elements": []};
|
2011-03-02 22:18:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if ((!_test || _test(this)) && this.getSelected())
|
|
|
|
_list.elements.push(this);
|
|
|
|
|
|
|
|
if (this.selectedChildren)
|
|
|
|
{
|
|
|
|
for (var i = 0; i < this.selectedChildren.length; i++)
|
2011-02-26 19:04:28 +01:00
|
|
|
{
|
2014-02-25 16:03:13 +01:00
|
|
|
this.selectedChildren[i].getSelectedObjects(_test, _list);
|
2011-02-26 19:04:28 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-03-02 22:18:20 +01:00
|
|
|
return _list.elements;
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-02-24 17:10:11 +01:00
|
|
|
|
2011-02-26 21:40:27 +01:00
|
|
|
/**
|
|
|
|
* Returns whether all objects in this tree are selected
|
|
|
|
*/
|
|
|
|
egwActionObject.prototype.getAllSelected = function()
|
|
|
|
{
|
2011-03-02 22:18:20 +01:00
|
|
|
if (this.children.length == this.selectedChildren.length)
|
2011-02-26 21:40:27 +01:00
|
|
|
{
|
|
|
|
for (var i = 0; i < this.children.length; i++)
|
|
|
|
{
|
|
|
|
if (!this.children[i].getAllSelected())
|
|
|
|
return false;
|
|
|
|
}
|
2011-05-31 19:02:51 +02:00
|
|
|
// If this element is an container *and* does not have any children, we
|
|
|
|
// should return false. If this element is not an container we have to
|
|
|
|
// return true has this is the recursion base case
|
|
|
|
return (!egwBitIsSet(this.flags, EGW_AO_FLAG_IS_CONTAINER)) ||
|
|
|
|
(this.children.length > 0);
|
2011-02-26 21:40:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-02-26 21:40:27 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Toggles the selection of all objects.
|
|
|
|
*
|
|
|
|
* @param _select boolean specifies whether the objects should get selected or not.
|
|
|
|
* If this parameter is not supplied, the selection will be toggled.
|
|
|
|
*/
|
|
|
|
egwActionObject.prototype.toggleAllSelected = function(_select)
|
|
|
|
{
|
|
|
|
if (typeof _select == "undefined")
|
|
|
|
{
|
|
|
|
_select = !this.getAllSelected();
|
|
|
|
}
|
|
|
|
|
2014-02-28 00:06:27 +01:00
|
|
|
// Check for a select_all action
|
|
|
|
if(_select && this.manager && this.manager.getActionById('select_all'))
|
|
|
|
{
|
|
|
|
return this.manager.getActionById('select_all').execute(this);
|
|
|
|
}
|
2011-03-02 22:18:20 +01:00
|
|
|
this.setAllSelected(_select);
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-02-26 21:40:27 +01:00
|
|
|
|
2011-02-24 17:10:11 +01:00
|
|
|
/**
|
|
|
|
* Creates a list which contains all items of the element tree.
|
|
|
|
*
|
2014-02-25 16:03:13 +01:00
|
|
|
* @param {boolean} _visibleOnly
|
|
|
|
* @param {object} _obj is used internally to pass references to the array inside
|
2011-02-24 17:10:11 +01:00
|
|
|
* the object.
|
2014-02-25 16:03:13 +01:00
|
|
|
* @return {array}
|
2011-02-24 17:10:11 +01:00
|
|
|
*/
|
2011-07-03 14:33:18 +02:00
|
|
|
egwActionObject.prototype.flatList = function(_visibleOnly, _obj)
|
2011-02-24 17:10:11 +01:00
|
|
|
{
|
|
|
|
if (typeof(_obj) == "undefined")
|
|
|
|
{
|
|
|
|
_obj = {
|
2011-02-24 20:00:47 +01:00
|
|
|
"elements": []
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-02-24 17:10:11 +01:00
|
|
|
}
|
|
|
|
|
2011-07-03 14:33:18 +02:00
|
|
|
if (typeof(_visibleOnly) == "undefined")
|
|
|
|
{
|
|
|
|
_visibleOnly = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!_visibleOnly || this.getVisible())
|
|
|
|
{
|
|
|
|
_obj.elements.push(this);
|
|
|
|
}
|
2011-02-24 17:10:11 +01:00
|
|
|
|
|
|
|
for (var i = 0; i < this.children.length; i++)
|
|
|
|
{
|
2011-07-03 14:33:18 +02:00
|
|
|
this.children[i].flatList(_visibleOnly, _obj);
|
2011-02-24 17:10:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return _obj.elements;
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-02-24 17:10:11 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns a traversal list with all objects which are in between the given object
|
|
|
|
* and this one. The operation returns an empty list, if a container object is
|
|
|
|
* found on the way.
|
2014-02-25 16:03:13 +01:00
|
|
|
*
|
|
|
|
* @param {object} _to
|
|
|
|
* @return {array}
|
|
|
|
* @todo Remove flatList here!
|
2011-02-24 17:10:11 +01:00
|
|
|
*/
|
|
|
|
egwActionObject.prototype.traversePath = function(_to)
|
|
|
|
{
|
|
|
|
var contRoot = this.getContainerRoot();
|
|
|
|
|
|
|
|
if (contRoot)
|
|
|
|
{
|
|
|
|
// Get a flat list of all the hncp elements and search for this object
|
|
|
|
// and the object supplied in the _to parameter.
|
|
|
|
var flatList = contRoot.flatList();
|
2011-02-26 19:04:28 +01:00
|
|
|
var thisId = flatList.indexOf(this);
|
|
|
|
var toId = flatList.indexOf(_to);
|
2011-02-24 17:10:11 +01:00
|
|
|
|
|
|
|
// Check whether both elements have been found in this part of the tree,
|
|
|
|
// return the slice of that list.
|
|
|
|
if (thisId !== -1 && toId !== -1)
|
|
|
|
{
|
|
|
|
var from = Math.min(thisId, toId);
|
|
|
|
var to = Math.max(thisId, toId);
|
|
|
|
|
2011-02-26 19:04:28 +01:00
|
|
|
return flatList.slice(from, to + 1);
|
2011-02-24 17:10:11 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return [];
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-02-24 17:10:11 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the index of this object in the children list of the parent object.
|
|
|
|
*/
|
|
|
|
egwActionObject.prototype.getIndex = function()
|
|
|
|
{
|
|
|
|
if (this.parent === null)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return this.parent.children.indexOf(this);
|
|
|
|
}
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-02-24 17:10:11 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the deepest object which is currently focused. Objects with the
|
|
|
|
* "container"-flag will not be returned.
|
|
|
|
*/
|
|
|
|
egwActionObject.prototype.getFocusedObject = function()
|
|
|
|
{
|
2014-01-18 12:21:53 +01:00
|
|
|
return this.focusedChild || null;
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-02-24 17:10:11 +01:00
|
|
|
|
2011-02-24 20:00:47 +01:00
|
|
|
/**
|
|
|
|
* Internal function which is connected to the ActionObjectInterface associated
|
|
|
|
* with this object in the constructor. It gets called, whenever the object
|
|
|
|
* gets (de)selected.
|
|
|
|
*
|
2014-02-25 16:03:13 +01:00
|
|
|
* @param {number} _newState is the new state of the object
|
|
|
|
* @param {number} _changedBit
|
|
|
|
* @param {number} _shiftState is the status of extra keys being pressed during the
|
2011-02-24 20:00:47 +01:00
|
|
|
* selection process.
|
2014-02-25 16:03:13 +01:00
|
|
|
* @param {number}
|
2011-02-24 20:00:47 +01:00
|
|
|
*/
|
2011-03-02 22:18:20 +01:00
|
|
|
egwActionObject.prototype._ifaceCallback = function(_newState, _changedBit, _shiftState)
|
2011-02-24 17:10:11 +01:00
|
|
|
{
|
2011-02-24 22:39:05 +01:00
|
|
|
if (typeof _shiftState == "undefined")
|
|
|
|
_shiftState = EGW_AO_SHIFT_STATE_NONE;
|
2011-03-02 22:18:20 +01:00
|
|
|
|
|
|
|
var selected = egwBitIsSet(_newState, EGW_AO_STATE_SELECTED);
|
|
|
|
var visible = egwBitIsSet(_newState, EGW_AO_STATE_VISIBLE);
|
|
|
|
|
|
|
|
// Check whether the visibility of the object changed
|
|
|
|
if (_changedBit == EGW_AO_STATE_VISIBLE && visible != this.getVisible())
|
|
|
|
{
|
|
|
|
// Deselect the object
|
|
|
|
if (!visible)
|
|
|
|
{
|
|
|
|
this.setSelected(false);
|
|
|
|
this.setFocused(false);
|
|
|
|
return EGW_AO_STATE_NORMAL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Auto-register the actions attached to this object
|
|
|
|
this.registerActions();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-02-24 17:10:11 +01:00
|
|
|
// Remove the focus from all children on the same level
|
2011-03-02 22:18:20 +01:00
|
|
|
if (this.parent && visible && _changedBit == EGW_AO_STATE_SELECTED)
|
2011-02-24 17:10:11 +01:00
|
|
|
{
|
|
|
|
var selected = egwBitIsSet(_newState, EGW_AO_STATE_SELECTED);
|
2011-02-24 22:39:05 +01:00
|
|
|
var objs = [];
|
2011-02-24 17:10:11 +01:00
|
|
|
|
|
|
|
if (selected)
|
|
|
|
{
|
|
|
|
// Search the index of this object
|
|
|
|
var id = this.parent.children.indexOf(this);
|
|
|
|
|
|
|
|
// Deselect all other objects inside this container, if the "MULTI" shift-
|
|
|
|
// state is not set
|
|
|
|
if (!egwBitIsSet(_shiftState, EGW_AO_SHIFT_STATE_MULTI))
|
|
|
|
{
|
2011-03-02 22:18:20 +01:00
|
|
|
var lst = this.getContainerRoot().setAllSelected(false);
|
2011-02-24 17:10:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// If the LIST state is active, get all objects inbetween this one and the focused one
|
|
|
|
// and set their select state.
|
2011-02-24 20:00:47 +01:00
|
|
|
if (egwBitIsSet(_shiftState, EGW_AO_SHIFT_STATE_BLOCK))
|
2011-02-24 17:10:11 +01:00
|
|
|
{
|
2011-03-10 21:58:35 +01:00
|
|
|
var focused = this.getFocusedObject();
|
2011-02-24 17:10:11 +01:00
|
|
|
if (focused)
|
|
|
|
{
|
|
|
|
objs = this.traversePath(focused);
|
|
|
|
for (var i = 0; i < objs.length; i++)
|
|
|
|
{
|
|
|
|
objs[i].setSelected(true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-02-24 22:39:05 +01:00
|
|
|
}
|
2011-02-24 17:10:11 +01:00
|
|
|
|
2011-02-24 22:39:05 +01:00
|
|
|
// If the focused element didn't belong to this container, or the "list"
|
|
|
|
// shift-state isn't active, set the focus to this element.
|
|
|
|
if (objs.length == 0 || !egwBitIsSet(_shiftState, EGW_AO_SHIFT_STATE_BLOCK))
|
|
|
|
{
|
|
|
|
this.setFocused(true);
|
2011-03-02 22:18:20 +01:00
|
|
|
_newState = egwSetBit(EGW_AO_STATE_FOCUSED, _newState, true);
|
2011-02-24 17:10:11 +01:00
|
|
|
}
|
2011-03-02 22:18:20 +01:00
|
|
|
|
|
|
|
this.setSelected(selected);
|
2011-02-24 17:10:11 +01:00
|
|
|
}
|
2011-03-02 22:18:20 +01:00
|
|
|
|
|
|
|
return _newState;
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-02-24 17:10:11 +01:00
|
|
|
|
2011-06-12 18:41:40 +02:00
|
|
|
/**
|
|
|
|
* Handler for key presses
|
2014-02-25 16:03:13 +01:00
|
|
|
*
|
|
|
|
* @param {number} _keyCode
|
|
|
|
* @param {boolean} _shift
|
|
|
|
* @param {boolean} _ctrl
|
|
|
|
* @param {boolean} _alt
|
|
|
|
* @returns {boolean}
|
2011-06-12 18:41:40 +02:00
|
|
|
*/
|
|
|
|
egwActionObject.prototype.handleKeyPress = function(_keyCode, _shift, _ctrl, _alt) {
|
|
|
|
switch (_keyCode) {
|
|
|
|
case EGW_KEY_ARROW_UP:
|
|
|
|
case EGW_KEY_ARROW_DOWN:
|
|
|
|
case EGW_KEY_PAGE_UP:
|
|
|
|
case EGW_KEY_PAGE_DOWN:
|
|
|
|
|
2011-06-20 21:25:50 +02:00
|
|
|
if (!_alt)
|
2011-06-12 18:41:40 +02:00
|
|
|
{
|
2014-01-16 17:49:26 +01:00
|
|
|
var intval =
|
2011-06-19 12:48:51 +02:00
|
|
|
(_keyCode == EGW_KEY_ARROW_UP || _keyCode == EGW_KEY_ARROW_DOWN) ?
|
|
|
|
1 : 10;
|
2011-06-12 18:41:40 +02:00
|
|
|
|
2011-06-19 12:48:51 +02:00
|
|
|
if (this.children.length > 0)
|
2011-06-12 18:41:40 +02:00
|
|
|
{
|
2011-06-19 12:48:51 +02:00
|
|
|
// Get the focused object
|
|
|
|
var focused = this.getFocusedObject();
|
2011-06-12 18:41:40 +02:00
|
|
|
|
2011-06-19 12:48:51 +02:00
|
|
|
// Determine the object which should get selected
|
|
|
|
var selObj = null;
|
|
|
|
if (!focused)
|
2011-06-12 18:41:40 +02:00
|
|
|
{
|
2011-06-19 12:48:51 +02:00
|
|
|
selObj = this.children[0];
|
2011-06-12 18:41:40 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-06-19 12:48:51 +02:00
|
|
|
selObj = (_keyCode == EGW_KEY_ARROW_UP || _keyCode == EGW_KEY_PAGE_UP) ?
|
|
|
|
focused.getPrevious(intval) : focused.getNext(intval);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (selObj != null)
|
|
|
|
{
|
|
|
|
if (!_shift)
|
2011-06-12 18:41:40 +02:00
|
|
|
{
|
2011-06-19 12:48:51 +02:00
|
|
|
this.setAllSelected(false);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
var objs = focused.traversePath(selObj);
|
|
|
|
for (var i = 0; i < objs.length; i++)
|
|
|
|
{
|
|
|
|
objs[i].setSelected(true);
|
|
|
|
}
|
2011-06-12 18:41:40 +02:00
|
|
|
}
|
|
|
|
|
2011-06-19 12:48:51 +02:00
|
|
|
selObj.setSelected(true);
|
|
|
|
selObj.setFocused(true);
|
2011-06-12 18:41:40 +02:00
|
|
|
|
2011-06-19 12:48:51 +02:00
|
|
|
// Tell the aoi of the object to make it visible
|
|
|
|
selObj.makeVisible();
|
|
|
|
}
|
2011-06-12 18:41:40 +02:00
|
|
|
|
2011-06-19 12:48:51 +02:00
|
|
|
return true;
|
|
|
|
}
|
2011-06-12 18:41:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
// Handle CTRL-A to select all elements in the current container
|
|
|
|
case EGW_KEY_A:
|
2011-06-19 12:48:51 +02:00
|
|
|
if (_ctrl && !_shift && !_alt)
|
2011-06-12 18:41:40 +02:00
|
|
|
{
|
2011-06-16 19:08:32 +02:00
|
|
|
this.toggleAllSelected();
|
2011-06-12 18:41:40 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-06-12 18:41:40 +02:00
|
|
|
|
|
|
|
egwActionObject.prototype.getPrevious = function(_intval)
|
|
|
|
{
|
|
|
|
if (this.parent != null)
|
|
|
|
{
|
2011-06-15 22:54:58 +02:00
|
|
|
if (this.getFocused() && !this.getSelected()) {
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
2011-07-03 14:33:18 +02:00
|
|
|
var flatTree = this.getContainerRoot().flatList();
|
2011-06-15 22:54:58 +02:00
|
|
|
|
2011-07-03 14:33:18 +02:00
|
|
|
var idx = flatTree.indexOf(this);
|
2011-06-12 18:41:40 +02:00
|
|
|
if (idx > 0)
|
|
|
|
{
|
2011-07-03 14:33:18 +02:00
|
|
|
idx = Math.max(1, idx - _intval);
|
|
|
|
return flatTree[idx];
|
2011-06-12 18:41:40 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return this;
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-06-12 18:41:40 +02:00
|
|
|
|
|
|
|
egwActionObject.prototype.getNext = function(_intval)
|
|
|
|
{
|
|
|
|
if (this.parent != null)
|
|
|
|
{
|
2011-06-15 22:54:58 +02:00
|
|
|
if (this.getFocused() && !this.getSelected()) {
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
2011-07-03 14:33:18 +02:00
|
|
|
var flatTree = this.getContainerRoot().flatList(true);
|
|
|
|
|
|
|
|
var idx = flatTree.indexOf(this);
|
|
|
|
if (idx < flatTree.length - 1)
|
2011-06-12 18:41:40 +02:00
|
|
|
{
|
2011-07-03 14:33:18 +02:00
|
|
|
idx = Math.min(flatTree.length - 1, idx + _intval);
|
|
|
|
return flatTree[idx];
|
2011-06-12 18:41:40 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return this;
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-06-12 18:41:40 +02:00
|
|
|
|
2011-02-24 20:00:47 +01:00
|
|
|
/**
|
|
|
|
* Returns whether the object is currently selected.
|
|
|
|
*/
|
2011-02-24 17:10:11 +01:00
|
|
|
egwActionObject.prototype.getSelected = function()
|
|
|
|
{
|
|
|
|
return egwBitIsSet(this.getState(), EGW_AO_STATE_SELECTED);
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-02-24 17:10:11 +01:00
|
|
|
|
2011-02-24 20:00:47 +01:00
|
|
|
/**
|
|
|
|
* Returns whether the object is currently focused.
|
|
|
|
*/
|
2011-02-24 17:10:11 +01:00
|
|
|
egwActionObject.prototype.getFocused = function()
|
|
|
|
{
|
2011-02-24 20:00:47 +01:00
|
|
|
return egwBitIsSet(this.getState(), EGW_AO_STATE_FOCUSED);
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-02-24 17:10:11 +01:00
|
|
|
|
2011-03-02 22:18:20 +01:00
|
|
|
/**
|
|
|
|
* Returns whether the object currently is visible - visible means, that the
|
|
|
|
* AOI has a dom node and is visible.
|
|
|
|
*/
|
|
|
|
egwActionObject.prototype.getVisible = function()
|
|
|
|
{
|
|
|
|
return egwBitIsSet(this.getState(), EGW_AO_STATE_VISIBLE);
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-03-02 22:18:20 +01:00
|
|
|
|
2011-02-24 20:00:47 +01:00
|
|
|
/**
|
|
|
|
* Returns the complete state of the object.
|
|
|
|
*/
|
2011-02-24 17:10:11 +01:00
|
|
|
egwActionObject.prototype.getState = function()
|
|
|
|
{
|
2011-02-24 20:00:47 +01:00
|
|
|
return this.iface.getState();
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-02-24 17:10:11 +01:00
|
|
|
|
|
|
|
|
2011-02-24 20:00:47 +01:00
|
|
|
/**
|
|
|
|
* Sets the focus of the element. The formerly focused element in the tree will
|
|
|
|
* be de-focused.
|
|
|
|
*
|
2014-02-25 16:03:13 +01:00
|
|
|
* @param {boolean} _focused - whether to remove or set the focus. Defaults to true
|
2011-02-24 20:00:47 +01:00
|
|
|
*/
|
2011-03-02 22:18:20 +01:00
|
|
|
egwActionObject.prototype.setFocused = function(_focused)
|
2011-02-24 20:00:47 +01:00
|
|
|
{
|
|
|
|
if (typeof _focused == "undefined")
|
|
|
|
_focused = true;
|
2011-02-24 17:10:11 +01:00
|
|
|
|
2011-03-02 22:18:20 +01:00
|
|
|
var state = this.iface.getState();
|
|
|
|
|
|
|
|
if (egwBitIsSet(state, EGW_AO_STATE_FOCUSED) != _focused)
|
|
|
|
{
|
|
|
|
// Un-focus the currently focused object
|
|
|
|
var currentlyFocused = this.getFocusedObject();
|
|
|
|
if (currentlyFocused && currentlyFocused != this)
|
|
|
|
{
|
|
|
|
currentlyFocused.setFocused(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
this.iface.setState(egwSetBit(state, EGW_AO_STATE_FOCUSED, _focused));
|
|
|
|
if (this.parent)
|
|
|
|
{
|
|
|
|
this.parent.updateFocusedChild(this, _focused);
|
|
|
|
}
|
|
|
|
}
|
2011-06-12 18:41:40 +02:00
|
|
|
|
|
|
|
if (this.focusedChild != null && _focused == false)
|
|
|
|
{
|
|
|
|
this.focusedChild.setFocused(false);
|
|
|
|
}
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-02-24 17:10:11 +01:00
|
|
|
|
2011-03-02 22:18:20 +01:00
|
|
|
/**
|
|
|
|
* Sets the selected state of the element.
|
2014-02-25 16:03:13 +01:00
|
|
|
*
|
|
|
|
* @param {boolean} _selected
|
|
|
|
* @TODO Callback
|
2011-03-02 22:18:20 +01:00
|
|
|
*/
|
|
|
|
egwActionObject.prototype.setSelected = function(_selected)
|
|
|
|
{
|
|
|
|
var state = this.iface.getState();
|
2011-02-24 17:10:11 +01:00
|
|
|
|
2011-03-02 22:18:20 +01:00
|
|
|
if ((egwBitIsSet(state, EGW_AO_STATE_SELECTED) != _selected) &&
|
|
|
|
egwBitIsSet(state, EGW_AO_STATE_VISIBLE))
|
2011-02-24 17:10:11 +01:00
|
|
|
{
|
2011-03-02 22:18:20 +01:00
|
|
|
this.iface.setState(egwSetBit(state, EGW_AO_STATE_SELECTED, _selected));
|
|
|
|
if (this.parent)
|
2011-02-24 17:10:11 +01:00
|
|
|
{
|
2011-03-02 22:18:20 +01:00
|
|
|
this.parent.updateSelectedChildren(this, _selected || this.selectedChildren.length > 0);
|
2011-02-24 17:10:11 +01:00
|
|
|
}
|
2011-03-02 22:18:20 +01:00
|
|
|
}
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-03-02 22:18:20 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Sets the selected state of all elements, including children
|
2014-02-25 16:03:13 +01:00
|
|
|
*
|
|
|
|
* @param {boolean} _selected
|
|
|
|
* @param {boolean} _informParent
|
2011-03-02 22:18:20 +01:00
|
|
|
*/
|
|
|
|
egwActionObject.prototype.setAllSelected = function(_selected, _informParent)
|
|
|
|
{
|
|
|
|
if (typeof _informParent == "undefined")
|
|
|
|
_informParent = true;
|
2011-02-24 17:10:11 +01:00
|
|
|
|
2011-03-02 22:18:20 +01:00
|
|
|
var state = this.iface.getState();
|
|
|
|
|
|
|
|
// Update this element
|
|
|
|
if (egwBitIsSet(state, EGW_AO_STATE_SELECTED) != _selected)
|
|
|
|
{
|
|
|
|
this.iface.setState(egwSetBit(state, EGW_AO_STATE_SELECTED, _selected));
|
|
|
|
if (_informParent && this.parent)
|
2011-02-24 20:00:47 +01:00
|
|
|
{
|
2011-03-02 22:18:20 +01:00
|
|
|
this.parent.updateSelectedChildren(this, _selected);
|
2011-02-24 20:00:47 +01:00
|
|
|
}
|
2011-03-02 22:18:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Update the children if the should be selected or if they should be
|
|
|
|
// deselected and there are selected children.
|
|
|
|
if (_selected || this.selectedChildren.length > 0)
|
|
|
|
{
|
|
|
|
for (var i = 0; i < this.children.length; i++)
|
2011-02-24 17:10:11 +01:00
|
|
|
{
|
2011-03-02 22:18:20 +01:00
|
|
|
this.children[i].setAllSelected(_selected, false);
|
2011-02-24 17:10:11 +01:00
|
|
|
}
|
2011-03-02 22:18:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Copy the selected children list
|
2011-03-23 15:36:25 +01:00
|
|
|
this.selectedChildren = [];
|
|
|
|
if (_selected)
|
|
|
|
{
|
|
|
|
for (var i = 0; i < this.children.length; i++)
|
|
|
|
{
|
|
|
|
this.selectedChildren.push(this.children[i]);
|
|
|
|
}
|
|
|
|
}
|
2011-03-31 14:56:47 +02:00
|
|
|
|
|
|
|
// Call the setSelectedCallback
|
|
|
|
egwQueueCallback(this.setSelectedCallback, [], this, "setSelectedCallback");
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-03-02 22:18:20 +01:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Updates the selectedChildren array each actionObject has in order to determine
|
|
|
|
* all selected children in a very fast manner.
|
2014-02-25 16:03:13 +01:00
|
|
|
*
|
|
|
|
* @param {(string|egwActionObject} _child
|
|
|
|
* @param {boolean} _selected
|
|
|
|
* @todo Has also to be updated, if an child is added/removed!
|
2011-03-02 22:18:20 +01:00
|
|
|
*/
|
|
|
|
egwActionObject.prototype.updateSelectedChildren = function(_child, _selected)
|
|
|
|
{
|
2011-03-10 21:58:35 +01:00
|
|
|
var id = this.selectedChildren.indexOf(_child); // TODO Replace by binary search, insert children sorted by index!
|
2011-03-30 16:28:49 +02:00
|
|
|
var wasEmpty = this.selectedChildren.length == 0;
|
2011-02-24 20:00:47 +01:00
|
|
|
|
2011-03-02 22:18:20 +01:00
|
|
|
// Add or remove the given child from the selectedChildren list
|
|
|
|
if (_selected && id == -1)
|
|
|
|
{
|
|
|
|
this.selectedChildren.push(_child);
|
|
|
|
}
|
|
|
|
else if (!_selected && id != -1)
|
|
|
|
{
|
|
|
|
this.selectedChildren.splice(id, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the emptieness of the selectedChildren array has changed, update the
|
|
|
|
// parent selected children array.
|
|
|
|
if (wasEmpty != this.selectedChildren.length == 0 && this.parent)
|
|
|
|
{
|
|
|
|
this.parent.updateSelectedChildren(this, wasEmpty);
|
2011-02-24 17:10:11 +01:00
|
|
|
}
|
2011-03-30 16:28:49 +02:00
|
|
|
|
2011-03-31 14:56:47 +02:00
|
|
|
// Call the setSelectedCallback
|
2013-04-12 12:27:04 +02:00
|
|
|
egwQueueCallback(this.setSelectedCallback, this.getContainerRoot().getSelectedObjects(), this, "setSelectedCallback");
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-02-24 17:10:11 +01:00
|
|
|
|
2011-02-24 20:00:47 +01:00
|
|
|
/**
|
2011-03-02 22:18:20 +01:00
|
|
|
* Updates the focusedChild up to the container boundary.
|
2014-02-25 16:03:13 +01:00
|
|
|
*
|
|
|
|
* @param {(string|egwActionObject} _child
|
|
|
|
* @param {boolean} _focused
|
2011-02-24 20:00:47 +01:00
|
|
|
*/
|
2011-03-02 22:18:20 +01:00
|
|
|
egwActionObject.prototype.updateFocusedChild = function(_child, _focused)
|
2011-02-24 17:10:11 +01:00
|
|
|
{
|
2011-03-02 22:18:20 +01:00
|
|
|
if (_focused)
|
|
|
|
{
|
|
|
|
this.focusedChild = _child;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-03-09 23:16:41 +01:00
|
|
|
if (this.focusedChild == _child)
|
2011-03-02 22:18:20 +01:00
|
|
|
{
|
|
|
|
this.focusedChild = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-06-12 18:41:40 +02:00
|
|
|
if (this.parent /*&& !egwBitIsSet(this.flags, EGW_AO_FLAG_IS_CONTAINER)*/)
|
2011-03-02 22:18:20 +01:00
|
|
|
{
|
|
|
|
this.parent.updateFocusedChild(_child, _focused);
|
|
|
|
}
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-02-23 19:24:16 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Updates the actionLinks of the given ActionObject.
|
|
|
|
*
|
2014-02-25 16:03:13 +01:00
|
|
|
* @param {array} _actionLinks contains the information about the actionLinks which
|
2011-02-23 19:24:16 +01:00
|
|
|
* should be updated as an array of objects. Example
|
|
|
|
* [
|
|
|
|
* {
|
|
|
|
* "actionId": "file_delete",
|
|
|
|
* "enabled": true
|
|
|
|
* }
|
|
|
|
* ]
|
|
|
|
* If an supplied link doesn't exist yet, it will be created (if _doCreate is true)
|
|
|
|
* and added to the list. Otherwise the information will just be updated.
|
2014-02-25 16:03:13 +01:00
|
|
|
* @param {boolean} _recursive If true, the settings will be applied to all child
|
2011-02-23 19:24:16 +01:00
|
|
|
* object (default false)
|
2014-02-25 16:03:13 +01:00
|
|
|
* @param {boolean} _doCreate If true, not yet existing links will be created (default true)
|
2011-02-23 19:24:16 +01:00
|
|
|
*/
|
|
|
|
egwActionObject.prototype.updateActionLinks = function(_actionLinks, _recursive, _doCreate)
|
|
|
|
{
|
|
|
|
if (typeof _recursive == "undefined")
|
|
|
|
_recursive = false;
|
|
|
|
if (typeof _doCreate == "undefined")
|
|
|
|
_doCreate = true;
|
|
|
|
|
|
|
|
for (var i = 0; i < _actionLinks.length; i++)
|
|
|
|
{
|
|
|
|
var elem = _actionLinks[i];
|
2011-03-16 18:50:25 +01:00
|
|
|
|
|
|
|
// Allow single strings for simple action links.
|
|
|
|
if (typeof elem == "string")
|
|
|
|
{
|
|
|
|
elem = {"actionId": elem};
|
|
|
|
}
|
|
|
|
|
2011-02-23 19:24:16 +01:00
|
|
|
if (typeof elem.actionId != "undefined" && elem.actionId)
|
|
|
|
{
|
2011-02-26 19:04:28 +01:00
|
|
|
//Get the action link object, if it doesn't exist yet, create it
|
2011-02-23 19:24:16 +01:00
|
|
|
var actionLink = this.getActionLink(elem.actionId);
|
|
|
|
if (!actionLink && _doCreate)
|
|
|
|
{
|
|
|
|
actionLink = new egwActionLink(this.manager);
|
2011-02-26 19:04:28 +01:00
|
|
|
this.actionLinks.push(actionLink);
|
2011-02-23 19:24:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//Set the supplied data
|
|
|
|
if (actionLink)
|
|
|
|
{
|
|
|
|
actionLink.updateLink(elem);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_recursive)
|
|
|
|
{
|
|
|
|
for (var i = 0; i < this.children.length; i++)
|
|
|
|
{
|
|
|
|
this.children[i].updateActionLinks(_actionLinks, true, _doCreate);
|
|
|
|
}
|
|
|
|
}
|
2011-03-02 22:18:20 +01:00
|
|
|
|
2011-03-14 21:11:08 +01:00
|
|
|
if (this.getVisible() && this.iface != null)
|
2011-03-02 22:18:20 +01:00
|
|
|
{
|
|
|
|
this.registerActions();
|
|
|
|
}
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-03-02 22:18:20 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Reconnects the actions.
|
|
|
|
*/
|
|
|
|
egwActionObject.prototype._reconnectCallback = function()
|
|
|
|
{
|
|
|
|
this.registeredImpls = [];
|
2011-03-14 21:11:08 +01:00
|
|
|
this.registerActions();
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-02-23 19:24:16 +01:00
|
|
|
|
2011-02-26 21:40:27 +01:00
|
|
|
/**
|
|
|
|
* Registers the action implementations inside the DOM-Tree.
|
|
|
|
*/
|
2011-02-26 19:04:28 +01:00
|
|
|
egwActionObject.prototype.registerActions = function()
|
|
|
|
{
|
|
|
|
var groups = this.getActionImplementationGroups();
|
|
|
|
|
2011-04-23 11:07:31 +02:00
|
|
|
for (var group in groups)
|
2011-02-26 19:04:28 +01:00
|
|
|
{
|
|
|
|
// Get the action implementation for each group
|
|
|
|
if (typeof _egwActionClasses[group] != "undefined" &&
|
|
|
|
_egwActionClasses[group].implementation &&
|
|
|
|
this.iface)
|
|
|
|
{
|
|
|
|
var impl = _egwActionClasses[group].implementation();
|
|
|
|
|
2011-03-02 22:18:20 +01:00
|
|
|
if (this.registeredImpls.indexOf(impl) == -1)
|
|
|
|
{
|
|
|
|
// Register a handler for that action with the interface of that object,
|
|
|
|
// the callback and this object as context for the callback
|
|
|
|
if (impl.registerAction(this.iface, this.executeActionImplementation, this))
|
|
|
|
{
|
|
|
|
this.registeredImpls.push(impl);
|
|
|
|
}
|
|
|
|
}
|
2011-02-26 19:04:28 +01:00
|
|
|
}
|
|
|
|
}
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-02-26 19:04:28 +01:00
|
|
|
|
2011-06-26 16:57:05 +02:00
|
|
|
/**
|
|
|
|
* Unregisters all action implementations registerd to this element
|
|
|
|
*/
|
|
|
|
egwActionObject.prototype.unregisterActions = function()
|
|
|
|
{
|
|
|
|
while (this.registeredImpls.length > 0) {
|
|
|
|
var impl = this.registeredImpls.pop();
|
|
|
|
if (this.iface) {
|
|
|
|
impl.unregisterAction(this.iface);
|
|
|
|
}
|
|
|
|
}
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-06-26 16:57:05 +02:00
|
|
|
|
|
|
|
|
2011-02-26 21:40:27 +01:00
|
|
|
/**
|
|
|
|
* Calls the onBeforeTrigger function - if it is set - or returns false.
|
|
|
|
*/
|
2011-02-26 19:04:28 +01:00
|
|
|
egwActionObject.prototype.triggerCallback = function()
|
|
|
|
{
|
|
|
|
if (this.onBeforeTrigger)
|
|
|
|
{
|
|
|
|
return this.onBeforeTrigger();
|
|
|
|
}
|
|
|
|
return true;
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-02-26 19:04:28 +01:00
|
|
|
|
2011-06-12 18:41:40 +02:00
|
|
|
/**
|
|
|
|
* Calls the corresponding function of the AOI which tries to make the object
|
|
|
|
* visible.
|
|
|
|
*/
|
|
|
|
egwActionObject.prototype.makeVisible = function()
|
|
|
|
{
|
|
|
|
this.iface.makeVisible();
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-06-12 18:41:40 +02:00
|
|
|
|
2011-03-24 18:06:44 +01:00
|
|
|
var EGW_AO_EXEC_SELECTED = 0;
|
|
|
|
var EGW_AO_EXEC_THIS = 1;
|
|
|
|
|
2011-02-26 21:40:27 +01:00
|
|
|
/**
|
|
|
|
* Executes the action implementation which is associated to the given action type.
|
|
|
|
*
|
2014-02-25 16:03:13 +01:00
|
|
|
* @param {object} _implContext is data which should be delivered to the action implementation.
|
2011-02-26 21:40:27 +01:00
|
|
|
* E.g. in case of the popup action implementation, the x and y coordinates where the
|
2014-12-17 11:34:27 +01:00
|
|
|
* menu should open, and contextmenu event are transmitted.
|
2014-02-25 16:03:13 +01:00
|
|
|
* @param {string} _implType is the action type for which the implementation should be
|
2011-02-26 21:40:27 +01:00
|
|
|
* executed.
|
2014-02-25 16:03:13 +01:00
|
|
|
* @param {number} _execType specifies in which context the execution should take place.
|
2011-03-24 18:06:44 +01:00
|
|
|
* defaults to EGW_AO_EXEC_SELECTED
|
2011-02-26 21:40:27 +01:00
|
|
|
*/
|
2011-03-24 18:06:44 +01:00
|
|
|
egwActionObject.prototype.executeActionImplementation = function(_implContext, _implType, _execType)
|
2011-02-26 19:04:28 +01:00
|
|
|
{
|
2011-03-24 18:06:44 +01:00
|
|
|
if (typeof _execType == "undefined")
|
|
|
|
{
|
|
|
|
_execType = EGW_AO_EXEC_SELECTED;
|
|
|
|
}
|
|
|
|
|
2011-02-26 19:04:28 +01:00
|
|
|
if (typeof _implType == "string")
|
2011-03-24 18:06:44 +01:00
|
|
|
{
|
2011-02-26 19:04:28 +01:00
|
|
|
_implType = _egwActionClasses[_implType].implementation();
|
2011-03-24 18:06:44 +01:00
|
|
|
}
|
2011-02-26 19:04:28 +01:00
|
|
|
|
|
|
|
if (typeof _implType == "object" && _implType)
|
|
|
|
{
|
2011-03-24 18:06:44 +01:00
|
|
|
if (_execType == EGW_AO_EXEC_SELECTED)
|
|
|
|
{
|
Fixed problems with executeActionImplementation when called from a container object, fixed problem with popup menu which did not open in some cases, added the ability to use the 'enabled' property of an action as an callback function (actionObject is passed as parameter), introduced egwFnct-class which consistently handles 'javaScript:fnct' strings, added 'allowOnMultiple':'only' setting, added 'hint', 'checkbox', 'checked', 'radioGroup' properties to popup actions, added 'setDefaultExecute' function to egwAction objects, which applies an handler to all objects which don't have a handler yet
2011-04-17 17:38:46 +02:00
|
|
|
if (!(egwBitIsSet(EGW_AO_FLAG_IS_CONTAINER, this.flags)))
|
|
|
|
{
|
|
|
|
this.forceSelection();
|
|
|
|
}
|
2011-03-24 18:06:44 +01:00
|
|
|
var selectedActions = this.getSelectedLinks(_implType.type);
|
|
|
|
}
|
2014-02-25 16:03:13 +01:00
|
|
|
else if (_execType == EGW_AO_EXEC_THIS)
|
2011-03-24 18:06:44 +01:00
|
|
|
{
|
|
|
|
selectedActions = this._getLinks([this], _implType.type);
|
|
|
|
}
|
|
|
|
|
2011-02-26 19:04:28 +01:00
|
|
|
if (selectedActions.selected.length > 0 && egwObjectLength(selectedActions.links) > 0)
|
|
|
|
{
|
2011-02-26 21:40:27 +01:00
|
|
|
return _implType.executeImplementation(_implContext,
|
2011-02-26 19:04:28 +01:00
|
|
|
selectedActions.selected, selectedActions.links);
|
|
|
|
}
|
|
|
|
}
|
2011-02-26 21:40:27 +01:00
|
|
|
|
|
|
|
return false;
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-02-26 19:04:28 +01:00
|
|
|
|
|
|
|
/**
|
2011-02-26 21:40:27 +01:00
|
|
|
* Forces the object to be inside the currently selected objects. If this is
|
|
|
|
* not the case, the object will select itself and deselect all other objects.
|
2011-02-26 19:04:28 +01:00
|
|
|
*/
|
2011-02-26 21:40:27 +01:00
|
|
|
egwActionObject.prototype.forceSelection = function()
|
2011-02-26 19:04:28 +01:00
|
|
|
{
|
2011-03-02 22:18:20 +01:00
|
|
|
var selected = this.getContainerRoot().getSelectedObjects();
|
2011-02-26 19:04:28 +01:00
|
|
|
|
2011-02-26 21:40:27 +01:00
|
|
|
// Check whether this object is in the list
|
|
|
|
var thisInList = selected.indexOf(this) != -1;
|
2011-02-26 19:04:28 +01:00
|
|
|
|
2011-02-26 21:40:27 +01:00
|
|
|
// If not, select it
|
|
|
|
if (!thisInList)
|
|
|
|
{
|
2011-03-02 22:18:20 +01:00
|
|
|
this.getContainerRoot().setAllSelected(false);
|
2011-02-26 21:40:27 +01:00
|
|
|
this.setSelected(true);
|
2011-02-26 19:04:28 +01:00
|
|
|
}
|
2011-03-02 22:18:20 +01:00
|
|
|
|
|
|
|
this.setFocused(true);
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-02-26 21:40:27 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns all selected objects, and all action links of those objects, which are
|
|
|
|
* of the given implementation type, wheras actionLink properties such as
|
|
|
|
* "enabled" and "visible" are accumulated.
|
|
|
|
*
|
|
|
|
* Objects have the chance to change their action links or to deselect themselves
|
|
|
|
* in the onBeforeTrigger event, which is evaluated by the triggerCallback function.
|
|
|
|
*
|
|
|
|
* @param _actionType is the action type for which the actionLinks should be collected.
|
|
|
|
* @returns object An object which contains a "links" and a "selected" section with
|
|
|
|
* an array of links/selected objects-
|
|
|
|
*/
|
|
|
|
egwActionObject.prototype.getSelectedLinks = function(_actionType)
|
|
|
|
{
|
|
|
|
// Get all objects in this container which are currently selected
|
2011-03-02 22:18:20 +01:00
|
|
|
var selected = this.getContainerRoot().getSelectedObjects();
|
2011-02-26 19:04:28 +01:00
|
|
|
|
2011-03-24 18:06:44 +01:00
|
|
|
return this._getLinks(selected, _actionType);
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-03-24 18:06:44 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
2014-02-25 16:03:13 +01:00
|
|
|
* @param {array} _objs
|
|
|
|
* @param {string} _actionType
|
|
|
|
* @return {object} with attributes "selected" and "links"
|
2011-03-24 18:06:44 +01:00
|
|
|
*/
|
|
|
|
egwActionObject.prototype._getLinks = function(_objs, _actionType)
|
|
|
|
{
|
2011-02-26 19:04:28 +01:00
|
|
|
var actionLinks = {};
|
|
|
|
var testedSelected = [];
|
2014-01-16 17:49:26 +01:00
|
|
|
|
2013-09-04 21:09:48 +02:00
|
|
|
var test = function(olink)
|
|
|
|
{
|
|
|
|
// Test whether the action type is of the given implementation type
|
|
|
|
if (olink.actionObj.type == _actionType)
|
|
|
|
{
|
|
|
|
if (typeof actionLinks[olink.actionId] == "undefined")
|
|
|
|
{
|
|
|
|
actionLinks[olink.actionId] = {
|
|
|
|
"actionObj": olink.actionObj,
|
|
|
|
"enabled": (testedSelected.length == 1),
|
|
|
|
"visible": false,
|
|
|
|
"cnt": 0
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2013-09-04 21:09:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Accumulate the action link properties
|
|
|
|
var llink = actionLinks[olink.actionId];
|
|
|
|
llink.enabled = llink.enabled && olink.actionObj.enabled.exec(olink.actionObj, _objs, _objs[i]) &&
|
|
|
|
olink.enabled && olink.visible;
|
|
|
|
llink.visible = (llink.visible || olink.visible);
|
|
|
|
llink.cnt++;
|
2014-01-16 17:49:26 +01:00
|
|
|
|
2013-09-04 21:09:48 +02:00
|
|
|
// Add in children, so they can get checked for visible / enabled
|
|
|
|
if(olink.actionObj && olink.actionObj.children.length > 0)
|
|
|
|
{
|
|
|
|
for(var j = 0; j < olink.actionObj.children.length; j++)
|
|
|
|
{
|
|
|
|
var child = olink.actionObj.children[j];
|
|
|
|
test({
|
|
|
|
actionObj: child,
|
|
|
|
actionId: child.id,
|
|
|
|
enabled: olink.enabled,
|
|
|
|
visible: olink.visible
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
2014-01-16 17:49:26 +01:00
|
|
|
|
2011-03-24 18:06:44 +01:00
|
|
|
for (var i = 0; i < _objs.length; i++)
|
2011-02-26 19:04:28 +01:00
|
|
|
{
|
2011-03-24 18:06:44 +01:00
|
|
|
var obj = _objs[i];
|
2011-05-28 17:24:31 +02:00
|
|
|
if (!egwBitIsSet(obj.flags, EGW_AO_FLAG_IS_CONTAINER) && obj.triggerCallback())
|
2011-02-26 19:04:28 +01:00
|
|
|
{
|
|
|
|
testedSelected.push(obj);
|
|
|
|
|
|
|
|
for (var j = 0; j < obj.actionLinks.length; j++)
|
|
|
|
{
|
2013-09-04 21:09:48 +02:00
|
|
|
test(obj.actionLinks[j]); //object link
|
2011-02-26 19:04:28 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-02-26 21:40:27 +01:00
|
|
|
// Check whether all objects supported the action
|
2011-04-23 11:07:31 +02:00
|
|
|
for (var k in actionLinks)
|
2011-02-26 19:04:28 +01:00
|
|
|
{
|
2011-02-26 21:40:27 +01:00
|
|
|
actionLinks[k].enabled = actionLinks[k].enabled &&
|
|
|
|
(actionLinks[k].cnt >= testedSelected.length) &&
|
Fixed problems with executeActionImplementation when called from a container object, fixed problem with popup menu which did not open in some cases, added the ability to use the 'enabled' property of an action as an callback function (actionObject is passed as parameter), introduced egwFnct-class which consistently handles 'javaScript:fnct' strings, added 'allowOnMultiple':'only' setting, added 'hint', 'checkbox', 'checked', 'radioGroup' properties to popup actions, added 'setDefaultExecute' function to egwAction objects, which applies an handler to all objects which don't have a handler yet
2011-04-17 17:38:46 +02:00
|
|
|
(
|
2014-01-16 17:49:26 +01:00
|
|
|
(actionLinks[k].actionObj.allowOnMultiple === true) ||
|
Fixed problems with executeActionImplementation when called from a container object, fixed problem with popup menu which did not open in some cases, added the ability to use the 'enabled' property of an action as an callback function (actionObject is passed as parameter), introduced egwFnct-class which consistently handles 'javaScript:fnct' strings, added 'allowOnMultiple':'only' setting, added 'hint', 'checkbox', 'checked', 'radioGroup' properties to popup actions, added 'setDefaultExecute' function to egwAction objects, which applies an handler to all objects which don't have a handler yet
2011-04-17 17:38:46 +02:00
|
|
|
(actionLinks[k].actionObj.allowOnMultiple == "only" && actionLinks[k].cnt > 1) ||
|
|
|
|
(actionLinks[k].actionObj.allowOnMultiple == false && actionLinks[k].cnt == 1)
|
|
|
|
);
|
2016-02-03 14:12:37 +01:00
|
|
|
if (!egwIsMobile()) actionLinks[k].actionObj.hideOnMobile = false;
|
|
|
|
actionLinks[k].visible = actionLinks[k].visible && !actionLinks[k].actionObj.hideOnMobile &&
|
2011-03-23 21:08:33 +01:00
|
|
|
(actionLinks[k].enabled || !actionLinks[k].actionObj.hideOnDisabled);
|
2011-02-26 19:04:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Return an object which contains the accumulated actionLinks and all selected
|
|
|
|
// objects.
|
|
|
|
return {
|
|
|
|
"selected": testedSelected,
|
|
|
|
"links": actionLinks
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
|
|
|
};
|
2011-02-26 19:04:28 +01:00
|
|
|
|
2011-02-23 19:24:16 +01:00
|
|
|
/**
|
|
|
|
* Returns the action link, which contains the association to the action with
|
|
|
|
* the given actionId.
|
|
|
|
*
|
2014-02-25 16:03:13 +01:00
|
|
|
* @param {string} _actionId name of the action associated to the link
|
2011-02-23 19:24:16 +01:00
|
|
|
*/
|
|
|
|
egwActionObject.prototype.getActionLink = function(_actionId)
|
|
|
|
{
|
|
|
|
for (var i = 0; i < this.actionLinks.length; i++)
|
|
|
|
{
|
|
|
|
if (this.actionLinks[i].actionObj.id == _actionId)
|
|
|
|
{
|
|
|
|
return this.actionLinks[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-02-23 19:24:16 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns all actions associated to the object tree, grouped by type.
|
|
|
|
*
|
2014-02-25 16:03:13 +01:00
|
|
|
* @param {function} _test gets an egwActionObject and should return, whether the
|
2011-02-23 19:24:16 +01:00
|
|
|
* actions of this object are added to the result. Defaults to a "always true"
|
|
|
|
* function.
|
2014-02-25 16:03:13 +01:00
|
|
|
* @param {object} _groups is an internally used parameter, may be omitted.
|
2011-02-23 19:24:16 +01:00
|
|
|
*/
|
|
|
|
egwActionObject.prototype.getActionImplementationGroups = function(_test, _groups)
|
|
|
|
{
|
|
|
|
// If the _groups parameter hasn't been given preset it to an empty object
|
|
|
|
// (associative array).
|
|
|
|
if (typeof _groups == "undefined")
|
|
|
|
_groups = {};
|
|
|
|
if (typeof _test == "undefined")
|
2014-02-25 16:03:13 +01:00
|
|
|
_test = function(_obj) {return true;};
|
2011-02-23 19:24:16 +01:00
|
|
|
|
|
|
|
for (var i = 0; i < this.actionLinks.length; i++)
|
|
|
|
{
|
2011-02-26 19:04:28 +01:00
|
|
|
var action = this.actionLinks[i].actionObj;
|
2011-02-23 19:24:16 +01:00
|
|
|
if (typeof action != "undefined" && _test(this))
|
|
|
|
{
|
|
|
|
if (typeof _groups[action.type] == "undefined")
|
|
|
|
{
|
|
|
|
_groups[action.type] = [];
|
|
|
|
}
|
|
|
|
|
|
|
|
_groups[action.type].push(
|
|
|
|
{
|
|
|
|
"object": this,
|
|
|
|
"link": this.actionLinks[i]
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-02-24 17:10:11 +01:00
|
|
|
// Recursively add the actions of the children to the result (as _groups is
|
|
|
|
// an object, only the reference is passed).
|
2011-02-23 19:24:16 +01:00
|
|
|
for (var i = 0; i < this.children.length; i++)
|
|
|
|
{
|
|
|
|
this.children[i].getActionImplementationGroups(_test, _groups);
|
|
|
|
}
|
|
|
|
|
|
|
|
return _groups;
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-02-23 19:24:16 +01:00
|
|
|
|
2014-10-24 13:15:33 +02:00
|
|
|
/**
|
|
|
|
* Check if user tries to get dragOut action
|
2016-03-29 14:49:05 +02:00
|
|
|
*
|
2014-10-24 13:15:33 +02:00
|
|
|
* keys for dragOut:
|
|
|
|
* -Mac: Command + Shift
|
|
|
|
* -Others: Alt + Shift
|
2016-03-29 14:49:05 +02:00
|
|
|
*
|
2014-10-24 13:15:33 +02:00
|
|
|
* @param {event} _event
|
|
|
|
* @return {boolean} return true if Alt+Shift keys and left mouse click arre pressed, otherwise false
|
|
|
|
*/
|
|
|
|
egwActionObject.prototype.isDragOut = function (_event)
|
|
|
|
{
|
|
|
|
return (_event.altKey || _event.metaKey) && _event.shiftKey && _event.which == 1;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Check if user tries to get selection action
|
2016-03-29 14:49:05 +02:00
|
|
|
*
|
2014-10-24 13:15:33 +02:00
|
|
|
* Keys for selection:
|
|
|
|
* -Mac: Command key
|
|
|
|
* -Others: Ctrl key
|
2016-03-29 14:49:05 +02:00
|
|
|
*
|
2014-10-24 13:15:33 +02:00
|
|
|
* @param {type} _event
|
2016-03-29 14:49:05 +02:00
|
|
|
* @returns {Boolean} return true if left mouse click and Ctrl/Alt key are pressed, otherwise false
|
2014-10-24 13:15:33 +02:00
|
|
|
*/
|
|
|
|
egwActionObject.prototype.isSelection = function (_event)
|
|
|
|
{
|
2016-03-29 14:49:05 +02:00
|
|
|
return !(_event.shiftKey) && _event.which == 1 && (_event.metaKey || _event.ctrlKey || _event.altKey);
|
2014-10-24 13:15:33 +02:00
|
|
|
};
|
2011-02-24 17:10:11 +01:00
|
|
|
|
|
|
|
/** egwActionObjectInterface Interface **/
|
|
|
|
|
|
|
|
/**
|
2014-01-16 17:49:26 +01:00
|
|
|
* The egwActionObjectInterface has to be implemented for each actual object in
|
2011-02-24 17:10:11 +01:00
|
|
|
* the browser. E.g. for the object "DataGridRow", there has to be an
|
|
|
|
* egwActionObjectInterface which is responsible for returning the outer DOMNode
|
|
|
|
* of the object to which JS-Events may be attached by the egwActionImplementation
|
|
|
|
* object, and to do object specific stuff like highlighting the object in the
|
|
|
|
* correct way and to route state changes (like: "object has been selected")
|
|
|
|
* to the egwActionObject object the interface is associated to.
|
2014-02-25 16:03:13 +01:00
|
|
|
*
|
|
|
|
* @return {egwActionObjectInterface}
|
2011-02-24 17:10:11 +01:00
|
|
|
*/
|
|
|
|
function egwActionObjectInterface()
|
|
|
|
{
|
|
|
|
//Preset the interface functions
|
|
|
|
|
2014-02-25 16:03:13 +01:00
|
|
|
this.doGetDOMNode = function() {return null;};
|
2011-02-24 17:10:11 +01:00
|
|
|
|
|
|
|
// _outerCall may be used to determine, whether the state change has been
|
|
|
|
// evoked from the outside and the stateChangeCallback has to be called
|
|
|
|
// or not.
|
|
|
|
this.doSetState = function(_state, _outerCall) {};
|
|
|
|
|
2011-03-24 18:06:44 +01:00
|
|
|
// The doTiggerEvent function may be overritten by the aoi if it wants to
|
|
|
|
// support certain action implementation specific events like EGW_AI_DRAG_OVER
|
|
|
|
// or EGW_AI_DRAG_OUT
|
2014-02-25 16:03:13 +01:00
|
|
|
this.doTriggerEvent = function(_event, _data) {return false;};
|
2011-03-24 18:06:44 +01:00
|
|
|
|
2011-06-12 18:41:40 +02:00
|
|
|
this.doMakeVisible = function() {};
|
|
|
|
|
2011-03-02 22:18:20 +01:00
|
|
|
this._state = EGW_AO_STATE_NORMAL || EGW_AO_STATE_VISIBLE;
|
2011-02-24 17:10:11 +01:00
|
|
|
|
2011-03-02 22:18:20 +01:00
|
|
|
this.stateChangeCallback = null;
|
|
|
|
this.stateChangeContext = null;
|
|
|
|
this.reconnectActionsCallback = null;
|
|
|
|
this.reconnectActionsContext = null;
|
2011-02-24 17:10:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sets the callback function which will be called when a user interaction changes
|
|
|
|
* state of the object.
|
2014-02-25 16:03:13 +01:00
|
|
|
*
|
|
|
|
* @param {function} _callback
|
|
|
|
* @param {object} _context
|
2011-02-24 17:10:11 +01:00
|
|
|
*/
|
2011-02-24 20:00:47 +01:00
|
|
|
egwActionObjectInterface.prototype.setStateChangeCallback = function(_callback, _context)
|
2011-02-24 17:10:11 +01:00
|
|
|
{
|
|
|
|
this.stateChangeCallback = _callback;
|
|
|
|
this.stateChangeContext = _context;
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-02-24 17:10:11 +01:00
|
|
|
|
2011-03-02 22:18:20 +01:00
|
|
|
/**
|
|
|
|
* Sets the reconnectActions callback, which will be called by the AOI if its
|
|
|
|
* DOM-Node has been replaced and the actions have to be re-registered.
|
2014-02-25 16:03:13 +01:00
|
|
|
*
|
|
|
|
* @param {function} _callback
|
|
|
|
* @param {object} _context
|
2011-03-02 22:18:20 +01:00
|
|
|
*/
|
|
|
|
egwActionObjectInterface.prototype.setReconnectActionsCallback = function(_callback, _context)
|
|
|
|
{
|
|
|
|
this.reconnectActionsCallback = _callback;
|
|
|
|
this.reconnectActionsContext = _context;
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-03-02 22:18:20 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Will be called by the aoi if the actions have to be re-registered due to a
|
|
|
|
* DOM-Node exchange.
|
|
|
|
*/
|
|
|
|
egwActionObjectInterface.prototype.reconnectActions = function()
|
|
|
|
{
|
|
|
|
if (this.reconnectActionsCallback)
|
|
|
|
{
|
|
|
|
this.reconnectActionsCallback.call(this.reconnectActionsContext);
|
|
|
|
}
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-03-02 22:18:20 +01:00
|
|
|
|
2011-02-24 17:10:11 +01:00
|
|
|
/**
|
|
|
|
* Internal function which should be used whenever the select status of the object
|
|
|
|
* has been changed by the user. This will automatically calculate the new state of
|
|
|
|
* the object and call the stateChangeCallback (if it has been set)
|
|
|
|
*
|
2014-02-25 16:03:13 +01:00
|
|
|
* @param {number} _stateBit is the bit in the state bit which should be changed
|
|
|
|
* @param {boolean} _set specifies whether the state bit should be set or not
|
|
|
|
* @param {boolean} _shiftState
|
2011-02-24 17:10:11 +01:00
|
|
|
*/
|
2011-03-02 22:18:20 +01:00
|
|
|
egwActionObjectInterface.prototype.updateState = function(_stateBit, _set, _shiftState)
|
2011-02-24 17:10:11 +01:00
|
|
|
{
|
2011-03-02 22:18:20 +01:00
|
|
|
// Calculate the new state
|
|
|
|
var newState = egwSetBit(this._state, _stateBit, _set);
|
|
|
|
|
|
|
|
// Call the stateChangeCallback if the state really changed
|
2011-02-24 22:39:05 +01:00
|
|
|
if (this.stateChangeCallback)
|
2011-02-24 17:10:11 +01:00
|
|
|
{
|
2011-03-02 22:18:20 +01:00
|
|
|
this._state = this.stateChangeCallback.call(this.stateChangeContext, newState,
|
|
|
|
_stateBit, _shiftState);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this._state = newState;
|
2011-02-24 17:10:11 +01:00
|
|
|
}
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-02-24 17:10:11 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the DOM-Node the ActionObject is actually a representation of.
|
|
|
|
* Calls the internal "doGetDOMNode" function, which has to be overwritten
|
|
|
|
* by implementations of this class.
|
|
|
|
*/
|
|
|
|
egwActionObjectInterface.prototype.getDOMNode = function()
|
|
|
|
{
|
|
|
|
return this.doGetDOMNode();
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-02-24 17:10:11 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Sets the state of the object.
|
|
|
|
* Calls the internal "doSetState" function, which has to be overwritten
|
|
|
|
* by implementations of this class. The state-change callback must not be evoked!
|
|
|
|
*
|
|
|
|
* @param _state is the state of the object.
|
|
|
|
*/
|
|
|
|
egwActionObjectInterface.prototype.setState = function(_state)
|
|
|
|
{
|
|
|
|
//Call the doSetState function with the new state (if it has changed at all)
|
|
|
|
if (_state != this._state)
|
|
|
|
{
|
|
|
|
this._state = _state;
|
2011-03-02 22:18:20 +01:00
|
|
|
this.doSetState(_state);
|
2011-02-24 17:10:11 +01:00
|
|
|
}
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-02-24 17:10:11 +01:00
|
|
|
|
|
|
|
/**
|
2014-01-16 17:49:26 +01:00
|
|
|
* Returns the current state of the object. The state is maintained by the
|
2011-02-24 17:10:11 +01:00
|
|
|
* egwActionObjectInterface and implementations do not have to overwrite this
|
|
|
|
* function as long as they call the _selectChange function.
|
|
|
|
*/
|
|
|
|
egwActionObjectInterface.prototype.getState = function()
|
|
|
|
{
|
|
|
|
return this._state;
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-02-24 17:10:11 +01:00
|
|
|
|
2011-03-24 18:06:44 +01:00
|
|
|
/**
|
|
|
|
* The trigger event function can be called by the action implementation in order
|
2014-02-25 16:03:13 +01:00
|
|
|
* to tell the AOI to perform some action.
|
2011-03-24 18:06:44 +01:00
|
|
|
* In the drag/drop handler this function is e.g. used for telling the droppable
|
|
|
|
* element that there was a drag over/out event.
|
2014-02-25 16:03:13 +01:00
|
|
|
*
|
|
|
|
* @param {object} _event
|
|
|
|
* @param _data
|
2011-03-24 18:06:44 +01:00
|
|
|
*/
|
|
|
|
egwActionObjectInterface.prototype.triggerEvent = function(_event, _data)
|
|
|
|
{
|
|
|
|
if (typeof _data == "undefined")
|
|
|
|
{
|
|
|
|
_data = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
return this.doTriggerEvent(_event, _data);
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-03-24 18:06:44 +01:00
|
|
|
|
2011-06-12 18:41:40 +02:00
|
|
|
/**
|
|
|
|
* Scrolls the element into a visble area if it is currently hidden
|
|
|
|
*/
|
|
|
|
egwActionObjectInterface.prototype.makeVisible = function()
|
|
|
|
{
|
|
|
|
return this.doMakeVisible();
|
2014-02-25 16:03:13 +01:00
|
|
|
};
|
2011-03-09 23:16:41 +01:00
|
|
|
|
|
|
|
/** -- egwActionObjectDummyInterface Class -- **/
|
|
|
|
|
|
|
|
var egwActionObjectDummyInterface = egwActionObjectInterface;
|
|
|
|
|
2011-02-24 20:00:47 +01:00
|
|
|
/** egwActionObjectManager Object **/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The egwActionObjectManager is a dummy class which only contains a dummy
|
|
|
|
* AOI. It may be used as root object or as object containers.
|
2014-02-25 16:03:13 +01:00
|
|
|
*
|
|
|
|
* @param {egwAction} _id
|
|
|
|
* @param {string} _manager
|
|
|
|
* @return {egwActionObjectManager}
|
2011-02-24 20:00:47 +01:00
|
|
|
*/
|
|
|
|
function egwActionObjectManager(_id, _manager)
|
|
|
|
{
|
2011-02-26 21:40:27 +01:00
|
|
|
var ao = new egwActionObject(_id, null, new egwActionObjectInterface(),
|
2011-02-24 22:39:05 +01:00
|
|
|
_manager, EGW_AO_FLAG_IS_CONTAINER);
|
2011-02-26 21:40:27 +01:00
|
|
|
|
|
|
|
// The object manager doesn't allow selections and cannot perform actions
|
|
|
|
ao.triggerCallback = function() {return false;};
|
|
|
|
|
|
|
|
return ao;
|
2011-02-24 20:00:47 +01:00
|
|
|
}
|