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

This commit is contained in:
Andreas Stöckel 2011-04-17 15:38:46 +00:00
parent fe5202c7a2
commit cb9355ac00
6 changed files with 197 additions and 52 deletions

View File

@ -53,7 +53,7 @@ function egwAction(_parent, _id, _caption, _iconUrl, _onExecute, _allowOnMultipl
this.caption = _caption;
this.iconUrl = _iconUrl;
this.allowOnMultiple = _allowOnMultiple;
this.enabled = true;
this.enabled = new egwFnct(this, true);
this.hideOnDisabled = false;
this.data = null; // Data which can be freely assigned to the action
@ -62,9 +62,7 @@ function egwAction(_parent, _id, _caption, _iconUrl, _onExecute, _allowOnMultipl
this.parent = _parent;
this.children = [];
this.execJSFnct = null;
this.execHandler = false;
this.set_onExecute(_onExecute);
this.onExecute = new egwFnct(this, null, []);
}
/**
@ -189,6 +187,28 @@ egwAction.prototype.updateActions = function(_actions)
}
}
/**
* Applys the same onExecute handler to all actions which don't have an execute
* handler set.
*/
egwAction.prototype.setDefaultExecute = function(_value)
{
// Check whether the onExecute handler of this action should be set
if (this.type != "actionManager" && !this.onExecute.hasHandler())
{
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);
}
}
}
/**
* Executes this action by using the method specified in the onExecute setter.
*
@ -202,14 +222,7 @@ egwAction.prototype.execute = function(_senders, _target)
_target == null;
}
if (this.execJSFnct && typeof this.execJSFnct == "function")
{
return this.execJSFnct(this, _senders, _target);
}
else if (this.execHandler)
{
//this.handler.execute(this, _senders); TODO
}
this.onExecute.exec(this, _senders, _target);
return false;
}
@ -230,35 +243,7 @@ egwAction.prototype.execute = function(_senders, _target)
*/
egwAction.prototype.set_onExecute = function(_value)
{
//Reset the onExecute handlers
this.execJSFnct = null;
this.execHandler = false;
if (typeof _value == "string")
{
// Check whether the given string contains a javaScript function which
// should be called upon executing the action
if (_value.substr(0, 11) == "javaScript:")
{
//Check whether the given function exists
var fnct = _value.substr(11);
if (typeof window[fnct] == "function")
{
this.execJSFnct = window[fnct];
}
}
}
else if (typeof _value == "boolean")
{
// There is no direct reference to the PHP code which should be executed,
// as the PHP code has knowledge about this.
this.execHandler = _value;
}
else if (typeof _value == "function")
{
//The JS function has been passed directly
this.execJSFnct = _value;
}
this.onExecute.setValue(_value);
}
egwAction.prototype.set_caption = function(_value)
@ -273,9 +258,12 @@ egwAction.prototype.set_iconUrl = function(_value)
egwAction.prototype.set_enabled = function(_value)
{
this.enabled = _value;
this.enabled.setValue(_value);
}
/**
* The allowOnMultiple property may be true, false or "only"
*/
egwAction.prototype.set_allowOnMultiple = function(_value)
{
this.allowOnMultiple = _value;
@ -1314,7 +1302,10 @@ egwActionObject.prototype.executeActionImplementation = function(_implContext, _
{
if (_execType == EGW_AO_EXEC_SELECTED)
{
this.forceSelection();
if (!(egwBitIsSet(EGW_AO_FLAG_IS_CONTAINER, this.flags)))
{
this.forceSelection();
}
var selectedActions = this.getSelectedLinks(_implType.type);
}
else if (_execType = EGW_AO_EXEC_THIS)
@ -1406,7 +1397,7 @@ egwActionObject.prototype._getLinks = function(_objs, _actionType)
// Accumulate the action link properties
var llink = actionLinks[olink.actionId];
llink.enabled = olink.actionObj.enabled && llink.enabled &&
llink.enabled = llink.enabled && olink.actionObj.enabled.exec(this) &&
olink.enabled && olink.visible;
llink.visible = (llink.visible || olink.visible);
llink.cnt++;
@ -1420,8 +1411,11 @@ egwActionObject.prototype._getLinks = function(_objs, _actionType)
{
actionLinks[k].enabled = actionLinks[k].enabled &&
(actionLinks[k].cnt >= testedSelected.length) &&
(actionLinks[k].actionObj.allowOnMultiple ||
actionLinks[k].cnt == 1);
(
(actionLinks[k].actionObj.allowOnMultiple === true) ||
(actionLinks[k].actionObj.allowOnMultiple == "only" && actionLinks[k].cnt > 1) ||
(actionLinks[k].actionObj.allowOnMultiple == false && actionLinks[k].cnt == 1)
);
actionLinks[k].visible = actionLinks[k].visible &&
(actionLinks[k].enabled || !actionLinks[k].actionObj.hideOnDisabled);
}

View File

@ -295,6 +295,87 @@ egwEventQueue.prototype.queueTimeout = function(_proc, _context, _args, _id, _ti
}, _timeout)
}
/**
* Class which is used to be able to handle references to JavaScript functions
* from strings.
*
* @param object _context is the context in which the function will be executed.
* @param mixed _default is the default value which should be returned when no
* function (string) has been set. If it is a function this function will be
* called.
* @param array _acceptedTypes is an array of types which contains the "typeof"
* strings of accepted non-functions in setValue
*/
function egwFnct(_context, _default, _acceptedTypes)
{
if (typeof _context == "undefined")
{
_context = null;
}
if (typeof _default == "undefined")
{
_default = false;
}
if (typeof _acceptedTypes == "undefined")
{
_acceptedTypes = ["boolean"];
}
this.context = _context;
this.acceptedTypes = _acceptedTypes;
this.fnct = null;
this.value = null;
this.setValue(_default);
}
egwFnct.prototype.hasHandler = function()
{
return this.fnct !== null;
}
/**
* Sets the function/return value for the exec function
*/
egwFnct.prototype.setValue = function(_value)
{
this.value = null;
this.fnct = null;
if (typeof _value == "function")
{
this.fnct = _value;
}
else if (typeof _value == "string" &&
_value.substr(0,11) == "javaScript:" &&
typeof window[_value.substr(11)] == "function")
{
this.fnct = window[_value.substr(11)];
}
else if (this.acceptedTypes.indexOf(typeof _value) >= 0)
{
this.value = _value;
}
}
/**
* Executes the function
*/
egwFnct.prototype.exec = function()
{
if (this.fnct)
{
return this.fnct.apply(this.context, arguments);
}
else
{
return this.value;
}
}
/**
sprintf() for JavaScript 0.6

View File

@ -25,6 +25,10 @@ function egwPopupAction(_id, _handler, _caption, _icon, _onExecute, _allowOnMult
action["default"] = false;
action.order = 0;
action.group = 0;
action.hint = false;
action.checkbox = false;
action.radioGroup = 0;
action.checked = false;
action.set_default = function(_value) {
action["default"] = _value;
@ -38,6 +42,25 @@ function egwPopupAction(_id, _handler, _caption, _icon, _onExecute, _allowOnMult
action.group = _value;
}
action.set_hint = function(_value) {
action.hint = _value;
}
// If true, the action will be rendered as checkbox
action.set_checkbox = function(_value) {
action.checkbox = _value;
}
action.set_checked = function(_value) {
action.checked = _value;
}
// If radioGroup is >0 and the element is a checkbox, radioGroup specifies
// the group of radio buttons this one belongs to
action.set_radioGroup = function(_value) {
action.radioGroup = _value;
}
return action;
}
@ -136,8 +159,8 @@ function egwPopupActionImplementation()
// Calculate context menu position from the given DOM-Node
var node = _context;
x = node.offsetLeft;
y = node.offsetTop;
x = $(node).offset().left;
y = $(node).offset().top;
_context = {"posx": x, "posy": y}
}
@ -284,10 +307,23 @@ function egwPopupActionImplementation()
var item = _menu.addItem(link.actionObj.id, link.actionObj.caption,
link.actionObj.iconUrl);
item["default"] = link.actionObj["default"];
item.data = link.actionObj;
// As this code is also used when a drag-drop popup menu is built,
// we have to perform this check
if (link.actionObj.type == "popup")
{
item.set_hint(link.actionObj.hint);
item.set_checkbox(link.actionObj.checkbox);
item.set_checked(link.actionObj.checked);
item.set_groupIndex(link.actionObj.radioGroup);
}
item.set_data(link.actionObj);
if (link.enabled && _enabled)
{
item.set_onClick(function(elem) {
// Copy the "checked" state
elem.data.checked = elem.checked;
elem.data.execute(_selected, _target);
});
}

View File

@ -406,3 +406,8 @@ egwMenuItem.prototype.set_data = function(_value)
this.data = _value;
}
egwMenuItem.prototype.set_hint = function(_value)
{
this.hint = _value;
}

View File

@ -116,6 +116,12 @@ egwMenuImpl.prototype._translateStructure = function(_structure, _parentId, _idC
//Set the actual egw menu as user data element
this.dhtmlxmenu.setUserData(id, 'egw_menu', elem);
// Set the tooltip if one has been set
if (elem.hint)
{
this.dhtmlxmenu.setTooltip(id, elem.hint);
}
var last_id = id;
}
@ -136,7 +142,11 @@ egwMenuImpl.prototype.showAt = function(_x, _y, _onHide)
}
});
}
this.dhtmlxmenu.showContextMenu(_x, _y);
var self = this;
window.setTimeout(function() {
self.dhtmlxmenu.showContextMenu(_x, _y);
}, 0);
}
egwMenuImpl.prototype.hide = function()

View File

@ -256,7 +256,9 @@
"onExecute": alertClicked,
"type": "popup",
"group": 1,
"order": 2
"order": 2,
"allowOnMultiple": "only",
"hint": "Compresses multiple files and mails them"
},
{
"id": "send_to",
@ -333,6 +335,21 @@
"iconUrl": "imgs/copy.png",
"onExecute": alertClicked,
"acceptedTypes": "file"
},
{
"id": "chk1",
"type": "popup",
"checkbox": true,
"checked": true,
"caption": "Test1"
},
{
"id": "chk2",
"type": "popup",
"checkbox": true,
"checked": false,
"caption": "Test2",
"onExecute": alertClicked
}
]
);
@ -347,7 +364,9 @@
{"actionId": "file_compress", "enabled": true},
{"actionId": "file_delete", "enabled": true},
{"actionId": "send_to", "enabled": true},
"file_drag"
"file_drag",
"chk1",
"chk2"
];
var listboxFolderLinks = [