2011-08-15 14:34:00 +02:00
|
|
|
/**
|
|
|
|
* eGroupWare eTemplate2 - JS file which contains the complete et2 module
|
|
|
|
*
|
|
|
|
* @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
|
|
|
|
// Include all widget classes here
|
2011-08-24 12:18:07 +02:00
|
|
|
et2_widget_template;
|
|
|
|
et2_widget_grid;
|
|
|
|
et2_widget_box;
|
|
|
|
et2_widget_hbox;
|
|
|
|
et2_widget_button;
|
|
|
|
et2_widget_description;
|
|
|
|
et2_widget_textbox;
|
|
|
|
et2_widget_number;
|
|
|
|
et2_widget_selectbox;
|
|
|
|
et2_widget_checkbox;
|
|
|
|
et2_widget_radiobox;
|
|
|
|
et2_widget_date;
|
|
|
|
et2_widget_styles;
|
|
|
|
et2_widget_html;
|
|
|
|
et2_widget_tabs;
|
|
|
|
et2_widget_hrule;
|
2011-08-15 14:34:00 +02:00
|
|
|
|
2011-08-25 15:35:53 +02:00
|
|
|
et2_extension_nextmatch;
|
|
|
|
|
2011-08-15 14:34:00 +02:00
|
|
|
// Requirements for the etemplate2 object
|
2011-08-24 12:18:07 +02:00
|
|
|
et2_core_xml;
|
|
|
|
et2_core_arrayMgr;
|
2011-08-25 17:54:15 +02:00
|
|
|
et2_core_interfaces;
|
2011-08-15 14:34:00 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The etemplate2 class manages a certain etemplate2 instance.
|
|
|
|
*
|
|
|
|
* @param _container is the DOM-Node into which the DOM-Nodes of this instance
|
|
|
|
* should be inserted
|
|
|
|
* @param _submitURL is the URL to which the form data should be submitted.
|
|
|
|
*/
|
2011-08-15 16:29:58 +02:00
|
|
|
function etemplate2(_container, _menuaction)
|
2011-08-15 14:34:00 +02:00
|
|
|
{
|
2011-08-15 16:29:58 +02:00
|
|
|
if (typeof _menuaction == "undefined")
|
|
|
|
{
|
|
|
|
_menuaction = "etemplate_new::ajax_process_content";
|
|
|
|
}
|
|
|
|
|
2011-08-15 14:34:00 +02:00
|
|
|
// Copy the given parameters
|
|
|
|
this.DOMContainer = _container;
|
2011-08-15 16:29:58 +02:00
|
|
|
this.menuaction = _menuaction;
|
2011-08-15 14:34:00 +02:00
|
|
|
|
|
|
|
// Preset the object variable
|
|
|
|
this.widgetContainer = null;
|
2011-08-16 20:18:18 +02:00
|
|
|
|
2011-08-25 17:54:15 +02:00
|
|
|
// Connect to the window resize event
|
|
|
|
$j(window).resize(this, function(e) {e.data.resize()});
|
|
|
|
|
2011-08-16 20:18:18 +02:00
|
|
|
// Associative array with the event listeners
|
|
|
|
this.listeners = {};
|
2011-08-15 14:34:00 +02:00
|
|
|
}
|
|
|
|
|
2011-08-25 17:54:15 +02:00
|
|
|
/**
|
|
|
|
* Calls the resize event of all widgets
|
|
|
|
*/
|
|
|
|
etemplate2.prototype.resize = function()
|
|
|
|
{
|
|
|
|
if (this.widgetContainer)
|
|
|
|
{
|
|
|
|
// Call the "resize" event of all functions which implement the
|
|
|
|
// "IResizeable" interface
|
|
|
|
this.widgetContainer.iterateOver(function(_widget) {
|
|
|
|
_widget.resize();
|
|
|
|
}, this, et2_IResizeable);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-08-15 14:34:00 +02:00
|
|
|
/**
|
|
|
|
* Clears the current instance.
|
|
|
|
*/
|
|
|
|
etemplate2.prototype.clear = function()
|
|
|
|
{
|
|
|
|
if (this.widgetContainer != null)
|
|
|
|
{
|
2011-08-19 18:00:44 +02:00
|
|
|
// $j(':input',this.DOMContainer).validator().data("validator").destroy();
|
2011-08-25 15:35:53 +02:00
|
|
|
this.widgetContainer.free();
|
2011-08-15 14:34:00 +02:00
|
|
|
this.widgetContainer = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates an associative array containing the data array managers for each part
|
|
|
|
* of the associative data array. A part is something like "content", "readonlys"
|
|
|
|
* or "sel_options".
|
|
|
|
*/
|
|
|
|
etemplate2.prototype._createArrayManagers = function(_data)
|
|
|
|
{
|
2011-08-15 14:46:27 +02:00
|
|
|
if (typeof _data == "undefined")
|
|
|
|
{
|
|
|
|
_data = {};
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create all neccessary _data entries
|
2011-08-23 17:27:34 +02:00
|
|
|
var neededEntries = ["content", "sel_options", "readonlys", "modifications",
|
|
|
|
"validation_errors"];
|
2011-08-15 14:46:27 +02:00
|
|
|
for (var i = 0; i < neededEntries.length; i++)
|
|
|
|
{
|
|
|
|
if (typeof _data[neededEntries[i]] == "undefined")
|
|
|
|
{
|
2011-08-23 17:27:34 +02:00
|
|
|
et2_debug("log", "Created not passed entry '" + neededEntries[i] +
|
|
|
|
"' in data array.");
|
2011-08-15 14:46:27 +02:00
|
|
|
_data[neededEntries[i]] = {};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-08-15 14:34:00 +02:00
|
|
|
var result = {};
|
|
|
|
|
|
|
|
// Create an array manager object for each part of the _data array.
|
|
|
|
for (var key in _data)
|
|
|
|
{
|
2011-08-16 14:31:18 +02:00
|
|
|
switch (key) {
|
2011-08-16 21:40:48 +02:00
|
|
|
case "etemplate_exec_id": // already processed
|
|
|
|
case "app_header":
|
|
|
|
break;
|
2011-08-16 14:31:18 +02:00
|
|
|
case "readonlys":
|
|
|
|
result[key] = new et2_readonlysArrayMgr(_data[key]);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
result[key] = new et2_arrayMgr(_data[key]);
|
|
|
|
}
|
2011-08-15 14:34:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Loads the template from the given URL and sets the data object
|
|
|
|
*/
|
|
|
|
etemplate2.prototype.load = function(_url, _data)
|
|
|
|
{
|
|
|
|
// Asynchronously load the XET file (code below is executed ahead of the
|
|
|
|
// code in the callback function)
|
|
|
|
et2_loadXMLFromURL(_url, function(_xmldoc) {
|
2011-08-19 18:00:44 +02:00
|
|
|
// Read the XML structure
|
2011-08-15 14:34:00 +02:00
|
|
|
this.widgetContainer.loadFromXML(_xmldoc);
|
2011-08-25 17:54:15 +02:00
|
|
|
|
2011-08-19 18:00:44 +02:00
|
|
|
// Inform the widget tree that it has been successfully loaded.
|
|
|
|
this.widgetContainer.loadingFinished();
|
2011-08-25 17:54:15 +02:00
|
|
|
|
|
|
|
// Trigger the "resize" event
|
|
|
|
this.resize();
|
2011-08-15 14:34:00 +02:00
|
|
|
}, this);
|
|
|
|
|
|
|
|
// Clear any existing instance
|
|
|
|
this.clear();
|
|
|
|
|
|
|
|
// Create the basic widget container and attach it to the DOM
|
|
|
|
this.widgetContainer = new et2_container(null);
|
2011-08-15 16:29:58 +02:00
|
|
|
this.widgetContainer.setInstanceManager(this);
|
2011-08-15 14:34:00 +02:00
|
|
|
this.widgetContainer.setParentDOMNode(this.DOMContainer);
|
|
|
|
|
2011-08-16 21:40:48 +02:00
|
|
|
// store the id to submit it back to server
|
2011-08-16 23:18:26 +02:00
|
|
|
if(_data) {
|
|
|
|
this.etemplate_exec_id = _data.etemplate_exec_id;
|
|
|
|
}
|
2011-08-16 21:40:48 +02:00
|
|
|
|
|
|
|
// set app_header
|
|
|
|
if (window.opener) { // popup
|
|
|
|
document.title = _data.app_header;
|
|
|
|
} else {
|
|
|
|
// todo for idots or jdots framework
|
|
|
|
}
|
|
|
|
|
2011-08-15 14:34:00 +02:00
|
|
|
// Split the given data into array manager objects and pass those to the
|
|
|
|
// widget container
|
|
|
|
this.widgetContainer.setArrayMgrs(this._createArrayManagers(_data));
|
|
|
|
}
|
|
|
|
|
2011-08-15 16:29:58 +02:00
|
|
|
etemplate2.prototype.submit = function()
|
|
|
|
{
|
2011-08-17 23:36:08 +02:00
|
|
|
// Validator
|
2011-08-19 18:00:44 +02:00
|
|
|
/*var valid = true;
|
2011-08-17 23:36:08 +02:00
|
|
|
var inputs = $j(':input',this.DOMContainer).each(function() {
|
|
|
|
if(typeof $j(this).data("validator") == "undefined") return true;
|
|
|
|
valid = valid && $j(this).data("validator").checkValidity();
|
|
|
|
return true;
|
|
|
|
});
|
2011-08-19 18:00:44 +02:00
|
|
|
if(!valid) return false;*/
|
2011-08-17 23:36:08 +02:00
|
|
|
|
2011-08-15 16:29:58 +02:00
|
|
|
// Get the form values
|
2011-08-23 16:59:49 +02:00
|
|
|
var values = this.getValues(this.widgetContainer);
|
2011-08-15 16:29:58 +02:00
|
|
|
|
2011-08-16 20:18:18 +02:00
|
|
|
// Trigger the submit event
|
|
|
|
if (this.fireEvent("submit", [values]))
|
2011-08-15 16:29:58 +02:00
|
|
|
{
|
2011-08-16 20:18:18 +02:00
|
|
|
// Create the request object
|
|
|
|
if (typeof egw_json_request != "undefined")
|
|
|
|
{
|
2011-08-16 21:40:48 +02:00
|
|
|
var request = new egw_json_request(this.menuaction, [this.etemplate_exec_id,values], this);
|
2011-08-16 20:18:18 +02:00
|
|
|
request.sendRequest(true);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
et2_debug("info", "Form got submitted with values: ", values);
|
|
|
|
}
|
2011-08-15 16:29:58 +02:00
|
|
|
}
|
2011-08-16 20:18:18 +02:00
|
|
|
}
|
|
|
|
|
2011-08-23 16:59:49 +02:00
|
|
|
/**
|
|
|
|
* Fetches all input element values and returns them in an associative
|
|
|
|
* array. Widgets which introduce namespacing can use the internal _target
|
|
|
|
* parameter to add another layer.
|
|
|
|
*/
|
|
|
|
etemplate2.prototype.getValues = function(_root)
|
|
|
|
{
|
|
|
|
var result = {};
|
|
|
|
|
|
|
|
// Iterate over the widget tree
|
|
|
|
_root.iterateOver(function(_widget) {
|
|
|
|
|
|
|
|
// The widget must have an id to be included in the values array
|
|
|
|
if (_widget.id == "")
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the path to the node we have to store the value at
|
|
|
|
var path = _widget.getArrayMgr("content").getPath();
|
|
|
|
|
|
|
|
// check if id contains a hierachical name, eg. "button[save]"
|
|
|
|
var id = _widget.id;
|
|
|
|
if (_widget.id.indexOf('[') != -1)
|
|
|
|
{
|
|
|
|
var parts = _widget.id.replace(/]/g,'').split('[');
|
|
|
|
id = parts.pop();
|
|
|
|
path = path.concat(parts);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set the _target variable to that node
|
|
|
|
var _target = result;
|
|
|
|
for (var i = 0; i < path.length; i++)
|
|
|
|
{
|
|
|
|
// Create a new object for not-existing path nodes
|
|
|
|
if (typeof _target[path[i]] == "undefined")
|
|
|
|
{
|
|
|
|
_target[path[i]] = {};
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check whether the path node is really an object
|
|
|
|
if (_target[path[i]] instanceof Object)
|
|
|
|
{
|
|
|
|
_target = _target[path[i]];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
et2_debug("error", "ID collision while writing at path " +
|
|
|
|
"node '" + path[i] + "'");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check whether the entry is really undefined
|
|
|
|
if (typeof _target[id] != "undefined")
|
|
|
|
{
|
|
|
|
et2_debug("error", _widget, "Overwriting value of '" + _widget.id +
|
|
|
|
"', id exists twice!");
|
|
|
|
}
|
|
|
|
|
|
|
|
// Store the value of the widget and reset its dirty flag
|
|
|
|
var value = _widget.getValue();
|
|
|
|
if (value !== null)
|
|
|
|
{
|
|
|
|
_target[id] = value;
|
|
|
|
}
|
|
|
|
_widget.resetDirty();
|
|
|
|
|
|
|
|
}, this, et2_IInput);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2011-08-16 20:18:18 +02:00
|
|
|
/**
|
|
|
|
* Adds an callback function to the given event slot
|
|
|
|
*
|
|
|
|
* @param _event is the name of the event
|
|
|
|
* @param _callback is the function which should be called once the event gets
|
|
|
|
* fired.
|
|
|
|
* @param _context is the context in which the function should be executed.
|
|
|
|
*/
|
|
|
|
etemplate2.prototype.addListener = function(_event, _callback, _context)
|
|
|
|
{
|
|
|
|
// Add the event slot if it does not exist yet
|
|
|
|
if (typeof this.listeners[_event] == "undefined")
|
2011-08-15 16:29:58 +02:00
|
|
|
{
|
2011-08-16 20:18:18 +02:00
|
|
|
this.listeners[_event] = [];
|
2011-08-15 16:29:58 +02:00
|
|
|
}
|
2011-08-16 20:18:18 +02:00
|
|
|
|
|
|
|
this.listeners[_event].push({
|
|
|
|
"callback": _callback,
|
|
|
|
"context": _context
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Removes the given callback function from the given event slot.
|
|
|
|
*/
|
|
|
|
etemplate2.prototype.removeListener = function(_event, _callback)
|
|
|
|
{
|
|
|
|
if (typeof this.listeners[_event] != "undefined")
|
|
|
|
{
|
|
|
|
var events = this.listeners[_event];
|
|
|
|
|
|
|
|
for (var i = events.length - 1; i >= 0; i--)
|
|
|
|
{
|
|
|
|
if (events[i].callback == _callback)
|
|
|
|
{
|
|
|
|
events.splice(i, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Fires the given event. The return values are conected via AND
|
|
|
|
*/
|
|
|
|
etemplate2.prototype.fireEvent = function(_event, _args)
|
|
|
|
{
|
|
|
|
if (typeof _args == "undefined")
|
|
|
|
{
|
|
|
|
_args = [];
|
|
|
|
}
|
|
|
|
|
|
|
|
var result = true;
|
|
|
|
|
|
|
|
if (typeof this.listeners[_event] != "undefined")
|
|
|
|
{
|
|
|
|
var events = this.listeners[_event];
|
|
|
|
|
|
|
|
for (var i = 0; i < events.length; i++)
|
|
|
|
{
|
|
|
|
result = result && events[i].callback.apply(events[i].context, _args);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
2011-08-15 16:29:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Function which handles the EGW JSON et2_load response
|
|
|
|
*/
|
|
|
|
function etemplate2_handle_response(_type, _response)
|
|
|
|
{
|
|
|
|
if (_type == "et2_load")
|
|
|
|
{
|
|
|
|
// Check the parameters
|
|
|
|
var data = _response.data;
|
|
|
|
if (typeof data.url == "string" && data.data instanceof Object)
|
|
|
|
{
|
|
|
|
this.load(data.url, data.data);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
throw("Error while parsing et2_load response");
|
2011-08-17 23:36:08 +02:00
|
|
|
} else if (_type == "et2_validation_error") {
|
|
|
|
// Display validation errors
|
2011-08-19 18:00:44 +02:00
|
|
|
// $j(':input',this.DOMContainer).data("validator").invalidate(_response.data);
|
2011-08-15 16:29:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Register the egw_json result object
|
|
|
|
if (typeof egw_json_register_plugin != "undefined")
|
|
|
|
{
|
|
|
|
// Calls etemplate2_handle_response in the context of the object which
|
|
|
|
// requested the response from the server
|
|
|
|
egw_json_register_plugin(etemplate2_handle_response, null);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
et2_debug("info", "EGW JSON Plugin could not be registered, running ET2 standalone.");
|
|
|
|
}
|
2011-08-15 14:34:00 +02:00
|
|
|
|