forked from extern/egroupware
allow to submit partial content by passing a container(-widget) to etemplate2.submit()
- not send content is not validated and therefore not passed to server-side callback (currently only implemented for text-, select- and checkbox) - new method et2_grid.getRow(_widget) to return a fake row container to pass it etemplate2.submit() --> implemented a real row-container for et2_grid - new output_mode=4 for etemplate_new::exec() to force a json response, like form was submitted from client-side --> allows to use full server-side validation for ajax like calls submitting only partial content
This commit is contained in:
parent
d4c0992f45
commit
8c8e61630d
@ -95,6 +95,7 @@ class etemplate_new extends etemplate_widget_template
|
||||
* -1 = first time return html, after use 0 (echo html incl. navbar), eg. for home
|
||||
* 2 = echo without navbar (eg. for popups)
|
||||
* 3 = return eGW independent html site
|
||||
* 4 = json response
|
||||
* @param string $ignore_validation if not empty regular expression for validation-errors to ignore
|
||||
* @param array $changes change made in the last call if looping, only used internaly by process_exec
|
||||
* @return string html for $output_mode == 1, else nothing
|
||||
@ -106,6 +107,11 @@ class etemplate_new extends etemplate_widget_template
|
||||
|
||||
if (!$this->rel_path) throw new egw_exception_assertion_failed("No (valid) template '$this->name' found!");
|
||||
|
||||
if ($output_mode == 4)
|
||||
{
|
||||
$output_mode = 0;
|
||||
self::$response = egw_json_response::get();
|
||||
}
|
||||
self::$request->output_mode = $output_mode; // let extensions "know" they are run eg. in a popup
|
||||
self::$request->content = self::$cont = $content;
|
||||
self::$request->changes = $changes;
|
||||
|
@ -717,6 +717,22 @@ class etemplate_widget
|
||||
return $pos;
|
||||
}
|
||||
|
||||
/**
|
||||
* return a reference to $arr[$idx]
|
||||
*
|
||||
* This works for non-trival indexes like 'a[b][c]' too: it returns &$arr[a][b][c]
|
||||
* $sub = get_array($arr,'a[b]'); $sub = 'c'; is equivalent to $arr['a']['b'] = 'c';
|
||||
*
|
||||
* @param array& $_arr the array to search, referenz as a referenz gets returned
|
||||
* @param string $_idx the index, may contain sub-indices like a[b], see example below
|
||||
* @param mixed $_value value to set
|
||||
*/
|
||||
static function set_array(&$_arr, $_idx, $_value)
|
||||
{
|
||||
$ref =& self::get_array($_arr, $_idx, true);
|
||||
if (true) $ref = $_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a widget is readonly:
|
||||
* - readonly attribute set
|
||||
|
@ -52,6 +52,7 @@ class etemplate_widget_checkbox extends etemplate_widget
|
||||
if (!$this->is_readonly($cname, $form_name))
|
||||
{
|
||||
$value = self::get_array($content, $form_name);
|
||||
if (!isset($value)) return; // value not transmitted --> nothing to validate
|
||||
$valid =& self::get_array($validated, $form_name, true);
|
||||
|
||||
if (!$value && $this->attrs['needed'])
|
||||
|
@ -174,9 +174,11 @@ class etemplate_widget_menupopup extends etemplate_widget
|
||||
}
|
||||
}
|
||||
}
|
||||
$valid =& self::get_array($validated, $form_name, true);
|
||||
if (true) $valid = $value;
|
||||
//error_log(__METHOD__."() $form_name: ".array2string($value_in).' --> '.array2string($value).', allowed='.array2string($allowed));
|
||||
if (isset($value))
|
||||
{
|
||||
self::set_array($validated, $form_name, $value);
|
||||
//error_log(__METHOD__."() $form_name: ".array2string($value_in).' --> '.array2string($value).', allowed='.array2string($allowed));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -131,7 +131,6 @@ class etemplate_widget_textbox extends etemplate_widget
|
||||
}
|
||||
|
||||
$value = $value_in = self::get_array($content, $form_name);
|
||||
$valid =& self::get_array($validated, $form_name, true);
|
||||
|
||||
// passwords are not transmitted back to client (just asterisks)
|
||||
// therefore we need to replace it again with preserved value
|
||||
@ -185,8 +184,11 @@ class etemplate_widget_textbox extends etemplate_widget
|
||||
}
|
||||
}
|
||||
}
|
||||
if (true) $valid = $value;
|
||||
//error_log(__METHOD__."() $form_name: ".array2string($value_in).' --> '.array2string($value));
|
||||
if (isset($value))
|
||||
{
|
||||
self::set_array($validated, $form_name, $value);
|
||||
//error_log(__METHOD__."() $form_name: ".array2string($value_in).' --> '.array2string($value));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1026,6 +1026,47 @@ var et2_grid = et2_DOMWidget.extend([et2_IDetachedDOM, et2_IAligned, et2_IResize
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Get a dummy row object containing all widget of a row
|
||||
*
|
||||
* This is only a temp. solution until rows are implemented as eT2 containers and
|
||||
* _sender.getParent() will return a real row container.
|
||||
*
|
||||
* @param {et2_widget} _sender
|
||||
* @returns {Array|undefined}
|
||||
*/
|
||||
getRow: function(_sender)
|
||||
{
|
||||
if (!_sender || !this.cells) return;
|
||||
|
||||
for(var r=0; r < this.cells.length; ++r)
|
||||
{
|
||||
var row = this.cells[r];
|
||||
for(var c=0; c < row.length; ++c)
|
||||
{
|
||||
if (!row[c].widget) continue;
|
||||
|
||||
var found = row[c].widget === _sender;
|
||||
if (!found) row[c].widget.iterateOver(function(_widget) {if (_widget === _sender) found = true;});
|
||||
if (found)
|
||||
{
|
||||
// return a fake row object allowing to iterate over it's children
|
||||
var row_obj = new et2_widget(this, {});
|
||||
for(var c=0; c < row.length; ++c)
|
||||
{
|
||||
if (row[c].widget) row_obj._children.push(row[c].widget);
|
||||
}
|
||||
row_obj.isInTree = jQuery.proxy(this.isInTree, this);
|
||||
// we must not free the children!
|
||||
row_obj.destroy = function(){
|
||||
delete row_obj._children;
|
||||
};
|
||||
return row_obj;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
et2_register_widget(et2_grid, ["grid"]);
|
@ -498,7 +498,7 @@ etemplate2.prototype.load = function(_name, _url, _data, _callback)
|
||||
$this = $j(this);
|
||||
return !$this.attr('tabindex') || $this.attr('tabIndex')>=0;
|
||||
}).first();
|
||||
|
||||
|
||||
// mobile device, focus only if the field is empty (usually means new entry)
|
||||
// should focus always for non-mobile one
|
||||
if (egwIsMobile() && $input.val() == "" || !egwIsMobile()) $input.focus();
|
||||
@ -616,23 +616,25 @@ etemplate2.prototype.autocomplete_fixer = function ()
|
||||
* @param {(et2_button|string)} button button widget or string with id
|
||||
* @param {boolean} async true: do an asynchronious submit, default is synchronious
|
||||
* @param {boolean} no_validation - Do not do individual widget validation, just submit their current values
|
||||
* @param {et2_widget|undefined} _container container to submit, default whole template
|
||||
* @return {boolean} true if submit was send, false if eg. validation stoped submit
|
||||
*/
|
||||
etemplate2.prototype.submit = function(button, async, no_validation)
|
||||
etemplate2.prototype.submit = function(button, async, no_validation, _container)
|
||||
{
|
||||
if(typeof no_validation == 'undefined')
|
||||
{
|
||||
no_validation = false;
|
||||
}
|
||||
var container = _container || this.widgetContainer;
|
||||
|
||||
// Get the form values
|
||||
var values = this.getValues(this.widgetContainer);
|
||||
var values = this.getValues(container);
|
||||
|
||||
// Trigger the submit event
|
||||
var canSubmit = true;
|
||||
if(!no_validation)
|
||||
{
|
||||
this.widgetContainer.iterateOver(function(_widget) {
|
||||
container.iterateOver(function(_widget) {
|
||||
if (_widget.submit(values) === false)
|
||||
{
|
||||
canSubmit = false;
|
||||
|
@ -13,15 +13,15 @@
|
||||
<description value="Header" span="all"/>
|
||||
<description/>
|
||||
</row>
|
||||
<row part="footer">
|
||||
<description value="Footer" span="all"/>
|
||||
<description/>
|
||||
</row>
|
||||
<row class="th">
|
||||
<row class="th" part="header">
|
||||
<grid-sortheader label="Col 1 Header" id="first" custom-sort="app.method"/>
|
||||
<grid-sortheader label="Col 2 Header" id="second"/>
|
||||
<description value="Col 3 Header"/>
|
||||
</row>
|
||||
<row part="footer">
|
||||
<description value="Footer" span="all"/>
|
||||
<description/>
|
||||
</row>
|
||||
<row class="row">
|
||||
<description id="${row}[first]"/>
|
||||
<description id="${row}[second]"/>
|
||||
|
Loading…
Reference in New Issue
Block a user