mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-11-25 01:13:25 +01:00
ability to specify plugins for htmlarea
This commit is contained in:
parent
efdf383dc4
commit
1d5a9f0954
858
etemplate/doc/referenz.html
Normal file
858
etemplate/doc/referenz.html
Normal file
@ -0,0 +1,858 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>eGroupWare: eTemplate-Referenz</title>
|
||||
<!-- $Id$ -->
|
||||
<STYLE type="text/css">
|
||||
<!--
|
||||
pre { font-family: monospace; background-color: #e0e0e0; padding: 2mm; border-width: thin; border-style: solid; border-color: black; white-space: pre; }
|
||||
span { color: darkblue; font-family: sans-serife; }
|
||||
li { margin-top: 5px; }
|
||||
body { background-color: white; color: black; }
|
||||
-->
|
||||
</STYLE>
|
||||
</head>
|
||||
<body>
|
||||
<h1>eTemplate-Referenz - Templates and Dialog-Editor for eGroupWare</h1>
|
||||
<h3>by Ralf Becker <a href="#" onClick="document.location='mai'+'lto:RalfBecker'+unescape('%40')+'outdoor-training'+unescape('%2E')+'de'; return false;">RalfBecker AT outdoor-training DOT de</a></h3>
|
||||
<p>A referenz documentation about the new eTemplates and the <a href="#referenz">syntax and parameters</a>
|
||||
of the several widgets.</p>
|
||||
<hr>
|
||||
<h1>Introduction - The concept of the eTemplates</h1>
|
||||
<p>As I already covered this in the <a href="etemplate.html">Tutorial</a>, I like would suggest to have a look
|
||||
there if your are not familiar with the overal concept.</p>
|
||||
<p>There are two possibilities now to create an eTemplate:</p>
|
||||
<ol>
|
||||
<li>Use the eTemplate-Editor (as descript in the <a href="etemplate.html">Tutorial</a>) to interactivly
|
||||
design your template.
|
||||
<li>Write a xml-file in a Syntax similar to XUL (the mozilla UI-interface definition language) and import
|
||||
it into the database with the eTemplate-Editor
|
||||
</ol>
|
||||
<hr>
|
||||
<h1>The xml-interface to the eTemplates</h1>
|
||||
<p>The eTemplates-Editor can import and export now eTemplates as xml-files. Here is short example showing
|
||||
an eTemplate from the example app in the <a href="etemplate.html">Tutorial</a>
|
||||
(here are screenshots of the template in the <a href="editor.gif">editor</a> and the
|
||||
<a href="show.gif">show-function</a>):</p>
|
||||
<pre>
|
||||
<?xml version="1.0"?>
|
||||
<span><!-- $Id$ --></span>
|
||||
<overlay>
|
||||
<grid id="et_media.edit" template="" lang="" group="" version="" width="100%">
|
||||
<columns>
|
||||
<column/>
|
||||
<column/>
|
||||
<column/>
|
||||
<column/>
|
||||
</columns>
|
||||
<rows>
|
||||
<row>
|
||||
<description options="ib" span="all" value="eTemplates MediaDB" no_lang="1" id="msg"/>
|
||||
</row>
|
||||
<row>
|
||||
<hrule span="all"/>
|
||||
</row>
|
||||
<row>
|
||||
<description span="all"/>
|
||||
</row>
|
||||
<row>
|
||||
<description value="Name"/>
|
||||
<textbox size="100" maxlength="100" span="all" id="name" statustext="here goes the name of the publication / record"/>
|
||||
</row>
|
||||
<row>
|
||||
<description value="Author"/>
|
||||
<textbox size="100" maxlength="100" span="all" id="author" statustext="please use Name, First Name"/>
|
||||
</row>
|
||||
<row>
|
||||
<description value="Type"/>
|
||||
<menulist span="all" statustext="select the type fitting most">
|
||||
<menupopup id="type"/>
|
||||
</menulist>
|
||||
</row>
|
||||
<row>
|
||||
<description value="Description"/>
|
||||
<textbox ="" cols="3" rows="100" span="all" id="descr" statustext="we have a fulltext search using that description"/>
|
||||
</row>
|
||||
<row>
|
||||
<description span="all"/>
|
||||
</row>
|
||||
<row>
|
||||
<button label="Read" id="read" statustext="reads or searches for entries matching the criteria above"/>
|
||||
<button label="Save" id="save" statustext="saves the change to the db"/>
|
||||
<button label="Cancel" id="cancel" statustext="clears the form, without changing anything"/>
|
||||
<button label="Delete" id="delete" statustext="deletes an entry"/>
|
||||
</row>
|
||||
</rows>
|
||||
</grid>
|
||||
</overlay>
|
||||
</pre>
|
||||
<p>The tags / widget-names and attributes / parameters used are as close as possible to XUL. For more
|
||||
information about XUL refer to <a href="http://www.xulplanet.com">www.xulplanet.com</a> or the Mozilla docs
|
||||
<a href="http://www.mozilla.org/xpfe/xulref/">www.mozilla.org/xpfe/xulref/</a>.</p>
|
||||
<p>Please keep in mind that the xml-files used to store the eTemplates are only similar to XUL and
|
||||
implement only a subset of XUL. Here are the main differences:</p>
|
||||
<ul>
|
||||
<li>only certain widgets and widget attributes are implemented
|
||||
<li>xul-files can contain the actual content or refer to it via a datasources (RDF's) and use a
|
||||
different template syntax to fill in content from a variable: <label value="?label"/><br>
|
||||
eTemplates get there content from an array passed to the exec or show-function of the template-object
|
||||
and referenz to the content by the id / name-field of each widget.
|
||||
<li>xul-files can contain an unlimited number of nested elements, where as the eTemplates xml-root-node
|
||||
has to be a xul-grid and can not contain other grids as element (vbox and hbox are Ok).
|
||||
<i>This limitation might be removed in the near future, for now you have to use the non-xul-element
|
||||
<template id="app.template_name"/> us load an other template by its name.</i>
|
||||
</ul>
|
||||
<p>Like XUL the eTemplate-xml-files are quite strict with the xml-syntax:</p>
|
||||
<ul>
|
||||
<li>All tags and attributes must be written in lowercase
|
||||
<li>All strings must be double quoted, like id="string"
|
||||
<li>Every XUL widget must use close tags (either <tag></tag> or <tag/>) to be well-formed
|
||||
<li>All attributes must have a value, no <tag attr> it has to be <tag attr="">
|
||||
</ul>
|
||||
<hr>
|
||||
<a name="referenz"></a>
|
||||
<h1>Syntax and Parameter Referenz</h1>
|
||||
<h2>Standard parametes / attributes for <a href="#widgets">all widgets</a></h2>
|
||||
<table border=1>
|
||||
<tr>
|
||||
<th>Name in Editor</th>
|
||||
<th>xml attr</th>
|
||||
<th>xul</th>
|
||||
<th>internal name</th>
|
||||
<th>description of the attribut<th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Type</b></td>
|
||||
<td>type<br><i>(only for<br>sub-types)</td>
|
||||
<td>no</td>
|
||||
<td>type</td>
|
||||
<td>
|
||||
The type of the widget is stored in the tag itself, some widgets have sub-types (unknow to XUL).
|
||||
In that case the subtype is stored in the type attribut.<br>
|
||||
The Type / tag has to be either the name of a standard eTemplate-widget or of
|
||||
an already existing <a href="#extensions">extension</a>.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Name</b></td>
|
||||
<td>id</td>
|
||||
<td>yes</td>
|
||||
<td>name</td>
|
||||
<td>
|
||||
A string to locate the content for the widget in the content array (index) to show the dialog
|
||||
and for the returned content.
|
||||
Can be left blank or be obmitted as xml-attribut if the widget needs no content.<p>
|
||||
The name can contain the following variables, which gets expanded before they are used as
|
||||
array index (for an example see the <a href="etemplate.html">Tutorial</a>):<br>
|
||||
<table>
|
||||
<tr>
|
||||
<td><b>$c</b></td>
|
||||
<td>the column-number (starting with 0, if you have a header, data-cells start at 1)</td>
|
||||
</tr><tr>
|
||||
<td><b>$col</b></td>
|
||||
<td>the column-letter: 'A', 'B', 'C', ...</td>
|
||||
</tr><tr>
|
||||
<td><b>$row</b></td>
|
||||
<td>the row-number (starting with 0, if you have a header, data-cells start at 1)</td>
|
||||
</tr><tr>
|
||||
<td><b>$cont</b></td>
|
||||
<td>the content-array the (sub-)template, on auto-repeated row's this could eg. be
|
||||
used to generate button-names with id-values in it: "del[$cont[id]]" expands to "del[123]",
|
||||
if $cont = array('id' => 123)</td>
|
||||
</tr><tr>
|
||||
<td><b>$row_cont</b></td>
|
||||
<td>the sub-array indexed by $row of the content-array, on auto-repeated row's this could eg. be
|
||||
used to generate button-names with id-values in it: "del[$row_cont[id]]" expands to "del[123]",
|
||||
if $cont = array('1' => array('id' => 123),'2' => array('id' => 456)) and $row = 1</td>
|
||||
</tr><tr>
|
||||
<td><b>$c_<br>$col_<br>$row_</b></td>
|
||||
<td>are the respective values of the previous template-inclusion,
|
||||
eg. the column-headers in the eTemplate-editor are templates itself,
|
||||
to show the column-name in the header you can not use $col as it will
|
||||
be constant as it is always the same col in the header-template,
|
||||
what you want is the value of the previous template-inclusion.</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Label</b></td>
|
||||
<td>label</td>
|
||||
<td>no</td>
|
||||
<td>label</td>
|
||||
<td>
|
||||
The label is displayed by default in front (for radiobuttons behind) each widget (if not empty).
|
||||
If you want to specify a different position, use a '%s' in the label, which gets replaced by
|
||||
the widget itself. Eg. '%s Name' to have the label Name behind a checkbox.
|
||||
The label can contain variables, as descript for name.
|
||||
If the label starts with a '@' it is replaced by the value of the content-array at this
|
||||
index (with the '@'-removed and after expanding the variables).<br>
|
||||
<b>Note</b>: The label gets always translated, if its longer than 1 char! If this is not
|
||||
disired, use a label widget, place the not-to-translate label in the content-array
|
||||
<u>and</u> check NoTranslation or set the xml attribute no_lang.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Help</b></td>
|
||||
<td>statustext</td>
|
||||
<td>yes</td>
|
||||
<td>help</td>
|
||||
<td>
|
||||
This text / help-message is displayed in the status-bar of the browser when the widget gets focus
|
||||
(or as tooltip for buttons or general in gtk).
|
||||
If the user has JavaScript switched off, the help-texts get NOT submitted, as this is detected.
|
||||
If the helptext starts with a '@' it is replaced by the value of the content-array at this
|
||||
index (with the '@'-removed).
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Options</b></td>
|
||||
<td>?</td>
|
||||
<td>?</td>
|
||||
<td>size</td>
|
||||
<td>
|
||||
This attribute controls certain aspects of the different widgets. It's meaning and xml / xul-values
|
||||
are document with the widgets.
|
||||
If the options-string starts with a '@' it is replaced by the value of the content-array at this
|
||||
index (with the '@'-removed).
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>NoTranslation</b></td>
|
||||
<td>no_lang</td>
|
||||
<td>no</td>
|
||||
<td>no_lang</td>
|
||||
<td>
|
||||
If checked the content of the widget and the label gets NOT translated.<br>
|
||||
The helptext of a widget is always translated.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>needed</b></td>
|
||||
<td>needed</td>
|
||||
<td>no</td>
|
||||
<td>needed</td>
|
||||
<td>
|
||||
If checked (xml-attr: needed="1") the etemplates will reprompt the user if he left
|
||||
the widget / field empty.<br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Readonly</b></td>
|
||||
<td>readonly</td>
|
||||
<td>yes</td>
|
||||
<td>readonly</td>
|
||||
<td>
|
||||
If checked (xml-attr: readonly="true") the widget will NOT be editable.
|
||||
If it is not supported by the browser, the etemplate-class makes shure that no
|
||||
changes / content is transmitted back to the app.
|
||||
Only applicable to widgets with input capabilities. Readonly Buttons get removed
|
||||
from the dialog, like they where disabled.
|
||||
The readonly attribute could be set on runtime via a readonly-array sublied to
|
||||
the exec or show function of the class, the value on index=name/id has to be true
|
||||
to make a widget readonly.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Disabled</b></td>
|
||||
<td>disabled</td>
|
||||
<td>yes</td>
|
||||
<td>disabled</td>
|
||||
<td>
|
||||
If checked (xml-attr: disabled="true") the widget will NOT be shown.
|
||||
For buttons this could be archived on runtime via setting them readonly.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>onChange</b></td>
|
||||
<td>onchange</td>
|
||||
<td>?</td>
|
||||
<td>onchange</td>
|
||||
<td>
|
||||
If checked (xml-attr: onchange="1") and the contet of the widget is changed by
|
||||
the user, the form will be submitted.
|
||||
Via xml or by a program other values can be set (not in the editor at the moment and
|
||||
this is not compatible with the phpGTK implementation of the eTemplates).
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Span, Class</b></td>
|
||||
<td>span<br>class</td>
|
||||
<td>span: no<br>class: yes</td>
|
||||
<td>span</td>
|
||||
<td>
|
||||
In the editor and internaly this field contains two comma-separated values:<p>
|
||||
<b>span</b>: how many cell a widget should span (default is one), the special value
|
||||
of 'all' can be used to indicate it should span all remaining cells of a row.
|
||||
This is not supported by xul-grid's at the moment, but is planned to be.<p>
|
||||
<b>class</b>: the CSS class for the widget.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Align</b></td>
|
||||
<td>align</td>
|
||||
<td>yes</td>
|
||||
<td>align</td>
|
||||
<td>
|
||||
Can be set to 'left' (default), 'center' or 'right'.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Width, Disabled</b><br>column-attr.</td>
|
||||
<td>width</td>
|
||||
<td>yes</td>
|
||||
<td>row[0][#]</td>
|
||||
<td>
|
||||
Can be set to a percentage (eg. '10%'), a number of pixels or ...
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Height, Disabled</b><br>row-attr.</td>
|
||||
<td>height</td>
|
||||
<td>yes</td>
|
||||
<td>row[0][h#]</td>
|
||||
<td>
|
||||
Can be set to a percentage (eg. '10%'), a number of pixels or ...
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Disabled</b><br>column-attr.<br>row-attr.</td>
|
||||
<td>disabled</td>
|
||||
<td>no</td>
|
||||
<td>disabled</td>
|
||||
<td>
|
||||
Syntax: <b>[!]{@name|value}[={@name2|value2}]</b><br>
|
||||
Disables (=dont show it) a row/column if a certain criteria is (not (=!)) meet.<br>
|
||||
If no '=...' / 2. value is given, the test is made on the first value being not empty, else
|
||||
the test is made by comparing the two values. Instead of a value you can give a name as an
|
||||
index into the content prefixed by @. Examples:<br>
|
||||
<b>!@data</b> disables row/col if value of data is empty, <br>
|
||||
<b>@val=false</b> disables if value of val is equal to (the string) 'false'
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Class, Valign</b><br>row-attr.</td>
|
||||
<td>class<br>valign</td>
|
||||
<td>both: yes</td>
|
||||
<td>row[0][c#]</td>
|
||||
<td>
|
||||
In the editor and internaly this field contains two comma-separated values:<p>
|
||||
<b>class</b>: the CSS class for the row, there are 4 predefined css-classes:
|
||||
nmh: next-match-header-background, nmr: alternating next-match-row-background which
|
||||
gets replaced by the etemplate class with nmr0 or nmr1.<p>
|
||||
<b>valign</b>: vertical alignment of the widgets in the row: 'top', 'middle' (default)
|
||||
or 'bottom'
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>blurText</b></td>
|
||||
<td>blur</td>
|
||||
<td>no</td>
|
||||
<td>blur</td>
|
||||
<td>
|
||||
This text get displayed if an input-field is empty <u>and</u> does not have the
|
||||
input-focus (blur). It can be used to show a default value or a kind of help-text.<br>
|
||||
If it contains a text (eg. 'Search...'), this text is run through lang(), if it contains
|
||||
a reference to the content array (eg. '@blur_text') it does <u>not</u> get translated.
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<a name="widgets">
|
||||
<h2>standard widgets and extensions of the eTemplates</h2>
|
||||
<table border=1>
|
||||
<tr>
|
||||
<th>Widget Name in Editor</th>
|
||||
<th>xml tag</th>
|
||||
<th>xul</th>
|
||||
<th>internal name</th>
|
||||
<th>description of the widget<th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Label</b></td>
|
||||
<td><description/></td>
|
||||
<td>yes</td>
|
||||
<td>label</td>
|
||||
<td>
|
||||
<b>a textual label</b><br>
|
||||
The content is taken from the content-array but it can have an own label from
|
||||
the label attribute too.<p>
|
||||
<b>Options</b> has 2 comma-separated fields:<br>
|
||||
<b>1.</b> if it contains a 'i' and/or a 'b' the content (not the label) is rendered
|
||||
in italic and/or bold.<br>
|
||||
<b>2.</b> if set to a menuaction, a link to that methode = app.class.method is put around the label
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Text</b></td>
|
||||
<td><textbox/></td>
|
||||
<td>yes</td>
|
||||
<td>text</td>
|
||||
<td>
|
||||
<b>a single-line input field for text</b><br>
|
||||
In the html-UI this is rendered as <input ...><p>
|
||||
<b>Options</b> has 3 comma-separated fields:<br>
|
||||
xml: <b>size</b>: the length in chars of the input-field<br>
|
||||
xml: <b>maxlength</b>: the maximum length of the input<br>
|
||||
xml: <b>validator</b>: perl regular expression to validate the input (kommas are allowed in the expression)
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Integer</b></td>
|
||||
<td><textbox<br>type="int"/></td>
|
||||
<td>?</td>
|
||||
<td>int</td>
|
||||
<td>
|
||||
<b>a input-field to enter an integer</b><br>
|
||||
In the html-UI this is rendered as <input ...>. <i>The input-validation is done at the moment only on server-side,
|
||||
clientside validation and input-restriction to only numbers is planed.</i><p>
|
||||
<b>Options</b> has 3 comma-separated fields:<br>
|
||||
xml: <b>min</b>: minimum value, default none, empty values are Ok, as long as <b>needed</b> is not set<br>
|
||||
xml: <b>max</b>: maximum value, default none, empty values are Ok, as long as <b>needed</b> is not set<br>
|
||||
xml: <b>size</b>: the length in chars of the input-field, default 5
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Float</b></td>
|
||||
<td><textbox<br>type="float"/></td>
|
||||
<td>?</td>
|
||||
<td>float</td>
|
||||
<td>
|
||||
<b>a input-field to enter a float</b><br>
|
||||
In the html-UI this is rendered as <input ...>. <i>The input-validation is done at the moment only on server-side,
|
||||
clientside validation and input-restriction to only numbers is planed.</i><p>
|
||||
<b>Options</b> has 3 comma-separated fields:<br>
|
||||
xml: <b>min</b>: minimum value, default none, empty values are Ok, as long as <b>needed</b> is not set<br>
|
||||
xml: <b>max</b>: maximum value, default none, empty values are Ok, as long as <b>needed</b> is not set<br>
|
||||
xml: <b>size</b>: the length in chars of the input-field, default 5
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Textarea</b></td>
|
||||
<td><textbox<br>multiline="true"/></td>
|
||||
<td>yes</td>
|
||||
<td>textarea</td>
|
||||
<td>
|
||||
<b>a multiline input-field for text</b><br>
|
||||
In the html-UI this is rendered as <textarea ...>.<p>
|
||||
<b>Options</b> has 2 comma-separated fields:<br>
|
||||
xml: <b>cols</b>: the width of the field in chars<br>
|
||||
xml: <b>rows</b>: the number of rows
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Formatted Text (HTML)</b></td>
|
||||
<td><htmlarea /></td>
|
||||
<td>no</td>
|
||||
<td>htmlarea</td>
|
||||
<td>
|
||||
<b>a multiline input-field for formatted (HTML) text</b><br>
|
||||
In the html-UI this is rendered as <textarea ...> and the HTMLarea javascript editor is used.<p>
|
||||
<b>Options</b> has 2 comma-separated fields:<br>
|
||||
xml: <b>style</b>: inline styles for the text/htmlarea<br>
|
||||
xml: <b>plugins</b>: plugins (comma-separated) to load
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Checkbox</b></td>
|
||||
<td><checkbox/></td>
|
||||
<td>yes</td>
|
||||
<td>checkbox</td>
|
||||
<td>
|
||||
<b>a widget that can be checked or unchecked</b><br>
|
||||
In the html-UI this is rendered as <input type="checkbox" ...>.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Radiobutton</b></td>
|
||||
<td><radio/></td>
|
||||
<td>?</td>
|
||||
<td>radio</td>
|
||||
<td>
|
||||
<b>a widget in a group of which only one can be checked</b><br>
|
||||
In the html-UI this is rendered as <input type="radio" ...><br>
|
||||
Unlike XUL (and like html) the radio-buttons are grouped by giving them the same name / id.
|
||||
If it is checked, the value is set to what is entered in <b>Options</b>. If the value of the
|
||||
content array at index name/id matches the options-field the radiobutton is marked 'checked'.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Submitbutton</b></td>
|
||||
<td><button image="img.gif" ro_image="img-grey.gif"/></td>
|
||||
<td>yes</td>
|
||||
<td>button</td>
|
||||
<td>
|
||||
<b>a button to submit the form / end the dialog</b><br>
|
||||
In the html-UI this is rendered as <input type="submit" ...>.<br>
|
||||
If a button is set readonly (via seting its id in the $readonlys array passed to exec) it is not rendered
|
||||
at all (if no ro_image is given), like it would be diabled.<p>
|
||||
<b>onChange</b> xml: <b>onchange</b>: if set and the user has JavaScript enabled
|
||||
the button is renderd as a link around the label and a hidden
|
||||
input to set id if the link is clicked.<br>
|
||||
<b>Options</b> xml: <b>image, ro_image</b>: Image to use instead of a Button with a label. There will
|
||||
be no button around the image. If a ro_image is given (separated by a comma in the editors options)
|
||||
it will be used if the button is set readonly (else the button is no rendered at all) .
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Horizonatal Rule</b></td>
|
||||
<td><hrule/></td>
|
||||
<td>no</td>
|
||||
<td>hrule</td>
|
||||
<td>
|
||||
<b>a horizontal rule / line</b><br>
|
||||
In the html-UI this is rendered as <hr ...><br>
|
||||
<b>Options</b> can contain a width of the rule, default is 100%
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Template</b></td>
|
||||
<td><grid id="app.name" content="subarr"/></td>
|
||||
<td>yes</td>
|
||||
<td>template</td>
|
||||
<td>
|
||||
<b>a separate eTemplate to be loaded into this cell</b><br>
|
||||
<b>Name</b> xml: <b>id</b>: the name of the etemplate to load<br>
|
||||
<b>Options</b> xml: <b>content</b>: if set, the template uses an own sub-array
|
||||
of the content array indexed by the value of this field (if not the full
|
||||
content-array is used). Variables like $row can be used as descript
|
||||
for the general attribute Name.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Image</b></td>
|
||||
<td><image src="foo.gif" label="Get a foo" options="app.class.method"/></td>
|
||||
<td>yes</td>
|
||||
<td>image</td>
|
||||
<td>
|
||||
<b>shows an image</b><br>
|
||||
<b>Label</b> xml: <b>label</b>: the label is shown as tooltip (like html-title)<br>
|
||||
<b>Name</b> xml: <b>src</b>: the name of the image to load, the image is search in the apps template-dirs<br>
|
||||
<b>Options</b> xml: <b>options</b>: if set, a link to that methode = app.class.method is put around the image
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Selectbox</b></td>
|
||||
<td>
|
||||
<menulist><br>
|
||||
<menupopup id="name" options="Select one"/><br>
|
||||
</menulist><p>
|
||||
<i>multiselect: <b>options</b> > 1</i><br>
|
||||
<listbox rows="#"/><p>
|
||||
<i>Examples for predefined selectboxes</i>:<p>
|
||||
<listbox type="select-cat" rows="5"/><p>
|
||||
<menulist><br>
|
||||
<menupopup type="select-account" options="All,both,2"/><br>
|
||||
</menulist><p>
|
||||
|
||||
|
||||
</td>
|
||||
<td>yes</td>
|
||||
<td>select</td>
|
||||
<td>
|
||||
<b>shows a selectbox</b><br>
|
||||
The content of the selectbox / the options have to be in an array which can be in 2 locations:
|
||||
<ol>
|
||||
<li>in $content["options-$name"]
|
||||
<li>or in an separate array only for select-box-options under the index name, this array is passed
|
||||
to the exec or show function of the etemplate-class
|
||||
</ol>
|
||||
<b>Options</b> <i>in the editor</i>: if set and > 1 the selectbox is a multiselection with options number of lines<p>
|
||||
xml: <b>rows</b>: <i>only for <listbox></i>: number of rows to show<p>
|
||||
xml <b>options</b>: <i>only for <menupopup/></i>: textual label for a first Row, e.g. 'All' or 'None'
|
||||
(id will be ''), additional attr see sub-types<p>
|
||||
xml: <b>type</b>: can be set to get several predefined select-contents, in that case you dont need to set
|
||||
the content as descripted above (if set it too its in front of the predefined rows): <br>
|
||||
<b>select-cat</b>:<br>
|
||||
Select a phpgw category<br>
|
||||
<b>select-account</b>:<br>
|
||||
Select a user and/or group, determined by the options-field:<br>
|
||||
,{accounts(default)|groups|both},{''(phpgw-default)|0(only lid)|1(only names)|2(both)}<br>
|
||||
<b>select-percent, select-priority, select-access, select-country, select-state</b>:<br>
|
||||
as you expect by the name<br>
|
||||
<b>select-year, select-month, select-day</b>:<br>
|
||||
options for year: ,start,end (start and end can be a number of
|
||||
years from now or if > 100 a absolut year)<br>
|
||||
<b>select-number</b>:<br>
|
||||
Select a number out of a range specified by the options-field:<br>
|
||||
,{start (default=1)},{end (incl., default=10)},{decrement (default={padding zeros}1)}.<br>
|
||||
Example with padding zeros: options=',0,59,05' will give values: 00, 05, 10, ..., 55
|
||||
(like you would use it for minutes in a time-field)<br>
|
||||
<b>select-app</b>:<br>
|
||||
Select an application, availible options: ,{''=user enabled(default)|installed|all)}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>FileUpload</b></td>
|
||||
<td>
|
||||
<file id="name"/><br>
|
||||
</td>
|
||||
<td>no</td>
|
||||
<td>file</td>
|
||||
<td>
|
||||
<b>Input and Button to select a file for uploading</b><br>
|
||||
Returns the file-name of the uploaded file in the servers tmp-dir (the webserver needs to have a
|
||||
writable tmp-dir) plus, if javascript is enabled, the local filename of the client as "${name}_path".
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Date</b></td>
|
||||
<td>
|
||||
<date options="Y-m-d,1"/><p>
|
||||
<date type="date-time"/><p>
|
||||
<date type="date-timeonly" options="H:i"/>
|
||||
</td>
|
||||
<td>no</td>
|
||||
<td>date</td>
|
||||
<td>
|
||||
<b>Date-/Time-input</b> via selectboxes or a field for the year<br>
|
||||
The order of the input-fields is determined by the prefs of the user.<br>
|
||||
<b>Options</b>: [datetime-storage-format][,&1=year-no-selectbox|&2=today-button]<br>
|
||||
<b>datetime-storage-format</b> is the format, in which the date is stored in the variable:
|
||||
empty means an unix-timestamp (in GMT), or a string containing the letters <b>Y</b>, <b>m</b>,
|
||||
<b>d</b>, <b>H</b>, <b>i</b> plus separators, eg. 'Y-m-d': 2002-12-31. The storage format
|
||||
for times is always 24h or timestamp with date 1.1.1970 (if no date used). (This has nothing
|
||||
to do with the format of the display, which is only determined by the users preferences.)<br>
|
||||
<b>year-no-selectbox</b> if set (&1) an int-widget (input-field) is used instead of a
|
||||
select-year widget.<br>
|
||||
<b>today-button</b>: if set (&2) a [Today] button is displayed which sets the fields to
|
||||
the up-to-date date (via javascript)<br>
|
||||
<b>Sub-widgets</b>: <b>date-time</b>: a date and a time and <b>date-timeonly</b>: only a time<br>
|
||||
These widgets allow the input of times too or only, they use 12h am/pm or 24h format as
|
||||
specified in the user prefs.<br>
|
||||
<i>If readonly is set, this widget can be used to display a date, without the need to convert it.</i>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>VBox, HBox</b></td>
|
||||
<td>
|
||||
<vbox><br>
|
||||
<widget ...><br>
|
||||
<widget ...><br>
|
||||
</vbox><p>
|
||||
<hbox span="all"><br>
|
||||
<widget ...><br>
|
||||
<widget ...><br>
|
||||
</hbox>
|
||||
</td>
|
||||
<td>yes</td>
|
||||
<td>vbox, hbox</td>
|
||||
<td>
|
||||
<b>vertical or horizontal container</b> to contain other widgets. This is useful if one needs more
|
||||
widgets or widgets outside the column- / row-order of a grid.<br>
|
||||
Disabled child-cells are completly left out (no empty cells or rows get generated).<p>
|
||||
<b>Options</b> <i>in the editor</i>: the number of cells in the box (does NOT need to be set in xml).
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Tabs</b></td>
|
||||
<td>
|
||||
<tabbox id="name"><br>
|
||||
<tabs><br>
|
||||
<tab label="Tab 1" statustext="Help"/><br>
|
||||
...<br>
|
||||
</tabs><br>
|
||||
<tabpanels><br>
|
||||
<grid id="app.name.tab1"/><br>
|
||||
...<br>
|
||||
</tabpanels><br>
|
||||
</tabbox>
|
||||
</td>
|
||||
<td>yes</td>
|
||||
<td>tab</td>
|
||||
<td>
|
||||
<b>shows a tab-widget</b><br>
|
||||
The tab-widget is implemented as an extension, as html does not have a tab-widget.<p>
|
||||
The following fields / attributes are in the Editor and internaly in the class separeted by '|', in the
|
||||
xml/xul-file the are attributes of each tab- or grid-tag:<br>
|
||||
<b>Label</b> xml: <b>label</b>: the labels of the tabs eg. 'Tab 1|Tab 2|Tab 3'<br>
|
||||
<b>Help</b> xml: <b>statustext</b>: of the tabs<br>
|
||||
<b>Name</b> xml: <b>id</b>: the names/ids of the eTemplates/grid's to fill the bodies of the tabs, if the
|
||||
name contains no '.', it will be prefixed with the name of the template the widget is in plus a '.'<p>
|
||||
<b>Demo</b>: <i>There is a demo availible</i>: load 'etemplate.tab_widget.test' into the eTemplate editor and
|
||||
run it with show.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>NextMatch</b></td>
|
||||
<td>
|
||||
<nextmatch options="notes.index.rows" id="nm"/>
|
||||
</td>
|
||||
<td>yes</td>
|
||||
<td>tab</td>
|
||||
<td>
|
||||
<b>shows a table with some selectboxes, a search-field and arrows to scroll the table</b><br>
|
||||
The nextmatch-widget is implemented as an extension.<p>
|
||||
<b>Options</b> xml: <b>options</b>: name of the template to display the rows<br>
|
||||
<b>Name</b> xml: <b>id</b>: index into the content-array, it need to be pre-set with some information
|
||||
for the nextmatch widget and it returns its content with it:
|
||||
</td>
|
||||
<tr>
|
||||
<td colspan="5">
|
||||
<pre>
|
||||
$content[$id] = array( <span>// I = value set by the app, 0 = value on return / output</span>
|
||||
'get_rows' => <span>// I method/callback to request the data for the rows eg. 'notes.bo.get_rows'</span>
|
||||
'filter_label' => <span>// I label for filter (optional)</span>
|
||||
'filter_help' => <span>// I help-msg for filter (optional)</span>
|
||||
'no_filter' => True <span>// I disable the 1. filter</span>
|
||||
'no_filter2' => True <span>// I disable the 2. filter (params are the same as for filter)</span>
|
||||
'no_cat' => True <span>// I disable the cat-selectbox</span>
|
||||
'template' => <span>// I template to use for the rows, if not set via options</span>
|
||||
'header_left' => <span>// I template to show left of the range-value, left-aligned (optional)</span>
|
||||
'header_right' => <span>// I template to show right of the range-value, right-aligned (optional)</span>
|
||||
'bottom_too' => True <span>// I show the nextmatch-line (arrows, filters, search, ...) again after the rows</span>
|
||||
'start' => <span>// IO position in list</span>
|
||||
'cat_id' => <span>// IO category, if not 'no_cat' => True</span>
|
||||
'search' => <span>// IO search pattern</span>
|
||||
'order' => <span>// IO name of the column to sort after (optional for the sortheaders)</span>
|
||||
'sort' => <span>// IO direction of the sort: 'ASC' or 'DESC'</span>
|
||||
'col_filter' => <span>// IO array of column-name value pairs (optional for the filterheaders)</span>
|
||||
'filter' => <span>// IO filter, if not 'no_filter' => True</span>
|
||||
'filter2' => <span>// IO filter2, if not 'no_filter2' => True</span>
|
||||
'rows' => <span>// O content set by callback</span>
|
||||
'total' => <span>// O the total number of entries</span>
|
||||
);
|
||||
|
||||
<span>/*
|
||||
* example: the get_rows function from notes.bo.get_rows (has to be in public_functions !)
|
||||
*/</span>
|
||||
function get_rows($query,&$rows,&$readonlys)
|
||||
{
|
||||
$rows = $this->read($query['start'],$query['search'],$query['filter'],$query['cat_id']);
|
||||
if (!is_array($rows))
|
||||
{
|
||||
$rows = array( );
|
||||
}
|
||||
else
|
||||
{
|
||||
array_unshift($rows,0); each($rows); <span>// first entry is not used !!!</span>
|
||||
}
|
||||
$readonlys = array( ); <span>// set readonlys to enable/disable our edit/delete-buttons</span>
|
||||
while (list($n,$note) = each($rows))
|
||||
{
|
||||
if (!$this->check_perms($this->grants[$note['owner_id']],PHPGW_ACL_EDIT))
|
||||
{
|
||||
$readonlys["edit[$note[id]]"] = True;
|
||||
}
|
||||
if (!$this->check_perms($this->grants[$note['owner_id']],PHPGW_ACL_DELETE))
|
||||
{
|
||||
$readonlys["delete[$note[id]]"] = True;
|
||||
}
|
||||
}
|
||||
return $this->total_records;
|
||||
}
|
||||
|
||||
<span>/*
|
||||
* Example how the nextmatch-widget is used in notes.ui.index:
|
||||
*/</span>
|
||||
function index($content = 0)
|
||||
{
|
||||
if (!is_array($content))
|
||||
{
|
||||
$content = array('nm' => $this->session_data); <span>// restore settings from the session</span>
|
||||
}
|
||||
if (isset($content['nm']['rows'])) <span>// one of the buttons in the rows is pressed</span>
|
||||
{
|
||||
$this->session_data = $values['nm']; <span>// save the settings in the session</span>
|
||||
unset($this->session_data['rows']); <span>// we dont want to save the content of the rows</span>
|
||||
$this->save_sessiondata();
|
||||
|
||||
if (isset($values['nm']['rows']['edit']))
|
||||
{
|
||||
list($id) = each($values['nm']['rows']['edit']);
|
||||
return $this->edit($id);
|
||||
}
|
||||
elseif (isset($values['nm']['rows']['delete']))
|
||||
{
|
||||
list($id) = each($values['nm']['rows']['delete']);
|
||||
return $this->delete($id);
|
||||
}
|
||||
}
|
||||
$values['nm']['options-filter'] = array ( <span>// set up the data for our filter</span>
|
||||
'all' => 'Show all',
|
||||
'public' => 'Only yours',
|
||||
'private' => 'Private'
|
||||
);
|
||||
$values['nm']['get_rows'] = 'notes.bo.get_rows';
|
||||
$values['nm']['no_filter2'] = True; <span>// disable the 2. filter</span>
|
||||
|
||||
$this->tpl->read('notes.index');
|
||||
$this->tpl->exec('notes.ui.index',$values);
|
||||
}
|
||||
</pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Nextmatch-SortHeader</b><p><b>Nextmatch-FilterHeader</b></td>
|
||||
<td>
|
||||
<nextmatch type="nextmatch-sortheader" id="col-name" label="ColLabel"/><p>
|
||||
<nextmatch type="nextmatch-filterheader" id="col-name"/>
|
||||
</td>
|
||||
<td>no</td>
|
||||
<td>nextmatch-sortheader<p>nextmatch-filterheader</td>
|
||||
<td>
|
||||
These widget are an optional part of the nextmatch widget.<p>
|
||||
<b>nextmatch-sortheader</b><br>
|
||||
Widget to be placed as a colum-header in the headerline of a nextmatch-template. It allows, by clicking on it,
|
||||
to order the lines of the nextmatch after a certain column. The column-name is given as <b>name</b> (xml:id) the
|
||||
<b>label</b> is show as a link of button (no javascript). Consecutive click on the header change the sorting
|
||||
direction, indicated by a little up- or down-arrow.<p>
|
||||
<b>nextmatch-filterheader</b><br>
|
||||
Widget to allow to show only certain row, which match a selected filter-value. The column-name is given as <b>name</b>
|
||||
(xml:id), the options of the displayed selectbox need to be set as for an ordinary selectbox (eg. in the options
|
||||
parameter to the uietemplate::exec function). If no extra-label is given in options, lang('all') will be used for
|
||||
the empty value, which means no filter activ. An (optional) <b>label</b> can be given.<p>
|
||||
<i><u>Note</u>:</i> Both widgets interoperate with the nextmatch-widget which passes the set values as part if
|
||||
the query-parameter to its get_rows function, they are <u>not</u> returned in the rows sub-array.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>LinkWidgets</b></td>
|
||||
<td>
|
||||
<link type="link-to" id="name"/><p>
|
||||
<link type="link-list" id="name"/><p>
|
||||
<link type="link-string" id="name"/><p>
|
||||
</td>
|
||||
<td>no</td>
|
||||
<td>link-to<p>link-list<p>link-string</td>
|
||||
<td>
|
||||
These widget are the UI-part of the link-class ({bo|so}link) in InfoLog and maybe the API soon.<p>
|
||||
<b>link-to</b><br>
|
||||
Widget to make a links to other entries of link-aware apps and to attach files.<p>
|
||||
<b>link-list</b><br>
|
||||
Widget to shows the links to an entry and a Unlink Button for each link. <p>
|
||||
<i><u>Note</u>:</i> Both Widgets can be used on the same template with the <u>same</u> name. They share
|
||||
the content of that variable, which contains just the id of the entry in the current app.<p>
|
||||
|
||||
<b>link-string</b><br>
|
||||
Comma-separated list of link-titles with a link to its view-method, value is like the return
|
||||
of bolink::get_links().
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<h3>One remark about cross-site-scripting</h3>
|
||||
The following eTemplate Widgets are parsing its content before displaying through <b>htmlspecialchars()</b> to
|
||||
correctly display the content and to gard against malecious data (like scripts etc.):
|
||||
<ul>
|
||||
<li>Label
|
||||
<li>Text, Textarea
|
||||
<li>Integer, Float
|
||||
<li>SelectBoxes (it's options-strings)
|
||||
<li>LinkWidgets: link-to, link-list, link-string
|
||||
</ul>
|
||||
This is done in most cases by the underlaying html-class and not direct in eTemplate.
|
||||
<p>
|
||||
<hr>
|
||||
<a name="extensions">
|
||||
<h1>How to implement new widgets / extensions to the eTemplates?</h1>
|
||||
<p>The eTemplates have an interface to extend them with new widgets. These widgets are php-classes, can use
|
||||
eTemplates to define the UI of the new widget and are stored in the eTemplate's inc-dir or the inc-dir of a
|
||||
eGroupWare application. The editor and the etemplate-class autoload the existing extensions.</p>
|
||||
|
||||
<i>I will made more documentation about the interface availible soon. For now have a look for the source
|
||||
of the existing extensions.</i>
|
||||
|
||||
<h2>please <a href="#" onClick="document.location='mai'+'lto:RalfBecker'+unescape('%40')+'outdoor-training'+unescape('%2E')+'de'; return false;">contact me</a> if you have further questions or comments about the eTemplates</h2>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -646,10 +646,11 @@
|
||||
);
|
||||
}
|
||||
break;
|
||||
case 'htmlarea': // Multiline formatted Text Input, size: [inline styles for the widget]
|
||||
case 'htmlarea': // Multiline formatted Text Input, size: [inline styles for the widget][,plugins (comma-sep.)]
|
||||
if (!$readonly)
|
||||
{
|
||||
$html .= $this->html->htmlarea($form_name,$value,$cell_options);
|
||||
list($styles,$plugins) = explode(',',$cell_options,2);
|
||||
$html .= $this->html->htmlarea($form_name,$value,$styles,'',$plugins);
|
||||
$GLOBALS['phpgw_info']['etemplate']['to_process'][$form_name] = array(
|
||||
'type' => $cell['type'],
|
||||
'needed' => $cell['needed'],
|
||||
|
620
etemplate/inc/class.xul_io.inc.php
Normal file
620
etemplate/inc/class.xul_io.inc.php
Normal file
@ -0,0 +1,620 @@
|
||||
<?php
|
||||
/**************************************************************************\
|
||||
* eGroupWare - eTemplates - XUL/XML Import & Export *
|
||||
* http://www.egroupware.org *
|
||||
* Written by Ralf Becker <RalfBecker@outdoor-training.de> *
|
||||
* -------------------------------------------- *
|
||||
* This program is free software; you can redistribute it and/or modify it *
|
||||
* under the terms of the GNU General Public License as published by the *
|
||||
* Free Software Foundation; either version 2 of the License, or (at your *
|
||||
* option) any later version. *
|
||||
\**************************************************************************/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
|
||||
if (!function_exists('var2xml'))
|
||||
{
|
||||
if (file_exists(PHPGW_API_INC.'class.xmltool.inc.php'))
|
||||
{
|
||||
include_once(PHPGW_API_INC.'class.xmltool.inc.php');
|
||||
}
|
||||
else
|
||||
{
|
||||
include_once('class.xmltool.inc.php');
|
||||
}
|
||||
}
|
||||
|
||||
class xul_io
|
||||
{
|
||||
var $widget2xul;
|
||||
var $attr2xul;
|
||||
var $xul2widget;
|
||||
|
||||
function xul_io()
|
||||
{
|
||||
$this->attr2xul = array( // how to translate attr, common to all widgets
|
||||
'name' => 'id',
|
||||
'help' => 'statustext',
|
||||
'span' => 'span,class',
|
||||
'type' => '', // this is the widget-name => dont write as attr
|
||||
'disabled' => 'disabled=true',
|
||||
'readonly' => 'readonly=true',
|
||||
'size' => 'options'
|
||||
);
|
||||
$this->widget2xul = array( // how to translate widget-names and widget-spec. attr.
|
||||
'label' => array(
|
||||
'.name' => 'description',
|
||||
'label' => 'value'
|
||||
),
|
||||
'text' => array(
|
||||
'.name' => 'textbox',
|
||||
'size' => 'size,maxlength,validator'
|
||||
),
|
||||
'textarea' => array(
|
||||
'.name' => 'textbox',
|
||||
'.set' => 'multiline=true',
|
||||
'size' => 'rows,cols'
|
||||
),
|
||||
'integer' => array(
|
||||
'.name' => 'textbox',
|
||||
'.set' => 'type=integer',
|
||||
'size' => 'min,max,size'
|
||||
),
|
||||
'float' => array(
|
||||
'.name' => 'textbox',
|
||||
'.set' => 'type=float',
|
||||
'size' => 'min,max,size'
|
||||
),
|
||||
'select' => array(
|
||||
'.name' => 'menulist,menupopup',
|
||||
),
|
||||
'select-multi' => array( // multiselection, if size > 0
|
||||
'.name' => 'listbox',
|
||||
'size' => 'rows,options'
|
||||
),
|
||||
'template' => array(
|
||||
'.name' => 'grid',
|
||||
'size' => 'content'
|
||||
),
|
||||
'image' => array(
|
||||
'.name' => 'image',
|
||||
'name' => 'src'
|
||||
),
|
||||
'tab' => array(
|
||||
'.name' => 'tabbox,tabs,tabpanels'
|
||||
),
|
||||
'button' => array(
|
||||
'.name' => 'button',
|
||||
'size' => 'image,ro_image'
|
||||
),
|
||||
'htmlarea' => array(
|
||||
'size' => 'style,plugins',
|
||||
),
|
||||
);
|
||||
$this->xul2widget = array(
|
||||
'menulist' => 'select',
|
||||
'listbox' => 'select',
|
||||
'description' => 'label'
|
||||
);
|
||||
}
|
||||
|
||||
function set_attributes(&$widget,$attr,$val)
|
||||
{
|
||||
$this->set_attributes2($widget,$attr,$val,$dummy);
|
||||
}
|
||||
|
||||
function set_attributes2(&$widget,$attr,$val,&$spanned)
|
||||
{
|
||||
if ($attr != '')
|
||||
{
|
||||
$attrs = explode(',',$attr);
|
||||
|
||||
if (count($attrs))
|
||||
{
|
||||
$vals = count($attrs) > 1 ? split(',',$val,count($attrs)) : array($val);
|
||||
while (list($n,$attr) = each($attrs))
|
||||
{
|
||||
if (($val = $vals[$n]) != '')
|
||||
{
|
||||
if ($attr == 'span')
|
||||
{
|
||||
$spanned = $val == 'all' ? 999 : $val - 1;
|
||||
}
|
||||
list($attr,$set) = explode('=',$attr);
|
||||
$widget->set_attribute($attr,$set != '' ? $set : $val);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function cell2widget($cell,&$spanned,$etempl,&$root,&$embeded_too)
|
||||
{
|
||||
$type = $cell['type'];
|
||||
if (is_array($type))
|
||||
{
|
||||
list(,$type) = each($type);
|
||||
}
|
||||
if (substr($type,0,6) == 'select')
|
||||
{
|
||||
$type = $cell['size'] > 1 ? 'select-multi' : 'select';
|
||||
}
|
||||
$widgetattr2xul = isset($this->widget2xul[$type]) ? $this->widget2xul[$type] : array();
|
||||
$type = isset($widgetattr2xul['.name']) ? $widgetattr2xul['.name'] : $type;
|
||||
list($parent,$child,$child2) = explode(',',$type);
|
||||
$widget = new xmlnode($parent);
|
||||
$attr_widget = &$widget;
|
||||
if ($child)
|
||||
{
|
||||
$child = new xmlnode($child);
|
||||
$attr_widget = &$child;
|
||||
}
|
||||
if ($child2)
|
||||
{
|
||||
$child2 = new xmlnode($child2);
|
||||
}
|
||||
if (isset($widgetattr2xul['.set'])) // set default-attr for type
|
||||
{
|
||||
$attrs = explode(',',$widgetattr2xul['.set']);
|
||||
while (list(,$attr) = each($attrs))
|
||||
{
|
||||
list($attr,$val) = explode('=',$attr);
|
||||
$widget->set_attribute($attr,$val);
|
||||
}
|
||||
}
|
||||
switch ($parent)
|
||||
{
|
||||
case 'nextmatch':
|
||||
list($tpl) = explode(',',$cell['size']);
|
||||
$embeded = new etemplate($tpl,$etempl->as_array());
|
||||
if ($embeded_too)
|
||||
{
|
||||
$this->etempl2grid($embeded,$root,$embeded_too);
|
||||
}
|
||||
$cell['size'] = $embeded->name;
|
||||
unset($embeded);
|
||||
break;
|
||||
case 'tabbox':
|
||||
$labels = explode('|',$cell['label']); unset($cell['label']);
|
||||
$helps = explode('|',$cell['help']); unset($cell['help']);
|
||||
$names = explode('|',$cell['name']); unset($cell['name']);
|
||||
for ($n = 0; $n < count($labels); ++$n)
|
||||
{
|
||||
$tab = new xmlnode('tab');
|
||||
$tab->set_attribute('label',$labels[$n]);
|
||||
$tab->set_attribute('statustext',$helps[$n]);
|
||||
$child->add_node($tab);
|
||||
|
||||
$embeded = new etemplate($names[$n],$etempl->as_array());
|
||||
if ($embeded_too)
|
||||
{
|
||||
$this->etempl2grid($embeded,$root,$embeded_too);
|
||||
}
|
||||
$grid = new xmlnode('grid');
|
||||
$grid->set_attribute('id',$embeded->name);
|
||||
$child2->add_node($grid);
|
||||
unset($embeded);
|
||||
}
|
||||
break;
|
||||
case 'menulist': // id,options belongs to the 'menupopup' child
|
||||
if ($cell['span'])
|
||||
{
|
||||
$widget->set_attribute('span',$cell['span']);
|
||||
unset($cell['span']);
|
||||
}
|
||||
// fall-trought
|
||||
case 'listbox':
|
||||
if ($cell['type'] != 'select') // one of the sub-types
|
||||
{
|
||||
$attr_widget->set_attribute('type',$cell['type']);
|
||||
}
|
||||
break;
|
||||
case 'vbox':
|
||||
case 'hbox':
|
||||
list($anz,$options) = split(',',$cell['size'],2);
|
||||
for ($n = 1; $n <= $anz; ++$n)
|
||||
{
|
||||
$widget->add_node($this->cell2widget($cell[$n],$no_span,$etempl,$root,$embeded_too));
|
||||
unset($cell[$n]);
|
||||
}
|
||||
$cell['size'] = $options;
|
||||
break;
|
||||
|
||||
case 'grid':
|
||||
if ($cell['name'][0] != '@' && $embeded_too)
|
||||
{
|
||||
$embeded = new etemplate();
|
||||
if ($embeded->read($name=$embeded->expand_name($cell['name'],0,0),'default','default',0,'',$etempl->as_array()))
|
||||
{
|
||||
$this->etempl2grid($embeded,$root,$embeded_too);
|
||||
}
|
||||
$cell['name'] = $embeded->name;
|
||||
unset($embeded);
|
||||
}
|
||||
break;
|
||||
}
|
||||
while (list($attr,$val) = each($cell))
|
||||
{
|
||||
if (is_array($val)) // correct old buggy etemplates
|
||||
{
|
||||
list(,$val) = each($val);
|
||||
}
|
||||
if (isset($widgetattr2xul[$attr]))
|
||||
{
|
||||
$attr = $widgetattr2xul[$attr];
|
||||
}
|
||||
elseif (isset($this->attr2xul[$attr]))
|
||||
{
|
||||
$attr = $this->attr2xul[$attr];
|
||||
}
|
||||
$this->set_attributes2($attr_widget,$attr,$val,$spanned);
|
||||
}
|
||||
if ($child)
|
||||
{
|
||||
$widget->add_node($child);
|
||||
}
|
||||
if ($child2)
|
||||
{
|
||||
$widget->add_node($child2);
|
||||
}
|
||||
return $widget;
|
||||
}
|
||||
|
||||
function etempl2grid($etempl,&$root,&$embeded_too)
|
||||
{
|
||||
if (is_array($embeded_too))
|
||||
{
|
||||
if (isset($embeded_too[$etempl->name]))
|
||||
{
|
||||
return; // allready embeded
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$embeded_too = array();
|
||||
}
|
||||
$embeded_too[$etempl->name] = True;
|
||||
|
||||
$xul_grid = new xmlnode('grid');
|
||||
$xul_grid->set_attribute('id',$etempl->name);
|
||||
$xul_grid->set_attribute('template',$etempl->template);
|
||||
$xul_grid->set_attribute('lang',$etempl->lang);
|
||||
$xul_grid->set_attribute('group',$etempl->group);
|
||||
$xul_grid->set_attribute('version',$etempl->version);
|
||||
$this->set_attributes($xul_grid,'width,height,border,class,spacing,padding',$etempl->size);
|
||||
|
||||
$xul_columns = new xmlnode('columns');
|
||||
$xul_rows = new xmlnode('rows');
|
||||
|
||||
reset($etempl->data);
|
||||
list(,$opts) = each ($etempl->data); // read over options-row
|
||||
while (list($r,$row) = each ($etempl->data))
|
||||
{
|
||||
$xul_row = new xmlnode('row');
|
||||
$this->set_attributes($xul_row,'class,valign',$opts["c$r"]);
|
||||
$this->set_attributes($xul_row,'height,disabled',$opts["h$r"]);
|
||||
|
||||
$spanned = 0;
|
||||
while (list($c,$cell) = each($row))
|
||||
{
|
||||
if ($r == '1') // write columns only once in the first row
|
||||
{
|
||||
$xul_column = new xmlnode('column');
|
||||
$this->set_attributes($xul_column,'width,disabled',$opts[$c]);
|
||||
$xul_columns->add_node($xul_column);
|
||||
}
|
||||
if ($spanned)
|
||||
{
|
||||
--$spanned;
|
||||
continue; // spanned cells are not written
|
||||
}
|
||||
$xul_row->add_node($this->cell2widget($cell,$spanned,$etempl,$root,$embeded_too));
|
||||
}
|
||||
$xul_rows->add_node($xul_row);
|
||||
}
|
||||
$xul_grid->add_node($xul_columns);
|
||||
$xul_grid->add_node($xul_rows);
|
||||
|
||||
if ($etempl->style != '')
|
||||
{
|
||||
$styles = new xmlnode('styles');
|
||||
$styles->set_value($etempl->style);
|
||||
$xul_grid->add_node($styles);
|
||||
}
|
||||
$root->add_node($xul_grid);
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
function export($etempl)
|
||||
{
|
||||
if ($this->debug)
|
||||
{
|
||||
echo "<p>etempl->data = "; _debug_array($etempl->data);
|
||||
}
|
||||
$doc = new xmldoc();
|
||||
$doc->add_comment('$'.'Id$');
|
||||
|
||||
$xul_overlay = new xmlnode('overlay');
|
||||
|
||||
$embeded_too = True;
|
||||
$this->etempl2grid($etempl,$xul_overlay,$embeded_too);
|
||||
|
||||
$doc->add_root($xul_overlay);
|
||||
$xml = $doc->export_xml();
|
||||
|
||||
//if ($this->debug)
|
||||
{
|
||||
echo "<pre>\n" . htmlentities($xml) . "\n</pre>\n";
|
||||
}
|
||||
return $xml;
|
||||
}
|
||||
|
||||
function add_cell(&$etempl,$cell,&$box,&$col,$node_level)
|
||||
{
|
||||
if (!isset($box[$node_level-1]))
|
||||
{
|
||||
list($spanned) = explode(',',$cell['span']);
|
||||
$spanned = $spanned == 'all' ? $etempl->cols - $col : $spanned;
|
||||
|
||||
$etempl->data[$etempl->rows][$etempl->num2chrs($col++)] = $cell;
|
||||
|
||||
/* if ($attr['type'] == 'template' && !empty($attr['name']) && $attr['name'][0] != '@')
|
||||
{
|
||||
$etempl->data[$etempl->rows][$etempl->num2chrs($col++)]['obj'] = new etemplate($attr['name']);
|
||||
} */
|
||||
while (--$spanned > 0)
|
||||
{
|
||||
$etempl->data[$etempl->rows][$etempl->num2chrs($col++)] = $etempl->empty_cell();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$pcell = &$box[$node_level-1];
|
||||
$pcell[++$pcell['anz']] = $cell;
|
||||
}
|
||||
}
|
||||
|
||||
function import(&$etempl,$data)
|
||||
{
|
||||
if ($this->debug)
|
||||
{
|
||||
echo "<pre>\n" . htmlentities($data) . "\n</pre><p>\n";
|
||||
}
|
||||
$parser = xml_parser_create();
|
||||
xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
|
||||
xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
|
||||
$vals = $index = '';
|
||||
$ok = xml_parse_into_struct($parser, $data, $vals, $index);
|
||||
|
||||
if (!$ok || !is_array($vals))
|
||||
{
|
||||
$err = 'Error Line '.xml_get_current_line_number($parser).', Column '.xml_get_current_column_number($parser).
|
||||
': '.xml_error_string(xml_get_error_code($parser));
|
||||
}
|
||||
xml_parser_free($parser);
|
||||
|
||||
if ($err != '')
|
||||
{
|
||||
return $err;
|
||||
}
|
||||
while (list($n,$node) = each($vals))
|
||||
{
|
||||
$type = $node['type'];
|
||||
$tag = $node['tag'];
|
||||
$attr = is_array($node['attributes']) ? $node['attributes'] : array();
|
||||
if ($attr['id'])
|
||||
{
|
||||
$attr['name'] = $attr['id']; unset($attr['id']);
|
||||
}
|
||||
if (isset($attr['options']) && $attr['options'] != '')
|
||||
{
|
||||
$attr['size'] = $attr['options']; unset($attr['options']);
|
||||
}
|
||||
if ($tag == 'grid' && $type == 'complete' && !is_array($tab_attr))
|
||||
{
|
||||
$tag = 'template';
|
||||
}
|
||||
if ($tag != 'textbox' && !isset($attr['type']))
|
||||
{
|
||||
$attr['type'] = $this->xul2widget[$tag] ? $this->xul2widget[$tag] : $tag;
|
||||
}
|
||||
if ($this->debug)
|
||||
{
|
||||
echo "<p>$node[level]: $tag/$type: value='$node[value]' attr=\n"; _debug_array($attr);
|
||||
}
|
||||
switch ($tag)
|
||||
{
|
||||
case 'overlay':
|
||||
break;
|
||||
case 'grid':
|
||||
if ($type != 'close' && is_array($tab_attr))
|
||||
{
|
||||
$tab_names[] = $attr['name'];
|
||||
break;
|
||||
}
|
||||
if ($node['level'] > 2) // level 1 is the overlay
|
||||
{
|
||||
return "Can't import nested $node[tag]'s !!!";
|
||||
}
|
||||
if ($type != 'open')
|
||||
{
|
||||
break;
|
||||
}
|
||||
if ($grid_started) // more than one grid in the file --> place it into the cache
|
||||
{
|
||||
$cname = ($etempl->template == '' ? 'default' : $etempl->template).'/'.$etempl->name.
|
||||
($etempl->lang == '' ? '' : '.'.$etempl->lang);
|
||||
$imported[] = $etempl->name;
|
||||
$GLOBALS['phpgw_info']['etemplate']['cache'][$cname] = $etempl->as_array(1);
|
||||
}
|
||||
$grid_started = True;
|
||||
$etempl->init($attr);
|
||||
$size_opts = array('padding','spacing','class','border','height','width');
|
||||
for ($size = ''; list(,$opt) = each($size_opts); )
|
||||
{
|
||||
$size = $attr[$opt] . ($size != '' ? ",$size" : '');
|
||||
}
|
||||
$etempl->size = $size;
|
||||
$etempl->cols = $etempl->rows = 0;
|
||||
$etempl->data = array();
|
||||
break;
|
||||
case 'columns':
|
||||
case 'rows':
|
||||
break;
|
||||
case 'column':
|
||||
if ($type != 'complete')
|
||||
{
|
||||
return 'place widgets in <row> and not in <column> !!!';
|
||||
}
|
||||
$etempl->data[0][$etempl->num2chrs($etempl->cols++)] = $attr['width'] .
|
||||
($attr['disabled'] ? ','.$attr['disabled'] : '');
|
||||
break;
|
||||
case 'row':
|
||||
if ($type != 'open')
|
||||
{
|
||||
break;
|
||||
}
|
||||
$r = ++$etempl->rows;
|
||||
$col = 0;
|
||||
$etempl->data[0]["c$r"] = $attr['class'] . ($attr['valign'] ? ','.$attr['valign'] : '');
|
||||
$etempl->data[0]["h$r"] = $attr['height'] .
|
||||
($attr['disabled'] ? ','.$attr['disabled'] : '');
|
||||
break;
|
||||
case 'styles':
|
||||
$etempl->style = trim($node['value']);
|
||||
break;
|
||||
case 'tabbox':
|
||||
if ($type == 'open')
|
||||
{
|
||||
$tab_labels = $tab_helps = $tab_names = array();
|
||||
$tab_attr = $attr;
|
||||
}
|
||||
else
|
||||
{
|
||||
$tab_attr['type'] = 'tab';
|
||||
$tab_attr['label'] = implode('|',$tab_labels);
|
||||
$tab_attr['name'] = implode('|',$tab_names);
|
||||
$tab_attr['help'] = implode('|',$tab_helps);
|
||||
$tab_attr['span'] .= $tab_attr['class'] ? ','.$tab_attr['class'] : '';
|
||||
unset($tab_attr['class']);
|
||||
|
||||
$this->add_cell($etempl,$tab_attr,$box,$col,$node['level']);
|
||||
unset($tab_attr);
|
||||
}
|
||||
break;
|
||||
case 'tabs':
|
||||
case 'tabpanels':
|
||||
break;
|
||||
case 'tab':
|
||||
if ($type != 'close')
|
||||
{
|
||||
$tab_labels[] = $attr['label'];
|
||||
$tab_helps[] = $attr['statustext'];
|
||||
}
|
||||
break;
|
||||
case 'menupopup':
|
||||
if (is_array($menulist_attr))
|
||||
{
|
||||
$attr['help'] = $attr['statustext']; unset($attr['statustext']);
|
||||
unset($menulist_attr['type']);
|
||||
$menulist_attr += $attr;
|
||||
}
|
||||
break;
|
||||
case 'menulist':
|
||||
if ($type == 'open')
|
||||
{
|
||||
$menulist_attr = $attr;
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->add_cell($etempl,$menulist_attr,$box,$col,$node['level']);
|
||||
unset($menulist_attr);
|
||||
}
|
||||
break;
|
||||
case 'vbox':
|
||||
case 'hbox':
|
||||
if ($type == 'open')
|
||||
{
|
||||
$box[$node['level']] = $attr;
|
||||
}
|
||||
else
|
||||
{
|
||||
$cell = &$box[$node['level']];
|
||||
$cell['size'] = $cell['anz'] . ($cell['size'] != '' ? ','.$cell['size'] : '');
|
||||
unset($cell['anz']);
|
||||
$this->add_cell($etempl,$cell,$box,$col,$node['level']);
|
||||
unset($box[$node['level']]);
|
||||
}
|
||||
break;
|
||||
case 'textbox':
|
||||
if ($attr['multiline'])
|
||||
{
|
||||
$attr['type'] = 'textarea';
|
||||
$attr['size'] = $attr['rows'] . ($attr['cols'] ? ','.$attr['cols'] : '');
|
||||
unset($attr['cols']);
|
||||
unset($attr['rows']);
|
||||
}
|
||||
elseif ($attr['type']) // integer,float
|
||||
{
|
||||
$attr['size'] = $attr['min'] . ($attr['max'] ? ','.$attr['max'] : ($attr['size'] ? ',':'')) . ','.$attr['size'];
|
||||
unset($attr['min']);
|
||||
unset($attr['max']);
|
||||
}
|
||||
else // input
|
||||
{
|
||||
$attr['type'] = 'text';
|
||||
$attr['size'] .= $attr['maxlength']!='' ? ','.$attr['maxlength'] : '';
|
||||
unset($attr['maxlength']);
|
||||
}
|
||||
// fall-through
|
||||
default:
|
||||
switch ($tag)
|
||||
{
|
||||
case 'description':
|
||||
case 'label':
|
||||
$attr['label'] = $attr['value'];
|
||||
unset($attr['value']);
|
||||
break;
|
||||
case 'template':
|
||||
$attr['size'] = $attr['content'];
|
||||
unset($attr['content']);
|
||||
break;
|
||||
case 'image':
|
||||
$attr['name'] = $attr['src'];
|
||||
unset($attr['src']);
|
||||
break;
|
||||
case 'listbox':
|
||||
$attr['size'] = ereg_replace(',*$','',$attr['rows'].','.$attr['size']);
|
||||
unset($attr['rows']);
|
||||
break;
|
||||
case 'button':
|
||||
if ($attr['image'] || $attr['ro_image'])
|
||||
{
|
||||
$attr['size'] = $attr['image'] . ($attr['ro_image'] ? ','.$attr['ro_image'] : '');
|
||||
unset($attr['image']); unset($attr['ro_image']);
|
||||
}
|
||||
break;
|
||||
}
|
||||
$attr['help'] = $attr['statustext']; unset($attr['statustext']);
|
||||
$attr['span'] .= $attr['class'] ? ','.$attr['class'] : ''; unset($attr['class']);
|
||||
if ($type == 'close')
|
||||
{
|
||||
break;
|
||||
}
|
||||
$this->add_cell($etempl,$attr,$box,$col,$node['level']);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($this->debug)
|
||||
{
|
||||
_debug_array($etempl->data);
|
||||
}
|
||||
$imported[] = $etempl->name;
|
||||
|
||||
return $imported;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
Loading…
Reference in New Issue
Block a user