backport of several eT2 fixes from work on ranking / result-service app:

r52153: implement part attribute with values "header" and "footer" to put rows in thead or tfoot instead of tbody of table
r52163: stop etemplate_widget_template::instance from returning a stdClass object for a not found template after content-expanding, leading to a fatal error in etemplate_widget line 338
r52175: there should be no validation for disabled widgets
r52176: $cont is NOT root but current name-space in old eTemplate, leaving now identical $_cont for now
r52194: fixed eT2 data returned from client for case where name-space contains more then one component eg. "nm[rows]"
r52195: fixed not run validation on server-side for templates included via template tag
r52196: implement formatting of numbers in read-only widget
This commit is contained in:
Ralf Becker 2015-03-18 22:16:15 +00:00
commit 12c308cd71
10 changed files with 111 additions and 20 deletions

View File

@ -0,0 +1,14 @@
<?php
class etemplate_table_test
{
var $public_functions = array(
'index' => true,
);
function index(array $content=null, $msg='')
{
$tmpl = new etemplate_new('etemplate.table_test');
$content = array();
$tmpl->exec('etemplate.etemplate_table_test.index', $content);
}
}

View File

@ -76,9 +76,9 @@ class etemplate_widget_template extends etemplate_widget
if (is_array(self::$request->content))
{
$expand_name = self::expand_name($name, '','','','',self::$cont);
if($expand_name && $expand_name != $name)
if ($expand_name && $expand_name != $name &&
($template = self::instance($expand_name, $template_set, $version, $load_via)))
{
$template = self::instance($expand_name, $template_set, $version, $load_via);
// Remember original, un-expanded name in case content changes while still cached
$template->original_name = $name;
return $template;
@ -216,7 +216,8 @@ class etemplate_widget_template extends etemplate_widget
if ($this->attrs['content']) $cname = self::form_name($cname, $this->attrs['content'], $params[1]);
// Check for template from content, and run over it
$expand_name = self::expand_name($this->id, '','','','',self::$request->content);
// templates included via template tag have their name to load them from in attribute "template"
$expand_name = self::expand_name($this->id ? $this->id : $this->attrs['template'], '','','','',self::$request->content);
if($this->original_name)
{
$expand_name = self::expand_name($this->original_name, '','','','',self::$request->content);
@ -224,8 +225,10 @@ class etemplate_widget_template extends etemplate_widget
//error_log("$this running $method_name() cname: {$this->id} -> expand_name: $expand_name");
if($expand_name && $expand_name != $this->id)
{
$row_template = etemplate_widget_template::instance($expand_name);
$row_template->run($method_name, $params, $respect_disabled);
if (($row_template = etemplate_widget_template::instance($expand_name)))
{
$row_template->run($method_name, $params, $respect_disabled);
}
}
else
{

View File

@ -156,7 +156,8 @@ var et2_arrayMgr = Class.extend(
if (this.perspectiveData.key != null)
{
_path.unshift(this.perspectiveData.key);
// prepend components of this.perspectiveData.key to path, can be more then one eg. "nm[rows]"
_path = this.perspectiveData.key.replace(/]/g, '').split('[').concat(_path);
}
if (this.parentMgr != null)
@ -238,8 +239,9 @@ var et2_arrayMgr = Class.extend(
// Get the content array for the current row
var row = this.perspectiveData.row;
var row_cont = this.data[row] || {};
var cont = this.getRoot().data;
var _cont = this.data;
// $cont is NOT root but current name-space in old eTemplate
var cont = this.data;//getRoot().data;
var _cont = this.data;// according to a grep only used in ImportExport just twice
// Check whether the expression has already been compiled - if not,
// try to compile it first. If an error occurs, the identifier

View File

@ -296,7 +296,8 @@ var et2_inputWidget = et2_valueWidget.extend([et2_IInput,et2_ISubmitListener],
var ok = true;
// Check for required
if(this.options && this.options.needed && !this.options.readonly && (this.getValue() == null || this.getValue().valueOf() == ''))
if (this.options && this.options.needed && !this.options.readonly && !this.disabled &&
(this.getValue() == null || this.getValue().valueOf() == ''))
{
messages.push(this.egw().lang('Field must not be empty !!!'));
ok = false;

View File

@ -62,10 +62,14 @@ var et2_grid = et2_DOMWidget.extend([et2_IDetachedDOM, et2_IAligned, et2_IResize
*/
init: function() {
// Create the table body and the table
this.tbody = $j(document.createElement("tbody"));
this.table = $j(document.createElement("table"))
.addClass("et2_grid");
this.table.append(this.tbody);
this.thead = $j(document.createElement("thead"))
.appendTo(this.table);
this.tfoot = $j(document.createElement("tfoot"))
.appendTo(this.table);
this.tbody = $j(document.createElement("tbody"))
.appendTo(this.table);
// Call the parent constructor
this._super.apply(this, arguments);
@ -180,7 +184,7 @@ var et2_grid = et2_DOMWidget.extend([et2_IDetachedDOM, et2_IAligned, et2_IResize
colDataEntry["class"] = et2_readAttrWithDefault(node, "class", "");
colDataEntry["align"] = et2_readAttrWithDefault(node, "align", "");
colDataEntry["span"] = et2_readAttrWithDefault(node, "span", "1");
// Keep any others attributes set, there's no 'column' widget
for(var i in node.attributes)
{
@ -212,6 +216,7 @@ var et2_grid = et2_DOMWidget.extend([et2_IDetachedDOM, et2_IAligned, et2_IResize
rowDataEntry["class"] = et2_readAttrWithDefault(node, "class", "");
rowDataEntry["valign"] = et2_readAttrWithDefault(node, "valign", "");
rowDataEntry["span"] = et2_readAttrWithDefault(node, "span", "1");
rowDataEntry["part"] = et2_readAttrWithDefault(node, "part", "body");
var id = et2_readAttrWithDefault(node, "id", "");
if(id)
@ -645,7 +650,23 @@ var et2_grid = et2_DOMWidget.extend([et2_IDetachedDOM, et2_IAligned, et2_IResize
for (var y = 0; y < h; y++)
{
var row = _cells[y];
var tr = $j(document.createElement("tr")).appendTo(this.tbody)
var parent = this.tbody;
switch(this.rowData[y]["part"])
{
case 'header':
if (!this.tbody.children().length && !this.tfoot.children().length)
{
parent = this.thead;
}
break;
case 'footer':
if (!this.tbody.children().length)
{
parent = this.tfoot;
}
break;
}
var tr = $j(document.createElement("tr")).appendTo(parent)
.addClass(this.rowData[y]["class"]);
if (this.rowData[y].disabled)
@ -838,6 +859,8 @@ var et2_grid = et2_DOMWidget.extend([et2_IDetachedDOM, et2_IAligned, et2_IResize
}
}
this.managementArray = [];
this.thead.empty();
this.tfoot.empty();
this.tbody.empty();
// Update array managers
@ -982,7 +1005,7 @@ var et2_grid = et2_DOMWidget.extend([et2_IDetachedDOM, et2_IAligned, et2_IResize
}
return ids.join('_');
},
resize: function (_height)
{
if (typeof this.options != 'undefined' && _height
@ -1001,7 +1024,7 @@ var et2_grid = et2_DOMWidget.extend([et2_IDetachedDOM, et2_IAligned, et2_IResize
this.table.height(this.table.height() + _height );
}
}
}
}
});

View File

@ -149,8 +149,22 @@ var et2_number_ro = et2_textbox_ro.extend(
attributes: {
min: { ignore: true},
max: { ignore: true},
precision: { ignore: true},
precision: {
name: "Precision",
type: "integer",
default: et2_no_init,
description: "Allowed precision - # of decimal places",
ignore: true
},
value: { type: "float" }
},
set_value: function(_value)
{
if (typeof this.options.precision != 'undefined' && ""+_value != "")
{
_value = parseFloat(_value).toFixed(this.options.precision);
}
this._super.call(this, _value);
}
});
et2_register_widget(et2_number_ro, ["int_ro", "integer_ro", "float_ro"]);

View File

@ -135,7 +135,7 @@ var et2_radiobox = et2_inputWidget.extend(
return val == this.options.set_value ? this.options.set_value : null;
},
/**
* Overridden from parent so if it's required, only 1 in a group needs a value
*/
@ -143,7 +143,8 @@ var et2_radiobox = et2_inputWidget.extend(
var ok = true;
// Check for required
if(this.options && this.options.needed && !this.options.readonly && (this.getValue() == null || this.getValue().valueOf() == ''))
if (this.options && this.options.needed && !this.options.readonly && !this.disabled &&
(this.getValue() == null || this.getValue().valueOf() == ''))
{
if(jQuery.isEmptyObject(this.getInstanceManager().getValues(this.getInstanceManager().widgetContainer)[this.id.replace('[]', '')]))
{

View File

@ -120,7 +120,7 @@ var et2_template = et2_DOMWidget.extend(
}
// Read the XML structure of the requested template
this.loadFromXML(templates[template_name]);
if (typeof templates[template_name] != 'undefined') this.loadFromXML(templates[template_name]);
// Update flag
this.loading.resolve();

View File

@ -154,7 +154,7 @@ var et2_textbox = et2_inputWidget.extend([et2_IResizeable],
{
var ok = true;
// Check input is valid
if(this.options && this.options.validator && !this.options.readonly)
if(this.options && this.options.validator && !this.options.readonly && !this.disabled)
{
if (typeof this.options.validator == 'string')
{

View File

@ -0,0 +1,33 @@
<?xml version="1.0"?>
<!DOCTYPE overlay PUBLIC "-//Stylite AG//eTemplate 2//EN" "http://www.egroupware.org/etemplate2.dtd">
<!-- $Id$ -->
<overlay>
<template id="etemplate.table_test" template="" lang="" group="0" version="">
<grid id="rows" order="first" sort="asc" onsort="alert">
<columns>
<column/>
<column/>
</columns>
<rows>
<row part="header">
<description value="Header" span="all"/>
<description/>
</row>
<row part="footer">
<description value="Footer" span="all"/>
<description/>
</row>
<row class="th">
<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 class="row">
<description id="${row}[first]"/>
<description id="${row}[second]"/>
<description id="${row}[third]"/>
</row>
</rows>
</grid>
</template>
</overlay>