2011-08-11 15:53:35 +02:00
|
|
|
/**
|
2013-04-13 21:00:13 +02:00
|
|
|
* EGroupware eTemplate2 - JS DOM Widget class
|
2011-08-11 15:53:35 +02:00
|
|
|
*
|
|
|
|
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
|
|
|
* @package etemplate
|
|
|
|
* @subpackage api
|
|
|
|
* @link http://www.egroupware.org
|
|
|
|
* @author Andreas Stöckel
|
|
|
|
* @copyright Stylite 2011
|
|
|
|
* @version $Id$
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*egw:uses
|
2011-08-25 15:35:53 +02:00
|
|
|
et2_core_interfaces;
|
2011-08-24 12:18:07 +02:00
|
|
|
et2_core_widget;
|
2016-04-07 12:38:05 +02:00
|
|
|
/api/js/egw_action/egw_action.js;
|
2011-08-11 15:53:35 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Abstract widget class which can be inserted into the DOM. All widget classes
|
|
|
|
* deriving from this class have to care about implementing the "getDOMNode"
|
|
|
|
* function which has to return the DOM-Node.
|
2013-10-30 10:43:12 +01:00
|
|
|
*
|
2013-04-13 21:00:13 +02:00
|
|
|
* @augments et2_widget
|
2011-08-11 15:53:35 +02:00
|
|
|
*/
|
2016-02-29 21:40:43 +01:00
|
|
|
var et2_DOMWidget = (function(){ "use strict"; return et2_widget.extend(et2_IDOMNode,
|
2013-04-13 21:00:13 +02:00
|
|
|
{
|
2011-08-12 17:26:08 +02:00
|
|
|
attributes: {
|
|
|
|
"disabled": {
|
2013-02-11 09:13:29 +01:00
|
|
|
"name": "Disabled",
|
2011-08-12 17:26:08 +02:00
|
|
|
"type": "boolean",
|
2013-02-11 09:13:29 +01:00
|
|
|
"description": "Defines whether this widget is visible. Not to be confused with an input widget's HTML attribute 'disabled'.",
|
2011-08-12 17:26:08 +02:00
|
|
|
"default": false
|
2011-08-19 18:00:44 +02:00
|
|
|
},
|
|
|
|
"width": {
|
|
|
|
"name": "Width",
|
|
|
|
"type": "dimension",
|
|
|
|
"default": et2_no_init,
|
|
|
|
"description": "Width of the element in pixels, percentage or 'auto'"
|
|
|
|
},
|
|
|
|
"height": {
|
|
|
|
"name": "Height",
|
|
|
|
"type": "dimension",
|
|
|
|
"default": et2_no_init,
|
|
|
|
"description": "Height of the element in pixels, percentage or 'auto'"
|
2011-08-22 13:16:37 +02:00
|
|
|
},
|
|
|
|
"class": {
|
|
|
|
"name": "CSS Class",
|
|
|
|
"type": "string",
|
|
|
|
"default": et2_no_init,
|
|
|
|
"description": "CSS Class which is applied to the dom element of this node"
|
2011-08-22 18:37:04 +02:00
|
|
|
},
|
|
|
|
"overflow": {
|
|
|
|
"name": "Overflow",
|
|
|
|
"type": "string",
|
|
|
|
"default": et2_no_init,
|
|
|
|
"description": "If set, the css-overflow attribute is set to that value"
|
2013-02-13 12:21:24 +01:00
|
|
|
},
|
|
|
|
"parent_node": {
|
|
|
|
"name": "DOM parent",
|
|
|
|
"type": "string",
|
|
|
|
"default": et2_no_init,
|
|
|
|
"description": "Insert into the target DOM node instead of the normal location"
|
2013-03-26 22:19:17 +01:00
|
|
|
},
|
|
|
|
"actions": {
|
|
|
|
"name": "Actions list",
|
|
|
|
"type": "any",
|
|
|
|
"default": et2_no_init,
|
|
|
|
"description": "List of egw actions that can be done on the widget. This includes context menu, drag and drop. TODO: Link to action documentation"
|
2014-03-06 19:35:57 +01:00
|
|
|
},
|
|
|
|
default_execute: {
|
|
|
|
name: "Default onExecute for actions",
|
|
|
|
type: "js",
|
|
|
|
default: et2_no_init,
|
|
|
|
description: "Set default onExecute javascript method for action not specifying their own"
|
2015-01-21 19:59:12 +01:00
|
|
|
},
|
2014-12-04 17:38:34 +01:00
|
|
|
resize_ratio: {
|
|
|
|
name: "Resize height of the widget on callback resize",
|
|
|
|
type:"string",
|
|
|
|
default: '',
|
|
|
|
description: "Allow Resize height of the widget based on exess height and given ratio"
|
2015-01-21 19:59:12 +01:00
|
|
|
},
|
|
|
|
data: {
|
|
|
|
name: "comma-separated name:value pairs set as data attributes on DOM node",
|
|
|
|
type: "string",
|
|
|
|
default: '',
|
|
|
|
description: 'data="mime:${row}[mime]" would generate data-mime="..." in DOM, eg. to use it in CSS on a parent'
|
2015-10-13 17:03:41 +02:00
|
|
|
},
|
|
|
|
background: {
|
|
|
|
name: "Add background image",
|
|
|
|
type: "string",
|
|
|
|
default:'',
|
|
|
|
description: "Sets background image, left, right and scale on DOM",
|
2014-01-29 18:45:24 +01:00
|
|
|
}
|
2011-08-12 17:26:08 +02:00
|
|
|
},
|
|
|
|
|
2011-08-11 15:53:35 +02:00
|
|
|
/**
|
|
|
|
* When the DOMWidget is initialized, it grabs the DOM-Node of the parent
|
|
|
|
* object (if available) and passes it to its own "createDOMNode" function
|
2013-10-30 10:43:12 +01:00
|
|
|
*
|
2013-04-13 21:00:13 +02:00
|
|
|
* @memberOf et2_DOMWidget
|
2011-08-11 15:53:35 +02:00
|
|
|
*/
|
2011-08-19 18:00:44 +02:00
|
|
|
init: function() {
|
|
|
|
// Call the inherited constructor
|
|
|
|
this._super.apply(this, arguments);
|
|
|
|
|
2011-08-11 15:53:35 +02:00
|
|
|
this.parentNode = null;
|
|
|
|
|
|
|
|
this._attachSet = {
|
|
|
|
"node": null,
|
|
|
|
"parent": null
|
|
|
|
};
|
|
|
|
|
2012-03-26 16:08:57 +02:00
|
|
|
this.disabled = false;
|
2011-08-23 16:59:49 +02:00
|
|
|
this._surroundingsMgr = null;
|
2011-08-11 15:53:35 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Detatches the node from the DOM and clears all references to the parent
|
|
|
|
* node or the dom node of this widget.
|
|
|
|
*/
|
|
|
|
destroy: function() {
|
|
|
|
|
2013-05-28 01:24:22 +02:00
|
|
|
this.detachFromDOM();
|
2011-08-11 15:53:35 +02:00
|
|
|
this.parentNode = null;
|
|
|
|
this._attachSet = {};
|
|
|
|
|
2014-05-07 16:38:44 +02:00
|
|
|
if(this._actionManager)
|
|
|
|
{
|
2014-09-30 18:52:42 +02:00
|
|
|
var app_om = egw_getObjectManager(this.egw().getAppName(), false,1);
|
|
|
|
if(app_om)
|
2014-05-07 22:55:34 +02:00
|
|
|
{
|
2014-09-30 18:52:42 +02:00
|
|
|
var om = app_om.getObjectById(this.id);
|
2014-05-07 22:55:34 +02:00
|
|
|
if(om) om.remove();
|
|
|
|
}
|
2014-05-07 16:38:44 +02:00
|
|
|
this._actionManager.remove();
|
|
|
|
this._actionManager = null;
|
|
|
|
}
|
2015-01-21 19:59:12 +01:00
|
|
|
|
2011-08-23 16:59:49 +02:00
|
|
|
if (this._surroundingsMgr)
|
|
|
|
{
|
2011-08-25 15:35:53 +02:00
|
|
|
this._surroundingsMgr.free();
|
2011-08-23 16:59:49 +02:00
|
|
|
this._surroundingsMgr = null;
|
|
|
|
}
|
|
|
|
|
2011-08-11 15:53:35 +02:00
|
|
|
this._super();
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
2011-08-19 18:00:44 +02:00
|
|
|
* Attaches the container node of this widget to the DOM-Tree
|
2011-08-11 15:53:35 +02:00
|
|
|
*/
|
2011-08-19 18:00:44 +02:00
|
|
|
doLoadingFinished: function() {
|
2011-08-11 15:53:35 +02:00
|
|
|
// Check whether the parent implements the et2_IDOMNode interface. If
|
|
|
|
// yes, grab the DOM node and create our own.
|
|
|
|
if (this._parent && this._parent.implements(et2_IDOMNode)) {
|
2013-02-13 12:21:24 +01:00
|
|
|
if(this.options.parent_node)
|
|
|
|
{
|
|
|
|
this.set_parent_node(this.options.parent_node);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this.setParentDOMNode(this._parent.getDOMNode(this));
|
|
|
|
}
|
2011-08-11 15:53:35 +02:00
|
|
|
}
|
2011-08-19 18:00:44 +02:00
|
|
|
|
|
|
|
return true;
|
2011-08-11 15:53:35 +02:00
|
|
|
},
|
2015-01-21 19:59:12 +01:00
|
|
|
|
2011-08-11 15:53:35 +02:00
|
|
|
/**
|
|
|
|
* Detaches the widget from the DOM tree, if it had been attached to the
|
|
|
|
* DOM-Tree using the attachToDOM method.
|
|
|
|
*/
|
2013-05-28 01:24:22 +02:00
|
|
|
detachFromDOM: function() {
|
2011-08-11 15:53:35 +02:00
|
|
|
|
|
|
|
if (this._attachSet.node && this._attachSet.parent)
|
|
|
|
{
|
|
|
|
// Remove the current node from the parent node
|
2013-05-28 01:24:22 +02:00
|
|
|
try {
|
|
|
|
this._attachSet.parent.removeChild(this._attachSet.node);
|
|
|
|
} catch (e) {
|
|
|
|
// Don't throw a DOM error if the node wasn't in the parent
|
|
|
|
}
|
2011-08-11 15:53:35 +02:00
|
|
|
|
|
|
|
// Reset the "attachSet"
|
|
|
|
this._attachSet = {
|
|
|
|
"node": null,
|
|
|
|
"parent": null
|
|
|
|
};
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Attaches the widget to the DOM tree. Fails if the widget is already
|
|
|
|
* attached to the tree or no parent node or no node for this widget is
|
|
|
|
* defined.
|
|
|
|
*/
|
|
|
|
attachToDOM: function() {
|
|
|
|
// Attach the DOM node of this widget (if existing) to the new parent
|
|
|
|
var node = this.getDOMNode(this);
|
|
|
|
if (node && this.parentNode &&
|
|
|
|
(node != this._attachSet.node ||
|
|
|
|
this.parentNode != this._attachSet.parent))
|
|
|
|
{
|
2011-08-23 16:59:49 +02:00
|
|
|
// If the surroundings manager exists, surround the DOM-Node of this
|
|
|
|
// widget with the DOM-Nodes inside the surroundings manager.
|
|
|
|
if (this._surroundingsMgr)
|
|
|
|
{
|
|
|
|
node = this._surroundingsMgr.getDOMNode(node);
|
|
|
|
}
|
|
|
|
|
2011-08-26 13:15:28 +02:00
|
|
|
// Append this node at its index
|
2011-09-05 16:35:28 +02:00
|
|
|
var idx = this.getDOMIndex();
|
2011-08-26 13:15:28 +02:00
|
|
|
if (idx < 0 || idx >= this.parentNode.childNodes.length - 1)
|
|
|
|
{
|
|
|
|
this.parentNode.appendChild(node);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this.parentNode.insertBefore(node, this.parentNode.childNodes[idx]);
|
|
|
|
}
|
2011-08-11 15:53:35 +02:00
|
|
|
|
|
|
|
// Store the currently attached nodes
|
|
|
|
this._attachSet = {
|
|
|
|
"node": node,
|
|
|
|
"parent": this.parentNode
|
|
|
|
};
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
},
|
|
|
|
|
2011-08-21 17:22:00 +02:00
|
|
|
isAttached: function() {
|
|
|
|
return this.parentNode != null;
|
|
|
|
},
|
|
|
|
|
2011-08-23 16:59:49 +02:00
|
|
|
getSurroundings: function() {
|
|
|
|
if (!this._surroundingsMgr)
|
|
|
|
{
|
|
|
|
this._surroundingsMgr = new et2_surroundingsMgr(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
return this._surroundingsMgr;
|
|
|
|
},
|
|
|
|
|
2019-04-03 22:59:32 +02:00
|
|
|
/**
|
|
|
|
* Get data for the tab this widget is on.
|
|
|
|
*
|
|
|
|
* Will return null if the widget is not on a tab or tab data containing
|
|
|
|
* - id
|
|
|
|
* - label
|
|
|
|
* - widget (top level widget)
|
|
|
|
* - contentDiv (jQuery object for the div the tab content is in)
|
|
|
|
*
|
|
|
|
* @returns {Object|null} Data for tab the widget is on
|
|
|
|
*/
|
|
|
|
get_tab_info: function() {
|
|
|
|
var parent = this;
|
|
|
|
do {
|
|
|
|
parent = parent._parent;
|
|
|
|
} while (parent !== this.getRoot() && parent._type !== 'tabbox');
|
|
|
|
|
|
|
|
// No tab
|
|
|
|
if(parent === this.getRoot())
|
|
|
|
{
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Find the tab index
|
|
|
|
for(var i = 0; i < parent.tabData.length; i++)
|
|
|
|
{
|
|
|
|
// Find the tab
|
|
|
|
if(parent.tabData[i].contentDiv.has(this.div).length)
|
|
|
|
{
|
|
|
|
return parent.tabData[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// On a tab, but we couldn't find it? This gives best result so far.
|
|
|
|
return this._parent.get_tab_info();
|
|
|
|
},
|
|
|
|
|
2013-02-13 12:21:24 +01:00
|
|
|
/**
|
|
|
|
* Set the parent DOM node of this element. Takes a wider variety of types
|
|
|
|
* than setParentDOMNode(), and matches the set_<attribute> naming convention.
|
|
|
|
*
|
|
|
|
* @param _node String|DOMNode DOM node to contain the widget, or the ID of the DOM node.
|
|
|
|
*/
|
|
|
|
set_parent_node: function(_node) {
|
|
|
|
if(typeof _node == "string")
|
|
|
|
{
|
2016-06-02 16:51:15 +02:00
|
|
|
var parent = jQuery('#'+_node);
|
2017-05-18 19:45:56 +02:00
|
|
|
if(parent.length === 0 && window.parent)
|
|
|
|
{
|
|
|
|
// Could not find it, try again with wider context
|
|
|
|
// (in case there's an iframe in admin, for example)
|
|
|
|
parent = jQuery('#'+_node, window.parent.document);
|
|
|
|
}
|
|
|
|
if(parent.length === 0)
|
2014-02-03 17:22:27 +01:00
|
|
|
{
|
|
|
|
this.egw().debug('warn','Unable to find DOM parent node with ID "%s" for widget %o.',_node,this);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this.setParentDOMNode(parent.get(0));
|
|
|
|
}
|
2013-02-13 12:21:24 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this.setParentDOMNode(_node);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2011-08-11 15:53:35 +02:00
|
|
|
/**
|
|
|
|
* Set the parent DOM node of this element. If another parent node is already
|
|
|
|
* set, this widget removes itself from the DOM tree
|
2014-01-29 18:45:24 +01:00
|
|
|
*
|
|
|
|
* @param _node
|
2011-08-11 15:53:35 +02:00
|
|
|
*/
|
|
|
|
setParentDOMNode: function(_node) {
|
|
|
|
if (_node != this.parentNode)
|
|
|
|
{
|
|
|
|
// Detatch this element from the DOM tree
|
2013-05-28 01:24:22 +02:00
|
|
|
this.detachFromDOM();
|
2011-08-11 15:53:35 +02:00
|
|
|
|
|
|
|
this.parentNode = _node;
|
|
|
|
|
|
|
|
// And attatch the element to the DOM tree
|
|
|
|
this.attachToDOM();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the parent node.
|
|
|
|
*/
|
|
|
|
getParentDOMNode: function() {
|
|
|
|
return this.parentNode;
|
|
|
|
},
|
|
|
|
|
2011-09-05 16:35:28 +02:00
|
|
|
/**
|
|
|
|
* Returns the index of this element in the DOM tree
|
|
|
|
*/
|
|
|
|
getDOMIndex: function() {
|
|
|
|
if (this._parent)
|
|
|
|
{
|
|
|
|
var idx = 0;
|
|
|
|
var children = this._parent.getChildren();
|
|
|
|
|
2014-12-08 21:38:48 +01:00
|
|
|
if(children && children.indexOf) return children.indexOf(this);
|
|
|
|
|
|
|
|
egw.debug('warn', 'No Array.indexOf(), falling back to looping. ');
|
2011-09-05 16:35:28 +02:00
|
|
|
for (var i = 0; i < children.length; i++)
|
|
|
|
{
|
|
|
|
if (children[i] == this)
|
|
|
|
{
|
|
|
|
return idx;
|
|
|
|
}
|
|
|
|
else if (children[i].isInTree())
|
|
|
|
{
|
|
|
|
idx++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
},
|
|
|
|
|
2011-08-11 15:53:35 +02:00
|
|
|
/**
|
|
|
|
* Sets the id of the DOM-Node.
|
2013-10-30 10:43:12 +01:00
|
|
|
*
|
2013-08-29 14:10:06 +02:00
|
|
|
* DOM id's have dots "." replaced with dashes "-"
|
2014-01-29 18:45:24 +01:00
|
|
|
*
|
|
|
|
* @param {string} _value id to set
|
2011-08-11 15:53:35 +02:00
|
|
|
*/
|
|
|
|
set_id: function(_value) {
|
|
|
|
|
|
|
|
this.id = _value;
|
2013-08-29 14:10:06 +02:00
|
|
|
this.dom_id = _value ? this.getInstanceManager().uniqueId+'_'+_value.replace(/\./g, '-') : _value;
|
2011-08-11 15:53:35 +02:00
|
|
|
|
|
|
|
var node = this.getDOMNode(this);
|
|
|
|
if (node)
|
|
|
|
{
|
|
|
|
if (_value != "")
|
|
|
|
{
|
2013-08-23 16:10:37 +02:00
|
|
|
node.setAttribute("id", this.dom_id);
|
2011-08-11 15:53:35 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
node.removeAttribute("id");
|
|
|
|
}
|
|
|
|
}
|
2011-08-12 17:26:08 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
set_disabled: function(_value) {
|
2013-06-13 01:14:09 +02:00
|
|
|
var node = this._surroundingsMgr != null ? this._surroundingsMgr.getDOMNode(this.getDOMNode(this)) : this.getDOMNode(this);
|
2012-03-26 16:08:57 +02:00
|
|
|
if (node && this.disabled != _value)
|
2011-08-12 17:26:08 +02:00
|
|
|
{
|
2011-08-17 19:48:39 +02:00
|
|
|
this.disabled = _value;
|
2011-08-12 17:26:08 +02:00
|
|
|
|
|
|
|
if (_value)
|
|
|
|
{
|
2016-06-02 16:51:15 +02:00
|
|
|
jQuery(node).hide();
|
2011-08-12 17:26:08 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-06-02 16:51:15 +02:00
|
|
|
jQuery(node).show();
|
2011-08-12 17:26:08 +02:00
|
|
|
}
|
|
|
|
}
|
2011-08-19 18:00:44 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
set_width: function(_value) {
|
|
|
|
this.width = _value;
|
2011-08-11 15:53:35 +02:00
|
|
|
|
2011-08-19 18:00:44 +02:00
|
|
|
var node = this.getDOMNode(this);
|
|
|
|
if (node)
|
|
|
|
{
|
2016-06-02 16:51:15 +02:00
|
|
|
jQuery(node).css("width", _value);
|
2011-08-19 18:00:44 +02:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
set_height: function(_value) {
|
|
|
|
this.height = _value;
|
|
|
|
|
|
|
|
var node = this.getDOMNode(this);
|
|
|
|
if (node)
|
|
|
|
{
|
2016-06-02 16:51:15 +02:00
|
|
|
jQuery(node).css("height", _value);
|
2011-08-19 18:00:44 +02:00
|
|
|
}
|
2011-08-22 13:16:37 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
set_class: function(_value) {
|
|
|
|
var node = this.getDOMNode(this);
|
|
|
|
if (node)
|
|
|
|
{
|
|
|
|
if (this["class"])
|
|
|
|
{
|
2016-06-02 16:51:15 +02:00
|
|
|
jQuery(node).removeClass(this["class"]);
|
2011-08-22 13:16:37 +02:00
|
|
|
}
|
2016-06-02 16:51:15 +02:00
|
|
|
jQuery(node).addClass(_value);
|
2011-08-22 13:16:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
this["class"] = _value;
|
2011-08-22 18:37:04 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
set_overflow: function(_value) {
|
|
|
|
this.overflow = _value;
|
|
|
|
|
|
|
|
var node = this.getDOMNode(this);
|
|
|
|
if (node)
|
|
|
|
{
|
2016-06-02 16:51:15 +02:00
|
|
|
jQuery(node).css("overflow", _value);
|
2011-08-22 18:37:04 +02:00
|
|
|
}
|
2013-03-26 22:19:17 +01:00
|
|
|
},
|
|
|
|
|
2015-01-21 19:59:12 +01:00
|
|
|
set_data: function(_value)
|
|
|
|
{
|
|
|
|
var node = this.getDOMNode(this);
|
|
|
|
if (node && _value)
|
|
|
|
{
|
|
|
|
var pairs = _value.split(/,/g);
|
|
|
|
for(var i=0; i < pairs.length; ++i)
|
|
|
|
{
|
|
|
|
var name_value = pairs[i].split(':');
|
2016-06-02 16:51:15 +02:00
|
|
|
jQuery(node).attr('data-'+name_value[0], name_value[1]);
|
2015-01-21 19:59:12 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
2016-02-29 21:40:43 +01:00
|
|
|
|
2015-10-13 17:03:41 +02:00
|
|
|
set_background: function(_value)
|
|
|
|
{
|
|
|
|
var node = this.getDOMNode(this);
|
|
|
|
var values = '';
|
|
|
|
if (_value && node)
|
|
|
|
{
|
|
|
|
values = _value.split(',');
|
|
|
|
jQuery(node).css({
|
|
|
|
"background-image":'url("'+values[0]+'")',
|
|
|
|
"background-position-x":values[1],
|
|
|
|
"background-position-y":values[2],
|
|
|
|
"background-scale":values[3]
|
|
|
|
});
|
|
|
|
}
|
|
|
|
},
|
2016-02-29 21:40:43 +01:00
|
|
|
|
2013-03-26 22:19:17 +01:00
|
|
|
/**
|
2013-04-20 21:20:51 +02:00
|
|
|
* Set Actions on the widget
|
2013-03-26 22:19:17 +01:00
|
|
|
*
|
2013-04-20 21:20:51 +02:00
|
|
|
* Each action is defined as an object:
|
|
|
|
*
|
|
|
|
* move: {
|
|
|
|
* type: "drop",
|
|
|
|
* acceptedTypes: "mail",
|
|
|
|
* icon: "move",
|
|
|
|
* caption: "Move to"
|
|
|
|
* onExecute: javascript:mail_move"
|
|
|
|
* }
|
|
|
|
*
|
|
|
|
* This will turn the widget into a drop target for "mail" drag types. 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. The
|
2013-03-26 22:19:17 +01:00
|
|
|
* etemplate2 widget involved can typically be found in action.parent.data.widget, so your handler
|
|
|
|
* can operate in the widget context easily. The location varies depending on your action though. It
|
|
|
|
* might be action.parent.parent.data.widget
|
|
|
|
*
|
|
|
|
* To customise how the actions are handled for a particular widget, override _link_actions(). It handles
|
|
|
|
* the more widget-specific parts.
|
2013-04-20 21:20:51 +02:00
|
|
|
*
|
2014-01-29 18:45:24 +01:00
|
|
|
* @param {object} actions {ID: {attributes..}+} map of egw action information
|
2016-03-19 17:16:59 +01:00
|
|
|
* @see api/src/Etemplate/Widget/Nextmatch.php egw_actions() method
|
2013-04-20 21:20:51 +02:00
|
|
|
*/
|
|
|
|
set_actions: function(actions)
|
2013-03-26 22:19:17 +01:00
|
|
|
{
|
|
|
|
if(this.id == "" || typeof this.id == "undefined")
|
|
|
|
{
|
|
|
|
this.egw().debug("warn", "Widget should have an ID if you want actions",this);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Initialize the action manager and add some actions to it
|
2014-01-18 12:21:53 +01:00
|
|
|
// Only look 1 level deep
|
|
|
|
var gam = egw_getActionManager(this.egw().appName,true,1);
|
2013-05-21 22:24:40 +02:00
|
|
|
if(typeof this._actionManager != "object")
|
|
|
|
{
|
2015-08-05 23:24:07 +02:00
|
|
|
if(gam.getActionById(this.getInstanceManager().uniqueId,1) !== null)
|
2013-05-21 22:24:40 +02:00
|
|
|
{
|
2015-08-05 23:24:07 +02:00
|
|
|
gam = gam.getActionById(this.getInstanceManager().uniqueId,1);
|
|
|
|
}
|
|
|
|
if(gam.getActionById(this.id,1) != null)
|
|
|
|
{
|
|
|
|
this._actionManager = gam.getActionById(this.id,1);
|
2013-05-21 22:24:40 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this._actionManager = gam.addAction("actionManager", this.id);
|
|
|
|
}
|
|
|
|
}
|
2013-07-20 15:45:22 +02:00
|
|
|
this._actionManager.updateActions(actions);
|
2014-03-06 19:35:57 +01:00
|
|
|
if (this.options.default_execute) this._actionManager.setDefaultExecute(this.options.default_execute);
|
2013-03-26 22:19:17 +01:00
|
|
|
|
|
|
|
// 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
|
2013-07-20 15:45:22 +02:00
|
|
|
this._link_actions(actions);
|
|
|
|
},
|
2013-10-30 10:43:12 +01:00
|
|
|
|
2014-03-06 19:35:57 +01:00
|
|
|
set_default_execute: function(_default_execute)
|
|
|
|
{
|
|
|
|
this.options.default_execute = _default_execute;
|
|
|
|
|
|
|
|
if (this._actionManager) this._actionManager.setDefaultExecute(null, _default_execute);
|
|
|
|
},
|
|
|
|
|
2013-07-20 15:45:22 +02:00
|
|
|
/**
|
|
|
|
* Get all action-links / id's of 1.-level actions from a given action object
|
2013-10-30 10:43:12 +01:00
|
|
|
*
|
2013-07-20 15:45:22 +02:00
|
|
|
* This can be overwritten to not allow all actions, by not returning them here.
|
2013-10-30 10:43:12 +01:00
|
|
|
*
|
2013-07-20 15:45:22 +02:00
|
|
|
* @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;
|
2013-03-26 22:19:17 +01:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Link the actions to the DOM nodes / widget bits.
|
|
|
|
*
|
2014-01-29 18:45:24 +01:00
|
|
|
* @param {object} actions {ID: {attributes..}+} map of egw action information
|
2013-03-26 22:19:17 +01:00
|
|
|
*/
|
2013-07-20 15:45:22 +02:00
|
|
|
_link_actions: function(actions)
|
2013-03-26 22:19:17 +01:00
|
|
|
{
|
|
|
|
// Get the top level element for the tree
|
|
|
|
var objectManager = egw_getAppObjectManager(true);
|
|
|
|
var widget_object = objectManager.getObjectById(this.id);
|
|
|
|
if (widget_object == null) {
|
|
|
|
// Add a new container to the object manager which will hold the widget
|
|
|
|
// objects
|
2013-05-21 22:24:40 +02:00
|
|
|
widget_object = objectManager.insertObject(false, new egwActionObject(
|
|
|
|
this.id, objectManager, new et2_action_object_impl(this),
|
2015-08-11 17:37:20 +02:00
|
|
|
this._actionManager || objectManager.manager.getActionById(this.id) || objectManager.manager
|
2013-05-21 22:24:40 +02:00
|
|
|
));
|
2013-03-26 22:19:17 +01:00
|
|
|
}
|
2015-02-10 20:34:46 +01:00
|
|
|
else
|
|
|
|
{
|
|
|
|
widget_object.setAOI(new et2_action_object_impl(this, this.getDOMNode()));
|
|
|
|
}
|
2013-03-26 22:19:17 +01:00
|
|
|
|
|
|
|
// Delete all old objects
|
|
|
|
widget_object.clear();
|
2015-02-10 20:34:46 +01:00
|
|
|
widget_object.unregisterActions();
|
2013-03-26 22:19:17 +01:00
|
|
|
|
|
|
|
// Go over the widget & add links - this is where we decide which actions are
|
|
|
|
// 'allowed' for this widget at this time
|
2013-07-20 15:45:22 +02:00
|
|
|
var action_links = this._get_action_links(actions);
|
2013-03-26 22:19:17 +01:00
|
|
|
widget_object.updateActionLinks(action_links);
|
2016-02-29 21:40:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
});}).call(this);
|
2011-08-11 15:53:35 +02:00
|
|
|
|
2011-08-23 16:59:49 +02:00
|
|
|
/**
|
|
|
|
* The surroundings manager class allows to append or prepend elements around
|
|
|
|
* an widget node.
|
2013-10-30 10:43:12 +01:00
|
|
|
*
|
2013-04-13 21:00:13 +02:00
|
|
|
* @augments Class
|
2011-08-23 16:59:49 +02:00
|
|
|
*/
|
2016-02-29 21:40:43 +01:00
|
|
|
var et2_surroundingsMgr = (function(){ "use strict"; return ClassWithAttributes.extend(
|
2013-04-13 21:00:13 +02:00
|
|
|
{
|
|
|
|
/**
|
|
|
|
* Constructor
|
2013-10-30 10:43:12 +01:00
|
|
|
*
|
2013-04-13 21:00:13 +02:00
|
|
|
* @memberOf et2_surroundingsMgr
|
|
|
|
* @param _widget
|
|
|
|
*/
|
2011-08-23 16:59:49 +02:00
|
|
|
init: function(_widget) {
|
|
|
|
this.widget = _widget;
|
|
|
|
|
|
|
|
this._widgetContainer = null;
|
|
|
|
this._widgetSurroundings = [];
|
|
|
|
this._widgetPlaceholder = null;
|
|
|
|
this._widgetNode = null;
|
|
|
|
this._ownPlaceholder = true;
|
|
|
|
},
|
|
|
|
|
|
|
|
destroy: function() {
|
|
|
|
this._widgetContainer = null;
|
|
|
|
this._widgetSurroundings = null;
|
|
|
|
this._widgetPlaceholder = null;
|
|
|
|
this._widgetNode = null;
|
|
|
|
},
|
|
|
|
|
|
|
|
prependDOMNode: function(_node) {
|
|
|
|
this._widgetSurroundings.unshift(_node);
|
|
|
|
this._surroundingsUpdated = true;
|
|
|
|
},
|
|
|
|
|
|
|
|
appendDOMNode: function(_node) {
|
|
|
|
// Append an placeholder first if none is existing yet
|
|
|
|
if (this._ownPlaceholder && this._widgetPlaceholder == null)
|
|
|
|
{
|
|
|
|
this._widgetPlaceholder = document.createElement("span");
|
|
|
|
this._widgetSurroundings.push(this._widgetPlaceholder);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Append the given node
|
|
|
|
this._widgetSurroundings.push(_node);
|
|
|
|
this._surroundingsUpdated = true;
|
|
|
|
},
|
|
|
|
|
|
|
|
insertDOMNode: function(_node) {
|
|
|
|
if (!this._ownPlaceholder || this._widgetPlaceholder == null)
|
|
|
|
{
|
|
|
|
this.appendDOMNode(_node);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the index of the widget placeholder and delete it, insert the
|
|
|
|
// given node instead
|
|
|
|
var idx = this._widgetSurroundings.indexOf(this._widgetPlaceholder);
|
|
|
|
this._widgetSurroundings.splice(idx, 1, _node);
|
|
|
|
|
|
|
|
// Delete the reference to the own placeholder
|
|
|
|
this._widgetPlaceholder = null;
|
|
|
|
this._ownPlaceholder = false;
|
|
|
|
},
|
|
|
|
|
|
|
|
removeDOMNode: function(_node) {
|
2013-10-30 10:43:12 +01:00
|
|
|
for (var i = 0; this._widgetSurroundings && i < this._widgetSurroundings.length; i++)
|
2011-08-23 16:59:49 +02:00
|
|
|
{
|
|
|
|
if (this._widgetSurroundings[i] == _node)
|
|
|
|
{
|
|
|
|
this._widgetSurroundings.splice(i, 1);
|
|
|
|
this._surroundingsUpdated = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
setWidgetPlaceholder: function(_node) {
|
|
|
|
if (_node != this._widgetPlaceholder)
|
|
|
|
{
|
|
|
|
if (_node != null && this._ownPlaceholder && this._widgetPlaceholder != null)
|
|
|
|
{
|
|
|
|
// Delete the current placeholder which was created by the
|
|
|
|
// widget itself
|
|
|
|
var idx = this._widgetSurroundings.indexOf(this._widgetPlaceholder);
|
|
|
|
this._widgetSurroundings.splice(idx, 1);
|
|
|
|
|
|
|
|
// Delete any reference to the own placeholder and set the
|
|
|
|
// _ownPlaceholder flag to false
|
|
|
|
this._widgetPlaceholder = null;
|
|
|
|
this._ownPlaceholder = false;
|
|
|
|
}
|
2013-10-30 10:43:12 +01:00
|
|
|
|
2011-08-23 16:59:49 +02:00
|
|
|
this._ownPlaceholder = (_node == null);
|
|
|
|
this._widgetPlaceholder = _node;
|
|
|
|
this._surroundingsUpdated = true;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
_rebuildContainer: function() {
|
|
|
|
// Return if there has been no change in the "surroundings-data"
|
|
|
|
if (!this._surroundingsUpdated)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Build the widget container
|
|
|
|
if (this._widgetSurroundings.length > 0)
|
|
|
|
{
|
|
|
|
// Check whether the widgetPlaceholder is really inside the DOM-Tree
|
|
|
|
var hasPlaceholder = et2_hasChild(this._widgetSurroundings,
|
|
|
|
this._widgetPlaceholder);
|
|
|
|
|
|
|
|
// If not, append another widget placeholder
|
|
|
|
if (!hasPlaceholder)
|
|
|
|
{
|
|
|
|
this._widgetPlaceholder = document.createElement("span");
|
|
|
|
this._widgetSurroundings.push(this._widgetPlaceholder);
|
|
|
|
|
|
|
|
this._ownPlaceholder = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the surroundings array only contains one element, set this one
|
|
|
|
// as the widget container
|
|
|
|
if (this._widgetSurroundings.length == 1)
|
|
|
|
{
|
|
|
|
if (this._widgetSurroundings[0] == this._widgetPlaceholder)
|
|
|
|
{
|
|
|
|
this._widgetContainer = null;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this._widgetContainer = this._widgetSurroundings[0];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Create an outer "span" as widgetContainer
|
|
|
|
this._widgetContainer = document.createElement("span");
|
|
|
|
|
|
|
|
// Append the children inside the widgetSurroundings array to
|
|
|
|
// the widget container
|
|
|
|
for (var i = 0; i < this._widgetSurroundings.length; i++)
|
|
|
|
{
|
|
|
|
this._widgetContainer.appendChild(this._widgetSurroundings[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this._widgetContainer = null;
|
|
|
|
this._widgetPlaceholder = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
this._surroundingsUpdated = false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
},
|
|
|
|
|
|
|
|
update: function() {
|
|
|
|
if (this._surroundingsUpdated)
|
|
|
|
{
|
|
|
|
var attached = this.widget ? this.widget.isAttached() : false;
|
|
|
|
|
|
|
|
// Reattach the widget - this will call the "getDOMNode" function
|
|
|
|
// and trigger the _rebuildContainer function.
|
|
|
|
if (attached && this.widget)
|
|
|
|
{
|
2013-05-28 01:24:22 +02:00
|
|
|
this.widget.detachFromDOM();
|
2011-08-23 16:59:49 +02:00
|
|
|
this.widget.attachToDOM();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
getDOMNode: function(_widgetNode) {
|
|
|
|
// Update the whole widgetContainer if this is not the first time this
|
|
|
|
// function has been called but the widget node has changed.
|
|
|
|
if (this._widgetNode != null && this._widgetNode != _widgetNode)
|
|
|
|
{
|
|
|
|
this._surroundingsUpdated = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Copy a reference to the given node
|
|
|
|
this._widgetNode = _widgetNode;
|
|
|
|
|
|
|
|
// Build the container if it didn't exist yet.
|
2011-10-12 18:27:50 +02:00
|
|
|
var updated = this._rebuildContainer();
|
2011-08-23 16:59:49 +02:00
|
|
|
|
|
|
|
// Return the widget node itself if there are no surroundings arround
|
|
|
|
// it
|
|
|
|
if (this._widgetContainer == null)
|
|
|
|
{
|
|
|
|
return _widgetNode;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Replace the widgetPlaceholder with the given widget node if the
|
|
|
|
// widgetContainer has been updated
|
|
|
|
if (updated)
|
|
|
|
{
|
|
|
|
this._widgetPlaceholder.parentNode.replaceChild(_widgetNode,
|
|
|
|
this._widgetPlaceholder);
|
|
|
|
if (!this._ownPlaceholder)
|
|
|
|
{
|
|
|
|
this._widgetPlaceholder = _widgetNode;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Return the widget container
|
|
|
|
return this._widgetContainer;
|
|
|
|
}
|
|
|
|
|
2016-02-29 21:40:43 +01:00
|
|
|
});}).call(this);
|
2011-08-23 16:59:49 +02:00
|
|
|
|
2013-03-26 22:19:17 +01:00
|
|
|
/**
|
|
|
|
* The egw_action system requires an egwActionObjectInterface Interface implementation
|
|
|
|
* to tie actions to DOM nodes. This one can be used by any widget.
|
|
|
|
*
|
|
|
|
* The class extension is different than the widgets
|
|
|
|
*
|
2014-01-29 18:45:24 +01:00
|
|
|
* @param {et2_DOMWidget} widget
|
2014-03-06 19:35:57 +01:00
|
|
|
* @param {Object} node
|
|
|
|
*
|
2013-03-26 22:19:17 +01:00
|
|
|
*/
|
2014-02-18 14:59:45 +01:00
|
|
|
function et2_action_object_impl(widget, node)
|
2013-03-26 22:19:17 +01:00
|
|
|
{
|
|
|
|
var aoi = new egwActionObjectInterface();
|
2014-02-18 14:59:45 +01:00
|
|
|
var objectNode = node;
|
|
|
|
|
2015-06-10 23:45:06 +02:00
|
|
|
aoi.getWidget = function() {
|
|
|
|
return widget;
|
|
|
|
};
|
2016-02-29 21:40:43 +01:00
|
|
|
|
2013-03-26 22:19:17 +01:00
|
|
|
aoi.doGetDOMNode = function() {
|
2014-02-18 14:59:45 +01:00
|
|
|
return objectNode?objectNode:widget.getDOMNode();
|
2013-03-26 22:19:17 +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.
|
|
|
|
aoi.doSetState = function(_state, _outerCall) {
|
|
|
|
};
|
|
|
|
|
|
|
|
// 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
|
|
|
|
aoi.doTriggerEvent = function(_event, _data) {
|
|
|
|
switch(_event)
|
|
|
|
{
|
|
|
|
case EGW_AI_DRAG_OVER:
|
2016-06-02 16:51:15 +02:00
|
|
|
jQuery(this.node).addClass("ui-state-active");
|
2013-03-26 22:19:17 +01:00
|
|
|
break;
|
|
|
|
case EGW_AI_DRAG_OUT:
|
2016-06-02 16:51:15 +02:00
|
|
|
jQuery(this.node).removeClass("ui-state-active");
|
2013-03-26 22:19:17 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
};
|
2014-03-06 19:35:57 +01:00
|
|
|
|
2011-08-11 15:53:35 +02:00
|
|
|
|
2013-03-26 22:19:17 +01:00
|
|
|
return aoi;
|
|
|
|
};
|