- added legacy-options parsing and defintions for currently implemented widgets

- added more server-side debuging:
* etemplate_widget_template class can be called via url and displays parsed xml, eg:
  http://localhost/egroupware/etemplate/inc/class.etemplate_widget_template.inc.php?name=infolog.edit
  This is different from directly calling the xet file, as it show what got parsed and how:
  http://localhost/egroupware/infolog/templates/default/edit.xet
* etemplate_new class can be called via url to render an arbitrary template, eg:
  http://localhost/egroupware/etemplate/inc/class.etemplate_new.inc.php?name=timesheet.edit
  Thought not all are already rendered correct, eg. infolog.edit is not:
  http://localhost/egroupware/etemplate/inc/class.etemplate_new.inc.php?name=infolog.edit
This commit is contained in:
Ralf Becker 2011-08-19 08:22:19 +00:00
parent 107b12abcd
commit 30ed6a8ab7
8 changed files with 249 additions and 69 deletions

View File

@ -1698,7 +1698,7 @@ class etemplate extends boetemplate
case 'vbox':
case 'hbox':
case 'groupbox':
case 'box':
case 'box': // size: num,orient,cellpadding,cellspacing,keep
$rows = array();
$box_row = 1;
$box_col = 'A';

View File

@ -11,6 +11,19 @@
* @version $Id$
*/
// allow to call direct for tests (see end of class)
if (!isset($GLOBALS['egw_info']))
{
$GLOBALS['egw_info'] = array(
'flags' => array(
'currentapp' => 'login',
'nonavbar' => true,
'debug' => 'etemplate_new',
)
);
include_once '../../header.inc.php';
}
/**
* New eTemplate serverside contains:
* - main server methods like read, exec
@ -198,8 +211,9 @@ class etemplate_new extends etemplate_widget_template
{
$this->rel_path = self::relPath($this->name=$name, $this->template_set=$template_set,
$this->version=$version, $this->laod_via = $load_via);
error_log(__METHOD__."('$name', '$template_set', '$lang', $group, '$version', '$load_via') rel_path=".array2string($this->rel_path));
return (boolean)$this->real_path;
return (boolean)$this->rel_path;
}
/**
@ -390,4 +404,30 @@ class etemplate_new extends etemplate_widget_template
}
return $old;
}
/**
* Debug callback just outputting content
*
* @param array $content=null
*/
public function debug(array $content=null)
{
common::egw_header();
_debug_array($content);
common::egw_footer();
}
}
if ($GLOBALS['egw_info']['flags']['debug'] == 'etemplate_new')
{
$name = isset($_GET['name']) ? $_GET['name'] : 'timesheet.edit';
$template = new etemplate_new();
if (!$template->read($name))
{
header('HTTP-Status: 404 Not Found');
echo "<html><head><title>Not Found</title><body><h1>Not Found</h1><p>The requested eTemplate '$name' was not found!</p></body></html>\n";
exit;
}
$GLOBALS['egw_info']['flags']['app_header'] = $name;
$template->exec('etemplate.etemplate.debug', array(), array(), array(), array(), 2);
}

View File

@ -53,6 +53,13 @@ class etemplate_widget
*/
protected $children = array();
/**
* (Array of) comma-separated list of legacy options to automatically replace when parsing with set_attrs
*
* @var string|array
*/
protected $legacy_options;
/**
* Request object of the currently created request
*
@ -132,6 +139,17 @@ class etemplate_widget
{
$reader = self::get_reader($xml);
// check if we have to split legacy options (can be by type)
$legacy_options = $this->legacy_options;
if (is_array($legacy_options))
{
if (!($type = $reader->getAttribute('type')))
{
$type = $this->type;
}
$legacy_options = $legacy_options[$type];
}
// read and set all attributes
$template = $this;
while($reader->moveToNextAttribute())
@ -140,11 +158,66 @@ class etemplate_widget
{
if (!$cloned) $template = clone($this);
$template->attrs[$reader->name] = $reader->value;
// split legacy options
if ($legacy_options && $reader->name == 'options')
{
$legacy_options = explode(',', $legacy_options);
foreach(self::csv_split($reader->value, count($legacy_options)) as $n => $val)
{
if ($legacy_options[$n] && (string)$val !== '') $template->attrs[$legacy_options[$n]] = $val;
}
}
}
}
return $template;
}
/**
* Split a $delimiter-separated options string, which can contain parts with delimiters enclosed in $enclosure
*
* Examples:
* - csv_split('"1,2,3",2,3') === array('1,2,3','2','3')
* - csv_split('1,2,3',2) === array('1','2,3')
* - csv_split('"1,2,3",2,3',2) === array('1,2,3','2,3')
* - csv_split('"a""b,c",d') === array('a"b,c','d') // to escape enclosures double them!
*
* @param string $str
* @param int $num=null in how many parts to split maximal, parts over this number end up (unseparated) in the last part
* @param string $delimiter=','
* @param string $enclosure='"'
* @return array
*/
public static function csv_split($str,$num=null,$delimiter=',',$enclosure='"')
{
if (strpos($str,$enclosure) === false)
{
return is_null($num) ? explode($delimiter,$str) : explode($delimiter,$str,$num); // no need to run this more expensive code
}
$parts = explode($delimiter,$str);
for($n = 0; isset($parts[$n]); ++$n)
{
$part =& $parts[$n];
if ($part[0] === $enclosure)
{
while (isset($parts[$n+1]) && substr($part,-1) !== $enclosure)
{
$part .= $delimiter.$parts[++$n];
unset($parts[$n]);
}
$part = substr(str_replace($enclosure.$enclosure,$enclosure,$part),1,-1);
}
}
$parts = array_values($parts); // renumber the parts (in case we had to concat them)
if ($num > 0 && count($parts) > $num)
{
$parts[$num-1] = implode($delimiter,array_slice($parts,$num-1,count($parts)-$num+1));
$parts = array_slice($parts,0,$num);
}
return $parts;
}
/**
* Registry of classes implementing widgets
*
@ -249,7 +322,7 @@ class etemplate_widget
*/
public function __toString()
{
return $this->type.'#'.$this->id;
return $this->type.($this->attrs['type'] && $this->attrs['type'] != $this->type ? '('.$this->attrs['type'].')' : '').'#'.$this->id;
}
/**
@ -264,6 +337,11 @@ class etemplate_widget
if ($this->id) echo ' id="'.htmlspecialchars($this->id).'"';
foreach($this->attrs as $name => $value)
{
if ($name == 'options' && $this->legacy_options && (!is_array($this->legacy_options) ||
isset($this->legacy_options[$this->attrs['type'] ? $this->attrs['type'] : $this->type])))
{
continue; // do NOT output already converted legacy options
}
echo ' '.$name.'="'.htmlspecialchars($value).'"';
}
echo ' php-class="'.get_class($this).'"';
@ -431,6 +509,19 @@ class etemplate_widget
*/
class etemplate_widget_named extends etemplate_widget
{
/**
* (Array of) comma-separated list of legacy options to automatically replace when parsing with set_attrs
*
* @var string|array
*/
protected $legacy_options = array(
'box' => ',cellpadding,cellspacing,keep',
'hbox' => 'cellpadding,cellspacing,keep',
'vbox' => 'cellpadding,cellspacing,keep',
'groupbox' => 'cellpadding,cellspacing,keep',
'grid' => null, // not used
);
/**
* Validate input
*
@ -450,3 +541,18 @@ class etemplate_widget_named extends etemplate_widget
}
// register class for layout widgets, which can have an own namespace
etemplate_widget::registerWidget('etemplate_widget_named', array('grid', 'box', 'hbox', 'vbox', 'groupbox'));
/**
* Describtion widget
*
* Reimplemented to set legacy options
*/
class etemplate_widget_description extends etemplate_widget
{
/**
* (Array of) comma-separated list of legacy options to automatically replace when parsing with set_attrs
*
* @var string|array
*/
protected $legacy_options = 'bold-italic,link,activate_links,label_for,link_target,link_popup_size,link_title';
}

View File

@ -17,6 +17,7 @@ if (!isset($GLOBALS['egw_info']))
$GLOBALS['egw_info'] = array(
'flags' => array(
'currentapp' => 'login',
'debug' => 'etemplate_widget_template',
)
);
include_once '../../header.inc.php';
@ -114,6 +115,7 @@ class etemplate_widget_template extends etemplate_widget
* @param array &$validated=array() validated content
* @param string $cname='' current namespace
* @return boolean true if no validation error, false otherwise
* @todo handle template references containing content in id, eg. id="edit.$cont[something]"
*/
public function validate(array $content, &$validated=array(), $cname = '')
{
@ -123,9 +125,15 @@ class etemplate_widget_template extends etemplate_widget
}
}
if ($GLOBALS['egw_info']['flags']['currentapp'] == 'login')
if ($GLOBALS['egw_info']['flags']['debug'] == 'etemplate_widget_template')
{
$template = etemplate_widget_template::instance('timesheet.edit');
$name = isset($_GET['name']) ? $_GET['name'] : 'timesheet.edit';
if (!($template = etemplate_widget_template::instance($name)))
{
header('HTTP-Status: 404 Not Found');
echo "<html><head><title>Not Found</title><body><h1>Not Found</h1><p>The requested eTemplate '$name' was not found!</p></body></html>\n";
exit;
}
header('Content-Type: text/xml');
echo $template->toXml();
}

View File

@ -13,8 +13,8 @@
/**
* eTemplate textbox widget with following sub-types:
* - textbox optional multiline="true" and rows="123"
* - int
* - textbox with optional multiline="true" and rows="123"
* - integer or int
* - float
* - hidden
* - colorpicker
@ -22,6 +22,26 @@
*/
class etemplate_widget_textbox extends etemplate_widget
{
/**
* Constructor
*
* @param string|XMLReader $xml string with xml or XMLReader positioned on the element to construct
* @throws egw_exception_wrong_parameter
*/
public function __construct($xml)
{
parent::__construct($xml);
// normalize types
if ($this->type !== 'textbox')
{
if ($this->type == 'int') $this->type = 'integer';
$this->attrs['type'] = $this->type;
$this->type = 'textbox';
}
}
/**
* Validate input
*
@ -40,14 +60,13 @@ class etemplate_widget_textbox extends etemplate_widget
public function validate(array $content, &$validated=array(), $cname = '')
{
$ok = true;
$type = isset($this->attrs['type']) ? $this->attrs['type'] : $this->type;
if (!$this->is_readonly($cname))
{
if (!isset($this->attrs['preg']))
{
switch($type)
switch($this->type)
{
case 'int':
case 'integer':
$this->attrs['preg'] = '/^-?[0-9]*$/';
break;
case 'float':
@ -74,9 +93,9 @@ class etemplate_widget_textbox extends etemplate_widget
}
if ($this->attrs['preg'] && !preg_match($this->attrs['preg'],$value))
{
switch($type)
switch($this->type)
{
case 'int':
case 'integer':
self::set_validation_error($form_name,lang("'%1' is not a valid integer !!!",$value),'');
break;
case 'float':
@ -88,22 +107,22 @@ class etemplate_widget_textbox extends etemplate_widget
}
$ok = false;
}
elseif ($type == 'int' || $type == 'float') // cast int and float and check range
elseif ($this->type == 'integer' || $this->type == 'float') // cast int and float and check range
{
if ((string)$value !== '' || $this->attrs['needed']) // empty values are Ok if needed is not set
{
$value = $type == 'int' ? (int) $value : (float) str_replace(',','.',$value); // allow for german (and maybe other) format
$value = $this->type == 'integer' ? (int) $value : (float) str_replace(',','.',$value); // allow for german (and maybe other) format
if (!empty($this->attrs['min']) && $value < $this->attrs['min'])
{
self::set_validation_error($form_name,lang("Value has to be at least '%1' !!!",$this->attrs['min']),'');
$value = $type == 'int' ? (int) $this->attrs['min'] : (float) $this->attrs['min'];
$value = $this->type == 'integer' ? (int) $this->attrs['min'] : (float) $this->attrs['min'];
$ok = false;
}
if (!empty($this->attrs['max']) && $value > $this->attrs['max'])
{
self::set_validation_error($form_name,lang("Value has to be at maximum '%1' !!!",$this->attrs['max']),'');
$value = $type == 'int' ? (int) $this->attrs['max'] : (float) $this->attrs['max'];
$value = $this->type == 'integer' ? (int) $this->attrs['max'] : (float) $this->attrs['max'];
$ok = false;
}
}
@ -113,4 +132,4 @@ class etemplate_widget_textbox extends etemplate_widget
return parent::validate($content, $validated, $cname) && $ok;
}
}
etemplate_widget::registerWidget('etemplate_widget_textbox', array('textbox','int','float','passwd','hidden','colorpicker'));
etemplate_widget::registerWidget('etemplate_widget_textbox', array('textbox','int','integer','float','passwd','hidden','colorpicker'));

View File

@ -51,7 +51,7 @@ class xul_io
var $widget2xul = array(
'label' => array(
'.name' => 'description',
'label' => 'value'
'label' => 'value',
),
'text' => array(
'.name' => 'textbox',
@ -65,12 +65,17 @@ class xul_io
'integer' => array(
'.name' => 'textbox',
'.set' => 'type=integer',
'size' => 'min,max,size'
'size' => 'min,max,size,precision,step'
),
'int' => array(
'.name' => 'textbox',
'.set' => 'type=integer',
'size' => 'min,max,size,precision,step'
),
'float' => array(
'.name' => 'textbox',
'.set' => 'type=float',
'size' => 'min,max,size,precision'
'size' => 'min,max,size,precision,step'
),
'select' => array(
'.name' => 'menulist,menupopup',

View File

@ -2,7 +2,7 @@
/**
* EGroupware - eTemplates for Application etemplate
* http://www.egroupware.org
* generated by soetemplate::dump4setup() 2011-07-12 11:52
* generated by soetemplate::dump4setup() 2011-08-19 09:30
*
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package etemplate
@ -183,6 +183,8 @@ $templ_data[] = array('name' => 'etemplate.test.duration','template' => '','lang
$templ_data[] = array('name' => 'etemplate.test.grid-export','template' => '','lang' => '','group' => '0','version' => '2','data' => 'a:1:{i:0;a:5:{s:4:"type";s:4:"grid";s:4:"data";a:3:{i:0;a:0:{}i:1;a:1:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:5:"label";s:9:"some cell";}}i:2;a:1:{s:1:"A";a:6:{s:5:"class";s:9:"hboxClass";s:4:"type";s:4:"hbox";s:4:"size";s:1:"3";i:1;a:3:{s:4:"size";s:1:"1";s:4:"type";s:5:"label";s:5:"label";s:2:"1.";}i:2;a:2:{s:4:"type";s:5:"label";s:5:"label";s:2:"2.";}i:3;a:3:{s:5:"align";s:5:"right";s:4:"type";s:5:"label";s:5:"label";s:10:"last right";}}}}s:4:"cols";i:1;s:4:"rows";i:2;s:4:"size";s:16:"100%,,,gridClass";}}','size' => '100%,,,gridClass','style' => '','modified' => '1179507244',);
$templ_data[] = array('name' => 'etemplate.test.html','template' => '','lang' => '','group' => '0','version' => '','data' => 'a:1:{i:0;a:4:{s:4:"type";s:4:"grid";s:4:"data";a:2:{i:0;a:0:{}i:1;a:1:{s:1:"A";a:2:{s:4:"type";s:8:"htmlarea";s:4:"name";s:4:"test";}}}s:4:"rows";i:1;s:4:"cols";i:1;}}','size' => '','style' => '','modified' => '1313581424',);
$templ_data[] = array('name' => 'etemplate.test.infolog','template' => '','lang' => '','group' => '0','version' => '','data' => 'a:1:{i:0;a:4:{s:4:"type";s:4:"grid";s:4:"data";a:2:{i:0;a:0:{}i:1;a:1:{s:1:"A";a:3:{s:4:"type";s:13:"infolog-value";s:4:"name";s:4:"test";s:7:"options";a:0:{}}}}s:4:"rows";i:1;s:4:"cols";i:1;}}','size' => '','style' => '','modified' => '1242560130',);
$templ_data[] = array('name' => 'etemplate.test.required','template' => '','lang' => '','group' => '0','version' => '','data' => 'a:1:{i:0;a:4:{s:4:"type";s:4:"grid";s:4:"data";a:6:{i:0;a:0:{}i:1;a:2:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:5:"label";s:4:"Text";}s:1:"B";a:3:{s:4:"type";s:4:"text";s:4:"name";s:4:"text";s:6:"needed";s:1:"1";}}i:2;a:2:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:5:"label";s:4:"File";}s:1:"B";a:3:{s:4:"type";s:4:"file";s:4:"name";s:4:"file";s:6:"needed";s:1:"1";}}i:3;a:2:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:5:"label";s:8:"Checkbox";}s:1:"B";a:4:{s:4:"type";s:8:"checkbox";s:5:"label";s:22:"Gelesen und verstanden";s:4:"name";s:5:"check";s:6:"needed";s:1:"1";}}i:4;a:2:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:5:"label";s:6:"Radios";}s:1:"B";a:4:{s:4:"type";s:4:"hbox";s:4:"size";s:1:"2";i:1;a:5:{s:4:"type";s:5:"radio";s:4:"size";s:3:"one";s:5:"label";s:3:"One";s:4:"name";s:5:"radio";s:6:"needed";s:1:"1";}i:2;a:5:{s:4:"type";s:5:"radio";s:4:"name";s:5:"radio";s:4:"size";s:3:"two";s:5:"label";s:3:"Two";s:6:"needed";s:1:"1";}}}i:5;a:2:{s:1:"A";a:2:{s:4:"type";s:6:"button";s:5:"label";s:6:"Submit";}s:1:"B";a:1:{s:4:"type";s:5:"label";}}}s:4:"rows";i:5;s:4:"cols";i:2;}}','size' => '','style' => '','modified' => '1279699676',);

View File

@ -13,44 +13,44 @@
</columns>
<rows>
<row class="row">
<description options=",,,type" value="Type"/>
<description value="Type" options=",,,type"/>
<menulist>
<menupopup id="type" onchange="1" statustext="type of the field (select Label if field should be empty)"/>
<menupopup statustext="type of the field (select Label if field should be empty)" id="type" onchange="1"/>
</menulist>
<description options=",,,size" value="Options" align="center"/>
<textbox size="10" id="size" statustext="Label:[bold][italic] Text:[len][,max] Numbers:[min][,[max][,len]] T.area:[rows][,cols] Radiob.:value H.Rule:[width] Templ.:[IndexInContent] Select:[multiselect] Date:[values: eg. 'Y-m-d']"/>
<description options=",,,span" value="Span, Class" align="center"/>
<textbox size="10" id="span" statustext="number of colums the field/cell should span or 'all' for the remaining columns, CSS-class name (for the TD tag)"/>
<description align="center" value="Options" options=",,,size"/>
<textbox statustext="Label:[bold][italic] Text:[len][,max] Numbers:[min][,[max][,len]] T.area:[rows][,cols] Radiob.:value H.Rule:[width] Templ.:[IndexInContent] Select:[multiselect] Date:[values: eg. 'Y-m-d']" id="size" size="10"/>
<description align="center" value="Span, Class" options=",,,span"/>
<textbox statustext="number of colums the field/cell should span or 'all' for the remaining columns, CSS-class name (for the TD tag)" id="span" size="10"/>
</row>
<row class="row">
<description options=",,,label" value="Label"/>
<textbox id="label" statustext="displayed in front of input or input is inserted for a '%s' in the label (label of the Submitbutton or Image-filename)"/>
<checkbox span="2" label="%s NoTranslation" align="center" id="no_lang" statustext="select if content of field should not be translated (label gets always translated)"/>
<description value="Align" align="center"/>
<description value="Label" options=",,,label"/>
<textbox statustext="displayed in front of input or input is inserted for a '%s' in the label (label of the Submitbutton or Image-filename)" id="label"/>
<checkbox align="center" statustext="select if content of field should not be translated (label gets always translated)" label="%s NoTranslation" id="no_lang" span="2"/>
<description align="center" value="Align"/>
<menulist>
<menupopup id="align" statustext="alignment of label and input-field in table-cell"/>
<menupopup statustext="alignment of label and input-field in table-cell" id="align"/>
</menulist>
</row>
<row class="row">
<description options=",,,name" value="Name"/>
<textbox id="name" statustext="index/name of returned content (name of the Template, Link / Method for Image)"/>
<description value="Name" options=",,,name"/>
<textbox statustext="index/name of returned content (name of the Template, Link / Method for Image)" id="name"/>
<hbox span="4">
<checkbox label="%s needed" align="center" id="needed" statustext="check if field has to be filled by user"/>
<checkbox label="%s readonly" align="center" id="readonly" statustext="check if content should only be displayed but not altered (the content is not send back then!)"/>
<checkbox label="%s disabled" align="center" id="disabled" statustext="if field is disabled an empty table-cell is displayed, for (temporal) removement of a field/cell"/>
<checkbox align="center" statustext="check if field has to be filled by user" label="%s needed" id="needed"/>
<checkbox align="center" statustext="check if content should only be displayed but not altered (the content is not send back then!)" label="%s readonly" id="readonly"/>
<checkbox align="center" statustext="if field is disabled an empty table-cell is displayed, for (temporal) removement of a field/cell" label="%s disabled" id="disabled"/>
</hbox>
</row>
<row class="row" disabled="@type=label">
<description options=",,,blur" value="blurText"/>
<textbox id="blur" statustext="this text gets displayed if the input-field is empty and has no focus (blur)"/>
<description value="blurText" options=",,,blur"/>
<textbox statustext="this text gets displayed if the input-field is empty and has no focus (blur)" id="blur"/>
<hbox span="4">
<int label="Tabindex" span="2" id="tabindex" statustext="Order to navigating by tab key through the form"/>
<textbox size="1" maxlength="1" id="accesskey" statustext="Accesskeys can also be specified with an &amp; in the label (eg. &amp;Name)" label="Accesskey"/>
<textbox type="integer" statustext="Order to navigating by tab key through the form" label="Tabindex" id="tabindex" span="2"/>
<textbox statustext="Accesskeys can also be specified with an &amp; in the label (eg. &amp;Name)" label="Accesskey" id="accesskey" size="1" maxlength="1"/>
</hbox>
</row>
<row class="row">
<description options=",,,help" value="Help"/>
<textbox size="71" span="all" class="inputFullWidth" id="help" statustext="displayed in statusline of browser if input-field gets focus"/>
<description value="Help" options=",,,help"/>
<textbox statustext="displayed in statusline of browser if input-field gets focus" id="help" size="71" span="all" class="inputFullWidth"/>
<description/>
<description/>
<description/>
@ -60,18 +60,18 @@
<description value="onChange"/>
<hbox options="0,0" span="all">
<menulist>
<menupopup id="onchange_type" statustext="Should the form be submitted or any custom javascript be executed"/>
<menupopup statustext="Should the form be submitted or any custom javascript be executed" id="onchange_type"/>
</menulist>
<textbox size="50" span="all" class="leftPad5 inputFullWidth" id="onchange" statustext="custom javascript for onChange" align="right"/>
<textbox align="right" statustext="custom javascript for onChange" id="onchange" size="50" span="all" class="leftPad5 inputFullWidth"/>
</hbox>
</row>
<row class="row">
<description options="onclick" value="onClick"/>
<description value="onClick" options="onclick"/>
<hbox options="0,0" span="all">
<menulist>
<menupopup id="onclick_type" statustext="confirmation necesary or custom java-script"/>
<menupopup statustext="confirmation necesary or custom java-script" id="onclick_type"/>
</menulist>
<textbox size="53" span="all" class="leftPad5 inputFullWidth" id="onclick" statustext="confirmation message or custom javascript (returning true or false)" align="right"/>
<textbox align="right" statustext="confirmation message or custom javascript (returning true or false)" id="onclick" size="53" span="all" class="leftPad5 inputFullWidth"/>
</hbox>
</row>
</rows>
@ -87,21 +87,21 @@
<row class="th">
<hbox span="all">
<menulist>
<menupopup options="Edit..." id="edit_menu" onchange="1" statustext="delete and cut save the template!"/>
<menupopup statustext="delete and cut save the template!" id="edit_menu" onchange="1" options="Edit..."/>
</menulist>
<menulist>
<menupopup options="Box..." id="box_menu" onchange="1" statustext="all operations save the template!"/>
<menupopup statustext="all operations save the template!" id="box_menu" onchange="1" options="Box..."/>
</menulist>
<menulist>
<menupopup options="Row..." id="row_menu" onchange="1" statustext="all operations save the template!"/>
<menupopup statustext="all operations save the template!" id="row_menu" onchange="1" options="Row..."/>
</menulist>
<menulist>
<menupopup options="Column..." id="column_menu" onchange="1" statustext="all operations save the template!"/>
<menupopup statustext="all operations save the template!" id="column_menu" onchange="1" options="Column..."/>
</menulist>
</hbox>
</row>
<row disabled="!@msg">
<description span="all" class="redItalic" no_lang="1" id="msg"/>
<description id="msg" no_lang="1" span="all" class="redItalic"/>
</row>
<row>
<html label="Name" id="java_script"/>
@ -109,46 +109,46 @@
<textbox id="name" readonly="true"/>
<textbox id="template" readonly="true"/>
<textbox id="lang" readonly="true"/>
<textbox size="20" label="Version" id="version" statustext="increment version to not overwrite the existing template"/>
<description class="gray" value="Path" no_lang="1" id="path"/>
<textbox statustext="increment version to not overwrite the existing template" label="Version" id="version" size="20"/>
<description value="Path" id="path" no_lang="1" class="gray"/>
</hbox>
</row>
<row>
<description options=",,,goto" value="Path"/>
<description value="Path" options=",,,goto"/>
<hbox>
<path no_lang="1" id="goto" statustext="switch to a parent widget"/>
<path options=" " label=" " no_lang="1" id="goto2" statustext="switch to an other widgets of that container"/>
<path statustext="switch to a parent widget" id="goto" no_lang="1"/>
<path statustext="switch to an other widgets of that container" label=" " id="goto2" no_lang="1" options=" "/>
</hbox>
</row>
<row>
<template content="cell" span="all" id="etemplate.editor.widget.generic"/>
<template id="etemplate.editor.widget.generic" content="cell" span="all"/>
</row>
<row disabled="!@grid_row">
<groupbox span="all" orient="horizontal">
<caption label="Grid row attributes"/>
<textbox size="5" label="Height" id="grid_row[height]" statustext="height of row (in % or pixel)"/>
<textbox size="10" label="Disabled" id="grid_row[disabled]" statustext="to disable: [! = not]&lt;value&gt;[=&lt;check&gt;] eg: '!@data' disables if content of data is empty"/>
<textbox size="10" label="Class" id="grid_row[class]" statustext="CSS-class name for this row, preset: 'th' = header, 'row' = alternating row, 'row_off'+'row_on' rows"/>
<textbox statustext="height of row (in % or pixel)" label="Height" id="grid_row[height]" size="5"/>
<textbox statustext="to disable: [! = not]&lt;value&gt;[=&lt;check&gt;] eg: '!@data' disables if content of data is empty" label="Disabled" id="grid_row[disabled]" size="10"/>
<textbox statustext="CSS-class name for this row, preset: 'th' = header, 'row' = alternating row, 'row_off'+'row_on' rows" label="Class" id="grid_row[class]" size="10"/>
<menulist>
<menupopup label="Valign" id="grid_row[valign]" statustext="vertical alignment of row"/>
<menupopup statustext="vertical alignment of row" label="Valign" id="grid_row[valign]"/>
</menulist>
<menulist>
<menupopup label="Part" id="grid_row[part]" statustext="part of the table (header and footer have to be before body!)"/>
<menupopup statustext="part of the table (header and footer have to be before body!)" label="Part" id="grid_row[part]"/>
</menulist>
</groupbox>
</row>
<row disabled="!@grid_column">
<groupbox span="all" orient="horizontal">
<caption label="Grid column attributes"/>
<textbox size="5" label="Width" id="grid_column[width]" statustext="width of column (in % or pixel)"/>
<textbox size="10" label="Disabled" id="grid_column[disabled]" statustext="to disable: [! = not]&lt;value&gt;[=&lt;check&gt;] eg: '!@data' disables if content of data is empty"/>
<textbox statustext="width of column (in % or pixel)" label="Width" id="grid_column[width]" size="5"/>
<textbox statustext="to disable: [! = not]&lt;value&gt;[=&lt;check&gt;] eg: '!@data' disables if content of data is empty" label="Disabled" id="grid_column[disabled]" size="10"/>
</groupbox>
</row>
<row>
<hbox span="all">
<button label="Save" id="save" statustext="saves the template with given version number and closes the window"/>
<button label="Apply" id="apply" statustext="applies the changes to the given version of the template"/>
<button label="Cancel" id="cancel" statustext="closes the window without saving the changes" onclick="window.close();"/>
<button statustext="saves the template with given version number and closes the window" label="Save" id="save"/>
<button statustext="applies the changes to the given version of the template" label="Apply" id="apply"/>
<button statustext="closes the window without saving the changes" label="Cancel" id="cancel" onclick="window.close();"/>
</hbox>
</row>
</rows>