mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-11-23 00:13:35 +01:00
Fixed correct expanding of names and implemented the dataProvider class
This commit is contained in:
parent
e151398d94
commit
87c0db7be1
@ -61,14 +61,14 @@ var et2_arrayMgr = Class.extend({
|
||||
return this;
|
||||
},
|
||||
|
||||
getValueForID : function(_id) {
|
||||
/* getValueForID : function(_id) {
|
||||
if (typeof this.data[_id] != "undefined")
|
||||
{
|
||||
return this.data[_id];
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
},*/
|
||||
|
||||
/**
|
||||
* Returns the path to this content array manager perspective as an array
|
||||
@ -306,7 +306,6 @@ var et2_readonlysArrayMgr = et2_arrayMgr.extend({
|
||||
// If the attribute is set, return that
|
||||
if (typeof _attr != "undefined" && _attr !== null)
|
||||
{
|
||||
console.log(_attr, et2_evalBool(_attr));
|
||||
return et2_evalBool(_attr);
|
||||
}
|
||||
|
||||
|
@ -335,6 +335,32 @@ function et2_arrayValues(_arr)
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Equivalent to the PHP array_keys function
|
||||
*/
|
||||
function et2_arrayKeys(_arr)
|
||||
{
|
||||
var result = [];
|
||||
for (var key in _arr)
|
||||
{
|
||||
result.push(key);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function et2_arrayIntKeys(_arr)
|
||||
{
|
||||
var result = [];
|
||||
for (var key in _arr)
|
||||
{
|
||||
result.push(parseInt(key));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Equivalent to the PHP substr function, partly take from phpjs, licensed under
|
||||
* the GPL.
|
||||
|
@ -80,7 +80,7 @@ var et2_inputWidget = et2_valueWidget.extend(et2_IInput, {
|
||||
// Check whether an validation error entry exists
|
||||
if (this.id)
|
||||
{
|
||||
var val = this.getArrayMgr("validation_errors").getValueForID(this.id);
|
||||
var val = this.getArrayMgr("validation_errors").getEntry(this.id);
|
||||
if (val)
|
||||
{
|
||||
_attrs["validation_error"] = val;
|
||||
|
@ -119,4 +119,3 @@ var et2_IDetachedDOM = new Interface({
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
@ -343,12 +343,14 @@
|
||||
}
|
||||
|
||||
var parts = [];
|
||||
var hasString = false;
|
||||
for (var i = 0; i < _string.length; i++)
|
||||
{
|
||||
var part = _string[i];
|
||||
|
||||
if (typeof part == "string")
|
||||
{
|
||||
hasString = true;
|
||||
// Escape all "'" and "\" chars and add the string to the parts array
|
||||
parts.push("'" + part.replace(/\\/g, "\\\\").replace(/'/g, "\\'") + "'");
|
||||
}
|
||||
@ -358,7 +360,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
if (parts.length == 0)
|
||||
if (!hasString) // Force the result to be of the type string
|
||||
{
|
||||
parts.push('""');
|
||||
}
|
||||
@ -433,6 +435,7 @@
|
||||
test("${row}[title]", "10[title]");
|
||||
test("{$row_cont[title]}", "Hello World!");
|
||||
test('{$cont["$row"][\'title\']}', "Hello World!");
|
||||
test("$row_cont[${row}[title]]");
|
||||
test("\\\\", "\\");
|
||||
test("", "");
|
||||
})();*/
|
||||
|
@ -41,7 +41,7 @@ var et2_valueWidget = et2_baseWidget.extend({
|
||||
// Set the value for this element
|
||||
var contentMgr = this.getArrayMgr("content");
|
||||
if (contentMgr != null) {
|
||||
var val = contentMgr.getValueForID(this.id);
|
||||
var val = contentMgr.getEntry(this.id);
|
||||
if (val !== null)
|
||||
{
|
||||
_attrs["value"] = val;
|
||||
|
@ -510,7 +510,12 @@ var et2_widget = Class.extend({
|
||||
// Apply the content of the modifications array
|
||||
if (this.id)
|
||||
{
|
||||
var data = this.getArrayMgr("modifications").getValueForID(this.id);
|
||||
if (typeof this.id != "string")
|
||||
{
|
||||
console.log(this.id);
|
||||
}
|
||||
|
||||
var data = this.getArrayMgr("modifications").getEntry(this.id);
|
||||
if (data instanceof Object)
|
||||
{
|
||||
for (var key in data)
|
||||
@ -769,7 +774,7 @@ var et2_widget = Class.extend({
|
||||
this._template_application = this.getParent().getTemplateApp();
|
||||
return this._template_application;
|
||||
}
|
||||
return null;
|
||||
return "phpgwapi";
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -33,3 +33,49 @@ var et2_dataview_IViewRange = new Interface({
|
||||
setViewRange: function(_range) {}
|
||||
|
||||
});
|
||||
|
||||
/**
|
||||
* Interface which objects have to implement, that want to act as low level
|
||||
* datasource.
|
||||
*/
|
||||
var et2_IRowFetcher = new Interface({
|
||||
|
||||
/**
|
||||
* @param _fetchList is an array consisting of objects whith the entries
|
||||
* "startIdx" and "count"
|
||||
* @param _callback is the callback which is called when the data is ready
|
||||
* (may be immediately or deferred). The callback has the following
|
||||
* signature:
|
||||
* function (_rows)
|
||||
* where _rows is an associative array which contains the data for that row.
|
||||
* @param _context is the context in which the callback should run.
|
||||
*/
|
||||
getRows: function(_fetchList, _callback, _context) {}
|
||||
|
||||
});
|
||||
|
||||
/**
|
||||
* Interface the data provider has to implement
|
||||
*/
|
||||
var et2_IDataProvider = new Interface({
|
||||
|
||||
/**
|
||||
* Returns the total count of grid elements
|
||||
*/
|
||||
getCount: function() {},
|
||||
|
||||
/**
|
||||
* Registers the given dataRow for the given index. Calls _dataRow.updateData
|
||||
* as soon as data is available for that row.
|
||||
*/
|
||||
registerDataRow: function(_dataRow, _idx) {},
|
||||
|
||||
/**
|
||||
* Stops calling _dataRow.updateData for the dataRow registered for the given
|
||||
* index.
|
||||
*/
|
||||
unregisterDataRow: function(_idx) {}
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
@ -13,49 +13,234 @@
|
||||
"use strict"
|
||||
|
||||
/*egw:uses
|
||||
et2_inheritance;
|
||||
et2_core_inheritance;
|
||||
et2_core_common;
|
||||
et2_dataview_interfaces;
|
||||
*/
|
||||
|
||||
var et2_dataview_dataProvider = Class.extend({
|
||||
var et2_dataview_dataProvider = Class.extend(et2_IDataProvider, {
|
||||
|
||||
init: function() {
|
||||
this.updateQueue = 0;
|
||||
/**
|
||||
* Creates this instance of the data provider.
|
||||
*/
|
||||
init: function(_source, _total) {
|
||||
this._source = _source;
|
||||
this._total = _total;
|
||||
|
||||
this._registeredRows = {};
|
||||
|
||||
this._data = {};
|
||||
this._dataCount = 0;
|
||||
|
||||
this._queue = {};
|
||||
this._queueSize = 0;
|
||||
|
||||
this._stepSize = 25; // Count of elements which is loaded at once
|
||||
this._maxCount = 1000; // Maximum count before the elements are cleaned up
|
||||
|
||||
var self = this;
|
||||
this._cleanupInterval = window.setInterval(function() {self._cleanup()},
|
||||
10 * 1000);
|
||||
this._queueFlushTimeout = null;
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
// Destroy the cleanup timer callback
|
||||
window.clearInterval(this._cleanupInterval);
|
||||
|
||||
// Destroy the _queueFlushTimeout
|
||||
if (this._queueFlushTimeout !== null)
|
||||
{
|
||||
window.clearTimeout(this._queueFlushTimeout);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the total count
|
||||
*/
|
||||
getCount: function() {
|
||||
return 10000;
|
||||
return this._total;
|
||||
},
|
||||
|
||||
registerDataRow: function(_dataRow, _idx) {
|
||||
/* var row = {
|
||||
"type": "dataRow",
|
||||
"data": {
|
||||
"ts_title": "Row " + _idx
|
||||
}
|
||||
};
|
||||
// Make sure _idx is a int
|
||||
_idx = parseInt(_idx);
|
||||
|
||||
// Get a random value which is used to simulate network latency and time
|
||||
// it needs to load the data.
|
||||
var rnd = Math.round(Math.random() * 1000);
|
||||
et2_debug("log", "--> registering row", _idx);
|
||||
|
||||
if (rnd < 200)
|
||||
if (typeof this._registeredRows[_idx] != "undefined")
|
||||
{
|
||||
_dataRow.updateData(row);
|
||||
et2_debug("warn", "Overriding data row for index " + _idx);
|
||||
}
|
||||
|
||||
window.setTimeout(function() {_dataRow.updateData(row); },
|
||||
Math.round(rnd / 2));*/
|
||||
// Associate the given data row with that index
|
||||
this._registeredRows[_idx] = _dataRow;
|
||||
|
||||
|
||||
// All data rows are updated independently of all others - this allows
|
||||
// user input between generation of the widgets.
|
||||
//window.setTimeout(function() {_dataRow.updateData({"readonlys": {"__ALL__": true}});}, 0);
|
||||
_dataRow.updateData({"content": {"ts_title": "Idx: " + _idx}});
|
||||
// Check whether an entry exists in the data array - if yes, call the
|
||||
// request immediately
|
||||
if (typeof this._data[_idx] != "undefined")
|
||||
{
|
||||
this._callUpdateData(_idx);
|
||||
}
|
||||
else
|
||||
{
|
||||
this._queueIndex(_idx);
|
||||
}
|
||||
},
|
||||
|
||||
unregisterDataRow: function(_dataRow) {
|
||||
//
|
||||
unregisterDataRow: function(_idx) {
|
||||
// Make sure _idx is a int
|
||||
_idx = parseInt(_idx);
|
||||
|
||||
et2_debug("log", "<-- unregistering row", _idx);
|
||||
|
||||
delete(this._data[_idx]);
|
||||
},
|
||||
|
||||
/* ---- PRIVATE FUNCTIONS ---- */
|
||||
|
||||
_queueIndex: function(_idx) {
|
||||
// Mark the index as queued
|
||||
if (typeof this._queue[_idx] == "undefined")
|
||||
{
|
||||
this._queue[_idx] = true;
|
||||
this._queueSize++;
|
||||
}
|
||||
|
||||
if (this._queueSize > this._stepSize)
|
||||
{
|
||||
this._flushQueue();
|
||||
}
|
||||
else
|
||||
{
|
||||
// (Re)start the queue flush timer
|
||||
var self = this;
|
||||
this._stopFlushTimer();
|
||||
this._queueFlushTimeout = window.setTimeout(function() {
|
||||
self._queueFlushTimeout = null;
|
||||
self._flushQueue();
|
||||
}, 50);
|
||||
}
|
||||
},
|
||||
|
||||
_flushQueue: function() {
|
||||
// Stop the flush timer if it is still active
|
||||
this._stopFlushTimer();
|
||||
|
||||
// Mark all elements in a radius of this._stepSize / 2
|
||||
var marked = {};
|
||||
var r = Math.floor(this._stepSize / 2);
|
||||
for (var key in this._queue)
|
||||
{
|
||||
key = parseInt(key);
|
||||
|
||||
var b = Math.max(0, key - r);
|
||||
var t = Math.min(key + r, this._total - 1);
|
||||
for (var i = b; i <= t; i ++)
|
||||
{
|
||||
marked[i] = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Reset the queue
|
||||
this._queue = {};
|
||||
this._queueSize = 0;
|
||||
|
||||
// Create a list with start indices and counts
|
||||
var fetchList = [];
|
||||
var entry = null;
|
||||
var last = 0;
|
||||
|
||||
// Get the int keys and sort the array numeric
|
||||
var arr = et2_arrayIntKeys(marked).sort(function(a,b){return a > b ? 1 : (a == b ? 0 : -1)});
|
||||
|
||||
for (var i = 0; i < arr.length; i++)
|
||||
{
|
||||
if (i == 0 || arr[i] - last > 1)
|
||||
{
|
||||
if (entry)
|
||||
{
|
||||
fetchList.push(entry);
|
||||
}
|
||||
entry = {
|
||||
"startIdx": arr[i],
|
||||
"count": 1
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
entry.count++;
|
||||
}
|
||||
|
||||
last = arr[i];
|
||||
}
|
||||
|
||||
if (entry)
|
||||
{
|
||||
fetchList.push(entry);
|
||||
}
|
||||
|
||||
// Call the "getRows" callback
|
||||
this._source.getRows(fetchList, this._receiveData, this);
|
||||
},
|
||||
|
||||
_receiveData: function(_data) {
|
||||
var time = (new Date).getTime();
|
||||
|
||||
for (var key in _data)
|
||||
{
|
||||
// Make sure the key is a int
|
||||
key = parseInt(key);
|
||||
|
||||
// Copy the data for the given index
|
||||
this._data[key] = {
|
||||
"data": _data[key],
|
||||
"timestamp": time
|
||||
};
|
||||
|
||||
// Update the row associated to the index
|
||||
this._callUpdateData(key);
|
||||
}
|
||||
},
|
||||
|
||||
_stopFlushTimer: function() {
|
||||
// Stop the queue flush timer
|
||||
if (this._queueFlushTimeout !== null)
|
||||
{
|
||||
window.clearTimeout(this._queueFlushTimeout);
|
||||
}
|
||||
},
|
||||
|
||||
_callUpdateData: function(_idx) {
|
||||
if (typeof this._registeredRows[_idx] != "undefined")
|
||||
{
|
||||
// this._data[idx].timestamp = (new Date).getTime();
|
||||
this._registeredRows[_idx].updateData({
|
||||
"content": this._data[_idx].data
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
_cleanup: function() {
|
||||
// Delete all data rows which have not been accessed for more than
|
||||
// "delta" ms (5 minutes) - this method does not ensure that _dataCount
|
||||
// gets below _maxCount!
|
||||
var delta = 5 * 60 * 1000;
|
||||
var now = (new Date).getTime();
|
||||
|
||||
if (this._dataCount > this._maxCount)
|
||||
{
|
||||
for (var key in this._data)
|
||||
{
|
||||
var entry = this._data[key];
|
||||
|
||||
if (now - entry.timestamp > delta)
|
||||
{
|
||||
delete(this._data[key]);
|
||||
this._dataCount--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
@ -101,6 +101,12 @@ var et2_dataview_partitionNode = Class.extend([et2_dataview_IPartitionHeight,
|
||||
// Invalidate the parent node
|
||||
if (this._parent)
|
||||
{
|
||||
// Invalidate the neighbor node
|
||||
if (this._pidx < this._parent._children.length - 1)
|
||||
{
|
||||
this._parent._children[this._pidx + 1].invalidate();
|
||||
}
|
||||
|
||||
this._parent.invalidate(origin ? this : _sender);
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ var et2_dataview_row = et2_dataview_container.extend(et2_dataview_IDataRow, {
|
||||
this._super(_dataProvider, _rowProvider, _invalidationElem);
|
||||
|
||||
this._avgHeight = _avgHeight;
|
||||
this._idx = null;
|
||||
|
||||
this.rowWidget = null;
|
||||
this.hasAvgHeight = false;
|
||||
@ -37,7 +38,10 @@ var et2_dataview_row = et2_dataview_container.extend(et2_dataview_IDataRow, {
|
||||
destroy: function() {
|
||||
|
||||
// Unregister the row from the data provider
|
||||
this.dataProvider.unregisterDataRow(this);
|
||||
if (this._idx !== null)
|
||||
{
|
||||
this.dataProvider.unregisterDataRow(this._idx);
|
||||
}
|
||||
|
||||
// Free the row widget first, if it has been set
|
||||
if (this.rowWidget)
|
||||
|
@ -76,17 +76,6 @@ var et2_dataview_rowProvider = Class.extend({
|
||||
"data": []
|
||||
};
|
||||
|
||||
// Include the "value" attribute if the widget is derrived from
|
||||
// et2_valueWidget
|
||||
if (_widget instanceof et2_valueWidget)
|
||||
{
|
||||
hasAttr = true;
|
||||
widgetData.data.push({
|
||||
"attribute": "value",
|
||||
"expression": "@${row}"
|
||||
});
|
||||
}
|
||||
|
||||
// Get all attribute values
|
||||
for (var key in _widget.attributes)
|
||||
{
|
||||
@ -166,13 +155,22 @@ var et2_dataview_rowProvider = Class.extend({
|
||||
// "detached" mode
|
||||
var supportedAttrs = [];
|
||||
widget.getDetachedAttributes(supportedAttrs);
|
||||
supportedAttrs.push("id");
|
||||
isDetachable = true;
|
||||
|
||||
for (var j = 0; j < _varAttrs[i].data.length && isDetachable; j++)
|
||||
for (var j = 0; j < _varAttrs[i].data.length/* && isDetachable*/; j++)
|
||||
{
|
||||
var data = _varAttrs[i].data[j];
|
||||
|
||||
isDetachable &= supportedAttrs.indexOf(data.attribute) != -1;
|
||||
var supportsAttr = supportedAttrs.indexOf(data.attribute) != -1;
|
||||
|
||||
if (!supportsAttr)
|
||||
{
|
||||
et2_debug("warn", "et2_IDetachedDOM widget " +
|
||||
widget._type + " does not support " + data.attribute);
|
||||
}
|
||||
|
||||
isDetachable &= supportsAttr;
|
||||
}
|
||||
}
|
||||
|
||||
@ -294,7 +292,7 @@ var et2_dataview_rowProvider = Class.extend({
|
||||
// Record the path to each DOM-Node
|
||||
for (var j = 0; j < nodes.length; j++)
|
||||
{
|
||||
nodeFuncs[i] = this._compileDOMAccessFunc(_rowTemplate.row,
|
||||
nodeFuncs[j] = this._compileDOMAccessFunc(_rowTemplate.row,
|
||||
nodes[j]);
|
||||
}
|
||||
}
|
||||
@ -320,7 +318,7 @@ var et2_dataview_rowProvider = Class.extend({
|
||||
};
|
||||
|
||||
// Create the row widget and insert the given widgets into the row
|
||||
var rowWidget = new et2_dataview_rowWidget(row[0]);
|
||||
var rowWidget = new et2_dataview_rowWidget(_rootWidget, row[0]);
|
||||
rowWidget.createWidgets(_widgets);
|
||||
|
||||
// Get the set containing all variable attributes
|
||||
@ -354,6 +352,18 @@ var et2_dataview_rowProvider = Class.extend({
|
||||
var rowWidget = null;
|
||||
if (this._template.seperated.remaining.length > 0)
|
||||
{
|
||||
// Transform the variable attributes
|
||||
for (var i = 0; i < this._template.seperated.remaining.length; i++)
|
||||
{
|
||||
var entry = this._template.seperated.remaining[i];
|
||||
|
||||
for (var j = 0; j < entry.data.length; j++)
|
||||
{
|
||||
var set = entry.data[j];
|
||||
entry.widget.options[set.attribute] = mgrs["content"].expandName(set.expression);
|
||||
}
|
||||
}
|
||||
|
||||
// Create the row widget
|
||||
var rowWidget = new et2_dataview_rowTemplateWidget(this._rootWidget,
|
||||
_row[0]);
|
||||
@ -371,7 +381,7 @@ var et2_dataview_rowProvider = Class.extend({
|
||||
var data = {};
|
||||
for (var j = 0; j < entry.data.length; j++)
|
||||
{
|
||||
var set = entry.data[i];
|
||||
var set = entry.data[j];
|
||||
data[set.attribute] = mgrs["content"].expandName(set.expression);
|
||||
}
|
||||
|
||||
@ -384,6 +394,13 @@ var et2_dataview_rowProvider = Class.extend({
|
||||
nodes[j] = entry.nodeFuncs[j](_row[0]);
|
||||
}
|
||||
|
||||
// Set the array managers first
|
||||
entry.widget._mgrs = mgrs;
|
||||
if (typeof data.id != "undefined")
|
||||
{
|
||||
entry.widget.id = data.id;
|
||||
}
|
||||
|
||||
// Call the setDetachedAttributes function
|
||||
entry.widget.setDetachedAttributes(nodes, data);
|
||||
}
|
||||
@ -431,9 +448,9 @@ var et2_dataview_rowProvider = Class.extend({
|
||||
|
||||
var et2_dataview_rowWidget = et2_widget.extend(et2_IDOMNode, {
|
||||
|
||||
init: function(_row) {
|
||||
init: function(_parent, _row) {
|
||||
// Call the parent constructor with some dummy attributes
|
||||
this._super(null, {"id": "", "type": "rowWidget"});
|
||||
this._super(_parent, {"id": "", "type": "rowWidget"});
|
||||
|
||||
// Initialize some variables
|
||||
this._widgets = [];
|
||||
|
@ -71,7 +71,7 @@ var et2_nextmatch = et2_DOMWidget.extend(et2_IResizeable, {
|
||||
|
||||
// Create the data provider which cares about streaming the row data
|
||||
// efficiently to the rows
|
||||
this.dataProvider = new et2_dataview_dataProvider();
|
||||
this.dataProvider = new et2_dataview_dataProvider(this, 100);
|
||||
|
||||
// Create the outer grid container
|
||||
this.dataviewContainer = new et2_dataview_gridContainer(this.div,
|
||||
@ -101,6 +101,26 @@ var et2_nextmatch = et2_DOMWidget.extend(et2_IResizeable, {
|
||||
}, this);
|
||||
},
|
||||
|
||||
/**
|
||||
* Get Rows callback
|
||||
*/
|
||||
getRows: function(_fetchList, _callback, _context) {
|
||||
console.log("Nextmatch will fetch ", _fetchList);
|
||||
// Create the entries:
|
||||
var entries = {};
|
||||
for (var i = 0; i < _fetchList.length; i++)
|
||||
{
|
||||
var start = _fetchList[i].startIdx;
|
||||
for (var j = 0; j < _fetchList[i].count; j++)
|
||||
{
|
||||
entries[start + j] =
|
||||
{"info_id":"5","info_type":"email","info_from":"tracker","info_addr":"tracker","info_subject":"InfoLog grid view: problem with Opera; 'permission denied' while saving","info_des":"<snip>","info_owner":"5","info_responsible":[],"info_access":"public","info_cat":"0","info_datemodified":1307112528,"info_startdate":1306503000,"info_enddate":"0", "info_id_parent":"0","info_planned_time":"0","info_replanned_time":"0","info_used_time":"0","info_status":"done", "info_confirm":"not","info_modifier":"5","info_link_id":0,"info_priority":"1","pl_id":"0","info_price":null, "info_percent":"100%","info_datecompleted":1307112528,"info_location":"","info_custom_from":1, "info_uid":"infolog-5-18d12c7bf195f6b9d602e1fa5cde28f1","info_cc":"","caldav_name":"5.ics","info_etag":"0", "info_created":1307112528,"info_creator":"5","links":[],"info_anz_subs":0,"sub_class":"normal_done","info_link":{"title":"tracker"},"class":"rowNoClose rowNoCloseAll ","info_type_label":"E-Mail","info_status_label":"done","info_number":"5"}
|
||||
}
|
||||
}
|
||||
|
||||
_callback.call(_context, entries);
|
||||
},
|
||||
|
||||
/**
|
||||
* Sorts the nextmatch widget by the given ID.
|
||||
*
|
||||
@ -253,7 +273,6 @@ var et2_nextmatch = et2_DOMWidget.extend(et2_IResizeable, {
|
||||
/**
|
||||
* When the template attribute is set, the nextmatch widget tries to load
|
||||
* that template and to fetch the grid which is inside of it. It then calls
|
||||
* _parseGrid in order to get the information for the column headers etc.
|
||||
*/
|
||||
set_template: function(_value) {
|
||||
if (!this.template)
|
||||
|
@ -81,9 +81,6 @@ var et2_description = et2_baseWidget.extend([et2_IDetachedDOM], {
|
||||
init: function() {
|
||||
this._super.apply(this, arguments);
|
||||
|
||||
this.value = "";
|
||||
this.font_style = "";
|
||||
|
||||
// Create the span/label tag which contains the label text
|
||||
this.span = $j(document.createElement(this.options["for"] ? "label" : "span"))
|
||||
.addClass("et2_label");
|
||||
@ -100,6 +97,20 @@ var et2_description = et2_baseWidget.extend([et2_IDetachedDOM], {
|
||||
this.setDOMNode(this.span[0]);
|
||||
},
|
||||
|
||||
transformAttributes: function(_attrs) {
|
||||
this._super.apply(arguments);
|
||||
|
||||
if (this.id)
|
||||
{
|
||||
var val = this.getArrayMgr("content").getEntry(this.id);
|
||||
|
||||
if (val)
|
||||
{
|
||||
_attrs["value"] = val;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_parseText: function(_value) {
|
||||
if (this.options.href)
|
||||
{
|
||||
@ -131,7 +142,7 @@ var et2_description = et2_baseWidget.extend([et2_IDetachedDOM], {
|
||||
|
||||
getDetachedAttributes: function(_attrs)
|
||||
{
|
||||
_attrs.push("value");
|
||||
_attrs.push("value", "class");
|
||||
},
|
||||
|
||||
getDetachedNodes: function()
|
||||
@ -141,11 +152,18 @@ var et2_description = et2_baseWidget.extend([et2_IDetachedDOM], {
|
||||
|
||||
setDetachedAttributes: function(_nodes, _values)
|
||||
{
|
||||
this.transformAttributes(_values);
|
||||
|
||||
if (typeof _values["value"] != "undefined")
|
||||
{
|
||||
et2_insertLinkText(this._parseText(_values["value"]), _nodes[0],
|
||||
this.options.extra_link_target);
|
||||
}
|
||||
|
||||
if (typeof _values["class"] != "undefined")
|
||||
{
|
||||
this.set_class(_values["class"]);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -14,13 +14,14 @@
|
||||
|
||||
/*egw:uses
|
||||
jquery.jquery;
|
||||
et2_core_interfaces;
|
||||
et2_core_baseWidget;
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class which implements the "image" XET-Tag
|
||||
*/
|
||||
var et2_image = et2_baseWidget.extend({
|
||||
var et2_image = et2_baseWidget.extend(/*et2_IDetachedDOM,*/ {
|
||||
|
||||
attributes: {
|
||||
"src": {
|
||||
@ -44,17 +45,31 @@ var et2_image = et2_baseWidget.extend({
|
||||
this._super.apply(this, arguments);
|
||||
|
||||
// Create the image or a/image tag
|
||||
this.image = this.node = $j(document.createElement("img"));
|
||||
var node = this.image = $j(document.createElement("img"));
|
||||
if(this.options.link)
|
||||
{
|
||||
this.node = $j(document.createElement("a"));
|
||||
this.image.appendTo(this.node);
|
||||
this._node = $j(document.createElement("a"));
|
||||
this.image.appendTo(node);
|
||||
}
|
||||
if(this.options["class"])
|
||||
{
|
||||
this.node.addClass(this.options["class"]);
|
||||
node.addClass(this.options["class"]);
|
||||
}
|
||||
this.setDOMNode(node[0]);
|
||||
},
|
||||
|
||||
transformAttributes: function(_attrs) {
|
||||
this._super.apply(arguments);
|
||||
|
||||
// Check to expand name
|
||||
if (typeof _attrs["src"] != "undefined")
|
||||
{
|
||||
var src = this.getArrayMgr("content").getEntry(_attrs["src"]);
|
||||
if (src)
|
||||
{
|
||||
_attrs["src"] = src;
|
||||
}
|
||||
}
|
||||
this.setDOMNode(this.node[0]);
|
||||
},
|
||||
|
||||
set_label: function(_value) {
|
||||
@ -62,7 +77,7 @@ var et2_image = et2_baseWidget.extend({
|
||||
this.options.label = _value;
|
||||
// label is NOT the alt attribute in eTemplate, but the title/tooltip
|
||||
this.image.attr("alt", _value);
|
||||
this.image.set_statustext(_value);
|
||||
this.set_statustext(_value);
|
||||
},
|
||||
|
||||
setValue: function(_value) {
|
||||
@ -70,36 +85,69 @@ var et2_image = et2_baseWidget.extend({
|
||||
this.set_src(_value);
|
||||
},
|
||||
|
||||
percentagePreg: /^[0-9]+%$/,
|
||||
|
||||
set_src: function(_value) {
|
||||
if(!this.isInTree())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Check to expand name
|
||||
if(_value.indexOf("$") != -1 || _value.indexOf("@") != -1) {
|
||||
var contentMgr = this.getArrayMgr("content");
|
||||
if (contentMgr != null) {
|
||||
var val = contentMgr.getValueForID(_value);
|
||||
if (val !== null)
|
||||
{
|
||||
_value = val;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.options.src = _value;
|
||||
// Get application to use from template ID
|
||||
var appname = this.getTemplateApp();
|
||||
var src = egw.image(_value,appname || "phpgwapi");
|
||||
if(src )
|
||||
|
||||
// Check whether "src" is a percentage
|
||||
if (this.percentagePreg.test(_value))
|
||||
{
|
||||
this.image.attr("src", src).show();
|
||||
this.getSurroundings().prependDOMNode(document.createTextNode(_value));
|
||||
}
|
||||
else
|
||||
{
|
||||
this.image.css("display","none");
|
||||
// Get application to use from template ID
|
||||
var src = egw.image(_value, this.getTemplateApp());
|
||||
if(src)
|
||||
{
|
||||
this.image.attr("src", src).show();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.image.css("display","none");
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Implementation of "et2_IDetachedDOM" for fast viewing in gridview
|
||||
*/
|
||||
|
||||
// Does currently not work for percentages, as the surroundings manager
|
||||
// cannot opperate on other DOM-Nodes.
|
||||
|
||||
/* getDetachedAttributes: function(_attrs) {
|
||||
_attrs.push("src", "label");
|
||||
},
|
||||
|
||||
getDetachedNodes: function() {
|
||||
return [this.node, this.image[0]];
|
||||
},
|
||||
|
||||
setDetachedAttributes: function(_nodes, _values) {
|
||||
// Set the given DOM-Nodes
|
||||
this.node = _nodes[0];
|
||||
this.image = $j(_nodes[1]);
|
||||
|
||||
this.transformAttributes(_values);
|
||||
|
||||
// Set the attributes
|
||||
if (_values["src"])
|
||||
{
|
||||
this.set_src(_values["src"]);
|
||||
}
|
||||
|
||||
if (_values["label"])
|
||||
{
|
||||
this.set_label(_values["label"]);
|
||||
}
|
||||
}*/
|
||||
});
|
||||
|
||||
et2_register_widget(et2_image, ["image"]);
|
||||
|
@ -118,7 +118,7 @@ var et2_link_to = et2_inputWidget.extend({
|
||||
if (_attrs["select_options"] == null)
|
||||
{
|
||||
_attrs["select_options"] = this.getArrayMgr('content')
|
||||
.getValueForID("options-" + this.id)
|
||||
.getEntry("options-" + this.id)
|
||||
}
|
||||
|
||||
// Default to an empty object
|
||||
|
@ -77,14 +77,14 @@ var et2_selectbox = et2_inputWidget.extend({
|
||||
this._super.apply(this, arguments);
|
||||
|
||||
// Try to find the options inside the "sel-options" array
|
||||
_attrs["select_options"] = this.getArrayMgr("sel_options").getValueForID(this.id);
|
||||
_attrs["select_options"] = this.getArrayMgr("sel_options").getEntry(this.id);
|
||||
|
||||
// Check whether the options entry was found, if not read it from the
|
||||
// content array.
|
||||
if (_attrs["select_options"] == null)
|
||||
{
|
||||
_attrs["select_options"] = this.getArrayMgr('content')
|
||||
.getValueForID("options-" + this.id)
|
||||
.getEntry("options-" + this.id)
|
||||
}
|
||||
|
||||
// Default to an empty object
|
||||
|
@ -64,7 +64,7 @@ var et2_tabbox = et2_DOMWidget.extend({
|
||||
// Set the value for this element
|
||||
var contentMgr = this.getArrayMgr("content");
|
||||
if (contentMgr != null) {
|
||||
var val = contentMgr.getValueForID(this.id);
|
||||
var val = contentMgr.getEntry(this.id);
|
||||
if (val !== null)
|
||||
{
|
||||
selected = val;
|
||||
@ -72,7 +72,7 @@ var et2_tabbox = et2_DOMWidget.extend({
|
||||
}
|
||||
contentMgr = this.getArrayMgr("readonlys");
|
||||
if (contentMgr != null) {
|
||||
var val = contentMgr.getValueForID(this.id);
|
||||
var val = contentMgr.getEntry(this.id);
|
||||
if (val !== null)
|
||||
{
|
||||
hidden = val;
|
||||
|
@ -63,19 +63,69 @@
|
||||
<nextmatch-sortheader label="last changed" id="info_datemodified" options="DESC"/>
|
||||
</row>
|
||||
<row class="$row_cont[info_cat] $row_cont[class]" valign="top">
|
||||
<vbox>
|
||||
<description value="Dynamic description tag:" />
|
||||
<description value="$cont[$row][ts_title]" />
|
||||
<button label="This is a button" />
|
||||
<hbox align="center" options="5">
|
||||
<image label="$row_cont[info_type]" src="${row}[info_type]"/>
|
||||
<button statustext="Change the status of an entry, eg. close it" label="$row_cont[info_status_label]" id="edit_status[$row_cont[info_id]]" onclick="window.open(egw::link('/index.php','menuaction=infolog.infolog_ui.edit&info_id=$row_cont[info_id]'),'_blank','dependent=yes,width=750,height=600,scrollbars=yes,status=yes'); return false;" image="$row_cont[info_status_label]" ro_image="$row_cont[info_status_label]"/>
|
||||
<button statustext="Change the status of an entry, eg. close it" label="$row_cont[info_percent]" id="edit_percent[$row_cont[info_id]]" onclick="window.open(egw::link('/index.php','menuaction=infolog.infolog_ui.edit&info_id=$row_cont[info_id]'),'_blank','dependent=yes,width=750,height=600,scrollbars=yes,status=yes'); return false;" image="$row_cont[info_percent]"/>
|
||||
<image label="$row_cont[info_percent2]" src="{$row}[info_percent2]" onclick="window.open(egw::link('/index.php','menuaction=infolog.infolog_ui.edit&info_id=$row_cont[info_id]'),'_blank','dependent=yes,width=750,height=600,scrollbars=yes,status=yes'); return false;"/>
|
||||
</hbox>
|
||||
<vbox options="0,0" class="fullWidth">
|
||||
<link label="%s $row_cont[info_addr]" id="${row}[info_link]" options="b"/>
|
||||
<hbox options="0,0">
|
||||
<description id="${row}[info_subject]" no_lang="1" class="$row_cont[sub_class]"/>
|
||||
<description align="right" id="{$row}[info_number]" no_lang="1" class="infoId"/>
|
||||
</hbox>
|
||||
<box class="infoDes">
|
||||
<description id="${row}[info_des]" no_lang="1" options=",,1"/>
|
||||
</box>
|
||||
<link-string id="${row}[filelinks]"/>
|
||||
</vbox>
|
||||
<customfields-list id="$row" class="customfields"/>
|
||||
<menulist>
|
||||
<menupopup type="select-cat" id="${row}[info_cat]" readonly="true"/>
|
||||
</menulist>
|
||||
<vbox cols="1" rows="3" options="0,0,1">
|
||||
<date-time id="${row}[info_startdate]" readonly="true" options=",8" class="fixedHeight"/>
|
||||
<date id="${row}[info_enddate]" readonly="true" class="$row_cont[end_class] fixedHeight"/>
|
||||
<date-time id="${row}[info_datecompleted]" readonly="true" class="fixedHeight"/>
|
||||
</vbox>
|
||||
<vbox cols="1" rows="3" options="0,0">
|
||||
<hbox readonly="true">
|
||||
<hbox readonly="true" options="1,0">
|
||||
<date-duration id="${row}[info_used_time]" readonly="true" options="@duration_format"/>
|
||||
<date-duration id="${row}[info_sum_timesheets]" readonly="true" options="@duration_format" class="timesheet"/>
|
||||
</hbox>
|
||||
<description/>
|
||||
</hbox>
|
||||
<date-duration id="${row}[info_planned_time]" readonly="true" options="@duration_format" span="all" class="planned"/>
|
||||
</vbox>
|
||||
<vbox cols="1" rows="3" options="0,0">
|
||||
<hbox id="r_used_time" options="1,0">
|
||||
<image label="Times" src="timesheet"/>
|
||||
<date-duration id="${row}[info_used_time]" readonly="true" options="@duration_format"/>
|
||||
<date-duration id="${row}[info_sum_timesheets]" readonly="true" options="@duration_format" class="timesheet"/>
|
||||
</hbox>
|
||||
<hbox id="planified" options="1,0">
|
||||
<image label="planned time" src="k_alarm.png"/>
|
||||
<date-duration id="${row}[info_planned_time]" readonly="true" options="@duration_format" span="all" class="planned"/>
|
||||
</hbox>
|
||||
<hbox id="replanified" options="1,0">
|
||||
<image label="Re-planned time" src="agt_reload.png"/>
|
||||
<date-duration id="${row}[info_replanned_time]" readonly="true" options="@duration_format" span="all" class="replanned"/>
|
||||
</hbox>
|
||||
</vbox>
|
||||
<vbox options="0,0">
|
||||
<menulist>
|
||||
<menupopup type="select-account" id="${row}[info_owner]" readonly="true"/>
|
||||
</menulist>
|
||||
<listbox type="select-account" id="${row}[info_responsible]" readonly="true" rows="5"/>
|
||||
</vbox>
|
||||
<vbox options="0" orient="0">
|
||||
<date-time id="${row}[info_datemodified]" readonly="true"/>
|
||||
<menulist>
|
||||
<menupopup type="select-account" id="${row}[info_modifier]" readonly="true"/>
|
||||
</menulist>
|
||||
</vbox>
|
||||
<description value="test" />
|
||||
<description value="test" />
|
||||
<description value="test" />
|
||||
<description value="test" />
|
||||
<description value="test" />
|
||||
<description value="test" />
|
||||
<description value="test" />
|
||||
<description value="test2" />
|
||||
</row>
|
||||
</rows>
|
||||
</grid>
|
||||
|
Loading…
Reference in New Issue
Block a user