mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-12-26 08:39:07 +01:00
Backup of current development stage
This commit is contained in:
parent
398185f525
commit
e416c61890
@ -332,6 +332,22 @@ egwActionLink.prototype.set_actionId = function(_value)
|
|||||||
|
|
||||||
/** egwActionObject Object **/
|
/** egwActionObject Object **/
|
||||||
|
|
||||||
|
//State bitmask (only use powers of two for new states!)
|
||||||
|
const EGW_AO_STATE_NORMAL = 0x00;
|
||||||
|
const EGW_AO_STATE_SELECTED = 0x01;
|
||||||
|
const EGW_AO_STATE_FOCUSED = 0x02;
|
||||||
|
|
||||||
|
const EGW_AO_EVENT_DRAG_OVER_ENTER = 0x00;
|
||||||
|
const EGW_AO_EVENT_DRAG_OVER_LEAVE = 0x01;
|
||||||
|
|
||||||
|
const EGW_AO_SHIFT_STATE_NONE = 0x00;
|
||||||
|
const EGW_AO_SHIFT_STATE_MULTI = 0x01;
|
||||||
|
const EGW_AO_SHIFT_STATE_LIST = 0x02;
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
const EGW_AO_FLAG_IS_CONTAINER = 0x01;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The egwActionObject represents an abstract object to which actions may be
|
* The egwActionObject represents an abstract object to which actions may be
|
||||||
* applied. Communication with the DOM tree is established by using the
|
* applied. Communication with the DOM tree is established by using the
|
||||||
@ -341,17 +357,280 @@ egwActionLink.prototype.set_actionId = function(_value)
|
|||||||
* @param string _id is the identifier of the object which
|
* @param string _id is the identifier of the object which
|
||||||
* @param object _parent is the parent object in the hirachy. This may be set to NULL
|
* @param object _parent is the parent object in the hirachy. This may be set to NULL
|
||||||
* @param object _manager is the action manager this object is connected to
|
* @param object _manager is the action manager this object is connected to
|
||||||
* @param object _interaction is the egwActionObjectInterface which connects
|
* @param object _iface is the egwActionObjectInterface which connects
|
||||||
* this object to the DOM tree.
|
* this object to the DOM tree.
|
||||||
|
* @param boolean _flags a set of additional flags being applied to the object
|
||||||
*/
|
*/
|
||||||
function egwActionObject(_id, _parent, _manager, _interaction)
|
function egwActionObject(_id, _parent, _manager, _iface, _flagss)
|
||||||
{
|
{
|
||||||
this.id = _id;
|
this.id = _id;
|
||||||
this.parent = _parent;
|
this.parent = _parent;
|
||||||
this.interaction = _interaction;
|
|
||||||
this.children = [];
|
this.children = [];
|
||||||
this.actionLinks = [];
|
this.actionLinks = [];
|
||||||
this.manager = _manager;
|
this.manager = _manager;
|
||||||
|
this.selectBehaviour = _selectBehaviour;
|
||||||
|
|
||||||
|
this.iface = _iface;
|
||||||
|
this.iface.setStateChangeCallback(this._ifaceCallback, this)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a list which contains all items of the element tree.
|
||||||
|
*
|
||||||
|
* @param object _obj is used internally to pass references to the array inside
|
||||||
|
* the object.
|
||||||
|
*/
|
||||||
|
egwActionObject.prototype.flatList = function(_obj)
|
||||||
|
{
|
||||||
|
if (typeof(_obj) == "undefined")
|
||||||
|
{
|
||||||
|
_obj = {
|
||||||
|
"elements": [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_obj.elements.push(this);
|
||||||
|
|
||||||
|
for (var i = 0; i < this.children.length; i++)
|
||||||
|
{
|
||||||
|
this.children[i].flatList(_obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
return _obj.elements;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
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();
|
||||||
|
var thisId = contRoot.indexOf(this);
|
||||||
|
var toId = contRoot.indexOf(_to);
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
return this.slice(from, to + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the deepest object which is currently focused. Objects with the
|
||||||
|
* "container"-flag will not be returned.
|
||||||
|
*/
|
||||||
|
egwActionObject.prototype.getFocusedObject = function()
|
||||||
|
{
|
||||||
|
//Search for the focused object in the children
|
||||||
|
for (var i = 0; i < this.children.length; i++)
|
||||||
|
{
|
||||||
|
var obj = this.children[i].getFocused()
|
||||||
|
if (obj)
|
||||||
|
{
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//One of the child objects hasn't been focused, probably this object is
|
||||||
|
if (!egwBitIsSet(this.flags, EGW_AO_FLAG_IS_CONTAINER) && this.getFocused())
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
egwActionObject.prototype._ifaceCallback = function(_newState, _shiftState)
|
||||||
|
{
|
||||||
|
// Remove the focus from all children on the same level
|
||||||
|
if (this.parent)
|
||||||
|
{
|
||||||
|
var selected = egwBitIsSet(_newState, EGW_AO_STATE_SELECTED);
|
||||||
|
|
||||||
|
if (selected)
|
||||||
|
{
|
||||||
|
// Search the index of this object
|
||||||
|
var id = this.parent.children.indexOf(this);
|
||||||
|
var objs = [];
|
||||||
|
|
||||||
|
// Deselect all other objects inside this container, if the "MULTI" shift-
|
||||||
|
// state is not set
|
||||||
|
if (!egwBitIsSet(_shiftState, EGW_AO_SHIFT_STATE_MULTI))
|
||||||
|
{
|
||||||
|
var lst = this.getContainerRoot().flatList();
|
||||||
|
for (var i = 0; i < lst.length; i++)
|
||||||
|
{
|
||||||
|
if (lst[i] != this)
|
||||||
|
{
|
||||||
|
lst[i].setSelected(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the LIST state is active, get all objects inbetween this one and the focused one
|
||||||
|
// and set their select state.
|
||||||
|
if (egwBitIsSet(_shiftState, EGW_AO_SHIFT_STATE_LIST))
|
||||||
|
{
|
||||||
|
var focused = this.getRootObject().getFocusedObject();
|
||||||
|
if (focused)
|
||||||
|
{
|
||||||
|
objs = this.traversePath(focused);
|
||||||
|
for (var i = 0; i < objs.length; i++)
|
||||||
|
{
|
||||||
|
objs[i].setSelected(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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_LIST))
|
||||||
|
{
|
||||||
|
this.getRootObject().setFocused(false);
|
||||||
|
this.setFocused(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
egwActionObject.prototype.getSelected = function()
|
||||||
|
{
|
||||||
|
return egwBitIsSet(this.getState(), EGW_AO_STATE_SELECTED);
|
||||||
|
}
|
||||||
|
|
||||||
|
egwActionObject.prototype.getFocused = function()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
egwActionObject.prototype.getState = function()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
egwActionObject.prototype.setSelected = function(_selected, _applyToSelf,
|
||||||
|
_applyToChildren, _applyToParent)
|
||||||
|
{
|
||||||
|
if (typeof _applyToSelf == "undefined")
|
||||||
|
_applyToSelf = true;
|
||||||
|
if (typeof _applyToChildren == "undefined")
|
||||||
|
_applyToChildren = true;
|
||||||
|
if (typeof _applyToParent == "undefined")
|
||||||
|
_applyToParent = false;
|
||||||
|
|
||||||
|
if (_applyToSelf)
|
||||||
|
{
|
||||||
|
var state = this.iface.getState();
|
||||||
|
|
||||||
|
if (_selected)
|
||||||
|
{
|
||||||
|
state &= ~EGW_AO_STATE_SELECTED;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
state |= EGW_AO_STATE_SELECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.iface.setState(state, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_applyToChildren)
|
||||||
|
{
|
||||||
|
for (var i = 0; i < this.children.length; i++)
|
||||||
|
{
|
||||||
|
this.children[i].setFocused(true, true, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_applyToParent)
|
||||||
|
{
|
||||||
|
for (var i = 0; i < this.children.length; i++)
|
||||||
|
{
|
||||||
|
this.children[i].setFocused(true, false, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
egwActionObject.prototype.setFocused = function(_focused, _applyToSelf,
|
||||||
|
_applyToChildren, _applyToParent)
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -462,8 +741,8 @@ egwActionObject.prototype.getActionImplementationGroups = function(_test, _group
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Recursively add the actions of the children to the result (as _groups is)
|
// Recursively add the actions of the children to the result (as _groups is
|
||||||
// a object, only the reference is passed.
|
// an object, only the reference is passed).
|
||||||
for (var i = 0; i < this.children.length; i++)
|
for (var i = 0; i < this.children.length; i++)
|
||||||
{
|
{
|
||||||
this.children[i].getActionImplementationGroups(_test, _groups);
|
this.children[i].getActionImplementationGroups(_test, _groups);
|
||||||
@ -472,3 +751,102 @@ egwActionObject.prototype.getActionImplementationGroups = function(_test, _group
|
|||||||
return _groups;
|
return _groups;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** egwActionObjectInterface Interface **/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The egwActionObjectInterface has to be implemented for each actual object in
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
function egwActionObjectInterface()
|
||||||
|
{
|
||||||
|
//Preset the interface functions
|
||||||
|
|
||||||
|
this.doGetDOMNode = function() {return null};
|
||||||
|
|
||||||
|
// _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) {};
|
||||||
|
|
||||||
|
this.doTriggerEvent = function(_event) {};
|
||||||
|
|
||||||
|
this._state = EGW_AO_STATE_NORMAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the callback function which will be called when a user interaction changes
|
||||||
|
* state of the object.
|
||||||
|
*/
|
||||||
|
egwActionObjectInterface.prototype.setStateChangeCallback(_callback, _context)
|
||||||
|
{
|
||||||
|
this.stateChangeCallback = _callback;
|
||||||
|
this.stateChangeContext = _context;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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)
|
||||||
|
*
|
||||||
|
* @param boolean _selected Whether the object is selected or not.
|
||||||
|
*/
|
||||||
|
egwActionObjectInterface.prototype._selectChange(_selected)
|
||||||
|
{
|
||||||
|
// Check whether the selected bit has actually changed - the callback may
|
||||||
|
// perform expensive operations, and we don't want those to happen without
|
||||||
|
// a reason.
|
||||||
|
if (egwBitIsSet(this._state, EGW_AO_STATE_SELECTED) != _selected)
|
||||||
|
{
|
||||||
|
//Set the EGW_AO_STATE_SELECTED bit accordingly and call the callback
|
||||||
|
this._state = egwBitSet(this._state, EGW_AO_STATE_SELECTED, _selected);
|
||||||
|
if (this.stateChangeCallback)
|
||||||
|
{
|
||||||
|
this.stateChangeCallback.call(this.stateChangeContext, this._state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
this.doSetState(_state, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current state of the object. The state is maintained by the
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -37,3 +37,27 @@ function egwActionStoreJSON(_data, _obj, _setterOnly)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Switches the given bit in the set on or off.
|
||||||
|
*
|
||||||
|
* @param int _set is the current set
|
||||||
|
* @param int _bit is the position of the bit which should be switched on/off
|
||||||
|
* @param boolean _state is whether the bit should be switched on or off
|
||||||
|
* @returns the new set
|
||||||
|
*/
|
||||||
|
function egwSetBit(_set, _bit, _state)
|
||||||
|
{
|
||||||
|
if (_state)
|
||||||
|
return _set |= _bit;
|
||||||
|
else
|
||||||
|
return _set &= ~_bit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the given bit is set in the set.
|
||||||
|
*/
|
||||||
|
function egwBitIsSet(_set, _bit)
|
||||||
|
{
|
||||||
|
return (_set & _bit) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user