diff --git a/etemplate/js/et2_core_DOMWidget.js b/etemplate/js/et2_core_DOMWidget.js
index c84a686dd0..2a2f7954c1 100644
--- a/etemplate/js/et2_core_DOMWidget.js
+++ b/etemplate/js/et2_core_DOMWidget.js
@@ -409,51 +409,40 @@ var et2_DOMWidget = et2_widget.extend(et2_IDOMNode,
this._actionManager = gam.addAction("actionManager", this.id);
}
}
- // ActionManager wants an array
- var parsed_actions = [];
- if(typeof actions == "object" && actions)
- {
- var parse = function(actions)
- {
- var parsed = [];
- for(var key in actions)
- {
- actions[key].id = key;
- if(typeof actions[key].icon != "undefined" && actions[key].icon)
- {
- actions[key].iconUrl = this.egw().image(actions[key].icon);
- }
- if(typeof actions[key].children != "undefined")
- {
- actions[key].children = parse(actions[key].children);
- }
- parsed.push(actions[key]);
- }
- return parsed;
- };
- // Don't make changes to original
- var action = jQuery.extend(true, {}, actions);
- parsed_actions = parse.call(this, action);
- }
- else
- {
- parsed_actions = actions;
- }
- this._actionManager.updateActions(parsed_actions);
+ this._actionManager.updateActions(actions);
// Put a reference to the widget into the action stuff, so we can
// easily get back to widget context from the action handler
this._actionManager.data = {widget: this};
// Link the actions to the DOM
- this._link_actions(parsed_actions);
+ this._link_actions(actions);
+ },
+
+ /**
+ * Get all action-links / id's of 1.-level actions from a given action object
+ *
+ * This can be overwritten to not allow all actions, by not returning them here.
+ *
+ * @param actions
+ * @returns {Array}
+ */
+ _get_action_links: function(actions)
+ {
+ var action_links = [];
+ for(var i in actions)
+ {
+ var action = actions[i];
+ action_links.push(typeof action.id != 'undefined' ? action.id : i);
+ }
+ return action_links;
},
/**
* Link the actions to the DOM nodes / widget bits.
*
*/
- _link_actions: function(parsed_actions)
+ _link_actions: function(actions)
{
// Get the top level element for the tree
var objectManager = egw_getAppObjectManager(true);
@@ -472,12 +461,7 @@ var et2_DOMWidget = et2_widget.extend(et2_IDOMNode,
// Go over the widget & add links - this is where we decide which actions are
// 'allowed' for this widget at this time
- var action_links = [];
- for(var i = 0; i < parsed_actions.length; i++)
- {
- action_links.push(parsed_actions[i].id);
- }
-
+ var action_links = this._get_action_links(actions);
widget_object.updateActionLinks(action_links);
}
});
diff --git a/etemplate/js/et2_extension_nextmatch_actions.js b/etemplate/js/et2_extension_nextmatch_actions.js
index 944227d4ca..b83b8d51f1 100644
--- a/etemplate/js/et2_extension_nextmatch_actions.js
+++ b/etemplate/js/et2_extension_nextmatch_actions.js
@@ -195,48 +195,6 @@ function nm_action(_action, _senders, _target, _ids)
}
}
-/**
- * Callback to check if none of _senders rows has disableClass set
- *
- * @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
- */
-function nm_not_disableClass(_action, _senders, _target)
-{
- return !$j(_target.iface.getDOMNode()).hasClass(_action.data.disableClass);
-}
-
-/**
- * Callback to check if all of _senders rows have enableClass set
- *
- * @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
- */
-function nm_enableClass(_action, _senders, _target)
-{
- return $j(_target.iface.getDOMNode()).hasClass(_action.data.enableClass);
-}
-
-/**
- * Enable an _action, if it matches a given regular expresstion in _action.data.enableId
- *
- * @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
- */
-function nm_enableId(_action, _senders, _target)
-{
- if (typeof _action.data.enableId == 'string')
- _action.data.enableId = new RegExp(_action.data.enableId);
-
- return _target.id.match(_action.data.enableId);
-}
-
/**
* Callback to check if a certain field (_action.data.fieldId) is (not) equal to given value (_action.data.fieldValue)
*
diff --git a/etemplate/js/et2_widget_split.js b/etemplate/js/et2_widget_split.js
index 5588b2a325..bf090ceea6 100644
--- a/etemplate/js/et2_widget_split.js
+++ b/etemplate/js/et2_widget_split.js
@@ -70,8 +70,8 @@ var et2_split = et2_DOMWidget.extend([et2_IResizeable],
this.div = $j(document.createElement("div"));
// Create the dynheight component which dynamically scales the inner
- // container.
- this.dynheight = new et2_dynheight(this.egw().window,this.div, 100);
+ // container.
+ this.dynheight = new et2_dynheight(this.egw().window,this.div, 100);
// Add something so we can see it - will be replaced if there's children
this.left = $j("
Top / Left
").appendTo(this.div);
diff --git a/etemplate/js/et2_widget_tree.js b/etemplate/js/et2_widget_tree.js
index 0593fbb4d0..cb7098ff0a 100644
--- a/etemplate/js/et2_widget_tree.js
+++ b/etemplate/js/et2_widget_tree.js
@@ -317,25 +317,11 @@ var et2_tree = et2_inputWidget.extend(
},
/**
- * Set Actions on the tree
+ * Links actions to tree nodes
*
- * Each action is defined as an object:
- * move: {
- * type: "drop",
- * acceptedTypes: "mail",
- * icon: "move",
- * caption: "Move to"
- * onExecute: javascript:mail_move"
- * }
- *
- * This will turn all the tree nodes into drop targets. When "mail" drag types are dropped,
- * the global function mail_move(egwAction action, egwActionObject sender) will be called. The ID of the
- * dragged "mail" will be in sender.id, some information about the sender will be in sender.context.
- *
- * @param Array[ {ID, attributes..}+] array of egw action information - this is different from what is passed in to
- * set_actions, which takes a more human-friendly Object map.
+ * @param Object[ {ID: attributes..}+] as for set_actions
*/
- _link_actions: function(parsed_actions)
+ _link_actions: function(actions)
{
// Get the top level element for the tree
var objectManager = egw_getAppObjectManager(true);
@@ -350,11 +336,8 @@ var et2_tree = et2_inputWidget.extend(
treeObj.clear();
// Go over the tree parts & add links
- var action_links = [];
- for(var i = 0; i < parsed_actions.length; i++)
- {
- action_links.push(parsed_actions[i].id);
- }
+ var action_links = this._get_action_links(actions);
+
if (typeof this.options.select_options != 'undefined')
{
diff --git a/phpgwapi/js/egw_action/egw_action.js b/phpgwapi/js/egw_action/egw_action.js
index cf64e453bc..0075f897fe 100644
--- a/phpgwapi/js/egw_action/egw_action.js
+++ b/phpgwapi/js/egw_action/egw_action.js
@@ -120,7 +120,7 @@ function egwActionHandler(_executeEvent)
* Associative array where action classes may register themselves
*/
if (typeof window._egwActionClasses == "undefined")
- window._egwActionClasses = {}
+ window._egwActionClasses = {};
_egwActionClasses["default"] = {
"actionConstructor": egwAction,
@@ -151,7 +151,7 @@ function egwAction(_parent, _id, _caption, _iconUrl, _onExecute, _allowOnMultipl
this.allowOnMultiple = _allowOnMultiple;
this.enabled = new egwFnct(this, true);
this.hideOnDisabled = false;
- this.data = null; // Data which can be freely assigned to the action
+ this.data = {}; // Data which can be freely assigned to the action
this.type = "default"; //All derived classes have to override this!
this.canHaveChildren = false; //Has to be overwritten by inherited action classes
@@ -274,23 +274,119 @@ egwAction.prototype.addAction = function(_type, _id, _caption, _iconUrl,
}
else
{
- throw "This action does not allow child elements!"
+ throw "This action does not allow child elements!";
}
-}
+};
+
+/**
+ * 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',
+ paste: 'editpaste',
+};
/**
* Updates the children of this element
+ *
+ * @param Object _actions { id: action, ...}
+ * @param string _app defaults to egw_getAppname()
*/
-egwAction.prototype.updateActions = function(_actions)
+egwAction.prototype.updateActions = function(_actions, _app)
{
if (this.canHaveChildren)
{
- for (var i = 0 ; i < _actions.length; i++)
+ 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)
{
- //Check whether the given action is already part of this action manager instance
var elem = _actions[i];
- if (typeof elem == "object" && typeof elem.id == "string" && elem.id)
+
+ if (typeof elem == "string") elem = { caption: elem };
+
+ if (typeof elem == "object")
{
+ // 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")
+ {
+ var parts = elem.icon.split('/', 2); // app/image syntax to search icon in different app
+ if (parts.length == 2)
+ {
+ elem.iconUrl = egw.image(parts[1], parts[0]);
+ }
+ else
+ {
+ elem.iconUrl = egw.image(elem.icon);
+ }
+ }
+ delete elem.icon;
+ }
+
+ // 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') };
+ }
+
+ // translate caption
+ if (typeof elem.no_lang == "undefined" || !elem.no_lang)
+ {
+ 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) != '?' ? '?' : '');
+ }
+ }
+
+ if (typeof elem.confirm != "undefined") elem.confirm = egw.lang(elem.confirm);
+ if (typeof elem.confirm_multiple != "undefined") elem.confirm_multiple = egw.lang(elem.confirm_multiple);
+
+ // set certain enabled functions
+ if (typeof elem.enabled == "undefined")
+ {
+ 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;
+ }
+ }
+
//Check whether the action already exists, and if no, add it to the
//actions list
var action = this.getActionById(elem.id);
@@ -305,7 +401,7 @@ egwAction.prototype.updateActions = function(_actions)
// array
if (this.canHaveChildren !== true && this.canHaveChildren.indexOf(elem.type) == -1)
{
- throw "This child type '" + elem.type + "' is not allowed!"
+ throw "This child type '" + elem.type + "' is not allowed!";
}
if (typeof _egwActionClasses[elem.type] != "undefined")
@@ -324,7 +420,7 @@ egwAction.prototype.updateActions = function(_actions)
// Add sub-actions to the action
if (elem.children)
{
- action.updateActions(elem.children);
+ action.updateActions(elem.children, _app);
}
}
}
@@ -333,7 +429,49 @@ egwAction.prototype.updateActions = function(_actions)
{
throw "This action element cannot have children!";
}
-}
+};
+
+/**
+ * Callback to check if none of _senders rows has disableClass set
+ *
+ * @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)
+{
+ return !$j(_target.iface.getDOMNode()).hasClass(_action.data.disableClass);
+};
+
+/**
+ * Callback to check if all of _senders rows have enableClass set
+ *
+ * @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)
+{
+ return $j(_target.iface.getDOMNode()).hasClass(_action.data.enableClass);
+};
+
+/**
+ * Enable an _action, if it matches a given regular expresstion in _action.data.enableId
+ *
+ * @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);
+
+ return _target.id.match(_action.data.enableId);
+};
/**
* Applys the same onExecute handler to all actions which don't have an execute
@@ -370,8 +508,21 @@ egwAction.prototype.execute = function(_senders, _target)
_target = null;
}
+ // check if actions needs to be confirmed first
+ if (this.data && this.data.confirm && this.onExecute.fcnt != window.nm_action)
+ {
+ var self = this;
+ et2_dialog.show_dialog(function(_button)
+ {
+ if (_button == et2_dialog.YES_BUTTON)
+ {
+ return self.onExecute.exec(self, _senders, _target);
+ }
+ }, self.data.confirm, self.data.hint, {}, et2_dialog.BUTTONS_YES_NO, et2_dialog.QUESTION_MESSAGE);
+ return;
+ }
return this.onExecute.exec(this, _senders, _target);
-}
+};
/**
* The set_onExecute function is the setter function for the onExecute event of
@@ -427,7 +578,7 @@ egwAction.prototype.set_data = function(_value)
egwAction.prototype.updateAction = function(_data)
{
- egwActionStoreJSON(_data, this, true);
+ egwActionStoreJSON(_data, this, "data");
}
function _egwActionTreeContains(_tree, _elem)
diff --git a/phpgwapi/js/egw_action/egw_action_common.js b/phpgwapi/js/egw_action/egw_action_common.js
index ac97f36b9c..4d8db7149a 100644
--- a/phpgwapi/js/egw_action/egw_action_common.js
+++ b/phpgwapi/js/egw_action/egw_action_common.js
@@ -17,6 +17,7 @@
* @param object _data may be an object with data that will be stored inside the
* given object.
* @param object _obj is the object where the data will be stored.
+ * @param mixed _setterOnly false: store everything, true: only store when setter exists, "data" store rest in data property
*/
function egwActionStoreJSON(_data, _obj, _setterOnly)
{
@@ -33,6 +34,10 @@ function egwActionStoreJSON(_data, _obj, _setterOnly)
{
_obj[key] = _data[key];
}
+ else if (_setterOnly === 'data')
+ {
+ _obj.data[key] = _data[key];
+ }
}
}
}