# CMS Handbuch – Entwickler

Technische Referenz und Entwicklerdokumentation für das batix® CMS

# Einführung & Grundlagen

Konzepte, Tag-Grundlagen, Filter, Datums-Patterns, Redakteurs-Tags.

# Filter

<!-- last_modified: 29. Jun 2021 -->
<p class="callout info">Um mittels Code einfacher zu filtern, gibt es die Hilfsklasse <code>Records</code> (<a href="/books/cms-handbuch-entwickler/page/records-hilfsklasse-fur-einfaches-filtern">siehe Beschreibung</a>).</p>

Filter können z.B. in Zusammenhang mit [bx:containerfilter](/books/cms-handbuch-entwickler/page/bxcontainerfilter) oder [Container-Filteraction](/books/cms-handbuch-entwickler/page/container-filteraction) verwendet werden, um bestimmte Datensätze anzuzeigen.

## Aufbau eines Filters

Filter werden in XML angegeben. Der grundlegende Aufbau ist folgender:

```xml
<filter>
  <filter-object>
    ...
  </filter-object>
  <filter-object>
    ...
  </filter-object>
  <order/> <!-- ab Version 2.5.7 -->
  <limit/> <!-- ab Version 2.5.7 -->
  <status/> <!-- ab Version 2.6.1 -->
</filter>


```

Eine Mehrfachverwendung von "filter-object" bewirkt eine UND-Verknüpfung dieser Objekte.

## Objekte

Ein "filter-object" ist folgendermaßen aufgebaut:

```xml
<filter-object [required="true"]>
  <field>...</field>
  <field>...</field>
  <type>...</type>
  [
   <request-value>...</request-value>
  |<static-value>...</static-value>
  |<special-value>...</special-value>
  |<request-attribute>...</request-attribute>
  |<session-attribute>...</session-attribute>
  ]
</filter-object>


```

Eine Mehrfachverwendung von "field" bewirkt eine ODER-Verknüpfung der Felder.
Die optionale Angabe von required="true" bewirkt, dass ein Wert, der zum Vergleichen übergeben wird (z.B. bei "request-value") auch vorhanden sein muss, d.h. wenn nichts übergeben wird, wird die Bedingung auch nicht erfüllt.

### field

Der Name des zu überprüfenden Feldes wird angegeben.
Falls das Feld eine Verknüpfung darstellt (Untercontainer, Einzelverknüpfung, Mehrfachverknüpfung), kann auch der Wert eines Feldes der Verknüpfung abgefragt werden, dazu einfach das gesuchte Unter-Feld mit einem Schrägstrich anfügen.

```xml
<field>feldname</field>
<field>feldname/unterfeld</field>     <!-- Untercontainerfeld -->
```

### type

Hier wird die Art des Vergleiches angegeben. Je nach Typ des Feldes, das geprüft wird, sind verschiedene Vergleiche möglich. Diese sind der folgenden Tabelle zu entnehmen.
Verglichen wird dabei der Feldwert mit dem Testwert, so ließt sich z.B. die erste Zeile der Tabelle "*Feldwert enthält Testwert*" oder die Zeile bei Bildern/Dokumenten *"Feldwert ist leer"*.

| Feld-Typ | `Type` | Art des Vergleiches:<br>Feldwert ... [Testwert] |
|----------|--------|--------------------------------------------------|
| einzeiliger oder mehrzeiliger Text | 1 | enthält |
| | 2 | beginnt mit |
| | 3 | endet mit |
| | 4 | ist gleich |
| | 5 | ist leer (Feld soll leer sein: static-value: 1, Feld soll nicht leer sein: static-value: 0) |
| | 6 | Mustervergleich (Regex) |
| | 7 | enthält eines der Wörter von<br>(Wörter durch Leerzeichen oder Kommas trennen, findet auch Teilstrings) |
| | 8 | ist eines der Wörter von<br>(Wörter durch Leerzeichen oder Kommas trennen, nur ganze Wörter) |
| | 9 | enthält alle Wörter<br>(Wörter durch Leerzeichen oder Kommas trennen) |
| | 11 - 19 | <span style="color: rgb(0,0,0);">**leer ODER Bedingung**<br>Bedingung auch erfüllen, falls Feld leer ist (außer für type 5)</span><br><span style="color: rgb(0,0,0);">z.B.: type 14 für "ist gleich oder leer"</span> |
| | 21 - 29 | **NICHT-Bedingung**<br>kehrt die Bedingung um (außer für type 5)<br>z.B.: type 23 für "endet nicht mit" |
| | 31 - 39 | <span style="color: rgb(0,0,0);">**leer ODER NICHT-Bedingung**<br>Kombination von 11 - 19 und 21 - 29</span><br><span style="color: rgb(0,0,0);">z.B.: type 32 für "beginnt nicht mit oder ist leer"</span> |
| Datum mit oder ohne Zeit | 1 | Feld ist größer (neuer) als übergebener Wert |
| | 2 | Feld ist kleiner (älter) als übergebener Wert |
| | 3 | ist gleich (Uhrzeit wird ignoriert) |
| | 4 | ist ungleich (Uhrzeit wird ignoriert) |
| | 5 | ist leer (Feld soll leer sein: static-value: 1, Feld soll nicht leer sein: static-value: 0) |
| | 6 | ist im Jahr (vierstellig angeben) |
| | 7 | ist im Monat (gültige Werte: 1-12) |
| | 8 | ist am Tag (gültige Werte: 1-31) |
| | 11 | Feld ist größer oder gleich als übergebener Wert |
| | 12 | Feld ist kleiner oder gleich als übergebener Wert |
| | 21 | Feld ist leer oder größer/gleich als übergebener Wert |
| | 22 | Feld ist leer oder kleiner/gleich als übergebener Wert |
| | 31 | Feld ist größer/gleich als heute + Testwert Tage |
| | 32 | Feld ist kleiner/gleich als heute + Testwert Tage |
| nur (Uhr)Zeit | 1 | <span style="color: rgb(0,0,0);">Feld ist größer (später)</span> |
| | 2 | <span style="color: rgb(0,0,0);">Feld ist kleiner (früher)</span> |
| | 3 | <span style="color: rgb(0,0,0);">Feld ist gleich</span> |
| | 4 | <span style="color: rgb(0,0,0);">Feld ist ungleich</span> |
| | 11 | <span style="color: rgb(0,0,0);">Feld ist größer/gleich</span> |
| | 12 | <span style="color: rgb(0,0,0);">Feld ist kleiner/gleich</span> |
| | 21 | <span style="color: rgb(0,0,0);">Feld ist leer oder größer/gleich</span> |
| | 22 | <span style="color: rgb(0,0,0);">Feld ist leer oder kleiner/gleich</span> |
| | 6 | <span style="color: rgb(0,0,0);">Feld ist in Stunde (0-23)</span> |
| | 7 | <span style="color: rgb(0,0,0);">Feld ist in Minute (0-59)</span> |
| | 8 | <span style="color: rgb(0,0,0);">Feld ist in Sekunde (0-59)</span> |
| | 5 | <span style="color: rgb(0,0,0);">Feld ist leer (Feld soll leer sein: static-value: 1, Feld soll nicht leer sein: static-value: 0)</span> |
| Zahl oder Preis | 1 | Feld ist größer gleich als übergebener Wert |
| | 2 | Feld ist kleiner gleich als übergebener Wert |
| | 11 | Feld größer als übergebener Wert |
| | 12 | Feld kleiner als übergebener Wert |
| | 3 | ist gleich |
| | 4 | ist ungleich |
| | 5 | ist leer (Feld soll leer sein: static-value: 1, Feld soll nicht leer sein: static-value: 0) |
| | 21 - 24 | **leer ODER Bedingung** (1 bis 4) |
| | 31 - 32 | **leer ODER Bedingung** (11 und 12) |
| Wahrheitswert (Boolean) | 4 | ist angehakt/gesetzt |
| | 5 | ist leer (null) |
| Bild | 1 | bestimmte ID ist verknüpft |
| | 4 | nicht-gelöschtes Bild ist verknüpft *(ab v2.6.2)* |
| | 5 | ist leer (Feld soll leer sein: static-value: 1, Feld soll nicht leer sein: static-value: 0) |
| Dokument | 5 | ist leer |
| | 8 | bestimmte ID ist verknüpft |
| Kartenkoordinaten | 21 | x ist gleich |
| | 26 | y ist gleich |
| | 5 | ist leer (Feld soll leer sein: static-value: 1, Feld soll nicht leer sein: static-value: 0) |
| Einzelverknüpfung | 8 | Datensatz-ID ist gleich |
| | 10 | Datensatz-ID ist ungleich<br>Bei mehreren IDs, Filter mehrmals verwenden. |
| | 9 | Datenlisten-ID ist gleich (nur bei alten Containern) |
| | 12 | enthält eine der Datensatz-IDs von<br>(IDs durch Leerzeichen, Komma oder Semikolon trennen) |
| | 5 | ist leer (Feld soll leer sein: static-value: 1, Feld soll nicht leer sein: static-value: 0) |
| | 4 | ist verknüpft (ab 2.6.2) |
| | 3 | ist aktiviert (ab 2.6.2) |
| Mehrfachverknüpfung | 8 | enthält Datensatz-ID |
| | 10 | <span style="color: rgb(0,0,0);">enthält Datensatz-ID <u>nicht</u> (</span>*ab v2.6.2*<span style="color: rgb(0,0,0);">)</span> |
| | 12 | enthält eine der Datensatz-IDs von<br>(IDs durch Leerzeichen, Komma oder Semikolon trennen) |
| | 14 | enthält alle der angegebenen IDs |
| | 5 | ist leer (Feld soll leer sein: static-value: 1, Feld soll nicht leer sein: static-value: 0) |
| Untercontainer | 5 | ist leer (Feld soll leer sein: static-value: 1, Feld soll nicht leer sein: static-value: 0) |

### value

Der gesuchte Wert kann auf unterschiedliche Weise übergeben werden. Für `<value>...</value>` können die folgenden Abfragen eingesetzt werden.

#### request-value

Der Vergleich findet mit dem Wert eines Request-Parameters statt.

```xml
<request-value>Request-Parameter-Name</request-value>
```

#### request-attribute

Der Vergleich findet mit dem Wert eines Request-Attributes statt.

```xml
<request-attribute>Request-Attribut-Name</request-attribute>
```

#### session-attribute

Ein Session-Attribut wird mit dem Feld verglichen.

```xml
<session-attribute>Session-Attribut-Name</session-attribute>
```

#### static-value

Der Wert zum Vergleichen wird direkt übergeben.

```xml
<static-value>gesuchter Wert</static-value>
```

#### special-value

Es wird ein spezieller Wert zum Vergleich herangezogen.

| | |
|--|--|
| TODAY | Es wird mit dem heutigen Datum im Format dd.MM.yyyy verglichen. Um Tage dazu zu addieren (oder abzuziehen) kann das Attribut days verwendet werden (ganze Zahl, die auch negativ sein kann).<br>`<special-value [days="n"]>TODAY</special-value>` |
| NOW | Es wird mit der aktuellen Zeit im Format dd.MM.yyyy mm:HH verglichen. Um Tage, Stunden oder Minuten dazu zu addieren (oder abzuziehen) können die Attribute days, hours oder minutes verwendet werden (ganze Zahl, die auch negativ sein kann).<br>`<special-value [days="n"] [hours="n"] [minutes="n"]>NOW</special-value>` |
| USERID | Es wird mit der UserID des aktuellen (eingeloggten) Betrachters verglichen.<br>`<special-value>USERID</special-value>` |
| SESSIONID | Die aktuelle SessionID wird abgeglichen.<br>`<special-value>SESSIONID</special-value>` |
| USERGROUPS | Dieser Spezialwert erzeugt eine Zeichenkette, welche die ID des Users sowie die IDs der Gruppen, denen er angehört, enthält (jeweils durch Leerzeichen getrennt).<br>`<special-value>USERGROUPS</special-value>` |
| PARENTCONTAINER | Es wird mit der ID des übergeordneten Containers verglichen.<br>`<special-value>PARENTCONTAINER</special-value>` |

#### clipboard-value

Es wird ein spezieller Clipboard-Wert zum Vergleich herangezogen.

#### system-value

Es wird der Wert einer Systemvariablen zum Vergleich herangezogen. Die Systemvariable wird unter "<a href="/books/cms-handbuch-redakteure/page/systemeinstellungen">Systemeinstellungen</a>" angelegt und gespeichert.

## order

Hier wird ein Sortierfeld definiert.

```xml
<order field="{Feldname}" [direction="{ascending|descending}"] />
```

Bei "field" wird der Feldname angegeben, nach dem sortiert wird. Sortiert werden kann nach einzeiligen Text, Datumtypen und Zahlentypen.
Bei "direction" wird "ascending" für aufsteigende Sortierung, und descending für absteigende Sortierung angegeben. Bei weglassen der Sortierrichtung wird aufsteigend sortiert.

*Diese Funktion ist ab v2.5.7 verfügbar*

## limit

Hier wird eine Startposition und ein überlauf in der Ergebnisliste definiert

```xml
<limit [index="{feste Startposition}"] [max="{Anzahl bis überlauf}"] />
```

Bei "index" wird die Startposition in der Ergebnisliste angegeben. Standardwert ist 0 für den ersten Datensatz.
Bei max wird angegeben, wie viele Datensätze maximal (je Seite) angezeigt werden. Standardwert ist -1 für keine Einschränkung.
Bei Angabe von max im [bx:containerfilter](/books/cms-handbuch-entwickler/page/bxcontainerfilter) wird diese Einstellung überschrieben.

*Diese Funktion ist ab v2.5.7 verfügbar*

## status

Es kann angegeben werden, ob aktive und/oder inaktive Datensätze gefiltert werden sollen.

```xml
<status active="{false| true}" inactive="{false| true}" />
```

Erklärt sich - glaube ich - von selbst.

*Diese Funktion ist ab v2.6.1 verfügbar*

## ID-Filter

zum Filtern der Datensatz-ID oder mehrerer IDs - getrennt durch Komma

```xml
<filter-id type="include" request-value="paramname" />
<filter-id type="include" request/session-attribute="paramname" />
<filter-id type="include" system/clipboard-value="paramname" /> <!-- ab v2.6.2 -->
<filter-id type="include">feste_id</filter-id>
```

Gegenteil von include: exclude (schließt diese ID(s) aus) *(weitere Erläuterungen folgen noch)*

## Beispiele

**Datumsvergleich**

```xml
<filter>
  <filter-object>
    <field>Datum</field>
    <type>11</type>
    <special-value days="-1">TODAY</special-value>
 </filter-object>
</filter>
```

Es werden nur Datensätze angezeigt, die maximal einen Tag alt sind.

**Suche**

```xml
<filter>
  <filter-object>
    <field>Kategorie</field>
    <type>8</type>
    <request-value>kat</request-value>
  </filter-object>
  <filter-object>
    <field>Titel</field>
    <field>Text</field>
    <type>1</type>
    <request-value>search</request-value>
  </filter-object>
  <filter-object>
    <field>Archiv</field>
    <type>4</type>
    <static-value>0</static-value>
  </filter-object>
</filter>
```

Nur Datensätze, die folgenden Kriterien entsprechen werden ausgegeben:

- Kategorie-ID (Einzel- oder Mehrfachverknüpfung) ist die selbe wie im Request-Parameter `kat`
- Felder Titel oder Text enthalten den Suchbegriff aus dem Request-Parameter `search`
- Haken bei Archiv (Wahrheitswert) ist nicht gesetzt

# Parameter-Werte (Präfixe)

<!-- last_modified: 30. May 2014 -->
Mit den folgenden Präfixen kann man auf verschiedene Variablen zugreifen:

- **request**:Name - der Wert wird aus dem Request-Parameter "Name" geholt
- **attribute**:Name - der Wert wird aus dem Request-Attribut "Name" geholt
- **session**:Name - der Wert wird aus dem Session-Attribut "Name" geholt
- **clipboard**:Name - der Wert wird aus dem Clipboard "Name" geholt
- **static**:Wert - es wird direkt "Wert" verwendet
- **system**:Wert - es wird auf die Systemvariable "Wert" zugegriffen

Diese Präfixe können als Wert jedes Tag-Attributes verwendet werden.

### Nur bei [bx:containerfilter](/books/cms-handbuch-entwickler/page/bxcontainerfilter):

- **special**:PARENTCONTAINER - ID des übergeordneten Datensatzes
- **special**:USERID - ID des angemeldeten Users
- **special**:SESSIONID - Sessionid wird geholt
- **special**:NOW - Vergleich mit "jetzt"
- **special**:TODAY - Vergleich mit "heute"

ab 2.6.2.

- **requests**:IDs - IDs mit Leerzeichen getrennt werden aus dem Request genommen
- **requestc**:IDs - IDs mit Komma getrennt werden aus dem Request genommen

# Pattern bei Datum

<!-- last_modified: 10. Jan 2018 -->
| Pattern | Entsprechung |
|---------|-------------|
| d | Tages im Monat ohne vorangestellter 0 bei einstelligen Zahlen (z.B. <span style="color: rgb(255,0,0);">5</span>.12.2013) |
| dd | Tages im Monat mitvorangestellter = (z.B. <span style="color: rgb(255,0,0);">05</span>.12.2013) |
| M | Monatsangabe ohne vorangestellter 0 bei einstelligen Zahlen (z.B. 12.<span style="color: rgb(255,0,0);">5</span>.2016) |
| MM | Monatsangabe mit vorangestellter 0 (z.B. 12.<span style="color: rgb(255,0,0);">05</span>.2016) |
| MMM | Monatsangebe als Text (z.B. 12.<span style="color: rgb(255,0,0);">Mai</span>.2016) |
| yy | Zahresangabe zweistellig (z.B. 12.05.<span style="color: rgb(255,0,0);">16</span>), führt evtl. zu Missverständnissen (2016 oder 1916?) |
| yyyy | Jahresangabe vierstellig (z.B. 12.05.<span style="color: rgb(255,0,0);">2016</span>) |
| EE | Wochentagsausgabe als Text gekürzt (z.B. Mo, Di, Mi...) |
| EEE | Wochentagsausgabe als Text ungekürzt (z.B. Montag, Dienstag, Mittwoch...) |
| H | Ausgabe der Stunde ab 0 Uhr ohne vorangestellter 0 bei einstelligen Zahlen (z.B. <span style="color: rgb(255,0,0);">3</span>:40 Uhr) |
| HH | Ausgabe der Stunde ab 0 Uhr mit vorangestellter 0 (z.B. <span style="color: rgb(255,0,0);">03</span>:40 Uhr) |
| mm | augabe der minuten (z.B. 03:<span style="color: rgb(255,0,0);">40 </span>Uhr) |
| ss | Ausgabe der Sekunden (z.B. 03:23:<span style="color: rgb(255,0,0);">34</span><span style="color: rgb(255,0,0);"> </span>Uhr) |

Weitere Infos und Ausgabemöglichkeiten auf der <a href="https://docs.oracle.com/javase/8/docs/api/java/text/SimpleDateFormat.html" target="_blank">offiziellen JavaDoc-Seite</a>

## Beispiele

```xml
<bx:tools.datum pattern="dd.MM.yyyy HH:mm:ss"/>
```

Ausgabe eines Zeitstempels, z.B. 13.03.2016 13:48:33

```xml
Angebote im Monat <bx:recordfield.Datum pattern="MMM"/>
```

Ausgabe des Monatsnamen

# Redakteurs-Tags

<!-- last_modified: 23. Mar 2015 -->
## Titel

```xml
<bx:tag.{titel} />
```

Alle Unterstriche / Underscores ( _ ) im `{titel}` Platzhalter werden in der Verwaltung durch Leerzeichen ersetzt. Zum Beispiel wird dann aus

```xml
<bx:text.Haupt_Titel />
```

dieses Feld in der Verwaltung:

![image2014-1-26 23:12:4.png](https://batix.help/uploads/images/gallery/2026-05/ElAXpUfteo28Vx7S-1572874.png)

## Mehrfachverwendung

Wird der gleiche `{titel}` mehrfach in einem Template oder in mehreren Templates im selben Menüpunkt verwendet, so stellt sich das Tag in der Verwaltung nur einmal dar. Der Redakteur muss den gewünschten Inhalt also nur an einer Stelle einpflegen. Alle gleichnamigen Tags werden dann mit diesem Inhalt versorgt.

<p class="callout warning">Es ist darauf zu achten, nur gleichartige Tags mit dem selben <code>{titel}</code> zu versehen. So machen z.B. <code>&lt;bx:text.Titel /&gt;</code> und <code>&lt;bx:bild.Titel /&gt;</code> im selben Menüpunkt keinen Sinn.</p>

Rechts neben dem Titel in der Verwaltung wird angezeigt, in welchen Templates ein Tag mit diesem Titel verwendet wird. Wird ein Tag in mehreren Templates verwendet, sieht dies z.B. so aus:

![image2014-1-26 23:12:14.png](https://batix.help/uploads/images/gallery/2026-05/WMnozcefYFFCakYP-1572875.png)

Es wird versucht etwaige Parameter der Tags sinnvoll zusammenzufassen. So wird z.B. bei bx:text der maximale Wert aller Tags für `maxlength` genommen.

## Kommentar

```xml
<bx:tag.{titel} [comment="{kommentar}"] />
```

In `{kommentar}` kann ein zusätzlicher Beschreibungstext angegeben werden, der in der Verwaltung unterhalb des Titels angezeigt wird. Beispiel:

**Eingabefeld mit Kommentar**

```xml
<bx:text.Titel comment="Dies ist der große Titel direkt unter dem Headerbild." />
```

![image2014-1-26 0:26:36.png](https://batix.help/uploads/images/gallery/2026-05/H4NkLn4khXnrCDhc-1572871.png)

## Admin-Mode

```xml
<bx:tagname.Titel admin-mode="config" /> 
```

Erzwingt, daß das Tag bei den Tageinstellungen (anstatt bei Dateneingabe) angezeigt wird. So sehen es die Redakteure nicht mehr und können es nicht mehr kaputtmachen.
Bei \<bx:containerfilter\> wird das schon automatisch so gemacht. Jetzt lässt es sich auch per Parameter bei anderen Tags steuern.

### Beispiele

```xml
<bx:text.farbcode admin-mode="config"/>
<bx:textarea.xml type="plain" wrap="off" admin-mode="config"/>
<bx:pageinclude.teaserpfad admin-mode="config"/>
```

Einige Beispiele, wo dies sinnvoll sein könnte.

## Admin-Titel

```xml
<bx:tagname.Titel admin-title="{anderer Titel}" /> 
```

In Verwaltung wird ein anderer Titel ausgeben als der beim Tag angegebene.

### Beispiele

```xml
<bx:bild.picture admin-title="Großes Logo"/>
```

genauere Bezeichnung des "picture"

```xml
<bx:textarea.Haedline admin-title="Headline"/>
```

im Nachhinein einen Schreibfehler zu korrigieren, wenn das Design schon oft in Gebrauch ist

Diese Tags können sich in der Verwaltung darstellen:

- [bx:bild](/books/cms-handbuch-entwickler/page/bxbild)
- [bx:cmpageinclude](/books/cms-handbuch-entwickler/page/bxcmpageinclude)
- [bx:datum](/books/cms-handbuch-entwickler/page/bxdatum)
- [bx:dezimal](/books/cms-handbuch-entwickler/page/bxdezimal)
- [bx:document](/books/cms-handbuch-entwickler/page/bxdocument)
- [bx:email](/books/cms-handbuch-entwickler/page/bxemail)
- [bx:optional](/books/cms-handbuch-entwickler/page/bxoptional)
- [bx:text](/books/cms-handbuch-entwickler/page/bxtext)

# Batix-Tags Referenz

Vollständige Referenz aller bx: Tags, alphabetisch.

# Batix-Tags Referenz

<!-- last_modified: 16. Jan 2017 -->
<span style="color: rgb(0,0,0);"><span style="color: rgb(255,0,0);">**Hinweis für (fast) alle Tags:** für Parameterwerte können auch</span> <span style="color: rgb(0,0,255);">[<span style="color: rgb(0,0,255);">Präfix-Variablen</span>](/books/cms-handbuch-entwickler/page/parameter-werte-prafixe) </span><span style="color: rgb(255,0,0);">eingesetzt werden.</span></span>

| Kategorie | Tags |
|-----------|------|
| Container-Tags | [bx:containerdata](/books/cms-handbuch-entwickler/page/bxcontainerdata) \| [bx:containerfilter](/books/cms-handbuch-entwickler/page/bxcontainerfilter)<br>[bx:containerloop](/books/cms-handbuch-entwickler/page/bxcontainerloop) \| [bx:containersearch](/books/cms-handbuch-entwickler/page/bxcontainersearch)<br>[bx:record](/books/cms-handbuch-entwickler/page/bxrecord) \| [bx:recordchoice](/books/cms-handbuch-entwickler/page/bxrecordchoice)<br>[bx:recorddata](/books/cms-handbuch-entwickler/page/bxrecorddata) \| [bx:recordfield](/books/cms-handbuch-entwickler/page/bxrecordfield)<br>[bx:tablechoice](/books/cms-handbuch-entwickler/page/bxtablechoice) \| [bx:tabledata](/books/cms-handbuch-entwickler/page/bxtabledata)<br>[bx:tablefield](/books/cms-handbuch-entwickler/page/bxtablefield) \| [bx:tablefilter](/books/cms-handbuch-entwickler/page/bxtablefilter)<br>[bx:tablekat](/books/cms-handbuch-entwickler/page/bxtablekat) \| [bx:tableloop](/books/cms-handbuch-entwickler/page/bxtableloop)<br>[bx:tablerecord](/books/cms-handbuch-entwickler/page/bxtablerecord) \| [bx:tablesqlfilter](/books/cms-handbuch-entwickler/page/bxtablesqlfilter)<br>[bx:userrecord](/books/cms-handbuch-entwickler/page/bxuserrecord) \| [bx:validation](/books/cms-handbuch-entwickler/page/bxvalidation)
 |
| Einfache Elemente | [bx:bild](/books/cms-handbuch-entwickler/page/bxbild) \| [bx:datum](/books/cms-handbuch-entwickler/page/bxdatum)<br>[bx:dezimal](/books/cms-handbuch-entwickler/page/bxdezimal) \| [bx:document](/books/cms-handbuch-entwickler/page/bxdocument)<br>[bx:email](/books/cms-handbuch-entwickler/page/bxemail) \| [bx:optional](/books/cms-handbuch-entwickler/page/bxoptional)<br>[bx:text](/books/cms-handbuch-entwickler/page/bxtext) \| [bx:textarea](/books/cms-handbuch-entwickler/page/bxtextarea)<br>[bx:titel](/books/cms-handbuch-entwickler/page/bxtitel)
 |
| Includes | [bx:cmpageinclude](/books/cms-handbuch-entwickler/page/bxcmpageinclude) \| [bx:groovy](/books/cms-handbuch-entwickler/page/bxgroovy)<br>[bx:include](/books/cms-handbuch-entwickler/page/bxinclude) \| [bx:javainclude](/books/cms-handbuch-entwickler/page/bxjavainclude)<br>[bx:jspinclude](/books/cms-handbuch-entwickler/page/bxjspinclude) \| [bx:pageinclude](/books/cms-handbuch-entwickler/page/bxpageinclude)
 |
| Listen/Schleifen | [bx:designloop](/books/cms-handbuch-entwickler/page/bxdesignloop) \| [bx:loop](/books/cms-handbuch-entwickler/page/bxloop)<br>[bx:schleife](/books/cms-handbuch-entwickler/page/bxschleife) |
| Navigation | [bx:browse](/books/cms-handbuch-entwickler/page/bxbrowse) \| [bx:internlink](/books/cms-handbuch-entwickler/page/bxinternlink)<br>[bx:navigation](/books/cms-handbuch-entwickler/page/bxnavigation) \| [bx:navlink](/books/cms-handbuch-entwickler/page/bxnavlink)<br>[bx:sitemap](/books/cms-handbuch-entwickler/page/bxsitemap) \| [bx:submenu](/books/cms-handbuch-entwickler/page/bxsubmenu)
 |
| Zugriffskontrolle | [bx:access](/books/cms-handbuch-entwickler/page/bxaccess) \| [bx:login](/books/cms-handbuch-entwickler/page/bxlogin)<br>[bx:userdata](/books/cms-handbuch-entwickler/page/bxuserdata) \| [bx:userrecord](/books/cms-handbuch-entwickler/page/bxuserrecord) |
| Sonstige | [bx:admincomment](/books/cms-handbuch-entwickler/page/bxadmincomment) \| [bx:barcode](/books/cms-handbuch-entwickler/page/bxbarcode)<br>[bx:calendarfield](/books/cms-handbuch-entwickler/page/bxcalendarfield) \| [bx:calendarloop](/books/cms-handbuch-entwickler/page/bxcalendarloop)<br>[bx:choice](/books/cms-handbuch-entwickler/page/bxchoice) \| [bx:clipboard](/books/cms-handbuch-entwickler/page/bxclipboard)<br>[bx:contact](/books/cms-handbuch-entwickler/page/bxcontact) \| [bx:cookie](/books/cms-handbuch-entwickler/page/bxcookie)<br>[bx:directorylisting](/books/cms-handbuch-entwickler/page/bxdirectorylisting) \| [bx:documentlist](/books/cms-handbuch-entwickler/page/bxdocumentlist)<br>[bx:editbutton](/books/cms-handbuch-entwickler/page/bxeditbutton) \| [bx:evaluate](/books/cms-handbuch-entwickler/page/bxevaluate)<br>[bx:frame](/books/cms-handbuch-entwickler/page/bxframe) \| [bx:head](/books/cms-handbuch-entwickler/page/bxhead)<br>[Bx:i18n](/books/cms-handbuch-entwickler/page/bxi18n) \| [bx:if](/books/cms-handbuch-entwickler/page/bxif)<br>[bx:ignore](/books/cms-handbuch-entwickler/page/bxignore) \| [bx:json](/books/cms-handbuch-entwickler/page/bxjson)<br>[bx:link](/books/cms-handbuch-entwickler/page/bxlink) \| [bx:mapping](/books/cms-handbuch-entwickler/page/bxmapping)<br>[bx:math](/books/cms-handbuch-entwickler/page/bxmath) \| [bx:option](/books/cms-handbuch-entwickler/page/bxoption)<br>[bx:pagedata](/books/cms-handbuch-entwickler/page/bxpagedata) \| [bx:paypal](/books/cms-handbuch-entwickler/page/bxpaypal)<br>[bx:plugin](/books/cms-handbuch-entwickler/page/bxplugin) \| [bx:relativelink](/books/cms-handbuch-entwickler/page/bxrelativelink)<br>[bx:scanner](/books/cms-handbuch-entwickler/page/bxscanner) \| [bx:secureform](/books/cms-handbuch-entwickler/page/bxsecureform)<br>[bx:sessiondata](/books/cms-handbuch-entwickler/page/bxsessiondata) \| [bx:statistik](/books/cms-handbuch-entwickler/page/bxstatistik)<br>[bx:systemdata](/books/cms-handbuch-entwickler/page/bxsystemdata) \| [bx:tools](/books/cms-handbuch-entwickler/page/bxtools)<br>[bx:websearch](/books/cms-handbuch-entwickler/page/bxwebsearch) \| [bx:xml](/books/cms-handbuch-entwickler/page/bxxml)
 |
| Veraltet/Deprecated | [bx:containerkat](/books/cms-handbuch-entwickler/page/bxcontainerkat) \| [bx:gif](/books/cms-handbuch-entwickler/page/bxgif)<br>[bx:news](/books/cms-handbuch-entwickler/page/bxnews) \| [bx:search](/books/cms-handbuch-entwickler/page/bxsearch)<br>[bx:submenulist](/books/cms-handbuch-entwickler/page/bxsubmenulist) |

## Syntax-Konventionen

```xml
<bx:tag1.{command} static="value" [not] />
<bx:tag2 [optional="(option1 | option2)"] />
<bx:tag3 [first | last] />
<bx:tag4 required="(option1 | option2)">{content}</bx:tag> <!-- 'content' darf auch leer sein -->
```
Zur besseren Lesbarkeit steht ein Leerzeichen vor dem Ende selbstschließender Tags, also vor `/>`.

Platzhalter sind mit `{ }` umschlossen (siehe `command` und `content`). Im Beschreibungstext der Tags werden die Platzhalter genauer bestimmt, z.B. welche Werte oder Typen zugelassen sind.

Optionaler Code ist mit `[ ]` umschlossen (siehe `not`, `optional` und `first` / `last`). Dies bedeutet, dass dieser Bereich komplett weggelassen werden kann.

Pflichtauswahlen werden mit `( )` und Auswahlen, die auch komplett weggelassen werden können, werden mit `[ ]` umschlossen. Die jeweiligen Möglichkeiten sind durch `|` getrennt.

Falls unbedingt nötig, sind Kommentare in der Form `<!-- Kommentartext -->` eingefügt, diese Art der Beschreibung sollte allerdings nur in Ausnahmefällen auftauchen.

Diese Beispiele sind laut der obigen Definition valide:

```xml
<bx:tag1.replace static="value" />
<bx:tag2 />
<bx:tag2 optional="option1" />
<bx:tag3 />
<bx:tag3 first />
<bx:tag4 required="option2">Lorem Ipsum</bx:tag>
```
Die folgenden Beispiele sind allerdings nicht valide (das Kommentar hinter jedem Beispiel beschreibt warum):

```xml
<bx:tag1 static="value" />       <!-- der Platzhalter 'command' muss gefüllt werden -->
<bx:tag1.replace />              <!-- der Parameter 'static' muss exakt aus der Definition übernommen werden -->
<bx:tag2 optional="option3" />   <!-- 'option3' steht nicht zur Auswahl -->
<bx:tag2 optional="" />          <!-- es muss eine der Optionen gewählt werden -->
<bx:tag3 middle />               <!-- 'middle' steht nicht zur Auswahl -->
<bx:tag4 required=""></bx:tag>   <!-- es muss eine Option für 'required' gewählt werden, leerer Taginhalt ist laut Kommentar in Ordnung -->
```

# bx:access

Der Inhalt des Tags `access` wird nur ausgegeben, wenn der Intranetbenutzer Zugriff auf einen gewählten Pfad besitzt.

```xml
<bx:access [ path="{pfad}" | current ] [not] [quiet]> Inhalt </bx:access>
<bx:access.{bez} [ size="{n}" ] [ maxlength="{n}" ] [not] [quiet]> Inhalt </bx:access.<bez>>
```
In der ersten Form wird der Pfad über den Parameter `path` festgelegt oder mit `current` der aktuelle Menüpunkt bezeichnet.
Falls dieser aber über die Verwaltung eingegeben werden soll, muss die zweite Form benutzt werden. 
Mittels `size` und `maxlength` lassen sich dann Textfeldbreite und maximale Eingabelänge festlegen.
 In jedem Fall erfolgt die Angabe des Pfades relativ, d.h. ohne /www/webname/. `not` kehrt das Verhalten um, der Inhalt wird also nur angezeigt, wenn der User **keine** Berechtigung hat.
 `quiet` bewirkt, dass kein Fehler ausgegeben wird, falls der Pfad nicht gefunden wird. .

# bx:admincomment

Mit dem Tag `admincomment` kann man in der Redakteursansicht in der Verwaltung einen Hinweistext zur Datenpflege ausgeben. Die Eingabe des Textes erfolgt auf der "Tag-Einstellungen"-Seite (wo die XML-Containerfilter stehen) in einem mehrzeiligen Textfeld. *ab V 2.6.3 RC14*

```xml
<bx:admincomment.Name headless type="html"/>
```
Möglichst weit oben einfügen, damit der Hinweistext auch ganz oben steht.

| headless | Überschrift (Name des Tags) wird weggelassen. |
| --- | --- |
| type | Es kann HTML eingegeben werden. |

## in Schleifen

Das Tag funktioniert auch in Unterschleifen. Allerdings muß dann der Parameter loopable mit angegeben werden.

```xml
<bx:admincomment.Name loopable/>
```
Sollte erst ab v2.7.1 verwendet werden. Es gibt momentan keine "Tag-Einstellungen"-Ansicht in Unterschleifen. Bei `<bx:containerfilter>` mit loopable wird die XML-Konfig. deshalb in der Redakteursansicht gezeigt. Dieses Tag zeigt ab v2.7.1 für Redakteure nur den Text und für Admins die Bearabeiten-Ansicht an. "Redakteur" bedeutet in diesem Fall, daß das "Quelltexte"-Modul freigeschaltet ist.

## als offenes Tag

Als offenes Tag mit Kommentar direkt im Design geht jetzt.

```xml
<bx:admincomment.Name>
  Kommentar
  zweite Zeile
</bx:admincomment.Name>

<bx:admincomment.Name type="html">
  <strong>Kommentar:</strong><br>
  zweite Zeile
</bx:admincomment.Name>
```

# bx:barcode

<!-- last_modified: 03. Jan 2017 -->
Mit dem Tag `barcode` können verschiedene 1D und 2D-Codes erzeugt werden (Beispiele siehe unten). Ein Check auf Fehler ist mit bx:if möglich. Die Größe ist frei wählbar. Das erzeugte Format ist PNG (ggf. mit Transparenz)

## Allgemeine Syntax

```xml
<bx:barcode.qr width="250" height="250" [type="path"] [rotate="90"]> Inhalt </bx:barcode.qr>
```

### Parameter für alle Typen
| <div style="width:20px"/>  | |
| --- | --- |
| width und height | Geben die Größe des Barcodes an.<br>Ein weißer Rand ist teilweise automatisch enthalten und kann bei manchen Typen auch beeinflusst werden. |
| type | **image**: (Standard) es wird ein img-Tag erzeugt, Parameter wie style oder class im Barcode-Tag werden in das img-Tag übernommen.<br>**path**: es wird nur der Pfad zum Bild ab "/" zurückgegeben (ohne Host, falls Haupthost-Haken im Projekt nicht gesetzt wurde).<br>**url**: es wird eine komplette URL zum Bild zurückgegeben (aufgerufener Host oder Projekt-Haupthost). |
| rotate | Positive Werte drehen das erzeugte Bild im Uhrzeigersinn, negative Werte entgegen (in Grad, z.B. 90).<br>Die Größe des erzeugten Bildes wird neu berechnet, um den rotierten Barcode unterzubringen (Hintergrund ggf. transparent). |
<p class="callout info">Es ist generell empfehlenswert einen minimalen Kontrast-Rand (z.B. in weiß) zu setzen, damit Barcodeleser den Code einfacher identifizieren können.</p>
<p class="callout warning">Es kann weitere Einschränkungen, je nach offizieller Spezifikation des jeweiligen Barcode-Types, geben, die hier nicht extra aufgeführt sind.Die Ausgabegröße des Barcode-Bilds musst nicht exakt der angegebenen `width` / `height` entsprechen (liegt aber zumindest nicht darüber). Falls eine pixelgenaue Ausgabe benötigt wird, sollte ein Container um das Bild gepackt werden.</p>

## Typ-spezifische Informationen

<p class="callout warning">Die gezeigten Beispiele müssen nicht unbedingt den Anforderungen des jeweiligen Standards entsprechen! Es können also auch potentiell invalide Barcodes entstehen. Es ist die Spezifikation des jeweiligen Types zu Rate zu ziehen!</p>

### 1-Dimensionale Codes

Bei allen 1-dimensionalen Codes kann der parameter `margin` verwendet werden. Dieser legt die Größe des Randes links und rechts fest (**0** für keinen Rand, Standard ist **10**).

| <div style="width:160px">Typ</div> | <div style="width:80px">Ausgabe</div> | Einschränkungen |
| --- | --- | --- |
| `<bx:barcode.codabar>` | ![image2015-11-27 9:48:1.png](https://batix.help/uploads/images/gallery/2026-05/QlPgQM5EY46jxlaV-4489272.png)"12345" | Beginnt und endet mit einem Guard-Zeichen aus: `ABCD`.<br>ODER beginnt und endet mit einem Guard-Zeichen aus: `TN*E`.<br>Falls keine Guards gesetzt sind, wird automatisch `A` genommen.<br>Enthält nur Zeichen aus: `0123456789-$:/.+` |
| `<bx:barcode.code_39>` | ![image2015-11-27 9:54:42.png](https://batix.help/uploads/images/gallery/2026-05/tOD5diIW1fLoND0T-4489273.png)"BATIX" | maximal 80 Zeichen aus: `0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. *$/+%` |
| `<bx:barcode.code_93>` | ![image2015-11-27 10:23:18.png](https://batix.help/uploads/images/gallery/2026-05/zqdigFiEkq0v3Ku2-4489275.png)"BATIX" | maximal 80 Zeichen aus: `0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%abcd*` |
| `<bx:barcode.code_128>` | ![image2015-11-27 10:26:21.png](https://batix.help/uploads/images/gallery/2026-05/h8CjNIoELsLSy8oO-4489276.png)"BATIX" | maximal 80 Zeichen |
| `<bx:barcode.itf>`<br>(Interleaved Two of Five) | ![image2015-11-27 10:32:32.png](https://batix.help/uploads/images/gallery/2026-05/Yb2zNC2UlqGUevUZ-4489277.png)"123456" | Weniger als 80 Ziffern, gerade Anzahl<br>Am besten 6, 10, 12, 14, 16, 24, oder 44 Ziffern |
| `<bx:barcode.ean_8>` | ![image2015-11-27 10:34:44.png](https://batix.help/uploads/images/gallery/2026-05/ZVUVVtwS7yYN8S3E-4489278.png)"12345678" | genau 8 Ziffern |
| `<bx:barcode.ean_13>` | ![image2015-11-27 10:36:37.png](https://batix.help/uploads/images/gallery/2026-05/pzJv9xE58PHgBrjV-4489279.png)"1234567891118" | genau 13 Ziffern<br>Prüfziffer muss stimmen |
| `<bx:barcode.upc_a>` | ![image2015-11-27 10:40:2.png](https://batix.help/uploads/images/gallery/2026-05/LKtxVH050pZs6Mao-4489280.png)"12345678910" | genau 11 Ziffern (ohne Prüfziffer, wird automatisch berechnet)<br>ODER genau 12 Ziffern (mit Prüfziffer) |
| `<bx:barcode.upc_e>` | ![image2015-11-27 10:43:3.png](https://batix.help/uploads/images/gallery/2026-05/ZQxQQ0Wz6hNW2qzo-4489281.png)"12345678" | genau 8 Ziffern |

### 2-Dimensionale Codes

#### `<bx:barcode.qr>`

##### Ausgabe
![image2015-11-27 9:45:35.png](https://batix.help/uploads/images/gallery/2026-05/ZJcf8qk6LorCFXGf-4489271.png)  
`"http://batix.de"`

##### Parameter
**ecl**  
gibt das ErrorCorrectionLevel an:
- L ~7% (Standard)
- M ~15%
- Q ~25%
- H ~30%

##### Einschränkungen
Die Länge des verschlüsselten Strings kann die Ausgabe beeinflussen.

<br>

#### `<bx:barcode.datamatrix>`

##### Ausgabe
![image2015-11-27 11:45:10.png](https://batix.help/uploads/images/gallery/2026-05/QVh00k4kd8qLMulu-4489285.png) ![image2015-11-27 11:50:45.png](https://batix.help/uploads/images/gallery/2026-05/PUCbwx0sd3PtUz1F-4489290.png) "http:/batix.de" (rechts mit shape=square)  
![image2015-11-27 11:47:0.png](https://batix.help/uploads/images/gallery/2026-05/bUFZXcsRbUoGPo29-4489288.png) ![image2015-11-27 11:50:0.png](https://batix.help/uploads/images/gallery/2026-05/THgNdwGgz68ZiOtg-4489289.png) "Lorem ipsum dolor sit amet" (rechts mit shape=rectangle)

##### Parameter
**shape**
- `none` (Standard, wird automatisch je nach Inhalt gewählt)
- `square` (Quadrat erzwingen)
- `rectangle` (Rechteck erzwingen)

<br>

#### `<bx:barcode.aztec>`

##### Ausgabe
![image2015-11-27 12:35:47.png](https://batix.help/uploads/images/gallery/2026-05/EpyeaC8oDO3Y42WG-4489292.png)  
`"http://batix.de"`

##### Parameter
**ecl**  
gibt das ErrorCorrectionLevel an (in %, (0 - 100)), 25 sollte Minimum sein.

**layers**  
gibt die Anzahl der Aztec-Layer an
- 0 (Standard): Minimum benutzen
- -1, -2, -3, -4: kompakter Modus
- 1 - 32: selbst angeben (nicht-kompakter Modus)

**charset**  
gibt den Zeichensatz an, der zur Codierung des Inhaltes verwendet werden soll.  
Standard ist utf-8.

<br>

#### `<bx:barcode.pdf_417>`

##### Ausgabe
![image2015-11-27 12:50:36.png](https://batix.help/uploads/images/gallery/2026-05/jfz6zgcoucWqKnE8-4489293.png)  
`"BATIX"`

##### Parameter

**margin**  
legt die Größe des Randes rundherum fest

**ecl**  
gibt das ErrorCorrectionLevel an.  
0 - 8, Standard ist 2.

**charset**  
gibt den Zeichensatz an, der zur Codierung des Inhaltes verwendet werden soll.  
Standard ist utf-8.

**compact**  
kompakten Modus benutzen? true oder false.  
Standard ist false.

**compaction**  
welcher Verdichtungsmodus benutzt werden soll.
- auto (Standard)
- text
- byte
- numeric

**dimensions**  
- minimale und maximale Spalten- (Cols) und Zeilenanzahl (Rows)
- kommagetrennte Zahlen
- Reihenfolge: minCols,maxCols,minRows,maxRows
- Standard: 2,30,2,30


## Fehlerabfrage

```xml
<bx:if><bx:barcode.ean_8>1234</bx:barcode.ean_8><bx:if.else>Es konnte leider kein Barcode erzeugt werden!</bx:if.else></bx:if>
```
Da bx:barcode im Fehlerfall nichts ausgibt, kann ein alternativer Text mittels [bx:if](/books/cms-handbuch-entwickler/page/bxif) ausgegeben werden.

### Beispiele

```xml
<bx:barcode.qr>Hallo</bx:barcode.qr>
 
<bx:barcode.datamatrix shape="rectangle">Hallo</bx:barcode.datamatrix>
```

# bx:bild

<!-- last_modified: 05. Mar 2020 -->
Das Tag `bild` fügt ein Bild aus der Bildergalerie in das Dokument ein und lässt vielfältige Möglichkeiten zur Formatierung. Falls dasselbe Bild mehrmals verwendet werden soll, kann { `titel}` mehrmals verwendet werden mit z.B. verschiedenen Größenangaben.

Dieses Tag kann sich in der Verwaltung darstellen.


## Bild anzeigen mit Größenangabe und Ausrichtung

```xml
<bx:bild.{titel} [width="{n}"] [height="{n}"] [align="(left | right | leftright | rightleft)"] [alt="{text}"] [comment={komentar}] />
```
| width, height | Breiten- bzw Höhenangabe in Pixel; Bilder, die kleiner sind als diese Größenangaben werden jedoch nicht vergrößert. Ist keine Höhe und Breite angegeben, wird das Bild in Originalgröße dargestellt. |
| --- | --- |
| cover | nimmt die größere Angabe, z.B. bei Querformat wird die Höhe, bei Hochformat die Breite genommen (ab V 2.6.3, ansonsten bei 2.6.2 reinkopieren) |
| cover="crop" | Originalbild wird abgeschnitten und auch so gespeichert |
| align | links- bzw. rechtsseitige Ausrichtung; leftright/rightleft: die Bilder werden abwechselnd ausgerichtet, beginnend links bzw rechts |

### Beispiele

**einfache Anzeige mit Alt-Angabe**
```xml
<bx:bild.Seitenbild width="700" height="150" alt="Seitenbild dieser Seite" />
```
**Anzeige mit Kommentar in der Verwaltung**

```xml
 <bx:bild.Seitenbild width="200" height="300" align="right" comment="nichts ausgewählt: Text zieht sich über die gesamte Breite" />
```

## Ausgabeart festlegen

```xml
<bx:bild.{titel} [type="(path | url | origwidth | origheight | title | author | alt | calcwidth | calcheight | id | inline)"] />
```
| path / url | es wird nur der lokale Pfad bzw die URL zum Bild ausgegeben (z.B. Angabe im img-tag oder bei Wechsel der Grafik durch JavaScript) |
| --- | --- |
| origwidth / origheight | schreibt nur die Originalbreite oder -höhe (z.B. für Popup-Fenster) |
| title | der ursprüngliche Dateiname (gespeichert direkt in der Bildergalerie beim Bild) |
| author | Autor, falls keiner angegeben "null" (gespeichert direkt in der Bildergalerie beim Bild) |
| alt | der Alternativtext (gespeichert direkt in der Bildergalerie beim Bild) |
| calcwidth / calcheight | die berechnete Größe (unter Beachtung von width und height) wird ausgegeben |
| empty | Abfrage, ob ein Bild verknüpft wurde (ab v 2.7.0), `not` kehrt die Bedingung um |
| id | ID in der Bildergalerie (ab v 2.6.2) |
| inline | erzeugt img-Tag mit Binärdaten in src (ab 2.6.1), sinnvoll bei Newsletter, da steht das Bild direkt in der Seite, also nicht als Link oder Anhang |
| base64data | Tagerweiterung für vcf (Outlook-Visitenkarte) mit Foto ab v2.6.6 |

### Beispiele

**Anzeige mit img-tag, Angaben kommen alle aus der Bildergalerie**

```xml
<img src="<bx:bild.Seitenbild width="200" height="300" type="url"/>" alt="<bx:bild.Seitenbild type="alt"/>" 
  title="<bx:bild.Seitenbild type="title"/>, Autor:<bx:bild.Seitenbild type="author"/>" >
```

## Weitere Angaben

```xml
<bx:bild.{titel} [hspace="{n}"] [vspace="{n}"] [kategorie="{kat}"] [force] [nogifshrink] [border="{n}"] [noborder] />
```
| <div style="width:120px"> |  |
| --- | --- |
| **vspace, hspace** | Vertikal- bzw. Horizontalabstand einstellen (in Pixel) |
| **nogifshrink** | falls das Bild ein GIF ist und es nicht automatisch verkleinert werden soll,  Animationen bleiben so erhalten |
| **kat, force** | es kann der Name einer Kategorie der Bildergalerie angegeben werden, aus der das Bild gewählt werden kann. Wenn zusätzlich noch force gesetzt ist, kann die Kategorie in der Verwaltung nicht gewechselt werden. |
| **border, noborder** | Einstellen der Rahmenbreite bzw. Rahmen abstellen |

# bx:browse

Das Tag `browse` gibt benachbarte Menüpunkte (ebenenübergreifend) zum Zweck des Blätterns aus.

```xml
<bx:browse.previous>Linktext</bx:browse.previous>
<bx:browse.previous (level="{level}" | root="{pfad}") [loop]>Linktext</bx:browse.previous>
<bx:browse.next>Linktext</bx:browse.next>
<bx:browse.next (level="{level}" | root="{pfad}"} [loop]>Linktext</bx:browse.next>
```
Es wird ein Link zum entsprechenden Menüpunkt erzeugt.

|  |  |
| --- | --- |
| **root** | übergeordneter Menüpunkt, der nicht verlassen werden soll; leer = alles |
| **loop** | Erzeugen einer Endlosliste (wenn es in einer Richtung nicht mehr weiter geht, wird am anderen Ende neu begonnen) |
| **level** | Ebenentiefe |

# bx:calendarfield

Mit dem Tag `calendar` kann man in einem Kalender Datumseinträge aus einem Container abbilden.

Beispiel eines Kalenders unter ["Kalender bauen"](/books/cms-handbuch-entwickler/page/kalender-bauen)

## calendarfield.if

```xml
<bx:calendarfield.if prevmonth | nextmonth | currentmonth | weekend | today | activeday | firstweekday | lastweekday | mark [parametername="false"]> Inhalt </bx:calendarfield.if>
```
Nur in CalendarLoop Schleife zu verwenden. Bei Angabe mehrere Parameter werden diese mit „und" verknüpft. Die Angabe [Parametername]="false" negiert diesen.

| prevmonth | prüft, ob Datum zum vorhergehenden Monat gehört |
| --- | --- |
| nextmonth | prüft, ob Datum zum nächsten Monat gehört |
| currentmonth | prüft, ob Datum zum aktuellen Monat gehört |
| weekend | prüft, ob Datum zu einem Wochenende gehört |
| today | prüft, ob Datum gleich dem heutigen Datum ist |
| activeday | prüft, ob Datum das Aktuelle ist |
| firstweekday | prüft, ob Datum der erste Wochentag ist (Montag) |
| lastweekday | prüft, ob Datum der letzte Wochentag ist (Sonntag) |
| mark | prüft, ob Datum ein markiertes ist |

### Beispiele

```xml
...
<bx:calendarfield.if currentmonth="false">class="othermonth"</bx:calendarfield.if>
...
```
Abfrage der Tage, die nicht zum angezeigten Monat gehören(, um sie z.B. andersfarbig zu markieren) Siehe auch ["Kalender bauen"](/books/cms-handbuch-entwickler/page/kalender-bauen)

## calendarfield.day

```xml
<bx:calendarfield.day [pattern="{pattern}"] [link]/>
<bx:calendarfield.day> Inhalt </bx:calendarfield.day>
```
Gibt den Tag aus. Auch als offenes Tag nutzbar, um auf die beinhalteten DS zuzugreifen z.B. `<bx:calendarfield.day><bx:recordfield.Titel/></bx:calendarfield.day>`

| pattern | Ausgabeformat angeben, Standard: dd |
| --- | --- |
| link | Ausgabe erfolgt in Form activeday=dd.MM.yyyy (Wenn bei activedayrequest des CalendarLoop ein anderer Name definiert wurde erfolgt die Ausgabe mit diesem Namen.) |

## calendarfield.week

```xml
<bx:calendarfield.week [object="{loopname}"] [link={prev | next}] />

```
| object | Name der CalendarLoop Schleife, wenn außerhalb verwendet |
| --- | --- |
| link | Ausgabe erfolgt in Form activeday=dd.MM.yyyy mit jeweils Tage +7 oder -7 (mit Kalender berechnet) (Wenn bei activedayrequest des CalendarLoop ein anderer Name definiert wurde erfolgt die Ausgabe mit diesem Namen.) |

## calendarfield.month

```xml
<bx:calendarfield.month [object="{loopname}"] [pattern="{pattern}"] [link={previous | next}] />
```
Gibt den aktuellen Monat aus.

| object | Name der CalendarLoop Schleife, wenn außerhalb verwendet |
| --- | --- |
| pattern | Ausgabeformat angeben, Standard: MM |
| link | Ausgabe erfolgt in Form activeday=dd.MM.yyyy mit jeweils Monat +1 oder -1 (mit Kalender berechnet) (Wenn bei activedayrequest des CalendarLoop ein anderer Name definiert wurde erfolgt die Ausgabe mit diesem Namen.) |

## calendarfield.year

```xml
<bx:calendarfield.year [object="{loopname}"] [pattern="{pattern}"] [link={previous | next}] />
```
Gibt das aktuelle Jahr aus.

| object | Name der CalendarLoop Schleife, wenn außerhalb verwendet |
| --- | --- |
| pattern | Ausgabeformat angeben, Standard: yyyy |
| link | Ausgabe erfolgt in Form activeday=dd.MM.yyyy mit jeweils Jahr +1 oder -1 (mit Kalender berechnet) (Wenn bei activedayrequest des CalendarLoop ein anderer Name definiert wurde erfolgt die Ausgabe mit diesem Namen.) |

## calendarfield.today

```xml
<bx:calendarfield.today [object="{loopname}"] [pattern="{pattern}"] [link] />
```
Gibt den heutigen Tag aus.

Ein anderes Datum als das heutige für `today` angeben: today="dd.MM.yyyy" angeben oder über den Request mit Angabe des Parameternamens mit todayrequest="" (Standard: today) - (Angabe in der Schleifendefinition)

| object | Name der CalendarLoop Schleife, wenn außerhalb verwendet |
| --- | --- |
| pattern | Ausgabeformat angeben, Standard: dd.MM.yyyy |
| link | Ausgabe erfolgt in Form activeday=dd.MM.yyyy, (Wenn bei activedayrequest des CalendarLoop ein anderer Name definiert wurde erfolgt die Ausgabe mit diesem Namen.) |

## calendarfield.activeday

```xml
<bx:calendarfield.activeday [object="{loopname}"] [pattern="{pattern}"] />
```
Gibt den aktiven Tag aus (Request).
Ein anderes Datum als das heutige für den aktuellen Tag angeben: activeday="dd.MM.yyyy" angeben oder über den Request mit Angabe des Parameternamens mit activedayrequest="" (Standard: activeday) - (Angabe in der Schleifendefinition)

| object | Name der CalendarLoop Schleife, wenn außerhalb verwendet |
| --- | --- |
| pattern | Ausgabeformat angeben, Standard: dd.MM.yyyy |
Diese Funktionalität wurde umgesetzt mit Unterstützung unseres Partners Obtineo (<a href="http://www.obtineo.de" target="_blank">www.obtineo.de</a>).

# bx:calendarloop

Das Tag `calendarloop` benötigt man zur Erzeugung eines Kalenders mit Container-Anbindung. Siehe auch [Kalender bauen](/books/cms-handbuch-entwickler/page/kalender-bauen)

```xml
<bx:calendarloop.{bezeichner} pool="{ID}" datestart="Datum_Beginn" dateend="Datum_Ende" [type="monthly | weekly"] [today="{dd.MM.yyyy}"] [todayrequest="{dd.MM.yyyy}"] [activeday="{dd.MM.yyyy}"] [activedayrequest="{dd.MM.yyyy}"]>
  Inhalt
</bx:calenderloop.{bezeichner}>
```
In der Administration kann zusätzlich ein Filter definiert werden, wie beim ContainerFilter Tag. Innerhalb der Schleife kann mit [bx:calenderfield](/books/cms-handbuch-entwickler/page/bx-calendarfield) auf die einzelnen Felder zugegriffen werden.

| pool | ID des Containers (geht leider nicht mit Namensangabe) |
| --- | --- |
| datestart | Angabe des Feldes mit dem Startdatum |
| dateend | Angabe des Feldes mit dem Enddatum (kann weg gelassen werden) |
| type | Monats- oder Wochenanzeige |
| today | Festangabe eines Datums |
| todayrequest | anderer Requestname als der Standardname (today) |
| activeday | Festangabe eines Datums |
| activedayrequest | anderer Requestname als der Standardname (activeday) |
Diese Funktionalität wurde umgesetzt mit Unterstützung unseres Partners Obtineo (<a href="http://www.obtineo.de" target="_blank">www.obtineo.de</a>).

# bx:choice

Das Tag `choice` zeigt seinen Inhalt abhängig vom aktuellen Hauptmenüpunkt an (z.B. für mehrsprachige Templates).

```xml
<bx:choice root="<nav>"> Inhalt </bx:choice>
```

# bx:clipboard

Das Tag `clipboard` wird verwendet, um sich Werte oder (Quell)Texte zu merken und später auf der Seite wieder auszugeben. Ausgaben von anderen Tags, welche selbst keine Vergleichsfunktionen bieten, können so auch ausgewertet werden (dazu einfach die Ausgabe des Tags mit `clipboard.cut` abfangen und danach mit `clipboard.if` vergleichen).

## clipboard.copy

```xml
<bx:clipboard.copy name="{name}" [trim]> Inhalt </bx:clipboard.copy>
```
Schreibt den Inhalt in das Clipboard und gibt ihn auch auf der Seite aus.

| name | Name des Clipboard, wird auch unter diesem Namen wieder eingefügt |
| --- | --- |
| trim | Entfernt Leerzeichen und Zeilenumbrüchen an Anfang und Ende des gespeicherten und auch des anzuzeigenden Bereiches *(ab v2.5.7)* |

## clipboard.cut

```xml
<bx:clipboard.cut name="{name}" [trim]> Inhalt </bx:clipboard.cut>
```
Schreibt den Inhalt in das Clipboard und gibt ihn aber nicht aus. Erklärung der Parameter: siehe oben

## clipboard.paste

```xml
<bx:clipboard.paste [encode="typ"] name="{name}"/>
```
Gibt den Inhalt des Clipboards aus.

| encode | Hiermit kann der ausgegebene Text für verschiedene Formate kodiert werden:htmljavascriptsql (zur Verwendung in SQL für Strings)sql-like (zur Verwendung in SQL mit LIKE)sql-rlike (zur Verwendung in SQL mit RLIKE und REGEXP)urlxml |
| --- | --- |

## clipboard.clear

```xml
<bx:clipboard.clear/>
```
Löscht alle Clipboard-Einträge. Um einen einzelnen Eintrag zu Löschen kann `<bx:clipboard.cut name="Name"/>` verwendet werden.

## clipboard.append

```xml
<bx:clipboard.append [name="{bereich1}"] [trim]>...</bx:clipboard.append>
```
Fügt den Inhalt des Tags zu den bereits gespeicherten Daten hinzu, anstatt die Daten (wie bei cut) zu überschreiben. Der spätere paste-Befehl kann dann die zusammengetragenen Daten ausgeben.

### Beispiele

```xml
<bx:clipboard.cut name="Test">Hallo </bx:clipboard.cut>
<bx:clipboard.append name="Test">Welt</bx:clipboard.append>
Ausgabe "<bx:clipboard.paste name="Test"/>"
```
Am Ende wird "Hallo Welt" ausgegeben.

## clipboard.if

```xml
<bx:clipboard.if [name="{name}"] value="{text}" [not] [trim]> Inhalt </bx:clipboard.if>
<bx:clipboard.if [name="{name}"] value="clipboard:{name}" [not] [trim]> Inhalt </bx:clipboard.if>
<bx:clipboard.if [name="{name}"] contains="{text}" [not]> Inhalt </bx:clipboard.if>
<bx:clipboard.if [name="{name}"] regex="{regex}" [not] [trim]> Inhalt </bx:clipboard.if>
<bx:clipboard.if empty [name="{name}"] [not] [trim]>
```
Damit ist es möglich, einen bestimmten Inhalt abzufragen. *(ab Version 2.5.9)*

| name | Titel des Clipboards |
| --- | --- |
| value  contains  regex | Clipboardinhalt wird mit `text` verglichen, Ausgabe des Tag-Inhalts bei Übereinstimmung (**equals** ist ein Alias von **value**)  Ausgabe des Tag-Inhalts, wenn `text` im Clipboardinhalt enthalten ist  Ausgabe des Tag-Inhalts, wenn der Clipboardinhalt dem `regex` entspricht (**matches** ist ein Alias von **regex**) |
| trim | entfernt Leerzeichen und Zeilenumbrüchen an Anfang und Ende des Clipboard-Inhalts für die Prüfung |
| not | kehrt die Funktionalität um |
| empty | Abfrage, ob Clipboard leer oder nicht gesetzt ist |

### Beispiele

```xml
<bx:clipboard.copy name="text">Hallo Welt </bx:clipboard.copy>
<bx:clipboard.if name="text" value="hallo welt" trim>angezeigt</bx:clipboard.if>
<bx:clipboard.if name="text" contains="welt">angezeigt</bx:clipboard.if>
<bx:clipboard.if name="text" regex=".*Welt ">angezeigt</bx:clipboard.if>
```

# bx:cmpageinclude

Mit dem Tag `cmpageinclude` können Sie andere CM-Seiten einbinden. Es ist eine Erweiterung von <a href="http://wiki.batix.net/index.php/Bx:include" target="_blank">Bx:include</a>. In der Administration kann aus einer Dropdown-Liste die gewünsche Seite ausgewählt werden (es muss keine URL angegeben werden).

Dieses Tag kann sich in der Verwaltung darstellen.

```xml
<bx:cmpageinclude.<bezeichner> navid="{navid}" [jsp] [sendnav] />
```
| navid | ID eines Menüpunktes, von dem die Unterpunkte auswählbar sein sollen |
| --- | --- |
| sendnav | die NavID der Seite wird als Request-Parameter "nav" der einzubindenden Seite übergeben |
| jsp | echter JSP-Include |

### Beispiele

```xml
<div id="teaser"> 
  <bx:schleife.Teaser list="Titel">
    <!-- <bx:text.Titel/> -->
    <bx:cmpageinclude.Teaser_auswaehlen navid="14304C19DD0"/>
  </bx:schleife.Teaser>
</div> 
```
Dynamische Teaserauswahl beliebig vieler Teaser auf einer Menüpunkt-Verwaltungs-Seite.
Es wurde ein Menüpunkt Teaser (mit der Navid 14304C19DD0) angelegt mit den einzelnen Teasern als Unterpunkte, die dann auswählbar sind.

# bx:contact

Mit Hilfe des Tags  `contact` kann ein Kontaktformular erstellt werden. Die Ziel-Adresse kann über die Administration eingegeben werden. Wenn nichts eingegeben wird, wird die EMail-Adresse aus den Kundendaten genommen.

```xml
<bx:contact.{bez} [comment="{text}"] [name="{form}"] [onSubmit="{js}"] [nextpage="{seite}"]> Inhalt </bx:contact.{bez}>
```
Die Gestaltung des Formulars erfolgt als Inhalt des Tags. Es müssen nur noch Textfelder, Erklärungen, Submit-Button etc. erstellt werden.

| comment | zeigt zusätzlichen Text in der Verwaltung an |
| --- | --- |
| name | werden für das Formular übernommen |
| onSubmit | werden für das Formular übernommen |
| nextpage | Folgeseite |

# bx:containerdata

Das Tag `containerdata` zeigt zusätzliche Daten in bx:containerloop an. Wegen Systemkompatibilität unterstützt dieses Tag nicht das Interface ContainerLoop. Wenn Daten zu anderen Containerklassen benötigt werden kann bx:recorddata benutzt werden.

## ID

```xml
<bx:containerdata.id />
```
Diese Funktion gibt die ID des Datensatzes aus.

## Titel

```xml
<bx:containerdata.titel />
```
Es wird der Titel des Datensatzes angezeigt.

## ID = Request-Parameter

```xml
<bx:containerdata.isrequest [name="{parametername}"]> Inhalt </bx:containerdata.isrequest>
```
Der Inhalt wird nur ausgegeben, wenn der Requestparameter `<parametername>` die ID des aktuellen Datensatzes enthält.

|  |  |
| --- | --- |
| **parametername** | Request-Parameter<br>Falls "name" nicht gesetzt ist, wird der Standardwert "recordid" benutzt. |

# bx:containerfilter

Mit dem Tag `containerfilter` kann man eine Containerliste (spezifiziert durch die Container-ID oder den Container-Namen) nach Bedingungen filtern und aktivierte Elemente, die zutreffen, in einer Schleife durchlaufen lassen. Der Tag-Inhalt wird dabei für jedes gefundene Element ausgeführt.

Falls {titel} angegeben ist, wird in der Administration ein Eingabefeld für die Filter-Bedingungen angezeigt (zu finden rechts in der Toolbox unter "Tag-Einstellungen"). Alternativ kann auch eine Bedingung direkt im Tag angegeben werden.

Dieses Tag kann unter *Tag-Einstellungen* konfiguriert werden.

## mehrere Elemente (statische Angabe)

```xml
<bx:containerfilter.{titel} pool="(ContainerID | Containername)" force="list | top | standalone | match" [max="{n}"] [orderby="{feldname}"] [desc] [startindex="{n}"] [sql] [evalbx] [nulls-at-end] [id-descending-order] [force-parameter-reset] [loopable]>
  Inhalt
</bx:containerfilter.{titel}>
```
Die Parameter stehen statisch im Quelltext.

| titel | frei wählbarer Name des Filters |
| --- | --- |
| pool | ID oder  Name des Containers (ab Vers. 2.6.0) |
| force | Eine passende Wahl des Modus anhand der gewünschten Funktionen (einer oder mehrere Datensätze, Filterung ja/nein, Blättern ja/nein) trägt erheblich zur Performance-Steigerung bei, falls im Container sehr viele Datensätze vorhanden sind. So empfiehlt sich z.B. immer ein Modus ohne Blättern zu wählen, falls das Blättern nicht gebraucht wird. Die folgende Tabelle gibt Aufschluss über die verschiedenen Modi und zeigt jeweils, ob die Datensätze anhand der Filterung eingeschränkt werden bzw. ob ein Blättern möglich ist.<br>**Achtung**: Fehlt die Modusangabe, wird bei Vorhandensein des Standard-Requestparameters `recordid` eine Detailausgabe (`force=single`) ausgegeben, ansonsten eine Liste (`force=list`). Eine explizite Angabe von `force` wird empfohlen! | `force=` | Beschreibung | Filterung | Blättern | Performance | **list** | Liste von Datensätzenfür Standard-Blätterlisten |  |  |  | **top** | Liste von Datensätzen z.B. zur Anzeige der 3 aktuellsten News als Teaser |  |  |  | **single** | ein einzelner Datensatz, Übergabe der ID im Request Detailseite mit Einzel-Blätterfunktion zu einer Standard-Blätterliste |  |  |  | **match** | ein einzelner Datensatz, Übergabe der ID im Request geeignet für eine Detailseite mit Berechtigungs-Checks |  |  |  | **standalone** | ein einzelner Datensatz, Übergabe der ID im Request funktioniert wie [bx:record](/books/cms-handbuch-entwickler/page/bxrecord) |  |  |  |
| `force=` | Beschreibung | Filterung | Blättern | Performance |
| **list** | Liste von Datensätzenfür Standard-Blätterlisten |  |  |  |
| **top** | Liste von Datensätzen z.B. zur Anzeige der 3 aktuellsten News als Teaser |  |  |  |
| **single** | ein einzelner Datensatz, Übergabe der ID im Request Detailseite mit Einzel-Blätterfunktion zu einer Standard-Blätterliste |  |  |  |
| **match** | ein einzelner Datensatz, Übergabe der ID im Request geeignet für eine Detailseite mit Berechtigungs-Checks |  |  |  |
| **standalone** | ein einzelner Datensatz, Übergabe der ID im Request funktioniert wie [bx:record](/books/cms-handbuch-entwickler/page/bxrecord) |  |  |  |
| max | maximale Anzahl der auszugebenden Datensätze (z.B. max="5") |
| orderby | Feldangabe, nach der die Ausgabe sortiert sein soll (Datum, Name etc.) siehe auch bei `nulls-at-end` oder` id-descending-orderNEU: `Der Parameter orderby nimmt jetzt mehrere Feldnamen, getrennt durch Komma, Leerzeichen, Semikolon oder Pipe an und es kann über eine Einzelverknüpfung sortiert werden (siehe Beispiel) (ab V2.7) Dem Feldnamen kann man ein Pluszeichen für aufsteigende Sortierung (A..Z) oder ein Minuszeichen für absteigende Sortierung (Z..A) voranstellen (wenn kein `+` oder `-` vorangestellt ist, wird nach `desc` geschaut) |
| startindex | Stelle, an der die Ausgabe beginnen soll (Beginn bei 0) |
| desc | dreht die Sortierrichtung um |
| sql evalbx | statt Filterangaben kann in den Tag-Einstellungen eine SQL angegeben werden (siehe Beispiel) wenn angegeben, können in der SQL bx-Tags benutzt werden |
| nulls-at-end | null-Felder werden am Ende ausgegeben |
| id-descending-order | nach ID absteigend sortieren |
| force-parameter-reset | bewirkt, daß bei einer Containerfilter-Schachtelung der innere Container bei jedem Durchlauf des äußeren neu initialisiert wird (intern, Debugging) ab v.2.6.6 |
| loopable | Filterangaben innerhalb eines Designloops |

### Beispiele

**Containerfilter-Aufruf im Quelltext**

```xml
<bx:containerfilter.Mitglieder pool="Mitglieder" force="list" max="10" orderby="Name" desc startindex="5">
  <bx:recordfield.Name/><br>
</bx:containerfilter.Mitglieder>
```
Es werden maximal 10 Namen der im Container "Mitglieder" gespeicherten Datensätze ausgegeben. Die Datensätze sind nach Name (orderby) sortiert, allerdings absteigend (z-a), da "desc" angegeben wurde. Die Ausgabe startet mit dem 5. Datensatz.
Filterungen können dann beim Menüpunkt unter "Tag-Einstellungen" (rechts unter "Tools") vorgenommen werden. Siehe auch "[Filter](/books/cms-handbuch-entwickler/page/filter)".

**Beispiel:** Folgender Filter gibt nur die Mitglieder aus, die im Vorstand sind (Verknüpfung mit einem Container, der "Rollen" enthält über das Feld "Rolle", ID ist die DS-ID der Rolle "Vorstand"):

**zugehöriger Filter**

```xml
<filter>
  <filter-object>
    <field>Rolle</field>
    <type>8</type>
    <static-value>12FF89E7458</static-value>
  </filter-object>
</filter>
```
**gleiches Beispiel wie oben, nur mit einer SQL:**

**Containerfilter-Aufruf im Quelltext**

```xml
<bx:containerfilter.Mitglieder pool="Mitglieder" sql>
  <bx:recordfield.Name/><br>
</bx:containerfilter.Mitglieder>
```
**zugehöriger Filter**

```xml
SELECT m.*
FROM bxc_mitglieder m
WHERE
  m.ACTIV = 'j'
  AND m.Rolle = '12FF89E7458'
ORDER BY m.Name DESC
LIMIT 5,10;
```
**Wieder gleiches Beispiel, allerdings wird die Rolle über den Request angegeben**

**Containerfilter-Aufruf im Quelltext**

```xml
<bx:containerfilter.Mitglieder pool="Mitglieder" sql evalbx>
  <bx:recordfield.Name/><br>
</bx:containerfilter.Mitglieder>
```
**zugehöriger Filter**

```xml
SELECT m.*
FROM bxc_mitglieder m
WHERE
  m.ACTIV = 'j'
  AND m.Rolle = '<bx:pagedata.request name="rolle"/>'
ORDER BY m.Name DESC
LIMIT 5,10;
```
**mehrere Sortierparameter:** ** (ab V2.7)**

Der Parameter orderby nimmt jetzt mehrere Feldnamen, getrennt durch Komma, Leerzeichen, Semikolon oder Pipe an. Dem Feldnamen kann man ein Pluszeichen für aufsteigende Sortierung (A..Z) oder ein Minuszeichen für absteigende Sortierung (Z..A) voranstellen.

**zugehöriger Filter**

```xml
<bx:containerfilter.Name orderby="-Datum,+Titel"> <!-- wenn kein + oder - vorangestellt ist, wird nach desc geschaut -->

<bx:containerfilter.Name orderby="-Datum,Titel" [asc]>
<bx:containerfilter.Name orderby="Datum,+Titel" desc>				<!-- ergeben die gleiche Sortierung wie das Beispiel oben -->

<bx:containerfilter.Name orderby="-Jahr -Monat -Tag">      
<bx:containerfilter.Name orderby="Jahr Monat Tag" desc>        <!-- ergeben auch beide die selbe Sortierung.
```
**Sortierung über Einzelverknüpfung:** (ab V2.7)Sortierung über Einzelverknüpfung ist auch für jedes Feld möglich:

**zugehöriger Filter**

```xml
<bx:containerfilter.Name orderby="Kategorie/Titel;-Preisgruppe/Nummer">
```
Dreimal anders und doch das Gleiche

**zugehöriger Filter**

```xml
<bx:containerloop orderby="-Datum,+Titel">
<bx:containerloop orderby="-Datum,Titel" [asc]>
<bx:containerloop orderby="Datum,+Titel" desc>
```
noch ein Beispiel

**zugehöriger Filter**

```xml
<bx:containerloop orderby="-Jahr -Monat -Tag"> ist das gleiche wie
<bx:containerloop orderby="Jahr Monat Tag" desc>
```

## mehrere Elemente (dynamische Angaben im Request)

```xml
<bx:containerfilter.{titel} pool="(ContainerID | Containername)" [force="list"] [maxparam="{param}"] [orderbyparam="{param}"] [directionparam="{param}"] [indexparam="{param}"]> 
  Inhalt
</bx:containerfilter.{titel}>
```
Die Parameter werden im Request übergeben.

| {titel} | frei wählbarer Name des Filters |
| --- | --- |
| pool | ID oder  Name des Containers (ab Vers. 2.6.0) |
| force | Ausgabemodus Liste |
| orderbyparam | Parametername, mit dem das Sortierfeld übergeben wird, kann auch gleich mit der Sortierrichtung gekoppelt werden, z.B. "+Name" und "-Name" für Sortierung nach Name aufsteigend bzw. absteigend **NEU**: reagiert jetzt auch auf mehrfach vorkommende Request-Parameter (siehe Beispiel) (ab V2.7) |
| directionparam | Parametername für die Sortierrichtung: + für aufsteigend, - für absteigend |
| maxparam | Parametername für die maximale Anzahl der auszugebenden Datensätze (pro Seite) |
| indexparam | Stelle, an der die Ausgabe beginnen soll (Standard: "index") **NEU:** wird nur noch beachtet wenn kein + (%2B) oder - im Request-Parameter vorangestellt sind (ab V2.7) |

### Beispiele

```xml
<bx:containerfilter.aktuelleAngebote pool="Artikel" force="list" maxparam="max" orderbyparam="titel" directionparam="direction" indexparam="index"> 
  <bx:recordfield.Titel/>&nbsp;<bx:recordfield.Preis pattern="0.00"/><br>
</bx:containerfilter.aktuelleAngebote>
```
Diesen Filter findet man oft auf blätterbaren (Angebots-)Seiten. In diesem Beispiel werden alle Artikel mit Preis gelistet. Dann kann der Kunde selbst entscheiden (Form mit entsprechenden Auswahlmöglichkeiten - fehlt im Beispiel), wieviele Datensätze pro Seite angezeigt werden sollen (maxparam), nach welchem Feld sortiert werden soll (orderbyparam), z.b. Name, Preis, Datum, ob auf- oder absteigend sortiert sein soll (directionsparam).

Beim Blättern zwischen den Anzeigeseiten wird noch der Parameter "indexparam" gebraucht. Im Zusammenhang mit "maxparam" werden dann die jeweils pro Seite aufzulistenden Datensätze ermittelt.

```xml
<bx:containerfilter.Name orderbyparam="sort"> 
```
Mit dem Query-String ?sort=Name&sort=Vorname wird nun nach beiden Feldern sortiert. (ab V2.7)
Der Parameter directionparam wird nur noch beachtet wenn kein + (%2B) oder - im Request-Parameter vorangestellt sind.

## ein bestimmtes Element (über Request)

```xml
<bx:containerfilter.{titel} pool="(ContainerID | Containername)" force="single" idfield="{param}" [dummy]>
  Inhalt
</bx:containerfilter.{titel}>
```
Der Inhalt des Tags wird dann nur ausgegeben, wenn das gesuchte Element in der Ergebnisliste auftaucht, außer man gibt "dummy" an.

| {titel} | frei wählbarer Name des Filters |
| --- | --- |
| pool | ID oder  Name des Containers (ab Vers. 2.6.0) |
| force | Ausgabemodus Einzelausgabe |
| idfield | Parametername, der die ID des Datensatzes enthält (Standard: "recordid") |
| dummy | bei Fehlen des Parameters wird ein Datensatz simuliert (z.B. beim Erstaufruf von Formularen) |

### Beispiele

```xml
<bx:containerfilter.heimischeSingvoegel pool="Singvoegel" force="single" idfield="vogelid">
  <h1><bx:recordfield.Titel/></h1>
  <img src="<bx:recordfield.Bild width="250" height="180" type="path"/>" alt="<bx:recordfield.Titel/>">
  <bx:recordfield.Beschreibung/>
</bx:containerfilter.heimischeSingvoegel>
```
Typische Detailseite. Der Requestparameter "vogelid" enthält die ID des gewünschten Datensatzes. Möglicher Aufruf für dieses Beispiel: <a href="detail.htm?vogelid=1234567890">Elster</a>

## ein zufälliges Element

```xml
<bx:containerfilter.{titel} pool="(ContainerID | Containername)" force="random" [max="{n}"]> 
  Inhalt
</bx:containerfilter.{titel}>
```
Es wird ein zufälliges Element aus der Ergebnisliste ausgewählt. Ab Version 2.6.2 hat man auch die Möglichkeit, mehrere Random-Datensätze anzeigen zu lassen.

| {titel} | frei wählbarer Name des Filters |
| --- | --- |
| pool | ID oder  Name des Containers (ab Vers. 2.6.0) |
| force | Ausgabemodus Random (zufälliges Element) |
| max | Anzahl der auszugebenden Datensätze (ab Version 2.6.2) Standard: 1 |

### Beispiele

```xml
<bx:containerfilter.Kopfbild pool="Bilder" force="random"> 
  <div class="kopfbild">
    <img src="<bx:recordfield.Bild width="850" height="2000" type="path"/>" alt="<bx:recordfield.Titel/>">
  </div>
</bx:containerfilter.Kopfbild>
```
Bei jeden Seitenaufruf wird ein anderes Kopfbild angezeigt.

## Verknüpfte Tabelle filtern

```xml
<bx:containerfilter pool="(ContainerID | Containername)" base="{Anzeige-ID}" linkfield="{Verknüpfungsfeld}">
```
Durch diese Erweiterung kann auch eine mit der Haupttabelle verknüpfte Tabelle gefiltert werden.

| pool | ID oder  Name des Containers (ab Vers. 2.6.0) |
| --- | --- |
| base | ID des verknüpften Container (Name geht leider nicht) |
| linkfield | Name des Feldes in der Haupttabelle, das mit der Anzeige-Tabelle verknüpft ist |

### Beispiele

```xml
<bx:containerfilter.ArtikelKategorien pool="Artikel" base="0123456789" linkfield="Kategorie">
  <a href="artikelliste.htm?kat=<bx:recorddata.id/>"><bx:recordfield.Titel/></a><br>
</bx:containerfilter.ArtikelKategorien>
```
Es sollen nur Kategorien (im Container mit der ID "0123456789") aufgelistet werden, mit der auch Artikel (über das Feld "Kategorie") verknüpft sind. Kategorien ohne Artikel werden ignoriert. Allerdings werden auch deaktivierte Kategorien angezeigt, wenn der entsprechende Artikel aktiv ist.

## Bedingung im Tag

```xml
<bx:containerfilter pool="(ContainerID | Containername)" name="{Feldname}" type="{Vergleichsart}" value="{Vergleichswert}" [required] [dummy]>
  Inhalt
</bx:containerfilter>
```
**WICHTIG**: Der Filter darf keinen Bezeichner haben.
Es können auch die Parameter force, max, orderby, startindex angegeben werden (siehe oben bei `force`).

| {titel} | frei wählbarer Name des Filters |
| --- | --- |
| pool | ID oder  Name des Containers (ab Vers. 2.6.0) |
| name | Name des zu überprüfenden Feldes (siehe auch "[Filter](/books/cms-handbuch-entwickler/page/filter)") |
| type | Art des Vergleiches (siehe auch "[Filter](/books/cms-handbuch-entwickler/page/filter)") |
| value | gesuchter Wert (siehe auch "[Filter](/books/cms-handbuch-entwickler/page/filter)") **statisch**: einfach gesuchten Wert angeben (z.B. eine ID) **dynamisch**: mit Präfix (siehe auch "[Präfixe](/books/cms-handbuch-entwickler/page/parameter-werte-prafixe)") |
| required | wenn nicht vorhanden, dann wird nichts ausgegeben (ab Version 2.6.1) |
| dummy | im Detailmodus: wird kein Datensatz gefunden, wird ein Datensatz simuliert (Inhalt wird ausgegeben) Details dazu oben bei `force` |

### Beispiele

```xml
<bx:containerfilter pool="Bilder" name="Kategorie" type="8" value="1234567890" orderby="Titel">
  <img src="<bx:recordfield.Bild width="850" height="2000" type="path"/>" alt="<bx:recordfield.Titel/>">
</bx:containerfilter>
```
Alle Datensätze aus dem Container "Bilder", die im Feld "Kategorie" mit dem Datensatz mit der ID "1234567890" verknüpft sind, werden angezeigt.

## Bedingung im Clipboard

```xml
<bx:containerfilter pool="(ContainerID | Containername)" force="list" config="clipboard:config">
  Inhalt
</bx:containerfilter>
```
**WICHTIG**: Der Filter darf keinen Bezeichner haben.

| {titel} | frei wählbarer Name des Filters |
| --- | --- |
| pool | ID oder  Name des Containers (ab Vers. 2.6.0) |
| force | Ausgabemodus Liste |
| config | dynamische Konfiguration |

### Beispiele

```xml
<bx:clipboard.cut name="config" trim>
  <filter>
    <filter-object required="false">
      <field>Invalid</field>
      <type>4</type>
      <static-value>0</static-value>
    </filter-object>
    <filter-object required="false">
      <field>Anbieter</field>
      <type>8</type>
      <special-value>PARENTCONTAINER</special-value>
    </filter-object>
  </filter>
</bx:clipboard.cut>
```
Die Bedingung wird dynamisch zusammengestellt und im weiteren Verlauf für eine Container-Filterung genutzt.

## Bedingung in Systemeinstellungen

```xml
<bx:containerfilter.KontaktFilter pool="Kontakte" force="list" orderby="Name" config="system:filter_kontakte">
...
</bx:containerfilter.KontaktFilter>
```
Die Filterbedingungen werden in den Systemeinstellungen gespeichert.

# bx:containerkat

Das Tag `containerkat` listet Container, gefiltert nach einer verknüpften Kategorie.

** Deprecated - Veraltetes Feature**
Die hier aufgeführten Informationen beziehen sich auf eine veraltete Funktion, die nicht mehr weiterentwickelt wird und ggf. in zukünftigen Versionen nicht mehr unterstützt wird. Diese Funktion sollte deshalb nicht mehr benutzt werden.

```xml
<bx:containerkat[.bezeichner] pool="{id}" kat="{id}" linkfield="{feld}" [listid="{id}" | katidfield="{feld}" | parent | listall] [max="{n}"] [orderby="{feld}"] [desc]>
  Inhalt
</bx:containerkat[.bezeichner]>
```
| bezeichner | wenn angegeben und kein Modus angegeben, dann erscheint in der Verwaltung ein Drop-Down zur Auswahl der einschränkenden Kategorie |
| --- | --- |
| pool | ID oder Containername des zu listenden Containers |
| kat | ID oder Containername des Containers, der die einschränkenden Kategorie enthält |
| linkfield | Feldname, der die Verknüpfung zur Kategorie enthält |
| listid | ID der Kategorie (Modus: "feste Kategorie") |
| katidfield | Name des Requestfeldes, das die Kategorie-ID enthält  (Modus: "Kategorie aus Request") |
| parent | ohne Value  (Modus: "Kategorie aus übergeordneter Schleife") |
| listall | wenn Requestparameter fehlt, dann alle anzeigen, ohne `listall` wird nichts angezeigt |
| max | maximal Anzeigen (Überlauf) |
| orderby | Feld, nach dem sortiert wird |
| desc | Sortierreihenfolge umdrehen |

### Beispiele

```xml
<bx:containerkat.AlleWeine pool="Weine" kat="Anbaugebiete" linkfield="Anbaugebiet" max="9" orderby="Titel">
  <bx:recordfield.Titel/>
</bx:containerkat.AlleWeine>
```
Es werden alle Datensätze aus dem Container "Anbaugebiete" in der Verwaltung gelistet. Das ausgewählte Gebiet wird genommen, um "Weine" zu filtern. Das Verknüpungsfeld in "Weine" zu "Anbaugebiete" heißt "Anbaugebiet".

```xml
<bx:containerkat pool="Weine" kat="Anbaugebiete" linkfield="Anbaugebiet" katidfield="gebiet" listall max="9" orderby="Titel">
  <bx:recordfield.Titel/>
</bx:containerkat>
```
Ähnliches Beispiel wie oben, nur daß die Wahl des einzuschränkenden Anbaugebiets über den Request kommt. Wenn der Request "gebiet" fehlt, werden alle angezeigt (wegen `listall`).

# bx:containerloop

Das Tag `containerloop` listet Datensätze einer Datenliste.

In den unten aufgeführten Formen muss die ID eines vorhandenen Containers angegeben werden (`<id>`). Alternativ kann statt `<bx:containerloop pool="<id>"` auch `<bx:containerloop.<bez> definition="<id>"` verwendet werden. Hier muss dann ein Bezeichner (`<bez>`) angegeben werden, welcher in der Administration angezeigt wird. Ebenfalls wird hier die ID einer Container-Definition angegeben. In der Verwaltung wird dann eine Auswahlliste mit allen verfügbaren Containern angezeigt, die auf dieser Definition beruhen.

## eine Anzahl an Elementen

```xml
<bx:containerloop pool="{id}" [force={single | list | random | choice}] [indexparam="{param}" | index="{param}" | forceindex="{n}"] [max="{n}"] [show="all"] [orderbyparam="[+|-]{param}" [directionparam="{param}"] | orderby="{feld}" [desc]] >
  Inhalt 
</bx:containerloop>
```
Es werden die Listenelemente ab einer bestimmten Position ausgegeben, diese wird über ein Request-Parameter (`indexparam` oder `index`) festgelegt oder direkt dem Tag übergeben (`forceindex`). Standardmäßig werden alle Elemente ausgegeben, falls `max` angegeben ist, dann maximal nur `<n>`.

| pool | enthält die Containerid bzw. den Containernamen |
| --- | --- |
| indexparam | enthält den Request-Parameter-Namen, der die Startposition für die Ausgabe enthält |
| index | enthält die Startposition für die Ausgabe |
| forceindex | feste Angabe für die Startposition der Ausgabe |
| max | maximal Anzahl ausgegebener DS im Schleifendurchlauf |
| show="all" | auch Anzeige von inaktiven Elementen |
| orderbyparam | Sortierungsfeldangabe über einen Request-Parameter (`+` für aufsteigend und `-` für absteigend vor den Feldnamen) **NEU**: reagiert jetzt auch auf mehrfach vorkommende Request-Parameter (siehe Beispiel) (ab V2.7, siehe auch bei `containerfilter`) |
| directionparam | Sortierrichtung über einen Request-Parameter (wenn nicht bei `orderbyparam` vorangestellt) |
| orderby | Sortierfeld für die Anzeigereihenfolge (standardmäßig aufsteigend) `NEU: `Der Parameter orderby nimmt jetzt mehrere Feldnamen, getrennt durch Komma, Leerzeichen, Semikolon oder Pipe an und es kann über eine Einzelverknüpfung sortiert werden (siehe Beispiel) (ab V2.7) |
| desc | kehrt die Sortierreihenfolge um |
| force | **list:** Listenanzeige **single:** einzelner Datensatz **random:** <span style="color: rgb(71,71,71);">Erzwinge Einzelanzeige eines Zufallsdatensatzes</span> **choice:** <span style="color: rgb(71,71,71);">Erzwinge Listenanzeige einer im Request übergebenen Auswahl von Datensätzen, braucht idfield=...  (oder der Requestparameter heißt recordid)</span> |

### Beispiele

Containeranzeige: Listen- und Detailseite

**Listenseite**

```xml
<form>
  Sortierung nach:<br>
  Titel Preis
  
</form>

<bx:containerloop pool="Artikel" indexparam="anzeigeAb" max="10" orderbyparam="sortierfeld" directionparam="sortierrichtung" orderby="Titel">
  <a href="detail.htm?art=<bx:recorddata.id/>"><bx:recordfield.Titel/></a><br> 
</bx:containerloop>
```
In der Liste werden pro Seite 10 Artikel angezeigt (max).

**Detailseite**

```xml
<bx:containerloop pool="{id}" [indexparam="{param}" | index="{param}" | forceindex="{n}"] [max="{n}"] [show="all"] [orderbyparam="[+|-]{param}" [directionparam="{param}"] | orderby="{feld}" [desc]] >
  Inhalt 
</bx:containerloop>
```
**mehrere Sortierparameter:** ** (ab V2.7)**

Der Parameter orderby nimmt jetzt mehrere Feldnamen, getrennt durch Komma, Leerzeichen, Semikolon oder Pipe an. Dem Feldnamen kann man ein Pluszeichen für aufsteigende Sortierung (A..Z) oder ein Minuszeichen für absteigende Sortierung (Z..A) voranstellen.

**zugehöriger Filter**

```xml
<bx:containerloop orderby="-Datum,+Titel"> <!-- wenn kein + oder - vorangestellt ist, wird nach desc geschaut -->

<bx:containerloop orderby="-Datum,Titel" [asc]>
<bx:containerloop orderby="Datum,+Titel" desc>				<!-- ergeben die gleiche Sortierung wie das Beispiel oben -->

<bx:containerloop orderby="-Jahr -Monat -Tag">      
<bx:containerloop orderby="Jahr Monat Tag" desc>        <!-- ergeben auch beide die selbe Sortierung.
```
**Sortierung über Einzelverknüpfung:** (ab V2.7)Sortierung über Einzelverknüpfung ist auch für jedes Feld möglich:

**zugehöriger Filter**

```xml
<bx:containerloop orderby="Kategorie/Titel;-Preisgruppe/Nummer">
```

## ein zufälliges Element

```xml
<bx:containerloop pool="<id>" force="random" [show="all"] >
  Inhalt </bx:containerloop>
```
| id | Objekt-ID |
| --- | --- |
Es wird ein zufälliges Element der Liste ausgewählt. Falls `show="all"` gesetzt ist, werden auch inaktive Elemente in Betracht gezogen.

.

### Beispiele

```xml
<bx:tag.feature param="value" />
```

## ein bestimmtes Element

```xml
<bx:containerloop pool="<id>" force="single" [idfield="<param>"] >
  Inhalt </bx:containerloop>
```
| id | Objekt-ID |
| --- | --- |
| param | Name eines Request-Parameters |
Die ID des gewünschten Datensatzes wird durch ein Request-Parameter (festgelegt durch `idfield`, Standard ist "recordid") übergeben.

## mehrere bestimmte Elemente

```xml
<bx:containerloop pool="<id>" force="choice" [idfield="<param>"] [id="<idlist>"] [boundary="<text>"] [show="all"]
  [oderbyparam="[+|-]<param>" [directionparam="<param>"] | orderby="<feld>" [desc]] >
  Inhalt </bx:containerloop>
```
| id | Objekt-ID |
| --- | --- |
| param | Name eines Request-Parameters |
| text | beliebiger Text |
| idlist | Liste von IDs |
`idfield` gibt den Request-Parameter an, in welchem die Auswahl an Datensätzen steht. Es kann entweder eine Liste an IDs (getrennt durch Komma oder anderen Zeichen laut `boundary`) angegeben werden oder es wird der gleiche Request-Parameter (gleicher Name) mehrfach spezifiziert (für jeden gewünschten Datensatz einmal mit der entsprechenden Datensatz-ID). Alternativ kann die Liste der IDs im Attribut `id` übergeben werden.

Um auch hier inaktive Elemente anzuzeigen, muss `show="all"` gesetzt sein.

Die Möglichkeiten zur Sortierung sind die selben, wie unter <a href="http://wiki.batix.net/index.php/Bx:containerloop#eine_Anzahl_an_Elementen" target="_blank">eine Anzahl an Elementen</a>

Verweise auf diese Seite:

<a href="http://docs.batix.info/display/DEVS/bx%3Arecorddata" target="_blank">bx:recorddata</a>
<a href="http://docs.batix.info/display/DEVS/bx%3Atableloop" target="_blank">bx:tableloop</a>
<a href="http://docs.batix.info/pages/viewpage.action?pageId=19300386" target="_blank">bx:tableloop</a>
<a href="http://docs.batix.info/pages/viewpage.action?pageId=19300388" target="_blank">bx:recorddata</a>

<p>(4 Verweise)</p>

# bx:containersearch

Das Tag `containersearch` gibt eine Liste von Containerdatensätzen aus, die einem Suchergebnis in diesem Container entspricht. In der Liste sind nur aktive Datensätze enthalten.

```xml
<!-- Listenseite -->
<bx:containersearch pool="{id}" fields="{felder}" [indexparam="{param}"] [searchparam="{param}"] max="{n}" [listall]  [orderby="{feld}"] [desc]>
  Inhalt
</bx:containersearch>
 
<!-- Detailseite -->
<bx:containersearch pool="{id}" fields="{felder}" [searchparam="{param}"] max="{n}" [listall] [singleidname="{param}"] [orderby="{feld}"] [desc]>
  Inhalt
</bx:containersearch>
```
Erklärungstext.

| pool | ID des Containers |
| --- | --- |
| fields | die zu durchsuchenden Felder (durch Komma getrennt) |
| indexparam | Parameter, der den aktuellen Index hält (Standard: `searchidx`) |
| searchparam | gesuchter String (Standard: `search`) |
| max | maximale Anzahl an angezeigten Elementen |
| listall | Falls kein Suchbegriff angegeben wurde, wird nichts angezeigt, außer `listall` ist gesetzt |
| singleidname | Detailseite: Parameter, in dem die DS-ID steht |
| orderby | Feld, nach dem die Liste sortiert wird (Standard: nach Relevanz) |
| desc | kehrt Sortierung um |

### Beispiele

Beispiel für eine Listen-/Detailseite mit einer Suche im Container

**Listenseite**

```xml
<form action="index.htm" method="post">
  <input type="text" name="suchbegriff" value="<bx:pagedata.request name="suchbegriff"/>">
  <input type="submit" value="suchen">
</form>

<bx:containersearch.News pool="139439682C3" fields="Titel,Anmoderation,Text" indexparam="seite" searchparam="suchbegriff" max="2" listall  orderby="Titel">
  <a href="detail.htm?detail=<bx:recorddata.id/>"><bx:recordfield.Titel/></a> - Ranking: <bx:containersearch.rank/><br>
</bx:containersearch.News>

<bx:recorddata.nav object="News">
  <bx:recorddata.previouslist/> | <bx:recorddata.nextlist/>
</bx:recorddata.nav>
```
Der Container wird komplett gelistet, wenn kein Suchbegriff angegeben wurde. Wenn doch, dann wird in den Feldern Titel, Anmoderation und Text nach diesem Wort gesucht.

**Detailseite**

```xml
<bx:containersearch.News pool="139439682C3" fields="Titel,Anmoderation,Text" singleidname="detail" searchparam="suchbegriff" max="2" listall  orderby="Titel">
  <h1><bx:recordfield.Titel/></h1>
  <em><bx:recordfield.Anmoderation/></em><br>
  <bx:recordfield.Text/>
</bx:containersearch.News>

<a href="index.htm?seite=<bx:pagedata.request name="seite"/>">zurück</a>
```
Angabe von `singleidname`, damit der richtige Datensatz angezeigt wird. Der Zurück-Knopf enthält die Seite, die auf der Listenseite wiederum durch den Parameter `indexparam` gefunden wird.

## containersearch.rank

```xml
<bx:containersearch.rank/>
```
Innerhalb der obigen Schleife gibt dieses Tag den Rang des aktuellen Suchergebnisses zurück.

## containersearch.relevanz

```xml
<bx:containersearch.relevanz/>
```
Dieses Tag gibt innerhalb der Suchschleife die Relevanz des aktuellen Ergebnisses aus.

# bx:cookie

Mit diesem Tag können Cookies gesetzt/gelesen und Vergleiche angestellt werden. *(verfügbar ab Version 2.6)*

## bx:cookie

```xml
<bx:cookie name="{meinCookie}" [not] />
<bx:cookie name="{meinCookie}" [not] > ...Inhalt... </bx:cookie>
<bx:cookie name="{meinCookie}" value="{meinWert}" [not]> Ausgabe </bx:cookie>
```
Die Ausgabe von Cookies erfolgt einfach durch die Angabe von name. Mit Zeile 2 kann überprüft werden, ob es den Cookie überhaupt gibt. Weiterhin kann der gespeicherte Wert verglichen werden.

| name | name des gesetzten Cookies |
| --- | --- |
| value | Vergleichswert |
| not | kehrt die Bedingung um |

## cookie.cut

```xml
<bx:cookie.cut name="{meinCookie}" value="{meinWert}" [domain="..."] [path="..."] [maxage="..."] [secure] />
<bx:cookie.cut name="{meinCookie}" [...]> Wert für Cookie </bx:cookie.cut>
```
Hiermit kann ein Cookie gesetzt werden. Der Wert kann entweder über den Tag-Inhalt oder über value übergeben werden.

| name | Name des Cookies |
| --- | --- |
| value | Wert, der gesetzt werden soll |
| domain | für den Cookie gültige Domain Wenn nicht angegeben, wird diese vom Browser automatisch auf die aktuelle Domain gesetzt.  Wird z.B. als Domain "example.org" gesetzt, ist das Cookie auch unter "sub.example.org" verfügbar.  Es kann keine fremde Domain eingetragen werden. |
| path | Das selbe Prinzip wie für `domain` gilt für path.  Wird hier "/" eingetragen (Default-Wert) ist das Cookie auch unter "/sub/" verfügbar. |
| maxage | Verfallsalter des Cookies Valide Werte:   -1 (Default-Wert, Session-Cookie = wird gelöscht, wenn Browser geschlossen wird),   0 (Cookie wird sofort gelöscht, siehe auch cookie.delete)   Angabe in Sekunden (wie lang das Cookie gültig sein soll). |
| secure | secure legt fest, dass das Cookie nur über HTTPS übertragen werden soll. |

## cookie.copy

```xml
<bx:cookie.copy ... [...]
```
Funktioniert wie bx:cookie.cut, nur wird der Wert, der per Tag-Inhalt oder value gesetzt wird, noch zusätzlich ausgegeben.

## cookie.delete

```xml
<bx:cookie.delete name="{meinCookie}" [domain="..."] [path="..."] />
```
Mit diesem Befehl kann ein Cookie gelöscht werden. Es kann zusätzlich path (Standardwert "/") und domain angegeben werden (Erklärung siehe oben bei `cookie.cut).`

### Beispiele

```xml
<bx:cookie name="sprache" not >
  <bx:cookie.cut name="sprache">de</bx:cookie.cut>
</bx:cookie>
```
Wenn der Cookie "sprache" noch nicht gesetzt ist, wird als Sprache deutsch gesetzt.
Verweise auf diese Seite:

Keine Verweise gefunden.

### Suchbegriffe

Cookies

# bx:datum

Mit dem Tag `datum` kann ein Datum aus einem Kalender gewählt werden (z.B. um Verfallsdatum der Seite oder von einzelnen Elementen anzugeben).

Dieses Tag kann sich in der Verwaltung darstellen.

```xml
<bx:datum.{titel} [size="{n}"] [maxlength="{n}"] />
```
**size** - Feldgröße in der Administration

**maxlength** - maximale Eingabelänge des Feldes in der Administration

**![BspDatum1A.png](http://wiki.batix.net/images/f/f7/BspDatum1A.png)**

# bx:designloop

Das Tag `designloop` erzeugt eine Schleife von sortierbaren Designbausteinen.

**Früher mit Tabellen-Layout und alten Containern war das so gedacht**

```xml
<table border=0>
<bx:recordloop.Schleifenname [showmeta=”Meta-Wert”]>
  <tr>
    <td><bx:recordloopelement/></td>
  </tr>
</bx:recordloop.Schleifenname>
</table>
```
`<bx:recordloop.{Titel} [showmeta=”Meta-Wert”]>` ist ein erweitertes bx:schleife

`<bx:recordloopelement>` ist ein Platzhalter für den einzufügenden Designbaustein

**Jetzt das neu belebte bzw. eigentlich neue Tag mit neuen Containern:**

```xml
<bx:designloop.Schleifenname [showmeta=”Meta-Wert”]>
  <div style=””>
    <bx: designloopelement [dummy]/>
  </div>
</bx:designoop.Schleifenname>

```
In der Verwaltung wird eine Schleife von sortierbaren Designbausteinen angezeigt

Bei Klick auf eine Detailseite wird eine Konfiguration des Bausteins mit Auswahl des Designs und eines Containerdatensatzes angezeigt

Neu bei designloop:

-          ein Titel für das Schleifenelement kann eingegeben werden

-          es kann ein Element ohne Containerverknüpfung angelegt werden wenn der Parameter dummy angegeben wird

Zusätzlich werden optionale vom jeweilgen Baustein abhängige Eingabefelder (Texte,Bilder,..) angezeigt

| `<bx:designloop.{Titel} [showmeta=”Meta-Wert”]>` | erweitertes bx:schleife |
| --- | --- |
| `<bx:designloopelement [dummy]>` | Platzhalter für den einzufügenden Designbaustein |
| showmeta=”Meta-Wert” | zeigt einen Meta-Datenwert in der Liste mit an (ich glaube, das hatten wir bei IHK- und/oder  Kompetenzzentrum-Lehrgängen für eine Nummerierung der Kapitel gehabt z. B. „2.4.1“ als Meta-Wert) ) |
| Schleifenname | Titel der Schleife |
| dummy | Element kann auch ohne containerverknüpfung angelegt werden |
**<span style="color: rgb(255,0,0);">Zu beachten</span>**: Wird innerhalb eines Designloop eine Containerschleife verwendet in der wiederum ein bx:textarea o.ä. ausgegeben werden soll, dann muß ans bx:containerfilter `loopable` drangehängt werden.

```xml
<bx:record pool="test" id="12B10695FB1">
  <bx:containerfilter.Bild pool="test" force="list" loopable>
    <bx:recorddata.id/>: <bx:textarea.Titel/><br>
  </bx:containerfilter.Bild>
</bx:record>

```

### Beispiele

```xml
<bx:designloop.Content_Container>
  <bx:designloopelement dummy />
</bx:designloop.Content_Container>
```
Designloop, wie er beim Epona-Design eingesetzt wurde (z.B. Stadtwerke, Fröbeldekade)

### Beispiele One-Pager

**als Navigation**

```xml
<bx:schleife.Inhalte admin-mode="config">
  <a href="#<bx:loop.id/>"><bx:text.MenuTitel/></a>
</bx:schleife.Inhalte>

```
**eigentliche Schleife**

```xml
<bx:designloop.Inhalte>
  <a name="id<bx:loop.id/>"></a>
  <bx:clipboard.cut name="nichtAnzeigen"><bx:text.MenuTitel/></bx:clipboard.cut>
  <bx:designloopelement dummy />
</bx:designloop.Inhalte>

```
Keine Verweise gefunden.

# bx:dezimal

Mit dem Tag `dezimal` kann in der Verwaltung eine Zahl mit Nachkommastellen eingegeben werden. Man kann bestimmte Begrenzungen für die Eingabe bestimmen.

Dieses Tag kann sich in der Verwaltung darstellen.

```xml
<bx:dezimal.{bezeichner} [size="{n}"] [maxlength="{n}"] [nachkomma="{n}"] [minnachkomma="{n}"] [maxnachkomma="{n}"] [noformat] />
```
|  | <span style="color: rgb(0,0,0);">**Parameter für Anzeige in der Verwaltung**</span> |  | **<span style="color: rgb(0,0,0);">Parameter für Anzeige im Frontend</span>** |
| --- | --- | --- | --- |
| bezeichner | Name des Feldes in der Verwaltung | nachkomma | Anzeige auf der Website mit` n` Nachkommastellen, wird evtl. mit Nullen aufgefüllt wenn nicht angegeben, werden alle Kommastellen ausgegeben |
| size | Größe des Eingabefeldes in der Verwaltung (Standard 20) | minnachkomma | alternativ: Minimum an Nachkommastellen |
| maxlength | Maximale Eingebelänge für eine Zahl in der Verwaltung (Anzahl der Zeichen) | maxnachkomma | alternativ: Maximum an Nachkommastellen |
|  |  | noformat | Zahl wird nach US Formatierung ausgegeben (z.B. 1,337.23 statt normal 1.337,23). |

### Beispiele

```xml
<bx:dezimal.Preis size="10" maxlength="5" nachkomma="2" />
```
Man kann in das Feld "Preis" in der Verwaltung, das eine Breite von 10 hat, nur bis zu 5 Zeichen eingeben (incl. Komma). Auch wenn man nur "10" eingibt, wird auf der Website 10,00 angezeigt.

# bx:directorylisting

Mithilfe des Tags `directorylisting` lässt sich eine Verzeichnislistung der Dateiverwaltung darstellen.

## bx:directorylisting

```xml
<bx:directorylisting type="{mixed | group | files | folders}" [limit="<n>"] [folder="<pfad>"]
  [listfolder="<pfadID>"]>
  Inhalt</bx:directorylisting>
```
Folgende Typen sind möglich:

mixed Es werden Dateien und Verzeichnisse sortiert nach Name ausgegeben. group Dateien und Verzeichnisse werden gruppiert. files Es werden nur Dateien ausgegeben. folders Es werden nur Verzeichnisse ausgegeben.

Falls ein bestimmter Ordner angezeigt werden soll, kann dieser mittels `folder` übergeben werden, ansonsten wird das Hauptverzeichnis angenommen. Die Verzeichnisebene, die als Root gelistet werden soll, wird mittels `listfolder` übergeben. Die Ausgabe je Element lässt sich im Inhalt des Tags festlegen. Dabei können Sie die folgenden Elemente verwenden.

## directorylisting.isfile

```xml
<bx:directorylisting.isfile> Inhalt </bx:directorylisting.isfile>
```
Der Inhalt wird nur ausgegeben, wenn das aktuelle Element eine Datei ist.

## directorylisting.isfolder

```xml
<bx:directorylisting.isfolder> Inhalt </bx:directorylisting.isfolder>
```
Der Inhalt wird nur ausgegeben, wenn das aktuelle Element ein Verzeichnis ist.

## directorylisting.isparent

```xml
<bx:directorylisting.isparent> Inhalt </bx:directorylisting.isparent>
```
Der Inhalt wird nur ausgegeben, wenn das aktuelle Element das übergeordnete Verzeichnis ("..") ist.

## directorylisting.link

```xml
<bx:directorylisting.link [target="<ziel>"] />
<bx:directorylisting.link [target="<ziel>"]>Linktext</bx:directorylisting.link>
```
Falls das Element ein Verzeichnis ist, wird die Navigation bei Klick dort fortgesetzt, andernfalls wird die Datei angezeigt bzw. heruntergeladen.

| target | Zielfenster im Browser |
| --- | --- |

## directorylisting.filename

```xml
<bx:directorylisting.filename/>
```
Falls das Element eine Datei ist, wird der Dateiname ausgegeben.

## directorylisting.filesize

```xml
<bx:directorylisting.filesize unit="{b | k | m}" />
```
Falls das Element eine Datei ist, wird die Dateigröße ausgegeben.

| unit | bestimmt die Einheit ( Byte (b), Kilobyte (k), Megabyte (m) ) |
| --- | --- |

## directorylisting.filedate

```xml
<bx:directorylisting.filedata [pattern="<format>"] />
```
Falls das Element eine Datei ist, wird das Uploaddatum ausgegeben.

| pattern | Ausgabeformat, Standard ist: "dd.MM.yyyy". |
| --- | --- |

## directorylisting.titel

```xml
<bx:directorylisting.titel />
```
Falls das Element eine Datei ist, wird der Dateiname ausgegeben.

## directorylisting.description

```xml
<bx:directorylisting.description />
```
Falls das Element eine Date ist, wird die Beschreibung ausgegeben.

## directorylisting.previous

```xml
<bx:directorylisting.previous/>
<bx:directorylisting.previous>Linktext</bx:directorylisting.previous>
```
Dieses Tag steht außerhalb der Schleife. Es erzeugt einen Link zur vorherigen Seite, falls `limit` überschritten wurde. Standard-Linktext ist "zurück".

## directorylisting.next

```xml
<bx:directorylisting.next/>
<bx:directorylisting.next>Linktext</bx:directorylisting.next>
```
Dieses Tag steht außerhalb der Schleife. Es erzeugt einen Link zur nächsten Seite, falls `limit` übeschritten wird. Standard-Linktext ist "weiter".

# bx:document

Mittels des Tags `document` kann in der Verwaltung ein Dokument zugeordnet werden. Als Ausgabe ist ein Downloadlink oder nur die URL zu diesem Dokument möglich.

Dieses Tag kann sich in der Verwaltung darstellen.

```xml
<bx:document.{titel} [type="(url | path | link | id | name | filename | size | description)"] [unit="(b | k | kb | m | mb | auto)"] [pattern=""] [locale=""] [disposition="attachment|inline|none"]/>
```
| url | Ausgabe der URL zum Dokument |
| --- | --- |
| path | Ausgabe des Pfades zum Dokument |
| link | Ausgabe als Link |
| id | Ausgabe der Dokumenten-ID |
| name | Ausgabe des Original-Dateiname |
| filename | Ausgabe des Dateiname auf dem Server |
| size | Ausgabe der Dokument-Größe |
| description | Ausgabe der Description (Feld "Beschreibung" in der Dokumentenverwaltung) |
| unit | **(nur bei size-Angabe)**  Ausgabe in Byte (b), Kilobyte (kb oder k) oder Megabyte (mb oder m) bei auto: Angabe von pattern und locale möglich, Standard: `unit="b"` |
| pattern | **(nur wenn bei size=auto angegeben wurde) **Ausgabemuster festlegen, Standard:` pattern="#,##0"` |
| locale | **(nur wenn bei size=auto angegeben wurde) **Sprache festlegen, Standard:` locale="de_DE"` |
| disposition | siehe Beispiel2 |

### Beispiele

**einfache Verwendung**

```xml
Bewerbungsunterlagen als PDF: <bx:document.Bewerbungsunterlagen/>
```
**Ausgabe innerhalb eines a-Tags**

```xml
<a href="<bx:document.Protokoll type="path"/>">
  <bx:document.Protokoll type="name"/> | Größe: <bx:document.Protokoll type="size" unit="auto" pattern="#,###0.00" locale="en"/>
</a>
```
Ausgabe mit Nachkommastellen in englischer Schreibweise (Tausendertrenner ist Komma, Dezimaltrenner ist Punkt)

### Beispiele attachment

```xml
<bx:recordfield.Dokument disposition="inline"/>

```
Ausgabe: `http://domain/files/{Batix-ID}/{Dateiname}`setzt content-disposition:inline; filename=“{Dateiname}“, wird als Standard genommen, wenn nichts angegeben wird

```xml
<bx:recordfield.Dokument disposition="attachment"/>
```
Ausgabe:`http://domain/files/download/{Batix-ID}/{Dateiname} `
bewirkt bei PDFs einen Zwangsdownload anstatt eine Anzeige im Browser-Plugin, dasselbe auch durch `http://domain/files/{Batix-ID}/{Dateiname}?dl=true`

```xml
<bx:recordfield.Dokument disposition="none"/>

```
Ausgabe: `http://domain/files/media/{Batix-ID}/{Dateiname}`bewirkt bei MP4-Videos, die in Apple-Mobilgeräten abgespielt werden sollen, daß das funktioniert, weil der Header nicht geschrieben wird (scheint nur Apple-Geräte zu betreffen)
Verweise auf diese Seite:

Keine Verweise gefunden.

# bx:documentlist

Das Tag `documentlist` listet ein virtuelles Verzeichnis der Dokumentenverwaltung.

## bx:documentlist

```xml
<bx:documentlist [limit="{n}"] {folder="{pfad}" | folderid="{pfadID}"}> Inhalt </bx:documentlist>
```
Der Inhalt legt die Ansicht pro Element fest. Es können die folgenden Befehle verwendet werden.

| limit | Maximum an Ausgaben |
| --- | --- |
| folder | zu listendes Verzeichnis als Titel |
| folderid | zu listendes Verzeichnis als ID |

## documentlist.id

```xml
<bx:documentlist.id />
```
Dieser Befehl gibt die ID des Eintrags aus.

## documentlist.link

```xml
<bx:documentlist.link [target="<fenster>"] />
<bx:documentlist.link [target="<fenster>"]>Linktext</bx:documentlist.link>
```
Es wird ein Link zur Datei erstellt (auch freier Linktext möglich).

| target | Ziel-Browserfenster |
| --- | --- |

## documentlist.filename

```xml
<bx:documentlist.filename />
```
Der Dateiname aus dem System wird ausgegeben.

## documenlist.filesize

```xml
<bx:documentlist.filesize [unit="b | k | m"] />
```
Die Dateigröße wird ausgegeben.

| unit | Größeneinheit ( Byte (**b**), Kilobyte (**k**), Megabyte (**m**) ) |
| --- | --- |

## documentlist.filedate

```xml
<bx:documentlist.filedate [pattern="<format>"] />
```
Gibt das Uploaddatum der Datei aus.

| pattern | Anzeigeformat (Standard: "dd.MM.yyyy") |
| --- | --- |

## documentlist.titel

```xml
<bx:documentlist.titel />
```
Der Download-Dateiname wird geschrieben.

## documentlist.description

```xml
<bx:documentlist.description />
```
Die Beschreibung der Datei wird ausgegeben.

## documentlist.previous

```xml
<bx:documentlist.previous />
<bx:documentlist.previous>Linktext</bx:documentlist.previous>
```
Dieses Tag steht außerhalb der Schleife. Es erzeugt einen Link zur vorherigen Seite, falls `limit` überschritten wurde. Standard-Linktext ist "zurück".

## documentlist.next

```xml
<bx:documentlist.next/>
<bx:documentlist.next>Linktext</bx:documentlist.next>
```
Dieses Tag steht außerhalb der Schleife. Es erzeugt einen Link zur vorherigen Seite, falls `limit` überschritten wird. Standard-Linktext ist "weiter".

# bx:editbutton

<span style="color: rgb(0,0,0);">Mit dem Tag `editbutton` kann man im Frontend Buttons oder Links anzeigen, mit denen man in die Verwaltung an die richtige Stelle springen kann. Die Verwaltung muß offen sein.
</span>

<span style="color: rgb(0,0,0);"> </span>

```xml
<bx:editbutton [style="{classname}"] [class="{classname}"] [form-style="{classname}"] [form-class="{classname}"] target="{targetangabe}" label="{text}"/>

<bx:editbutton[.link] type="{container}" field="Feldname" [weitere Attribute z.B. class, id oder style] />
<!-- Neuer Datensatz (ab v 2.6.8)-->
<bx:editbutton[.link] type="{container}" [pool | baseloop]="{containername | containerid}" [weitere Attribute z.B. class, id oder style] /> 
<bx:editbutton[.link] type="container" sub="BilderListe" label="neues Bild" />

<bx:editbutton[.link] [type="nav"] />
<bx:editbutton[.link] [type="nav"] navid="navid" />
<bx:editbutton[.link] [type="nav"] function="{copy | sort | sortroot}" />
<bx:editbutton[.link] [type="nav"] file="{jsp-Datei in Verwaltung}" />

<bx:editbutton[.link] [type="nav"] />
```
Schreibt einen Edit-Button in Form einer HTML-Form mit Hidden-Feldern und einem `<input type=”submit”>` in die Seite, der bei Abschicken in einem neuen Tab in der Verwaltung eine Seite öffnet, <span style="color: rgb(0,0,0);">wenn der Benutzer Schreibzugriff (= Recht zum Speichern der Seite) auf den aktuellen Navigationspunkt hat.</span>

Das type=“nav“ kann weggelassen werden (ist Defaultwert und wegen Kompatbilität)

| link | Schreibt einen Link in die Seite anstatt eines Formulars (Form in Form ist nicht erlaubt, wenn Editbutton z.B. innerhalb einer Form ist) Weitere angegebenen Attribute werden einfach in den Edit-Link übernommen. |
| --- | --- |
| style | Styleangaben für das `<input type="submit">`-Feld |
| class | Klassenangabe für das `<input type="submit">`-Feld |
| form-style | Styleangaben für die umgebende Form |
| form-class | Klassenangabe für die umgebende Form |
| type="container" | ** innerhalb einer Containerschleife z. B. `<bx:record>` `<bx:containerfilter>` `<bx:recordfield.verknüpfung>`:** --> öffnet die Verwaltung und springt zum aktuellen Datensatz des Schleifendurchlaufs |
| field | Sprungmarke zum entsprechenden Feld |
| type="nav" | **innerhalb einer Navigationsschleife z. B. `<bx:navigation>` `<bx:navlink>` `<bx:submenu>`: **--> öffnet die Verwaltung und springt zum Menüpunkt des Schleifendurchlaufs<br>**innerhalb einer Contentschleife (`<bx:schleife>`, `<bx:designloop>`):** --> öffnet die Verwaltung und springt zum aktuellen Schleifenelement, auch mehrere geschachtelte Ebenen |
| navid | eine beliebige Nav-ID des Projektes Öffnet die Verwaltung und springt zum angegeben Menüpunkt |
| function | **copy**: Springt direkt zur Menüpunkt-kopieren-Seite **sort**: Springt direkt zur Untermenü-sortieren-Seite **sortroot**: Springt direkt zum Sortieren der Hauptebene **datalist**: Springt zur Container-Liste, die mit `pool` benannt ist (auf Anfrage) |
| file | Springt zu beliebiger Datei in Verwaltung mit „/“ am Anfang zu jsp in /verwaltung ansonsten zu virtueller Datei beim aktuellen Menüpunkt „kopieren.bx“, „sortieren.bx“ |
| pool\|baseloop | (ab v 2.6.8) pool analog containerfilter, baseloop, wenn die Schleife auch auf der Seite ist `<bx:editbutton[.link] type="container" pool="">` - Wenn die Schleife nicht auf der Seite steht |
| sub | Name des Untercontainer-Feldes (für neuer Untercontainer-Datensatz (siehe Beispiel 2)) |

### Beispiele

``

```xml
<bx:editbutton label="&#10000;"> 
```
schreibt ein ✐ als Buttontext

```xml
<bx:containerloop pool="Galerien">
   ...
   <bx:editbutton[.link] type="container" sub="BilderListe" label="neues Bild" />
 </bx:containerloop>
```

## Link in statischer Mail:

<a href="http://www.meine-domain.de/verwaltung/?client=12E2D639293&table=12EE71ADC48&record=[[recordid]]" target="_blank">http://www.meine-domain.de/verwaltung/?client=12E2D639293&table=12EE71ADC48&record=[[recordid]]</a>

## Anmeldeformular im Frontend (Anmeldung bei Verwaltung wird vermieden)

Folgendes Input-Feld muß ins Anmeldeformular:

```xml
<input type="hidden" name="editable" value="true">
```

# bx:email

Das Tag `email` stellt in der Verwaltung ein Eingabefeld für eine Email-Adresse zur Verfügung. Auf der Webseite wird diese mit "mailto" verlinkt dargestellt.

Wenn keine Email-Adresse eingegeben wurde wird nichts angezeigt. Bei einer ungültigen Email-Adresse wird in der Verwaltung das Eingabefeld farblich markiert.

Dieses Tag kann sich in der Verwaltung darstellen.

```xml
<bx:email.{bezeichner} [size="{n}"] />
```
| bezeichner | Name des Feldes in der Verwaltung |
| --- | --- |
| size | Größe des Eingabefeldes in der Verwaltung |
.

### Beispiele

```xml
<bx:email.Email size="<n>"] />
```
Wir in der Verwaltung in das Feld "Email" "test@batix.com" eingegeben, wird das zu: <a href="mailto:test@batix.com">test@batix.com</a> im Quelltext und auf der Website wird eine verlinkte Email-Adresse ausgegeben.

# bx:evaluate

Der Body dieses Tags `evaluate` wird ausgewertet und das Ergebnis ein zweites Mal bx-Tag-mäßig ausgewertet.

*Ab v2.6.3 ist folgender Anwendungsfall möglich:*
 Ein Konfigurationscontainer enthält ein (Quell-)Textfeld mit HTML + bx-Tags. Eine CM-Seite enthält einen Daten-Datensatz und darin eine Schleife über Datensätze des Konfigurationscontainers. Nun kann mit `<bx:evaluate><bx:recordfield.*Quelltextfeld* type="plain"/>` eine Ausführung des bx-Codes bewirkt werden. Im Quelltext-Containerfeld können mit z. B. `<bx:recordfield.*Feldname* baseloop="*Datenschleife*"/>` Daten aus dem äußeren Datencontainer ausgegeben werden.

```xml
<bx:evaluate [charset="( utf-8 | iso-8859-1 )"]> Tag, das ein Tag zurückgibt </bx:evaluate>
```
| charset | iso oder utf8 (wenn es Probleme gibt) |
| --- | --- |

### Beispiele

Ein Tag steht im Container, z.B. die Formel zur Berechnung von Bezahlarten oder Versandkosten, die sich dynamisch gestalten. Damit wird die Auswahl über feste IDs innerhalb der Seite gespart.

**Batix-Code im Container**

```xml
<bx:evaluate><bx:recordfield.QuellcodeSnippet type="plain" /></bx:evaluate>
```
<p class="callout warning">Darauf achten, dass Benutzer keine willkürlichen Quelltexte in dem Containerfeld speichern können!</p>
Ein Tag wird im Request übergeben: `test.htm?datum=<bx:tools.datum/>`

**Batix-Code im Request (nicht empfohlen)**

```xml
<bx:evaluate><bx:pagedata.request name="datum" /></bx:evaluate>
```
<p class="callout warning">Dies ist gefährlich, da der Benutzer im Normalfall den Request-Parameter beliebig manipulieren und somit sämtlichen Batix-Code ausführen kann!</p>

# bx:frame

Das Tag `frame` stellt Funktionen für Framesets zur Verfügung.

```xml
<bx:frame default="{pfad}" />
```
Um andere Seiten im Inhalts-Frame zu laden muss der Request-Parameter "dir" an das Frameset übergeben werden.

| default | gibt an, welche Seite standardmäßig im Frameset geladen werden soll |
| --- | --- |

## frame.script

```xml
<bx:frame.script [frameset="{pfad}"] />
```
Hiermit wird JavaScript Code in die Seite geschrieben, welcher das Frameset durchläd und die Seite im Inhalts-Frame anzeigt, falls sie nicht im Frameset geöffnet wurde. Dies passiert z.B. beim Öffnen von Links in Suchmaschinen.

| frameset | Falls das Frameset nicht die Startseite des Webs ist  (also nicht über <a href="http://IhreAdresse.de/www/webname/" target="_blank">http://IhreAdresse.de/www/webname/</a> aufgerufen wird),  muss der Parameter `frameset` verwendet werden. |
| --- | --- |

# bx:gif

Das Tag `gif` funktioniert ähnlich wie Bx:bild, nur wird hier die Grafik in den Dokumentenvorlagen ausgewählt.

** Deprecated - Veraltetes Feature**
Die hier aufgeführten Informationen beziehen sich auf eine veraltete Funktion, die nicht mehr weiterentwickelt wird und ggf. in zukünftigen Versionen nicht mehr unterstützt wird. Diese Funktion sollte deshalb nicht mehr benutzt werden.

```xml
<bx:gif.{titel} [type="url"] [name="{text}"] [border="{breitenangabe}"] [align="(top | middle | bottom)"] />
```
Falls type="url" angegeben ist, wird nur die URL zum Bild ausgegeben.

# bx:groovy

Mittels bx:groovy kann innerhalb eines Template einfach Groovy-Code ausgeführt werden.

## Groovy Code ausführen

```xml
<bx:groovy [includes="{Groovy-Bausteine}"] [nobody]> ... </bx:groovy>
```
Der Parameter `includes` (zur Kompatibilität auch `include` möglich) enthält einen oder mehrere (kommagetrennte) Titel von Groovy-Bausteinen. Diese werden in der angegebenen Reihenfolge zusammengesetzt. Danach wird noch der Groovy-Code im Tag-Body angehangen.

Die Angabe von `nobody` bewirkt, dass der Taginhalt nicht als Groovy-Code angesehen wird. Somit kann man selbst dynamische Sachen (via `includeTag.computeBody()`) auswerten.

### Beispiele

**Nur Code**

```xml
<bx:groovy>
println("Hello, World")
</bx:groovy>
```
**Include und Code**

```xml
<bx:groovy includes="MyLib">
MyLib.doStuff()
</bx:groovy>
```
**Nur Include**

```xml
<bx:groovy includes="MyLib,OtherLib" />
```
**Parameter übergeben und auslesen**

```xml
<bx:groovy name="clipboard:myName" age="25">
def name = includeTag.getStringParameter("name")
def age = includeTag.getIntParameter("age", 0)
 
println("Hello, $name")
if (age < 18) println("no access!")
</bx:groovy>
```
**nobody**

```xml
<bx:groovy includes="CheckRole" role="Admin" nobody>
  <p>Herzlich willkommen in der Administration</p>
</bx:groovy>
 
// CheckRole Groovy (Auszug):
def requestedRole = includeTag.getStringParameter("role")
if (hasRole(requestedRole)) {
  println(includeTag.computeBody())
}
```
Verweise auf diese Seite:

<a href="http://docs.batix.info/pages/viewpage.action?pageId=19300448" target="_blank">Verwendungsmöglichkeiten</a>
<a href="http://docs.batix.info/pages/viewpage.action?pageId=4849700" target="_blank">Verwendungsmöglichkeiten</a>

<p>(2 Verweise)</p>

# bx:head

Der Befehl `head` schreibt diverse Angaben zum Projekt in den Headbereich.

## head.style

```xml
<bx:head.style/>
```
Schreibt ein `<link rel="stylesheet" type="text/css" ...>` in die Seite. Dies Tag wird benutzt, wenn der Stylesheet nicht am Ende des `<head>`-Bereiches geschrieben werden soll, z.B. bei einer Browserweiche.

## head.setstatus

```xml
<bx:head.setstatus code="statuscode"/>
```
Setzt den Status-Code der Seite (normalerweise "200")

## head.setheader

```xml
<bx:head.setheader [type="int|date"] name="Name" value="value"/>
  oder 
<bx:head.setheader [type="int|date"] name="Name"> Inhalt </bx:head.setheader>

```
Erlaubt es, einen HTTP-Header für die Seite zu setzen (z.B. content-disposition, wenn ein Download angeboten werden soll)

| type | Standard: String (wenn nicht angegeben) |
| --- | --- |
| name | Name (des Tags???) |
| value | Angaben, die in den Head geschrieben werden sollen |

### Beispiele

```xml
<bx:head.setheader name="Cache-Control" value="no-cache"/>
```
Angabe, daß die Seite nicht gecacht werden soll.

```xml
<bx:head.setheader name="Expires" type="date"><bx:tools.datum day="+7"/></bx:head.setheader>

```

## head.cancelpage

```xml
<bx:head.cancelpage (redirect|forward)="{Weiterleitungspfad}" [clearbody] [intern]> [optional:Daten die in den Body des Redirects geschrieben werden] </bx:head.cancelpage>

```
Bricht die Tagauswertung der Seite ab und führt stattdessen ein Redirect oder Forward aus bzw. leitet auf eine Fehlerseite weiter.

| redirect | URL, auf die weitergeleitet werden soll (Adresse im Browser ändert sich) |
| --- | --- |
| forward | URL, auf die im Hintergrund geforwarded werden soll (Adresse im Browser bleibt erhalten) |
| clearbody | löscht den Inhalt des `<body></body>` |
| intern | nur in Kombination mit **redirect** (nicht** forward**)stellt sicher, dass die angegebene URL nicht auf eine externe Seite verweist nützlich für dynamische Weiterleitungen (z.B. URL aus Request), um Sicherheitslücken zu vermeiden (Open Redirect) |

### Beispiele

```xml
<bx:recordfield.Artikel_verfügbar not>
  <bx:head.cancelpage redirect="liste.htm?info=ausverkauft"/>
</bx:recordfield.Artikel_verfügbar>

```
Wenn Artikel ausverkauft ist, wird von dieser Seite auf die Listenseite weitergeleitet.

```xml
<bx:recordfield.Artikel_verfügbar not>
  <bx:head.cancelpage forward="ausverkauft.htm"/>
</bx:recordfield.Artikel_verfügbar>

```
Wenn Artikel ausverkauft ist, wird eine Fehlerseite (ausverkauft.htm) angezeigt, aber nicht weitergeleitet.

```xml
<bx:userdata.in>
  <bx:head.cancelpage redirect="../intra/" clearbody> <body>
    This page has <a href="../intra/">moved</a>.</body>
  </bx:head.cancelpage>
</bx:userdata.in>

```
Wenn User eingeloggt (z.B. auf einer Login-Seite nach dem Login), wird der Body gelöscht und es wird ein Link für eine Weiterleitung angezeigt.

## head.localblock

```xml
<bx:head.localblock/>

```
Schreibt die Angaben vom Feld "Include im Head" beim Projekt an die angegebene Stelle, anstatt direkt vor `</head>`.

## head.metatags

```xml
<bx:head.metatags [hidden] />

```
Legt die Position im `<head>` fest, an der die Keywords und Description vom Nav-Punkt erscheinen. (ab V 2.6.5)

| hidden | Wenn man Keywords und Description eingegeben hat, aber sie bei einem Design nicht anzeigen will, weil sie dort speziell zusammengebaut werden (kann man an beliebiger Stelle ins Design schreiben) |
| --- | --- |

# Bx:i18n

Das Tag `i18n` ist zur Unterscheidung von Text in unterschiedlichen Sprachen.

```xml
<bx:i18n.{Schluesselwort}/>
```
Voraussetzungen:

- Die Sprachbezeichnung (z.B. DE,EN...) wird in der Session unter der Variablen I18N gespeichert. (Standard ist "de")
- Es gibt für jede Sprache einen Container, der so heißen muß, wie die in der I18N gespeicherten Sprachbezeichnung (z.B. DE, EN...)
- In diesen Containern gibt es zwei Felder, die beliebig heißen können. In dem einen wird das Schlüsselwort gespeichert, in der anderen die Übersetzung. Für die Übersetzung ist es sinnvoll, ein HTML-Editorfeld zu nehmen, denn so kann man mit kleinen Schlüsselwörtern (z.B. Begrüßung) viel Text abbilden.

# bx:if

Das Tag `if` zeigt seinen Inhalt nur an, wenn eines oder mehrere innere Tags einen Inhalt besitzen.

```xml
<bx:if [type="{any | one | all}"] [trim] [rekursiv="{n}"] ] > Inhalt </bx:if>
<bx:if.1>...<bx:if.2>...<bx:if.else>...</bx:if.else>...</bx:if.2>...<bx:if.else>...</bx:if.else>...</bx:if.1> 
```
Bei mehreren geschachtelten Schleifen kann ein Bezeichner angegeben werden (ab Version 2.6.0.). Die else-Blöcke beziehen sich auf das jeweils direkt übergeordnete if.
Ab Version 2.6.2 kann man auch trim angeben, damit störende Leerzeichen und Umbrüche ignoriert werden (auf die das if sonst anschlagen würde).

| type="any" | Inhalt nur anzeigen, wenn mindestens ein Tag einen Inhalt hat |
| --- | --- |
| type="one" | Inhalt nur anzeigen, wenn genau ein Tag einen Inhalt besitzt |
| type="all" | (Standard) Inhalt nur anzeigen, wenn alle Tags einen Inhalt haben |
| trim | Check Leerzeichen und Umbrüche im zu prüfenden Inhalt (entspricht einem tools.trim um das zu prüfende Tag) |
| rekursiv | Check auch verschachtelte Ebenen, n gibt die Ebene an (siehe Beispiel) |

### Beispiele

```xml
<bx:if recursive="1" type="any">
  <ul>
    <bx:recordfield.alleAnsprechpartner>
      <li><bx:recordfield.Name/></li>
    </bx:recordfield.alleAnsprechpartner>
  </ul>
</bx:if>

Alternativ bisher:
<bx:iF>
  <ul>
    <bx:recordfield.alleAnsprechpartner>
      <bx:if><li><bx:recordfield.Name/></li></bx:if>
    </bx:recordfield.alleAnsprechpartner>
  </ul>
</bx:iF>

```
Ansprechpartner (mit umgebenenden <ul>) soll ausgegeben werden, wenn mindestens ein Ansprechpartner verknüpft ist (ist die Ebene 1)

## 

## if.else

```xml
<bx:if>
 zu prüfende <bx:tags>
 <bx:if.else [showalways]> 
  alternativer Text
 </bx:if.else> 
</bx:if> 

```
Der Inhalt dieses Tags wird immer dann ausgeführt, wenn die Bedingungen des übergeordneten Tests nicht zutreffen.

**Kurzform:**

```xml
<bx:if else=“keine Angabe“><bx:recordfield.Ansprechpartner/></bx:if> 

entspricht:

<bx:if>
  <bx:recordfield.Ansprechpartner/>
  <bx:if.else>
    keine Angabe
  </bx:if.else>
</bx:if> 
```
| showalways | Inhalt des else-Blocks wird immer ausgegeben* (ab *V2.6.1) siehe Beispiel |
| --- | --- |

### Beispiele

```xml
<bx:if>
  <a href="<bx:recordfield.Link />">
  <bx:if.else showalways> 
    <bx:recordfield.Bild />
  </bx:if.else>
  </a>
</bx:if> 
```
Hier wird in jedem Fall das Bild ausgegeben und nur falls `Link` gefüllt ist, wird ein a-Element um das Bild gesetzt.

## if.elseif

```xml
<bx:if>
  zu prüfende <bx:tags>
  <bx:if.elseif> 
    weiterer zu prüfender Inhalt
    <bx:if.else>
      alternativer Inhalt
    </bx:if.else>
  </bx:if.elseif> 
</bx:if> 
```
Statt `bx:if.else` kann auch `bx:if.elseif` verwendet werden. Die Besonderheit liegt darin, dass dieses Tag dann wie eine verschaltete if-Verzweigung wirkt, es startet also eine eigene Auswertung seines Inhalts.

### Beispiele

```xml
<bx:if>
  <bx:recordfield.Telefon/>
  <bx:if.elseif> 
    <bx:recordfield.Handy/>
    <bx:if.else>
      telefonisch nicht erreichbar
    </bx:if.else>
  </bx:if.elseif> 
</bx:if> 
```
Erst wird geprüft, ob eine Telefonnummer angegeben ist und wenn vorhanden ausgegeben. Wenn nicht, wird nach der Handynummer gefragt und wenn diese angegeben ist, ausgegeben. Wenn keine der beiden Felder ausgefüllt ist, wird der Text ausgegeben.

## if.ignore

```xml
<bx:if>
  zu prüfende <bx:tags>
  <bx:if.ignore>
    <bx:recordfield.wird_nicht_geprueft />
  </bx:if.ignore>
</bx:if>
```
Um Bereiche innerhalb eines `bx:if`-Tags von der Inhaltsprüfung auszuschließen, kann `bx:if.ignore` verwendet werden. Der Inhalt dieses Tags wird ganz normal auf der Seite angezeigt.

### Beispiele

```xml
<bx:if>
  <img src="<bx:recordfield.Bild type="path"/>" alt="<bx:if.ignore><bx:recordfield.Alt_Titel/></bx:if.ignore>">
</bx:if>
```
Wenn ein Bild angegeben ist, wird das img-Tag(Bild) angezeigt, der Alt-Titel, der erfahrungsgemäß nicht immer vorhanden ist, wird von der Prüfung ausgeschlossen, d.h. wenn er fehlt, bleibt der alt-Parameter leer, das Bild wird aber trotzdem ausgegeben.

## filter

Um JSP-Bausteine als Filter eines `bx:if`- oder `bx:if.elseif`-Tags zu verwenden, geben Sie als zusätzlichen Parameter `filter="<filtername>"` an. Die Entscheidung, ob der Inhalt ausgegeben wird oder nicht, wird dann dem Script überlassen. Die vorhergehende Auswertung durch das Tag selbst wird im Request-Parameter attrValue übergeben, welche über jenen Parameter auch geändert werden kann.

# bx:ignore

Um Bereiche eines Templates auszukommentieren kann das Tag `ignore` benutzt werden.

```xml
<bx:ignore> nicht auszuwertender Bereich </bx:ignore>
```
Bei einem auskommentierten Bereich im HTML-Code (mit <!-- und -->) wird der Quelltext dazwischen trotzdem vom CMS ausgewertet und in die Seite geschrieben. Dies führt zu einer schlechteren Performance. Deshalb ist die Verwendung von `<bx:ignore>` in solchen Fällen vorzuziehen.

# bx:include

Das Tag `include` bietet die Möglichkeit ein Textbaustein oder eine HTML-Seite einzufügen.
 **Hinweis:** Um auswertbare Seiten einzubinden, benutzen Sie bitte <a href="http://wiki.batix.net/index.php/Bx:cmpageinclude" target="_blank">bx:cmpageinclude</a> oder <a href="http://wiki.batix.net/index.php/Bx:jspinclude" target="_blank">bx:jspinclude</a>.

```xml
<bx:include (modul="{modulname}" | file="{filename}") />
```
Inaktiv geschaltene Textbausteine werden ab Version 2.5.7 nicht mehr angezeigt. 
In der **Vorschau** (Preview) werden allerdings auch die **inaktiven** Textbausteine **angezeigt**, damit man schon mal testen kann.

# bx:internlink

In der Administration bietet dieses Tag `internlink` die Auswahl eines Navigationspunktes und im Frontend zeigt es eine Verlinkung auf diesen Navigationspunkt an.

```xml
<bx:internlink.{bezeichner} [shortpath] [web="{projektname | ID des Projekts}"]/>
<bx:internlink.{bezeichner}> Linktext </bx:internlink.{bezeichner}>		<!-- es kann ein eigener Linktext angegeben werden -->
```
| shortpath | relativer Pfad wird ausgegeben (www wird weggelassen) |
| --- | --- |
| web | Angabe des  Projektes, um Menüpunkte dieses anderen Projektes auszuwählen |

# bx:javainclude

Mithilfe des Tags `javainclude` kann eine JSP-Datei eingebunden werden, die über die Dokumentvorlagen gepflegt wird.

```xml
<bx:javainclude modul="{bez}" [evalbx | evalbody] [quiet] [trim] />

<bx:javainclude modul="{bez}">[Text mit bx-Tags]</bx:javainclude>				<!-- zeigt Ausgaben, die im JSP gemacht werden, an. Der Text im Body des Include-Tags wird nicht ausgegeben -->
<bx:javainclude modul="{bez}" evalbody>[Text mit bx-Tags]</bx:javainclude>	<!-- verwirft Ausgaben, die im JSP gemacht werden, aber zeigt den Text im Body des Include-Tags an -->
<bx:javainclude modul="{bez}" evalbx>[Text mit bx-Tags]</bx:javainclude>		<!-- Wertet die Ausgaben aus dem JSP mit dem bx-Parser aus. Der Text im Body des Include-Tags wird nicht ausgegeben -->
```
| evalbx evalbody | steuert, ob der zurückgegebene Text nochmals evaluiert wird |
| --- | --- |
| quiet | es werden keine Fehlermeldungen ausgegeben |
| trim | Text wird getrimmt (es werden Leerzeichen und Zeilenumbrüche am Anfang und Ende abgeschnitten) |

### Beispiele

**Quelltext der Seite**

```xml
 ...
 <bx:javainclude modul="Baustein-Name" maxdays="14"><div>neu!</div></bx:javainclude>
 ... 
```
**Quelltext des JSP-Bausteins**

```xml
<%@taglib uri="/batix" prefix="batix"%>
 <%@page import="com.batix.admin.container.Record,com.batix.enterprise.DAT"%>
 <%@page import="java.util.Date,java.util.Calendar,com.batix.tags.ContainerLoop"%>
 <batix:taginfo><%
 Date limitDate;
 //auslesen eines selbst definierten Parameters vom <bx:javainclude>
 int days = includeTag.getIntParameter("maxdays", -1);
 Calendar cal = Calendar.getInstance();
 if (days>0) {
   cal.add(Calendar.DATE, -days);
 }
 cal.set(Calendar.HOUR_OF_DAY, 0);
 cal.set(Calendar.MINUTE, 0);
 limitDate = cal.getTime(); //das Vergleichsdatum
 
 //umgebende Containerschleife auslesen
 ContainerLoop loop = (ContainerLoop)includeTag.findParent(ContainerLoop.class);
 Record dok = loop.getCurrentRecord(); //aktueller Datensatz im Schleifendurchgang
 //Datumsfeld namens 'erstellt' aus dem Containerdatensatz lesen
 DAT dat = (DAT)dok.loadPublicField("erstellt", includeTag.checkConnection());
 Date date = dat!=null ? dat.getDate() : null;
 //wenn das gespeicherte Datum neuer als der Vergleichswert ist...
 if (date!=null && date.after(limitDate)) {
   StringBuffer htmlData = new StringBuffer();
   //...den Body des bx:include auswerten...
   includeTag.computeFrontend(htmlData);
   out.print(htmlData.toString().trim()); // ...und in die Seite schreiben
   //oder ab v2.5.6: out.print(includeTag.computeBody());
 }
 %></batix:taginfo>
```
Zeige Inhalt an, wenn Datensatz neuer ist als x Tage

# bx:json

Mit dem Tag `bx:json` können JSON Strukturen ausgelesen und einfach durchgegangen werden. Um schnell in tief verschachtelte Objekte zu gelangen, kann JsonPath genutzt werden.

## JSON laden

```xml
<bx:json data="[1, 2, 3]">...</bx:json>
<bx:json data="clipboard:json_data">...</bx:json>
<bx:json url="http://server/..." [encoding="utf-8"]>...</bx:json>
```
Das JSON-Dokument kann entweder direkt als Text übergeben werden (wobei der Umweg über ein Clipboard oder Attribut möglich ist), es kann aber auch eine URL angegeben werden, von der die Daten geladen werden (`encoding` gibt dabei an, mit welchem Zeichensatz die Daten eingelesen werden, Standard ist utf-8).

<p class="callout info">Im URL-Modus sendet das JSON-Tag nicht das Session-Cookie mit, da meist externe URLs aufgerufen werden und die SESSIONID nicht ausversehen preisgegeben werden soll.Falls die Daten von einem internen, geschützten Menüpunkt geladen werden (auf den der aktuell eingeloggte Benutzer Zugriff hat), kann `bx:jspinclude` verwendet werden - dieses schickt das Session-Cookie mit:

```xml
<bx:clipboard.cut name="json_data"><bx:jspinclude>/intern/api.json</bx:jspinclude></bx:clipboard.cut>
<bx:json data="clipboard:json_data">
  ...
</bx:json>
```
</p>
Der JSON-Parser akzeptiert auch nicht RFC-konformeres JSON, also z.B. Kommentare oder Keys, die nicht mit Anführungszeichen umgeben sind (<a href="https://google.github.io/gson/apidocs/com/google/gson/stream/JsonReader.html#setLenient-boolean-" target="_blank">Details siehe hier</a>).

Ist in den JSON-Daten ein Objekt kodiert, kann dieses mit geschachtelten Json-Tags durchgegangen werden; ein Array verhält sich wie eine Schleife; andere Datentypen haben ihre entsprechenden Funktionen (s.u.).

<p class="callout info">Falls die JSON selbst generiert wird, sollte zwecks Interoperabilität (z.B. Verwendung in JavaScript direkt) ein Objekt kodiert werden.Falls man nur einen String oder eine Zahl hat, kann man diese(n) einfach im Objekt unter einem Key angeben, also anstatt:
523
besser:
{ "data": 523 }</p>
Eine fortgeschrittenere Möglichkeit des Daten-Ladens, kann über das Attribut `application` realisiert werden. Hier gibt man den Name eines Application-Attributes an, in dem ein `JsonElement` gespeichert ist. Dieses wird dann vom Tag benutzt und es entfällt das String-Parsen. Dies ist nützlich bei Caches, die man global in der Application vorhalten kann, und die sich nicht oft ändern. Ein `JsonElement` kann mittels `Gson` und der `toJsonTree` Methode erzeugt werden (z.B. aus einer Map, die man mit Groovy zusammenbaut).

## JSON durchgehen

Die JSON-Struktur kann einfach via Tags durchgegangen werden:

```xml
<bx:json data="..."> <!-- Root-Tag -->
  <bx:json.Kunde> <!-- Sub-Tag -->
    Der Kunde heißt: <bx:json.Vorname /> <bx:json.Nachname />
    <bx:Json field="address home">
      Er wohnt in: <bx:json.Ort />
    </bx:Json>
  </bx:json.Kunde>
</bx:json>
```
Es ist jeweils die Angabe von `encode=...` möglich, um z.B. Ausgaben für URLs oder CSV zu encoden.

Das auszugebende Feld kann entweder im Tag-Titel (nach `bx:json.`, also im Beispiel "Kunde") oder im Parameter `field=""` (oben z.B. "address home") angegeben werden. Die Angabe via `field` ist nötig, falls der Feldname Sonderzeichen / Leerzeichen enthält.

Ist das zu parsende JSON kein Objekt oder Array, sondern z.B. ein String oder eine Zahl, kann das Root-Element direkt ausgegeben werden:

```xml
<bx:json data="12345" /> <!-- gibt 12345 aus -->
<bx:json data="'testing'" contains="test" true="Pass" false="Fail" /> <!-- gibt Pass aus -->
```
Wird versucht auf ein Feld zuzugreifen, das nicht existiert, wird nichts ausgegeben. Es kann alternativ via `dummy` ein Alternativwert (im JSON-Format) angegeben werden, der stattdessen genommen wird. Je nach Typ des Wertes in `dummy` (wird wie ein neues JSON geparst), stehen die Typ-spezifischen Funktionen (s.u.) zur Verfügung.

```xml
<!-- falls es kein Feld missingNumber gibt, wird automatisch der Wert 5 genommen -->
<bx:json.missingNumber dummy="5" lt="10">...</bx:json.missingNumber>
 
<!-- es können auch komplexe Sachen als Dummy spezifiziert werden, hier empfiehlt sich ein Clipboard -->
<bx:clipboard.cut name="objdummy">
{
  x: 5,
  s: ""
}
</bx:clipboard.cut>
<bx:json.missingObject dummy="clipboard:objdummy">...</bx:json.missingObject>
```
Da JSON-Tags (sowohl Root-Tags als auch Sub-Tags von Objekten oder Arrays) mehrfach verschachtelt sein können und man manchmal Sachen von Über-Über-...-Elementen ausgeben will, kann man via Tag-Titel oder `name` die Tags benennen und via `base` diese referenzieren (der Parameter `name` hat beim Suchen des passenden Parent-Tags Vorrang vor dem Tag-Titel). Das entspricht der Funktionalität von `baseloop` bei Containern. Mittels `base="$"` kann das Root-Tag referenziert werden (das Tag, bei dem die Daten geladen wurden). Die Angabe von base kann immer zusätzlich zu allen anderen Parametern erfolgen (z.B. können `base` und `path` gleichzeitig benutzt werden).

```xml
<bx:json data="..."> <!-- Root-Tag -->
  <bx:json.Sub>
    <bx:json.SubSub name="Kunde">
      <bx:json.SubSubSub>
        <bx:json.Feld base="Sub">
          <!-- selber Kontext, als wenn man direkt innerhalb von <bx:json.Sub> wäre -->
        </bx:json.Feld>
        <bx:json.Feld base="Kunde">
          <!-- selber Kontext, als wenn man direkt innerhalb von <bx:json.SubSub> wäre -->
        </bx:json.Feld>
        <bx:json.Feld base="$">
          <!-- selber Kontext, als wenn man direkt innerhalb des Root-Tags wäre -->
        </bx:json.Feld>
      </bx:json.SubSubSub>
    </bx:json.SubSub>
  </bx:json.Sub>
</bx:json>
```
Je nach Datentyp ergeben sich unterschiedliche Funktionen, die benutzt werden können:

### Null

Der Inhalt wird ausgeführt (oder nicht bei `not`), falls im JSON der Spezialwert `null` steht. Nicht vorhandene Elemente können so auch abgefragt werden (nicht vorhanden entspricht hier null).

```xml
<bx:json.Feld null>Feld war null oder nicht vorhanden</bx:json.Feld>
<bx:json.Feld null not>Feld war vorhanden und nicht null</bx:json.Feld>
```

### Boolean

Boolesche Werte können ähnlich wie Häkchenfelder im Container abgefragt werden. Eine kurze Version (geschlossenes Tag) mit `true` / `false` steht auch zur Verfügung.

```xml
<bx:json.Condition [not]>
  ...
</bx:json.Condition>
 
<bx:json.Condition [true=""] [false=""] />
```

### Number

#### ausgeben / formatieren

Zahlen können formatiert ausgegeben werden. Ist kein `pattern` angegeben, werden Ganzzahlen *ohne* und Kommazahlen *mit* Nachkommastellen ausgegeben. Der Tausender- und Dezimal-Trenner kann mittels `gs` bzw. `ds` spezifiziert werden. Der Rundungsmodus ist standardmäßig HALF_UP (normales kaufmännisches Runden) und kann via `rounding` geändert werden (<a href="https://docs.oracle.com/javase/8/docs/api/java/math/RoundingMode.html" target="_blank">siehe Java-Docs für mögliche Werte</a>).

```xml
<bx:json.Zahl [pattern=""] [locale=""] [gs=""] [ds=""] [rounding=""] />
```
`locale` sollte immer angegeben werden, da sonst die Standardeinstellung vom Server genutzt wird, die sich aber nach Updates oder Umzügen ändern kann.

#### vergleichen

Folgende Vergleiche sind möglich:

| Parameter | ausgeführter Vergleich |
| --- | --- |
| equals | == |
| gt | > |
| gte | >= |
| lt | < |
| lte | <= |
Das Ergebnis kann jeweils mit `not` umgekehrt werden. Für alle Vergleiche ist auch eine verkürzte Variante mit `true` / `false` möglich (hier wird der jeweilige Wert von `true` oder `false` ausgegeben).

```xml
<bx:json.Zahl [equals=""] [gt=""] [gte=""] [lt=""] [lte=""] [not]>
</bx:json.Zahl>
 
<bx:json.Zahl [equals=""] ... [true=""] [false=""] />
```

### Date

*Ab Version 2.6.8*

Da es im JSON keinen nativen Datumstyp gibt, wird mittels dem Tag-Parameter `date` der vorhande String-Wert im JSON als Datum interpretiert.

#### Eingabeformat

Ist lediglich `date` ohne weiteren Wert im Tag angegeben, werden einige Standard-<a href="https://docs.oracle.com/javase/8/docs/api/java/text/SimpleDateFormat.html" target="_blank">Patterns</a> unterstützt:

```xml
<bx:json.mydate date />
```
Es wird folgende Liste in dieser Reihenfolge durchprobiert:

- dd.MM.yy HH:mm:ss
- dd.MM.yy HH:mm
- dd.MM.yy HH.mm
- dd.MM.yy
- yyyy-MM-dd'T'HH:mm:ssZ (ISO 8601)
Alternativ kann ein eigenes Pattern angegeben werden:

```xml
<bx:json.mydate date="dd/MM/yyyy" />
```
Es muss nicht der gesamte String matchen. Möchte man z.B. aus dem Wert "20.08.2018 um 08:50" nur das Datum ziehen, genügt das Pattern `dd.MM.yyyy`.

#### Ausgabeformat

Standardmäßig wird das geparste Datum anhand des Patterns `dd.MM.yyyy HH:mm:ss` ausgegeben. Es kann auch ein eigenes Pattern angegeben werden:

```xml
<bx:json.mydate date pattern="dd.MM. HH:mm" />
```
Werden z.B. Tages- oder Monatsnamen ausgegeben, wird über `locale` die gewünschte Sprache eingestellt:

```xml
<bx:json.mydate date="yyyy-MM-dd" pattern="EEEE, d. MMMM" locale="de" />
```

#### Datum/Zeit modifizieren

Durch die Angabe von verschiedenen Parametern können alle Teile des Ausgangsdatums angepasst werden. Es kann eine Zahl angegeben werden, um den entsprechenden Wert absolut zu setzen. Dabei kann dieser Zahl ein Plus (`+`) oder Minus (`-`) vorangestellt werden, um die Modifikation stattdessen relativ durchzuführen. Die möglichen Parameter sind (werden auch in dieser Reihenfolge angewandt):

- year
- month (im Bereich 1 - 12)
- day
- weekday (s.u.)
- hour
- minute
- second
Etwaige Überschreitungen (z.B. +15 Monate) werden entsprechend weiter gezählt (also +1 Jahr und 3 Monate).

Beispiel (Tag auf den 15. Februar setzen, zwei Stunden dazu zählen, zehn Jahre abziehen):

```xml
<bx:json.mydate date day="15" month="2" hour="+2" year="-10" />
```
Mögliche Werte beim Wochentag sind dabei folgende Werte (keine Zahlen erlaubt):

- mo / di / mi / do / fr / sa / so
- mon / tue / wed / thu / fri / sat / sun
Es wird auf den entsprechenden Wochentag in der gleichen Woche gewechselt. Auch hier gibt es die Möglichkeit ein Plus oder Minus voranzustellen, dann wird entsprechend auf den Tag in der nächsten bzw. vorherigen Woche gewechselt.

Trifft der angegebene Wochentag bereits auf das Ausgangsdatum zu, wird das Datum nicht geändert. Dieses Verhalten kann durch Angabe eines doppelten Plus (`++`) oder Minus (`--`) überschrieben werden (es wird dann auch gewechselt, falls der Wochentag schon zutrifft).

#### Zeitliche Abfrage

Eine weitere Funktion ist die Abfrage, ob das Ausgangsdatum (bzw. das modifizierte Datum) vor oder nach dem jetzigen Zeitpunkt (Zeit auf dem Server) bzw. heute liegt. Der Unterschied ist, dass beim Vergleich mit **heute** die Uhrzeit nicht beachtet wird, sondern nur der Datumsteil.

Die folgenden Abfragen sind möglich:

- before-now
- after-now
- before-today
- after-today
- today (ist am heutigen Tag)
Das Tag kann dabei entweder offen (optional noch mit `not`) oder geschlossen mit den `true` und/oder `false` Parametern genutzt werden. Beispiele:

```xml
<bx:json.mydate date before-now>in der Vergangenheit</bx:json.mydate>
<bx:json.mydate date after-now not>auch in der Vergangenheit oder genau jetzt</bx:json.mydate>
 
<bx:json.mydate date before-today true="vor heute" />
<bx:json.mydate date after-today false="vor heute oder heute" />
 
<bx:json.mydate date today true="am heutigen Tag" false="nicht heute" />
```

### String

#### ausgeben

Im einfachsten Fall wird der String ausgegeben und ggf. automatisch encoded (siehe [Encodings](/books/cms-handbuch-entwickler/page/encodings-uebersicht) für andere Encoding-Möglichkeiten).

```xml
<bx:json.Text />
```

#### vergleichen

Strings können auch verglichen werden. Die Angabe von `ignoreCase` bewirkt, dass Groß-/Kleinschreibung nicht beachtet wird, `not` kehrt das Ergebnis um.

| Parameter | Vergleich |
| --- | --- |
| matches | Vergleich via RegEx (regulärem Ausdruck), String muss diesem komplett entsprechen |
| equals | Gleichheit |
| contains | der String muss den Wert das Parameters beinhalten |
Auch hier ist eine verkürzte Variante mit `true` und `false` möglich.

```xml
<bx:json.Text [matches=""] [equals=""] [contains=""] [ignoreCase] [not]>
</bx:json.Text>
 
<bx:json.Text [matches=""] [equals=""] [contains=""] [ignoreCase] [true=""] [false=""] />
```

#### BatixRecord

Steht in den JSON-Daten im Feld eine Batix-ID, so kann hier auch ein Container angebunden werden. Das Tag verhält sich dann wie `bx:record`, es können innerhalb die normalen Container-Tags wie `bx:recordfield` oder `bx:recorddata` benutzt werden. Auch der Zugriff von außerhalb des Tags mit z.B. `bx:recorddata.nav` ist möglich.

Der Datensatz wird anhand des Feldes ID rausgesucht. Es kann aber auch via `linkfield` auf ein anderes Feld im Datensatz verwiesen werden (Text oder Einzelverknüpfung), hierbei wird der erste gefundene Datensatz genommen.

Wird kein Datensatz mit entsprechender ID (oder Wert im Feld) gefunden, wird nichts ausgegeben. Die Angabe von `dummy` bewirkt, dass stattdessen ein leerer Datensatz vorgehalten wird (der Tag-Inhalt wird ausgeführt, innere `bx:recordfield`-Tags etc. geben aber nichts aus, wie bei `bx:record`).

```xml
<bx:json.IDFeld pool="Container" [linkfield=""] [dummy]>
  <bx:recordfield... />
  <bx:recorddata.if... />
</bx:json.IDFeld >
 
<bx:recorddata.nav object="IDFeld">
  <bx:recorddata.total />
</bx:recorddata.nav>
```

### Array

Ein Array funktioniert analog zu z.B. `bx:containerfilter`, für jedes Element wird der Tag-Inhalt einmal ausgeführt. Das Start-Element kann dabei mittels `index` (0-basiert) und die maximale Anzahl Durchläufe via `max` geregelt werden.

Um das aktuelle Element im Durchlauf auszugeben wird einfach `<bx:json />` verwendet. Je nach Datentyp (in Arrays können auch verschiedene Datentypen vorhanden sein) können hier die entsprechenden Funktionen verwendet werden (z.B. formatierte Ausgabe bei Zahlen).

```xml
<bx:json.Liste [index="20"] [max="10"]>
  <bx:json />
</bx:json.Liste>
```
Es können die meißten Funktionen von `bx:recorddata` verwendet werden:

```xml
<bx:json.Liste>
  ...
</bx:json.Liste>
<bx:recorddata.nav object="Liste">
  Gesamt: <bx:recorddata.total/><br>
  <bx:recorddata.navlist max="5">
    ...
```
Ferner gibt es noch folgende Hilfsmethoden:

```xml
<bx:json.Liste>
  <bx:json {first|last} [not]>...</bx:json> <!-- Inhalt nur ausführen, wenn es das erste oder letzte Element ist -->
  <bx:json {first|last} [true=...] [false=...] /> <!-- dito, nur verkürzte true/false Schreibweise -->
  <bx:json index [add="5"] /> <!-- aktuellen Durchlauf-Index ausgeben, ggf. etwas dazu addieren -->
  <bx:json total /> <!-- Gesamtanzahl der Elemente ausgeben -->
  <bx:json empty [not]>...</bx:json> <!-- ausführen, falls das Array leer ist -->
  <bx:json empty [true=...] [false=...] /> <!-- dito, nur mit true/false -->
  <bx:json cols=...> <!-- funktioniert wie bx:recorddata.cols -->
</bx:json.Liste>
```
Für mehr Informationen zu `cols` siehe die <a href="http://docs.batix.info/display/DEVS/bx:recorddata#bx:recorddata-recorddata.cols" target="_blank">entsprechende Passage bei `bx:recorddata`</a>.

#### Datensätze

Befinden sich im Array Strings, welche Batix-IDs sind, kann mittels `pool` eine Schleife über Datensätze (wie z.B. `bx:containerfilter`) aufgemacht werden. Falls die ID in einem anderen Feld steht, kann dies wieder via `linkfield` referenziert werden. Innerhalb des Json-Tags sind alle normalen Datensatz-Tags verfügbar. `dummy` verhält sich im Falle eines leeren Arrays wie ein leerer Datensatz (ansonsten wird der Inhalt nicht ausgeführt).

Falls im Array (zusätzlich) nicht-Strings sind, wird im Log eine Warnung ausgegeben.

```xml
<bx:json.Kunden pool="Shop_Kunden" [linkfield=""] [dummy]>
  <bx:recordfield... />
  <bx:recorddata.if... />
</bx:json.Kunden>
```

### Object

Um in ein JSON-Objekt tiefer einzusteigen, wird das Json-Tag (analog zu `bx:recordfield` bei Verknüpfungen) geschachtelt.

```xml
<bx:json data="...">
  <bx:json.Kunde>
    <bx:json.Name />
  </bx:json.Kunde>
</bx:json>
```

#### Objekt-Einträge durchgehen

*ab Version 2.6.9*

Ähnlich einem Array können die Elemente eines Objekts (jeweils Key und Value) durchgegangen werden. Das ist hilfreich, falls man die Struktur der Map (des Objektes) nicht direkt kennt (vor allem wenn die Keys dynamisch sind).
Dies erfolgt durch Angabe von `each`, innerhalb dieser Schleife können dann `<bx:json key>` und `<bx:json value>` benutzt werden um auf den entsprechenden Bestandteil zuzugreifen.

Das Tag mit `key` hat dabei immer einen String im Hintergrund, wobei das Tag mit `value` den Typ des Unterelementes hat (entsprechend sind dort auch wieder die verschiedenen Operationen je Typ möglich).

```xml
<bx:json data="...">
  <bx:json.Kunde each>
    Feld '<bx:json key />' hat den Wert '<bx:json value />'
  </bx:json.Kunde>
</bx:json>
```

## JsonPath

Mittels JsonPath-Expressions können relativ einfach verschachtelte Strukturen angesprochen werden. Das erspart lästiges Verschachteln von Json-Tags. Auf der <a href="https://github.com/jayway/JsonPath#operators" target="_blank">GitHub Seite</a> gibt es mehr Details zur Syntax, hier ist nur das Nötigste erwähnt.

| Operator | Bedeutung |
| --- | --- |
| `$` | aktuelle bx:json Node, der Startpunkt damit beginnen alle Expressions |
| `@` | aktuelle Node in der Expression in Filtern benutzt |
| `*` | Wildcard für aktuelles Level |
| `..` | Wildcard für beliebige Sub-Level |
| `.Name oder ['Name']` | Feld Name |
| `.Adresse.Ort` | Feld Ort im Unterobjekt Adresse |
| `[x] / [x:y]` | Index bzw. Range im Array |
| `[?(...)]` | Filter |
Es sind auch Statistikfunktionen verfügbar (siehe Link, z.B. min()), diese sind aber nur auf reine Arrays aus Zahlen anwendbar. Mittels Filtern können Vergleiche angestellt und dabei sogar andere Felder referenziert werden. (z.B. Ist die Zahl in Feld X größer als die Zahl in Feld Y?)

Sobald etwas passendes gefunden wurde, können die Typ-spezifischen Funktionen verwendet werden. Wird nichts passendes zum Pfad gefunden, wird der Tag-Inhalt nicht ausgeführt (außer bei `dummy`).

Zu bemerken ist auch, dass `path` an beliebiger Stelle innerhalb verschachtelter Json-Tags verwendet werden kann, `$` in der Pfadangabe entspricht dann dem direkten Parent-Objekt.

Beispiele:

```xml
<bx:json data="...">
  <bx:json path="$.Adresse.Name" equals="" false="nicht leer" />
  <!-- entspricht -->
  <bx:json path="$['Adresse']['Name']" equals="" false="nicht leer" />
  <!-- entspricht -->
  <bx:json.Adresse><bx:json.Name equals="" false="nicht leer" /></bx:json.Adresse>
  <!-- entspricht -->
  <bx:json.Adresse><bx:json path="$.Name" equals="" false="nicht leer" /></bx:json.Adresse>
 
  <!-- gibt das 2. Element im Array orders aus, je nach Datentyp der Elemente im Array können hier die spezifischen Typ-Funktionen genutzt werden -->
  <bx:json path="$.orders[1]" />
 
  <!-- gibt den höchsten Preis aus -->
  <bx:json path="$.prices.max()" pattern="0.00" locale="de" />
 
  <!-- gibt die Autoren aller Bücher aus -->
  <bx:json path="$.books[*].author">
    Autor: <bx:Json />
  </bx:json>
 
  <!-- dito, aber nur für Bücher mit einem Rating > 2 -->
  <!-- bei komplexen Expression empfiehlt sich ein Clipboard, gerade bei Sonderzeichen -->
  <bx:clipboard.cut name="expr">$.books[?(@.rating > 2)].author</bx:clipboard.cut>
  <bx:json path="clipboard:expr">
    Autor: <bx:Json />
  </bx:json>
 
  <!-- gibt die Preise aller Unterelemente (beliebige Tiefe) aus -->
  <bx:json path="$.store..price">
    Preis: <bx:Json locale="de" />
  </bx:json>
 
  <!-- gibt alle Preise aus, die kleiner als der Maximalpreis (ein Feld im JSON) sind -->
  <bx:clipboard.cut name="expr">$.store.articles[?(@.price < $.maxprice)]</bx:clipboard.cut>
  <bx:json path="clipboard:expr">
    Preis: <bx:Json locale="de" />
  </bx:json>
</bx:json>
```

# bx:jspinclude

Das Tag `jspinclude` veranlasst den Server eine URL aufzurufen und den zurückgegebenen Text in die Seite einzufügen.

```xml
<bx:jspinclude (page="{url}" | file="{url}") [request | jsp] [charset="{enc}"] />
<bx:jspinclude [request | jsp] [charset="{enc}"]> aufzurufende URL </bx:jspinclude>
```
Als offenes Tag verwendet besteht die Möglichkeit den Inhalt dieses Tags auszuwerten und als URL das Ergebnis (sofern vorhanden) zu verwenden.

| page file | Übergabe der URL |
| --- | --- |
| request | Übergabe des Request-Parameters der aktuellen CM-Seite (falls der Inhalt der URL mittels GET geholt wird) |
| jsp | echter JSP-Include |
| charset | Um die Zeichencodierung der einzubindenden Daten anzugeben, kann `encoding` verwendet werden, z.B. `encoding="utf-8"`. |
<p class="callout warning">Es wird das Session-Cookie mit der SESSIONID mitgeschickt. Das Ziel sollte also vertrauenswürdig sein, da sonst eine Session durch Angreifer übernommen werden könnte.</p>

### Beispiele

```xml
Irgendwo im Body einen Datensatz raussuchen:
<bx:containerfilter.Aemter pool="1234567890" force="list" max="1">
  <bx:clipboard.cut name="amtid"><bx:recorddata.id/></bx:clipboard.cut>
</bx:containerfilter.Aemter>

...

Im Teaserbereich:
<bx:jspinclude>/teaser/ansprechpartner.htm?amt=<bx:clipboard.paste name="amtid"/></bx:jspinclude>
```
Es wird ein Teaser mit den Ansprechpartnern für dieses Amt im Teaserbereich aufgerufen mit der entsprechenden Amt-ID.

# bx:link

Das Tag `link` schreibt einen automatisch generierten Link um seinen Inhalt. Unter anderem auch zur Verwendung im bx:loop, um auf die Detailseite zu verlinken.

## Detail-Link

```xml
<bx:link [class="{text}"] [target="{text}"]> Inhalt </bx:link>
```
Es wird ein relativer Link auf "detail.htm" erstellt, der die Seiten-ID als Parameter defaultLoop übergibt.

| class | CSS-Klasse |
| --- | --- |
| target | Zielfenster im Browser |

## Menü-Link

```xml
<bx:link type="menu" [target="{text}"]> Inhalt </bx:link>
```
Diese Form schreibt einen relativen Link auf ein Unterverzeichnis mit dem selben Namen wie der aktuelle Menüpunkt. .

| type="menu" |  |
| --- | --- |
| target | Zielfenster im Browser Falls nicht angegeben, wird der Wert aus den Menüpunkt-Einstellungen benutzt |

## List-Link

```xml
<bx:link type="list" [class="<text>"] [target="<text>"]> Inhalt </bx:link>
```
Es wird ein relativer Link auf "detail.htm" erstellt, der die Seiten-ID als Parameter defaultCatLoop übergibt. Über `class` und `target` lassen sich CSS-Klasse und Zielfenster des Links einstellen.

| class | CSS-Klasse |
| --- | --- |
| target | Zielfenster im Browser |

## Loop-Link

```xml
<bx:link href="{url}"> Inhalt </bx:link>
```
Es wird ein Link auf die angegebene URL erstellt und die ID des aktuellen Loop Elements übergeben.

| href | aufzurufende URL |
| --- | --- |

## Record-Link

```xml
<bx:link recordfield="{param}" [href="{url}"]> Inhalt </bx:link>
```
Dieses Tag steht innerhalb von [bx:record](/books/cms-handbuch-entwickler/page/bx-record) und erzeugt einen Link auf` url `bzw auf die aktuelle Seite, wenn `href` nicht angegeben wurde.

| recordfield | ID des Records |
| --- | --- |
| href | URL |

# bx:login

Das Tag `login` zeigt seinen Inhalt nur an, falls der User ein- bzw. ausgeloggt ist.

```xml
<bx:login.if (in | out)> Inhalt </bx:login.if>
```
Falls `in` angegeben wurde, wird der Inhalt nur dargestellt, wenn sich der Client mittels vorherigem Login in einer gültigen Session befindet. `out` zeigt den Inhalt dagegen nur an, wenn der User ausgeloggt ist. .

# bx:loop

Mithilfe des loop-Tags ist es möglich, sich wiederholende Inhalte mit gleichem Aufbau zusammenzufassen und ggf. zu sortieren.

Dieses Tag ist veraltet. Stattdessen sollte [bx:schleife](/books/cms-handbuch-entwickler/page/bx-schleife) genommen werden - alle Funktionen bleiben gleich, eben nur mit bx:schleife statt bx:loop davor.

## Loop erzeugen

** Deprecated - Veraltetes Feature**
Die hier aufgeführten Informationen beziehen sich auf eine veraltete Funktion, die nicht mehr weiterentwickelt wird und ggf. in zukünftigen Versionen nicht mehr unterstützt wird. Diese Funktion sollte deshalb nicht mehr benutzt werden.

```xml
<bx:loop [loop="{name}"] [orderby="{feldname}"] [showmax="{anzahl}"]> Inhalt </bx:loop>
```
Mit `loop` kann der Schleife ein Name gegeben werden (Standard: "defaultLoop") und mit `orderby` kann das Feld festgelegt werden, nach dem sortiert wird. Als Inhalt steht die Formatierung für jedes Element der Schleife. Es können dabei die folgenden Sub-Tags benutzt werden. Die maximale Anzahl an Elementen, die ausgegeben werden, wird über `showmax` festgelegt.

<p class="callout warning">Die folgenden Tags werden weiterhin in [bx:schleife](/books/cms-handbuch-entwickler/page/bx-schleife) genutzt</p>

## loop.count (ab v2.6.6. deprecated) --> neu: loop.index

```xml
<bx:loop.count [add="{anzahl}"] />
```
Hiermit lässt sich die aktuelle Position der Schleife ermitteln, also wieviele Wiederholungen schon erfolgt sind (z.B. für Nummerierung der Einträge, beginnt mit 0).
Dem Ergebnis wird der Wert von "add" hinzuaddiert, sofern vorhanden.

## loop.index (neu ab v2.6.6)

```xml
<bx:loop.index[add="{anzahl}"] />
```
Ist jetzt besser benannt. loop.count geht noch wegen Kompatibilität)

## loop.id

```xml
<bx:loop.id />
```
Diese Funktion gibt die ID des aktuellen Datensatzes zurück.

## loop.if

```xml
<bx:loop.if {first | notfirst | gerade | ungerade}> Inhalt </bx:loop.if>
```
Der Inhalt wird nur ausgewertet, wenn die entsprechende Bedingung zutrifft. 
Folgende Bedingungen können abgefragt werden:

- first: Datensatz ist der Erste der Liste
- notfirst: Datensatz ist nicht der Erste der Liste
- gerade: Datensatz ist der 2., 4., 6., ...
- ungerade: Datensatz ist der 1., 3., 5., ...

### Prüfen auf letztes Element

```xml
<bx:schleife.Inhalte>
  <bx:clipboard.cut name="LetztesElement"><bx:loop.id/></bx:clipboard.cut>
</bx:schleife.Inhalte>
      
<bx:schleife.Inhalte>
  <bx:clipboard.cut name="AktuellesElement"><bx:loop.id/></bx:clipboard.cut>
  <bx:clipboard.if name="AktuellesElement" value="clipboard:LetztesElement">{wird ausgeführt im Falle des letzten Elements}</bx:clipboard.if>
</bx:schleife.Inhalte>
```
Eine direkte Prüfung auf das letzte Element ist derzeit nicht möglich, kann aber mit einen Hilfs-Schleifendurchlauf und dem Clipboard simuliert werden.

## loop.cols

```xml
<bx:loop.cols num="{anzahl der spalten}" equals="{welche spalte}" [not]> Inhalt </bx:loop.cols>
```
Hier wird der Inhalt nur angezeigt, wenn sich der Datensatz in einer bestimmten Spalte der Ausgabe befindet.

Achtung! Die Anzahl der Spalten wird von 1 bis n angegeben, aber die Angabe der betreffenden Spalte wird von Null aus gezählt.
z. B. <<a href="http://bxloop.cols" target="_blank">bx:loop.cols</a> num="3" equals="1"> Inhalt </<a href="http://bxloop.cols" target="_blank">bx:loop.cols</a>> spricht die zweite Spalte an.

`num` gibt die Spaltenanzahl und `equals` die gesuchte Spalte an. `not` kehrt die Bedingung um.

## loop.previous / loop.next

Diese Tags erzeugen einen Link zum vorherigen bzw. nächsten Element. Der Linktext kann dabei geändert werden (Standard: "zurück" bzw. "weiter").

**Nur auf Detailseiten möglich!**

```xml
<bx:loop.previous [loop="{schleifenname}"] />
<bx:loop.previous [loop="{schleifenname}"]>Linktext</bx:loop.previous>
<bx:loop.next [loop="{schleifenname}"] />
<bx:loop.next [loop="{schleifenname}"]>Linktext</bx:loop.next>
```
Über den Parameter `loop` kann eine andere Schleife angesteuert werden.

## loop.previousid / loop.nextid

Diese Tags geben die ID des vorherigen bzw. nächsten Datensatzes aus.

**Nur auf Detailseiten möglich!**

```xml
<bx:loop.previousid [loop="{schleifenname}"] />
<bx:loop.nextid [loop="{schleifenname}"] />
```
Über den Parameter `loop` kann eine andere Schleife angesteuert werden

## loop.showprevious / loop.shownext

Mit `loop.count` lässt sich die aktuelle Position der Schleife ermitteln, also wieviele Wiederholungen schon erfolgt sind (z.B. für Nummerierung der Einträge).

```xml
<bx:loop.showprevious [schleife="{schleifenname}"] [hidden] [indexparam="{parametername}"] /> zurück </bx:loop.showprevious>
<bx:loop.shownext [schleife="{schleifenname}"] [hidden] [indexparam="{parametername}"] /> vor </bx:loop.shownext>
```
Über den Parameter `schleife` kann eine andere Schleife angesteuert werden. `indexparam` gibt den Name des Request-Parameters an, welcher den aktuellen Index enthält. Mit `hidden` werden die Links ganz ausgeblendet, wenn sie nicht klickbar sind, ansonsten werden die Links ausgegraut.

## loop.total

Dieses Tag gibt die Anzahl der in der Schleife angezeigten Datensätze aus. Es kann außerhalb der Schleife benutzt werden. (ab V2.6.6)

```xml
<bx:loop.total [object="{schleifenname}"] />
```
Über den Parameter `object` kann die jeweilige Schleife angesteuert werden.

## loop.designtitle

Dieses Tag gibt den Titel des Designbausteins aus. (ab V2.6.6)

```xml
<bx:loop.total [object="{schleifenname}"] />
```
Wenn das umgebende Schleifentag keine Designschleife ist, wird eine Fehlermeldung  ausgegeben.

# bx:mapping

Das Tag `mapping` kann sich Werte zu Schüsselwerten (values zu keys) merken und später können diese Werte wieder abgefragt und ausgegeben werden. Es ist eine Erweiterung von `<bx:clipboard>` mit der Erweiterung, daß bei jedem Befehl der Name einer Map angegeben werden muß.
ab V 2.6.2

## mapping.put

```xml
<bx:mapping.put map="{listname}"> key=value </bx:mapping.put>

```
Fügt ein Key-Value-Paar der angegebenen Liste hinzu. "=" ist der Trenner.

| map | Name der Liste, in der Keys und dazugehörige Values gespeichert werden sollen |
| --- | --- |

### Beispiele

```xml
<bx:mapping.put map="bewertung">1=super-spitzenmäßig</bx:mapping.put>
<bx:mapping.put map="bewertung">2=jo, paßt scho</bx:mapping.put>
<bx:mapping.put map="bewertung">3=grot-ten-schlecht</bx:mapping.put>

```

## mapping.paste

```xml
<bx:mapping.paste map="{listname}" name="{key}"/>
```
Holt das Value anhand des Keys aus der angegebenen Liste.

| map | Name der Liste, aus der das entsprechende Value geholt werden soll |
| --- | --- |
| name | Key-Wert |

### Beispiele

```xml
...
Ihre Bewertung: <bx:mapping.paste map="bewertung" name="request:note"/>
..
```
(siehe obiges Beispiel - das füllt die hier genutzte Liste ) reagiert auf den Requestparameter "note". So spart man sich dreimaliges pagedata.request-Gewurschtl.

# bx:math

Das Tag `math` führt Berechnungen durch. Ab Version 2.5.9.

```xml
<bx:math pattern="..." locale="de" gs="." ds="," rounding="[ceiling|down|floor|half_down|half_even|half_up|up]">{Aufgabe}</bx:math>
```
| pattern | Formatierung festlegen (Standard bei Zahl: "0.#####", bei Preis: "0.00"). Tausender-Trennzeichen (gs) und Dezimal-Trennzeichen (ds) können ebenfalls festgelegt werden. |
| --- | --- |
| locale | Sprachformatierung (z.B. "de" oder "en_US")<br> `locale` sollte immer angegeben werden, da sonst die Standardeinstellung vom Server genutzt wird, die sich aber nach Updates oder Umzügen ändern kann. |
| Aufgabe | z.Zt. unterstützte Operatoren: `+` (Addition)  `-` (Subtraktion)  `*` (Multiplikation) `/` (Division)  `^` (Hochrechnung) `%` (Modulo) |
| rounding | **ceiling:** Rundet zur nächsten Ganzzahl auf (in Richtung +unendlich) **floor:** Rundet zur nächsten Ganzzahl ab (in Richtung -unendlich) **up:** Rundet zur nächsten Ganzzahl auf (aus Richtung null) **down:** Rundet zur nächsten Ganzzahl ab (in Richtung null) **half_down:** Rundet bei ,5 nach oben auf **half_even:** Rundet bei ,5 bei geraden Zahlen ab, bei ungeraden Zahlen auf **half_up:** Rundet bei ,5 nach unten ab Resultat der jeweiligen Methode UPDOWNCEILINGFLOORHALF_UPHALF_DOWNHALF_EVEN5,565656562,532323221,621212221,121211111,01111111-1,0-1-1-1-1-1-1-1-1,1-2-1-1-2-1-1-1-1,6-2-1-1-2-2-2-2-2,5-3-2-2-3-3-2-2-5,5-6-5-5-6-6-5-6 |  | Resultat der jeweiligen Methode |  | UP | DOWN | CEILING | FLOOR | HALF_UP | HALF_DOWN | HALF_EVEN | 5,5 | 6 | 5 | 6 | 5 | 6 | 5 | 6 | 2,5 | 3 | 2 | 3 | 2 | 3 | 2 | 2 | 1,6 | 2 | 1 | 2 | 1 | 2 | 2 | 2 | 1,1 | 2 | 1 | 2 | 1 | 1 | 1 | 1 | 1,0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | -1,0 | -1 | -1 | -1 | -1 | -1 | -1 | -1 | -1,1 | -2 | -1 | -1 | -2 | -1 | -1 | -1 | -1,6 | -2 | -1 | -1 | -2 | -2 | -2 | -2 | -2,5 | -3 | -2 | -2 | -3 | -3 | -2 | -2 | -5,5 | -6 | -5 | -5 | -6 | -6 | -5 | -6 |
|  | Resultat der jeweiligen Methode |
|  | UP | DOWN | CEILING | FLOOR | HALF_UP | HALF_DOWN | HALF_EVEN |
| 5,5 | 6 | 5 | 6 | 5 | 6 | 5 | 6 |
| 2,5 | 3 | 2 | 3 | 2 | 3 | 2 | 2 |
| 1,6 | 2 | 1 | 2 | 1 | 2 | 2 | 2 |
| 1,1 | 2 | 1 | 2 | 1 | 1 | 1 | 1 |
| 1,0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
| -1,0 | -1 | -1 | -1 | -1 | -1 | -1 | -1 |
| -1,1 | -2 | -1 | -1 | -2 | -1 | -1 | -1 |
| -1,6 | -2 | -1 | -1 | -2 | -2 | -2 | -2 |
| -2,5 | -3 | -2 | -2 | -3 | -3 | -2 | -2 |
| -5,5 | -6 | -5 | -5 | -6 | -6 | -5 | -6 |

### Beispiele

```xml
<bx:math pattern="0.00">8*(-3+7)</bx:math>
```
gibt "32,00" aus

```xml
<bx:math pattern="#,##0.00"><bx:recordfield.Preis/>+<bx:recordfield.Versandkosten/></bx:math>
```
gibt einen Preis incl. Versandkosten aus

```xml
<bx:math pattern="0.00" locale="de">
 <bx:recordfield.Anzahl/>*<bx:recordfield.Nettoeinzelpreis/>*(1+<bx:recordfield.Steuersatz/>/100)
</bx:math>
```
gibt einen Bruttopreis aus.

## Debug

```xml
<bx:math.debug pattern="">{Aufgabe}</bx:math.debug>
```
gibt nicht nur das Ergebnis aus, sondern die gesamte Formel

### Beispiele

```xml
<bx:math.debug pattern="0.00">8*(-3+7)</bx:math.debug>
```
gibt "calc{8*(-3+7)}=32.0" aus

## Rechnen mittels Datenbank

```xml
<bx:math.mysql pattern="...">{Aufgabe}</bx:math.mysql>
```
Rechenoperationen werden mittels einer SQL-Formel gemacht.

### Beispiele

```xml
<bx:math.mysql pattern="0">POW(3,4)</bx:math.mysql>
```
gibt "81" aus ( 34 )

## Vergleich von Zahlen

```xml
<bx:math.compare value1="{Wert1}" operator="{Operator}" value2="{Wert2}"> angezeigter Inhalt </bx:math.compare>
```
Zeigt Inhalt abhängig vom Vergleich zweier Zahlenwerte aus.(ab V 2.5.9)

| value1 | erster Vergleichswert es können auch [Präfixe ](/books/cms-handbuch-entwickler/page/parameter-werte)verwendet werden |
| --- | --- |
| operator | Operator:`e` (gleich)`gt` (größer als)`lt` (kleiner als)`lte` (kleiner gleich)`gte` (größer gleich) sein |
| value2 | zweiter Vergleichswert es können auch [Präfixe ](/books/cms-handbuch-entwickler/page/parameter-werte)verwendet werden |

### Beispiele

```xml
<bx:pagedata.setattribute mode="set" name="kathede1">3</bx:pagedata.setattribute>
<bx:pagedata.setattribute mode="set" name="kathede2">4</bx:pagedata.setattribute>
<bx:pagedata.setattribute mode="set" name="hypotenuse">5</bx:pagedata.setattribute>
<bx:clipboard.cut name="v1">
  <bx:pagedata.attribute name="kathede1"/>*<bx:pagedata.attribute name="kathede1"/>
  +<bx:pagedata.attribute name="kathede2"/>*<bx:pagedata.attribute name="kathede2"/>
</bx:clipboard.cut>
<bx:clipboard.cut name="v2">
  <bx:pagedata.attribute name="hypotenuse"/>*<bx:pagedata.attribute name="hypotenuse/>
</bx:clipboard.cut>
<bx:math.compare value1="clipboard:v1" operator="e" value2="clipboard:v2">rechtwinklig</bx:math.compare>
```

## Vergleiche mit min und max

```xml
<bx:math.min [attribute|clipboard]="{name}"> {Vergleichszahl} </bx:math.min>			<!-- Wenn der Tag-Body einer kleineren Zahl entspricht, wird das gespeicherte Attribut aktualisiert. -->
<bx:math.max [attribute|clipboard]="{name}"> {Vergleichszahl} </bx:math.max>            <!-- Wenn der Tag-Body einer größeren Zahl entspricht, wird das gespeicherte Attribut aktualisiert. -->
<bx:math.[max|min] [attribute|clipboard]="{name}" extra-source="{text}" extra-target="[attribute|clipboard]:{name2}"> {Vergleichszahl} </bx:math.max>
```
Vergleicht den in Request-Attribut oder Clipboard-Objekt gespeicherten Zahlenwert mit dem Zahlenwert aus dem Tag-Body und ändert gegebenenfalls den Attributwert. Sinnvoll in Schleifen und den Min- bzw. Max-Wert zu ermitteln.

| attribute/clipboard | muß nicht zwangsläufig vorher vorhanden sein, kann aber, um einen Bestimmten Wert als Ausgangswert festzulegen |
| --- | --- |
| extra-source | wenn angegeben, wird zusätzlich bei jeder Änderung der Variablen der source-Text in das angegebenen target-Objekt gespeichert. |
| extra-target | Wohin der Text aus extra-source gespeichert werden soll (siehe Beispiel) |

### Beispiele

```xml
<bx:containerfilter.Fragen pool="Umfrage Elemente">
  <bx:math.max clipboard="maxSort"><bx:recordfield.Sortierung/></bx:math.max>
</bx:containerfilter.Fragen>
nächste Sortier-Position: <bx:math pattern="0"><bx:clipboard.paste name="maxSort"/>+1</bx:math>
```
Innerhalb einer Schleife wird die größte Sortierungsposition ermittelt

```xml
<bx:containerfilter.Produkt pool="Produkte" idield="pid">
  ...
  <bx:recordfield.Varianzen>
    <bx:clipboard.cut name="größe"><bx:recordfield.groesse/></bx:clipboard.cut>
    <bx:math.min clipboard="preis" extra-source="clipboard:größe" extra-target="clipboard:billigsteGröße"><bx:recordfield.NettoPreis/>*1.19</bx:math.min>
  <bx:recordfield.Varianzen>
  ...
  ab <bx:clipboard.paste name="preis"/> Euro (für Größe <bx:clipboard.paste name="billigsteGröße"/>)
  ...
</bx:containerfilter.Produkt>
```
Die Preise der Varianzen (hier: Größen) eines Produktes werden durchgegangen. Bei jedem Durchlauf wird im Clipboard "größe" die jeweilige Größe gespeichert. Ist der Wert im Recordfield NettoPreis nun kleiner als der im Clipboard "preis" schon gespeicherte, wird der Wert dieses Clipboards überschrieben und der Wert vom Clipboard "größe" ins Clipboard "billigsteGröße" gespeichert (muß nicht vorher angelegt werden) und kann dann am Ende ausgegeben werden.

```xml
[<bx:clipboard.cut name="gesamtPreis"></bx:clipboard.cut>] <!-- wird angelegt, wenn noch nicht vorhanden -->
<bx:containerfilter.Warenkorb pool="Warenkorb">
  <bx:math.add clipboard="gesamtPreis"><bx:recordfield.Preis/></bx:math.add>
</bx:containerfilter.Warenkorb >
Gesamtpreis: <bx:clipboard.paste name="gesamtPreis"/>
```
Addiert alle Preise im Warenkorb zusammen.

```xml
<bx:containerfilter.Warenkorb pool="Warenkorb">
  <bx:recordfield.MWST equals="7"><bx:math.add clipboard="7prozent" value="1"></bx:math.add><bx:recordfield.MWST>
  <bx:recordfield.MWST equals="19"><bx:math.add clipboard="19prozent" value="1"></bx:math.add><bx:recordfield.MWST>
</bx:containerfilter.Warenkorb >
Anzahl Artikel mit 7% Mwst: <bx:clipboard.paste name="7prozent"/>
Anzahl Artikel mit 19% Mwst: <bx:clipboard.paste name="19prozent"/>
```
Zählen in verschiedenen Kategorien

## Hochzählen / Zusammenzählen

```xml
<bx:math.add [attribute|clipboard]="{name}"> {Wert} </bx:math.add>   <!-- addiert Werte innerhalb einer Schleife auf -->
<bx:math.add (attribute|clipboard)="{name}" [value="1"] />		   <!-- als geschlossenes Tag zum Hochzählen mit dem Wert in value -->

```

### Beispiele

```xml
<bx:clipboard.cut name="gesamtPreis"></bx:clipboard.cut>] <!-- wird angelegt, wenn noch nicht vorhanden -->
<bx:containerfilter.Warenkorb pool="Warenkorb">
  <bx:math.add clipboard="gesamtPreis"><bx:recordfield.Preis/></bx:math.add>
</bx:containerfilter.Warenkorb >
Gesamtpreis: <bx:clipboard.paste name="gesamtPreis"/>
```
Addiert alle Preise im Warenkorb zusammen.

```xml
<bx:containerfilter.Warenkorb pool="Warenkorb">
  <bx:recordfield.MWST equals="7"><bx:math.add clipboard="7prozent" value="1"></bx:math.add><bx:recordfield.MWST>
  <bx:recordfield.MWST equals="19"><bx:math.add clipboard="19prozent" value="1"></bx:math.add><bx:recordfield.MWST>
</bx:containerfilter.Warenkorb >
Anzahl Artikel mit 7% Mwst: <bx:clipboard.paste name="7prozent"/>
Anzahl Artikel mit 19% Mwst: <bx:clipboard.paste name="19prozent"/>
```
Zählen in verschiedenen Kategorien

## Formatieren von Zahlenwerten

```xml
<bx:math.format (attribute|clipboard)="{name}" pattern="#,##0.00" [ ds="," gs="." | locale="de" ] [rounding="half_up"] />
```
Formatiert den Zahlenwert im Request-Attribut/Clipboard und gibt das Ergebnis aus.

## Vergleich von Datumsen

```xml
<bx:math.datecompare prior="{Wert1}" later="{Wert}" [pattern="{pattern}"] > angezeigter Inhalt </bx:math.datecompare>
```
Ein Vergleich der beiden übergebenen Datumswerte wird durchgeführt und der Inhalt nur ausgegeben, wenn der Wert prior zeitlich vor dem Wert later liegt.

| prior | zu prüfender Datumswert |
| --- | --- |
| later | zu prüfender Datumswert |
| pattern | Eingangsformat von prior und later, Standard ist "dd.MM.yyyy". |

### Beispiele

```xml
<bx:clipboard.cut name="Halloween">31.10.2011</bx:clipboard.cut>
<bx:clipboard.cut name="Allerheiligen">1.11.2011</bx:clipboard.cut>
<bx:math.datecompare prior="clipboard:Halloween" later="clipboard:Allerheiligen">immer angezeigt</bx:math.datecompare>
<bx:math.datecompare prior="clipboard:Allerheiligen" later="clipboard:Halloween">nie angezeigt</bx:math.datecompare>
```

## Datum modifizieren

```xml
<bx:math.modifydate pattern="{pattern}" locale="{de,en,fr,...}" (in-pattern="{Muster}" out-pattern="{Muster}") (in-locale="{de,en,fr,...}" out-locale="{de,en,fr,...}") (year|month|day|hour|minute|second)="[+|-]{Zahlenwert}" > {Datum} </bx:math.modifydate>
```
Eine Funktion, um ein im Body übergebenes Datum zu modifizieren und wieder auszugeben.

| pattern | beide Muster sind gleich |
| --- | --- |
| in-pattern/out-pattern | Muster unterscheiden sich |
| in-locale/out-locale | Sprachen unterscheiden sich |

### Beispiele

```xml
<bx:math.modifydate in-pattern="yyyyMMdd" month="+1" day="15" out-pattern="dd. MMMM yy">20110922</bx:math.modifydate>
```
gibt „15. Oktober 11“ aus

```xml
<bx:clipboard.copy><bx:tools.datum pattern="EEE, MMM d yyyy" locale="en"/></bx:clipboard.copy>
```
gibt aus und speichert im Clipboard “**Wed, Jan 3 2018**”

```xml
<bx:math.modifydate in-pattern="EEE, MMM d yyyy" out-pattern="EEEEEE, d. MMMMM yy" in-locale="en" out-locale="fr"><bx:clipboard.paste/></bx:math.modifydate> 
```
gibt aus “**mercredi, 3. janvier 18**”

```xml
<bx:math.modifydate in-pattern="EEE, MMM d yyyy" out-pattern="EEEEEE, d. MMMMM yy" locale="ru" in-locale="en"><bx:clipboard/></bx:math.modifydate> 
```
gibt aus “**среда****, 3. ****января**** 18**”

```xml
<bx:math.modifydate pattern="EEE, MMM d yyyy" in-locale="en" out-locale="es"><bx:clipboard/></bx:math.modifydate> 
```
gibt aus “**mié, ene 3 2018**”

```xml
<bx:math.modifydate in-pattern="EEE, MMM d yyyy" out-pattern="EEEEEE, d. MMMMM yy" locale="en"><bx:clipboard/></bx:math.modifydate>

```
gibt aus “**Wednesday, 3. January 18**“

## Feiertagsausgabe (ab V 2.3.)

```xml
<bx:math.holiday [inpattern="{pattern}"] [outpattern=("pattern" | "")] [year|month|day|hour|minute|second)="[+|-]{Zahlenwert}"]> Datumsangabe im konfigurierten Format </bx:math.holiday>
```
Ausgabe des Namens eines (Thüringer) Feiertags (z.B. Silvester). Das zu prüfende Datum wird im Tagbody angegeben. Leerzeichen an Anfang und Ende werden ignoriert. Ist das Datum kein Feiertag, wird der Wochentagsname ausgegeben (Standard) oder ein in `outpattern` definierter Inhalt.

| inpattern | Eingangsformat (Standard ist "dd.MM.yyyy") |
| --- | --- |
| outpattern | Art des ausgegebenen Inhalts (siehe Beispiel) oder Wochentagsname (Standard) |

### Beispiele

```xml
<bx:math.holiday>30.12.2015</bx:math.holiday> 		<!-- gibt "Silvester" aus -->

<bx:math.holiday inpattern="yyyy:dd MMM">2015:31 Dez</bx:math.holiday> 		<!-- gibt "Silvester" aus -->
<bx:math.holiday inpattern="yyyy:dd MMM">2015:30 Dez</bx:math.holiday> 		<!-- gibt "Mittwoch" aus -->

<bx:math.holiday outpattern="">30.12.2015</bx:math.holiday> 				<!-- gibt "" (nichts) aus <bx:if> verwendbar, ABER: -->
<bx:math.holiday outpattern="">31.12.2015</bx:math.holiday> 				<!-- gibt "Silvester" aus <bx:if> verwendbar -->
```
auch Datums-Modifizierer möglich: `<bx:math.holiday
day="+1">31.12.2015</bx:math.holiday>` gibt "Neujahr" aus

## Feiertagsabfrage (ab V 2.3.)

```xml
<bx:math.isholiday testdate="{datum]" [pattern="pattern"] [not]>Inhalt</bx:math.isholiday>
```
Testet, ob das übergebenen Datum ein Feiertag ist und gibt den Taginhalt aus.

| testdate | zu prüfendes Datum, über ein [**Präfix** ](/books/cms-handbuch-entwickler/page/parameter-werte)angegeben |
| --- | --- |
| pattern | Eingangsformat (Standard ist "dd.MM.yyyy") |
| not | kehrt die Bedingung um |

### Beispiele

```xml
<bx:math.isholiday testdate="request:pruefdatum" not pattern="dd.MM.yyyy">kein Feiertag</bx:math.isholiday>
```
beim Aufruf von ...detail.htm?pruefdatum=30.12.2015 würde "kein Feiertag" ausgegeben
```xml
<bx:math.isholiday testdate="request:pruefdatum" pattern="dd.MM.yyyy">Feiertag: <bx:math.holiday inpattern="dd.MM.yyyy"><bx:pagedata.request name="pruefdatum"/></bx:math.holiday></bx:math.isholiday>
  wär das gleiche wie 
<bx:if>Feiertag: <bx:math.holiday inpattern="dd.MM.yyyy" outpattern=""></bx:math.holiday> </bx:if>
```
Zwei Arten, einen Feiertag abzufragen.

auch Datums-Modifizierer möglich:
 `<bx:clipboard><bx:tools.datum></bx:clipboard>`
 `<bx:math.isholiday testdate="clipboard:default"
day="+1"> morgen ist ein Feiertag</bx:math.isholiday>`

## Tagesdifferenz zwischen zwei Daten

```xml
<bx:math.datetolong data="{wert}">        	// wandelt Datum in Millisekunden (seit 1970) und
<bx:math.datetolong> Wert </bx:math.datetolong>

<bx:math.longtodate>       					//wandelt Millisekunden zu Datum
<bx:math.longtodate> Wert <bx:math.longtodate>
```
Die Angabe von `pattern` ist jeweils optional möglich (Standard ist "dd.MM.yyyy").

### Beispiele

```xml
<bx:clipboard name="datum1">25.3.2017</bx:clipboard>
<bx:clipboard name="datum2">2.4.2017</bx:clipboard>

<bx:math>(<bx:math.datetolong data="clipboard:datum2"/>-<bx:math.datetolong><bx:clipboard name="datum1"/></bx:math.datetolong>)/ 1000 / 3600 /24</bx:math>

```
Da wird „`7.958333333333333`“ Tage ausgegeben. Normalerweise glatte Zahl, aber hier ist Sommerzeitumstellung dazwischen. Wenn man bei `<bx:math pattern=”0”>` schreibt, rundet es auf 8 Tage.

# bx:navdata

Das Tag `navdata `gibt zum aktuellen Menüpunkt des Schleifendurchlaufs Daten aus. Es kann innerhalb von `<bx:navigation.[Nummer]>` , `<bx:sitemap.[Nummer]>`, `<bx:submenu.list>`, `<bx:navlink>` verwendet werden.

## navdata.id

```xml
<bx:navdata.id />
```
Die Id des Menüpunkts wird ausgegeben.

## navdata.name

```xml
<bx:navdata.name [type="plain] />
```
Der Name des Menüpunkts wird ausgegeben.` type="plain"` z.B. für csv-Datei

## navdata.dir

```xml
<bx:navdata.dir />
```
Der virtuelle Verzeichnisname des Menüpunkts wird ausgegeben.

## navdata.path

```xml
<bx:navdata.path [follow] [no-encoding] />
```
Der ganze Pfad des Menüpunkts wird ausgegeben.

| follow | wenn der Zielmenüpunkt ein weitergeleiteter Menüpunkt ist, wird nicht auf den Punkt gelinkt, sondern auf das Ziel des Menüpunktes |
| --- | --- |
| no-encoding | der Pfad wird nicht korrekt encoded, sondern direkt reingeschrieben z. B. mit Umlauten und russischen Zeichen. Es liegt dann am Browser das zu korrigieren. |

## navdata.link

```xml
<bx:navdata.link [follow] [no-encoding] [html-Tags] />  <!-- Menüpunktname wird verlinkt -->
<bx:navdata.link> verlinkter Text </bx:navdata.link>
```
Es wird ein Link zum Menüpunkt erzeugt.

| follow | wenn der Zielmenüpunkt ein weitergeleiteter Menüpunkt ist, wird nicht auf den Punkt gelinkt, sondern auf das Ziel des Menüpunktes |
| --- | --- |
| no-encoding | der Pfad wird nicht korrekt encoded, sondern direkt reingeschrieben z. B. mit Umlauten und russischen Zeichen. Es liegt dann am Browser das zu korrigieren. |

## navdata.target

```xml
<bx:navdata.target/>
```
Das eventuell beim Menüpunkt eingetragene Target wird ausgegeben.

## navdata.meta

```xml
<bx:navdata.meta name="{eigenschaftsname}" />	<!-- Metadaten zum Menüpunkt ausgeben werden ausgegeben -->
<bx:navdata.meta name="{eigenschaftsname} [value="{vergleichswert}"] [not]" />   <!-- Block abhängig vom Wert der entsprechenden Metadaten anzeigen -->
```
Metadaten zum Menüpunkt ausgeben werden ausgegeben oder zum Vergleich herangezogen.

## navdata.index

```xml
<bx:navdata.index [add="{n}"]/>
```
Die laufende Nummer des Menüpunkts in der aktuellen Ebene wird ausgegeben.

| add | Ausgabe der aktuellen Nummer plus angegebener Wert.  **Standard ist 1**, d.h., weil bei 0 angefangen wird, wird bei Nicht-Angabe des Add-Parameters bei 1 angefangen. Soll bei 0 angefangen werden, muß add="0" sein (heißt: zum Startwert 0 wird 0 hinzugezählt anstatt (Standard)1 ). |
| --- | --- |

## navdata.robots

Es wird behauptet, daß eine Seite mit jeden externen Link, der darauf ist, von Google schlechter gerankt wird, und die verlinkte Seite dafür besser. Deshalb sollen alle externen Links der Suchmaschine sagen, daß sie dort nicht draufgehen soll.
Das Tag liest die Einstellungen in der Navigation, damit bei externen Links ein <a … rel=“nofollow“ angehängt werden kann.

```xml
<bx:navdata.robots [index] [follow] />
```
gibt "(no)index" bzw. "(no)follow" entsprechend der Menüpunkteinstellung aus. Wenn beide Parameter angegeben sind, werden die Werte beide, durch Komma getrennt, ausgegeben.

```xml
<bx:navdata.robots index|noindex|follow|nofollow> ... <bx:navdata.robots>
```
Zeigt den Inhalt an, wenn die angefragte Bedingung für den Menüpunkt zutrifft

### Beispiele

```xml
<bx:sitemap.2>
  <a href="<bx:sitemap.path/>" <bx:navdata.robots nofollow>rel="nofollow"</bx:navdata.robots>> … </a>
</bx:sitemap.2>
```

## navdata.visible

```xml
<bx:navdata.visible [not]> Inhalt </bx:navdata.visible>
```
Zeigt an, ob das Frontend-aktiv-Häkchen beim Nav-Punkt gesetzt ist. ab v2.6.6.

### Beispiele

```xml
<bx:sitemap.0 showinactive>
  <a href="<bx:sitemap.path/>"<bx:navdata.visible not> style="color:grey;"</bx:navdata.visible>><bx:sitemap.name/></a>
</bx:sitemap.0>
```
Es werden aktive und inaktive Menüpunkte angezeigt, die inaktiven werden in Grau dargestellt.

## navdata.if

```xml
<bx:navdata.if (open | closed | hasChilds | noChilds | self | notself | first | last | notfirst | notlast)> Inhalt </bx:navdata.if>
<bx:navdata.if (id="{id}" | parent="{id}" | path="{pfad}" | redirected [not])> Inhalt </bx:navdata.if>
```
Mit diesem Tag kann entschieden werden, ob ein bestimmter Quelltext ausgegeben werden soll.

| pfad | Menüpunkt-Pfad |
| --- | --- |
| open/closed | Menüpunkt ist geöffnet (gilt auch für Überebenen) |
| hasChilds/noChilds | Abfrage, ob Menüpunk Unterpunkte besitzt |
| self/notself | aktueller Menüpunkt |
| first/last/notfirst/notlast | erklärt sich selbst |
| id | Vergleich des Menüpunkts mit einer ID (mehrere IDs mit Komma, Semikolon oder Leerzeichen getrennt ab v 2.6.2) |
| parent | Vergleich des übergeordnete Menüpunkts mit einer ID |
| path | Vergleich des Menüpunktes mit einem bestimmten Pfad |
| redirected | wenn Menüpunkt weitergeleitet wird |
Verweise auf diese Seite:

<a href="http://docs.batix.info/display/DEVS/bx%3Anavigation" target="_blank">bx:navigation</a>
<a href="http://docs.batix.info/pages/viewpage.action?pageId=19300426" target="_blank">bx:navigation</a>

<p>(2 Verweise)</p>

# bx:navigation

Das Tag `navigation` wird verwendet, um eine Navigationsstruktur darzustellen.

## Allgemeine Syntax

```xml
<bx:navigation.{level} [normal | protected | showcurrentinactive] [open]>Inhalt</bx:navigation.<level>>
```

| level | Navigationstiefe (beginnt mit 0 = Root-Ebene)<br>um darunterliegende Menüpunkte anzuzeigen, werden<br>`bx:navigation`<br>-Tags geschachtelt (jeweils das Level um 1 erhöhen) |
| --- | --- |
| normal protected showcurrentinactive | nur nicht-geschützte Menüpunkte anzeigen nur geschützte (Intranet-)Menüpunkte anzeigen wird angezeigt, wenn man sich gerade in diesem inaktiven Menüpunkt befindet |
| open | geöffnete Menüpunkte anzeigen |

Ab Version 2.6.2 kann man auch auf Seiteninhalte zugreifen, so wie bei bx:submenu.

### Beispiele

```xml
<bx:navigation.0>
  <a href="<bx:navigation.path/>"><bx:navigation.name/></a><br>
  <bx:navigation.1>
    <a href="<bx:navigation.path/>">-<bx:navigation.name/></a><br>
    <bx:navigation.2>
      <a href="<bx:navigation.path/>">--<bx:navigation.name/></a><br>
    </bx:navigation.2>
  </bx:navigation.1>
</bx:navigation.0>
```

Beispiel für geschachtelte Navigation

## navigation.path

```xml
<bx:navigation.path/>
```

Der virtuelle Pfad wird ohne "/www/webname/" und ohne "/" am Ende ausgegeben (siehe Beispiel oben).

## navigation.dir

```xml
<bx:navigation.dir/>
```

Es wird nur der aktuelle Verzeichnisname ausgegeben.

## navigation.name

```xml
<bx:navigation.name/>
```

Dieses Tag gibt den angezeigten Name des Menüpunktes aus.

## navigation.target

```xml
<bx:navigation.target [default="{ziel}"] />
```

Das Zielframe wird ausgegeben.

| ziel | Standard-Zielframe, wenn im Menüpunkt kein Zielframe angegeben wurde |
| --- | --- |

## navigation.id

```xml
<bx:navigation.id/>
```

Dieses Tag gibt die ID des Menüpunktes aus. Die ID der aktuellen Seite kann auch mit `<a href="http://docs.batix.info/display/DEVS/bx%3Apagedata#bx:pagedata-pagedata.navid" target="_blank">bx:pagedata.navid</a>` ausgegeben werden.

## navigation.index

```xml
<bx:navigation.index/>
```

Es wird eine laufende Nummer innerhalb der Navigations-Schleife ausgegeben. Die Zählung beginnt bei 1 und startet in jedem Unterpunkt neu.

## navigation.if

```xml
<bx:navigation.if (open | closed | hasChilds | noChilds | self | notself | first | last | notfirst | notlast)> Inhalt </bx:navigation.if>
<bx:navigation.if (id="{id}" | parent="{id}" | path="{pfad}" | redirected [not])> Inhalt </bx:navigation.if>
```

Mit diesem Tag kann entschieden werden, ob ein bestimmter Quelltext ausgegeben werden soll. Die ID der aktuellen Seite kann auch mit `<a href="http://docs.batix.info/display/DEVS/bx%3Apagedata#bx:pagedata-pagedata.nav" target="_blank">bx:pagedata.nav</a>` abgefragt werden.

| pfad | Menüpunkt-Pfad |
| --- | --- |
| open/closed | Menüpunkt ist geöffnet (gilt auch für Überebenen) |
| hasChilds/noChilds | Abfrage, ob Menüpunk Unterpunkte besitzt |
| self/notself | aktueller Menüpunkt |
| first/last/notfirst/notlast | erklärt sich selbst |
| id | Vergleich des Menüpunkts mit einer ID (mehrere IDs mit Komma, Semikolon oder Leerzeichen getrennt ab v 2.6.2) |
| parent | Vergleich des übergeordnete Menüpunkts mit einer ID |
| path | Vergleich des Menüpunktes mit einem bestimmten Pfad |
| redirected | wenn Menüpunkt weitergeleitet wird |

## navigation.link

```xml
<bx:navigation.link/>
<bx:navigation.link> Linktext </bx:navigation.link>   <!-- es kann ein eigener Linktext angegeben werden -->
```

Es wird ein Link zum aktuellen Navigationspunkt des Schleifendurchlaufs erzeugt. 
Es werden alle angegebenen Parameter in das HTML-Tag übernommen. Als target für den Link wird der beim Menüpunkt gespeicherte Wert bevorzugt.

### Beispiele

```xml
<bx:navigation.0>
  <bx:navigation.link default="_blank"><span title="<bx:navigation.name/>"><bx:navigation.index/></span></bx:navigation.link><bx:navigation.if notlast> | </bx:navigation.if>
</bx:navigation.0>
```

Navigation mit Zahlen - ich weiß, issn blödes Beispiel

Ausgabe: 1 | 2 | 3 | 4    - beim Hover auf die Zahlen erscheint der Menüpunktname. Der letzte Trennstrich wurde ausgeklammert.

## navigation.meta

```xml
<bx:navigation.meta name="{metaname}"/>											<!-- Ausgabe der Meta-Eigenschaft -->
<bx:navigation.meta name="{metaname}" [not]> Inhalt </bx:navigation.meta>	<!-- gibt den Inhalt nur aus, wenn die Meta-Eigenschaft existiert bzw. nicht existiert (not) -->
```

Dieses Tag gibt Meta-Daten zum aktuellen Menüpunkt aus oder prüft, ob diese vorhanden sind. Es kann auch [bx:navdata](/books/cms-handbuch-entwickler/page/bx-navdata) benutzt werden.

# bx:navlink

Mit dem Tag `navlink` kann man auf Daten eines Menüpunktes zugreifen (z. B. bx:text, bx:bild usw). Kann inner- und außerhalb von einem Navigations-Tag verwendet werden.
Es kann auch <a href="http://docs.batix.info/display/DEVS/bx%3Anavdata" target="_blank">bx:navdata</a> benutzt werden, um auf die Eigenschaften des Menüpunktes zugreifen zu können.

## Innerhalb eines Navigations-Tags

```xml
<bx:navlink> Inhalt </bx:navlink>
```

sucht das nächste umgebende navigation-Tag (navigation, sitemap) und es können so Daten des Navigationspunktes abgerufen werden

### Beispiele

```xml
<bx:navigation.0>
  <a href="<bx:navigation.path/>"><img src="<bx:navlink><bx:bild.Seitenbild width="100" height="100"/></bx:navlink>"></a>
</bx:navigation.0>
```

Statt des Menüpunktnamen wird als Navigations-Link das Seitenbild des jeweiligen Menüpunkts ausgegeben.

## Außerhalb eines Navigations-Tags (ab v2.6.2)

```xml
<bx:navlink (navid="{id}" | path="{pfadangabe}")> Inhalt von der Seite </bx:navlink>
```

Daten innerhalb des Tags werden vom angegeben  Menüpunkt geholt und haben kein Eingabefeld im aktuellen Menüpunkt.

### Beispiele

**Angabe der Menüpunkt-ID**

```xml
Unsere Adresse: <bx:navlink navid="1234567890"><bx:text.Adresse/></bx:navlink>
```

Wiederkehrender Text (z.B. Adresse, Widerrufstext o.ä.) kann auf einer Konfigurationsseite abgelegt werden und überall im Web benutzt werden (ohne Container).

**Angabe eines Pfads zum Menüpunkt**

```xml
<strong>Achtung:</strong> <bx:navlink path="/konfigtexte/"><bx:text.Warnhinweis/></bx:navlink>
```

# bx:news

Momentan nur für alte Container

```xml
<bx:news.loopyears pool="..." datumfield="Datum" archivfield="Archiv" desc>
  <li><a href="..."><bx:news.year/></a> (<bx:news.count/> Beiträge)</li>
<bx:news.loopyears>
```

# bx:option

```xml
<bx:option.Auswahlbezeichner options="Option1,Option2,Option3" values="o1,o2,o3"/>
```

Stellt sich in der Verwaltung als Select dar. Ist momentan nicht standardmäßig im System integriert.

| options | werden im Dropdown angezeigt |
| --- | --- |
| value | entsprechende Values zu den Options, Reihenfolge beachten! |

### Beispiele

```xml
<bx:clipboard.cut name="bildlage" trim>
  <bx:option.Bildlage options="kleines Bild links,kleines Bild rechts,großes Bild ganze Breite" values="li,re,ce"/>
</bx:clipboard.cut>
```

Im weiteren Verlauf der Seite kann man dann das Clipboard abfragen und entsprechende Designs ausliefern.

# bx:optional

In der Administration stellt sich das Tag `optional` als Checkbox dar. Im Frontend wird der Inhalt nur angezeigt, wenn der Haken gesetzt ist. Sinnvoll, wenn für viele Seiten das gleiche Template benutzt wird, um die Darstellungsformen zu erhöhen (z.B. Bild anzeigen oder nicht, Bild rechts oder nicht, Anzeige eines Submenüs oder nicht... usw.)

<p class="callout info">Dieses Tag kann sich in der Verwaltung darstellen.</p>

```xml
<bx:optional.{titel} [label="{text}"] [not]> Inhalt </bx:optional.{titel}>
<bx:optional.{titel} [label="{text}"] [true="{text}"] [false="{text}"] />
```

Die erste Form gibt den Inhalt nur aus, wenn der Haken gesetzt ist (not kehrt dies um).

In der zweiten Form kann je ein Text für beide Fälle gesetzt werden (Haken gesetzt bzw. nicht gesetzt).

|  |  |
| --- | --- |
| **label** | der Text neben der Checkbox in der Administration kann damit geändert werden (Standard: "Bereich anzeigen"). |
| **true, false** | Text, der für den jeweiligen Zustand ausgegeben werden soll |

### Beispiele

```xml
<img src="/static/<bx:pagedata.webdir/>/seitenbild_kontakt.png" alt="Seitenbild" align="<bx:optional.Anzeige_rechts>right</bx:optional><bx:optional.Anzeige_rechts not>left</bx:optional>">
```

# bx:pagedata

Mithilfe des Tags `pagedata` lassen sich die verschiedensten Informationen die Seite betreffend ausgeben.

## pagedata.parentnavid

```xml
<bx:pagedata.parentnavid/>
```

Es wird die Navigations-ID des Elternpunktes (oder leer) ausgegeben.

## pagedata.webid

```xml
<bx:pagedata.webid/>
<bx:pagedata.customerid/>	<!-- veraltet -->
```

Gibt die ID des Webs (Projekts) aus

## pagedata.webdir

```xml
<bx:pagedata.webdir/>
<bx:pagedata.customerdir/>	<!-- veraltet -->
```

gibt das virtuelle Verzeichnis des Webs aus.

## pagedata.webhost

```xml
<bx:pagedata.webhost [addscheme]/>

```

(Verfügbar ab Version 2.7)

Der beim Projekt eingegebene Haupthost wird ausgegeben. Wenn "addscheme" angegeben ist, wird auch das beim Projekt eingestellte Protokoll ausgegeben. Dies ist bei Canonical-Angaben nützlich, wenn nicht der aktuelle Host (wie bei `<bx:pagedata.hostname/>`) gebraucht wird, sondern die Hauptdomain.

## pagedata.virtualpath

```xml
<bx:pagedata.virtualpath [original]/>
```

Der virtuelle Pfad des Menüpunktes wird ausgegeben. z.B. von http://www.beispielseite.de/produkte/textiles/pullover/ wird ausgegeben: produkte/textiles/pullover

| original | es wird der ursprüngliche Pfad ausgegeben (bei forwards) |
| --- | --- |

## pagedata.navid

```xml
<bx:pagedata.navid [level="{n}"]/>							<!-- gibt nur die ID aus -->
<bx:pagedata.navid is="{id}"> Inhalt </bx:pagedata.navid>	<!-- Inhalt wird nur dann ausgegeben, wenn die ID des aktuellen Menüpunktes mit der ID von "is" übereinstimmt" -->
```

Navigations-ID des aktuellen Menüpunktes oder eines Elternpunktes
Um auch mehrere IDs, die Eltern-ID oder den Pfad abfragen zu können, benutzen Sie bitte `pagedata.nav`.

| level | Ebene des gewünschten Navigationspunktes<br>Hauptmenüpunkt entspricht<br>`level="0"`<br>, Untermenüpunkte liegen jeweils eine Ebene höher |
| --- | --- |
| is | vorgegebene ID |
| <span style="color: rgb(255,0,0);">NOT</span> | <span style="color: rgb(255,0,0);">funktioniert hier nicht, bitte pagedata.nav verwenden</span> |

## pagedata.navpath

```xml
<bx:pagedata.navpath [previous | next] [active | inactive | all] />
```

Gibt den virtuellen Pfad des Menüpunktes aus, z.B. von http://www.beispielseite.de/produkte/textiles/pullover/ wird ausgegeben: pullover

| previous<br>next | sucht den vorherigen bzw. nächsten Menüpunkt im gleichen Level |
| --- | --- |
| active<br>inactive<br>all | nur aktive anzeigen (Standard)<br>nur inactive anzeigen<br>alle anzeigen |

### Beispiele

```xml
<div style="float:left;width:100px;">
  <a href="<bx:pagedata.navpath previous/>">&laquo; vorherige Seite</a>
</div>
<bx:pagedata.navname />
<div style="float:right;width:100px;text-align:right;">
  <a href="<bx:pagedata.navpath/>">nächste Seite &raquo;</a>
</div>
```

Ein Blättern zwischen den (aktiven) Menüpunkten einer Ebene. Sieht dann ungefähr so aus:

| « vorherige Seite | Angebote für Juli | nächste Seite » |
| --- | --- | --- |

## pagedata.navname

```xml
<bx:pagedata.navname [level="{n}"] />
```

Gib den Name des Menüpunktes oder eines Elternpunktes aus.

| level | Ebene des gewünschten Navigationspunktes (nur höhere Ebenen vom aktuellen Menüpunkt aus)<br>Hauptmenüpunkt entspricht<br>`level="0"`<br>, Untermenüpunkte liegen jeweils eine Ebene höher |
| --- | --- |

## pagedata.nav

```xml
<bx:pagedata.nav {id="{id}" | parent="{id}" | path="{pfad}"} [not] [original]> Inhalt </bx:pagedata.nav>
```

Entscheidet, ob Inhalt ausgegeben wird anhand von ID(s) oder Pfad

| id | ID des gesuchten Menüpunktes<br>ab V 2.6.2: es können mehrere ID mit Komma getrennt angegeben werden |
| --- | --- |
| parent | ID des Elternmenüpunktes (findet auch sich selbst als Punkt) ab V 2.7: es können mehrere ID mit Komma getrennt angegeben werden |
| path | Pfad des aktuellen Menüpunktes |
| not | kehrt die Bedingung um |
| original | es wird die Angabe von der ursprünglichen Seite genommen (z.B. bei einem jsp-include ) |

## pagedata.request

Ab V 2.6.3 RC14 wird in den meisten Fällen ein HTML-Encoding gemacht, wo kein encode-Parameter angegeben ist und auch kein `<bx:tools.htmlencode>` außen herum ist. Dies verursacht manchmal **Probleme**:

- SQL-Filter: wenn encode=sql fehlt, wird jetzt HTML-Encoded (aus WHERE Ort LIKE '%Köln%' wurde WHERE Ort LIKE '%K&ouml;ln%' und es wurde nichts mehr gefunden)
- `<bx:clipboard.cut><bx:pagedata.request/></bx:clipboard.cut>` ... `<bx:tools.htmlencode><bx:clipboard.paste/></bx:tools.htmlencode>` führt jetzt zu doppelten kodieren.

```xml
<bx:pagedata.request name="{param}" [boundary="{text}"] [empty] encode="{ html | javascript | sql | sql-like | sql-rlike | url | xml | plain}"/>	<!-- Ausgabe des Request-Parameters -->
<bx:pagedata.request name="{param}" value="<text>" [true="{text}"] [false="{text}"] />

<bx:pagedata.request name="{param}" [not] [empty]> Inhalt </bx:pagedata.request>					<!-- Auswertung des Request-Parameters -->
<bx:pagedata.request name="{param}" value="{text}" [not]> Inhalt </bx:pagedata.request>
```

Request-Parameter auswerten

`<bx:pagedata.request ... encode="html|javascript|sql|sql-like|sql-rlike|url|xml">`

javascript und url gibt's schon seit v2.3, den Rest ab v2.6.2

| name | Name des Request-Parameters<br>kann auch einen Platzhalter in der Form<br>`name="[platz]id"`<br>enthalten (siehe Beispiel) |
| --- | --- |
| encode | Codierung des Wertes, für JavaScript-Code (Sonderzeichen werden escaped) oder als URL (%nn)<br>Hiermit kann der ausgegebene Text für verschiedene Formate kodiert werden:<br>- html - javascript - sql (zur Verwendung in SQL für Strings) - sql-like (zur Verwendung in SQL mit LIKE) - sql-rlike (zur Verwendung in SQL mit RLIKE und REGEXP) - url - xml - plain (überschreibt automatisches Encoding) - htmltext: siehe Beipspiel (3)<br>Das erspart ein bx:tools, was ansonsten um das bx:pagedata gepackt werden müsste. |
| boundary | Falls der Parameter mehrfach vorkommt (?para=wert1&para=wert2) wird ohne Angabe von<br>`boundary`<br>nur der Erste ausgegeben,<br>andernfalls wird der Wert von<br>`boundary`<br>als Trennzeichen benutzt. |
| not<br>empty | Falls `empty` gesetzt ist, wird ein leerer Request-Parameter wie ein nicht vorhander behandelt.<br>\|  \| seite.htm \| seite.htm?p= \| seite.htm?p=wert \| \| --- \| --- \| --- \| --- \| \| `<bx:pagedata.request name="p">...` \| leer \| angezeigt \| angezeigt \| \| `<bx:pagedata.request name="p" not>...` \| angezeigt \| leer \| leer \| \| `<bx:pagedata.request name="p" empty>...` \| leer \| leer \| angezeigt \| \| `<bx:pagedata.request name="p" not empty>...` \| angezeigt \| angezeigt \| leer \| |  | seite.htm | seite.htm?p= | seite.htm?p=wert | `<bx:pagedata.request name="p">...` | leer | angezeigt | angezeigt | `<bx:pagedata.request name="p" not>...` | angezeigt | leer | leer | `<bx:pagedata.request name="p" empty>...` | leer | leer | angezeigt | `<bx:pagedata.request name="p" not empty>...` | angezeigt | angezeigt | leer |
|  | seite.htm | seite.htm?p= | seite.htm?p=wert |
| `<bx:pagedata.request name="p">...` | leer | angezeigt | angezeigt |
| `<bx:pagedata.request name="p" not>...` | angezeigt | leer | leer |
| `<bx:pagedata.request name="p" empty>...` | leer | leer | angezeigt |
| `<bx:pagedata.request name="p" not empty>...` | angezeigt | angezeigt | leer |
| value | Text, den der Request-Parameter enthalten soll |
| true<br>false | Wenn der Wert des Parameters mit `value` verglichen wird kann entweder ` true` (wird ausgegeben, wenn gleich) und/oder `false` (wird ausgegeben, wenn ungleich) verwendet werden  oder man setzt den Inhalt, welcher dann bei Übereinstimmung ausgegeben wird (umkehrbar durch `not`).<br>ab v2.6.6: es kann auch abgefragt werden, ob der Parameter übergeben wurde oder nicht (siehe Beispiel) |

### Beispiele

Fall 1 true/false

```xml
<bx:pagedata.request name=“test“ value=“3“ true=”ist drei” false=”ist nicht drei” />
```

Fall 2 true/false

```xml
<bx:pagedata.request name=“test“ true=”test ist übergeben” false=”test ist nicht übergeben” />

```

es wird nicht der Wert abgefragt, sondern ob überhaupt der Parameter übergeben wurde

```xml
<bx:pagedata.request name=“test“ encode=”htmltext”/> 

```

Eingabe: test.htm?test=erste+Zeile%0azweite+Zeile   («%0a» ist ein Zeilenumbruch) →  schreibt «erste Zeile<br>zweite Zeile» und damit sieht man einen Zeilenumbruch im Browser

## pagedata.attribute

### Beispiele

```xml
speichern.act?feld=[]/Name[containerID]&containerID=12345
```

Bissl weit hergeholtes Beispiel: ... ich hab keine Ahnung!

```xml
speichern.act?feld=[]/Name[containerID]&containerID=12345
xml
test.htm?test=erste+Zeile%0azweite+Zeile  // "%0a" ist ein Zeilenumbruch

<bx:pagedata.request name="test" encode="htmltext"/> // schreibt erste Zeile<br>zweite Zeile und damit sieht man einen Zeilenumbruch im Browser
xml
<bx:pagedata.attribute name="{attrib}" />														<!-- schreibt den Wert des Attributes (falls vorhanden) in die Seite -->
<bx:pagedata.attribute name="{attrib}" [not]> Inhalt </bx:pagedata.attribute>					<!-- gibt den Tag-Inhalt aus, wenn das Attribut vorhanden ist -->
<bx:pagedata.attribute name="{attrib}" value="{text}" [not]> Inhalt </bx:pagedata.attribute>	<!-- vergleicht den Wert des Attributes mit dem Wert von value und gibt den Tag-Inhalt bei Übereinstimmung aus -->
```

Ein Request-Attribute, das z.B. durch JSP-Includes oder das bx:setattribute gesetzt wurde, kann ausgewertet werden.

| name | Name des Request-Attributs |
| --- | --- |
| value | beliebiger Text, der mit dem Attribut übereinstimmen muß (oder auch nicht bei<br>`not`<br>) |

## pagedata.setattribute

```xml
<bx:pagedata.setattribute mode="[copy | set | remove]" name="{name}"> Inhalt </bx:pagedata.setattribute>
```

Ein Request-Attributekann gesetzt, geändert oder gelöscht werden.

| name | Name des Request-Attributs |
| --- | --- |
| mode | `copy:` Zeigt den Taginhalt in der Seite an und kopiert ihn in das Request-Attribut `set:` Kopiert den Inhalt in das Request-Attribut aber zeigt ihn nicht in der Seite an  `remove:` löscht das Request-Attribut (das Tag wird geschlossen verwendet) |

## pagedata.scriptattribute

```xml
<bx:pagedata.scriptattribute name="{attrib}" />																<!-- gibt den Wert des Script-Attributes (falls vorhanden) aus -->
<bx:pagedata.scriptattribute name="{attrib}" [not]> Inhalt </bx:pagedata.scriptattribute>					<!-- gibt den Tag-Inhalt aus, wenn das Script-Attribut vorhanden ist -->
<bx:pagedata.scriptattribute name="{attrib}" value="{text}" [not]> Inhalt </bx:pagedata.scriptattribute>	<!-- vergleicht den Wert des Script-Attributes mit dem Wert von value und gibt den Tag-Inhalt bei Übereinstimmung aus -->
```

Ein Script-Attribut, das z.B. durch Actions gesetzt wurde, kann ausgewertet werden.

| name | Name des Script-Attributs |
| --- | --- |
| value | beliebiger Text, der mit dem Attribut übereinstimmen muß (oder auch nicht bei<br>`not`<br>) |

## pagedata.setscriptattribute

```xml
<bx:pagedata.setscriptattribute mode="[copy | set | remove]" name="{name}" [trim]> Inhalt </bx:pagedata.setscriptattribute>
```

Ein Script-Attribut kann gesetzt, geändert oder gelöscht werden.

| name | Name des Script-Attributs |
| --- | --- |
| mode | `copy:` Gibt den Taginhalt aus und kopiert ihn in das Script-Attribut `set:` Kopiert den Taginhalt in das Script-Attribut aber zeigt ihn nicht an  `remove:` löscht das Script-Attribut (das Tag wird geschlossen verwendet) |

## pagedata.listrequest

```xml
<bx:pagedata.listrequest/>
```

alle Request-Parameter werden als 'hidden' Formularfeld in die Seite geschrieben

## pagedata.querystring

```xml
<bx:pagedata.querystring [original]/>
```

QueryString ausgeben

Ein '?' am Anfang ist in der Ausgabe nicht enthalten. Ge**POST**ete Parameter sind nicht enthalten!
Falls dieses Tag im HTML-Quelltext (z.b. für Links) verwendet wird, muss die Ausgabe noch durch <a href="http://docs.batix.info/display/DEVS/bx%3Atools#bx:tools-tools.urlencode" target="_blank">bx:tool.urlencode</a> umgewandelt werden.

| original | es wird der ursprüngliche QueryString ausgegeben (bei forwards) |
| --- | --- |

## pagedata.meta

```xml
<bx:pagedata.meta name="<meta>" />													<!-- schreibt den Wert der Meta-Eigenschaft (falls vorhanden) in die Seite -->
<bx:pagedata.meta name="<meta>" [not]> Inhalt </bx:pagedata.meta>					<!-- gibt den Tag-Inhalt aus, wenn die Meta-Eigenschaft vorhanden ist -->
<bx:pagedata.meta name="<meta>" value="<text>" [not]> Inhalt </bx:pagedata.meta>	<!-- vergleicht den Wert der Eigenschaft mit dem Wert von value und gibt den Tag-Inhalt bei Übereinstimmung aus -->
```

Metadaten auswerten

| name | Name der Meta-Eigenschaft |
| --- | --- |
| value | beliebiger Text, der mit der Meta-Eigenschaft übereinstimmen muß (oder auch nicht bei<br>`not`<br>) |

## pagedata.cookie

```xml
<bx:pagedata.cookie name="{cookie}" />													<!-- schreibt den Wert des Cookies (falls vorhanden) in die Seite -->
<bx:pagedata.cookie name="{cookie}" [not]> Inhalt </bx:pagedata.cookie>					<!-- gibt den Tag-Inhalt aus, wenn der Cookie vorhanden ist -->
<bx:pagedata.cookie name="{cookie}" value="{text}" [not]> Inhalt </bx:pagedata.cookie>  <!-- vergleicht den Wert des Cookies mit dem Wert von value und gibt den Tag-Inhalt bei Übereinstimmung aus -->
```

Wertet vom Browser übergebene Cookies aus.

| name | Name des Cookies |
| --- | --- |
| value | beliebiger Text, der mit dem Cookie-Wert übereinstimmen muß (oder auch nicht bei<br>`not`<br>) |

## pagedata.hostname

```xml
<bx:pagedata.hostname [addscheme] />													<!-- gibt den Hostnamen des Servers aus (wenn Port != 80 Ausgabe = hostname:port -->
<bx:pagedata.hostname match="{regex}" [addscheme] [not]> Inhalt </bx:pagedata.hostname>	<!-- vergleich des Hostnames mit einem regulären Ausdruck (ab v2.5.5)-->
```

Der Hostname (und evtl. Port) der aktuellen Anfrage wird ausgegeben.

| match | Regulärer Ausdruck |
| --- | --- |
| addscheme | gibt zusätzlich das Protokoll (http:// oder<br>https://)<br>des aktuellen Seitenaufrufs aus |

### Beispiele

Wenn man im Web von batix. com folgende Tags einbindet:

```xml
<bx:pagedata.hostname/>
```

wir ausgegeben: www.batix.com

```xml
<bx:pagedata.hostname addscheme/>
```

 wird ausgegeben: http://www.batix.com (ab v2.5.8)

```xml
<bx:pagedata.hostname match=".*\.[com|net]"> Sie haben unsere net- oder com-Domain aufgerufen.</bx:pagedata.hostname>
```

beim Aufruf von www.batix.de oder www.batix.eu wird der Text nicht ausgegeben, beim Aufruf von www.batix.com oder www.batix.net schon.

## pagedata.sessionid

```xml
<bx:pagedata.sessionid/>
```

Die Session-ID wird ausgegeben.
Wenn es noch keine Session gibt, dann wird eine erstellt und dann ausgegeben, außer man gibt "no-create" an* (ab V 2.6.9)*

## pagedata.sessionurl

```xml
<bx:pagedata.sessionurl/>
```

Session-URL-Komponente (;jsessionid=) ausgeben, falls Cookies ausgeschaltet sind

## pagedata.url

```xml
<bx:pagedata.url [encode="html"] />
```

Dieser Befehl schreibt die komplette Request-URL inklusive Query-String in die Seite.
Falls `encode="html"` angegeben ist, werden <, >, ", & und ' durch ihre HTML-Umschreibungen ersetzt.

## pagedata.filename

```xml
<bx:pagedata.filename [original]/> 															<!-- der Dateiname wird ausgegeben (z. B. "index.htm") -->
<bx:pagedata.filename equals="{vergleichsname}" [not] [original]> ... </bx:pagedata.filename>	<!-- Taginhalt wird nur ausgeführt, wenn der aktuelle Dateiname dem angegebenen Namen entspricht (ab v2.5.7) -->
```

Gibt den virtuellen Dateinamen aus der gerade aufgerufenen URL zurück. Wenn die Seite mit "/" aufgerufen wird, behandelt das Tag den Namen als "index.htm".

| original | es wird der ursprüngliche Dateiname ausgegeben (bei forwards) |
| --- | --- |

## pagedata.errortext

```xml
<bx:pagedata.errortext/>
```

Fehlertext in eine Fehlerseite schreiben. Der Befehl ist nur in der Fehlerseite "/www/[host-dir]/errorpage/index.htm" verfügbar. (ab* v2.3.15)*

## pagedata.errorstacktrace

```xml
<bx:pagedata.errorstacktrace/>
```

Schreibt den Stacktrace einer Exception in die Fehlerseite. Der Befehl ist nur in der Fehlerseite "/www/[host-dir]/errorpage/index.htm" verfügbar. *seit v2.5.8*

## pagedata.remoteip

```xml
<bx:pagedata.remoteip/>			<!-- schreibt die IP-Adresse des Clients (der die Abfrage macht) in die Seite. (z. B. um sie in einen Container zu speichern)  -->
<bx:pagedata.remoteip equals="{testip}" [not]> Inhalt </bx:pagedata.remoteip>		<!-- Vergleich der IP und entsprechende Ausgabe des Tag-Inhalts -->
<bx:pagedata.remoteip host="{hostname}" [not]> Inhalt  </bx:pagedata.remoteip>
<bx:pagedata.remoteip matches="{regex}" [not]> Inhalt  </bx:pagedata.remoteip>
```

*(ab v2.5.7*)

### Beispiele

```xml
<bx:pagedata.remoteip matches="123\.210\.12\.[0-9]+">
 <a href="...">Intranet</a>
</bx:pagedata.remoteip>
```

 Inhalt nur für IP-Adressen im Bereich "123.210.12.*" zeigen

## pagedata.scheme

```xml
<bx:pagedata.scheme/>
```

Gibt das Protokoll zurück. ("http" oder "https") (ab* v2.5.8*)

## pagedata.compressed

```xml
<bx:pagedata.compressed />			<!-- es wird ".bxmin" ausgegeben* -->
<bx:pagedata.compressed>.bxmin</bx:pagedata.compressed>  <!-- der Inhalt des Body (im Beispiel ebenfalls ".bxmin")wird ausgegeben, ansonsten wird keine Ausgabe gemacht* -->
```

Unterscheidet abhängig vom Projektstatus die Einstellung der Scriptkomprimierung (ab* v2.6.2*).
*Greift, wenn das Projekt auf Produktiv und "Style- und Script-Compressor" im Projekt angehakt ist.

## pagedata.status

```xml
<bx:pagedata.status type="{dev | prod | debug}"> ... </bx:pagedata.status>
```

Zeigt abhängig vom Projektstatus den Taginhalt an (ab* v2.6.2*).

### Beispiele

```xml
<script src="tools<bx:pagedata.status type="prod">.bxmin</bx:pagedata.status>.js"></script>
```

Wenn das System auf "Produktiv" gestellt ist, wird tools.bxmin.js ausgegeben, sonst tools.js

## pagedata.charset

```xml
<bx:pagedata.charset />
```

Gibt den Zeichensatz aus, der beim Projekt bzw. beim Design angegeben wurde. Wenn bei beiden nichts angegeben wurde, wird nichts ausgegeben und es gilt der Standard der Servlet-API (iso-8859-1)

## pagedata.writecontenttype

```xml
<bx:pagedata.writecontenttype/>  
```

Gibt folgendes aus: `<meta http-equiv="Content-Type" content="[mimetype]; charset=[Zeichensatz]">`
Bisher wird es immer von Hand reingeschrieben und bei Änderung des Seiteneincodngs passen die Zeichensätze nicht mehr zusammen.

## pagedata.header

```xml
<bx:pagedata.header name="..." (value|matches|contains)="[Vergleichswert]" [not]>
```

### Beispiele

```xml
<a href="<bx:pagedata.header name="Referer"/>">zurück</a>
<bx:pagedata.header name="Referer" not>Direkt eingetippt</bx:pagedata.header>
<bx:pagedata.header name="accept-language" contains="es">¡hola!</bx:pagedata.header>
<bx:pagedata.header name="User-Agent" matches=".*(google|bing|yahoo).*">Hallo Suchmaschine!</bx:pagedata.header>
```

Verweise auf diese Seite:

- <a href="http://docs.batix.info/pages/viewpage.action?pageId=19300461" target="_blank">Container-Filteraction</a>
- <a href="http://docs.batix.info/display/DEVS/bx%3Atools" target="_blank">bx:tools</a>
- <a href="http://docs.batix.info/pages/viewpage.action?pageId=19300375" target="_blank">bx:tools</a>
- <a href="http://docs.batix.info/pages/viewpage.action?pageId=19300512" target="_blank">Support für not hinzufügen</a>
- <a href="http://docs.batix.info/pages/viewpage.action?pageId=19300504" target="_blank">Google-Sitemap Datei erzeugen</a>
- <a href="http://docs.batix.info/display/DEVS/Container-Filteraction" target="_blank">Container-Filteraction</a>
- <a href="http://docs.batix.info/display/DEVS/Google-Sitemap+Datei+erzeugen" target="_blank">Google-Sitemap Datei erzeugen</a>
- <a href="http://docs.batix.info/pages/viewpage.action?pageId=5472365" target="_blank">Support für not hinzufügen</a>

<p>(8 Verweise)</p>

# bx:pageinclude

Das Tag `pageinclude` bindet eine JSP- oder CM-Seite in das aktuelle Design ein. Die einzubindende Seite wird in der Administration dynamisch über ein Textfeld bestimmt.

```xml
<bx:pageinclude.{bezeichner} [jsp] [onlyactive] />
```

Bei der Angabe des Pfades zur Datei (in der Administration) kann statt` /www/webname/...` auch `/www/[webdir]/...` als Platzhalter benutzt werden. Dieser wird dann mit dem virtuellen Pfad ersetzt.

| jsp | wenn angeforderte Datei ein JSP-Script ist |
| --- | --- |
| onlyactive | Normalerweise wird die andere Seite eingebunden, egal ob sie aktiv oder inaktiv im Frontend ist (meistens wahrscheinlich inaktiv). Wenn man aber nach diesen Häkchen die Anzeige ein oder ausschalten will, kann man das onlyactive dranschreiben. ab v2.6.6. |

# bx:paypal

Mithilfe dieses Tags wird ein verschlüsselter Wert für ein `<hidden>`-Feld generiert, das an Paypal geschickt wird.

Nach dem Bestellprozeß wird ein Paypal-Button eingeblendet, der ein neues Fenster mit der Paypal-Website öffnet. Dies wird durch eine HTML-For ausgelöst:

```xml
<form action="https://www.paypal.com/cgi-bin/webscr" target="_blank" method="post">
 <input type="hidden" name="cmd" value="_s-xclick">
 <input type="text" name="encrypted" size=80 value="<bx:paypal.crypt pass="{Das Passwort}" cmdtext="cmd=_xclick,cert_id={Die ID von Paypal},business={Email-Adresse des Kunden},currency_code=EUR,item_name={Betreff}" paypalcert="{Zertifikat-Datei}" certfile="{Zertifikat-Datei}" keyfile="{Zertifikat-Datei}" price="{Betrag}"/>">
 <input type="image" style="margin-right:10px;" src="http://www.paypal.com/de_DE/i/btn/x-click-but6.gif" name="submit" alt="Zahlen Sie mit PayPal - schnell, kostenlos und sicher!">
</form>
```

Die Erzeugung der ID bei Paypal wird hier beschrieben: <a href="https://www.paypalobjects.com/de_DE/html/IntegrationCenter/ic_button-encryption.html" target="_blank">https://www.paypalobjects.com/de_DE/html/IntegrationCenter/ic_button-encryption.html</a> (Schritt 2 und 3 muß der Kunde mit seinem Paypal-Zugang durchführen)
 siehe auch: <a href="https://cms.paypal.com/us/cgi-bin/?cmd=_render-content&content_ID=developer/e_howto_html_encryptedwebpayments" target="_blank">https://cms.paypal.com/us/cgi-bin/?cmd=_render-content&content_ID=developer/e_howto_html_encryptedwebpayments</a>

Dort muß die .pem-Datei (Attribut `certfile`), die man mit Open-SSL erzeugt, hochladen und bekommt das öffentliche Zertifikat zurück (Attribut `paypalcert`). Der private Schlüssel im P12-Format wird ebenfalls mir OpenSSL generiert und bei Attribut `keyfile` ins Tag eingetragen. Das Passwort, das beim Erzeugen des P12-Schlüssels eingegeben wurde, muß im Attribut `pass` angegeben werden. Im Attribut `cmdtext` muß dann die ID von Paypal (nach Upload der .pem-Datei), die beim Erzeugen der Datei angegebene Email-Adresse und ein Infotext für die Buchung eingegeben werden.

Syntax:

```xml
<bx:paypal.crypt pass="..." cmdtext="..." paypalcert="..." certfile="..." keyfile="..." />
```

benötigte Tag-Parameter:

| certfile | eine Datei mit dem Public Cert (.pem) |
| --- | --- |
| keyfile | eine Datei mit dem Private Key in PKCS12-Format (.p12) |
| paypalcert | eine Datei mit PayPal's Public Cert |
| pass | ein Passwort mit dem die Datei in Parameter keyfile verschlüsselt ist |
| cmdtext | Format "cmd=_xclick,cert_id=[ID von Paypal],business=[email],currency_code=EUR,item_name=[infotext]" |

Desweiteren wird ein Request-Attribut oder Request-Parameter namens 'price' benötigt.

Ein Request-Parameter namens 'orderid' kann an den Infotext für Paypal angehängt werden.

### Beispiele

```xml
<bx:paypal.crypt pass="geheim"
  cmdtext="cmd=_xclick,cert_id=ABCD1234EF56,business=info@mustermann.de,currency_code=EUR,item_name=Bestellung bei Mustermanns" 
  paypalcert="133117E8C9D.txt" certfile="133117DCAB5.pem" keyfile="133117E4A90.p12" price="1234.50"/>
```

# bx:plugin

Mit dem Tag `plugin` kann man sicherstellen, daß Pluginseiten genauso aussehen wie normale Verwaltungsseiten.

## plugin.css

```xml
<bx:plugin.css/>

```

Es werden die nötigen Styles in den Head geschrieben, die der Pluginseite ihr Aussehen geben. und zwar:

```html
<link rel="STYLESHEET" href="/verwaltung/style.css" type="text/css">
<link rel="STYLESHEET" href="/verwaltung/control/css.jsp" type="text/css">
```

## plugin:headline

```xml
<bx:plugin.headline name="{titel1}" sub="{titel2"/>

<bx:plugin.headline name="{titel1}" sub="{titel2}">
  Inhalt
</bx:plugin.headline>

```

Die Überschrift der Seite wird generiert.

| name | Text, der in der oberen Zeile stehen soll |
| --- | --- |
| sub | Text, der darunter stehen soll |
| als offenes Tag | Inhalt, der oben rechts angezeigt werden soll (z.B. Link oder Drop-Down) |

## plugin.toolarea

```xml
<bx:plugin.toolarea>
  <bx:plugin.toolblock id="{id}" title="{text}" icon="{pfad}">
    Inhalt
  </bx:plugin.toolblock>
  ... evtl. weiterer toolblock
</bx:plugin.toolarea>

```

| id | frei wählbare id für die Box, muß auf der Seite eindeutig sein |
| --- | --- |
| title | Titel der Box |
| icon | Pfad:/verwaltung/control/imgnav/bildname.gif |
| open | beim Aufruf der Seite geöffnet |

### Beispiele

**Containerfilter-Aufruf im Quelltext**

```xml
<html>
  <head>
  <title><bx:pagedata.navname/></title>
  <bx:plugin.css/>
  </head>
  
  <body>
    <bx:plugin.headline name="Umfragetool" sub="Frage erstellen/bearbeiten">
      <a href="liste.htm">zurück zur Liste</a>
    </bx:plugin.headline>

    <bx:plugin.toolarea>
      <bx:plugin.toolblock id="tools" title="Tools" icon="/verwaltung/control/imgnav/tools.gif">
        <a href="umfragedetail.htm?umfrageid=<bx:pagedata.request name="umfrageid"/>">zurück zur Umfrage</a>        
        <a href="detail.htmumfrageid=<bx:pagedata.request name="umfrageid"/>">NEU</a>
      </bx:plugin.toolblock>
      <bx:plugin.toolblock id="info" title="Information" open icon="/verwaltung/control/imgnav/information.gif">
        Datum: <bx:tools.datum/><br>
        Zeit: <bx:tools.datum pattern="HH.mm 'Uhr' zzz"/>
      </bx:plugin.toolblock>
    </bx:plugin.toolarea>
    <div class="content">
      ...
    </div>
  </body>
</html>

```

# bx:record

Das Tag `record` stellt einen Datensatz einer Containerliste auf einer Seite dar. Es kann entweder ein Datensatz in der Verwaltung gewählt, oder direkt im Tag eine ID angegeben werden.

## ein bestimmtes Element anzeigen

```xml
<bx:record.{name} pool="{id}" [id="{id}"] [sub="{name}"] [show="{active | inactive | all}"] [list="{all}"] [size="{n}"]>
  <bx:recordfield.{feldname}/>
</bx:record.{name}>
```

| name | Bezeichner |
| --- | --- |
| pool | ID des betreffenden Containers |
| id | eine ID kann direkt oder über ein [Präfix](/books/cms-handbuch-entwickler/page/parameter-werte) angegeben werden**  nicht angegeben:** bestimmter Datensatz kann in der Administration über ein Auswahlfeld gewählt werden **angegeben:** DS mit dieser ID wird ausgegeben und es erfolgt keine Auswahl in der Administration   <p class="callout warning">Falls `id` verwendet wird, werden auch inaktive Datensätze angezeigt. Soll dies nicht sein, muss zusätzlich `show="active"` angegeben werden.</p> |
| sub | bestimmer Untercontainer kann als Basis für die Datensätze festgelegt werden<br><span style="color: rgb(255,102,0);"> (gilt für alte Container)</span> |
| show | Anzeige von aktiven, inaktiven oder allen Datensätzen |
| list | list=all: im Auswahlfeld in der Verwaltung werden auch die inaktiven DS angezeigt |
| size | Größenangabe für das Select-Tag |

## Angabe eines Filters zur Auswahleinschränkung in der Verwaltung

```xml
<bx:record.Feldname pool="{Container-ID}" name="{Feldname}" type="{Vergleichsart}" value="{Vergleichswert}"> ... </bx:record.Feldname>
```

(ab V 2.7.) Erweiterung im Tag, vergleichbar mit dem Filter am Tag bei  `<bx:containerfilter>` und auch die Felder sind so genannt. Dies schränkt die angezeigte Liste <span style="color: rgb(255,0,0);">in der **Verwaltung**</span> entsprechend des Filters ein.

| name | Name des zu überprüfenden Feldes (siehe auch "<br><a href="http://docs.batix.info/display/DEVS/Filter" target="_blank">Filter</a><br>") |
| --- | --- |
| type | Art des Vergleiches (siehe auch "<br><a href="http://docs.batix.info/display/DEVS/Filter" target="_blank">Filter</a><br>") |
| value | gesuchter Wert (siehe auch "<br><a href="http://docs.batix.info/display/DEVS/Filter" target="_blank">Filter</a><br>")<br>**statisch**<br>: einfach gesuchten Wert angeben (z.B. eine ID)<br>**dynamisch**<br>: mit Präfix (siehe auch "<br><a href="http://docs.batix.info/pages/viewpage.action?pageId=1507396" target="_blank">Präfixe</a><br>") |

### Beispiel

```xml
<bx:record.Beitrag pool="Seitentexte" name="Sprache" type="8" value="system:sprache"> <!-- ID für Sprache ist eine Systemvariable -->
  <a href="detail.htm?rid=<bx:recorddata.id/>"><bx:recordfield.Titel/></a>
</bx:record.Beitrag>
```

Es werden in der Verwaltung nur Beiträge zur Auswahl angezeigt, die die jeweilige Sprache haben. Die ID für die Sprache wird in einer Systemvariablen gespeichert.

## Dummy-Element anzeigen

```xml
<bx:record.{name} pool="{id}" id="attribute:xx" dummy> Inhalt </bx:record.{name}>
```

Ist das id-Feld leer, wird ein Dummy-Datensatz angezeigt, d.h., die im Inhalt angebenen Felder sind leer.

### Beispiel

```xml
<form action="save.act" method="post">
  <bx:record.Kontakt pool="11111111111" id="request:kontaktid" dummy>  
    <bx:if><input type="hidden" name="kontaktid" value="<bx:recorddata.id/>"></bx:if>
    <input type="text" name="Name" value="<bx:recordfield.Name/>">
    <input type="text" name="Vorname" value="<bx:recordfield.Vorname/>">
    <input type="text" name="Email" value="<bx:recordfield.Email/>">
    <input type="submit" value="abschicken">
  </bx:record.Kontakt >
</form>
```

Ein Formular muß nur einmal gebaut werden, da auch der Fall eines leeren Formulars damit abgedeckt ist. Allerdings darf dann die recordid als hidden-Field nicht mit übergeben werden (in ifs einschließen).

## Mehrfach-Auswahl

```xml
<bx:multirecord.{name} pool="{id}" ...> Inhalt </bx:multirecord.{name}>
```

Dieses Tag funktioniert wie bx:record, es können aber mehrere Datensätze ausgewählt werden.

# bx:recordchoice

Das Tag `recordchoice` dient dem Anzeigen eines verknüpften Containerdatenfeldes z. B. als Dropdownfeld oder Liste von Radiobuttons, wobei der aktuell zugewiesene Datensatz angewählt ist und die Liste durch Datensätze einer Containerliste gefüllt wird.

## einfache, kurze Variante

```xml
<bx:recordchoice.if field="{feldname}" [baseloop="{name}"] current> Inhalt </bx:recordchoice.if>
```

Dies ist die schnellste und unkomplizierteste Methode für eine Recordchoice-Abfrage.* Nur für neue Container, ab Version 2.5.9 verfügbar*.

| field | Feldname im umgebenden Container |
| --- | --- |
| baseloop | Name des betreffenden Containers (bei Schachtelungen nötig) |
| current | aktueller Datensatz |

### Beispiele

**Auflistung**

```xml
<bx:containerfilter.Rezept pool="Rezepte" idfield="rid">
  ...
  Kategorien: <br>
  <bx:containerfilter.Kategorien pool="Rezeptkategorien">
    <div class="<bx:recordchoice.if field="Kategorie" current>aktiv</bx:recordchoice.if><bx:recordchoice.if field="Kategorie" current not>inaktiv</bx:recordchoice.if>">
    <bx:recordfield.Titel/>
  </bx:containerfilter.Kategorien>
  ... 
</bx:containerfilter.Rezept>
```

Auf der Detailseite des Rezepts werden alle Kategorien aufgelistet und die verknüpften bekommen die Klasse `aktiv`, die nicht verknüpten die Klasse `inaktiv`. Diese Klassen können dann beliebig gestylt werden, z. B. mit verschiedenen Hintergrundfarben usw.

**Verwendung in einem Select-Feld**

```xml
<form ...>
<bx:containerfilter.Rezept pool="Rezepte" idfield="rid">
  ...
  Kategorie:<br>
  <select name="Kategorie">
    <option value="">bitte wählen</option>
    <bx:containerfilter.Kategorien pool="Rezeptkategorien">
    <option value="<bx:recorddata.id/>"<bx:recordchoice.if field="Kategorie" current> selected</bx:recordchoice.if>><bx:recordfield.Titel/></option>
    </bx:containerfilter.Kategorien>
  </select>
  ...
</bx:containerfilter.Rezept>
</form>
```

Formular, um Rezepte einzugeben.
Die Funktion würde hier beim Wiederaufruf nach fehlgeschlagener Validierung zum Tragen kommen oder wenn das Rezept geändert wird.
Die Kategorien stehen im Container "Rezeptkategorien" und sind über das Feld "Kategorie" in den Rezept-Datensatz eingebunden.

**noch ein Beispiel**

```xml
<bx:containerfilter.Kontakt pool="12E28377495" idfield="recordid" force="single" dummy>
  <form action="save.act" method="post">
    <bx:if><input type="hidden" name="recordid" value="<bx:pagedata.request name="recordid"/>"></bx:if>
    <label class="label" for="Name">Name:</label><input class="input" id="Name" type="text" name="Name" value="<bx:recordfield.Name/>"><br>
    <label class="label" for="Email">E-Mail:</label><input id="Email" type="text" name="Email" value="" class="input">
    <label class="label" for="Hobbies">Ihre Hobbies:</label>
    <bx:containerloop.Hobbies pool="11111111111">
      <input type="checkbox" value="<bx:recorddata.id/>"<bx:recordchoice.if field="Hobbies" current> checked</bx:recordchoice.if>>&nbsp;<bx:recordfield.Titel/><br>
    </bx:containerloop.Hobbies>
    <textarea class="input" id="Text" rows="5" cols="40" name="Text"><bx:recordfield.Text/></textarea><bx:javainclude modul="Validator" field="Text" /><br>
    <input class="submit" type="submit" value="abschicken">
  </form>
</bx:containerfilter.Kontakt>
```

## ausführliche Variante

```xml
<bx:recordchoice name="{feld}" pool="{id}"> Inhalt </bx:recordchoice>
```

Erklärungstext.

| name | Name des verknüpften Feldes im aktuellen Record |
| --- | --- |
| pool | Datenliste, welche die zur Auswahl stehenden Datensätze enthält |

Innerhalb dieses Tags können die folgenden Tags benutzt werden.

### recordchoice.if

```xml
<bx:recordchoice.if (empty | unknown) [not]> Inhalt </bx:recordchoice.if>
```

Dieses Tag gibt seinen Inhalt nur bei bestimmten Bedingungen aus.

| empty<br>unknown | Der Inhalt wird nur angezeigt, falls aktuell  nichts oder  ein unbekanntes/gelöschtes Objekt verknüpft ist. |
| --- | --- |
| not | kehrt die Bedingung um |

### recordchoice.poolid

```xml
<bx:recordchoice.poolid/>
```

Die unter `pool` (im umgebenden Tag) angegebene ID wird ausgegeben.

### recordchoice.loop

```xml
<bx:recordchoice.loop [list="active"] [orderby="{field}"] [desc] [max="{n}"]> Inhalt </bx:recordchoice.loop>
```

Es wird eine Schleife erzeugt, die jeden möglichen Datensatz auflistet. Innerhalb dieser Schleife kann z.B. mittels <a href="http://wiki.batix.net/index.php/Bx:recorddata" target="_blank">Bx:recorddata</a> oder <a href="http://wiki.batix.net/index.php/Bx:recordfield" target="_blank">Bx:recordfield</a> auf Daten zugegriffen werden.
**Hinweis:** Es empfiehlt sich bx:recordchoice.loop durch z.B. <a href="http://wiki.batix.net/index.php/Bx:containerloop" target="_blank">Bx:containerloop</a> oder <a href="http://wiki.batix.net/index.php/Bx:containerfilter" target="_blank">Bx:containerfilter</a> zu ersetzen, um größere Flexibilität zu erhalten. Das ist möglich, da diese Tags alle vom Typ Containerschleife sind.

| list | list="active" - zeigt nur aktive Datensätze an |
| --- | --- |
| orderby | ein Feld, nach dem sortiert werden soll |
| desc | kehrt die Sortierrichtung um |
| max | es werden nur eine bestimmte Anzahl an Elementen angezeigt |

Ebenfalls kann innerhalb der Schleife bx:recordchoice.if verwendet werden, allerdings mit einer anderen Bedeutung und anderen Parametern.

```xml
<bx:recordchoice.if [not] current value="<text>" />
<bx:recordchoice.if [not] current> Inhalt </bx:recordchoice.if>
```

| current |  |
| --- | --- |
| value | Der Inhalt bzw. der Text von<br>`value`<br>wird nur ausgegeben, wenn das Schleifenelement aktuell zugewiesen ist bzw. nicht ist (<br>`not`<br>). |

### Beispiele

**Einzelverknüpfung**

```xml
<label for="Branche">Branche</label><br/>
<select name="Branche" id="Branche">
  <bx:recordchoice name="Branche" pool="11111111111">
    <bx:containerloop pool="11111111111" orderby="Titel">
      <option value="<bx:recorddata.id/>" <bx:recordchoice.if current>selected="selected"</bx:recordchoice.if>>
        <bx:recordfield.Titel/>
      </option>
    </bx:containerloop>
  </bx:recordchoice>
</select>

```

Dieser Code erzeugt eine Dropdown-Liste zum Auswählen eines Elementes für die Einfachverknüpfung "Branche". Die möglichen Werte für die Auswahl stehen im Container 11111111111. Der aktuell zugewiesene Datensatz ist ausgewählt.

**Mehrfachverknüpfung**

```xml
<input type="hidden" name="Branchen.LINKLIST" value="22222222222">
<bx:recordchoice name="Branchen" pool="22222222222">
  <bx:containerloop pool="22222222222" orderby="Titel">
    <label>
      <input type="checkbox" name="Branchen.LINKRECORD" id="id_<bx:recorddata.id/>" value="<bx:recorddata.id/>"<bx:recordchoice.if current> checked="checked"</bx:recordchoice.if>>
    </label><br>
  </bx:containerloop>
</bx:recordchoice>

```

Es werden für jeden Datensatz aus dem Container 22222222222 Checkboxen erzeugt. Alle aktuell zugewiesenen Elemente sind angehakt. Das Hidden-Field Branchen.LINKLIST wird benötigt, da der Browser wenn keine Checkbox angehakt ist sonst nichts sendet.

# bx:recorddata

Das Tag `recorddata` gibt zusätzliche Daten innerhalb einer Containerliste (z.B. [bx:containerloop](/books/cms-handbuch-entwickler/page/bx-containerloop) oder [bx:containerfilter](/books/cms-handbuch-entwickler/page/bx-containerdata)) aus oder steuert die Ausgabe von Daten in verschiedenen Abhängigkeiten.

## recorddata.id

```xml
<bx:recorddata.id [level="<n>" | parent | parent="<n>" | baseloop="<base>"] [{filter="<name>" | dynamicfilter="<name>"} [quiet]] />
```

Gibt die ID eines Datensatzes innerhalb einer Containerliste aus.

| level | ID des DS in der angegebenen Ebene einer verschachtelten Containerliste wird zurückgegeben,<br>wobei "0" die äußerste Containerliste ist und alle weiteren inneren Containerlisten jeweils um 1 erhöht werden (0,1,2,...). |
| --- | --- |
| parent<br>parent=... | hat die selbe Wirkung wie<br>`level`<br>, nur dass hier von der aktuellen Containerliste mit "0" ausgegangen wird und für jede<br>weiter übergeordnete Containerliste 1 addiert wird (...,2,1,0).<br>` parent`<br>ist identisch mit<br>`parent="1"`<br>. |
| baseloop | übergeordneten Containerliste direkt mit Namen ansprechen, vorausgesetzt, es wurde auch ein Name vergeben (siehe<br>[Bx:containerloop](/books/cms-handbuch-entwickler/page/bx-containerloop)<br>und<br>[Bx:containerfilter](/books/cms-handbuch-entwickler/page/bx-containerdata)<br>). |
| filter<br>dynamicfilter | es kann ein<br>JSP-Baustein<br>als Filter angegeben werden |
| quiet | Fehlermeldungen des Filters wird unterdrückt |

## recorddata.creationdate

```xml
<bx:recorddata.creationdate  [pattern=""] [locale=""] />
```

Wandelt die ID in Datum um.

| pattern | Ausgabe-Pattern, Standard: dd.MM.yyyy |
| --- | --- |
| locale | Sprachausgabe, Standard: de |

## recorddata.containerid

```xml
<bx:recorddata.containerid />
```

Gibt die Container-ID aus (ab Version 2.6.2).

## recorddata.titel

```xml
<bx:recorddata.titel />

```

Gibt den Titel des aktuellen Datensatzes einer Containerliste aus. Der Titel ist der Selbe, der auch in der <a href="http://wiki.batix.net/index.php/Definition" target="_blank">Containerdefinition</a> als Anzeigeelement angegeben wurde.

## recorddata.if

```xml
<bx:recorddata.if [first | last] [not] > Inhalt </bx:recorddata.if>
<bx:recorddata.if [request="{name}" | baseloop="{name}" | id="{ID}" | id="attribute:{Name}" | id="clipboard:{Name}" ] [not]> Inhalt </bx:recorddata.if>
<bx:recorddata.if ... [true="{Ausdruck}"] [false="{Ausdruck}"] />

```

Mit diesem Tag kann auf einen Request-Parameter der Seite reagiert werden, der die ID eines Datensatzes der Containerliste enthält. Außerdem kann auf die DS-ID reagiert werden und die erste bzw. letzte Position ermittelt werden.

| first \| last | Abfrage, ob es der erste oder letzt DS der Datenliste ist |
| --- | --- |
| request | Name des Request-Parameter, der die gesuchte ID enthält<br>`{name}`<br>kann auch einen Platzhalter in der Form<br>`request="[platz]"`<br>enthalten. In diesem Fall wird<br>`[platz]`<br>durch den Wert des Requestparameters<br>`platz`<br>ersetzt. |
| baseloop | Angabe |
| id | Angabe der gesuchten IDs (mit Komma oder Leerzeichen getrennt), entweder direkt oder mit einem [Präfix](/books/cms-handbuch-entwickler/page/parameter-werte) Abfrage, ob Dummy-Datensatz:` id=""`<br>ab V2.5.9: Abfrage dummy mit `#null` |
| not | kehrt die Bedingung um |
| true \| false | Im Tag ohne Inhalt wird der Wert von<br>`true`<br>bei Übereinstimmung ausgegeben, sonst der Wert von<br>`false`<br>. |

### Beispiele

```xml
<bx:containerfilter.Mitglieder pool="Mitglieder" force="list">
  <div style="border-top:1px solid black;<bx:recorddata.if last true="border-bottom:1px solid black;" false="margin-bottom:20px;"/>">
    <bx:recordfield.Titel/>
  </div>
</bx:containerfilter.Mitglieder>
```

Beim letzten DS der Liste soll die Anzeigeliste mit einem Strich abgeschlossen werden. Ansonsten wird ein Abstand zwischen den einzelnen Divs angezeigt.

```xml
<bx:containerfilter.Mitglieder pool="Mitglieder" force="list">
  <bx:recorddata.if request="[platz]">......<bx:recorddata.if>
</bx:containerfilter.Mitglieder>
```

Browseraufruf: <a href="http://www.musterseiten.de/menuepunkt1/?platz=id1&id1=xxxxxxx&id2=yyyyyyyy&id3=zzzzzzzzzz" target="_blank">http://www.musterseiten.de/menuepunkt1/?platz=id2&id1=xxxxxxx&id2=yyyyyyyy&id3=zzzzzzzzzz</a>
Es wird die id2 zur Überprüfung herangezogen.

### Infos über Verhalten / Buginfo

**v2.5.8 Inhalt wird ausgeführt, wenn die ID des Datensatzes der ID im Parameter entspricht:**

```xml
<bx:recorddata.if id="{Batix-ID}" [not]> ... </bx:recorddata.if>
<bx:recorddata.if id="{Batix-ID}" [true="{angezeigter Text}"] [false="{angezeigter Text}"]/>
```

**Inhalt wird ausgeführt, wenn man sich gerade in einem Dummy-Datensatz befindet:**

```xml
v2.6.2 neu <bx:recorddata.if id="" [not]> ... </bx:recorddata.if>
v2.6.3 neu <bx:recorddata.if id="attribute:undefiniert" [not]> ... </bx:recorddata.if>
v2.6.3-v2.6.4.1** Bug** bei <bx:recorddata.if id="" [not]>
v2.7.1 neu <bx:recorddata.if id="#null" [not]> ... </bx:recorddata.if>
```

**Inhalt wird ausgeführt, wenn die ID des Datensatzes einer der IDs im Parameter entspricht (oder #null):**

```xml
v2.6.3 <bx:recorddata.if id="{Batix-ID1},{Batix-ID2}" [not]> ... </bx:recorddata.if>
v2.7.1 <bx:recorddata.if id="{Batix-ID1},{Batix-ID2},#null" [not]> ... </bx:recorddata.if>
```

**Bug v2.6.3-v2.6.4.1**: `<bx:containerloop force=single dummy><bx:recorddata.if id="request:recordid">`

'test.htm' [ok, ist dummy]
'test.htm?recordid=' [Dummy wird nicht mehr erkannt]
'test.htm?recordid=1234567ABCD' [ok, kein dummy]
in v2.6.2 und v>2.6.4.1 geht es wieder

## recorddata.currentindex

```xml
<bx:recorddata.currentindex [add="{n}"] [baseloop="{base}"] />

```

Gibt die Nummer des aktuellen Datensatzes einer Containerliste aus beginnend mit "1" für den Ersten. Auch wenn die Ausgabe über Blätterfunktionen eingeschränkt ist, wird immer die Nummer über die gesamte Liste ausgegeben, so als wären keine Beschränkungen da.

| add | bewirkt, dass immer die Ausgabe der aktuellen Nummer plus den Wert von<br>`add`<br>ausgegeben<br>Standard ist 1, d.h., weil bei 0 angefangen wird, wird bei Nicht-Angabe des Add-Parameters<br>bei 1 angefangen. Soll bei 0 angefangen werden, muß add="0" sein (heißt: zum Startwert 0<br>wird 0 hinzugezählt anstatt (Standard)1 ). |
| --- | --- |
| baseloop | Index einer übergeordneten Liste abfragen |

## recorddata.pageindex

```xml
<bx:recorddata.pageindex [add="<n>"] />

```

funktioniert im Prinzip genau wie `recorddata.currentindex`, nur, dass hier die Nummerierung Seitenweise erfolgt. Das heißt, auch bei einer Blätterfunktion werden nur die aktuell sichtbaren Datensätze durchnummeriert, beginnend bei "1", unabhängig von der gesamten Anzahl an Datensätzen in der Containerliste.

## recorddata.ifcontains

Diese Funktion ist entweder noch in Entwicklung oder sehr speziell. Bitte ggf. nachfragen!

## recorddata.ifmatch

(zum Löschen vorgesehen)

Vergleicht den aktuellen Datensatz in der Eltern-Containerschleife mit dem Datensatz in der Großeltern-Containerschleife und führt den Taginhalt nur aus, wenn beide aktuellen Datensätze den selben Containerdatensatz darstellen.

## recorddata.cols

```xml
<bx:recorddata.cols num="{n}" equals="{n}" [not] > ... </bx:recorddata.cols>
<bx:recorddata.cols num="{n}" equals="{n}" true="{Ausdruck}" false="{Ausdruck}" />
<bx:recorddata.cols num="{n}" [col]{n}="<Ausdruck>" />

```

Dieses Kommando zeigt Daten abhängig von der Spaltennummer der Containerschleife an.

| num | Anzahl an Spalten in der Ausgabe |
| --- | --- |
| equals | aktuelle Position in der Spalte |
| not | kehrt Bedingung um |
| true \| false | bei Zutreffen bzw. Nichtzutreffen der Bedingung wird der jeweils angegebenen Text ausgegeben |
| col[n] | es kann jede einzelne Spalte angesprochen werden<br>(die Spalten können hier entweder 1, 2, 3 oder col1, col2, col3 heißen) |

### Beispiele

```xml
<div class="liste">
  <div class="item"<bx:recorddata.cols num="5" equals="5"> style="margin-right:0;"</bx:recorddata.cols>>
   <a href="detail.htm?id=<bx:recorddata.id/>"><bx:recordfield.Titel/></a>
  </div>
  <bx:recorddata.cols num="5" equals="5"><div class="clear"></div></bx:recorddata.cols>
</div>
```

Der letzte DS in der Reihe, die aus 5 Elementen besteht, soll keinen rechten Abstand haben. Danach soll ein Clear-Div stehen.

```xml
<div class="liste">
  <div class="item" style="<bx:recorddata.cols num="5" equals="5" not true="margin-right:10px" false="margin-right:0"/>;">
   <a href="detail.htm?id=<bx:recorddata.id/>"><bx:recordfield.Titel/></a>
  </div>
  <bx:recorddata.cols num="5" equals="5" true="<div class="clear"></div>"/>
</div>
```

Gleiches Beispiel wie oben, allerdings mit true|false

```xml
<div class="liste">
  <div class="item" style="background-color:<bx:recorddata.cols num="7" col1="red" col2="orange" col3="yellow" col4="green" col5="lightskyblue" col6="blue" col7="darkviolett"/>;">
   <a href="detail.htm?id=<bx:recorddata.id/>"><bx:recordfield.Titel/></a>
  </div>
  <bx:recorddata.cols num="7" equals="7" true="<div class="clear"></div>"/>
</div>
```

Die Spalten sollen Regenbogenfarben als Hintergrund bekommen (issn dämliches Beispiel, ich weiß - Vorschläge willkommen)

## recorddata.active

```xml
<bx:recorddata.active [not]> ... </bx:recorddata.active>
<bx:recorddata.active [true="{Ausdruck}"] [false="{Ausdruck}"] />

```

führt den Ausdruck abhängig vom Aktivstatus des Containerdatensatzes aus (Häkchenfeld im DS im Container ganz oben. Man kann also auch inaktive DS anzeigen lassen. 
Auch dieses Tag kann entweder mit Inhalt (und optional mit `not`) versehen oder mit den Parametern `true` und/oder `false` verwendet werden.

## Blätterfunktionen

[Beispiel für eine Blätterfunktion](/books/cms-handbuch-entwickler/page/bx-container)

### recorddata.nav

```xml
<bx:recorddata.nav [object="{bez}"] [labelname="{bez}"] [param="{bez}"] [indexparam="{bez}"] [filename="{bez}"]> ... </bx:recorddata.nav> 
```

Dieses Tag erzeugt keine Ausgabe, sondern fasst Parameter zusammen, die zur Navigation in Listen verwendet werden.
 Diese Parameter werden bei Tags, die .nav unterstützen nicht noch einmal aufgeführt! 
Beim Seitenblättern muss ein **Anzeigelimit** (Parameter `max`) bei der entsprechenden Liste definiert sein!

| object<br>labelname | Name bzw. den Labelname des Containerloops |
| --- | --- |
| param | Name des Request-Parameters mit der Datensatz-ID (bei Blättern Einzeldatensatz) Standard:<br>`param` |
| indexparam | Name des Request-Parameter, der die Index-Position enthält (bei Listenblättern) Standard:<br>`index` |
| filename | (nur für alte Container) bezeichnet die Datei, auf die verlinkt wird (z.B. bei<br>`.previouslist`<br>). |

### Beispiele

**Listenblättern**

```xml
<bx:containerfilter.Voegel pool="Tiere" force="list" max="10">
  <a href="detail.htm?vid=<bx:recorddata.id/>"><bx:recordfield.Titel/></a><br>
</bx:containerfilter.Voegel>
...
<bx:recorddata.nav object="Voegel" indexparam="pos">
  <bx:recorddata.previouslist/> | <bx:recorddata.nextlist/>
</bx:recorddata.nav> 
```

Blätterfunktion in einer Liste. Im Requestparameter `pos` steht dann beim Blättern die entsprechende Index-Position innerhalb der Liste. `nextlist` generiert einen Link, der ca. so aussieht: url/navpunkt/liste.htm?pos=11

**DS-Blättern**

```xml
<bx:containerfilter.Voegel pool="Tiere" idfield="vid" force="single">
  <a href="detail.htm?vid=<bx:recorddata.id/>"><bx:recordfield.Titel/></a><br>
</bx:containerfilter.Voegel>
...
<bx:recorddata.nav object="Voegel" param="vid">
  <bx:recorddata.previouselement/> | <bx:recorddata.nextelement/>
</bx:recorddata.nav> 
```

DS-Blättern auf der Detailseite. Im Requestparameter `vid` steht die DS-ID. `previouselement` generiert einen Link, der ca. so aussieht: url/navpunkt/detail.htm?vid=1111111111

**Labelverwendung**

```xml
<bx:containerfilter label="Voegel" pool="Tiere" force="list" max="10" name="Klasse" type="8" value="33333333333">
  <a href="detail.htm?vid=<bx:recorddata.id/>"><bx:recordfield.Titel/></a><br>
</bx:containerfilter>
...
<bx:recorddata.nav labelname="Voegel" indexparam="pos">
  <bx:recorddata.previouslist/> | <bx:recorddata.nextlist/>
</bx:recorddata.nav> 
```

Wenn der Container keine Bezeichnung hat (z.B. bei Bedingung im Tag), dann kann auch ein Label zur Zuordnung verwendet werden.

### Seitenblättern

#### recorddata.previouslist

**Hinweis:** Dieses Tag kann innerhalb von `recorddata.nav` benutzt werden und von dort alle relvanten Parameter übernehmen.

```xml
<bx:recorddata.previouslist [type="link | url | index | if"] [plain] [show] [encode="plain | html"] [not] /> <!-- Link wird erzeugt, Standardtext: zurück -->
<bx:recorddata.previouslist Parameter siehe oben> Linktext </bx:recorddata.previouslist>  <!-- eigener Linktext kann ausgegeben werden -->

```

Gibt einen Link zur vorherigen Seite der Listenansicht aus, falls es eine vorherige Seite gibt. Nicht alle Parameter sind gleichzeitig verwendbar (Standard ist "link").

| type="link" | gibt einen Link aus (<a href="...">zurück</a>) verwendbare Parameter: show |
| --- | --- |
| type="url" | gibt nur den relativen Pfad aus (datei.htm?...) verwendbare Parameter: encode |
| type="index" | gibt nur den neuen Index aus |
| type="if" | gibt den Inhalt des Tags aus, wenn die vorherige Seite existiert  verwendbare Parameter: not |
| plain | setzt<br>`type`<br>auf<br>`"url"` |
| show | zeigt den Text auch dann an, wenn keine Vorgängerseite existiert |
| encode | kodiert jedes Zeichen des Links bei Angabe von<br>`html`<br>als &#nnn;<br>(ist standardmäßig gesetzt, um dies abzustellen<br>`encode="plain"`<br>angeben) |
| not | kehrt den Effekt bei<br>`type="if"`<br>um |

#### recorddata.nextlist

**Hinweis:** Dieses Tag kann innerhalb von `recorddata.nav` benutzt werden und von dort alle relvanten Parameter übernehmen.

(identisch mit .previouslist, nur dass hier die nächste Seite verlinkt wird und der Linktext standardmäßig "weiter" lautet)

```xml
<bx:recorddata.nextlist [type="link | url | index | if"] [plain] [show] [encode="plain | html"] [not] />        <!-- Link wird erzeugt, Standardtext: weiter-->
<bx:recorddata.nextlist Parameter siehe oben> Linktext </bx:recorddata.nextlist >                                 <!-- eigener Linktext kann ausgegeben werden -->
```

#### recorddata.firstlist

**Hinweis:** Dieses Tag kann innerhalb von `recorddata.nav` benutzt werden und von dort alle relvanten Parameter übernehmen.

(identisch mit .previouslist, nur dass hier die erste Seite verlinkt wird und der Linktext standardmäßig "erste Seite" lautet)

```xml
<bx:recorddata.firstlist[type="link | url | index | if"] [plain] [show] [encode="plain | html"] [not] /> <!-- Link wird erzeugt, Standardtext: erste Seite-->
<bx:recorddata.firstlist Parameter siehe oben> Linktext </bx:recorddata.firstlist>  <!-- eigener Linktext kann ausgegeben werden -->
```

#### recorddata.lastlist

**Hinweis:** Dieses Tag kann innerhalb von `recorddata.nav` benutzt werden und von dort alle relvanten Parameter übernehmen.

(identisch mit .previouslist, nur dass hier die letzte Seite verlinkt wird und der Linktext standardmäßig "letzte Seite" lautet)

```xml
<bx:recorddata.lastlist[type="link | url | index | if"] [plain] [show] [encode="plain | html"] [not] /> <!-- Link wird erzeugt, Standardtext: letzte Seite-->
<bx:recorddata.lastlist Parameter siehe oben> Linktext </bx:recorddata.lastlist>  <!-- eigener Linktext kann ausgegeben werden -->
```

### Datensatzweise blättern

#### recorddata.previouselement

**Hinweis:** Dieses Tag kann innerhalb von `recorddata.nav` benutzt werden und von dort alle relvanten Parameter übernehmen.

```xml
<bx:recorddata.previouselement [type="link | url | if | id | title"] [encode="html | plain"] [not] [show] [loop]/>      <!-- Link wird erzeugt, Standardtext: zurück-->
<bx:recorddata.previouselement Parameter siehe oben> Linktext </bx:recorddata.previouselement >                         <!-- eigener Linktext kann ausgegeben werden -->
<bx:recorddata.previouselement type="object"><bx:recordfield.Titel/></bx:recorddata.previouselement >
```

Diese Funktion generiert einen Link zum vorherigenElement der Liste (nur bei Detailansicht).

| type="link" | (Standard) produziert einen klickbaren Link wenn das entsprechende Element existiert (immer anzeigen mittels show) |
| --- | --- |
| type="url" | gibt die relative URL aus |
| type="if" | gibt den Inhalt des Tags nur aus, wenn das Element existiert (kann mit not umgekehrt werden) |
| type="id" | zeigt nur die ID des Datensatzes an |
| type="title" | zeigt nur den Name des Datensatzes an (so wie er in der Verwaltung angezeigt wird) |
| type="object" | ab V 2.6.2: Tag wird als offenens Tag benutzt und ermöglich, direkt auf das erste Element (Datensatz) zuzugreifen,<br>um z.B. den Titel anzuzeigen. Sonst wird nur die ID übergeben und man hat keine Möglichkeit, die DS-Felder auszulesen. |
| encode | `encode="html"`<br>(nur bei<br>`type="url"`<br>unterstützt) bewirkt, dass jedes Zeichen in &#nnn; umgewandelt wird (ist standardmäßig gesetzt, um dies abzustellen<br>`encode="plain"`<br>angeben). |
| loop | signalisiert, dass es sich um eine Endlosliste handelt, d.h. Vorgänger vom ersten Element ist das letzte Element |

#### recorddata.nextelement

**Hinweis:** Dieses Tag kann innerhalb von `recorddata.nav` benutzt werden und von dort alle relvanten Parameter übernehmen.
 (identisch mit .previouselement, nur dass hier das nächste Element verlinkt wird und der Linktext standardmäßig "weiter" lautet, ebenfalls kann mit dem Parameter `loop` signalisiert werden, dass es sich um eine Endlosliste handelt, d.h. Nachfolger vom letzten Element ist das erste Element)

```xml
<bx:recorddata.nextelement [type="link | url | if | id | title"] [encode="html | plain"] [not] [show] [loop]/>      <!-- Link wird erzeugt, Standardtext: weiter-->
<bx:recorddata.nextelement Parameter siehe oben> Linktext </bx:recorddata.nextelement >                             <!-- eigener Linktext kann ausgegeben werden -->
<bx:recorddata.nextelement type="object"><bx:recordfield.Titel/></bx:recorddata.nextelement >
```

#### recorddata.firstelement

**Hinweis:** Dieses Tag kann innerhalb von `recorddata.nav` benutzt werden und von dort alle relvanten Parameter übernehmen.
(fast identisch mit .previouselement, nur dass hier das erste Element verlinkt wird und der Linktext standardmäßig "erster" lautet)

```xml
<bx:recorddata.firstelement [type="link | url | if | id | title"] [encode="html | plain"] [not] [show] />      <!-- Link wird erzeugt, Standardtext: erster-->
<bx:recorddata.nextelement Parameter siehe oben> Linktext </bx:recorddata.nextelement >                        <!-- eigener Linktext kann ausgegeben werden -->
<bx:recorddata.nextelement type="object"><bx:recordfield.Titel/></bx:recorddata.nextelement >
```

#### recorddata.lastelement

**Hinweis:** Dieses Tag kann innerhalb von `recorddata.nav` benutzt werden und von dort alle relvanten Parameter übernehmen.
(identisch mit .previouselement, nur dass hier das letzte Element verlinkt wird und der Linktext standardmäßig "letzter" lautet)

```xml
<bx:recorddata.firstelement [type="link | url | if | id | title"] [encode="html | plain"] [not] [show] />      <!-- Link wird erzeugt, Standardtext: letzter-->
<bx:recorddata.nextelement Parameter siehe oben> Linktext </bx:recorddata.nextelement >                        <!-- eigener Linktext kann ausgegeben werden -->
<bx:recorddata.nextelement type="object"><bx:recordfield.Titel/></bx:recorddata.nextelement >
```

### Ausgabe von aktuellen Parametern und Positionen (oder wie könnte man das nennen???)

#### recorddata.total

**Hinweis:** Dieses Tag kann innerhalb von `recorddata.nav` benutzt werden und von dort alle relvanten Parameter übernehmen.

```xml
<bx:recorddata.total/>
```

Gibt die gesamte Anzahl an Datensätzen aus.

#### recorddata.startindex

**Hinweis:** Dieses Tag kann innerhalb von `recorddata.nav` benutzt werden und von dort alle relvanten Parameter übernehmen.

```xml
<bx:recorddata.startindex/>
```

gibt die Nummer des ersten Datensatzes aus, der auf der aktuellen Seite angezeigt wird bzw. die Nummer des aktuellen Detaildatensatzes innerhalb der angegebenen Filterung und Sortierung.

#### recorddata.endindex

**Hinweis:** Dieses Tag kann innerhalb von `recorddata.nav` benutzt werden und von dort alle relvanten Parameter übernehmen.

```xml
<bx:recorddata.endindex/>
```

gibt die Nummer des letzten Datensatzes auf der aktuellen Seite aus.

#### recorddata.listindex

**Hinweis:** Dieses Tag kann innerhalb von `recorddata.nav` benutzt werden und von dort alle relvanten Parameter übernehmen.

```xml
<bx:recorddata.listindex max="<n>" />
```

Mit diesem Kommando erhält man die Indexnummer, auf die man bei einem Link zurück zur Übersicht verlinken muss. `max` ist Pflicht.

Wenn z. B. Datensatz 14 angezeigt wird und auf der Listseite 6 Datensätze angezeigt werden, gibt dieses Tag 12 aus.

#### recorddata.currentpage

**Hinweis:** Dieses Tag kann innerhalb von `recorddata.nav` benutzt werden und von dort alle relvanten Parameter übernehmen.

```xml
<bx:recorddata.currentpage/>
```

Dieses Tag gibt die Nummer der aktuellen Seite (beginnend bei 1) aus.

#### recorddata.totalpages

**Hinweis:** Dieses Tag kann innerhalb von `recorddata.nav` benutzt werden und von dort alle relvanten Parameter übernehmen.

```xml
<bx:recorddata.totalpages/>
```

Dieses Tag gibt die Anzahl der Anzeigeseiten aus.

### recorddata.navlist / recorddata.navdetail

```xml
<bx:recorddata.navlist [max="<n>"] [boundary="<text>"] />
<bx:recorddata.navlist [max="<n>"] [boundary="<text>"]> ... </bx:recorddata.navlist>
<bx:recorddata.navdetail [max="<n>"] [boundary="<text>"] />
<bx:recorddata.navdetail [max="<n>"] [boundary="<text>"]> ... </bx:recorddata.navdetail>
```

Mittels `.navlist` wird eine verlinkte Liste an benachbarten Seiten (`.navlist`) bzw. Detailseiten (`.navdetail`) ausgegeben.

| max | Wenn<br>`max`<br>nicht angegeben wird oder "0" ist, werden alle Seiten angezeigt |
| --- | --- |
| boundary | legt das Trennzeichen zwischen den Zahlen fest (Standard: " \| ") |

**Beispiel:** Eine Liste besteht aus 23 Datensätzen und füllt wegen `max="3"` (Parameter der Containerliste, nicht von `.navlist`) 8 Seiten. Wir befinden uns auf Seite 5 und `max` von `.navlist` ist auf `"2"` gesetzt. Folgendes wird ausgegeben (mit entsprechender Verlinkung): <a href="http://wiki.batix.net/index.php/Bx:recorddata#recorddata.navlist_.2F_recorddata.navdetail" target="_blank">3</a> | <a href="http://wiki.batix.net/index.php/Bx:recorddata#recorddata.navlist_.2F_recorddata.navdetail" target="_blank">4</a> | 5 | <a href="http://wiki.batix.net/index.php/Bx:recorddata#recorddata.navlist_.2F_recorddata.navdetail" target="_blank">6</a> | <a href="http://wiki.batix.net/index.php/Bx:recorddata#recorddata.navlist_.2F_recorddata.navdetail" target="_blank">7</a>

Um die Verlinkung individueller zu gestalten verwenden Sie die zweite Form dieses Tags. Der Inhalt wird dann für jede anzuzeigende Seite ausgegeben. Sie können eine Reihe von Unterelementen einbinden:

#### recorddata.navlistpage / recorddata.navdetailpage

```xml
<bx:recorddata.navlistpage/>
<bx:recorddata.navdetailpage/>
```

gibt die Nummer der Seite bzw. Detailseite aus

#### recorddata.navlistindex

```xml
<bx:recorddata.navlistindex/>
```

gibt die Indexnummer zurück, die zum Aufruf der im Schleifendurchlauf repräsentierten Seite benötigt wird

#### recorddata.navdetailid

```xml
<bx:recorddata.navdetailid/>
```

gibt die Datensatz-ID zurück, die zum Aufruf der im Schleifendurchlauf repräsentierten Detailseite benötigt wird

#### recorddata.navlistpath / recorddata.navdetailpath

```xml
<bx:recorddata.navlistpath [encoding="html | plain"] />
<bx:recorddata.navdetailpath [encoding="html | plain"] />
```

gibt den Pfad zurück, über den die im Schleifendurchlauf repräsentierte Seite bzw. Detailseite aufgerufen werden kan
Mit `encoding` wird das Ausgabeformat gesteuert. Standard ist `"html"` (Zeichen werden durch &#nnn; ersetzt), wenn Sie normalen Text ausgeben wollen setzen sie `encoding` auf `"plain"`.

#### recorddata.navlistcurrent / recorddata.navdetailcurrent

```xml
<bx:recorddata.navlistcurrent [not]> Inhalt </bx:recorddata.navlistcurrent>
<bx:recorddata.navdetailcurrent [not]> Inhalt </bx:recorddata.navdetailcurrent>
```

führt den Inhalt nur aus, wenn die anzuzeigende Zahl die aktuelle Seite bzw. Detailseite ist. `not` kehrt das Verhalten um.

#### recorddata.navlistfirst / recorddata.navdetailfirst

```xml
<bx:recorddata.navlistfirst [not]> Inhalt </bx:recorddata.navlistfirst>
<bx:recorddata.navdetailfirst [not]> Inhalt </bx:recorddata.navdetailfirst>
```

führt den Inhalt nur aus, wenn die anzuzeigende Zahl die erste Seite bzw. Detailseite ist. `not` kehrt das Verhalten um.

#### recorddata.navlistlast / recorddata.navdetaillast

```xml
<bx:recorddata.navlistlast [not]> Inhalt </bx:recorddata.navlistlast>
<bx:recorddata.navdetaillast [not]> Inhalt </bx:recorddata.navdetaillast>
```

führt den Inhalt nur aus, wenn die anzuzeigende Zahl die letzte Seite bzw Detailseite ist. `not` kehrt das Verhalten um.

### recorddata.navlink

**Hinweis:** Dieses Tag kann innerhalb von `recorddata.nav` benutzt werden und von dort alle relvanten Parameter übernehmen.

```xml
<bx:recorddata.navlink move="<n>" />
<bx:recorddata.navlink move="<n>"> Linktext </bx:recorddata.navlink>
```

Dieses Tag schreibt einen Link zu einer vorhergehenden oder nachfolgenden Seite (falls mehrere Seiten vorhanden sind).

|  |  |
| --- | --- |
| `<n>` | ganze Zahl |

`move` gibt dabei die Schrittweite an (kann auch negativ sein). Falls die erste Form verwendet wird, ist der Linktext standardmäßig "...".

### recorddata.detaillink

**Hinweis:** Dieses Tag kann innerhalb von `recorddata.nav` benutzt werden und von dort alle relvanten Parameter übernehmen.

```xml
<bx:recorddata.detaillink move="{n}" />							<!-- Linktext standardmäßig "..." -->
<bx:recorddata.detaillink move="{n}"> Linktext </bx:recorddata.detaillink>
```

Dieses Tag schreibt einen Link zu einem vorhergehenden oder nachfolgenden Datensatz (falls mehrere Dantesätze vorhanden sind).

| move | Schrittweite (kann auch negativ sein) |
| --- | --- |

### recorddata.navdetailobject

**Hinweis:** Dieses Tag kann innerhalb von `recorddata.nav` benutzt werden und von dort alle relvanten Parameter übernehmen.

```xml
<bx:recorddata.navdetailobject> ... </bx:recorddata.navdetailobject>
```

repräsentiert den jeweiligen Containerdatensatz. Funktioniert wie `recorddata.nextelement type="object" `(oder die anderen artverwanden Tags)

### Beispiele

**Beispiel 1**

```xml
<bx:recorddata.navdetail max="3">
  <bx:recorddata.navdetailobject><bx:recordfield.Titel/></bx:recorddata.navdetailobject>
</bx:recorddata.navdetail>
```

Die Wirbeltierklassen (Säugetiere, Vögel, Amphibien, Reptilien, Fische) werden ausgegeben und in Klammern die Anzahl der Tiere aus dem Container "Tiere", die mit der jeweiligen Klasse verbunden sind.

## recorddata.meta

```xml
<bx:recorddata.meta (key="{metakey}" | name="{metakey}") [date [pattern="{format}"]] />
```

Gibt den Inhalt eines Metawertes aus.

|  |  |
| --- | --- |
| key \| name | Name einer Metaeigenschaft |
| date | Datum soll angezeigt werden |
| pattern | Datumsformatierung (Standard ist "EEEEEE, d. MMMMMM yyyy") |

## recorddata.katcount

```xml
<bx:recorddata.katcount pool="{liste}" field="<feld>" />
<bx:recorddata.katcount pool="{liste}" field="<feld>"> Text </bx:recorddata>
```

Dieses Tag gibt die Anzahl der Datensätze aus einer Recordliste zurück, welche dort über ein Feld mit dem Datensatz im aktuellen Schleifendurchlauf verknüpft sind. Ebenso kann auch ein Text ausgegeben werden, falls die Anzahl größer als Null ist.

| pool | ID oder Alias des Containers |
| --- | --- |
| field | Name des Feldes (muss vom Typ Einzelverknüpfung sein) |

### Beispiele

**Beispiel 1**

```xml
<bx:containerfilter.Wirbeltierklassen pool="Klassen">
  <bx:recordfield.Titel/> ( <bx:recorddata.katcount pool="Tiere" field="Klasse"/> )<br>
</bx:containerfilter.Wirbeltierklassen >
```

Die Wirbeltierklassen (Säugetiere, Vögel, Amphibien, Reptilien, Fische) werden ausgegeben und in Klammern die Anzahl der Tiere aus dem Container "Tiere", die mit der jeweiligen Klasse verbunden sind.

## recorddata.empty

```xml
<bx:recorddata.empty [object="{name}"] [not] > Inhalt </bx:recorddata.empty>
```

Der Inhalt wird nur ausgeführt, wenn in der Schleife keine Datensätze zum Anzeigen vorhanden sind.
Wenn das Tag nicht innerhalb von `<bx:recorddata.nav>` verwendet wird müssen der Parameter `object` mit dem Namen der zugehörigen Containerschleife und evtl. auch der Parameter `label` mit angegeben werden. *ab Version 2.5.6*

| object | Name der Containerschleife |
| --- | --- |
| not | kehr die Funktion um |

### Beispiele

**Beispiel 1**

```xml
<bx:recorddata.empty object="Newsliste">z. Z. keine Newsbeiträge vorhanden</bx:recorddata.empty>
<bx:recorddata.empty object="Newsliste" not><bx:recorddata.total/> News vorhanden:</bx:recorddata.empty>

oder

<bx:recorddata.nav object="Newsliste">
  <bx:recorddata.empty>z. Z. keine Newsbeiträge vorhanden</bx:recorddata.empty>
  <bx:recorddata.empty not><bx:recorddata.total/> News vorhanden:</bx:recorddata.empty>
<bx:recorddata.nav>
```

**Beispiel 2**

```xml
<bx:containerfilter.Suche_Tier pool="Tiere">
  ...
</bx:containerfilter.Suche_Tier>

<bx:recorddata.empty object="Suche_Tier">
  Leider wurde kein Tier mit dem gesuchten Begriff gefunden.
</bx:recorddata.empty>
```

# bx:recordfield

Das Tag `recordfield` stellt ein einzelnes Element eines Container-Datensatzes dar. Dies kann ein simpler Typ wie z.B. Text, Datum oder Bild, aber auch eine Schleife über Untercontainer sein.

## Allgemeine Syntax

```xml
<bx:recordfield.{field} [parent | parent="{n}"] [baseloop="{schleifenname}"] [level=".."] zusätzliche Parameter />
<bx:recordfield.{field} [parent | parent="{n}"] [baseloop="{schleifenname}"] [level=".."] zusätzliche Parameter [dummy]> Inhalt </bx:recordfield.{field}>
```

Je nach Feld-Typ stellt sich bx:recordfield unterschiedlich dar und akzeptiert verschiedene Parameter.

| field | Name des Feldes im Container |
| --- | --- |
| level | level=".." - übergeordneter Container<br>Zugriff auf die Felder des übergeordneten Containers (zur Zeit nur direkt-übergeordnet möglich)<br>sollte nicht mehr verwendet werden, lieber<br>`parent` |
| baseloop | Name der Containerschleife (wie er nach dem Punkt im Tag steht)<br>Bezug auf eine bestimmte Containerschleife (z.B. bei Verschachtelungen) |
| parent | parent: Zugriff auf direkt übergeordneten Container parent="2": Zugriff auf n-ten übergeordneten Container |
| dummy | bewirkt, daß, wenn noch kein DS verknüpft ist, ein neuer DS erzeugt wird<br>Dazu darf beim Speicher-Action weder ja noch nein bei createnew gewählt sein. |

### Beispiele

```xml
<bx:containerfilter.Kategorie pool="Kategorien" orderby="Titel">
  <h2><bx:recordfield.Titel/></h2>
  <bx:containerfilter.Artikel pool="Artikel" orderby="Titel">
    <a href="detail.htm?artikel=<bx:recorddata.id/>&amp;kat=<bx:recorddata.id baseloop="Kategorie"/>"><bx:recordfield.Titel/></a>
  </bx:containerfilter.Artikel>
  <br>
</bx:containerfilter.Artikel>
```

Linkaufruf mit Übergabe der Kategorie in der inneren Schleife. Zugriff auf die Kategorie-ID mit `baseloop`.

```xml
<bx:containerfilter.Anbieter pool="Anbieter" orderby="Titel">
  <h2><bx:recordfield.Titel/></h2>
  <bx:containerfilter.Kategorie pool="Kategorien" orderby="Titel">
    <h2><bx:recordfield.Titel/></h2>
    <bx:containerfilter.Artikel pool="Artikel" orderby="Titel">
      <a href="detail.htm?artikel=<bx:recorddata.id/>&amp;kat=<bx:recorddata.id parent="1"/>&amp;anbieter=<bx:recorddata.id parent="2"/>"><bx:recordfield.Titel/></a>
    </bx:containerfilter.Artikel>
    <br>
  </bx:containerfilter.Artikel>
</bx:containerfilter.Anbieter>
```

Ähnliches Beispiel wie oben mit zusätzlicher Ebene. Zugriff auf die Kategorie-ID und die Anbeiter-ID mit `parent`.

## Filter

```xml
<bx:recordfield.{field} [filter="{name}" | dynamicfilter="{feldname}"] [quiet] .../>
```

Bei einfachen Typen (Text, Datum, Zahl, Wahrheitswert) lassen sich auch JSP-Filter einsetzen.
Die Schnittstelle zum Filter bildet das Request-Attribut "attrValue". Über dieses wird dem Filter der Inhalt des Tags übergeben und aus diesem wird nach dem Filteraufruf auch der neue Tag-Inhalt gelesen.

| filter | Angabe eines Filters (direkt über JSP-Baustein) |
| --- | --- |
| dynamicfilter | Angabe eines Feldes im Datensatz, wo der Name des Filters drin steht (dynamisch) |
| quiet | Fehler werden nicht auf der Seite ausgegeben |

<span style="color: rgb(255,0,0);">
</span>

### Beispiele für Filter

**Filtername im Feld**

```xml
...
Preis ohne MWSt.: <bx:recordfield.Preis_netto/>
Preis incl. MWSt: <bx:recordfield.Preis_netto filter="Bruttopreis"/>
...
```

Innerhalb des Filters "Bruttopreis" wird der (Netto)Preis in Bruttopreis umgerechnet und anstelle des Wertes im Recordfield ausgegeben.

**Filtername aus Container**

```xml
...
Preis ohne MWSt.: <bx:recordfield.Preis_netto/>
Preis incl. MWSt: <bx:recordfield.Preis_netto dynamicfilter="Filter"/>
...
```

Gleiches Beispiel wie oben, nur daß der Filtername (also Bruttopreis) im Feld "Filter" steht und von dort genommen wird. Vorteil: es kann pro DS ein völlig anderer Filter bestimmt werden.

## einzeiliger Text

```xml
<bx:recordfield.{field} [encode|type="(quoted-printable | javascript | url | plain | csvfield)"] [maxwords="{n}"] [maxchars="{n}" [ellipsis]]  />
```

Je nach Feld-Typ stellt sich bx:recordfield unterschiedlich dar und akzeptiert verschiedene Parameter.

| encode \| type | Der Text wird (falls gewünscht umgewandelt) ausgegeben.** Standard: [htmlencode](/books/cms-handbuch-entwickler/page/bx-tools) quoted-printable:** das Format in einer Email, siehe entsprechenden Wikipedia-Eintrag **javascript:** Den Zeichen "\n \r \t " ' \" wird ein Backslash vorangestellt. **url:** <span style="color: rgb(0,0,0);">zum Kodieren von Request-Parametern</span>. Es wird <a href="http://java.net" target="_blank">java.net</a>.URLEncoder benutzt. **urlpath:** <span style="color: rgb(0,0,0);">zum Kodieren von Pfadbestandteilen (z. B. Dateiname)</span> **plain:** unformatierter Text **csvfield:** (ab v2.5.9) der Text wird mit " umgeben und allen " im Text wird ein zusätzliches " vorangestellt |
| --- | --- |
| maxwords | nur eine bestimmte Anzahl an Wörtern ausgeben |
| maxchars | nur bestimmte Anzahl Buchstaben ausgeben |
| ellipsis | ohne Parameter: fügt "..." an den text an, wenn dieser abgeschnitten wurde.<br>ellipsis=" usw." (mit Parameterwert) fügt usw. an den Text an oder halt irgendwas anderes sinnvolles. |

### Feldinhalt vergleichen

```xml
<bx:recordfield.{field} matches="{regex}" [not]> Inhalt </bx:recordfield.{field}>
<bx:recordfield.{field} equals="{Vergleichs-Feldinhalt}" [not]> Inhalt </bx:recordfield.{field}>
<bx:recordfield.{field} contains="{Suchbegriff im Feld}" [not]> Inhalt </bx:recordfield.{field}>
```

Der Inhalt des Tags wird nur dann angezeigt, wenn der Inhalt des Container-Feldes mit den Testkriterien übereinstimmt (umkehrbar mit `not`).

| matches | Regulärer Ausdruck<br>auf "leer" prüfen:<br>`matches="^$"(Achtung: es wird immer der gesamte String verglichen, "^" vor und "$" nach dem Ausdruck sind also implizit!)` |
| --- | --- |
| equals | String, der mit dem Feldinhalt übereinstimmen muß |
| contains | String, der im Feldinhalt enthalten sein muß |

### Beispiele

```xml
<bx:recordfield.Email matches="^[_a-zA-Z0-9-](\.{0,1}[_a-zA-Z0-9-])*@([_a-zA-Z0-9-]{2,}\.){0,}[_a-zA-Z0-9-]{3,}(\.[_a-zA-Z]{2,4}){1,2}$" not> keine gültige E-Mail-Adresse </bx:recordfield.Email>
```

**Achtung:** `matches` funktioniert nicht oder nicht korrekt wenn RegEx-Sonderzeichen wie Klammern, „+“ „?“, „*“ im Request stehen
Mit equals funktioniert es dann:

```xml
<selected>
  <option value="bx:recorddata.id/>"<bx:recordfield.Kategoriename equals="request:param"> selected</bx:recordfield.Kategoriename>><bx:recordfield.Kategoriename/></option>
</selected>
```

Innerhalb einer Schleife: wenn übergebener Wert des Parameters `param` mit dem Kategorienamen übereinstimmt, wird dieser DS vorausgewählt.

```xml
<bx:recordfield.Email contains="batix.com">class="intern"</bx:recordfield.Email>
```

Jedem Link, der den String "<a href="http://batix.com" target="_blank">batix.com</a>" enthält, wird die Klasse "intern" zugewiesen (um ihn z.B. auf <a href="http://www.batix.com" target="_blank">www.batix.com</a> von externen Links zu unterscheiden)

## mehrzeiliger Text

```xml
<bx:recordfield.{field} [encode="(quoted-printable | javascript | csv | plain | csvfield)"] [maxwords="{n}"] [maxchars="{n}" [ellipsis]] />
```

| csv |  |
| --- | --- |
| encode \| type | Der Text wird (falls gewünscht umgewandelt) ausgegeben.** Standard: [htmlencode](/books/cms-handbuch-entwickler/page/bx-tools) quoted-printable:** das Format in einer Email, siehe entsprechenden Wikipedia-Eintrag **javascript:** Den Zeichen "\n \r \t " ' \" wird ein Backslash vorangestellt. **csv:** alle Zeilenumbrüche durch Leerzeichen ersetzt und sonstige Steuerzeichen entfernt. **plain:** unformatierter Text **csvfield:** (ab v2.5.9) der Text wird mit " umgeben und allen " im Text wird ein zusätzliches " vorangestellt url: gibt es für dieses Tag nicht, man kann bx:tools.urlencode drumrum machen **htmltext:** zeigt plain-Feld in Verwaltung aber macht <br>s im Frontend rein |
| maxwords | nur eine bestimmte Anzahl an Wörtern ausgeben |
| maxchars | nur bestimmte Anzahl Buchstaben ausgeben |
| ellipsis | ohne Parameter: fügt "..." an den text an, wenn dieser abgeschnitten wurde.<br>ellipsis=" usw." (mit Parameterwert) fügt usw. an den Text an oder halt irgendwas anderes sinnvolles. |

<span style="color: rgb(255,0,0);">
</span>

### Beispiele

```xml
<bx:recordfield.Titel/>
<bx:recordfield.Text maxwords="20" ellipsis />
<a href="detail.htm?beitragsid=<bx:recorddata.id/>">mehr</a>
```

Anteasern in einer Liste: es sollen max. 20 Wörter ausgegeben werden, dann wird ein ... gesetzt.

## Datum/Zeit

```xml
<bx:recordfield.{field} [locale="{lang}"] [pattern="{format}"] [year="{mod}"] [month="{mod}"] [day="{mod}"] [hour="{mod}"] [minute="{mod}"] [second="{mod}"] [type="holiday"]/>
```

| locale | Sprachformatierung (z.B. "de" oder "en_US")<br>`locale` sollte immer angegeben werden, da sonst die Standardeinstellung vom Server genutzt wird, die sich aber nach Updates oder Umzügen ändern kann. |
| --- | --- |
| pattern | Formatierung des Datums (Standard für Datum / Datum+Zeit / Zeit ist "EEEEEE, d. MMMMMM yyyy" / "dd.MM.yyyy HH:mm" / "HH:mm") |
| year month day minute second | Datum direkt setzen oder das aktuelle Datum manipulieren folgende Angaben bei `{mod}`: **n:** das entsprechende Feld wird auf den Wert n gesetzt **+n:** das entsprechende Feld wird um den Wert n erhöht **-n:** das entsprechende Feld wird um den Wert n verringert **Achtung:** Monate laufen von 0-11 |
| type="holiday" | prüft, ob der Tag auf einen Feiertag fällt und schreibt statt des Datums die Feiertagsbezeichnung hin (z. B. Silvester)(ab V2.6.0)(Thüringer Feiertage) |

### Beispiele

```xml
<bx:recordfield.Datumsfeld day="15" month="+1" /> 
```

zeigt anstatt des gespeicherten Datums den 15. des folgenden Monats an.

### Abfrage

```xml
<bx:recordfield.{field} if="( past | future | empty | today)" [not] > Inhalt </bx:recordfield.{field}>
```

Mittels dieser Variante wird *Inhalt* nur ausgegeben wenn das Datum im Datensatz (inklusive eventueller Modifikationen) in der Vergangenheit liegt (`past`), in der Zukunft liegt (`future`) oder leer ist (`empty`). `not` kehrt die Bedingung um.

### Beispiele

```xml
<bx:clipboard.cut name="aktJahr"><bx:tools.datum pattern="yyyy"/></bx:clipboard.cut>
<bx:recordfield.Geburtsdatum year="clipboard:aktJahr" if="today"> Herzlichen Glückwunsch zum Geburtstag! </bx:recordfield.Geburtsdatum >
```

Das Feld Geburtsdatum wird mit dem heutigen Datum verglichen. Da das Jahr ja nicht stimmt, wird es auf das aktuelle Jahr gesetzt und kann nun verglichen werden.

### Datumsmanipulation

```xml
<bx:recordfield.{field} weekday="{angabe}"/>
```

<span style="color: rgb(71,71,71);text-decoration: none;">mo", "di", "mi", "do", "fr", "sa", "so" oder "mon", "tue", "wed", "thu", "fri", "sat", "sun" wechselt auf den entsprechenden Wochentag, der Woche in dem das Calendar-Objekt ist.</span>
<span style="color: rgb(71,71,71);text-decoration: none;">vorangestelltes Plus- oder Minuszeichen wechslet zum folgenden bzw. vorigen entsprechenden Wochentag. Wenn calendar bereits auf dem gleichen Wochentag steht, wird nichts geändert. Dieser Fall wird mit doppelten plus/minus anders behandelt. Dann wird nämlich +/-7 Tage gerechnet.</span>

Vom gespeicherten Wert aus können folgende Werte ermittelt werden:

| weekday | Do = der Donnerstag dieser Woche (egal ob schon vergangen oder nicht) +Do = der nächste Donnerstag (heute, falls heute Donnerstag) -Do = der vorige Donnerstag (heute, falls heute Donnerstag) ++Do bzw --Do = der nächste/vorige Donnerstag (nie heute) |
| --- | --- |

## Zahl/Preis

### Formatierte Ausgabe

```xml
<bx:recordfield.{field} [locale="{lang}"] [pattern="{format}"] [gs="{c}"] [ds="{c}"] />
<bx:recordfield.{field} isempty [not]> Inhalt </bx:recordfield.{field}>
```

| locale | Sprachformatierung (z.B. "de" oder "en_US") |
| --- | --- |
| pattern | Formatierung festlegen, (Standard bei Zahl: "0.#####", bei Preis: "0.00", bei Preis mit Tausenderpunkt: "#,##0.00") |
| gs | Tausender-Trennzeichen festlegen |
| ds | Dezimal-Trennzeichen festlegen |
| isempty | Abfrage, ob das Feld leer ist |

### Abfrage des Betrages

```xml
<bx:recordfield.{field} equals="{n}" [not]> Inhalt </bx:recordfield.{field}>
<bx:recordfield.{field} equals="{n}" [true="{text}"] [false="{text}"] />
```

(Ausgabe von Quelltext abhängig vom Zahlenwert)

| equals | Vergleich des Feldinhalts mit einem Wert. Ausgabe bei Übereinstimmung |
| --- | --- |
| true, false | eingetragener Text wird bei Übereinstimmung bzw. Nicht-Übereinstimmung ausgegeben. |

```xml
<bx:recordfield.{field} {gt | gte | lt | lte}="{n}"> Inhalt </bx:recordfield.{field}>
```

Zahl mit einem Wert vergleichen. Ausgabe bei Übereinstimmung.
Ab *Version 2.5.7* kann anstatt der festen Vergleichszahl für ` {n}` auch "`request:{Parametername}`", "`attribute:{Attributname}`" oder "`clipboard:{Name}`" verwendet werden.

| gt<br>gte<br>lt<br>lte | größer größer gleich kleiner kleiner gleich |
| --- | --- |

### Alternativwert

```xml
<bx:recordfield.Preis alt="0" pattern="0.00"/>
<bx:recordfield.Anzahl alt="-1" lte="0">Anzahl fehlt oder ist 0</bx:recordfield.Anzahl>
```

Ab *Version 2.5.8* kann der Parameter `alt` verwendet werden um einen Alternativwert zu verwenden, falls keine Zahl gespeichert ist (auch keine 0).

```xml
<bx:recordfield.Preis alttext="gratis" pattern="0.00"/>
```

Ab *Version 2.5.8* kann der Parameter `alttext` verwendet werden um einen Alternativtext anzuzeigen, falls keine Zahl gespeichert ist (auch keine 0).

Dies kann z. B. auch für Intranet-Eingabeseiten verwendet werden, um zu markieren wo Zahlenwerte leer sind.

## Wahrheitswert

```xml
<bx:recordfield.{field}> Inhalt </bx:recordfield.{field}>				<!-- Ausgabe, wenn Feld im Container angehakt ist -->
<bx:recordfield.{field} not> Inhalt </bx:recordfield.{field}>			<!-- Ausgabe, wenn Feld im Container NICHT angehakt ist -->
<bx:recordfield.{field} empty> Inhalt </bx:recordfield.{field}>         <!-- Ausgabe, wenn Feld im Container "nicht gewählt" ist -->
<bx:recordfield.{field} not empty> Inhalt </bx:recordfield.{field}>     <!-- Ausgabe, wenn Feld nicht "nicht gewählt", also entweder ja oder nein ist -->
```

Zusätzlich zu den beiden Statussen "j" und "n" also true und false, gibt es noch den Status "empty". Diesen Status hat das Feld, wenn es noch nie ausgewählt wurde (im Backend wurde beim Speichern des DS keine Feld mit dem entsprechenden Namen übergeben) oder wenn im Container direkt dieser Status ausgewählt wurde (siehe Bild "Datenansicht").

Ob dieser Status "nicht gewählt" erlaubt ist, kann in der Containerdefinition festgelegt werden. Dort kann auch ein Wert den entsprechenden Statussen zugewiesen werden (Felder "angezeigter Text...".

|  |  |
| --- | --- |
| Definitionsansicht:  ![image2015-7-21 12:54:54.png](attachments/2392328/3932441.png) | Datenansicht:  ![image2015-7-21 12:51:38.png](attachments/2392328/3932440.png) |

| not | Ausgabe, wenn das Feld nicht angehakt wurde (ohne: Ausgabe, wenn das Feld angehakt wurde)<br>veraltet für<br>`not`<br>: invert und else |
| --- | --- |
| empty | Ausgabe, wenn Status "nicht gewählt" zutriffe (Erklärung siehe Text oben) |

### Beispiele

```xml
<bx:recordfield.Infomaterial_gewuenscht empty>
  <input type="radio" name="Infomaterial_gewuenscht" value="j"> Infomaterial gewünscht
  <input type="radio" name="Infomaterial_gewuenscht" value="n"> kein Infomaterial gewünscht
</bx:recordfield.Infomaterial_gewuenscht>

<bx:recordfield.Infomaterial_gewuenscht not empty>
  Du hast dich bereits entschieden.
</bx:recordfield.Infomaterial_gewuenscht>

```

Das Feld "Infomaterial_gewuenscht" kann nur einmal ausgewählt werden und dann nie wieder.

```xml
<bx:recordfield.Häkchenfeld show="( real | config )" />	  <!-- Ausgabe der in der Verwaltung gespeicherten Einstellungen -->
<bx:recordfield.{field} show="config" [true="{text}"] [false="{text}"] [empty="{text}"] />  <!-- direkt im Tag angegebene Werte überschreiben die Einstellung -->

```

Eine Ausgabe entspechend des gespeicherten Statuses erfolgt.

| true | Text, der ausgegeben wird, wenn das Feld angehakt wurde |
| --- | --- |
| false | Text, der ausgegeben wird, wenn das Feld nicht angehakt wurde |
| empty | Text, der ausgegeben wird, wenn das Feld den Status "nicht ausgewählt" hat (Erklärung siehe oben) |
| show | ab V 2.6.2 real: gibt den wirklich gespeicherten Wert (z.B. "j", "n", "1", "0") aus config: gibt den in der Verwaltung konfigurierten Wert aus (Standard: "wahr", "falsch") |

Bisher gab es noch keine Option um zu sagen „nicht angehakt oder leer“ bzw. „angehakt oder leer“.

```xml
<bx:recordfield.{häkchenfeld} [not empty] alt="{true|false}">...</bx:recordfield.{häkchenfeld}>
```

|  | `<bx:rf>` | `<bx:rf not>` | `<bx:rf empty>` | `<bx:rf not empty>` | `<bx:rf not alt="..">` | `<bx:rf alt="..">` |
| --- | --- | --- | --- | --- | --- | --- |
| angehakt | angezeigt |  |  | angezeigt |  | angezeigt |
| nicht angehakt |  | angezeigt |  | angezeigt | angezeigt |  |
| leer |  |  | angezeigt |  | angezeigt (wenn alt="false") | angezeigt (wenn alt="true") |

| einen der drei Werte abfragen | Gegenteil(die beiden anderen Möglichkeiten) |
| --- | --- |
| `<bx:recordfield.häkchen>`<br>zeigt Block an, wenn das Feld angehakt ist | `<bx:recordfield.häkchen not alt="false">`<br>zeigt Block an, wenn das Feld nicht angehakt oder leer ist |
| `<bx:recordfield.häkchen not>`<br>zeigt Block an, wenn das Feld als nicht angehakt gespeichert ist | `<bx:recordfield.häkchen alt="true">`<br>zeigt Block an, wenn das Feld angehakt oder leer ist |
| `<bx:recordfield.häkchen empty>` zeigt Block an, wenn das Feld leer ist | `<bx:recordfield.häkchen not empty>` zeigt Block an, wenn das Feld als angehakt oder nicht angehakt gespeichert ist |

### Beispiele

```xml
...
Infomaterial gewünscht? <bx:recordfield.Infomaterial_gewuenscht true="ja" false="nein" empty="noch nicht entschieden" />
...
xml
<div id='status' style='background-color:<bx:recordfield.aktiviert true="green" false="red"/>;'>...</div>
```

## Bild

```xml
<bx:recordfield.{field} [width="{n}"] [height="{n}"] [nogifshrink] [cover]/>
```

Es wird das Bild (also ein <img> Tag) ausgegeben, ggf. verkleinert, wenn gewünscht.

| width | Angabe der max. Breite (abhängig von der Höhe) |
| --- | --- |
| height | Angabe der max. Höhe (abhängig von der Breite) |
| nogifshrink | keine Verkleinerung von GIF-Dateien |
| cover | (ab V 2.6.3, ansonsten bei 2.6.2 reinkopieren)<br>Bild wird nur soweit verkleinert, daß es das angegebene Element ganz ausfüllt (siehe Beispiel 2) |
| cover="crop" | Originalbild wird abgeschnitten und auch so gespeichert |

<span style="color: rgb(255,0,0);">
</span>

### Beispiele

**Beispiel 1**

```xml
<div style="width:150px;height:150px;border:1px solid black;">
  <img src="<bx:recordfield.Bild width="150" height="150" type="path"/>" alt="">
</div>
```

Bild wird in den genannten Dimensionen ausgegeben. Es wird entweder auf die Breite oder Höhe verkleinert.

**Beispiel 2**

```xml
css:
.qimg{
  width:150px;
  height:150px;
  overflow:hidden;
  border:1px solid black;
  background-position:center;
  }
______________________

<div class="qimg" style="background-image:url('<bx:recordfield.Bild width="150" height="150" cover type="path"/>');">
  <img src="" alt="">
</div>
```

Bild wird deckend in den genannten Dimensionen ausgegeben. Es wird entweder in der Breite (bei Querformt) oder in der Höhe (bei Hochformat) beschnitten.

Unterschied: siehe Bild, halbtransparente Bildteile werden durch css abgeschnitten

![beispiel-cover.jpg](attachments/2392328/3211265.jpg)

### Bild-Daten ausgeben

```xml
<bx:recordfield.{field} type="(path | url | title | alt | author | empty | id | inline)" [not] />
```

| type | statt des eigentlichen Bildes kann folgendes ausgegeben werden: **path:** relativer Pfad **url:** komplette URL **title, name:** Titel des Bildes (Metadaten, Eingabe unter "Grafiken") **originalname**: Originaldateiname vom Upload **licence:** Lizenzangabe **description:** Beschreibung des Bildes **alt:** Alternativtext des Bildes (Metadaten, Eingabe unter "Grafiken") **author:** Autor des Bildes (Metadaten, Eingabe unter "Grafiken") **empty:** Abfrage, ob Feld leer ist (ab v 2.6.2) **id:** ID in der Bildergalerie (ab v 2.6.2) **inline:** erzeugt img-Tag mit Binärdaten in src (ab 2.6.1), sinnvoll bei Newsletter, da steht das Bild direkt in der Seite, also nicht als Link oder Anhang **base64data:** Tagerweiterung für vcf (Outlook-Visitenkarte, siehe Beispiel 2) mit Foto ab v2.6.6 |
| --- | --- |
| not | in Verbindung mit empty, kehrt die Abfrage um |

### Beispiele

```xml
<bx:recordfield.Bild type="empty" not>
  <div style="background-image:url('<bx:recordfield.Bild type="path"/>');" title="<bx:recordfield.Bild type="path"/>"> Inhalt </div>
</bx:recordfield.Bild>
```

Anzeige als Hintergrundbild, aber nur, wenn auch ein Bild vorhanden ist.

```xml
<bx:record.Visitenkarte pool="Ansprechpartner" id="request:editID">
BEGIN:VCARD
VERSION:2.1
N:<bx:recordfield.Name/>;<bx:if><bx:recordfield.Titel/> </bx:if><bx:recordfield.Vorname/>;;;
FN:<bx:if><bx:recordfield.Titel/> </bx:if><bx:recordfield.Vorname/> <bx:recordfield.Name/>
<bx:if>PHOTO;<bx:recordfield.Bild type="base64data" pattern="TYPE=$type;ENCODING=BASE64:\n$data\n" width="200" height="200"/></bx:if>
ORG:<bx:recordfield.Unternehmen><bx:recordfield.Titel/></bx:recordfield.Unternehmen>;
<bx:if>TITLE: <bx:recordfield.Taetigkeit/></bx:if>
NOTE;ENCODING=QUOTED-PRINTABLE: <bx:recordfield.Beschreibung type="plain"/>
contact=0D=0A
TEL;WORK;VOICE:<bx:recordfield.Telefon/>
<bx:if>TEL;HOME;VOICE:</bx:if>
<bx:if>TEL;CELL;VOICE:<bx:recordfield.Mobil/></bx:if>
<bx:if>TEL;WORK;FAX:<bx:recordfield.Fax/></bx:if>
ADR;WORK:;;<bx:recordfield.Straße/>;<bx:recordfield.Ort/>;<bx:recordfield.PLZ/>;;
LABEL;WORK;ENCODING=QUOTED-PRINTABLE:<bx:recordfield.Straße/>=0D=0A<bx:recordfield.Ort/>, <bx:recordfield.PLZ/> =0D=0A
<bx:if>URL:<WWLINK TYPE="GENERIC" VALUE="<bx:recordfield.Internet/>"><bx:recordfield.Internet/></WWLINK></bx:if>
EMAIL;PREF;INTERNET:<bx:recordfield.Email/>
REV:
END:VCARD
</bx:record.Visitenkarte>
```

Erzeugung einer Visitenkarte für Outlook

### Bild-Größenangaben ausgeben

```xml
<bx:recordfield.{field} type="(origwidth | origheight | calcwidth | calcheight)" />
```

Hier werden nur die Größen als Zahl ausgegeben (z.B.: für Javascript-Popups um die Größe zu übergeben).

| origwidth | Ausgabe der Originalbreite |
| --- | --- |
| origheight | Ausgabe der Originalhöhe |
| calcwidth | Ausgabe der (berechneten) Endbreite |
| calcheight | Ausgabe der (berechneten) Endhöhe |

## Dokument

```xml
<bx:recordfield.{field} [type="(link | path | url | id | name | size | description | meta)"] [name="{meta}"] [disposition="attachment|inline|none"]/> 
<bx:recordfield.{field} [type="link"]> Inhalt </bx:recordfield.{field}>
```

Falls `type` nicht angegeben wurde, wird der Standardwert `link` verwendet.

| type | link: erzeugt einen klickbaren Link auf das Dokument (falls Inhalt angegeben, wird dieser als Linktext verwendet) path: gibt den relativen Pfad url: gibt die komplette URL aus id: gibt die ID aus name: gibt den Namen aus size: gibt die Dateigröße aus,  description: gibt die Beschreibung aus meta: Metadatenabfrage, Name des Meta-Feldes wird mit `name` übergeben (siehe unten) empty: (ab V 2.6.2) Abfrage, ob Feld leer ist |
| --- | --- |
| name | (nur in Verbindung mit `type="meta")` Name der Meta-Eigenschaft |
| unit | (nur in Verbindung mit `type="size") `auto: wählt automatisch die entsprechende Einheit, je nach Größe der Datei b: Angabe in Byte kb: Angabe in Kilobyte mb: Angabe in Megabyte |
| pattern | (nur in Verbindung mit<br>`type="size")`<br>Formatierung der Zahl (Standardwert ist "#,##0") |
| locale | (nur in Verbindung mit<br>`type="size")`<br>Sprachen-Formatierung der Zahl (standardmäßig "de_DE") |
| disposition | siehe Beispiele |

### Beispiele

```xml
<bx:recordfield.Dokument disposition="inline"/>

```

Ausgabe: `http://domain/files/{Batix-ID}/{Dateiname}
`setzt content-disposition:inline; filename=“{Dateiname}“, wird als Standard genommen, wenn nichts angegeben wird

```xml
<bx:recordfield.Dokument disposition="attachment"/>
```

Ausgabe:`http://domain/files/download/{Batix-ID}/{Dateiname} `
bewirkt bei PDFs einen Zwangsdownload anstatt eine Anzeige im Browser-Plugin, dasselbe auch durch `http://domain/files/{Batix-ID}/{Dateiname}?dl=true`

```xml
<bx:recordfield.Dokument disposition="none"/>

```

Ausgabe: `http://domain/files/media/{Batix-ID}/{Dateiname}
`bewirkt bei MP4-Videos, die in Apple-Mobilgeräten abgespielt werden sollen, daß das funktioniert, weil der Header nicht geschrieben wird (scheint nur Apple-Geräte zu betreffen)

## Pixelkoordinaten

```xml
<bx:recordfield.{field} type="(x | y) [multiply="{n}"] [add="{n}"] [alt="{n}"] />
```

| type | Je nach<br>`type`<br>wird entweder die x- oder die y-Koordinate ausgegeben |
| --- | --- |
| multiply | Angabe zum Multiplizieren des Koordinatenwertes (bei Kartenvergrößerund bzw. -verkleinerung) |
| add | Wert, der zum Koordinatenwerte dazuaddiert werden kann |
| alt | Alternativwert, der ausgegeben wird, wenn keine Zahl festgelegt ist |

## Einfachverknüpfung

```xml
<bx:recordfield.{field} [chkuser] [show="active|inactive|all"] <not> > Inhalt </bx:recordfield.<field>>
<bx:recordfield.{field} type="id" />
<bx:recordfield.{field}> />
<bx:recordfield.{field} type="if" value="{ID}" <not>> Inhalt </bx:recordfield.<field>>
```

Innerhalb des Tags kann wiederum mittels `bx:recordfield` auf die Elemente der Verknüpfung zugegriffen werden.
Falls kein Vergleich passt, wird der Inhalt nicht ausgegeben. 
Falls kein Inhalt angegeben ist, wird der Titel des Datensatz-Feldes ausgegeben.

| chkuser | ID des Datensatzes mit der User-ID des aktuell eingeloggten Users bzw. mit den IDs seiner Gruppen verglichen. |
| --- | --- |
| type="id" | gibt die ID des Datensatzes aus |
| type="if" | (ab V *2.5.8*) Inhalt des Tags wird nur dann angezeigt, wenn die ID des verknüpften Datensatzes mit der in `value` angegebenen übereinstimmt |
| value | zu prüfenden ID.  Mehrere zu prüfende IDs können durch Leerzeichen oder Kommas getrennt werden. **#null**: "nichts verknüpft" wird abgefragt **#all**: hebt alle Bedingungen auf, zeigt alles an (siehe Beispiel) |
| not | kehrt die Bedingung um |
| show | active: nur aktive DS (Standard) inactive: nur inaktive DS all: aktive und inaktive DS werden angezeigt |

### Beispiele

**Beispiel für den Einsatz von nofilter**

```xml
<bx:clipboard.cut>#all</bx:clipboard.cut>
 <bx:irgendeineBedingung><bx:clipboard.cut>eine Kategorieid</bx:clipboard.cut></bx:irgendeineBedingung>
 <bx:recordfield.Einzelkategorie type="if" value="clipboard:default">...</bx:recordfield.Einzelkategorie>
```

Clipboard wird mit `#all` initialisiert
Clipboard wird mit einer ID gefüllt oder auch nicht
wenn nicht gefüllt, greift das #all und hebt alle Bedingungen auf (`ID` = gibt aus, wenn es diese ID ist, `#null` = gibt aus, wenn nichts verknüpft ist) und gibt bei jedem DS aus

## 

## Mehrfachverknüpfung

```xml
<bx:recordfield.{field} [forceindex="<n>" | indexparam="<param>"] [max="<n>"] [idfield="<param>"] [force = {single | list}] [orderby="<field>"] [desc] [chkuser] [type="quantity"] [show="{active | inactive | all}"]>
 Inhalt 
</bx:recordfield.{field}>

<bx:recordfield.{field} zusätzliche Parameter [boundary="<text>"] [type="ids"] />
```

Hier stellt sich bx:recordfield als Schleife dar, welche für jeden Unter-Datensatz durchlaufen wird.

| forceindex | Stelle, an der die Ausgabe beginnen soll |
| --- | --- |
| indexparam | Parametername, wo die Stelle, an der die Ausgabe beginnen soll, steht |
| max | maximale Anzahl der auszugebenden Datensätze (z.B. max="5") |
| idfield | Parametername, der die ID des Datensatzes enthält (Standard ist der Name des Feldes) |
| force | Ausgabemodus (single oder list) kann erzwungen werden |
| orderby | Feldangabe, nach der die Ausgabe sortiert sein soll (Datum, Name etc.) |
| desc | dreht die Sortierrichtung um |
| chkuser | DS-ID und ID seiner zugeordneten Gruppen wird mit der ID des eingeloggten Users verglichen, dh:<br>Wenn im DS eine Gruppe zugeordnet ist, dann wird der Inhalt ausgegeben |
| type | quantity: Anzahl der verknüpften Datensätze anzuzeigen |
| boundary | Trennzeichen, wenn die Titel aller Elemente ausgegeben werden (Standard ","), sollen nur die IDs ausgegeen werden, muß<br>`type="ids"`<br>angegeben werden (Tag ohne Inhalt) |
| show | auch inaktive anzeigen lassen ab v2.6.6 |

***Erweiterung für neue Container (v2.5.8)* Werte für `type`:**

```xml
<bx:recordfield.{field} type="[ ids | titel | quantity ]" [boundary="{text}"]/>

<bx:recordfield.{field} type="[ if-any | if-none | if-all ]" value="{Liste von IDs}"> ... </bx:recordfield.{field}>

<bx:recordfield.{field} type="[ if-empty | computebody | chkuser ]" [not] [nosv]> Inhalt </bx:recordfield.{field}>
```

| type= | ids | gibt die verknüpften ID's mit Leerzeichen getrennt aus |
| --- | --- | --- |
|  | titel | gibt zur Zeit den Titel aus z. B. "2 verknüpfte Datensätze" (Standard wenn type nicht angegeben und geschlossenes Tag) |
|  | quantity | gibt die Datensatzanzahl aus. "0" wenn keine Datensätze verknüpft |
|  | if-any | gibt den Inhalt aus, wenn ein verknüpfter Datensatz die angegebene ID hat |
|  | if-none | gibt den Inhalt nur aus, wenn keiner der verknüpften Datensätze die angegebene ID hat |
|  | if-all | gibt den Inhalt aus, wenn alle angegebenen IDs im Datensatz verknüpft sind |
|  | if-empty | gibt den Inhalt aus wenn kein Datensatz verknüpft ist<br>not: wenn mindestens 1 Datensatz verknüpft ist |
|  | computebody | gibt eine Schleife für jeden verknüpften Datensatz aus (Standard, wenn type nicht angegeben und offenes Tag)<br>Die Parameter von oben sind noch gültig (force, idfield, max, indexparame, orderby nofilter) |
|  | chkuser | wenn das Feld eine BC-Verknüpfung ist, wird geprüft, ob es mit dem eingeloggten Benutzer/Gruppe übereinstimmt (wie bei if-empty) |
| boundary |  | damit kann man den Trenner angeben, z.B. boundary=","  Standard ist Leerzeichen |
| nosv |  | wenn Admin, der ja in allen Gruppen drin ist, eingeloogt, wird er keiner Gruppe zugewiesen |

## Untercontainer

```xml
<bx:recordfield.{field} [forceindex="{n}" | indexparam="{param}"] [max="{n}"] [idfield="{param}"] [force="{single | list}"] [orderby="{field}"] [desc] [type="empty | quantity"] [show="active|inactive|all"] [not]> Inhalt </bx:recordfield.<field>>

<bx:recordfield.{field} [filterfield="{field}" [filtertype="{n}"] filtervalue="{text}" [filterrequired="{true|false}"] [nofilter]> Inhalt </bx:recordfield.<field>>
```

Dieser Typ ist der Mehrfachverknüpfung ähnlich. Für jeden Datensatz wird der Inhalt des Tags angezeigt. Ab *v2.5.?* gibt es die Möglichkeit einen Filter zu definieren, nach dem die Unterdatensätze gefiltert werden

| forceindex | Stelle, an der die Ausgabe beginnen soll |
| --- | --- |
| indexparam | Parametername, wo die Stelle, an der die Ausgabe beginnen soll, steht |
| max | maximale Anzahl der auszugebenden Datensätze (z.B. max="5") |
| idfield | Parametername, der die ID des Datensatzes enthält (Standard ist der Name des Feldes) |
| force | Ausgabemodus (single oder list) kann erzwungen werden |
| orderby | Feldangabe, nach der die Ausgabe sortiert sein soll (Datum, Name etc.)<br>Sortierung nach Anlegereihenfolge: Angabe des Feldes, das die Parent-ID enthält |
| desc | dreht die Sortierrichtung um |
| nofilter | Filtereigenschaften werden nicht vom übergeordneten Container übernommen (siehe Beispiel unten) |
| filterfield | gibt den Namen des Feldes im Untercontainer an, das durchsucht werden soll |
| filtertype | Vergleichstyp (siehe<br>[Filter](/books/cms-handbuch-entwickler/page/filter)<br>, standardmäßig auf 8 gestellt) |
| filtervalue | Static-Wert oder<br>[Parameter-Werte](/books/cms-handbuch-entwickler/page/parameter-werte) |
| filterrequired | required-Flag für das Filter-Objektsetzen (standardmäßig false) |
| type<br>not | empty: Abfrage, ob der UK leer ist.<br>`not`<br>kehrt die Abfrage um<br>quantity: gibt die Anzahl aus |
| show | active: nur aktive DS (Standard) inactive: nur inaktive DS all: aktive und inaktive DS werden angezeigt |

### Beispiele

**Beispiel für eine Filterung des Untercontainers**

```xml
<bx:recordfield.Sub filterfield="Text" filtertype="1" filtervalue="request:suche">
  <bx:recordfield.Text />
</bx:recordfield.Sub>
```

**Beispiel für den Einsatz von nofilter**

```xml
<bx:containerfilter.Kuecheninhalt pool="Kuecheninhalt">
  ...
  <bx:recordfield.Lebensmittel>
    ..
  </bx:recordfield.Lebensmittel>
  ..
</bx:containerfilter.Kuecheninhalt>
```

Filter für den Container "Kücheninhalt" (alle DS, die im UK "Lebensmittel" das Wort "brot" im Feld "Titel" enthalten).):

```xml
<filter-object>
  <field>Lebensmittel/Titel</field>
  <type>1</type>
  <static-value>brot</static-value>
</filter-object>
```

Verhalten, wenn `nofilter` **nicht gesetzt** ist:

Bei Ausgabe des Recordfield "Lebensmittel" werden nur die DS, die im Titel "brot" enthalten, ausgegeben, da der Filter vom Containerfilter übernommen wurde. `nofilter` verhindert das und alle DS werden ausgegeben.

## Veraltete Tags

Die folgenden Befehle sind veraltet und werden durch bx:recorddata ersetzt.

```xml
<bx:recordfield.parentid />		           <!-- Gibt die ID des übergeordneten Objekes zurück. -->
<bx:recordfield.recordid />                  <!-- Gibt die ID des Feldes aus. -->
<bx:recordfield.rootid />                    <!-- Die ID des zugehörigen Hauptcontainers wird ausgegeben. -->
<bx:recordfield.previous object="<name>" />  <!-- veraltet: stattdessen bx:recorddata.previouslist benutzen -->
<bx:recordfield.next object="<name>" />      <!-- veraltet: stattdessen bx:recorddata.nextlist -->
```

Verweise auf diese Seite:

- <a href="http://docs.batix.info/pages/viewpage.action?pageId=19300461" target="_blank">Container-Filteraction</a>
- <a href="http://docs.batix.info/display/DEVS/bx%3Atablefield" target="_blank">bx:tablefield</a>
- <a href="http://docs.batix.info/pages/viewpage.action?pageId=19300458" target="_blank">Container</a>
- <a href="http://docs.batix.info/pages/viewpage.action?pageId=19300363" target="_blank">bx:recordfield</a>
- <a href="http://docs.batix.info/display/DEVS/Container" target="_blank">Container</a>
- <a href="http://docs.batix.info/pages/viewpage.action?pageId=19300385" target="_blank">bx:tablefield</a>
- <a href="http://docs.batix.info/display/DEVS/Container-Filteraction" target="_blank">Container-Filteraction</a>
- <a href="http://docs.batix.info/display/DEVS/bx%3Arecordfield" target="_blank">bx:recordfield</a>

<p>(8 Verweise)</p>

# bx:relativelink

Das Tag `relativelink` dient zum Erzeugen relativer Links.

## Unterpunkt des aktuellen Hauptmenüpunktes

```xml
<bx:relativelink pattern="?/{pfad}" [href="{datei}]" />
<bx:relativelink pattern="?/{pfad}" [href="{datei}]" [ifempty="showbody | hide"]> Inhalt </bx:relativelink>
```

 Falls der gesuchte Pfad nicht existiert, wird in der ersten Form nichts ausgegeben. In der zweiten Form wird der Taginhalt ausgegeben, dies allerdings nur, wenn `ifempty` auf `"showbody"` gesetzt ist (was der Standard ist). Wenn `ifempty="hide"` angegeben wurde, wird bei Nichtfinden des Pfades auch nichts angezeigt. Um einen klickbaren Link zu erzeugen, muss das Tag einen Inhalt besitzen, dieser wird dann als Linktext übernommen.

| pattern | {pfad} gibt hier einen Menüpfad, ab dem aktuellen Haupmenüpunkt an |
| --- | --- |
| href | Optional kann eine Zieldatei mittels<br>`href`<br>angegeben werden, die an den Pfad angehängt wird. |
| ifempty | showbody: Taginhalt wird ausgegeben (Standard)<br>hide: bei Nichtfinden wird auch nichts angezeigt |

## Hauptmenüpunkt wechseln

```xml
<bx:relativelink pattern="{menü}/*" [href="{datei}]" />
<bx:relativelink pattern="{menü}/*" [href="{datei}]"> Inhalt </bx:relativelink>
```

Um den Hauptmenüpunkt zu wechseln, die tieferliegende Navigation aber intakt zu lassen, wird diese Variante verwendet (z.B. um zwischen Sprachen zu wechseln). Es wird nur der Hauptmenüpunkt des aktuellen Navigationspfades durch `<menü>` ersetzt und geprüft, ob der Zielpfad existiert. Falls dieser nicht gefunden wird, erfolgt die Ausgabe des Tag-Inhalts (falls vorhanden). Über `href` kann eine Zieldatei spezifiziert werden, die an den Pfad angehängt wird. Wenn der Zielpfad schließlich existiert und der Tag-Inhalt angegeben wurde, wird dieser als Linktext für einen klickbaren Link verwendet.

## allgemeiner Link

```xml
<bx:realtivelink pattern="{pfad}" [href="{datei}]" />
<bx:relativelink pattern="{pfad}" [href="{datei}]"> Inhalt </bx:relativelink>
```

`<pfad>` wird bei dieser Variante von der Startseite aus gesehen angegeben (siehe <a href="http://wiki.batix.net/index.php/Bx:relativelink/Beispiele" target="_blank">Beispiel</a>). Falls der Pfad nicht gefunden werden kann, wird ein Fehler ausgegeben. Auch hier kann eine Zieldatei über `href` und optionaler Linktext als Tag-Inhalt angegeben werden.

### Beispiele

**Code:**

```xml
Demo: <bx:relativelink pattern="?/demo"/><br/>
Eintragen: <bx:relativelink href="eintragen.htm" pattern="?/demo">
  Eintragen!</bx:relativelink><br/>
Deutsch: <bx:relativelink pattern="de/*"/><br/>
Englisch: <bx:relativelink pattern="en/*"/><br/>
<br/>
Fehler 1: <bx:relativelink pattern="?/nichtvorhanden">
  Nicht vorhanden!</bx:relativelink><br/>
Fehler 2: <bx:relativelink pattern="fr/*">
  Sprache unvollständig!</bx:relativelink><br/>
<br/>
<bx:relativelink pattern="en/demo"/>
```

**Administration:**

![](http://wiki.batix.net/images/1/1c/BspRelativelinkA.png)

**Webseite:**

![](http://wiki.batix.net/images/9/93/BspRelativelinkW.png)

# bx:scanner

Die Ausgabe des Tags `<span style="color: rgb(0,51,102);">scanner</span> `ist abhängig vom User-Agent, der die Seite aufruft. Wenn der User-Agent mit "Batix Crawler/" beginnt, werden die vom Tag umschlossenen Bereiche ggf. nicht in die Seite geschrieben und damit auch nicht in den Suchindex aufgenommen. 
*Wenn man "?crawler=batix" an die URL einer CM-Seite anhängt, wird die Seite angezeigt, wie sie der Batix-Crawler verarbeiten würde.*

## scanner.skip

```xml
<bx:scanner.skip> Inhalt </bx:scanner.skip>
```

Bereiche, die so markiert sind, werden nicht in den Suchindex aufgenommem. Links in diesen Bereichen wird die Suchmaschine folgen. Dieses Tag schreibt einen kleinen HTML-Kommentar, der vom Batix-Crawler dann berücksichtigt wird. Wenn ein anderer User-Agent die Seite aufruft, werden diese Bereiche angezeigt.

## scanner.hide

```xml
<bx:scanner.hide> Inhalt </bx:scanner.hide>
```

Diese Bereiche werden komplett vor dem Crawler verborgen. Daher wird er auch Links in diesen Bereichen nicht folgen.

## Text für Description in Seite sammeln

```xml
<bx:scanner.description> Inhalt </bx:scanner.description>
```

Diese Funktion markiert Bereiche, die als Meta-Description im HTML-Kopf angezeigt werden sollen.

# bx:schleife

Das Tag `schleife` ersetzt das frühere [bx:loop](/books/cms-handbuch-entwickler/page/bx-formdata). Es können nun mehrere Schleifen in einer Ebene oder geschaltet benutzt werden. Der Inhalt dieses Tags kann beliebig mit anderen Tags versehen werden, z.B. [bx:text](/books/cms-handbuch-entwickler/page/bx-text) oder [bx:bild](/books/cms-handbuch-entwickler/page/bx-if).
 Um innerhalb der Schleife zu navigieren, benutzt man die Eigenschaften von [bx:loop](/books/cms-handbuch-entwickler/page/bx-formdata).

<p class="callout success">Will man auf einer Seite nur eine Iteration vornehmen, dann kann man auch das [bx:tools.for](/books/cms-handbuch-entwickler/page/bx-tools) - Tag nehmen.</p>

## Listausgabe

```xml
<bx:schleife.{bez} [orderby="{feldname}"] [richtung="desc" | desc] [list="{feldname}"] [showmax="{n}" | single [random] | all] [indexparam="{param}"]>
  Inhalt 
</bx:schleife.{bez}>
```

| bez | frei wählbarer Titel der Schleife<br>dient auch zum Unterscheiden von mehreren Schleifen einer Seite in der Datenbank<br>dieser Titel ist auch der erwartete Request-Parametername bei Aufruf als Detailseite |
| --- | --- |
| orderby | Feldname innerhalb der Schleife, nach dem die Liste sortiert werden soll |
| richtung | oder nur "desc" dreht die Sortierrichtung um |
| list | Feld innerhalb der Schleife (z.B. Name), das in der Verwaltung als Datensatz-Titel angezeigt wird<br>Wenn man innerhalb der Schleife mit bx:record einen DS aussuchen kann, dann kann auch der Bezeichner des bx:record genommen werden. (siehe 3. Beispiel) |
| showmax | Angabe der maximale Anzahl an Elementen |
| indexparam | Um mehrere blätterbare Listen zu ermöglichen, legen Sie für jede Liste einen eigenen Request-Parameter mittels "indexparam" an. |
| single \| all | single: Detailseitenmodus - wenn keine ID übergeben wurde, wird nichts angezeigt all: Listenmodus, auch wenn eine ID angegeben ist single random: ein Random-Element wird angezeigt |

### Beispiele

**Listenseite**

```xml
<bx:schleife.Cats list="Name">
  <bx:loop.count add="1"/> - <a href="detail.htm?Cats=<bx:loop.id/>"><bx:text.Name/></a><br>
</bx:schleife.Cats>
```

Liste mit Link auf die Detailseite. Der Requestparameter für die Detailseite muß so heißen wie die Schleife (hier "Cats").

**Detailseite**

```xml
<bx:schleife.Cats>
  <h1><bx:text.Name/></h1>
  <bx:textarea.Beschreibung/>
  <bx:bild.Bild/>
</bx:schleife.Cats>
```

Die Detailseite.

**Record**

```xml
<bx:schleife.Ansprechpartner list="Mitarbeiter">
  <bx:record.Mitarbeiter pool="Mitarbeiter><bx:recordfield.Vorname/> <bx:recordfield.Name/></bx:record.Mitarbeiter>
</bx:schleife.Cats>
```

Es wird das angezeigt, was bei der Containerdefinition definiert wurde.

# bx:search

<p class="callout warning">**Achtung!**

Dieses Tag ist deprecated (missbilligt), es wird nicht mehr weiterentwickelt oder in zukünftigen Versionen nicht mehr unterstützt. 
Bitte stattdessen <a href="http://wiki.batix.net/index.php/Bx:websearch" target="_blank">bx:websearch</a> benutzen.</p>

```xml
<bx:search.category...
<bx:search.list...
<bx:search.name...
<bx:search.titel...
<bx:search.link...
<bx:search.topname...
<bx:search.parentname...
<bx:search.empty...
```

# bx:secureform

Das Tag `bx:secureform` wird benutzt, um Formulare gegen Manipulationen abzusichern. Es ist verfügbar ab *Version 2.6.5.*

<p class="callout info">[Unter diesem Link](/books/cms-handbuch-entwickler/page/manipulationsgeschuetzte-formulare-mit-secureform) gibt es eine ausführliche Anleitung, wie dieses Tag mit dem [zugehörigen Action](/books/cms-handbuch-entwickler/page/sicheres-formular-ueberpruefen) zu benutzen ist.</p>

## secureform

```xml
<bx:secureform> ... </bx:secureform>
```

Das Tag wird um eine `<form>` geschachtelt und definiert somit einen Gültigkeitsbereich für die inneren Tags (s.u.).

### Beispiele

```xml
<bx:secureform>
  <form action="save.act">
    ...
  </form>
</bx:secureform>
```

## secureform.field

```xml
<bx:secureform.field name="{parametername}" [cut]> ... </bx:secureform.field>
<bx:secureform.field name="{parametername}" hidden-when-empty [cut]> ... </bx:secureform.field>
```

Dieses innere Tag wird um die einzelnen Werte von `<input>`s oder Ähnlichem geschachtelt. Es merkt sich den Name und Wert des Parameters, um später über alle gesammelten Parameter den Hash zu bilden.

Der Wert wird auch wieder vom Tag ausgegeben, es funktioniert also wie `[bx:clipboard.copy](/books/cms-handbuch-entwickler/page/bx-clipboard)`. Falls der Wert nicht ausgegeben werden soll, kann `cut` angegeben werden (funktioniert dann wie `[bx:clipboard.cut](/books/cms-handbuch-entwickler/page/bx-clipboard)`).

<p class="callout warning">Falls im Inhalt andere Tags benutzt werden, muss darauf geachtet werden, dass diese **kein** HTML- oder sonstiges Encoding vornehmen (d.h. es muss ggf. `type="plain"` oder `encode="plain"` angegeben werden)! Das `secureform.field` Tag macht automatisch ein HTML-Encoding, falls es nicht von `tools.htmlencode` umschlossen ist.</p>

Der Parameter `hidden-when-empty` muss angegeben werden, falls leere Werte dieses Parameters vom Browser nicht mitgesendet werden. Das würde sonst die Hashbildung verfälschen, denn das Tag beachtet den Parameter und merkt sich den leeren Wert, allerdings bekommt das Action den Parameter nicht übergeben und zieht ihn entsprechend *nicht* zur Hashbildung heran. Ist `hidden-when-empty` also angegeben und der Taginhalt leer, dann fließt dieser Parameter nicht mit in die Hashberechnung ein.

<p class="callout warning">Als Wert (Tag-Inhalt) darf kein User-Input verwendet werden, die dieser ja nicht vom Server festgelegt wird.

Im Normalfall darf also z.B. kein `bx:pagedata.request` innerhalb von `bx:secureform.field` stehen.</p>

| parametername | entspricht dem Name des Parameters, der vom Browser später mitgeschickt wird<br>ist meistens gleich dem `name`-Attribut eines `<input>`s |
| --- | --- |

### Beispiele

```xml
<!-- statischer Wert -->
<input type="hidden" name="gruppe" value="<bx:secureform.field name="gruppe">12345ABC</bx:secureform.field>">
 
<!-- dynamischer Wert -->
<input type="hidden" name="kid" value="<bx:secureform.field name="kid"><bx:recordfield.Kunde type="id" /></bx:secureform.field>">
 
<!-- Wert, bei dem das HTML-Encoding abgeschaltet werden muss -->
<input type="hidden" name="fester_titel" value="<bx:secureform.field name="fester_titel"><bx:text.Titel_aus_Verwaltung type="plain" /></bx:secureform.field>">
 
<!-- Feld, dass z.B. bei <bx:containerfilter dummy> wegfallen kann und somit hidden-when-empty benutzt werden muss -->
<bx:if><input type="hidden" name="editid" value="<bx:secureform.field name="editid" hidden-when-empty><bx:recorddata.id /></bx:secureform.field>"></bx:if>
```

## secureform.values

```xml
<bx:secureform.values name="{parametername}" [cut]>...</bx:secureform.values>
```

In dieser Form wird ein erlaubter Wert eines Parameters gesammelt (siehe <a href="http://docs.batix.info/pages/viewpage.action?pageId=4489658#ManipulationsgeschützteFormularemitSecureform-ErlaubteWerte" target="_blank">Mehrere erlaubte Werte</a>). Es verhält sich wie `bx:secureform.field` (`cut`, HTML-Encoding). Bitte die Hinweise weiter oben auch hier beachten!

| parametername | entspricht dem Name des Parameters, der vom Browser später mitgeschickt wird |
| --- | --- |

Die gesammelten, erlaubten Werte müssen dann für jedes Feld ausgegeben werden. Dies geschieht in folgender Form:

```xml
<bx:secureform.values name="{parametername}" />                        <!-- hidden Feld wird erzeugt -->
<bx:secureform.values name="{parametername}" param [encode="..."] />   <!-- nur Parametername ausgeben -->
<bx:secureform.values name="{parametername}" values [encode="..."] />  <!-- nur gesammelte Werte ausgeben -->
```

Die erste Variante (nur ein geschlossenes Tag mit `name` Parameter) erzeugt ein `input type="hidden"` mit passenden `name` und `value` Attributen.

Falls man selbst einen Link zusammenbaut, kann `param` bzw. `values` benutzt werden, um entweder den Name des speziellen Parameters bzw. dessen Wert auszugeben. Je nach Fall muss die Rückgabe entsprechend encoded werden, z.B. `encode="javascript"` oder `encode="url"`.

<p class="callout warning">Falls keine Werte für den Parameter gesammelt wurden, geben alle drei Varianten nichts aus.</p>

## secureform.hash

```xml
<bx:secureform.hash />        <!-- hidden Feld wird erzeugt -->
<bx:secureform.hash name />   <!-- nur Hash-Parametername ausgeben -->
<bx:secureform.hash value />  <!-- nur Hash-Wert ausgeben -->
```

Dieses innere Tag durchläuft alle gesammelten Parameter-Werte-Paare und bildet mit anderen, geheimen Faktoren einen Hashwert. Ohne Parameter wird ein `<input type="hidden">` mit passenden `name` und `value` Attributen in die Seite geschrieben.

Möchte man nur Name oder Wert haben, ist dies auch möglich (um diese z.B. in Scripts zu verwenden).

<p class="callout warning">Nach `<bx:secureform.hash />` oder `<bx:secureform.hash value />` darf kein weiteres `<bx:secureform.field>` oder `<bx:secureform.values>` folgen. Alle Tags müssen außerdem innerhalb von `<bx:secureform>` stehen.</p>

## secureform.check

```xml
<bx:secureform.check securelist="{parameterliste}" [url="{url}"] [forward] />
```

Hiermit können in einem Template die abgesicherten Parameter geprüft werden. Die Parameter ähneln die des [Actions](/books/cms-handbuch-entwickler/page/sicheres-formular-ueberpruefen).

| parameterliste | Dies ist eine komma-getrennte Liste der Parameternamen, welche zur Hashbildung herangezogen werden.<br>Tauchen hier Parameternamen auf, die nicht im Request sind, so werden diese Parameter nicht zur Hashbildung benutzt.<br>Hier können auch Parameter stehen, die nie an die Seite übergeben werden dürfen - da diese im Frontend nicht mitgehasht werden und höchstens durch Manipulation im Request landen, schlägt die Prüfung fehl und die Seite bricht ab.<br>Zusätzlich zu dieser manuellen Liste gibt es eine im System verankerte Liste, welche einige Standardparameter enthält, die immer geschützt sein müssen (z.B.: recordid, listid). |
| --- | --- |
| url | Falls die Prüfung fehlschlägt, wird zu dieser URL weitergeleitet. Ist zusätzlich `forward` angegeben, wird statt dem Redirect ein Forward gemacht (URL bleibt im Browser stehen).<br>Ist hier nichts eingetragen und die Prüfung schlägt fehlt, wird die Abarbeitung der Seite abgebrochen und der generierte Quelltext wird nicht an den Client ausgeliefert.<br>Manche Tags führen schon Aktionen aus, bevor `<bx:secureform.check>` die Parameter prüft, diese sind aber meistens unkritisch. |

Alle Parameter in `securelist` müssen, falls vorhanden, abgesichert sein. Das heißt ihr Wert muss entweder direkt in den Hash eingeflossen sein, oder einen der erlaubten Werten entsprechen (und diese Liste muss dann in den Hash eingeflossen sein).

<p class="callout warning">Dieses Tag sollte in der ersten Zeile des Quelltextes stehen, um sicherzustellen, dass die Abarbeitung der restlichen Seite so früh wie möglich abgebrochen wird.</p>

### Erlaubte Werte

Falls ein spezieller Parameter für <a href="http://docs.batix.info/pages/viewpage.action?pageId=4489658#ManipulationsgeschützteFormularemitSecureform-ErlaubteWertefestlegen" target="_blank">mehrere erlaubte Werte</a> mitgeschickt wurde, wird zusätzlich geprüft, ob der originale Parameter einem dieser Werte entspricht.

Verweise auf diese Seite:

- <a href="http://docs.batix.info/pages/viewpage.action?pageId=19300538" target="_blank">Sicheres Formular überprüfen (SecureformAction)</a>
- <a href="http://docs.batix.info/pages/viewpage.action?pageId=4489649" target="_blank">Sicheres Formular überprüfen (SecureformAction)</a>
- <a href="http://docs.batix.info/pages/viewpage.action?pageId=19300514" target="_blank">Manipulationsgeschützte Formulare mit Secureform</a>
- <a href="http://docs.batix.info/pages/viewpage.action?pageId=4489658" target="_blank">Manipulationsgeschützte Formulare mit Secureform</a>

<p>(4 Verweise)</p>

# bx:sessiondata

Das Tag `sessiondata` setzt, liest und vergleicht Werte von Session-Variablen.

## Auslesen eine Attributes, das mit dem Action geschrieben wurde

```xml
<bx:sessiondata[.{mapname}] name="{key}" />
```

Ein in die Session geschriebener Wert wird abgerufen. Dies gilt für Werte, die über das Action SaveInSessionAction in der Session geschrieben wurden.
Falls `<mapname>` nicht spezifiziert ist, wird der Standardwert "default" verwendet. Es sind nur Strings möglich.
Ab Version 2.6.0 kann man im Filter auch direkt auf den Wert zugreifen, wenn kein Map-Name angegeben wurde. Ein Umspeichern auf der Seite entfällt.

| {mapname} | Name der Map |
| --- | --- |
| key | gesuchter Eintrag |

## sessiondata.id

```xml
<bx:sessiondata.id [force="no-create"]/>
```

Gibt die Session-ID aus *( ab Version 2.5.8 )
*Wenn es noch keine Session gibt, dann wird eine erstellt und dann ausgegben, außer man gibt "no-create" an* (ab V 2.6.9)
*

## sessiondata.attribute

```xml
<bx:sessiondata attribute="<key>" />
 <bx:sessiondata.attribute name="<key>" encode="typ"/>
 <bx:sessiondata.attribute name="<key>" [not] > Inhalt </bx:sessiondata.attribute>

 <bx:sessiondata.attribute name="<key>" value="<value>" [not] > Inhalt </bx:sessiondata.attribute>
```

*(ab V 2.5.6 ) *Ein Wert aus der Session wird über dessen key abgerufen. Werte vom Typ String werden hier unterstützt. Zusätzlich sind als Werte auch Objekte des Typs BatixModul möglich, hier wird der Titel des Moduls zurückgegeben. Falls das Object kein String oder BatixModul ist, wird der Wert von toString() zurückgegeben.

| attribute | Name des Attributs |
| --- | --- |
| name | Name des Attributs |
| value | Wert zum Vergleich mit dem Wert im Attribute |
| not | kehrt die Bedigung um |
| encode | Hiermit kann der ausgegebene Text für verschiedene Formate kodiert werden:<br>- html - javascript - sql (zur Verwendung in SQL für Strings) - sql-like (zur Verwendung in SQL mit LIKE) - sql-rlike (zur Verwendung in SQL mit RLIKE und REGEXP) - url - xml |

## sessiondata.setattribute

```xml
<bx:sessiondata.setattribute name="<key>" [cut] > Tag-Body </bx:sessiondata.setattribute>
```

Erzeugt ein Session-Attribut mit dem angegebenen Namen und speichert als Wert den ausgewerteten Body des Tags. Bei leerem Body wird das Attribut gelöscht. *(ab V 2.5.8 )*

| name | Name des Attributs |
| --- | --- |
| cut | bewirkt, daß der Body nicht auf der Seite angezeigt wird |

## sessiondata.removeattribute

```xml
<bx:sessiondata.removeattribute name="<key>" />
```

Ein Wert aus der Session wird gelöscht. Ab der Stelle dieses Aufrufs in der Seite ist der Wert nicht mehr verfügbar. *(ab V 2.5.8 )
*

## sessiondata.invalidationtime

```xml
<bx:sessiondata.invalidationtime pattern="HH:mm"/>
```

Gibt die Uhrzeit aus zu der die Session inaktiv wird, falls keine weiteren Requests erfolgen. **(ab V 2.5.8 )**

| pattern | Datumsmuster |
| --- | --- |

# bx:sitemap

<p class="callout warning">**Erweitertes Tag**
 Das Tag `sitemap` ist eine Erweiterung von **[bx:navigation](/books/cms-handbuch-entwickler/page/bx-navigation)**. Alles was in **[bx:navigation](/books/cms-handbuch-entwickler/page/bx-navigation)** möglich ist, ist auch hier möglich (evtl. Änderungen sind weiter unten angegeben). Neue Funktionen, die auf dieser Seite angegeben sind, können nur in diesem Tag verwendet werden, nicht in **[bx:navigation](/books/cms-handbuch-entwickler/page/bx-navigation)**.</p>

## Allgemeine Syntax

```xml
<bx:sitemap.{level} [normal | protected] [showprotected] [showinactive] [path="{pfad}"]  > Inhalt </bx:sitemap.<level>>
```

Da die Sitemap eine komplett aufgeklappte Navigation darstellt, ist der Parameter `open` weggefallen.

| normal/protected | nur nicht-geschützte Menüpunkte anzeigen / nur geschützte (Intranet-)Menüpunkte anzeigen |
| --- | --- |
| showprotected | geschütze Elemente auch dann einblenden, wenn der Betrachter keinen Zugriff darauf hat |
| showinactive | inaktive Elemente anzeigen |
| path | Pfad zum Menüpunkt, von welchem die Unterpunkte angezeigt werden sollen (nur wenn<br>`<level>`<br>> 0 und kein<br>`<bx:sitemap.0>`<br>-Tag außen herum steht) |

## sitemap.text

```xml
<bx:sitemap.text/>
```

Gibt die Beschreibung des Punktes aus. .

# bx:statistik

Dies ist ein Tag, das statistische Angaben von Userzugriffen auf Navigationspunkte ausgeben kann. Funktioniert nur mit langen URLs (also mit /www/projektname/.....)

## statistik.visitors

```xml
<bx:statistik.visitors start="{date}" ende="{date}" />
```

Die Anzahl an unterschiedlichen Session-IDs, die den aktuellen Navigationspunkt im angegebenen Zeitraum aufriefen. Die Auswertung erfolgt nur für den aktuellen Menüpunkt.

<span style="color: rgb(255,0,0);">**veraltet**</span>: `<bx:statistik.anzahl ... />`

| start | Startdatum, pattern: dd.MM.yyyy, kann durch ein Formularfeld übergeben werden |
| --- | --- |
| ende | Endedatum, pattern: dd.MM.yyyy, kann durch ein Formularfeld übergeben werden |

## statistik.totalvisitors

```xml
<bx:statistik.totalvisitors start="{date}" ende="{date}" />
```

Die Anzahl an unterschiedlichen Session-IDs, die das Web im angegebenen Zeitraum aufriefen. Die Auswertung erfolgt für das gesamte Projekt.

## statistik.hits

```xml
<bx:statistik.hits start="{date}" ende="{date}" />
```

Die Anzahl an Seitenaufrufen des aktuellen Menüpunktes im angegebenen Zeitraum. Die Auswertung erfolgt nur für den aktuellen Menüpunkt.

## statistik.totalhits

```xml
<bx:statistik.totalhits start="{date}" ende="{date}" />
```

Die Anzahl an Seitenaufrufen des gesamtem Webs im angegebenen Zeitraum. Die Auswertung erfolgt für das gesamte Projekt.
statistik.pagelist

```xml
<bx:statistik.pagelist start="{date}" ende="{date}"> Inhalt </bx:statistik.pagelist>
```

Eine Schleife durch die unterschiedlichen URLs, die zu diesem Punkt gespeichert sind. In diesem Tag können .visitors, .hits, .url und .name als Inhalt verwendet werden. Es werden alle aufgerufenen URLs zum aktuellen Menüpunkt durchlaufen.

## statistik.initialdate

```xml
<bx:statistik.initialdate [ pattern="{format}" ] />
```

Schreibt das Datum / die Zeit des ersten (ältesten) Eintrags für das Web in die Seite. Falls pattern nicht angegeben wurde, wird der Standard-Wert "dd.MM.yyyy HH:mm:ss" verwendet.

## statistik.terminaldate

```xml
<bx:statistik.terminaldat [ pattern="{format}" ] />
```

Schreibt das Datum / die Zeit des letzen (neuesten) Eintrags für das Web in die Seite. Falls pattern nicht angegeben wurde, wird der Standard-Wert "dd.MM.yyyy HH:mm:ss" verwendet.

## statistik.url

```xml
<bx:statistik.url/>
```

Diese Funktion erfordert eine umgebende .pagelist. Es wird die URL des aktuellen Schleifenelements ausgegeben.

## statistik.name

```xml
<bx:statisik.name/>
```

Diese Funktion erfordert eine umgebende .pagelist.

### Beispiele

```xml
<form action="./" method="post">
  Zeitraum:<br>
  von <input type="text" name="von" value="<bx:if><bx:pagedata.request name="von"/><bx:if.else>01.<bx:tools.datum pattern="MM.yyyy"/></bx:if.else></bx:if>">
  bis <input type="text name="bis" value="<bx:if><bx:pagedata.request name="bis"/><bx:if.else><bx:tools.datum pattern="dd.MM.yyyy"/></bx:if.else></bx:if>">
  <input type="submit" value="anzeigen">
  <br>Beginn der Erfassung <bx:statistik.initialdate pattern="dd.MM.yyyy"/>
</form>

...

<table>
    <tr>
      <th>&nbsp;</th>
      <th>Seitenaufrufe</th>
      <th>Besucher</th>
    </tr>
    <bx:sitemap.0 showinactive>
      <tr>
        <td><a href="/www/<bx:pagedata.webdir/>/<bx:sitemap.path/>/"><bx:sitemap.name/></a></td>
        <td><bx:statistik.hits start="request:von" ende="request:bis"/></td>
        <td><bx:statistik.anzahl start="request:von" ende="request:bis"/></td>
      </tr>
  </bx:sitemap.0>
</table>
```

Beispiel einer einfachen Statistik

# bx:submenu

Das Tag `submenu` erzeugt eine Liste der Unterpunkte des aktuellen Menüpunktes. Kann geschachtelt werden (siehe Beispiel ganz unten).
Innerhalt der Schleife kann bx:navdata benutzt werden.

## submenu.list

```xml
<bx:submenu.list [all]> Inhalt </bx:submenu.list>
```

Innerhalb des Tags kann auf die Inhalte des Unterpunktes (bx:text..., bx:bild... usw) zugegriffen werden. Es können darin die nachfolgenden Tags verwendet werden.

| all | um auch nicht aktivierte Menupünkte anzuzeigen |
| --- | --- |

## submenu.name

```xml
<bx:submenu.name />
```

Der Name des Menüpunktes wird ausgegeben.

## submenu.link

```xml
<bx:submenu.link> Inhalt </bx:submenu.link>
```

Es wird ein Link auf den Menüpunkt erzeugt. Als Linktext wird der Tag-Inhalt verwendet.

## submenu.description

```xml
<bx:submenu.description [maxwords="{n}"] />
```

Dieses Tag gibt die Beschreibung des Menüpunktes aus,

| maxwords | optional auf {n} Wörter begrenzt |
| --- | --- |

## submenu.path

```xml
<bx:submenu.path />
```

Ausgabe des relativen Pfades zum Unterpunkt (auch bei mehreren Schachtelungsebenen). 
Der virtuelle Pfad wird ohne "/www/webname/" und ohne "/" am Ende ausgegeben.

## submenu.target

```xml
<bx:submenu.target alt="_self" />
```

Das Target aus dem Menüpunkt wird ausgegeben.

## submenu.meta

```xml
<bx:submenu.meta name="Meta-Key" />
<bx:submenu.meta name="Meta-Key" [not] > ... </bx:submenu.meta>
```

Metadaten aus dem Navigationspunkt ausgeben oder abhängig vom Vorhandensein einen Block ausgeben. Es kann auch bx:navdata (siehe Batix Docs) benutzt werden.

## submenu.cols

```xml
<bx:submenu.cols num="{n}" equals="{n}">...</bx:submenu.cols>
```

Zeigt abhängig von einer Spaltennummer einer Menüpunktliste Daten an.

### Beispiele

```xml
<bx:submenu.cols num="3" equals="3">style="margin-right:0;"</bx:submenu.cols>
```

Nur Spalte drei soll kein Rechts-Margin haben

```xml
<bx:submenu.cols num="3" equals="2" true="Spalte zwei" false="nicht Spalte zwei"/>
```

Wenn Spalte 2: zeige anderen Text als Spalte 1 und 3

```xml
<bx:submenu.cols num="3" 1="links" 2="mitte" 3="rechts"/>
<bx:submenu.cols num="3" col1="links" col2="mitte" col3="rechts"/>
```

Je nach Spalte anderer Text

## submenu.index

```xml
<bx:submenu.index [add="Startwert"]/>
```

Ausgabe einer laufenden Nummer des Schleifendurchlaufs. (Beginnend bei 1)
Mit `<bx:submenu.index add="0"/>` beginnt die Schleife ab 0 (z. B. für Javascript-Arrays)

## submenu.redirected

```xml
<bx:submenu.redirected> ... </bx:submenu.redirected>
<bx:submenu.redirected not> ... </bx:submenu.redirected>
```

Abfrage, ob der Punkt weitergeleitet ist

### Beispiele

```xml
<bx:submenu.redirected><a href="<bx:submenu.redirecturl/>"><bx:navlink><bx:bild.Bild/></bx:navlink></a></bx:submenu.redirected> (extern)
<bx:submenu.redirected not><bx:submenu.link><bx:submenu.name/></bx:submenu.link></bx:submenu.redirected> (intern)
```

Zugriff auf Inhalte eines Untermenü-Punkts, wenn Weiterleitung im Unterpunkt

## submenu.redirecturl

```xml
<bx:redirecturl />
```

Rückgabe der Redirect-URL

## Schachtelung und Geschwister

### Beispiel

```xml
<bx:submenu.list>
  <bx:submenu.name />
  <bx:Submenu.list>
    <bx:Submenu.name />
  </bx:Submenu.list>
</bx:submenu.list>
```

Es werden die zwei Ebenen unter dem jeweiligen Menüpunkt ausgegeben. Zur Unterscheidung der Schleifen muß die Schreibweise bissl kreativ angepaßt werden (Groß- und Kleinschreibung).

```xml
<bx:clipboard.cut name="navid"><bx:pagedata.parentnavid/></bx:clipboard.cut>

<bx:navlink navid="clipboard:navid">
  <bx:submenu.list>
    <button class="btn btn-default" onclick="location.href='<bx:submenu.path/>'"><bx:submenu.name/></button>
  </bx:submenu.list>
</bx:navlink>  
```

Geschwisternavigationspunkte ausgeben

# bx:submenulist

<p class="callout warning">**Achtung!**

Dieses Tag ist deprecated (missbilligt), es wird nicht mehr weiterentwickelt oder in zukünftigen Versionen nicht mehr unterstützt. 
Bitte stattdessen [bx:submenu](/books/cms-handbuch-entwickler/page/bx-submenu) benutzen.</p>

Dieses Tag stellt Untermenüpunkte des aktuellen Menüpunktes mittels einer Schleife dar.

```xml
<bx:submenulist [all]> Inhalt </bx:submenulist>
```

Um auch inaktive Punkte anzuzeigen, muss `all` angegeben werden. Folgende Tags können im Inhalt verwendet werden:

## submenuname

```xml
<bx:submenuname />
```

Gibt den Name des Menüpunktes aus.

## submenudir

```xml
<bx:submenudir />
```

Gibt den virtuellen Verzeichnisnamen des Menüpunktes aus.

Verweise auf diese Seite:

Keine Verweise gefunden.

# bx:systemdata

Mithilfe des Tags `systemdata` lassen sich Systemvariablen ausgeben. Systemvariablen werden in der Verwaltung unter dem Punkt "<a href="http://docs.batix.info/display/USERS/Systemeinstellungen" target="_blank">Systemeinstellungen</a>" angelegt und verwaltet. Sie können pro Projekt angepaßt werden.

## systemdata.attribute

```xml
<bx:systemdata.attribute name="<attrib>" />
<bx:systemdata.attribute name="<attrib>" [not]> Inhalt </bx:systemdata.attribute>
<bx:systemdata.attribute name="<attrib>" value="<Test-Value>" [not]> Inhalt </bx:systemdata.attribute>
```

globales System-Attribut auswerten
Die erste Form schreibt den Wert des Attributes (falls vorhanden) in die Seite, 
die Zweite den Tag-Inhalt (`not` verwendbar), falls das Attribut definiert/nicht definiert wurde*,
*die Dritte schreibt den Inhalt nur bei Übereinstimung des Wertes.

| name | Name des Requestattributs |
| --- | --- |
| value | zu prüfender Wert<br>* (seit v2.5.9)* |
| not | kehrt die Bedingung um |

## systemdata.variable

```xml
<bx:systemdata.variable name="<key>" />
<bx:systemdata.variable name="<key>" [not]> Inhalt </bx:systemdata.variable>
<bx:systemdata.variable name="<key>" value="<Test-Value>" [not]> Inhalt </bx:systemdata.variable>
```

Projektvariablen auswerten. Wird keine gefunden, wird die globale genommen.
Rest siehe oben.

## weitere Verwendungen

Auf die Variablen kann auch mit dem Präfix "system:" in bx-Tag-Parametern zugegriffen werden z. B.:

```xml
<bx:containerloop pool="system:newslistid">
```

wenn in jedem Projekt eine Variable namens newslistid definiert wird, die eine passende Container-ID enthält

oder:

```xml
<bx:recordfield.Datum pattern="system:pattern">
```

wenn im deutschen Projekt ein deutsches Datumsmuster und im englischen Projekt ein englisches Muster eingetragen wird

seit v2.6:

in java-includes können die Variablen so aufgerufen werden:

```xml
<%@taglib prefix="batix" uri="/batix"%>
<batix:taginfo>
<%
String wert = variables.getVariable("test");
%>
</batix:taginfo>
```

in Jsp-Action geht der Aufruf so:

```xml
<%@page import="com.batix.modul.SystemVariables"%>
<%@page import="com.batix.action.JspAction"%><%
JspAction action = JspAction.getInstance(request);
SystemVariables variables = SystemVariables.getInstance(action);
String wert = variables.getVariable("test");
%>
```

# bx:tablechoice

Dieses Tag ist eine Erweiterung von [bx:recordchoice](/books/cms-handbuch-entwickler/page/bx-recordchoice). Alles was in [bx:recordchoice](/books/cms-handbuch-entwickler/page/bx-recordchoice) möglich ist, ist auch hier möglich (evtl. Änderungen sind weiter unten angegeben). Neue Funktionen, die auf dieser Seite angegeben sind, können nur in diesem Tag verwendet werden, nicht in [bx:recordchoice](/books/cms-handbuch-entwickler/page/bx-recordchoice).

# bx:tabledata

Dieses Tag ist eine Erweiterung von [bx:recorddata](/books/cms-handbuch-entwickler/page/bx-recorddata). Alles was in [bx:recorddata](/books/cms-handbuch-entwickler/page/bx-recorddata) möglich ist, ist auch hier möglich (evtl. Änderungen sind weiter unten angegeben). Neue Funktionen, die auf dieser Seite angegeben sind, können nur in diesem Tag verwendet werden, nicht in [bx:recorddata](/books/cms-handbuch-entwickler/page/bx-recorddata).

# bx:tablefield

Dieses Tag ist eine Erweiterung von [bx:recordfield](/books/cms-handbuch-entwickler/page/bx-recordfield). Alles was in [bx:recordfield](/books/cms-handbuch-entwickler/page/bx-recordfield) möglich ist, ist auch hier möglich (evtl. Änderungen sind weiter unten angegeben). Neue Funktionen, die auf dieser Seite angegeben sind, können nur in diesem Tag verwendet werden, nicht in [bx:recordfield](/books/cms-handbuch-entwickler/page/bx-recordfield).

# bx:tablefilter

Dieses Tag ist eine Erweiterung von [bx:containerfilter](/books/cms-handbuch-entwickler/page/bx-containerdata). Alles was in [bx:containerfilter](/books/cms-handbuch-entwickler/page/bx-containerdata) möglich ist, ist auch hier möglich (evtl. Änderungen sind weiter unten angegeben). Neue Funktionen, die auf dieser Seite angegeben sind, können nur in diesem Tag verwendet werden, nicht in [bx:containerfilter](/books/cms-handbuch-entwickler/page/bx-containerdata).

# bx:tablekat

Dieses Tag ist eine Erweiterung von [bx:containerkat](/books/cms-handbuch-entwickler/page/bx-containerkat). Alles was in [bx:containerkat](/books/cms-handbuch-entwickler/page/bx-containerkat) möglich ist, ist auch hier möglich (evtl. Änderungen sind weiter unten angegeben). Neue Funktionen, die auf dieser Seite angegeben sind, können nur in diesem Tag verwendet werden, nicht in [bx:containerkat](/books/cms-handbuch-entwickler/page/bx-containerkat).

# bx:tableloop

Dieses Tag ist eine Erweiterung von [bx:containerloop](/books/cms-handbuch-entwickler/page/bx-containerloop). Alles was in [bx:containerloop](/books/cms-handbuch-entwickler/page/bx-containerloop) möglich ist, ist auch hier möglich (evtl. Änderungen sind weiter unten angegeben). Neue Funktionen, die auf dieser Seite angegeben sind, können nur in diesem Tag verwendet werden, nicht in [bx:containerloop](/books/cms-handbuch-entwickler/page/bx-containerloop).

# bx:tablerecord

Dieses Tag ist eine Erweiterung von [bx:record](/books/cms-handbuch-entwickler/page/bx-record). Alles was in [bx:record](/books/cms-handbuch-entwickler/page/bx-record) möglich ist, ist auch hier möglich (evtl. Änderungen sind weiter unten angegeben). Neue Funktionen, die auf dieser Seite angegeben sind, können nur in diesem Tag verwendet werden, nicht in [bx:record](/books/cms-handbuch-entwickler/page/bx-record).

# bx:tablesqlfilter

Das Tag `tablesqlfilter` filtert einen Container über eine SQL-Anweisung, die in den Tag-Einstellungen der Administraton angegeben ist.

```xml
<bx:tablesqlfilter.{titel} pool="{name | id }" [where="{sql}"]> Inhalt </bx:tablesqlfilter.{titel}>
```

Innerhalb der Bedingung (in der Administration) können Platzhalter für Request-Parameter verwendet werden. So wird z.B. "[[param]]" durch den Wert des Parameters "param" ersetzt, bevor die Bedingung ausgewertet wird.

Wenn weder in der Administration, noch im Parameter where eine Bedingung angegeben ist, werden alle Datensätze angezeigt.

|  |  |
| --- | --- |
| **containername \| id** | ID des zu filternden Containers |
| **where** | Standard-Bedingung, falls in der Administration nichts eingetragen ist |

# bx:text

Mittels des Tags `text` kann für Redakteure eine Eingabemöglichkeit in Form eines einzeiligen Textfeldes geschaffen werden.

Die einzelnen Funktionen können kombiniert werden.

<p class="callout info">Dieses Tag kann sich in der Verwaltung darstellen.</p>

## Textfeld anzeigen

```xml
<bx:text.{titel} [comment="{kommentar}"] [admin-mode="config" admin-title="{alternativer Titel}"]/>
```

| comment | Kommentar, der beim Tag z.B. als Hinweis mit ausgegeben wird |
| --- | --- |
| admin-mode | Erzwingt, daß das Tag bei den Tageinstellungen (anstatt bei Dateneingabe) angezeigt wird. |
| admin-title | In Verwaltung wird ein anderer Titel ausgeben als der beim Tag angegebene. |

<p class="callout info">Für `{titel}` und `{kommentar}` siehe die allgemeinen Hinweise zu [Redakteurs-Tags](/books/cms-handbuch-entwickler/page/redakteurs-tags).</p>

## Länge begrenzen

```xml
<bx:text.{titel} [size="{breite}"] [maxlength="{maxlänge}"] />
```

Das Eingabefeld ist hiermit `{breite}` Zeichen breit bzw. können dann nur `{maxlänge}` Zeichen in das Feld eingetragen werden.

`size` kann nicht auf kleiner als 2 gesetzt werden (wird dann auf 63 gesetzt), der Maximalwert beträgt 63. Der Standardwert ist 63.

`maxlength` kann nicht auf kleiner als 2 gesetzt werden (wird dann auf 255 gesetzt), der Maximalwert beträgt 255. Der Standardwert ist 255.

## Ausgabe maskieren

```xml
<bx:text.{titel} [encode="(html | plain | url | javascript | entitymask | xml)"] />
```

Standardmäßig wird ausgegebener Text HTML-kodiert (`html` ist also Standard für `encode`), außer der MIME-Type der Frontend-Seite beginnt mit "text/plain" (dann ist `plain` Standard).

Wenn etwas anderes benötigt wird - z.B. falls Text in JavaScript Code eingebunden ist - kann dies über `encode` gesteuert werden. Bei `plain` wird der Text unverändert ausgegeben.

Für Details zu den anderen Formaten, einfach den Links in der nachstehenden Tabelle folgen:

|  |  |
| --- | --- |
| `html` | [HtmlEncode](/books/cms-handbuch-entwickler/page/htmlencode) |
| ``` url ``` | [UrlEncode](/books/cms-handbuch-entwickler/page/urlencode)<br>mit Projekt-Zeichensatz |
| ``` javascript ``` | Non-Strict<br>[ScriptEncode](/books/cms-handbuch-entwickler/page/scriptencode) |
| ``` entitymask ``` | [HtmlMask](/books/cms-handbuch-entwickler/page/htmlmask) |
| ``` xml ``` | [XmlEncode](/books/cms-handbuch-entwickler/page/xmlencode) |

## Ausgabe maskieren (veraltet)

** Deprecated - Veraltetes Feature**
Die hier aufgeführten Informationen beziehen sich auf eine veraltete Funktion, die nicht mehr weiterentwickelt wird und ggf. in zukünftigen Versionen nicht mehr unterstützt wird. Diese Funktion sollte deshalb nicht mehr benutzt werden.

```xml
<bx:text.{titel} [urlencode | inscript | htmlmask | unmodified] />
```

Falls `encode` nicht angegeben ist, kann die Maskierung kann auch mittels Flags gesteuert werden. Dabei gelten foldende Zuordnungen zwischen den Flags hier und `encode` oben:

| Flag | `encode` |
| --- | --- |
| ``` urlencode ``` | ``` url ``` |
| ``` inscript ``` | ``` javascript ``` |
| ``` htmlmask ``` | ``` entitymask ``` |
| ``` unmodified ``` | ``` plain ``` |

# bx:textarea

Das Tag `textarea` stellt in der Verwaltung ein Eingabefeld für einen beliebigen, mehrzeiligen Text zur Verfügung.

```xml
<bx:textarea.{bezeichner} [cols="<n>"] [rows="<n>"] [ small | medium | large | xlarge ] [comment="<text>"] />
<bx:textarea.{bezeichner} [maxchars="<n>" | maxwords="<n>"] [type="plain"] [encode="htmltext"] [wrap="<wrap>"] />
<bx:textarea.{bezeichner} [imgloop="<schleife>"] [imgname="<text>"] [href="<text>"] [width="<n>"] [height="<n>"] />
```

Auf der Webseite wird der Text unformatiert dargestellt.

| cols | Breitenangabe |
| --- | --- |
| rows | Höhenangabe (Zeilen) |
| small<br>medium<br>lage<br>xlarge | \| Vorlage \| `cols` \| `rows` \| \| --- \| --- \| --- \| \| small \| 21 \| 5 \| \| medium \| 42 \| 8 \| \| large \| 63 \| 20 \| \| xlarge \| 63 \| 35 \| | Vorlage | `cols` | `rows` | small | 21 | 5 | medium | 42 | 8 | large | 63 | 20 | xlarge | 63 | 35 |
| Vorlage | `cols` | `rows` |
| small | 21 | 5 |
| medium | 42 | 8 |
| large | 63 | 20 |
| xlarge | 63 | 35 |
| comment | in der Verwaltung kann zusätzlicher Text angezeigt werden, z.B. für Erklärungen. |
| maxchars | nur angegebene Zeichenanzahl vom Text ausgeben z.B. für Anmoderationen<br>gibt ganze Worte, so weit wie möglich, aus |
| maxwords | nur angegebene Wortanzahl vom Text ausgeben z.B. für Anmoderationen |
| type="plain" | erweiterter Editor für dieses Textfeld wird in der Verwaltung deaktiviert<br>erweiterbar mit<br>**`encode="htmltext"`** |
| encode="htmltext" | zeigt plain-Feld in Verwaltung aber macht <br>s im Frontend rein |
| wrap="wrap" | Art des Zeilenumbruchs des Textfeldes in der Verwaltung,<br>Standardwert ist hier virtual. (siehe auch<br><a href="http://de.selfhtml.org/html/formulare/eingabe.htm#bereiche_umbruch" target="_blank">SELFHTML Dokumentation</a><br>) |

### Beispiele

**Code:**

```xml
<bx:textarea.Seitentext large comment="Dieser Text steht direkt unter der Überschrift."/>
```

**Ansicht in der Verwaltung** (Formatierungen werden über den zweiten Balken oben vorgenommen):

![image2015-4-10 8:17:45.png](attachments/3506265/3506274.png)

.......

![image2015-4-10 8:15:26.png](attachments/3506265/3506270.png)

**Ansicht auf der Seite:**

![image2015-4-10 8:32:55.png](attachments/3506265/3506277.png)

## Bilder mittels Platzhalter einfügen

Über den Button "Bild einfügen" in der <a href="http://wiki.batix.net/index.php/Toolbar" target="_blank">Toolbar</a> können Sie Platzhalter für Grafiken einfügen. Es besteht dann die Möglichkeit diese Platzhalter durch Bilder zu ersetzen, die in einer <a href="http://wiki.batix.net/index.php/Bx:schleife" target="_blank">Schleife</a> festgelegt sind.

Legen Sie dazu im Quelltext der Seite ein <a href="http://wiki.batix.net/index.php/Bx:schleife" target="_blank">Bx:schleife</a> Tag an, welches ein <a href="http://wiki.batix.net/index.php/Bx:bild" target="_blank">Bx:bild</a> Tag enthält. Damit die Schleife an sich nicht auf der Webseite ausgegeben wird, setzen Sie den Parameter `showmax` der Schleife auf 0. Zusätzlich muss im Textfeld der Paramater `imgloop` spezifiziert werden. `imgname` beschreibt den Titel des <a href="http://wiki.batix.net/index.php/Bx:bild" target="_blank">Bx:bild</a> Tags in der Schleife. Jetzt können Sie die Seite im <a href="http://wiki.batix.net/index.php/Projektmen%C3%BC" target="_blank">Projektmenü</a> bearbeiten und in der Schleife die gewünschten Bilder einfügen. Die Platzhalter im Text werden dann der Reihe nach durch die Bilder der Schleife ersetzt.

Um eine einheitliche Größe der Bilder festzulegen kann `width` und/oder `height` angegeben werden. Falls eine Verlinkung stattfinden soll muss der Parameter `href` gesetzt werden.

Deutlich wird das Ganze an einem <a href="http://wiki.batix.net/index.php/Bx:textarea/Beispiele" target="_blank">Beispiel</a>.

### Beispiele

**Code:**

```xml
<bx:schleife.bilder showmax="0">
  <bx:bild.DemoBild/>
</bx:schleife.bilder>
<bx:textarea.demotextarea medium imgloop="bilder" imgname="DemoBild" width="200" height="100" />
```

**In der Administration:**

![image2015-4-10 8:31:40.png](attachments/3506265/3506275.png)

**Auf der Seite:**

![image2015-4-10 8:32:15.png](attachments/3506265/3506276.png)

**Bilder verlinken**

Durch Hinzufügen von `href="bilder.htm"` zum `<bx:textarea>`, weglassen von `<bx:schleife.bilder showmax="0">` und stattdessen Erstellung eines Detail-Templates wie "bilder.htm" im nächsten Beispiel, werden die einzelnen Bilder im Text auf die jeweilige Detailseite verlinkt.

### Beispiele

In diesem zweiten Beispiel ist das Bild auf eine Detailseite mit Großansicht verlinkt. In diesem Fall fällt die Definition der Schleife in der Hauptseite weg.

Die Darstellung des Bildes in der Hauptseite kann durch Textbausteine flexibler definiert werden. Hierzu wird in `<bx:textarea>` Parametern namens `left`, `center` und/oder `right` der Name eines Textbaustein-Templates zugewiesen. In diesen Templates wird nur der Ersatz-Code für den Platzhalter im Eingabefeld geschrieben. Im Beispiel-Textbaustein "Bild-links" wird nur das Bild mit umgebenden div-Tag angezeigt. Im Beispiel "Bild-rechts" wird zusätzlich eine Bildunterschrift angegeben

**Code in Hauptseite "index.htm"**

```xml
<bx:textarea.demotextarea medium imgloop="bilder" left="Bild-links" right="Bild-rechts" />
```

**Code in Bilder-Detailseite "bilder.htm"**

```xml
...
<bx:schleife.bilder>
  <h1><bx:text.DemoBildName/></h1>
  <bx:bild.DemoBild width="640" height="480"/>
  <bx:textarea.BildBeschreibung medium/>
</bx:schleife.bilder>
...
<bx:loop.showprevious schleife="Bilder">vorheriges Bild</bx:loop.showprevious> |
<a href="index.htm">zurück zum Artikel</a> | 
<bx:loop.shownext schleife="Bilder">nächstes Bild</bx:loop.shownext>
...
```

**Textbaustein "Bild-links"**

```xml
<div style="float:left;padding:2px">
  <a href="bilder.htm?bilder=<bx:loop.id/>"><bx:bild.DemoBild width="200" height="200"/></a>
</div>
```

**Textbaustein "Bild-rechts"**

```xml
<div style="float:right;padding:2px">
  <a href="bilder.htm?bilder=<bx:loop.id/>"><bx:bild.DemoBild width="150" height="300"/></a><br>
  <a href="bilder.htm?bilder=<bx:loop.id/>"><small><bx:text.DemoBildName/></small></a>
</div>
```

# bx:titel

<p class="callout warning">**Erweitertes Tag** Das Tag `titel` ist eine Erweiterung von **[bx:text](/books/cms-handbuch-entwickler/page/bx-text)**. Alles was in **[bx:text](/books/cms-handbuch-entwickler/page/bx-text)** möglich ist, ist auch hier möglich (evtl. Änderungen sind weiter unten angegeben). 
Neue Funktionen, die auf dieser Seite angegeben sind, können nur in diesem Tag verwendet werden, nicht in **[bx:text](/books/cms-handbuch-entwickler/page/bx-text)**.</p>

Die einzige Änderung besteht darin, dass der Titel des Tags "loopTitel" ist und das Eingabefeld in der Administration eine Größe von 40 Zeichen hat.

```xml
<bx:titel/>
```

# bx:tools

Das Tag `tools` vereint kleine Hilfen, um häufig auftretende Aufgaben zu vereinfachen.

## Hilfsmittel für Requestparameter

### tools.request

```xml
<bx:tools.request name="{param}" />
<bx:tools.request name="{param}" [value="{text}"] [not]> Inhalt </bx:tools.request>
```

Es wird ein Request-Parameter ausgegeben oder dieser ausgewertet.

Die erste Form gibt den Inhalt von `<param>` aus, falls vorhanden.
In der zweiten Form wird der Tag-Inhalt nur ausgegeben, wenn der Request-Parameter existiert, oder, falls zusätzlich "value" angegeben ist, einen bestimmten Wert enthält. Die Bedingung ist mit not umkehrbar.
Eine vergleichbare Funktion beinhaltet [bx:pagedata](/books/cms-handbuch-entwickler/page/bx-pagedata).

### tools.listrequest

```xml
<bx:tools.listrequest [include="{filter}" | exclude="{filter}"] />
```

Alle Parameter aus dem Request werden als Formularfelder vom Typ "hidden" in die Seite geschrieben.
Falls nur bestimmte Request-Parameter ausgegeben (include) oder bestimmte Parameter ausgeschlossen (exclude) werden sollen, können diese als Komma-getrennte Liste angegeben werden (z.B.: include="artikelID,kundenID").

### tools.querystring

```xml
<bx:tools.querystring [include="{filter}" | exclude="{filter}"] />
```

Diese Funktion wandelt alle Request-Parameter in einen QueryString um. 
Falls nur bestimmte Request-Parameter umgewandelt (include) oder bestimmte Parameter ausgeschlossen (exclude) werden sollen, können diese als Komma-getrennte Liste angegeben werden (z.B.: exclude="counter,index").

## Kodierung (Encodings)

### tools.htmlencode

```xml
<bx:tools.htmlencode> Inhalt </bx:tools.htmlencode>
```

Der Tag-Inhalt wird HTML-kodiert. Wenn man nur `< > & "` encoden möchte, muß man `<bx:tools.xmlencode>` nehmen.
Es werden folgende Ersetzungen vorgenommen:

| Originalwert | ausgegebener Wert |
| --- | --- |
| < | \&lt; |
| > | \&gt; |
| " | \&quot; |
| & | \&amp; |
| ' | \&#039; |
| äöüÄÖÜß§€,<br>deutsche Anführungszeichen unten und oben<br>und langen Bindestrich |  |
| alles ab<br><a href="https://de.wikipedia.org/wiki/American_Standard_Code_for_Information_Interchange#ASCII-Tabelle" target="_blank">ASCII-Code</a><br>128 | zu "&#[code];" |

### tools.urlencode

```xml
<bx:tools.urlencode [charset="{set}"]> Inhalt </bx:tools.urlencode>
```

Es wird eine URL-Kodierung des Tag-Inhalts vorgenommen. 
Mit dem Parameter `charset` kann eine andere Zeichenkodierung angegeben werden (Standard ist "iso-8859-1"). Es wird <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/net/URLEncoder.html#encode%28java.lang.String,%20java.lang.String%29" target="_blank">java.net.URLEncoder</a> benutzt.

### tools.urlpathencode

```xml
<bx:tools.urlpathencode [charset="{set}"]> Inhalt </bx:tools.urlencode>
```

<span style="color: rgb(0,0,0);"><span style="color: rgb(0,0,0);"><span style="color: rgb(0,0,0);">Zum Kodieren von Pfadbestandteilen (z. B. Dateiname). </span>Führt ein URL-Encoding des Tag-Bodys aus. Mit dem Parameter 'charset' kann ein anderes Encoding angegeben werden (Standard=iso-8859-1). Zum encoden wird </span><a href="http://download.oracle.com/javase/6/docs/api/java/net/URLEncoder.html?is-external=true#encode(java.lang.String, java.lang.String)" target="_blank">`URLEncoder.encode(String, String)`</a><span style="color: rgb(0,0,0);"> verwendet.</span>

</span>

### tools.entityencode

```xml
<bx:tools.entityencode> Inhalt </bx:tools.entityencode>
```

Es werden alle Zeichen mit einem ASCII-Code > 127 (0x80) in die Form &#nnn; gebracht, wobei nnn für den ASCII-Code in dezimaler Schreibweise steht.
*Ab v2.5.9 werden auch eventuelle Steuerzeichen (0x00-0x1F) entfernt.*

### tools.xmlencode

```xml
<bx:tools.xmlencode> Inhalt </bx:tools.xmlencode>
```

Dieses Tag führt zunächst ein .htmlencode aus und lässt das Ergebnis nochmals durch .entityencode laufen. *
*Ab v2.5.9 werden auch eventuelle Steuerzeichen (0x00-0x1F) entfernt.**

### tools.removectrlchars

```xml
<![CDATA[<bx:tools.removectrlchars> Inhalt mit seltsamen Zeichen </bx:tools.removectrlchars>]]>
```

Dieses Tag entfernt eventuelle Steuerzeichen (0x00-0x1F, außer Tab und Zeilenumbruch). Das Ergebnis kann dann innerhalb eines CDATA-Blocks verwendet werden (ab Version 2.5.9).

### tools.html2plain

```xml
<bx:tools.html2plain> Inhalt </bx:tools.html2plain>
```

Der Inhalt wird zunächst durch `.htmlencode` umgewandelt, danach werden folgende Ersetzungen vorgenommen:

| **Originalwert** | **ausgegebener Wert** |  | **Originalwert** | **ausgegebener Wert** |
| --- | --- | --- | --- | --- |
| \r | *nichts* |  | \n | *Leerzeichen* |
| \<br> | \r\n |  | \<br /> | \r\n |
| \<BR> | \r\n |  | \<p> | \r\n\r\n |
| *`<sonstige Tags>`* | *nichts* |  | \&nbsp; | *Leerzeichen* |
| \&uuml; | ü |  | \&Uuml; | Ü |
| \&auml; | ä |  | \&Auml; | Ä |
| \&ouml; | ö |  | \&Ouml; | Ö |
| \&szlig; | ß |  | \&quot; | " (gerade Anführungsz. oben) |
|  |  |  |  |  |
| \&lt; | < |  | \&gt; | > |
| \&amp; | & |  | \&bdquo; | " (dopp. Anführungsz. unten) |
| \&ldquo; | " (dopp. Anführungsz.oben) |  | \&#150; | - (Breite n) |
| \&hellip; | ... |  | \&ndash; | - (Breite n) |
| \&euro; | € |  | \&acute; | ´ |
| \&rsquo; | ' |  | \&sect; | § |

Zuletzt wird noch eventueller Whitespace am Anfang und Ende des Textes entfernt.

### tools.plain2html

```xml
<bx:tools.plain2html> Inhalt </bx:tools.plain2html>
```

<span style="color: rgb(71,71,71);">Wandelt den plain-Text im body in HTML-Code um, indem er HTML encoded wird und bei jeden Zeilenumbruch ein <br> oder <br/> gesetzt wird</span>

### Wirkungsweise

`<bx:tools.plain2html>Erste
Zeile
Zweite
Zeile
Dritte
Zeile
Vierte
Zeile
Fünfte
Zeile</bx:tools.plain2html>`

Wird zu

`«Erste
Zeile<br>
Zweite
Zeile<br>
Dritte
Zeile<br>
Vierte
Zeile<br>
F&uuml;nfte Zeile»`

### tools.csvfield

```xml
<bx:tools.csvfield> Inhalt </bx:tools.csvfield>
```

Der Text wird mit " umgeben und allen " im Text wird ein zusätzliches " vorangestellt. (ab v2.5.9)

### tools.scriptencode

```xml
<bx:tools.scriptencode> Inhalt </bx:tools.scriptencode>
```

Diese Funktion dient zum Encoden eines Textes, damit dieser direkt als String in JavaScript verwendet werden kann. (ab v2.5.9)

| Originalwert | ausgegebener Wert |
| --- | --- |
| \n | \\\n |
| \r | \\\r |
| " | \\" |
| ' | \\' |
| \t | \\\t |

Zusätzlich wird jeder Backslash (\), der nicht zum Escapen verwendet wird (also **nicht** vor folgenden Zeichen steht: n r t " ') verdoppelt.

### tools.scripteventencode

```xml
<bx:tools.scripteventencode > Inhalt </bx:tools.scripteventencode >
```

Hier wird ein String so encoded, dass er direkt als Event-Code für ein HTML-Element festgelegt werden kann. (ab v2.5.9)

| Originalwert | ausgegebener Wert |
| --- | --- |
| \n | \\\n |
| \r | \\\r |
| & | \&amp; |
| " | \&quot; |
| ' | \\' |
| \t | \\\t |
| \ | \\\ |

### tools.umlautencode

```xml
<bx:tools.umlautencode > Inhalt </bx:tools.umlautencode >
```

Deutsche Umlaute werden hier in die Schreibweise mit normalen Buchstaben überführt. (ab v2.5.9)

| Originalwert | ausgegebener Wert |
| --- | --- |
| ß | ss |
| Ä | Ae |
| ä | ae |
| Ö | Oe |
| ö | oe |
| Ü | Ue |
| ü | ue |

### tools.mysqlencode

```xml
<bx:tools.mysqlencode>Gasthaus 'Zur Tanne'</bx:tools.mysqlencode>

```

Escaped einige Zeichen, die für SQL-Injections verwendet werden könnten. (ab v2.5.9) 
Beispiel im Quellcode: wird in `Gasthaus \'Zur Tanne\'` umgewandelt

### tools.mysqlencodeall

```xml
... WHERE KEYWORDS LIKE '%<bx:tools.mysqlencodeall><bx:pagedata.request name="suche"></bx:tools.mysqlencodeall>%' ...

```

Escaped einige Zeichen, die für SQL-Injections verwendet werden könnten (auch % und _). (ab v2.5.9) 
Dies ist zur Verwendung in einem SQL-`LIKE`-Befehl gedacht (siehe Quellcode)
Das %-Zeichen ist im LIKE ein Platzhalter für beliebig viele Zeichen. Ohne diesen Befehl würde z. B. im LIKE-Ausdruck `WHERE Feld LIKE '100%'` alles gefunden werden, das mit "100" beginnt.

## Sonstige Tools

### tools.lastmodified

```xml
<bx:tools.lastmodified [pattern="{format}"] />

```

Gibt Datum/Zeit der letzten Änderung des aktuellen Menüpunktes aus (Meta-Wert "dataPublished" oder "contentPublished"). 
Das Format der Ausgabe lässt sich über [`pattern` ](/books/cms-handbuch-entwickler/page/pattern-bei-datum)steuern (Standard ist "dd.MM.yyyy HH:mm").

### tools.positiontracker

```xml
<bx:tools.positiontracker [boundary="{text}"] [showall] [startlevel="{n}"] />

```

Für Breadcrumb. Es wird ein Position-Tracker in die Seite geschrieben. Die übergeordneten Menüpunkte werden jeweils mit einer entsprechenden Anzahl von "../" verlinkt.

| boundary | Text zwischen den einzelnen Ausgaben (Standard-Wert ist " >> ") |
| --- | --- |
| showall | auch inaktive<br>Hauptmenüpunkte<br>werden ausgegeben |
| startlevel | Angabe, wenn in einem anderen Level gestartet werden soll (Hauptmenü = Level 0) |

### Beispiele

```xml
<bx:tools.positiontracker boundary=" | " startlevel="1"/>
```

Ausgabe der Menüpunkte ab der 2. Ebene, Trenner ist ein Pipe-Zeichen zwischen zwei Leerzeiche.

### tools.datum

```xml
<bx:tools.datum [show="{month-begin | month-end}" |
                [year="{mod}"] [month|month1="{mod}"] [day="{mod}"] [hour="{mod}"] [minute="{mod}"] [second="{mod}"]]
                [locale="{lang}"] [pattern="{format}"] />

```

Dieses Tag kann benutzt werden, um das aktuelle oder ein bestimmtes Datum auszugeben. Das Datum kann auch manipuliert werden (siehe bei <a href="http://docs.batix.info/display/DEVS/bx%3Arecordfield#bx:recordfield-Datumsmanipulation" target="_blank">bx:recordfield</a>)
**Achtung:** Monate laufen von 0-11

| show | **month-begin**: 1. des aktuellen Monats (0.00.00) **month-end**: letzter des aktuellen Monats (23.59.59)<br>ohne Angabe von show: jetzt |
| --- | --- |
| year<br>month<br>day<br>hour<br>minute<br>second | mit diesen Parametern kann ein Datum manipuliert werden **n**: das entsprechende Feld wird auf den Wert **n** gesetzt **+n**: das entsprechende Feld wird um den Wert **n** erhöht **-n**: das entsprechende Feld wird um den Wert **n** verringert |
| locale | Sprachformatierung (z.B. "de" oder "en_US")<br>`locale` sollte immer angegeben werden, da sonst die Standardeinstellung vom Server genutzt wird, die sich aber nach Updates oder Umzügen ändern kann. |
| month1 | wie bei month, aber beginnt nicht bei 0 sondern bei 1, d.h. bei month1="1" wird Januar und nicht Februar ausgegeben |
| pattern | legt die<br>[Formatierung des Datums](/books/cms-handbuch-entwickler/page/pattern-bei-datum)<br>fest (Standard ist "dd.MM.yyyy") |

### Beispiele

```xml
<bx:tools.datum/>									<-- "heute", z.B. 08.06.2014 -->
<bx:tools.datum pattern="d. MMM yy HH:mm:ss"/>		<-- "jetzt" wird ausgegeben, z.B. 3. Feb 12 13:42:55 -->
<bx:tools.datum show="month-end" pattern="dd"/>		<-- Tag des Monatsende vom aktuellen Monat, z.B. beim Aufruf im Februar: 28 -->
<bx:tools.datum lang="en_US"/>						<-- Ausgabe von "heute" im US-Format, z.B. 2001-07-04 -->
xml
<bx:tools.datum month="+1" day="1"/> 							<-- nächster Monats-Erster -->
<bx:tools.datum month=+1 day=1 hour=-24"/>						<-- Monatsletzter   --> 
<bx:tools.datum day="+7"/>										<-- in einer Woche -->
<bx:tools.datum day="-1" hour="12" minute="0" second="0"/>		<-- gestern Mittag -->
<bx:tools.datum year="-1" month="11" day="31"/>					<-- Silvester letztes Jahr -->
```

### tools.timeframe

```xml
<bx:tools.timeframe after="{zeit}" before="{zeit}" week="{bits}" [not] [now={...}]> Inhalt </bx:tools.timeframe>

```

Zeigt den Inhalt an, wenn die aktuelle Serverzeit in einem bestimmten Rahmen liegt. Wenn before kleiner als after ist, wird der Uhrzeitbereich außerhalb der Angaben verwendet (ab v2.6.8. - vorher wäre es nie ausgeführt worden, weil keine Uhrzeit vor 7 und nach 20 Uhr sein kann)

| after | wird im 24h-Format angegeben (HH:mm) |
| --- | --- |
| before | wird im 24h-Format angegeben (HH:mm) |
| week | Angabe als eine sogenannte Bitmaske, d.h. jede Stelle steht für einen Tag.<br>So steht z.B. "1111100" für<br>*nur werktags*<br>oder "1010100" für<br>*montags, mittwochs, freitags*<br>. |
| not | zur Umkehrung der Uhrzeitangaben. Es beeinflußt nur die Uhrzeit und nicht den Parameter '<br>`week`<br>' |
| now | Mit dem Parameter `now` kann man eine andere Uhrzeit testen, ohne bis zu dieser Uhrzeit warten zu müssen. (siehe Beispiel 3) |

### Beispiele

**Beispiel 1**

```xml
<bx:tools.timeframe after="06:00" before="18:00" week="1000000">Wir haben geöffnet.</bx:tools.timeframe>
```

Inhalt wird nur Montags von 6.00 bis 18.00 Uhr angezeigt.

**Beispiel 2**

```xml
<bx:tools.timeframe before="6:00" after="18:00">Wir haben geschlossen.</bx:tools.timeframe>
```

entspricht: `<bx:tools.timeframe not before="18:00" after="6:00">`

**Beispiel 3**

```xml
<bx:tools.timeframe after="22:00" now="7.3.2018 22:01">Bettruhe!!!</bx:tools.timeframe>
```

### tools.for / tools.forchar

```xml
<bx:tools.for start="{n}" end="{n}" [inkrement="{n}"]> Inhalt </bx:tools.for>	<!-- für Zahlen -->
<bx:tools.forchar start="{zeichen}" end="{n}"> Inhalt </bx:tools.forchar>		<!-- für Buchstaben -->

```

Dieses Tag führt den Inhalt einer Schleife mehrfach aus und ersetzt jedesmal einen Platzhalter durch eine laufende Nummer. 
Im Inhalt des Tags können dann "{i}" und "{ii}" verwendet werden (ii = vorangestellte 0, wenn kleiner als 10)

| start | Startet bei angegebener Zahl<br>bzw. angegebenem Zeichen (z.B.<br>` a`<br>) |
| --- | --- |
| end | Endet bei angegebener Zahl bzw. angegebenem Zeichen (z.B.` z`) |
| inkrement | der Wert, um den erhöht werden soll (Standard: 1)<br>falls<br>`start`<br>><br>`end`<br>ist, muss hier eine negative Zahl eingetragen werden! |

### Beispiele

```xml
<bx:clipboard.cut name="anzTage"><bx:tools.datum show="month-end" pattern="dd"/></bx:clipboard.cut>
<select>
  <bx:tools.for start="1" end="clipboard:anzTage">
    <option value="{ii}">{i}</option>
  </bx:tools.for>
</select>
```

Die Tage des aktuellen Monats (Anzahl wurde vorher mit `bx:tools.datum` ermittelt und in einem [Clipboard ](/books/cms-handbuch-entwickler/page/bx-clipboard)zwischengespeichert) werden in einem Drop-Down ausgegeben (value mit vorangestellter 0, wenn unter 10)

```xml
Ergebnisse finden beginnend mit:<br>
|
<bx:tools.forchar start="A" end="Z">
  <a href="suche.act?init={i}">{i}</a>|
</bx:tools.forchar>

```

Es wurd eine verlinkte Buchstabenleiste  mit den Großbuchstaben von "A" bis "Z" erzeugt.

### tools.for-split

```xml
<bx:tools.for-split source="[Daten]" regex="[Trenner]" clipboard="[key]" attribute="[key]" placeholder="[Platzhalter]"> Auswertung mit [Platzhalter] </bx:tools.for-split>

```

Dieses Tag führt den Inhalt einer Schleife mehrfach aus und ersetzt jedesmal einen Platzhalter durch eine laufende Nummer. 
Im Inhalt des Tags können dann "{i}" und "{ii}" verwendet werden (ii = vorangestellte 0, wenn kleiner als 10)

| source | Quelle |
| --- | --- |
| regex | Angabe des Trenners, z.B. Komma, Leerzeichen oder Semikolon |
| clipboard | Wert kann wird im Clipboard gespeichert |
| attribute | Wert kann wird im Request-Attribute gespeichert |
| placeholder | Es kann ein anderer Platzhalter definiert werden, ansonsten lautet der Platzhalter {i} |

### Beispiele

```xml
<bx:tools.for-split source="Hallo Welt" regex=" "> :{i}: </bx:tools.for-split>
```

<span style="color: rgb(71,71,71);">ergibt " :Hallo: :Welt: "</span>

```xml
<bx:clipboard.cut name="idliste">AAA,BBB,CCC</bx:clipboard.cut>
<bx:tools.for-split source="clipboard:idliste" regex="," clipboard="einzelneID">
<bx:record id="clipboard:einzelneID">
 ... <bx:recordfield...> ... 
</bx:record>
</bx:tools.for-split>

```

### tools.random

```xml
<bx:tools.random/>												<-- zufälliger double-Wert zwischen 0 und 1, ca. 15 Nachkommastellen -->
<bx:tools.random max="{zahl}"/>									<-- zufälliger int-Wert zwischen 0 und {zahl} -->
<bx:tools.random chance="{zahl}"> [Inhalt] </bx:tools.random>	<-- zeigt den Inhalt mit der Wahrscheinlichkeit von {zahl} Prozent an (1≤{zahl}≤99) -->

```

Dieser Befehl zeigt eine Zufallszahl an bzw. zeigt einen Inhalt mit einer bestimmten Wahrscheinlichkeit an.

### tools.randstring

```xml
<bx:tools.randstring [length={len}] [lower] [upper] [num] [alphanum] [extra] [extra2] [all] />

```

Dieser Befehl erzeugt einen zufälligen String aus bestimmten Charakter-Klassen. Dies ist z.B. für Passwortgenerierung nützlich.

<p class="callout warning">Es muss mindestens eine Charakter-Klasse angegeben werden.</p>

| length | Länge des zu erzeugenden Strings (Standard 12 Zeichen) |
| --- | --- |
| lower | Kleinbuchstaben a-z |
| upper | Großbuchstaben A-Z |
| num | Ziffern 0-9 |
| alphanum | lower + upper + num |
| extra | ! ? - _ ( ) + * \ / \| $ ~ # @ |
| extra2 | < > { } [ ] " § % & ' ^ ° ; . : = |
| all | alphanum + extra + extra2 |

### Beispiele

```xml
<bx:tools.randstring length=10 alphanum/>
```

Es wird ein Paßwort mit 10 Zeichen erzeugt, das Groß- und Kleinbuchstaben sowie Zahl enthält.

### tools.uuid

```xml
<bx:tools.uuid />

```

Hiermit wird eine zufällige UUID (Typ 4) erzeugt (z.B. f3910a2f-63cf-433b-8117-1ac0d22bb4f5).

### tools.id

```xml
<bx:tools.id />

```

Dieses Tag erzeugt eine neue Batix-ID und gibt diese aus (z.B. 12E241E47CB).

## Fehlersuche (Debugging)

### tools.showrequest

```xml
<bx:tools.showrequest/>

```

Erzeugt eine Debug-Ausgabe des Request-Typs sowie sämtlicher Parameter, die im Request enthalten sind.

### tools.duration

```xml
<bx:tools.duration save="{name}"/>
<bx:tools.duration show="{name"/>

```

Erzeugt eine Debug-Ausgabe der Bearbeitungszeit einer im Aufbau befindlichen Seite.

| save | Anfang der Zeitmarke wird gesetzt<br>Durch die Benennung sind mehrere Zeitmarken möglich |
| --- | --- |
| show | verstrichene Zeit seit `save` wird angezeigt (in Sekunden mit 3 Nachkommastellen) Weitere `show`-Tags liefern fortlaufende Messungen. |

### Beispiele

```xml
<html>
  <head></head>
  <body>
    ... Quelltext ...
    <bx:tools.duration save="dauer1"/>
    ... komplizierte SQL ...
    Verarbeitungsdauer SQL1: <bx:tools.duration show="dauer1"/>
    <bx:tools.duration save="dauer2"/>
    ... zu vergleichende SQL ...
    Verarbeitungsdauer SQL2: <bx:tools.duration show="dauer2"/>
    ... Quelltext ...
  </body>
</html>
```

Für beide SQL-Aufrufe wird die Ausführungszeit gemessen und ausgegeben - ein direkter Vergleich ist möglich.

### tools.log

```xml
<bx:tools.log level="{stufe}" [copy]>zu loggender Text</bx:tools.log>

```

Schreibt den Inhalt in die Logdatei, anstatt in die Seite.

| level | Logstufe<br>`error`<br>,<br>`warn`<br>,<br>`info`<br>oder<br>`debug`<br>Standard:<br>`info` |
| --- | --- |
| copy | Text soll auch auf der Seite angezeigt werden |

### Beispiele

```xml
<bx:tools.duration save="dauer"/>
... aufwändige Filterungen ...
<bx:tools.log>Verarbeitungsdauer: <bx:tools.duration show="dauer"/></bx:tools.log>
```

Die Zeit, die die "aufwändige Filterung" braucht, wird in die Log-Datei geschrieben

## Zeichenketten-Funktionen

### tools.replacetext

##### Ersetzen-Modus

```xml
<bx:tools.replacetext regex="<ausdruck>" replacement="<text>"> Inhalt </bx:tools.replacetext>

```

Es wird nach bestimmten Ausdrücken im Tag-Inhalt gesucht und diese werden durch den gewünschten Text ersetzt.
Es wird die Java-Methode <a href="http://docs.oracle.com/javase/8/docs/api/java/lang/String.html#replaceAll-java.lang.String-java.lang.String-" target="_blank">String.replaceAll</a> verwendet, dadurch ergeben sich vielfältige Möglichkeiten.

| regex | regulärer Ausdruck, nach dem im Text gesucht werden soll |
| --- | --- |
| replacement | Ersetzungs-Text |

### Beispiele

```xml
<bx:tools.replacetext regex="World" replacement="Batix">Hello, World!</bx:tools.replacetext>
```

Hier wird aus "Hello, World!" der Text "Hello, Batix!"

```xml
<bx:tools.replacetext regex="(.+?),(.+?),(.+?)" replacement="Wert 2=$2; Wert 1=$1; Wert 3=$3">
  Alice,123,ABC
</bx:tools.replacetext>
```

Umwandeln von CSV-Daten: Das Ergebnis wäre hier der Text "Wert 2=123; Wert 1=Alice; Wert 3=ABC".

```xml
<bx:clipboard.cut name="temp"><a href="$1">$1<a></bx:clipboard.cut>
<bx:tools.replacetext regex="(http://[^\ ]+)" replacement="clipboard:temp">
  Einen Text mit http://einer.url/zu/einem Text mit einem Link machen.
</bx:tools.replacetext>
```

Um in einen Text mit einer URL einen Link um die URL einzufügen: Das bx:clipboard wird benötigt, weil im replacement-Parameter die Zeichen ", < und > nicht verwendet werden können. *ab v2.5.9*

*Allgemeine Hilfe und Beispiele zu regulären Ausdrücken gibt es u.a. auf <a href="http://www.regular-expressions.info" target="_blank">http://www.regular-expressions.info</a> (englisch). *

##### Schleifen-Modus

```xml
<bx:tools.replacetext regex="<ausdruck>" source="<quelle>">
  Inhalt
</bx:tools.replacetext>
```

Durch die Angabe von `source` schaltet das Tag in den Schleifen-Modus. Hierbei wird der Tag-Inhalt für jeden Match ausgeführt. Ausgaben, die im Tag-Inhalt erfolgen werden ignoriert (stattdessen kann ein Clipboard geschrieben werden, um den Match zu modifizieren). Es werden Informationen (Match-Index, Match-Gruppen) über Clipboards bereitgestellt, der gematchte Text kann so auch ersetzt / verändert werden.

Folgende Clipboards werden pro Durchlauf gesetzt:

| Clipboard-Name | Beschreibung |
| --- | --- |
| replacetext_match | Der komplette gematchte String.<br>In dieses Clipboard kann im Tag-Inhalt auch geschrieben werden, die gematchte Textstelle wird nach jedem Durchlauf mit dem Inhalt dieses Clipboards ersetzt. |
| replacetext_index | Laufende Nummerierung der Matches, beginnend bei Null.<br>Im ersten Durchlauf steht also "0" im Clipboard, danach "1", usw.. |
| replacetext_group_`<n>` | `<n>` ist eine Zahl<br>Für jede Gruppe des Regexes (mit runden Klammern umschlossen) werden die gematchten Textstellen pro Durchlauf in nummerierte Clipboards gepackt, wobei - wie bei Regex üblich - replacetext_group_0 noch mal den kompletten Match enthält, replacetext_group_1 die erste Gruppe, replacetext_group_2 die zweite usw.. |

Man kann sich den Tag-Inhalt wie eine Funktion vorstellen, die pro Match aufgerufen wird: Parameter werden über die Clipboards übergeben, der Rückgabewert läuft auch über ein Clipboard (replacetext_match).

### Beispiele

Batix Quelltext:

```xml
<bx:clipboard.cut name="zutaten" trim>
300#g#Mehl
5##Eier
150#ml#Milch
</bx:clipboard.cut>
<bx:tools.replacetext regex="(\d+)#([^#]+)?#(.*)" source="clipboard:zutaten">
  1 = Anzahl
  2 = Einheit
  3 = Zutat
  <bx:clipboard.cut name="replacetext_match">
    Zutat <bx:clipboard.paste name="replacetext_index" />:
    <bx:clipboard.paste name="replacetext_group_3" />
    (<bx:clipboard.paste name="replacetext_group_1" />
    <bx:clipboard.paste name="replacetext_group_2" />)
    <br>
  </bx:clipboard.cut>
</bx:tools.replacetext>
```

Ausgabe:

```xml
Zutat 0: Mehl (300 g)
Zutat 1: Eier (5 )
Zutat 2: Milch (150 ml)
```

Erkärung:

- Der zu durchsuchende Text wird in das Clipboard "zutaten" geschrieben, welches als `source` an `replacetext` übergeben wird.
- Der Regex lautet: `(\d+)#([^#]+)?#(.*)`
  1. Gruppe: `\d+` (nur Ziffern)
  2. `[^#]+` (alles außer #)
  3. `.*` (egal was)
- Beispielhaft die Clipboards im ersten Durchlauf:

|  |  |
| --- | --- |
| replacetext_match | 300#g#Mehl |
| replacetext_index | 0 |
| replacetext_group_0 | 300#g#Mehl |
| replacetext_group_1 | 300 |
| replacetext_group_2 | g |
| replacetext_group_3 | Mehl |
- Nach dem Durchlauf wird in das Clipboard "replacetext_match" zurückgeschrieben, was die Zeile im Original ersetzt.
- Hinweis: Da die zweite Gruppe mit einem Fragezeichen quantifiziert ist, ist sie optional. Im zweiten Durchlauf (die 5 Eier) ist das Clipboard "replacetext_group_2" also leer.

### tools.uppercase

```xml
<bx:tools.uppercase> bring mich gross raus </bx:tools.uppercase>

```

Wandelt alle Buchstaben im Body in Großbuchstaben um und gibt diese aus.

### tools.lowercase

```xml
<bx:tools.lowercase> jetzt werd ich ganz klein </bx:tools.lowercase>

```

Wandelt alle Buchstaben im Body in Kleinbuchstaben um und gibt diese aus.

### tools.substring

```xml
<bx:tools.substring maxlength="{Zahl}" [startindex="{Zahl}"] [fillbefore="{ein Zeichen}" | fillafter="{ein Zeichen}"]>

```

Schneidet aus dem übergebenen Tagbody den durch Indexpositionen angegebenen Bereich heraus und gibt nur diesen zurück.

| maxlength | muß mindestens 1 sein |
| --- | --- |
| startindex | Stelle, ab wann der Substring herausgelöst werden soll (startet mit 0)<br>Standard: 0 (bei Fehlen des Parameters) |
| fillbefore<br>fillafter | optionales Füllzeichen (keine Entity)<br>wenn Text kürzer ist als bei<br>`maxlength`<br>angegeben, wird er mit dem angegeben Zeichen aufgefüllt |

### Beispiele

```xml
<bx:tools.substring maxlength="5" startindex="6">Hello World</bx:tools.substring> 
```

Gibt "World" aus

```xml
<bx:tools.substring maxlength="5" fillbefore="0">7318</bx:tools.substring>
```

 gibt "07318" aus (wenn z. B. PLZ als Zahl gespeichert ist und demzufolge nur 4 Ziffern hat)

### bx:tools.trim

```xml
<bx:tools.trim [lines] [spaces] [single-line]> Inhalt </bx:tools.trim>

```

Entfernt alle Whitespace-Zeichen (Zeilenumbrüche, Leerzeichen, Tabulator) am Anfang  und Ende des inneren Bereiches

| lines | reduziert mehrfache Zeilen zu einem Einzelnen (siehe Beispiel) |
| --- | --- |
| spaces | <span style="color: rgb(0,0,0);"> reduziert mehrfache Leerzeichen zu einem einzelnen</span> |
| single-line | <span style="color: rgb(0,0,0);">entfernt alle Zeilenumbrüche und schreibt alles leerzeichengetrennt in eine Zeile</span> |

### Beispiele

```xml
<bx:tools.trim lines>   Hallo

 

 

          Welt

                         </bx:tools.trim>
```

reduziert mehrfache Zeilenumbrüche zu einem Einzelnen würde also nur „Hallo“ und darunter „Welt“ schreiben

## Links erzeugen

### tools.absoluteurl

```xml
<bx:tools.absoluteurl> Pfadangabe </bx:tools.absoluteurl>

```

Erzeugt aus dem relativen URL-Pfad im Tag-Body eine absolute URL und schreibt sie anstelle des Tags in die Seite.

### Beispiele

```xml
<bx:tools.absoluteurl>../test.htm</bx:tools.absoluteurl>
```

Im Beispiel würde das Tag in der Seite durch eine URL "http[s]://{hostname}/www/{pfad}/test.htm" ersetzt werden, die auf die Seite test.htm im übergeordneten Menüpunkt verweist.

### tools.rooturl

```xml
<bx:tools.rooturl> Pfadangabe </bx:tools.rooturl>

```

Erzeugt aus dem relativen URL-Pfad im Tag-Body eine absolute URL und schreibt einen absoluten Pfad beginnend mit "/" anstelle des Tags in die Seite.

### Beispiele

```xml
<bx:tools.rooturl> ../test.htm</bx:tools.rooturl>
```

Im diesem Beispiel würde das Tag in der Seite durch eine URL "/www/{pfad}/test.htm" ersetzt werden, die auf die Seite test.htm im übergeordneten Menüpunkt verweist.

# bx:userdata

Das Tag `userdata` gibt seinen Inhalt abhängig vom Status des angemeldeten Benutzers aus (z.B. für Intranetbereiche).

## userdata.in/userdata.login

```xml
<bx:userdata.in> Inhalt </bx:userdata.in>
<bx:userdata.login> Inhalt </bx:userdata.login>
```

Inhalt wird nur ausgeführt, wenn der User eingeloggt ist.

## userdata.out/userdata.logout

```xml
<bx:userdata.out> Inhalt </bx:userdata.out>
<bx:userdata.logout> Inhalt </bx:userdata.logout>
```

Inhalt wird nur ausgeführt, wenn der User ausgeloggt ist.

## userdata.id

```xml
<bx:userdata.id />
```

Die ID des Benutzers wird zurückgegeben.

## userdata.name

```xml
<bx:userdata.name />
```

Der vollständige Name (Anrede + Vorname + Nachname) wird ausgegeben.

## userdata.email

```xml
<bx:userdata.email />
```

Die Email-Adresse des Users wird ausgegeben.

## userdata.isintrauser

```xml
<bx:userdata.isintrauser [not]> Inhalt </bx:userdata.isintrauser>
```

Der Inhalt wird ausgeführt, wenn der Benutzer ein bzw. kein Intranetuser ist. Er wird nicht ausgeführt, wenn der Benutzer nicht eingeloggt ist oder einen höheren Status als Intranetuser besitzt. 
`not` kehrt die Funktionalität um, d.h. nur Intranetusern wird der Inhalt vorenthalten.

## userdata.ismember

```xml
<bx:userdata.ismember groupid="{ID}" [nosv] [not]> Inhalt </bx:userdata.ismember>
```

Dieses Tag prüft, ob der Benutzer einer bestimmten Gruppe angehört. Supervisoren werden automatisch als gruppenzugehörig erkannt. Falls kein Benutzer angemeldet ist, wird "nicht angemeldet" angezeigt.

| groupid | einzelne Gruppen-ID oder eine Liste von IDs, getrennt durch Komma |
| --- | --- |
| nosv | Supervisoren werden nicht als gruppenzugehörig erkannt |
| not | kehrt Bedingungen um. |

## userdata.issupervisor

```xml
<bx:userdata.issupervisor [not]> Inhalt </bx:userdata.issupervisor>
```

Wird ausgeführt wenn User ein Supervisor ist bzw. wenn er kein Supervisor ist. Es wird nie ausgeführt, wenn kein User eingeloggt ist. (ab v2.5.8)

## userdata.isbatix

```xml
<bx:userdata.isbatix [not]> Inhalt </bx:userdata.isbatix>
```

Block wird ausgeführt, wenn User ein Batix-Wartungszugang ist bzw. wenn nicht. Es wird nie ausgeführt, wenn kein User eingeloggt ist.

## userdata.issystemadmin

```xml
<bx:userdata.issystemadmin [not]> Inhalt </bx:userdata.issystemadmin>
```

Block wird ausgeführt, wenn User ein System-Supervior ist bzw. wenn nicht. Es wird nie ausgeführt, wenn kein User eingeloggt ist.

## userdata.username

```xml
<bx:userdata.username/>
```

Gibt den Username des angemeldeten Benutzers zurück.

## userdata.meta

```xml
<bx:userdata.meta name="{metaname}" />															<!-- Wert der Metaeigenschaft wird ausgegeben (falls vorhanden) -->
<bx:userdata.meta name="{metaname}" [value="{wert}"] [not]> Inhalt </bx:userdata.meta>			<!-- Bedingung: Inhalt wird getestet -->
```

Dieser Befehl gibt Metadaten des angemeldeten Benutzers aus oder zeigt Inhalte abhängig von Metadatenwerten an. Falls der Benutzer nicht angemeldet ist, zeigt das Tag nichts an.

| name | Name der Metaeigenschaft<br>ohne value: Ob Metaeigenschaft überhaupt vorhanden ist |
| --- | --- |
| value | Vergleichswert der Megaeigenschaft. Bei Übereinstimmung wird Inhalt ausgewertet<br>ohne value: Ob Metaeigenschaft überhaupt vorhanden ist |
| not | kehrt die Bedingung um |

# bx:userrecord

Das Tag `userrecord` erzeugt eine Schleife aus den Datensätzen einer Liste, in denen ein Wert der ID des angemeldeten Users entspricht. Ist kein Benutzer angemeldet, macht dieses Tag nichts.

## Vergleich mit einem Feld im Container

```xml
<bx:userrecord pool="{id}" field="{feld}" [dummy]> Inhalt </bx:userrecord>
<bx:userrecord pool="{id}" field="{feld}" [type="id"] [seperator="{,}{;"][dummy] />
```

Hier wird der Inhalt des Datensatz-Feldes `<feld>` mit der UserID verglichen - aber ACHTUNG! keine BC-Verknüpfung sondern ein Textfeld, wo die ID drin steht.
Falls kein Inhalt angegeben wurde, wird der Titel des Datensatzes ausgegeben.

Ab V 2.7.0: Das Feld "field" kann auch eine BC-Verknüpfung sein.

| pool | ID des Containers |
| --- | --- |
| field | BC-Verknüpfungs-Feld (das die ID des eingeloggten Users enthalten kann) |
| dummy | falls kein User angemeldet ist oder kein passender Datensatz gefunden wurde,<br>wird ein Dummy-Datensatz angezeigt |
| type="id" | Ausgabe der DS-IDs |
| seperator="," | Trenner zwischen den IDs (siehe Beispiel) |

### Beispiele

```xml
<bx:userrecord pool="Merkliste" field="BC" type="id" separator="," orderby="Nachname" desc />

```

Alle dem User zugeordneten Datensatz-IDs aus Merkliste mit Komma getrennt in die Seite schreiben

```xml
<bx:userrecord pool="Mitarbeiter" field="BC" type="id" />

```

Vom erstbesten (und hoffentlich einzigen) Datensatz aus Mitarbeiter, dem der eingeloggte User zugeordnet ist, die Datensatz-ID in die Seite schreiben

(mit zusätzlichen orderby kann man auch den ersten im Alphabet oder mit desc den Neuesten nehmen)

## Vergleich mit einer Metaangabe im Datensatz

```xml
<bx:userrecord pool="{id}" name="{meta}" [dummy]> Inhalt </bx:userrecord>
<bx:userrecord pool="{id}" name="{meta}" [dummy] />
```

Falls kein Inhalt angegeben wurde, wird der Titel des Datensatzes ausgegeben.

| pool | ID des Containers |
| --- | --- |
| name | erhält hier den Name eines Meta-Wertes der Datensätze,<br>dessen Inhalt wird dann mit der UserID verglichen. |
| dummy | falls kein User angemeldet ist oder kein passender Datensatz gefunden wurde,<br>wird ein Dummy-Datensatz angezeigt |

### Beispiele

```xml
Eingeloggt als: <bx:userrecord pool="Mitarbeiter" name="mitarbeiterID"><bx:recordfield.Vorname/> <bx:recordfield.Name/></bx:userrecord>
```

Im Datensatz des Containers "Mitarbeiter" gibt es eine Meta-Angabe namens "mitarbeiterID", in der die Datensatzid des Users steht.

## Datensatzid als Metaangabe beim User gespeichert

```xml
<bx:userrecord pool="..." meta="..." [dummy]>...</bx:userrecord>
```

Der Container-Datensatz, dessen ID im Meta-Wert 'meta' des Users steht oder nichts falls dort keine ID steht.

### Beispiele

```xml
Eingeloggt als: <bx:userrecord pool="Mitarbeiter" meta="mitarbeiterID"><bx:recordfield.Vorname/> <bx:recordfield.Name/></bx:userrecord>
```

Beim User gibt es eine Meta-Angabe namens "mitarbeiterID", in der die Datensatzid des zugehörigen Datensatzes im Container "Mitarbeiter" steht.

# bx:validation

Das Tag `validation` kann Fehlermeldungen einer Containervalidation auswerten und so die Anzeige von Fehlertexten möglich machen. Es ist verfügbar ab *Version 2.5.8*

## validation.error

```xml
<bx:validation.error field="{feldname}" data="{validationsfeldname}" [code="{n}"]> ... </bx:validation.error>
```

Dieser Befehl zeigt den Body des Tags an, wenn das angegebene Feld im Validations-Fehlerfeld aufgelistet ist.

**field:** Name des zu prüfenden Feldes

**data:** Feldname im Container, wo die Validierung als xml gespeichert ist

**code:** zu prüfender Fehlercode. Es gibt folgende Fehlertypen:
- 1	(0x01) benötigtes Feld ist leer
- 2	(0x02) falscher Datentyp
- 4	(0x04) regulärer Ausdruck passt nicht
- 8	(0x08) Bedingung nicht erfüllt
<br><br>

  Falls mehrere Fehlertypen auftreten, werden die Zahlen vom [ValidationAction](/books/cms-handbuch-entwickler/page/containerinhalt-validieren) addiert.
**5** (0x05) bedeutet z.B.: Das Feld ist leer und der reguläre Ausdruck passt nicht.
Mit bx:valdiation können die Codes nun einzeln (code="1" und code="4") oder
kombiniert (code="5") abgefragt werden.


## validation.haserror

```xml
<bx:validation.haserror data="{validationsfeldname}" [not]> ... </bx:validation.haserror>
```

Zeigt den Body an, wenn im Validationsfeld Fehler gelistet sind. Bei Verwendung von `not` wird der Body angezeigt, wenn keine Fehler gelistet sind.

## validation.errorcount

```xml
<bx:validation.errorcount data="{validationsfeldname}" />
```

Gibt die Anzahl der Validationsfehler aus.

# bx:websearch

Dieses Tag ermöglicht die Darstellung von Suchergebnissen der Webseite. Die Suche ist über die Funktionen des Jakarta Lucene Projektes realisiert worden. Das Web muss vorher indiziert worden sein.
 Zum Ausklammern von Bereichen aus der Suche verwendet man [bx:scanner](/books/cms-handbuch-entwickler/page/bx-scanner)

## Eingabefeld

```xml
<bx:websearch.input />
```

Es wird ein Text-Inputfeld erzeugt, welches in Suchformularen verwendet werden kann. Falls schon eine Suche stattgefunden hat, enthält das Feld den Suchtext.

## Hauptschleife

```xml
<bx:websearch [max="{n}"] [maxparam="{paramname}"] [indexparam="index"]> Inhalt </bx:websearch>
```

Dieses Tag bildet die Hauptschleife um die Suchergebnisse.
Zur Verwendung im Inhalt stehen die nun folgenden Tags bereit.

Bisher mußte der Blätterparameter „index“ heißen. Und bei den Containerfiltern (Teasern) in der Seite mußte man indexparam auf etwas anderes setzen. Nun kann der Parametername selbst definiert werden.
`<bx:websearch.previous|next|firstshown|lastshown>` lesen den neuen Parameter von der `<bx:websearch>`-Schleife und verlinken jetzt mit diesen Namen.

| max | maximale Anzahl an Ausgaben |
| --- | --- |
| maxparam | Request-Parameter, der den Zahlenwert für den Überlauf enthält<br>* (ab Version 2.5.9)* |
| indexparam | Name des Blätterparameters |

## websearch.title

```xml
<bx:websearch.title/>
```

gibt den Titel der Seite (`<title>` HTML-Tag) oder, falls dieser nicht existiert, "`<ohne Titel>`" aus

## websearch.rank

```xml
<bx:websearch.rank/>
```

Rangfolge des Ergebnisses, beginnend mit 1


## websearch.score

```xml
<bx:websearch.score/>
```

die Wertung des Suchergebnisses als Gleitkommazahl

## websearch.relevanz

```xml
<bx:websearch.relevanz/>
```

eine Wertung des Ergebnisses als Ganzzahl mit Prozentzeichen

## websearch.stars

```xml
<bx:websearch.stars [max="<n>"]> Inhalt </bx:websearch.stars>
```

Symbole als Relevanzanzeige ausgeben

| max | maximale Anzahl an Symbolen (Standard: 5)<br>Der Inhalt bestimmt das Symbol, er kann z.B. ein<br><a href="http://wiki.batix.net/index.php/Bx:bild" target="_blank">bx:bild</a><br>-Tag enthalten |
| --- | --- |

## websearch.link

```xml
<bx:websearch.link> Inhalt </bx:websearch.link>
<bx:websearch.link />
```

verlinkt den Inhalt mit der Fundstelle. Als geschlossenes Tag wird die URL verlinkt *(ab Version 2.5.9)*

## websearch.url

```xml
<bx:websearch.url/>
```

gibt die URL der Fundstelle an. *ab Version 2.5.8*

## websearch.path

```xml
<bx:websearch.path/>
```

gibt den Pfad zur Fundstelle an. Es handelt sich um die URL, deren Hostname abgeschnitten wurde. *ab Version 2.5.9*

## websearch.description

```xml
<bx:websearch.description/>
```

die Beschreibung des Dokuments (HTML `<meta>` Wert "description")


## websearch.navname

```xml
<bx:websearch.navname/>
```

der Name des entsprechenden Navigationspunktes

## websearch.navid

```xml
<bx:websearch.navid/>
```

die ID des entsprechenden Navigationspunktes

## websearch.previous

```xml
<bx:websearch.previous [hide] [url="{link}"] />
<bx:websearch.previous [hide] [url="{link}"]> Linktext </bx:websearch.previous>
```

(steht außerhalb der Schleife) einen Link zur vorigen Ergebnisseite generieren

| hide | es wird nichts ausgegeben wird, wenn es keine nächste Seite gibt |
| --- | --- |
| url | Ziel-Dateiname festlegen (Standard ist die aktuelle Seite) |
| Linktext | Ein Linktext kann als Tag-Inhalt angegeben werden (Standard: "weiter >>"). |

## websearch.next

```xml
<bx:websearch.next [hide] [url="{link}"] />
<bx:websearch.next [hide] [url="{link}"]> Linktext </bx:websearch.next>
```

(steht außerhalb der Schleife) einen Link zur nächsten Ergebnisseite generieren
**Parameter: siehe unter websearch.previous**

## websearch.totalhits

```xml
<bx:websearch.totalhits/>
```

(steht außerhalb der Schleife) Gesamtzahl der Ergebnisse

## websearch.firstshown

```xml
<bx:websearch.firstshown/>
```

(steht außerhalb der Schleife) Nummer des ersten Ergebnisses auf der Seite

## websearch.lastshown

```xml
<bx:websearch.lastshown/>
```

(steht außerhalb der Schleife) Nummer des letzten Ergebnisses auf der Seite

## websearch.query

```xml
<bx:websearch.query encode="typ"/>
```

(steht außerhalb der Schleife) der Begriff/Text, nach dem gesucht wurde

| encode | Hiermit kann der ausgegebene Text für verschiedene Formate kodiert werden:<br>- html - javascript - sql (zur Verwendung in SQL für Strings) - sql-like (zur Verwendung in SQL mit LIKE) - sql-rlike (zur Verwendung in SQL mit RLIKE und REGEXP) - url - xml |
| --- | --- |

## websearch.if

```xml
<bx:websearch.if [not] [empty | scrollable | morethan="<n>" | lessthan="<n>"] > Inhalt </bx:websearch.if>
```

(steht außerhalb der Schleife) zeigt Inhalt nur unter bestimmten Bedingungen an. Nur, wenn Suche bereits stattgefunden hat:
(Falls keiner der vier Parameter angegeben wurde, erfolgt die Ausgabe nur, wenn bereits eine Suche erfolgt ist (oder auch nich, bei `not`). )

| empty | es wurden keine Suchergebnisse gefunden<br>darf auch innerhalb der Schleife verwendet werden. Um das Gegenteil abzufragen, wird<br>`not`<br>verwendet. |
| --- | --- |
| scrollable | es sind mehr Seiten vorhanden (Anzahl Ergebnisse ><br>`max`<br>) |
| morethan<br>lessthan | es wurden mehr als<br>`<n>`<br>Ergebnisse gefunden<br>es wurden weniger als<br>`<n>`<br>Ergebnisse gefunden |

## Eingabefeld

```xml
<bx:websearch.input />
```

Es wird ein Text-Inputfeld erzeugt, welches in Suchformularen verwendet werden kann. Falls schon eine Suche stattgefunden hat, enthält das Feld den Suchtext.

### Beispiele

```xml
<bx:tag.feature param="value" />
```

Weitere Beispiele unter [Snippets/Websuche](/books/cms-handbuch-entwickler/page/websuche).

# bx:xml

*Ab Version 2.6.8*

Mit dem Tag `bx:xml` können XML Strukturen ausgelesen und einfach durchgegangen werden. Um schnell in tief verschachtelte Objekte zu gelangen, kann GPath genutzt werden.

## XML laden

```xml
<bx:xml data="[1, 2, 3]">...</bx:xml>
<bx:xml data="clipboard:xml_data">...</bx:xml>
<bx:xml url="http://server/..." [encoding="utf-8"]>...</bx:xml>
```

Das XML-Dokument kann entweder direkt als Text übergeben werden (wobei der Umweg über ein Clipboard oder Attribut möglich ist), es kann aber auch eine URL angegeben werden, von der die Daten geladen werden (`encoding` gibt dabei an, mit welchem Zeichensatz die Daten eingelesen werden, Standard ist utf-8).

<p class="callout info">Im URL-Modus sendet das XML-Tag nicht das Session-Cookie mit, da meist externe URLs aufgerufen werden und die SESSIONID nicht ausversehen preisgegeben werden soll.

Falls die Daten von einem internen, geschützten Menüpunkt geladen werden (auf den der aktuell eingeloggte Benutzer Zugriff hat), kann `<a href="http://docs.batix.info/display/DEVS/bx:jspinclude" target="_blank">bx:jspinclude</a>` verwendet werden - dieses schickt das Session-Cookie mit:

```xml
<bx:clipboard.cut name="xml_data"><bx:jspinclude>/intern/api.xml</bx:jspinclude></bx:clipboard.cut>
<bx:xmln data="clipboard:xml_data">
  ...
</bx:xml>
```</p>

Ist in den XML-Daten ein Objekt kodiert, kann dieses mit geschachtelten xml-Tags durchgegangen werden; ein Array über gleichnamige Tags kann simuliert werden.

Eine fortgeschrittenere Möglichkeit des Daten-Ladens, kann über das Attribut `application` realisiert werden. Hier gibt man den Name eines Application-Attributes an, in dem eine `Node` oder `NodeList` gespeichert ist. Dieses wird dann vom Tag benutzt und es entfällt das String-Parsen. Dies ist nützlich bei Caches, die man global in der Application vorhalten kann, und die sich nicht oft ändern. Ein entsprechendes Objekt kann z.B. mittels Groovys `XmlParser` erzeugt werden.

## XML durchgehen

Die XML-Struktur kann einfach via Tags durchgegangen werden:

```xml
<bx:xml data="..."> <!-- Root-Tag -->
  <bx:xml.Kunde> <!-- Sub-Tag -->
    Der Kunde heißt: <bx:xml.Vorname /> <bx:xml.Nachname />
    <bx:xml field="address_home">
      Er wohnt in: <bx:xml.Ort />
    </bx:xml>
  </bx:xml.Kunde>
</bx:xml>
```

Tag-Attribute können via @ angesprochen werden:

```xml
<!-- XML-Daten -->
...<age underage="false">18</age>...
 
<!-- Attribut age abfragen -->
...
<bx:xml.age@underage bool>Zutritt verboten!</bx:xml.age@underage>
...
```

Es ist jeweils die Angabe von `[encode=...](/books/cms-handbuch-entwickler/page/encodings-uebersicht)` möglich, um z.B. Ausgaben für URLs oder CSV zu encoden.

Das auszugebende Feld kann entweder im Tag-Titel (nach `bx:xml.`, also im Beispiel "Kunde") oder im Parameter `field=""` (oben z.B. "address_home") angegeben werden. Die Angabe via `field` ist nötig, falls der Feldname Sonderzeichen / Leerzeichen enthält.

Wird versucht auf ein Feld zuzugreifen, das nicht existiert, wird nichts ausgegeben. Es kann alternativ via `dummy` ein Alternativwert (als komplettes XML-Tag) angegeben werden, der stattdessen genommen wird.

```xml
<bx:clipboard.cut name="xmldummy">
  <object>
    <some></some>
    <item></item>
  </object>
</bx:clipboard.cut>
<bx:xml.missingObject dummy="clipboard:xmldummy">
  <bx:xml.some />
</bx:xml.missingObject>
```

Da XML-Tags (sowohl Root-Tags als auch Sub-Tags) mehrfach verschachtelt sein können und man manchmal Sachen von Über-Über-...-Elementen ausgeben will, kann man via Tag-Titel oder `name` die Tags benennen und via `base` diese referenzieren (der Parameter `name` hat beim Suchen des passenden Parent-Tags Vorrang vor dem Tag-Titel). Das entspricht der Funktionalität von `baseloop` bei Containern. Mittels `base="$"` kann das Root-Tag referenziert werden (das Tag, bei dem die Daten geladen wurden). Die Angabe von base kann immer zusätzlich zu allen anderen Parametern erfolgen (z.B. können `base` und `path` gleichzeitig benutzt werden).

```xml
<bx:xml data="..."> <!-- Root-Tag -->
  <bx:xml.Sub>
    <bx:xml.SubSub name="Kunde">
      <bx:xml.SubSubSub>
        <bx:xml.Feld base="Sub">
          <!-- selber Kontext, als wenn man direkt innerhalb von <bx:xml.Sub> wäre -->
        </bx:xml.Feld>
        <bx:xml.Feld base="Kunde">
          <!-- selber Kontext, als wenn man direkt innerhalb von <bx:xml.SubSub> wäre -->
        </bx:xml.Feld>
        <bx:xml.Feld base="$">
          <!-- selber Kontext, als wenn man direkt innerhalb des Root-Tags wäre -->
        </bx:xml.Feld>
      </bx:xml.SubSubSub>
    </bx:xml.SubSub>
  </bx:xml.Sub>
</bx:xml>
```

Je nach Datentyp muss ein entsprechender Parameter im bx:xml-Tag übergeben werden, da XML an sich keine Datentypen kennt (Schemas werden nicht unterstützt):

### Null

Der Inhalt wird ausgeführt (oder nicht bei `not`), falls im XML das gesuchte Feld nicht vorhanden ist. Es wird hier auch der Spezialtyp `nil` einer XML-Schema-Instanz beachtet.

```xml
<! -- Feld in XML nicht enhalten oder als nil mit korrektem Namespace markiert -->
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <mynull xsi:nil="true" />
</root>
 
<bx:xml.Feld null>Feld war nicht vorhanden oder nil</bx:xml.Feld>
<bx:xml.Feld null not>Feld war vorhanden und nicht nil</bx:xml.Feld>
```

### Boolean

Boolesche Werte können ähnlich wie Häkchenfelder im Container abgefragt werden. Eine kurze Version (geschlossenes Tag) mit `true` / `false` steht auch zur Verfügung.

```xml
<bx:xml.Condition bool [not]>
  ...
</bx:xml.Condition>
 
<bx:xml.Condition bool [true=""] [false=""] />
```

Um dem booleschen Wert `true` zu entsprechende, muss der Feldwert einer der folgenden Strings sein:

- true
- wahr
- yes
- y
- ja
- j
- on
- x
- 1
- 1.0

### Number

Zahlen (mit und ohne Dezimalstellen) können via `num` angesprochen werden. Das Tag erwartet als Dezimaltrenner einen Punkt. Die Angabe von `comma` bewirkt, dass vorher ein Komma im Feldwert durch einen Punkt ersetzt wird.

#### ausgeben / formatieren

Zahlen können formatiert ausgegeben werden. Ist kein `pattern` angegeben, werden Ganzzahlen *ohne* und Kommazahlen *mit* Nachkommastellen ausgegeben. Der Tausender- und Dezimal-Trenner kann mittels `gs` bzw. `ds` spezifiziert werden. Der Rundungsmodus ist standardmäßig HALF_UP (normales kaufmännisches Runden) und kann via `rounding` geändert werden (<a href="https://docs.oracle.com/javase/8/docs/api/java/math/RoundingMode.html" target="_blank">siehe Java-Docs für mögliche Werte</a>). ).

```xml
<bx:xml.Zahl num [comma] [pattern=""] [locale=""] [gs=""] [ds=""] [rounding=""] />
```

 `locale` sollte immer angegeben werden, da sonst die Standardeinstellung vom Server genutzt wird, die sich aber nach Updates oder Umzügen ändern kann.

#### vergleichen

Folgende Vergleiche sind möglich:

| Parameter | ausgeführter Vergleich |
| --- | --- |
| equals | == |
| gt | > |
| gte | >= |
| lt | < |
| lte | <= |

Das Ergebnis kann jeweils mit `not` umgekehrt werden. Für alle Vergleiche ist auch eine verkürzte Variante mit `true` / `false` möglich (hier wird der jeweilige Wert von `true` oder `false` ausgegeben).

```xml
<bx:xml.Zahl num [comma] [equals=""] [gt=""] [gte=""] [lt=""] [lte=""] [not]>
</bx:xml.Zahl>
 
<bx:xml.Zahl num [comma] [equals=""] ... [true=""] [false=""] />
```

### Date

Über den Tag-Parameter `date` wird der vorhande String-Wert im Feld als Datum interpretiert.

#### Eingabeformat

Ist lediglich `date` ohne weiteren Wert im Tag angegeben, werden einige Standard-<a href="https://docs.oracle.com/javase/8/docs/api/java/text/SimpleDateFormat.html" target="_blank">Patterns</a> unterstützt:

```xml
<bx:xml.mydate date />
```

Es wird folgende Liste in dieser Reihenfolge durchprobiert:

- `dd.MM.yy HH:mm:ss`
- `dd.MM.yy HH:mm`
- `dd.MM.yy HH.mm`
- `dd.MM.yy`
- `yyyy-MM-dd'T'HH:mm:ssZ` (<a href="https://de.wikipedia.org/wiki/ISO_8601" target="_blank">ISO 8601</a>)

Alternativ kann ein eigenes Pattern angegeben werden:

```xml
<bx:xml.mydate date="dd/MM/yyyy" />
```

Es muss nicht der gesamte String matchen. Möchte man z.B. aus dem Wert "20.08.2018 um 08:50" nur das Datum ziehen, genügt das Pattern `dd.MM.yyyy`.

#### Ausgabeformat

Standardmäßig wird das geparste Datum anhand des Patterns `dd.MM.yyyy HH:mm:ss` ausgegeben. Es kann auch ein eigenes Pattern angegeben werden:

```xml
<bx:xml.mydate date pattern="dd.MM. HH:mm" />
```

Werden z.B. Tages- oder Monatsnamen ausgegeben, wird über `locale` die gewünschte Sprache eingestellt:

```xml
<bx:xml.mydate date pattern="EEEE, d. MMMM" locale="de" />
```

#### Datum/Zeit modifizieren

Durch die Angabe von verschiedenen Parametern können alle Teile des Ausgangsdatums angepasst werden. Es kann eine Zahl angegeben werden, um den entsprechenden Wert absolut zu setzen. Dabei kann dieser Zahl ein Plus (`+`) oder Minus (`-`) vorangestellt werden, um die Modifikation stattdessen relativ durchzuführen. Die möglichen Parameter sind (werden auch in dieser Reihenfolge angewandt):

- year
- month (im Bereich 1 - 12)
- day
- weekday (s.u.)
- hour
- minute
- second

Etwaige Überschreitungen (z.B. +15 Monate) werden entsprechend weiter gezählt (also +1 Jahr und 3 Monate).

Beispiel (Tag auf den 15. Februar setzen, zwei Stunden dazu zählen, zehn Jahre abziehen):

```xml
<bx:xml.mydate date day="15" month="2" hour="+2" year="-10" />
```

Mögliche Werte beim Wochentag sind dabei folgende Werte (keine Zahlen erlaubt):

- mo / di / mi / do / fr / sa / so
- mon / tue / wed / thu / fri / sat / sun

Es wird auf den entsprechenden Wochentag in der gleichen Woche gewechselt. Auch hier gibt es die Möglichkeit ein Plus oder Minus voranzustellen, dann wird entsprechend auf den Tag in der nächsten bzw. vorherigen Woche gewechselt.

Trifft der angegebene Wochentag bereits auf das Ausgangsdatum zu, wird das Datum nicht geändert. Dieses Verhalten kann durch Angabe eines doppelten Plus (`++`) oder Minus (`--`) überschrieben werden (es wird dann auch gewechselt, falls der Wochentag schon zutrifft).

#### Zeitliche Abfrage

Eine weitere Funktion ist die Abfrage, ob das Ausgangsdatum (bzw. das modifizierte Datum) vor oder nach dem jetzigen Zeitpunkt (Zeit auf dem Server) bzw. heute liegt. Der Unterschied ist, dass beim Vergleich mit **heute** die Uhrzeit nicht beachtet wird, sondern nur der Datumsteil.

Die folgenden Abfragen sind möglich:

- before-now
- after-now
- before-today
- after-today
- today (ist am heutigen Tag)

Das Tag kann dabei entweder offen (optional noch mit `not`) oder geschlossen mit den `true` und/oder `false` Parametern genutzt werden. Beispiele:

```xml
<bx:xml.mydate date before-now>in der Vergangenheit</bx:xml.mydate>
<bx:xml.mydate date after-now not>auch in der Vergangenheit oder genau jetzt</bx:xml.mydate>
 
<bx:xml.mydate date before-today true="vor heute" />
<bx:xml.mydate date after-today false="vor heute oder heute" />
 
<bx:xml.mydate date today true="am heutigen Tag" false="nicht heute" />
```

### String

#### ausgeben

Im einfachsten Fall wird der String ausgegeben und ggf. automatisch encoded (siehe [Encodings](/books/cms-handbuch-entwickler/page/encodings-uebersicht) für andere Encoding-Möglichkeiten).

```xml
<bx:xml.Text />
```

#### vergleichen

Strings können auch verglichen werden. Die Angabe von `ignoreCase` bewirkt, dass Groß-/Kleinschreibung nicht beachtet wird, `not` kehrt das Ergebnis um.

| Parameter | Vergleich |
| --- | --- |
| matches | Vergleich via RegEx (regulärem Ausdruck),<br>String muss diesem komplett entsprechen |
| equals | Gleichheit |
| contains | der String muss den Wert das Parameters beinhalten |

Auch hier ist eine verkürzte Variante mit `true` und `false` möglich.

```xml
<bx:xml.Text [matches=""] [equals=""] [contains=""] [ignoreCase] [not]>
</bx:xml.Text>
 
<bx:xml.Text [matches=""] [equals=""] [contains=""] [ignoreCase] [true=""] [false=""] />
```

#### BatixRecord

Steht in den XML-Daten im Feld eine Batix-ID, so kann hier auch ein Container angebunden werden. Das Tag verhält sich dann wie `bx:record`, es können innerhalb die normalen Container-Tags wie `bx:recordfield` oder `bx:recorddata` benutzt werden. Auch der Zugriff von außerhalb des Tags mit z.B. `bx:recorddata.nav` ist möglich.

Der Datensatz wird anhand des Feldes ID rausgesucht. Es kann aber auch via `linkfield` auf ein anderes Feld im Datensatz verwiesen werden (Text oder Einzelverknüpfung), hierbei wird der erste gefundene Datensatz genommen.

Wird kein Datensatz mit entsprechender ID (oder Wert im Feld) gefunden, wird nichts ausgegeben. Die Angabe von `dummy` bewirkt, dass stattdessen ein leerer Datensatz vorgehalten wird (der Tag-Inhalt wird ausgeführt, innere `bx:recordfield`-Tags etc. geben aber nichts aus, wie bei `[bx:record](/books/cms-handbuch-entwickler/page/bx-record)`).

```xml
<bx:xml.IDFeld pool="Container" [linkfield=""] [dummy]>
  <bx:recordfield... />
  <bx:recorddata.if... />
</bx:xml.IDFeld >
 
<bx:recorddata.nav object="IDFeld">
  <bx:recorddata.total />
</bx:recorddata.nav>
```

### Array

Gleichnamige XML-Tags können mittels `array` in einer Schleife durchlaufen werden.

Ein Array funktioniert analog zu z.B. `bx:containerfilter`, für jedes Element wird der Tag-Inhalt einmal ausgeführt. Das Start-Element kann dabei mittels `index` (0-basiert) und die maximale Anzahl Durchläufe via `max` geregelt werden.

Um das aktuelle Element im Durchlauf auszugeben wird einfach `<bx:xml />` verwendet. Je nach Datentyp (in Arrays können auch verschiedene Datentypen vorhanden sein) können hier die entsprechenden Parameter und deren Funktionen verwendet werden (z.B. formatierte Ausgabe bei Zahlen).

```xml
<!-- XML Teil -->
<Liste>10</Liste>
<Liste>20</Liste>
<Liste>30</Liste>

<!-- durchgehen -->
<bx:xml.Liste array [index="20"] [max="10"]>
  <bx:xml />
</bx:xml.Liste>
```

Es können die meißten Funktionen von `[bx:recorddata](/books/cms-handbuch-entwickler/page/bx-recorddata)` verwendet werden:

```xml
<bx:xml.Liste array>
  ...
</bx:xml.Liste>
<bx:recorddata.nav object="Liste">
  Gesamt: <bx:recorddata.total/><br>
  <bx:recorddata.navlist max="5">
    ...
```

Ferner gibt es noch folgende Hilfsmethoden:

```xml
<bx:xml.Liste array>
  <bx:xml {first|last} [not]>...</bx:xml> <!-- Inhalt nur ausführen, wenn es das erste oder letzte Element ist -->
  <bx:xml {first|last} [true=...] [false=...] /> <!-- dito, nur verkürzte true/false Schreibweise -->
  <bx:xml index [add="5"] /> <!-- aktuellen Durchlauf-Index ausgeben, ggf. etwas dazu addieren -->
  <bx:xml total /> <!-- Gesamtanzahl der Elemente ausgeben -->
  <bx:xml empty [not]>...</bx:xml> <!-- ausführen, falls das Array leer ist -->
  <bx:xml empty [true=...] [false=...] /> <!-- dito, nur mit true/false -->
  <bx:xml cols=...> <!-- funktioniert wie bx:recorddata.cols -->
</bx:xml.Liste>
```

Für mehr Informationen zu `cols` siehe die <a href="http://docs.batix.info/display/DEVS/bx:recorddata#bx:recorddata-recorddata.cols" target="_blank">entsprechende Passage bei `bx:recorddata`</a>.

#### Datensätze

Befinden sich im Array Strings, welche Batix-IDs sind, kann mittels `pool` eine Schleife über Datensätze (wie z.B. `bx:containerfilter`) aufgemacht werden. Falls die ID in einem anderen Feld steht, kann dies wieder via `linkfield` referenziert werden. Innerhalb des Xml-Tags sind alle normalen Datensatz-Tags verfügbar. `dummy` verhält sich im Falle eines leeren Arrays wie ein leerer Datensatz (ansonsten wird der Inhalt nicht ausgeführt).

Falls im Array (zusätzlich) nicht-Strings sind, wird im Log eine Warnung ausgegeben.

```xml
<bx:xml.Kunden array pool="Shop_Kunden" [linkfield=""] [dummy]>
  <bx:recordfield... />
  <bx:recorddata.if... />
</bx:xml.Kunden>
```

### Object

Um in ein XML-Objekt tiefer einzusteigen, wird das Xml-Tag (analog zu `bx:recordfield` bei Verknüpfungen) geschachtelt.

```xml
<bx:xml data="...">
  <bx:xml.Kunde>
    <bx:xml.Name />
  </bx:xml.Kunde>
</bx:xml>
```

## Namespaces

Namespaces werden ebenfalls grundlegend unterstützt (es kann nach dem Namespace-Präfix gesucht werden, der Namespace-Identifier (meist eine URI) wird ignoriert). Hierbei muss für den Feldname allerdings `field` benutzt werden, da der Doppelpunkt sonst Probleme macht:

```xml
<!-- XML Teil -->
<nstest>Namespace 0</nstest>
<ns1:nstest>Namespace 1</ns1:nstest>
<ns2:nstest>Namespace 2</ns2:nstest>

ohne: <bx:xml field="nstest" />
1: <bx:xml field="ns1:nstest" />
2: <bx:xml field="ns2:nstest" />
alle: <bx:xmL field="*:nstest" array>...</bx:xmL> <!-- Elemente ohne expliziten Namespace sind nicht enthalten -->
```

## GPath

Mittels GPath-Expressions können relativ einfach verschachtelte Strukturen angesprochen werden. Das erspart lästiges Verschachteln von Xml-Tags.

| Operator | Bedeutung |
| --- | --- |
| `*` | children |
| `**` | depth-first |

Beispiele:

```xml
<bx:xml path="mystring" />
<bx:xml path="mystring@name" />
<bx:xml path="mystring.@name" />
<bx:xml path="myobj.name" />
<bx:xml path="myobj.age@underage" />
<bx:xml path="myobj.age.@underage" />
<bx:xml path="**.@title" />
<bx:Xml path="**.@title" array>[<bx:xml />]</bx:Xml>
<bx:Xml path="*.@title" array>[<bx:xml />]</bx:Xml>
<bx:Xml path="myobj.*" array>[<bx:xml />]</bx:Xml>
```

# Actions

Alle Action-Bausteine (39 Seiten).

# Actions – Übersicht

<!-- last_modified: 11. Jan 2017 -->
Aktionen realisieren im Zusammenwirken mit Dokumentvorlagen an bestimmten Menüpunkten erforderliche Funktionalitäten - z.B. das Speichern von Formulardaten, das Versenden von Emails, das Anmelden bei einem Newsletter u.v.m.

![actions1.jpg](https://batix.help/uploads/images/gallery/2026-05/E06CrHmEqC1ghFLe-3932320.jpg)

## Übersicht

| Kategorie | Actions |
|-----------|---------|
| Speicherung | [Bild hochladen](/books/cms-handbuch-entwickler/page/bild-hochladen)<br>[Containerdaten aus Email importieren](/books/cms-handbuch-entwickler/page/containerdaten-aus-email-importieren)<br>[Dokument hochladen](/books/cms-handbuch-entwickler/page/dokument-hochladen)<br>[Formulardaten validieren](/books/cms-handbuch-entwickler/page/formulardaten-validieren) |
| Container | [Container kopieren](/books/cms-handbuch-entwickler/page/container-kopieren)<br>[Container-Filteraction](/books/cms-handbuch-entwickler/page/container-filteraction)<br>[Containerdaten speichern](/books/cms-handbuch-entwickler/page/containerdaten-speichern)<br>[Containerdatensatz löschen](/books/cms-handbuch-entwickler/page/containerdatensatz-loschen)<br>[Containerinhalt validieren](/books/cms-handbuch-entwickler/page/containerinhalt-validieren)<br>[Validierungsergebnis ausgeben](/books/cms-handbuch-entwickler/page/validierungsergebnis-ausgeben) |
| Benutzer und Zugang | [Benutzergruppe anlegen](/books/cms-handbuch-entwickler/page/benutzergruppe-anlegen)<br>[Intranet Login](/books/cms-handbuch-entwickler/page/intranet-login)<br>[Intranet Logout](/books/cms-handbuch-entwickler/page/intranet-logout)<br>[Intranet-User anlegen/ändern](/books/cms-handbuch-entwickler/page/intranet-user-anlegenandern)<br>[Passwort des angemeldeten Users ändern](/books/cms-handbuch-entwickler/page/passwort-des-angemeldeten-users-andern) |
| Versenden von E-Mails | [CMS-Seite versenden](/books/cms-handbuch-entwickler/page/cms-seite-versenden)<br>[Formular als Mail versenden](/books/cms-handbuch-entwickler/page/formular-als-mail-versenden) |
| Ausführung von Code | [Batix Quelltext ausführen](/books/cms-handbuch-entwickler/page/batix-quelltext-ausfuhren)<br>[JSP-Baustein ausführen](/books/cms-handbuch-entwickler/page/jsp-baustein-ausfuhren) |
| Sonstiges | [Captcha Abfrage](/books/cms-handbuch-entwickler/page/captcha-abfrage)<br>[Excel-Action](/books/cms-handbuch-entwickler/page/excel-action)<br>[Sicheres Formular überprüfen (SecureformAction)](/books/cms-handbuch-entwickler/page/sicheres-formular-uberprufen-secureformaction)<br>[Suche im Web](/books/cms-handbuch-entwickler/page/suche-im-web)<br>[Vorhandene Bedingung abfragen](/books/cms-handbuch-entwickler/page/vorhandene-bedingung-abfragen)<br>[Weiterleitung](/books/cms-handbuch-entwickler/page/weiterleitung)<br>[Wert in Session speichern](/books/cms-handbuch-entwickler/page/wert-in-session-speichern)<br>[XHTML 2 PDF](/books/cms-handbuch-entwickler/page/xhtml-2-pdf) |
| Veraltet | [Newsletter – Abo abmelden](/books/cms-handbuch-entwickler/page/newsletter-abo-abmelden)<br>[Newsletter – Abo ändern](/books/cms-handbuch-entwickler/page/newsletter-abo-andern)<br>[Newsletter – Abonnentenlogin](/books/cms-handbuch-entwickler/page/newsletter-abonnentenlogin)<br>[Newsletter aktivieren](/books/cms-handbuch-entwickler/page/newsletter-aktivieren)<br>[Newsletter – Newsletter abonnieren](/books/cms-handbuch-entwickler/page/newsletter-newsletter-abonnieren)<br>[Newsletter – Passwort vergessen (1)](/books/cms-handbuch-entwickler/page/newsletter-passwort-vergessen-1)<br>[Newsletter – Passwort vergessen (2)](/books/cms-handbuch-entwickler/page/newsletter-passwort-vergessen-2)<br>[Shop – Bestellung versenden](/books/cms-handbuch-entwickler/page/shop-bestellung-versenden)<br>[Shop – Hinzufügen zu Warenkorb](/books/cms-handbuch-entwickler/page/shop-hinzufugen-zu-warenkorb)<br>[Shop – Löschen im Warenkorb](/books/cms-handbuch-entwickler/page/shop-loschen-im-warenkorb)<br>[Shop – Zusatzgebühr zum Warenkorb](/books/cms-handbuch-entwickler/page/shop-zusatzgebuhr-zum-warenkorb) |

Abgesehen von oben angeführten Actionbausteinen können spezielle individuelle Aktionen unter Voraussetzung entsprechender Kenntnisse problemlos angelegt werden.

## Aktionsliste

Wenn Sie den Eintrag Ressourcen->Aktionen anklicken, erhalten Sie etwa folgende Seite im Arbeitsbereich:

![image2015-5-28 9:32:45.png](https://batix.help/uploads/images/gallery/2026-05/refUIKMvPJjEEitU-3932309.png)

Es werden Ihnen alle momentanen Aktionen mit folgenden Informationen angezeigt:

- der Titel der Aktion
- die Anzahl der in der Aktion vorhandenen Aktionsbausteine
- der Status der Aktion (Nur aktive Aktionen und Aktionsbausteine können angewendet werden. Deaktivierte Aktionen und Aktionsbausteine verursachen bei Verwendung einen Fehler.)

## Details der Aktion

Klicken Sie auf den Titel einer Aktion, um deren Bausteine einzusehen und allgemeine Einstellungen zur Aktion vorzunehmen.

![image2015-5-28 9:30:5.png](https://batix.help/uploads/images/gallery/2026-05/ejZKjkAuUpEc8oyi-3932307.png)

Hier können Sie:

- die Aktion aktivieren/deaktivieren
- einen Titel sowie eine kurze Beschreibung der Aktion eingeben (wird auf der Übersichtsseite und anderen Bestandteilen des CMS als Erläuterung ausgegeben)
- die Aktionsbausteine ändern:
  - Mittels "neuen Aktionsbaustein anhängen" generieren Sie assistengesteuert einen neuen Baustein (s.u.)
  - Mit einem Klick auf die Zeile wechseln Sie zur Detailansicht des gewählten Aktionsbausteines (s.u.).
  - Aktivieren/Deaktivieren Sie das Kontrollkästchen "ausführen", um die Nutzung des Bausteines festzulegen.
- In der Toolbox finden Sie die durch das CMS verwendete interne ID der Aktion, sowie eine Auflistung der Verwendungsarten und -orte.

## Neuen Aktionsbaustein anhängen

Um eine neue Aktion anzulegen, klicken Sie - wenn Sie sich in der Übersichtsseite aller Aktionen befinden - auf den Button ![image2017-1-11 9:24:13.png](https://batix.help/uploads/images/gallery/2026-05/amt3aquA52QYWahB-6226200.png)/![image2017-1-11 7:48:54.png](https://batix.help/uploads/images/gallery/2026-05/NVSwKZo1IA7GoBvW-6226202.png)in der Symbolleiste. Hier müssen Sie noch die Felder ausfüllen und die Aktion abspeichern (![image2017-1-11 9:23:40.png](https://batix.help/uploads/images/gallery/2026-05/tuqE1DnZam46fD2x-6226197.png)/![image2017-1-11 7:49:23.png](https://batix.help/uploads/images/gallery/2026-05/bx3vi4F63DPFJmVR-6226198.png)). Anschließend werden Sie aufgefordert, einen neuen Aktionsbaustein hinzuzufügen. Klicken Sie auf diese Zeile und Sie sehen folgenden Assistenten:

![image2015-5-28 9:25:4.png](https://batix.help/uploads/images/gallery/2026-05/Lg53wIuc82g7D1B9-3932305.png)

Klicken Sie auf den Auswahlbutton neben der gewünschten Aktion und anschließend zum Speichern auf ![image2017-1-11 9:23:40.png](https://batix.help/uploads/images/gallery/2026-05/tuqE1DnZam46fD2x-6226197.png)/![image2017-1-11 7:49:23.png](https://batix.help/uploads/images/gallery/2026-05/bx3vi4F63DPFJmVR-6226198.png).

## Details des Aktionsbausteins

Hier können Sie:

- den Baustein aktivieren/deaktivieren
- einen Titel sowie eine Kurzbeschreibung festlegen
- die Felder für die Inhalte des Aktionsbausteins bearbeiten (diese unterscheiden sich je nach Baustein erheblich)

# Batix Quelltext ausführen

<!-- last_modified: 15. Dec 2016 -->
Führt Batix Quelltext aus

Werte können mit `bx:pagedata.setscriptattribute` an den nächsten Action-Baustein übergeben werden.

```xml
<bx:pagedata.setscriptattribute name="<name>"> Inhalt </bx:pagedata.setscriptattribute>
```

Ausgabe im Log: &lt;bx:tools.log&gt;...&lt;/bx:tools.log&gt;

# Benutzergruppe anlegen

<!-- last_modified: 27. May 2015 -->
Dieses Action erzeugt eine neue Benutzergruppe.

## Parameter

| | |
|--|--|
| groupname | Feld mit Gruppennamen<br>Parametername des Feldes, in dem der Benutzergruppenname steht (nur angeben, wenn Anlegen einer Gruppe) |
| field-id | Parametername des Gruppen-ID-Feldes<br>Feldname mit dem die Benutzergruppen-ID übergeben wird (nur angeben, wenn Änderung einer Gruppe) |
| activate | Gruppe aktiv schalten, Standard: ja |
| attribute-groupid | Name für neue Gruppen-ID<br>Attributname, in dem die ID der neuen Gruppe gespeichert werden soll |

# Bild hochladen

<!-- last_modified: 22. Dec 2015 -->
Diese Aktion verschiebt eine hochgeladene Datei in die Dateiverwaltung. Dabei ist es wichtig, dass im Upload-Formular enctype="multipart/form-data" gesetzt ist.

## Parameter

| | |
|--|--|
| **fileparam** | gibt den Request-Parameter an, der die hochgeladene Datei enthält |
| **folderid** | falls das Bild in einen bestimmten Ordner der Bildergallerie gespeichert werden soll, kann hier die ID des Ordners angegeben werden |
| **folderparam** | eine Alternativmöglichkeit um das Bild in einen bestimmten Ordner zu speichern, die ID wird aus dem hier angegebenen Request-Parameter ausgelesen (Standard-Parametername ist "folderid") |
| **folderpath** | die dritte Möglichkeit zur Angabe des Ordners, hier wird der Name des Ordners angegeben |
| **targetweb** | um das Bild in ein anderes Projekt/Web zu speichern, hier die ID des Webs angeben |
| **titel** | mit diesem Parameter kann der Titel des Bildes festgelegt werden |
| **titelparam** | um den Titel aus einem Request-Parameter auszulesen, hier den Parametername angeben |
| **autor** | hiermit kann der Autor des Bildes direkt festgelegt werden |
| **autorparam** | der Autor kann alternativ auch über einen Parameter angegeben werden |

## Bemerkungen

Bei Werten, die durch verschiedene Parameter festgelegt werden können, gilt folgende Reihenfolge der Überprüfung (es wird dabei abgebrochen, sobald ein Wert gefunden wurde):

- **Ordner**: `folderid` -> `folderparam` (wenn nicht angegeben, dann Standardwert "folderid") -> `folderpath`
- **Titel**: `titel` -> `titelparam`
- **Autor**: `autor` -> `autorparam`

In den Metadaten des Bildes werden unter "uploader" und "author" der eingeloggte Benutzer (falls er eingeloggt ist) sowie unter "uploaderIP" die IP des Uploaders eingetragen.

## Multi-Upload (ab V 2.6.3)

Mehrere Bilder werden gleichzeitig mit HTML5 über ein Multiupload hochgeladen und in einem verknüpften Container gespeichert.
**Achtung**! Da die Bilder im Hintergrund gespeichert werden, muß es schon einen Eltern-Datensatz geben, d.h., der Upload-Actionbaustein kommt nach dem Speicher-Actionbaustein.

| | |
|--|--|
| url | weiterleitende URL (z. B. zu einem Save-Action) |

**Beispiel**

**Detailseite**

```xml
<form action="send.act" method="post" enctype="multipart/form-data">
  ...
  <input name="Bilder" type="file" multiple>
  <input type="submit">
</form>
```

**Formular bauen**, file-input-Feld muß den Parameter `multiple` haben

**Action bauen**: der Upload-Actionbaustein kommt nach dem Speicher-Actionbaustein

Angaben beim Upload-Actionbaustein:

- bei `fileparam` muß "Bilder" stehen (Name im Formular)
- bei `Scriptausführung je Bild: (url)` steht die Weiterleitung zu einem Speicheraction, das die einzelnen Bilder im Untercontainer speichert, z.B. `/www/beispielweb/menupunkt/savePic.act?Bild\=[[Bilder]]&Datum\=[[Datum]]&Bildergalerie\=[[galerieID]]`
  Im anschließenden savePic.act wird in einem Bildercontainer das Bild mit Bildergalerie-Verknüpfung(Elterndatensatz-Verknüpfung) und Datum gespeichert

# Captcha Abfrage

<!-- last_modified: 08. May 2018 -->
Diese Aktion prüft, ob der zum CAPTCHA-Bild eingegebene Text korrekt ist. Dazu muß auf der Seite ein Bild mit dem Namen SimpleCaptcha.jpg, das die visuelle Ausgabe enthält, und ein Input-Feld mit name="captcha" eingebunden sein.

## Parameter

| | |
|--|--|
| requestField | der Requestparameter, der die Antwort enthält (standardmäßig "j_captcha_response") |
| successpage | die Seite, auf die weitergeleitet wird, wenn die Antwort richtig ist |
| failpage | die URL, die bei falscher Antwort aufgerufen wird |
| appendRequest | gibt an, ob der aktuelle Request an die Folgeseite weitergegeben wird |

Ein verfremdetes Bild mit einer Zeichenfolge wird ausgegeben und muß in ein Eingabefeld geschrieben werden.

Quelltext dazu:

```xml
<div>
  <img src="/SimpleCaptcha.jpg<bx:pagedata.sessionurl/>" alt="Captcha-Bild">
  <bx:pagedata.request name="fehler" value="1">Die eingegebene Zeichenfolge war nicht korrekt.</bx:pagedata.request>
  <input type="text" name="captcha" value="">
</div>
```

Die Felder werden anlog des erstellten HTML-Designs ausgefüllt.

**Achtung:** Wenn das Captcha in einem IFrame verwendet wird, muß beim Bild und bei der Form &lt;bx:pagedata.sessionurl/&gt; angehängt werden.

Beispiel: &lt;form action="save.htm&lt;bx:pagedata.sessenurl/&gt;"&gt;...&lt;/form&gt;

# CMS-Seite versenden

<!-- last_modified: 24. Jan 2017 -->
Eine normale Seite im Projekt wird gelesen und dann als HTML-Email versendet.

Da diese Aktion auf [Formular als Mail versenden](/books/cms-handbuch-entwickler/page/formular-als-mail-versenden) aufbaut, sind alle dort angegebenen Parameter auch hier verwendbar, mit den unten aufgeführten Änderungen bzw. Neuerungen.

## Parameter

| | |
|--|--|
| mailFrom | Die Email-Adresse, unter der die Mail versandt wird. Falls beim Versenden ein Fehler auftritt oder auf diese Mail geantwortet wird, geht bei dieser Adresse eine Email ein. Bei Kontakt könnte hier auch email angegeben werden, dann kann auf diese Mail direkt geantwortet werden (nicht mehr verwenden). Besser ist jedoch Reply-To (Beschreibung ganz unten) zu verwenden. |
| mailFromName | Der im Email-Programm angezeigte Absendername (auch möglich z.B. [[Name]] [[Vorname]]) |
| mailTo | Der Empfänger der Email |
| subject | Der Betreff der Mail |
| file | Der virtuelle Dateiname des zu versendenden HTML-Designs |
| appendRequest | gibt an, ob der Request, welcher der Aktion übergeben wurde, an die URL der CMS-Seite angehängt werden soll (wenn diese z.B. eine ID enthält) |

## Datei anhängen

Um Email-Anhänge zu erzeugen kann an einer beliebigen Stellen des Email-Templates der Platzhalter für den Anhang hinzugefügt werden.

Die Syntax ist folgende:

```xml
<![ATTACHMENT[Dokument-ID]]>
```

oder

```xml
<![ATTACHMENT[Anhang-Dateiname|URL für Anhangsdaten]]>
```

Um die Anhänge zu parsen muß im Action bei weitere Eigenschaften eine Einstellung eingetragen werden.

```xml
parse-attachments=true
```

### Beispiel

```xml
<![ATTACHMENT[<bx:pagedata.request name="pdf" />]]>
```

wenn die Dokument-ID mit dem Request-Parameter "pdf" übergeben wird

```xml
<![ATTACHMENT[export_<bx:tools.datum/>.css|exporttemplate.txt]]>
```

wenn die Ausgabe des Templates namens exporttemplate.txt aus dem selben Navigationspunkt als Anhang mit aktuellen Datum im Namen sesendet werden soll.

```xml
<bx:containerfilter.Sammlung pool="..." max="10">
 <![ATTACHMENT[<bx:recordfield.Dokument type="id"/>]]>
</bx:containerfilter.Sammlung>
```

Hängt alls gefilterten Dokumente des Containers an die Mail an.

## Reply-To

Ein Reply-To Header kann im Freieingabe-Feld gesetzt werden (ganz unten: Freigabe weiterer Eigenschaften):

```text
reply-to=[[Kontakt_Mail]] 
```

# Container-Filteraction

<!-- last_modified: 27. May 2015 -->
Mit diesem Action kann man einen Container nach bestimmten Filter-Kriterien durchsuchen und darauf reagieren.

## Parameter

| | |
|--|--|
| list | die ID der Datenliste (Container), die gefiltert werden soll (Pflichtfeld) |
| xml | die Definition des Filters (Pflichtfeld) |
| url | die für jeden gefundenen Datensatz aufgerufene URL. Das kann ein weiteres Action sein, z.B. ein Speicheraction. (Pflichtfeld)<br>Kann auch frei gelassen werden, wenn der Filter nur auf Erfolg oder Mißerfolg prüfen soll, z.B. ob eine bestimmte E-Mail schon vorhanden ist oder nicht. |
| Test-Modus (für Entwicklung gedacht) | Im Testmodus werden keine URLs ausgeführt, die Actionausführung wird nach dem Action abgebrochen und stattdessen eine Infoseite angezeigt, auf der aufgelistet wird, welche Urls ausgeführt würden. |
| emptyresulturl | eine URL die nur dann ausgeführt wird, wenn keine URL im Filter ausgeführt wurde. Die Ausführung erfolgt im Hintergrund, z.B. wenn eine bestimmte Email noch nicht angelegt ist, dann kann sie damit angelegt werden und die Action-Abfolge wird nicht unterbrochen. |
| successurl | wenn ausgefüllt und mindestens eine URL ausgeführt wurde, wird die Ausführung nach diesen Action abgebrochen und an die angegebene Seite weitergeleitet. |
| failurl | wenn ausgefüllt und keine URLs ausgeführt wurden, wird die Ausführung nach diesen Action abgebrochen und an die angegebene Seite weitergeleitet. |
| request-method | falls der Request mittels POST geschickt werden soll, muss dieser Parameter den Wert **POST** enthalten |

## spezielle Platzhalter bei successurl und failurl

*(ab v2.6)* bei "*weiteren Eigenschaften*" können Parameter definiert werden, die statistische Werte in Actionattribute mit den dort definierten Namen schreiben:

| | |
|--|--|
| record-counter-param=filterdurchläufe | Anzahl der DS, die durch die Filterung gekommen sind |
| processed-counter-param=versuche | Anzahl der URL-Aufrufe, es fallen evt. DS weg z.B. durch bx:if |
| success-counter-param=erfolge | Anzahl der erfolgreichen URL-Aufrufe |
| error-counter-param=fehler | Anzahl der nicht erfolgreichen URL-Aufrufe, aufgerufene Seite/Action bringt Fehler |

In anschließenden Actions kann auf die Werte über den angegebenen Name in eckigen Klammer zugegriffen werden (z.B. auswertung.htm?anzahl=[[anzAufruf]]&fehler=[[anzFehler]] )

diese Werte kann man dann z. B. im Success-URL-Feld benutzen:

```xml
erfolg.htm?report=[[versuche]]+Datensaetze+verarbeitet,+davon+[[fehler]]+mit+Fehlern
```

oder z. B. auch in einem folgenden Weiterleitungsaction oder Saveaction

## Bemerkungen

In der URL können [Batix-Tags](/books/cms-handbuch-entwickler/page/batix-tags-referenz) benutzt werden, z.B. [bx:pagedata](/books/cms-handbuch-entwickler/page/bxpagedata) um der Aktion übergebene Parameter weiterzuleiten oder [bx:recordfield](/books/cms-handbuch-entwickler/page/bxrecordfield) bzw. [bx:recorddata](/books/cms-handbuch-entwickler/page/bxrecorddata) um Informationen zum aktuellen Datensatz zu übergeben.

Die Parameter der URL müssen selbst URL-Encoded werden. Dazu kann man `<bx:tools.urlencode>Text</bx:tools.urlencode>` benutzen.

Im URL-Feld können beliebig Zeilenumbrüche und Leerzeichen gesetzt werden, um den Code entwicklerfreundlich zu formatieren. In der ausgeführten URL werden diese Zeichen vorher entfernt. Leerzeichen, die in Parametern übergeben werden sollen, müssen vorher kodiert werden.

# Container kopieren

<!-- last_modified: 25. Nov 2016 -->
Diese Aktion kopiert Daten aus einem Container in einen anderen. Felder mit gleichen Namen und Typ werden automatisch übernommen. Für weitere Felder kann über eine Konfiguration eine Zuordnung geschaffen werden. Über solch eine Konfigurationseinstellung können auch mehrere Felder in ein Feld hineinkopiert werden.

Funktionen:

## Parameter

| | |
|--|--|
| `source-listid` | gibt die ID der Quell-Liste an |
| `target-listid` | dies ist die ID der Ziel-Liste |
| `idfield` | der Name des Request-Parameters, der die ID des zu kopierenden Datensatzes enthält |
| `config` | die Kopierzuordnung in XML |

Auf die ID des erzeugen Kopie-DS kann man in einem weiteren Actionbaustein über das Action-Attribute `copyrecord` zugreifen.

Weitere Eigenschaften:
`include-child-lists=true` (es werden die Untercontainer mit kopiert - wie in der Verwaltung - ab V2.6.6)
`attribute-recordid=copyrecord` (es kann statt `copyrecord` für die ID des neuen DS ein anderer Name definiert werden)

## XML-Syntax

Die Syntax der Kopierzuordnung folgt diesem Muster:

```xml
<rules>
  <field name="Titel" source="Name"/>
  <field name="Datum"><![CDATA[<bx:recordfield.Datum_Beginn pattern="dd.MM.yyyy"/><bx:if> - <bx:recordfield.Datum_Ende pattern="dd.MM.yyyy"/></bx:if>]]></field>
  <field name="Alter"><![CDATA[<bx:pagedata.request name="neuesAlter"/>]]></field>
  <field name="Kategorie/Titel" source="Titel"/>
</rules>
```

| | |
|--|--|
| name | Feldname des Zielfelds |
| source | Feldname des Quellfelds |
| \<![CDATA[...]]> | zu speichernder Inhalt als Tag-Inhalt<br>es können auch Tags wie `bx:recordfield` verwendet werden |
| Feld/Unterfeld | Unterelemente einer Einzelverknüpfung ansprechen |

### Beispiele

**Die XML Datei hat folgendes Format:**

**Beispiel Titel**

```xml
<rules>
  <field name="Datum" source="Datum_Beginn"/>
  <field name="Flat_Ausgabe"><![CDATA[
Beschreibung:
<bx:recordfield.Beschreibung type="plain"/>
Bemerkungen:
<bx:recordfield.Bemerkungen type="plain"/>
]]></field>
  <field name="Kategorie" source="Kategorie/Titel"/>
  <field name="Zeitstempel" source=""/>
</rules>
```

Das Haupt-Tag heißt `<rules>`. Dazwischen dürfen beliebig viele `<field>`-Einträge stehen, die das Pflicht-Attribut `name` haben müssen, das den Feldnamen des Zielcontainers enthält.

Bei geschlossenen `<field/>`-Tag muß in einem Parameter `source` der Name des Feldes im Quellcontainer angegeben werden. Mit "/" kann auch ein Feld hinter einer Einzelverknüpfung aufgerufen werden.

Wenn ein Feld aus dem Quellcontainer nicht übernommen werden soll, kann bei `name` der Feldname und `source=""` angegeben werden. (Hier im Beispiel würde nicht der Inhalt des Timestamp-Feldes des Quellcontainers kopiert werden und so ein aktueller Timestamp im Zielcontainer erstellt werden)

Wenn `<field>` geöffnet wird, können <a href="http://wiki.batix.net/index.php/Kategorie:Tag" target="_blank">Batix-Tags</a> benutzt werden, um den Inhalt von Textfeldern im Zieldatensatz aus mehreren Feldern des Quelldatensatzes zusammenzusetzen. An &lt;bx&gt;-Tags können nur einige verwendet werden, z. B. <a href="http://wiki.batix.net/index.php/Bx:pagedata" target="_blank">bx:pagedata</a> um der Aktion übergebene Parameter weiterzuleiten oder <a href="http://wiki.batix.net/index.php/Bx:recordfield" target="_blank">bx:recordfield</a> bzw. <a href="http://wiki.batix.net/index.php/Bx:recorddata" target="_blank">bx:recorddata</a> um Informationen zum aktuellen Datensatz zu übergeben. Der Inhalt sollte in einem CDATA-Block eingeschlossen sein, wenn er XML-Sonderzeichen (z. B. "<", "&") enthalten könnte.

# Containerdaten aus Email importieren

<!-- last_modified: 27. May 2015 -->
Diese Aktion speichert Container- und Untercontainerdatensätze. Die nötigen Daten werden von einem Mail-Server abgerufen.

| | |
|--|--|
| singlemode | wenn gewählt wird mit jedem Aufruf der Aktion nur eine Mail gelesen, ansonsten alle |
| pop3server | der Server, von dem die Mails geholt werden |
| username | der Benutzername zur Anmeldung am Server |
| password | das Passwort zum Benutzername |
| delmail | sollen gelesene Mails gelöscht werden? |
| listid | ID des Containers, in den die Daten gespeichert werden sollen |
| recordidfield | Name des Tags, der die ID eines vorhandenen Datensatzes enthält (Standard ist "recordid") |
| dokumentContainerId | ID des Containers, in den die der Mail angehängten Dateien gespeichert werden sollen |
| dokumentFolder | ein Request-Parameter, der angibt, in welches Verzeichnis der Dateiverwaltung, die in der Mail angehängten Dateien gespeichert werden sollen, kann auch als Eigenschaft der Aktion festgelegt werden mittels documentFolder |
| documentField | Name des Feldes im Dokument-Container, dem die Datei zugewiesen werden soll |
| nextpage | auf diese Seite wird nach Fertigstellung weitergeleitet, diese URL kann auch im Request-Parameter backfile stehen |
| active | gespeicherten Datensatz aktivieren? |
| timestamp | gibt ein Feld an, in dem der Bearbeitungszeitpunkt des Imports im Container festgehalten werden kann |

weitere Eigenschaften:

| | |
|--|--|
| appendrecordid | falls gesetzt, gibt diese Eigenschaft den Parameter an, über den der Folgeseite die ID des gespeicherten Datensatzes mitgeteilt wird |
| targetweb | um die Daten in ein anderes Web zu speichern, hier die ID des Webs angeben |

# Containerdaten speichern

<!-- last_modified: 27. Mar 2019 -->
iese Aktion speichert einen Containerdatensatz, dessen Felder im Request übergeben wurden.

Funktionen:

## Parameter

| | |
|--|--|
| nextpage | auf diese Seite wird nach Fertigstellung weitergeleitet, diese URL kann auch im Request-Parameter **backfile** stehen |
| active | soll der erzeugte Datensatz aktiviert werden? |
| appendrecordid | der Name eines zusätzlichen Parameters, welcher der Folgeseite übergeben wird und die ID des erzeugten Datensatzes enthält |
| listid | ID der Liste, in die der neue Datensatz gespeichert wird |
| recordidfield | der Name des Parameters, der die ID des zu überschreibenden Datensatzes enthält |
| timestamp | der Name eines Datum-Feldes, in dem der Zeitpunkt der Erstellung festgehalten wird |
| createnew | gibt an, ob ein neuer Datensatz erstellt werden darf (nur wenn keine recordid übergeben wurde) |

**weitere Eigenschaften:**

| | |
|--|--|
| update-active=j<br>update-active=n | Datensatz aktivieren oder deaktivieren<br>es ist auch möglich den Wert via Platzhalter zu übergeben:<br>`update-active=[[paramName]]`<br>ein leerer oder nicht vorhandener Parameter führt zur Deaktivierung |
| log-meta=false | speichert keine MetaDaten (erstellt bzw. letzte Änderung) |

## Bemerkungen

Durch bestimmte Name und Verwendung der Request-Parameter kann der Ablauf dieser Aktion beeinflusst und angepasst werden.

Möchte man einen Datensatz aktivieren bzw. deaktivieren, so ist der Request-Parameter "activ" mit dem Wert "j" bzw."n" zu übergeben.

### einfaches Feld speichern

Hier entspricht der Name des Parameters dem Feldname. Veraltet: Bei Verknüpfungen werden "Name.LINKLIST" und "Name.LINKRECORD" verwendet.

### Mehrfachverknüpfung

Um bei einer Mehrfachverknüpfung einzelne DS hinzufügen oder löschen zu können, wir Name.MODE angegeben (set, add oder delete).

#### Beispiel

```xml
Aus Hobby-Liste entfernen:
  <form action="save.act" method="post">
    <input type="hidden" name="Hobbies.MODE" value="delete">
    <bx:recordfield.Hobbies>
      <input type="checkbox" name="Hobbies" value="<bx:recorddata.id/>"> <bx:recordfield.Titel/>
    <bx:recordfield.Hobbies>
  </form>

Weitere Hobbies hinzufügen:
  <form action="save.act" method="post">
    <input type="hidden" name="Hobbies.MODE" value="add">
    <bx:containerfilter.Hobbies pool="Hobbies" force="list" orderby="Titel">
      <input type="checkbox" name="Hobbies" value="<bx:recorddata.id/>"> <bx:recordfield.Titel/>
    </bx:containerfilter.Hobbies>  
  </form>
```

### Checkbox: Wert "unchecked" speichern

Um den Zustand einer Checkbox in einem Wahrheitswert zu speichern, erstellt man ein hidden-Field für den nein-Wert, das den Name der Checkbox.CHECKBOX hat.
Beispiel: `<input type="checkbox" name="agb" value="j"><input type="hidden" name="agb.CHECKBOX" value="n">`

### Radiobox: Wert "null" in einem Wahrheits-Feld speichern

Um den Zustand  null - also nicht ja und nicht nein - zu speichern, gibt man als Wert "#null" an.
Beispiel: `<input type="checkbox" name="feldname" value="#null">`

### in Untercontainer speichern

Es kann "Untercontainerfeld/Feld" verwendet werden, um Felder in einem Untercontainer anzusprechen. Ein bestimmter Untercontainer kann über seine ID angesprochen werden: "Untercontainerfeld.UNTERCONTAINERID/Feld". Es können auch mehrere DS auf einen Rutsch in Untercontaienr gespeichert werden: "Untercontainerfeld.new-n/Feld"

#### Beispiele

**Beispiel Titel**

```xml
<bx:containerfilter.Firmen pool="Firmen">
  <bx:recordfield.Telefonnummern>
    <input type="text" name="Telefonnummern.<bx:recorddata.id/>/Nummer" value="<bx:recordfield.Nummer/>">
  </bx:recordfield.Telefonnummern>
</bx:containerfilter.Firmen>
```

Untercontainer "Telefonnummern" im Container "Firmen", speichern von Änderungen in einem Rutsch

### mehrere Datensätze speichern

Um mehrere Datensätze zu ändern kann "DATENSATZID/Feld" benutzt werden.

### mehrere Datensätze erstellen

Weiterhin können mit einer Aktion mehrere Datensätze angelegt werden, die Parameter müssen dann wie folgt benannt werden: "new-n/Feld", wobei "n" durch eine Zahl ersetzt wird (also z.B. "new-1/Titel" und "new-2/Titel").

### Verknüpftes Bilder in einem Bild-Field wieder löschen

#### Beispiele

**Beispiel Titel**

```xml
<form>
  <input type="file" name="bild" value="">
  <input type="checkbox" name="bild.archivid" value="">
</form>

```

Feld wird mit dem Checkbox-Inhalt überschrieben.

# Containerdatensatz löschen

<!-- last_modified: 27. May 2015 -->
Es wird ein bestimmter Datensatz mitsamt allen Feldern und Untercontainern gelöscht.

## Parameter

| | |
|--|--|
| `table` | die ID der Liste, aus der ein Datensatz gelöscht werden soll |
| `nextpage` | auf diese Seite wird nach Fertigstellung weitergeleitet, diese URL kann auch im Request-Parameter backfile stehen |
| `ID-Field` | der Request-Parameter, der die ID des zu löschenden Datensatzes enthält (Standard ist "recordid") |

# Containerinhalt validieren

<!-- last_modified: 12. Feb 2016 -->
Diese Aktion liest einen Datensatz aus einem Container und validiert ihn anhand von Kriterien.

Funktionen:

## Parameter

| | |
|--|--|
| **idfield** | der Request-Parameter, der die ID des Datensatzes enthält |
| **list** | die Liste, aus welcher der Datensatz entnommen wird (Container-ID oder Containername) |
| **config** | die Validierungsregeln<br>alternativ auch Dateiname, wo die Regeln drin stehen |

## XML-Syntax der Validierungsregeln

```xml
<model>
	<bind nodeset="Name" index="alias" required="true()" match="..." constraint="..." type="xsd:anyURI"/>
	<bind nodeset="Feld1" required="Feld2 = 'Wert'"/>
	<bind nodeset="Location" .../>
</model>
```

Es kann auch ein Pfad angegeben werden, wo dann die Regeln hinterlegt sind (für mehr Flexibilität, da kann man die Regeln im Container speichern oder so)

| | |
|--|--|
| **nodeset** | gibt das Feld im Container an, welches validiert werden soll |
| **index** | ist ein Bezeichner für diesen Test (beliebiger Text) |
| **required** | required="true()" - Feld muß gefüllt sein<br><br>required="Feld2 = 'Wert'" - Feld muß in Abhängigkeit eines anderen Feldwertes gefüllt sein. Wichtig sind die Leerzeichen vor und nach dem = . Allerdings keine Leerzeichen vor und nach Feldname bzw. Wertangabe. |
| **match** | kann einen regulären Ausdruck enthalten (für einzeilige und mehrzeilige Textfelder) |
| **constraint** | kann eine Bedingung angegeben werden, die der Feldinhalt erfüllen muß (z.B. ". > 18:00", zur Zeit "< >" für Datumsangaben, "< > =" für Zahlen und "=" für einzeiligen Text) |
| **type** | gibt den xsd-Typnamen an (zur Zeit noch nicht unterstützt) |

#### Beispiele

**Feld muß gefüllt sein**

```xml
...
<bind nodeset="Zaehlernummer" required="true()"/>
...
```

Die Zählernummer (z.B. eines Stromanschlusses) muß immer angegeben werden (im Container muß im entsprechenden Textfeld etwas stehen).

**Feld muß in Abhängigkeit eines anderen Feldwertes gefüllt sein**

```xml
...
<bind nodeset="Zaehlernummer" required="Neuanschluß = false"/>
...
```

Die Zählernummer muß angegeben werden, wenn im Formular das Häkchen bei  "Neuanschluß" nicht gesetzt wurde (im Container angelegtes Häckchenfeld darf nicht angehakt sein).

**Feld muß in Abhängigkeit eines anderen Feldwertes gefüllt sein**

```xml
...
<bind nodeset="Zaehlernummer" required="Neuanschluß = 'nein'"/>
...
```

Gleiches Beispiel wie oben, nur daß das Feld "Neuanschluß" ein Textfeld ist und das Wort "nein" drin steht.

**E-Mail-Validierung**

```xml
...
<bind nodeset="Email" index="2" match="^[_a-zA-Z0-9-](\.{0,1}[_a-zA-Z0-9-])*@([_a-zA-Z0-9-]{2,}\.){0,}[_a-zA-Z0-9-]{3,}(\.[_a-zA-Z]{2,4}){1,2}$"/>
...
```

Der im Feld "Email" gespeicherte Wert muß dem angegebenen Regex ensprechen (dieser Regex ist nur einer von vielen).

**Datum prüfen**

```xml
...
<bind nodeset="Geburtsdatum" index="2" constraint="Geburtsdatum < #today"/>
...
```

Das Geburtsdatum muß vor heute liegen.

### constraint

Mit `constraint` werden Gültigkeitsbedingungen des Feldinhalts angegeben. Diese sind je nach Typ des Feldes unterschiedlich. Der Wert im Parameter `constraint` muß folgende Form haben:

```xml
<bind nodeset="..." constraint="{Containerfeld} {Operator} {Vergleichswert}" />
```

Wichtig sind die Leerzeichen, die die 3 Werte trennen.

Hier ist die Liste der unterstützten Bedingungen, geordnet nach Feldtyp:

#### Textfelder (einzeilig, mehrzeilig)

<u>{Vergleichswert}:</u>
      Gültig sind:

- Werte in Apostroph für Vergleich mit festen Wert
- Name eines anderen Feldes
- Spezialwerte
  - #null" (Feldinhalt ist null)
  - "#empty" (Feldinhalt ist Leerstring)
  - "#nodata" (Feldinhalt ist null oder Leerstring) (ab v2.5.8)

<u> {Operator}:</u>

- "=" prüft, ob Feld dem Testwert entspricht
- "!=" Prüft, ob Feld dem Testwert nicht entspricht (ab v2.5.8)
- "MATCH" Prüft, ob Feld dem regulären Ausdruck in Testwert entspricht (ab v2.5.8)

#### Datumsfelder

<u>{Vergleichswert}</u>

- Als Vergleichswert ist bisher (v2.5.8) nur ein fester Wert möglich. Er sollte wegen Kompatibilität zu zukünftigen Erweiterungen in Apostrophs eingeschlossen werden.
- Zeitfelder müssen in der Form "{Stunden}:{Minuten}[:{Sekunden}]" angegeben sein
- Datumsfelder müssen in der Form "{Tag}.{Monat}.{Jahr}" angegeben sein
- Datum-/Zeitfelder in der Form "{Tag}.{Monat}.{Jahr} {Stunden}:{Minuten}[:{Sekunden}]"
- Erweiterung mit ab v2.5.9: Schlüsselwort: "#today" (constraint="datum is #today+2")
- Erweiterung mit ab v2.5.9: Vergleich mit anderen Feld (constraint="vondatum before bisdatum" Bei zwei zu vergleichenden Feldern muß das Containerfeld als erstes angegeben werden.)

<u> {Operator}</u>

- "<" (&lt;)  - Prüft, ob Feld zeitlich vor dem Testwert liegt
- ">" (&gt;) - Prüft, ob Feld zeitlich nach dem Testwert liegt
- "before" - Prüft, ob Feld zeitlich vor dem Testwert liegt (ab v2.5.9)
- "after" - Prüft, ob Feld zeitlich nach dem Testwert liegt (ab v2.5.9)
- "=" oder "is" - Prüft, ob Feld gleich dem Testwert ist (gleicher Tag) (ab v2.5.9)
- "lt" - Prüft, ob Feld zeitlich vor dem Testwert liegt (ab v2.5.9)
- "gt" - Prüft, ob Feld zeitlich nach dem Testwert liegt (ab v2.5.9)
- "beforeOrEqual" - Prüft, ob Feld zeitlich vor oder genau auf dem Testwert liegt (ab v2.5.9)
- "afterOrEqual" - Prüft, ob Feld zeitlich nach oder genau auf dem Testwert liegt (ab v2.5.9)
- "lte" - Prüft, ob Feld zeitlich vor oder genau auf dem Testwert liegt (ab v2.5.9)
- "gte" - Prüft, ob Feld zeitlich nach oder genau auf dem Testwert liegt (ab v2.5.9)

#### Zahlenfelder

<u>{Vergleichswert}</u>

- Als Vergleichswert ist bisher (v2.5.8) nur ein fester Wert möglich. Als Dezimaltrenner muß das Komma verwendet werden.

<u> {Operator}</u>

- "<" prüft, ob Feld kleiner als der Testwert ist
- ">" Prüft, ob Feld größer als der Testwert ist
- "=" Prüft, ob Feld gleich dem Testwert ist

#### Häkchenfelder (Wahrheitswert)

<u>{Vergleichswert}</u>

- 'j', 'ja', 'true', 'y', 'yes' für Test auf wahr
- '#null' für Test auf nicht gewählt (ab v2.5.8)
- alles andere für Test auf falsch

<u> {Operator}</u>

- "=" prüft, ob Feld dem Testwert entspricht
- "!=" prüft, ob Feld nicht dem Testwert entspricht (ab v2.5.8)

#### Verknüpfungen, Untercontainer

werden in Version 2.5.8 noch nicht unterstützt

# Dokument hochladen

<!-- last_modified: 10. Jun 2016 -->
Diese Aktion verschiebt ein hochgeladenes Dokument in die Dateiverwaltung. Dabei ist es wichtig, dass im Upload-Formular enctype="multipart/form-data" gesetzt ist.

Funktionen:

| | |
|--|--|
| fileparam | gibt den Request-Parameter an, der die hochgeladene Datei enthält |
| folderid | falls das Dokument in einen bestimmten Ordner der Dokumentenverwaltung gespeichert werden soll, kann hier die ID des Ordners angegeben werden |
| folderparam | eine Alternativmöglichkeit um das Dokument in einen bestimmten Ordner zu speichern, die ID wird aus dem hier angegebenen Request-Parameter ausgelesen (Standard-Parametername ist "folderid") |
| folderpath | die dritte Möglichkeit zur Angabe des Ordners, hier wird der Name des Ordners angegeben |
| targetweb | um das Dokument in ein anderes Projekt/Web zu speichern, hier die ID des Webs angeben |
| info | mit diesem Parameter kann die Beschreibung des Dokumentes festgelegt werden |
| infoparam | um die Beschreibung aus einem Request-Parameter auszulesen, hier den Parametername angeben |

## Bemerkungen

Bei Werten, die durch verschiedene Parameter festgelegt werden können, gilt folgende Reihenfolge der Überprüfung (es wird dabei abgebrochen, sobald ein Wert gefunden wurde):

- **Ordner**: `folderid` -> `folderparam` (wenn nicht angegeben, dann Standardwert "folderid") -> `folderpath`
- **Titel**: `titel` -> `titelparam`
- **Autor**: `autor` -> `autorparam`

In den Metadaten des Dokumentes werden unter "uploader" und "author" der eingeloggte Benutzer (falls er eingeloggt ist) sowie unter "uploaderIP" die IP des Uploaders eingetragen.

## Multiupload

funktioniert wie beim [Bilderupload](/books/cms-handbuch-entwickler/page/bild-hochladen).

.

# Excel-Action

<!-- last_modified: 04. Apr 2018 -->
Erzeugt eine Excel-Datei, die gleich geöffnet oder als Download angeboten werden kann.

### Parameter

| | |
|--|--|
| createnew | Sheets anlegen, falls diese noch nicht existieren? (Standard = nein)<br>Wird keine Vorlage verwendet, muß `"ja"` gewählt sein. |
| downloadname | Dateiname der erzeugten Datei (nicht ausfüllen, um Datei nicht zum Download anzubieten) |
| dokumentname | Dateiname für die Dokumentenverwaltung (nicht ausfüllen um die erzeugte Datei nicht abzuspeichern)<br>ACHTUNG! `"ordnerid"` muß mit angegebenw werden. |
| ordnerid | ID des Ordners in der Dokumentenverwaltung, in der die fertige Datei abgelegt werden soll<br>Muß mit angegeben werden, wenn in der Dokumentenverwaltung gespeichert werden soll. |
| xml | XML Daten direkt eingeben (wenn leer wird xmlfile genommen)<br>Parameter mit [[[...]]] angeben |
| xmlfile | Dateiname der Seite, welche die XML Daten liefert |
| templateid | Server-Dateiname der Excel-Datei in der Dokumentenverwaltung, die als Vorlage dienen soll (wegen Styling oder Formeln).<br>Leer lassen um neue Datei zu erzeugen, die dann allerdings nicht gestylt werden kann. |
| overwrite | Soll eine evtl. vorhande Datei überschrieben werden (Standard: nein) - wird nicht mehr genutzt |
| beschreibung | Beschreibung für die gespeicherte Datei in der Dokumentenverwaltung (nur für neu erstellte Dateien) |
| forcehttp | Soll in jedem Fall http anstatt https zum template laden benutzt werden? (Standard: nein) |

**Aufbau der XML-Datei**

```xml
<?xml version="1.0" encoding="utf-8" ?>
<data>
  <style name="fettkursiv" bold="true" italic="true"/>
  <style name="comic" font="Comic Sans MS" size="14" color="red"/>

  <sheet name="Sheet-Name" [widthA="20" widthB="10" widthC="40"]>

    <insert row="0" col="0" style="fettkursiv">Zeile0 Spalte0</insert>
    <insert row="0" col="1">Zeile0 Spalte1</insert>
    <insert row="0" col="2">Zeile0 Spalte2</insert>
    
    <insert row="1" col="0">Zeile1 Spalte0</insert>
    <insert row="1" col="1">Zeile1 Spalte1</insert>
    <insert row="1" col="2">Zeile1 Spalte2</insert>

  </sheet>
</data>

ODER

<?xml version="1.0" encoding="utf-8" ?>
<data>
  <sheet idx="0">

    <insert adress="A1">Zeile0 Spalte0</insert>
    <insert adress="B1">Zeile0 Spalte1</insert>
    <insert adress="C1">Zeile0 Spalte2</insert>
    
    <insert adress="A2">Zeile1 Spalte0</insert>
    <insert adress="B2">Zeile1 Spalte1</insert>
    <insert adress="C2">Zeile1 Spalte2</insert>

  </sheet>
</data>
```

| | |
|--|--|
| bold | true/false (oder weglassen) |
| italic | true/false (oder weglassen) |
| color | siehe <a href="https://poi.apache.org/apidocs/org/apache/poi/hssf/util/HSSFColor.HSSFColorPredefined.html" target="_blank">hier</a>, nur Farbnamen<br>![excelfarben.png](https://batix.help/uploads/images/gallery/2026-05/MbGldPr4OpfQCrIB-13041695.png) |
| widthA, widthB ... | Spaltenbreite nach Spaltenname |

# Formular als Mail versenden

<!-- last_modified: 27. Jan 2015 -->
Die Daten aus dem Request werden in ein Email-Design mit Platzhaltern eingefügt. Dann wird es als Email versendet.

Funktionen:

## Parameter

| | |
|--|--|
| nextpage | auf diese Seite wird nach Fertigstellung weitergeleitet |
| mailFrom | die Email-Adresse, unter der die Mail versandt wird |
| mailFromName | der im Email-Programm angezeigte Absendername |
| mailTo | der Empfänger der Email |
| subject | der Betreff der Mail |
| sendHTMLFormat | wenn gewählt, wird die Email als HTML-Mail versandt |
| cc | Email-Adressen für CC (durch Semikolon trennen) |
| bcc | Email-Adressen für BCC (durch Semikolon trennen) |

## Bemerkungen

Platzhalter der Form "[[param]]" können in Adressen und Betreff verwendet werden. Diese werden dann durch die entsprechenden Request-Parameter oder Aktions-Attribute ersetzt. Ebenfalls kann im Betreff "{format}" verwendet werden, das aktuelle Datum wird dann gemäß "format" formatiert (bei fehlerhafter Angabe wird "dd.MM.yyyy" verwendet). .

# Formulardaten validieren

<!-- last_modified: 07. Mar 2017 -->
Mit dieser Aktion ist es möglich, Formulardaten auf korrekte Syntax zu überpüfen.

| | |
|--|--|
| failpage | die seite, auf die weitergeleitet wird, wenn die Validierung fehlschlägt |
| validate:param | für jeden Parameter, der validiert werden soll, muss es einen solchen Eintrag geben (param ist dabei durch den Name des zu überprüfenden Parameters zu ersetzen)<br>der Wert stellt den regulären Ausdruck dar, mit dessen Hilfe der Parameter überprüft wird |

## Bemerkungen

Um Email-Adressen zu validieren kann als Parameter-Wert statt dem regulären Ausdruck einfach "email" geschrieben werden, es wird dann ein Ausdruck benutzt, der auf die meisten gängigen Adressen passt. Ein erweiterter regulärer Ausdruck für Email-Adressen ist z.B. dieser (Quelle: <a href="http://www.regular-expressions.info/email.html" target="_blank">http://www.regular-expressions.info/email.html</a>):
`[A-Za-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[A-Za-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[A-Za-z0-9](?:[A-Za-z0-9-]*[A-Za-z0-9])?\.)+[A-Za-z0-9](?:[A-Za-z0-9-]*[A-Za-z0-9])?`
Um also wirklich sicher zu gehen, empfiehlt sich die Verwendung dieses Ausdrucks beim Überprüfen von Email-Adressen.

Innerhalb des regulären Ausdrucks können Platzhalter der Form [:param:] stehen, diese werden dann durch den Wert des Action-Parameters "param" ersetzt.

Beispiel für ein simples Formular mit den dazugehörigen Erweiterungen für die Validation

```xml
<form name="" method="" action="">
  <input type="hidden" name="validate:Vorname" value=".+">
  <input type="text" name="Vorname" value="">
  <input type="hidden" name="validate:Name" value=".+">
  <input type="text" name="Name" value="">
  <input type="hidden" name="validate:Strasse" value=".+">
  <input type="text" name="Strasse" value="">
  <input type="submit" value="senden">
</form>
```

Die Werte in den Value-Parametern der Hiddenfields sind <a href="http://www.regular-expressions.info" target="_blank">reguläre Ausdrücke</a>

# Intranet Login

<!-- last_modified: 27. Jan 2015 -->
Um einen User im Intranetbereich zu authentifizieren wird diese Aktion benutzt.

Funktionen:

## Parameter

| | |
|--|--|
| successpage | gibt die URL an, auf die bei Erfolg weitergeleitet wird, kann auch im Request übergeben werden (hat dann Vorrang) |
| failpage | auf diese URL wird bei Misserfolg weitergeleitet, kann auch als Request-Parameter übergeben werden (hat dann Vorrang) |
| block-counter | wenn ausgefüllt: Anzahl der erlaubten Fehlversuche bis zur Sperrung des Benutzers |
| block-timeout | Zeit in Minuten nach der Fehlversuche neu gezählt werden (Standard=60) |
| minimale Sessionlänge | (min-session-timeout) Angabe in Minuten. Die evtl. beim Benutzer eingestellte Sessionlänge wird für diese Session überschrieben |
| maximale Sessionlänge | Angabe in Minuten. Die evtl. beim Benutzer eingestellte Sessionlänge wird für diese Session überschrieben |

## Freigabe weitere Eigenschaften

| | |
|--|--|
| username | wird im Request übergeben, alternative Namen sind: j_username, user, name, login |
| passwort | wird im Request übergeben, alternative Namen sind: password, j_password, pass |

# Intranet Logout

<!-- last_modified: 27. May 2015 -->
Diese Aktion invalidiert die <a href="http://wiki.batix.net/index.php/Session" target="_blank">Session</a> und loggt damit den Benutzer aus.

## Parameter

| | |
|--|--|
| nextpage | auf diese Seite wird anschließend weitergeleitet |

# Intranet-User anlegen/ändern

<!-- last_modified: 01. Sep 2015 -->
Mit dem Action kann man einen Intranet-User anlegen und Angaben ändern (z.B. bei Paßwort vergessen). Meist in Verbindung mit einem Anmeldeformular kann man die im Formular eingegebenen und validierten Daten zum Anlegen des Users nutzen. field-user wäre z.B. Email und field-password wäre eines der beiden Paßwörter. Das Action gibt die ID des Users zurück (attribute-userid), die dann anschließend im Container gespeichert werden muß. Zusätzlich kann man noch die ID einer Benutzergruppe angeben, der der User zugeordnet sein soll. Mit dologin legt man schließlich fest, ob der User nach Abschluß der Anmeldung eingeloggt sein soll oder nicht.

## Parameter

| | |
|--|--|
| field-user | Parametername des Benutzerfeldes<br>Feldname mit dem der Benutzername übergeben wird (nur wenn neuer Benutzer) |
| field-id | Parametername des Benutzer-ID-Feldes<br>Feldname mit dem die Benutzer-ID übergeben wird (nur wenn Änderung eines Benutzers) |
| field-password | Parametername des Passwortfeldes<br>Feldname mit dem das Passwort übergeben wird |
| activate | Benutzer aktiv schalten, Standard: ja |
| attribute-userid | Name für neue Benutzer-ID<br>Attributname, in dem die ID des neuen Benutzers gespeichert werden soll |
| groups | zuzuordnende Gruppen, Liste von Gruppen-IDs |
| dologin | Benutzer sofort anmelden, (Standard nein) Ansonsten wird der aktuelle Benutzer ausgeloggt |

## Freigabe weiterer Eigenschaften:

  anrede=...

  name=...

  vorname=...

  email=...

  anschrift=...

  telefon=...

  fax=...

  bemerkung=...

## Löschen

Mit dem Action-Parameter (unter Freieingabe) `delete` (auf "true" setzen) kann der Benutzer auch gelöscht werden.

# JSP-Baustein ausführen

<!-- last_modified: 27. May 2015 -->
Ein JSP-Baustein wird ausgeführt.

## Parameter

| | |
|--|--|
| jsp-id | der auszuführende Baustein (ist aus einer Liste auswählbar) |
| quiet | wenn "true" werden keine keine Fehler angezeigt |

# Newsletter – Abo abmelden

<!-- last_modified: 27. Jan 2015 -->
Kurzbeschreibung

Funktionen:

## Parameter

| | |
|---|---|
| `entfernt` | `URL zur Folgeseite, wenn der Newsletter erfolgreich abgemeldet wurde` |
| `nichtvorhanden` | `die Folgeseite, falls für die angegebene Email-Adresse kein Newsletter vorhanden ist` |
| `falsch` | `Weiterleitung, falls das Passwort falsch ist` |

## Request-Parameter

| | |
|---|---|
| `email` | `die Email-Adresse` |
| `aboid` | `die ID des Abos` |
| `passwort` | `das Passwort zur Email-Adresse` |

## Bemerkungen

Es werden entweder die Request-Parameter `email` und `aboid` **oder** `email` und `passwort` benötigt.

# Newsletter – Abo ändern

<!-- last_modified: 27. May 2015 -->
Einstellungen des Newsletterabo werden geändert.

## Parameter

| | |
|---|---|
| nextpage | die Folgeseite |

## Request-Parameter

id
access
rubrik
email
htmlmail
passwort1
passwort2

# Newsletter – Abonnentenlogin

<!-- last_modified: 27. May 2015 -->
Authentifizierung um Newsletterabo zu ändern.

## Parameter

| | |
|---|---|
| login | Folgeseite, wenn Login OK war |
| error | Folgeseite, wenn der Login fehlgeschlagen ist |

## Request-Parameter

| | |
|---|---|
| email | die Email-Adresse |
| password | das Passwort |

# Newsletter aktivieren

<!-- last_modified: 11. Mar 2019 -->
Ein abonnierter Newsletter wird freigeschalten.

## Parameter

| | |
|---|---|
| successpage | die Seite, die nach erfolgreicher Freischaltung angezeigt wird |
| failpage | die angezeigte Seite, falls das Abo nicht aktiviert werden konnte |
| requestparam | der Request-Parameter der die Aktivierungs-ID enthält (Standard: "id"), alternativ kann im Request auch email und aboid übergeben werden |

Es kann eine Mail verschickt werden mit dem Optin-Link, mit dem der NL aktiviert werden kann.

## Beispiele

Sie haben sich bei unserem Newsletter angemeldet. Bitte bestätigen Sie Ihre Email-Adresse, indem Sie auf unten stehenden Link klicken.:<br/><br/>https://www.testseite.de/optin.act?nlid=[[activateid]]

# Newsletter – Newsletter abonnieren

<!-- last_modified: 28. May 2015 -->
Jemand wird zur Newsletter-Kundenliste hinzugefügt und erhält eine Email mit seinen Zugangsdaten.

## Parameter

| | |
|---|---|
| abonniert | URL der Folgeseite bei erfolgreicher Anmeldung |
| schonvorhanden | URL der Fehlerseite, wenn der Newsletter bereits abonniert wird |
| setactive | Abonnent ohne Prüfung sofort aktivieren? |
| subject | Betreff der Bestätigungsmail |
| mailFrom | die Email-Adresse des Absenders (wird bei Fehlermeldungen und beim Antworten auf Bestätigungsemail benutzt) |
| mailFromName | der in der Mail angezeigte Absendername |

## Request-Parameter

| | |
|---|---|
| email | die Email-Adresse |
| rubrik | (optional) mehrmals angeben, um die Rubriken zu spezifizieren (Standard: alle) |
| passwort1<br/> passwort2 | (optional) Passwort und -Bestätigung (Standard: zufall) |
| htmlmail | (optional) Newsletter im HTML-Format senden ('j' oder 'n', Standard: 'n') |
| firma, ansprech, strasse, ort | (optional) Abonenntendaten |
| frage, antwort | (optional) geheime Frage und Antwort |

# Newsletter – Passwort vergessen (1)

<!-- last_modified: 28. May 2015 -->
Diese Aktion verlangt eine Eingabe der Email-Adresse um die geheime Antwort eingeben zu können.

## Parameter

| | |
|---|---|
| question-page | Seite zur geheimen Frage (Standard: "./frage.htm") |
| unknown-page | Seite, wenn die Email-Adresse nicht in der Datenbank ist (Standard: "./") |
| unsupported-page | Seite, falls keine Frage festgelegt wurde (Standard: "./") |
| email | (Request-Parameter) die Email-Adresse |

# Newsletter – Passwort vergessen (2)

<!-- last_modified: 28. May 2015 -->
Nach Eingabe der geheimen Antwort wird eine Email mit dem Passwort versandt.

## Parameter

| | |
|---|---|
| ok-page | Ziel URL, wenn die Antwort richtig war |
| fail-page | Ziel URL wenn Antwort auf die Frage falsch war |
| mailFrom | Email-Adresse, unter der die Mail versandt wird |
| mailFromName | im Email-Programm angezeigter Absendername |
| subject | Betreff |
| sendHTMLFormat | Email im HTML-Format senden? |

## Request-Parameter

| | |
|---|---|
| aboid | die Abo-ID |
| antwort | die Antwort auf die geheime Frage |

# Passwort des angemeldeten Users ändern

<!-- last_modified: 27. May 2015 -->
Das Passwort des gerade angemeldeten Users kann mittels dieser Aktion geändert werden.

## Parameter

| | |
|---|---|
| oldpassword-field | Feld für altes Passwort<br/>Optional. Falls ausgefüllt, muss das alte Passwort in diesem Request-Paramater übergeben werden. Diese Eigenschaft muss ggf. über die weiteren Eigenschaften angegeben werden. |
| password1-field | Feld für Passwort<br/>Request-Feldname, der Passwortfeld enthält. |
| password2-field | Feld für Passwortwiederholung<br/>Request-Feldname, die Passwortwiederholung enthält. |
| failpage | Fehlerseite<br/>Fehlerseite falls Passwort leer, zu kurz oder ungleich der Wiederholung |

## Bemerkungen

Die beiden übergebenen Eingaben müssen übereinstimmen und das Passwort muss mindestens 3 Zeichen lang sein.

# Shop – Bestellung versenden

<!-- last_modified: 28. May 2015 -->
Diese Aktion versendet den Warenkorb per Email.

## Parameter

| | |
|---|---|
| name | der Name des Warenkorbes (falls mehrere getrennte Warenkörbe verwaltet werden sollen) |
| mailFrom | die Email-Adresse des Absenders |
| mailFromName | der anzuzeigende Absender-Name im Email-Programm |
| subject | der Betreff |
| mailTo | Empfänger-Adresse |
| ccMailField | der Request-Parameter, der die Adresse für die Bestätigungsmail enthält |
| ccSubject | der Betreff für die Bestätigungsmail |
| art-titel | Name des Feldes, was die Artikelbezeichnung enthält |
| art-preis | Name des Feldes, was den Preis enthält |
| art-nummer | Name des Feldes, was die Artikelnummer enthält |
| backfile | URL zur Bestätigungsseite (standardmäßig "../") |
| currency | das Währungssymbol |
| clearbasket | Warenkorb leeren? |
| extraChargeField | Feldname für den Betrag eines zusätzlichen, produktabhängigen Postens |
| extraChargeName | der Name des zusätzlichen Postens (Standard ist der Wert von extraChargeField) |

## Bemerkungen

Weiterhin können Parameter der Form "addCharge1Field" und "addCharge1Name" verwendet werden ("1" kann dabei jeweils erhöht werden, also "addCharge2Field, addCharge2Name, addCharge3Field, addCharge3Name, ..."). Diese zusätzlichen Posten werden der Summe hinzugefügt.

# Shop – Hinzufügen zu Warenkorb

<!-- last_modified: 28. May 2015 -->
Durch diese Aktion wird ein neues Element in den Warenkorb aufgenommen.

## Parameter

| | |
|---|---|
| name | Name des Warenkorbes (falls mehrere getrennte Warenkörbe verwaltet werden sollen), standardmäßig der Wert des Request-Parameters "basket" |
| basketlink | die URL der Folgeseite, hier kann "[[url]]" verwendet werden, die Folgeseite steht dann im Request-Parameter "url" |
| extraParameterPrefix | eine Markierung für zusätzlich Parameter, die dem Warenkorb übergeben werden (alle Parameter, die mit diesem Wert anfangen werden übergeben) |

## Request-Parameter

| | |
|---|---|
| basket | der Name des Warenkorbes |
| artikelid | die Artikel-ID |
| type | nur für CM-Seiten-Shop-Modus |
| url | die Folgeseite |
| anzahl | Bestellmenge |
| index | nur für Updatemodus |

# Shop – Löschen im Warenkorb

<!-- last_modified: 28. May 2015 -->
Diese Aktion löscht einen Artikel aus dem Warenkorb oder leert den Warenkorb komplett.

## Parameter

| | |
|---|---|
| name | der Name des Warenkorbes |
| nextpage | die Folgeseite |
| clear | löscht den gesamten Warenkorb (zu verwenden nach Versendung der Bestellung) |
| remove | (Request-Parameter) enthält die zu löschenden Posten (falls als erster Posten "all" übergeben wird, werden alle Einträge gelöscht) |

# Shop – Zusatzgebühr zum Warenkorb

<!-- last_modified: 28. May 2015 -->
Eine Zusatzgebühr (z. B. Nachnahme, Lieferkosten, Versicherung) wird in den Warenkorb gelegt oder entfernt.

## Parameter

| | |
|---|---|
| basketname | der Name des Warenkorbes |
| group | der Name des Postens (kann auch im Request übergeben werden, als "name" oder "group") |
| value / element | (Request-Parameter) enthält den Wert des Postens, falls hier nichts steht wird der Posten entfernt |

# Sicheres Formular überprüfen (SecureformAction)

<!-- last_modified: 28. Sep 2016 -->
Das SecureForm-Action wird benutzt, um Formulare gegen Manipulationen abzusichern. Es ist verfügbar ab *Version 2.6.5.*

<p class="callout info"><a href="/books/cms-handbuch-entwickler/page/manipulationsgeschutzte-formulare-mit-secureform">Unter diesem Link</a> gibt es eine ausführliche Anleitung, wie dieses Action mit dem <a href="/books/cms-handbuch-entwickler/page/bxsecureform">zugehörigen Tag</a> zu benutzen ist.</p>

## Parameter

| | |
|---|---|
| **securelist** | Dies ist eine komma-getrennte Liste der Parameternamen, welche zur Hashbildung herangezogen werden.<br>Tauchen hier Parameternamen auf, die nicht im Request sind, so werden diese Parameter nicht zur Hashbildung benutzt.<br>Hier können auch Parameter stehen, die nie an das Action übergeben werden dürfen - da diese im Frontend nicht mitgehasht werden und höchstens durch Manipulation im Request landen, schlägt die Prüfung fehl und das Action bricht ab.<br>Zusätzlich zu dieser manuellen Liste gibt es eine im System verankerte Liste, welche einige Standardparameter enthält, die immer geschützt sein müssen (z.B.: recordid, listid). |
| **failurl** | Falls die Prüfung fehlschlägt, wird zu dieser URL weitergeleitet.<br>Ist hier nichts eingetragen und die Prüfung schlägt fehlt, wird das Action mit einer Fehlermeldung abgebrochen. |

Alle Parameter in securelist müssen, falls vorhanden, abgesichert sein. Das heißt ihr Wert muss entweder direkt in den Hash eingeflossen sein, oder einen der erlaubten Werten entsprechen (und diese Liste muss dann in den Hash eingeflossen sein).

### Erlaubte Werte

Falls ein spezieller Parameter für <a href="http://docs.batix.info/pages/viewpage.action?pageId=4489658#ManipulationsgeschützteFormularemitSecureform-ErlaubteWertefestlegen" target="_blank">mehrere erlaubte Werte</a> mitgeschickt wurde, wird zusätzlich geprüft, ob der originale Parameter einen dieser Werte entspricht.

Actionklasse: com.batix.action.SecureformAction

# Suche im Web

<!-- last_modified: 27. May 2015 -->
Es wird eine Suche in vorher indizierten Seiten des Webs ausgeührt. Das Suchergebnis wird in der Benutzersitzung gespeichert und kann danach auf der Ergebnisseite wieder ausgelesen werden.

Diese Suchergebnisse können dann mittels [bx:websearch](/books/cms-handbuch-entwickler/page/bxwebsearch) in eine HTML-Seite eingefügt werden.

## Parameter

| | |
|---|---|
| searchparam | Request-Parameter der den Suchbegriff enthält (Standard ist "search") |
| resultpage | die Seite, auf die danach weitergeleitet wird |
| useAccessFilter | sollen Menüpunkte, auf die der Benutzer kein Zugriff hat herausgefiltert werden? |
| useNavFilter | aktiviert die Parameter includeNav, excludeNav sowie searchroot |
| includePattern | ein regulärer Ausdruck, der angibt, was in die Suche eingeschlossen wird |
| excludePattern | ein regulärer Ausdruck, der angibt, was aus der Suche ausgeschlossen wird |
| includeNav | Liste von Navigations-ID's von in die Suche eingeschlossenen Pfaden |
| excludeNav | Liste von Navigations-ID's von aus der Suche ausgeschlossenen Pfaden |
| searchroot | gesamtes Web durchsuchen? (wenn nicht speziell angegeben) |

## Bemerkung

Sobald `useAccessFilter` verwendet wird, werden alle anderen Parameter zur Einschränkung (wie z.B. `useNavFilter`, `include...` oder `exclude...`) nicht mehr beachtet.

# Validierungsergebnis ausgeben

<!-- last_modified: 27. May 2015 -->
Diese Aktion wertet das Ergebnis einer Container-Validierung aus. Es kann ein Report in ein Textfeld des Datensatzes geschrieben werden, ein Häkchen im Containerdatensatz geschalten werden oder das Action abgebrochen und auf eine andere URL weitergeleitet werden.

## Parameter

| | |
|---|---|
| reportfield | das Feld, in dem das Validierungsergebnis gespeichert werden soll |
| format | das Format, in dem das Validierungsergebnis geschrieben werden soll ("xml" oder "properties") |
| resultfield | das Häkchenfeld in dem der Validierungsstatus gespeichert werden soll (angehakt bedeutet "Validation nicht bestanden") |
| fail-url | hierhin wird weitergeleitet, wenn die Validierung fehlgeschlagen ist |
| success-url | hierhin wird weitergeleitet, wenn die Validierung erfolgreich war |
| list | zu validierende Datenliste, falls mehrere Container gleichzeitig validiert werden |

## Bemerkung

Es muss vorher eine [Validierung](/books/cms-handbuch-entwickler/page/containerinhalt-validieren) stattgefunden haben.

Sobald eine URL aufgerufen wird (`fail-url` oder `success-url`) wird die weitere Aktionsverarbeitung abgebrochen. In der URL-Angabe können auch Platzhalter der Form "[[param]]" verwendet werden, diese werden dann durch den jeweiligen Wert des Request-Parameters "param" ersetzt.

# Vorhandene Bedingung abfragen

<!-- last_modified: 27. May 2015 -->
Dies ist eine Aktion, die einen Abbruch der Aktionsverarbeitung bewirkt, wenn ein Requestparameter ungleich einem bestimmten Wert ist.

## Parameter

| | |
|---|---|
| requestField | der Requestparameter, dessen Wert abgefragt werden soll |
| compareValue | der Wert, den der Requestparameter haben muss, um die Bedingung zu erfüllen<br/>es können auch Spezailwerte verwendet werden:<br/><br/>        #null - Feld ist nicht im Request enthalten<br/>        #empty - Feld ist leer im Request<br/>        #nodata - Feld ist nicht im Request oder ist leer<br/><br/>Ferner ist es möglich, reguläre Ausdrücke der Form ^regex hier$ zu verwenden.<br/>Auch kann man zwei Request-Werte vergleichen, indem man bei compareValue den zweiten Parameter in zwei eckige Klammern stellt. |
| conditionTrue | zu dieser URL wird weitergeleitet, wenn die Bedingung erfüllt wird |
| conditionFalse | falls die Überprüfung fehlschlägt, wird hierhin weitergeleitet |

Die URLs können Platzhalter der Form [[Parametername]] sowie die speziellen Platzhalter {querystring} und {request} enthalten. Ebenfalls kann den speziellen Platzhaltern "?" oder "&" vorangestellt werden (z.B. {&request}), diese Zeichen werden dann mit ausgegeben, falls der Platzhalter zu einem Wert aufgelöst werden kann.

## Klassenname

`com.batix.action.ConditionAction`

# Weiterleitung

<!-- last_modified: 22. Aug 2018 -->
Diese Aktion leitet an eine andere Seite weiter.

Funktionen:

## Parameter

| | |
|---|---|
| destination | die Ziel-URL |
| appendQueryString | gibt den Query-String des aktuellen Requests an die Ziel-URL weiter |

## Bemerkungen

In der URL können Platzhalter der Form "[[param]]" verwendet werden, diese werden dann durch die Werte der entsprechenden Request-Parameter ersetzt. Weiterhin gibt es zwei spezielle Platzhalter:

| | |
|---|---|
| [[session-id]] | die Session-ID |
| [[newrecordid]] | ID eines Datensatzes, der durch eine vorherige Speicher-Aktion angelegt wurde |

## ACHTUNG!

Nach Update von einer V2.6.6 auf eine aktuelle Version wichtig:

Stilistischer Aufbau:
 /index.htm ->Liste
 /detail.htm ->Detailseite
 /save.act ->Speichern-Aktion

Bei Formular absenden an save.act haben Weiterleitungen die bisher mit "?query=foo" den Browser bisher wegen einem Tomcat "Bugfeature" auf "./?query=foo" weitergeleitet.
 Das ist eigentlich **falsch** und inzwischen gefixt.
 Nun wird aber der Browser bei *Verwendung" des Bugs als Endlosschleife immer wieder auf das Save-Action geleitet: "./save.act?query=foo".
 Daher muss in den aktuellen Versionen für eine Weiterleitung auf die Index-Seite des Menüpunktes "./?query=foo" verwendet werden, da sonst korrekterweise auf die Adresse geleitet wird, die der Browser auch zuletzt angefragt hat.
 Fehlerbild wären also seltsame leere Actionaufrufe aus dem Frontend und Benutzer, die melden, dass ihr Browser nach Formular-Absenden keine sinnvolle Seite mehr darstellt und stattdessen was von "Zu viele Weiterleitungen" berichtet.

# Wert in Session speichern

<!-- last_modified: 27. May 2015 -->
Alle Request-Parameter mit dem angegebenen Präfix werden in eine Hashmap in der Session geschrieben. Der Name des Session-Parameters ist "com.batix.sessionlist:**mapname**".

## Parameter

| | |
|---|---|
| mapname | Name der Hashmap (Standard: "default") |
| fieldname | Name des Parameters |
| fieldnamePrefix | alternativ: Präfix der zu speichernden Parameter |
| savename | (ggf. über Freieingabe setzen)<br/>Name des Session-Attributes, in dem der Wert aus dem Request gespeichert werden soll |

   Wird **savename** nicht angegeben, wird als Name des Session-Attributes der Wert aus **fieldname** verwendet.

# XHTML 2 PDF

<!-- last_modified: 17. Sep 2020 -->
Liest URLs aus einem Container,einem Request-Parameter oder mit Vorgabe im Action und erstellt daraus PDF-Dateien.
Vollständige und strikte Unterstützung von **CSS 2.1** sowie einigen Erweiterungen von **CSS 3.0**. (siehe <a href="http://code.google.com/p/flying-saucer/" target="_blank">[1]</a>)

Funktionen:

## Parameter

| | |
|---|---|
| **Dokumentverwaltung** | *in Dokumentverwaltung speichern (Standard = nein)*<br/>Wenn hier nein angegeben wird, dann wird das PDF-Dokument direkt zum Browser gestreamt |
| **Verzeichnis-Id**<br/>Eingabe bei weitere Eigenschaften:**<br/>folderparam=parametername<br/>folderpath=/pfad/<br/>targetweb=Projekt-ID** | *ID des Zielordners in des Dokumentenverwaltung*<br/>Wenn bei Dokumentverwaltung ein ja gewählt ist, kann man in Attribut Verzeichnis-Id die ID eines Ordners der Dokumentenverwaltung angeben oder alternativ diese ID in einem Request-Parameter namens 'Verzeichnis-Id' oder in einem Request-Parameter dessen Name in Attribut folderparam eingetragen ist. Der Ordner kann auch über dessen Namen angegeben werden in Attribut folderpath. Zusätzlich kann man im Attribut targetweb ein anderes Projekt des selben Mandanten angeben. |
| **Dokumentname** | *Dateiname des erzeugten PDF*<br/>Wenn bei Dokumentverwaltung der Standard nein gewählt ist, kann hier der vorgeschlagene Dateiname angegeben werden (Platzhalter sind erlaubt). bei einem ja wird dies als Originaldateiname verwendet |
| **Dateifeldname** | *Name des Feldes, in dem die Verknüpfung in nächsten Action gespeichert werden soll*<br/>nur wenn bei Dokumentverwaltung = ja gewählt ist: Hier kann ein Action-Parameter für Folgeactions definiert werden, z. B. um das Dokument zu einem Containerdatensatz zuzuweisen. |
| **URL** | *Pfad zur Seite*<br/>Im Hintergrund wird die URL aufgerufen und dann das zurückgelieferte HTML in eine PDF-Datei gerendert. |
| **Request-Name** | *Name des Requestparameters der eine URL enthält*<br/>Ein Parameter mit diesen Namen muß im Request, der dieses Action aufruft, mit übertragen werden. Er muß eine URL enthalten und diese URL wird aufgerufen und dann das zurückgelieferte HTML in eine PDF-Datei gerendert. (Wird ignoriert wenn bei URL etwas angegeben ist) |
| **Container-Id** | *Container in welchem die URLs gespeichert sind*<br/>Bei Angabe der ID eines Containers (pool) wird in diesen Container in allen Datensätzen bzw. diesen, die den Kriterien in Container-Filter entsprechen, nach dem Feld Container-Feld geschaut. Dieses Feld enthält die URL zum Quellcode für das PDF und von allen gefilterten Datensätzen werden diese Quellcodes zusammenkopiert und als ein großes PDF gerendert |
| **Container-Feld** | *Containerfeld welches die komplette URL enthält* |
| **Containerfilter** | *Filterkriterien des Containers im XML-Format*<br/>(z.B. Session-ID prüfen) |
| Eingabe bei weitere Eigenschaften:**<br/>info=irgendeine Info<br/>infoparam=parametername** | *Dateiname des erzeugten PDF*<br/>Hier kann eine Dokumentbeschreibung für den Eintrag in der Dokumentverwaltung eingetragen werden. Entweder ein fester Wert in Attribut info oder der Name eines anderen Request-Parameters im Attribut infoparam |

**Quelldatenmodi:**

- Direkte URL angeben: Feld URL ausfüllen
- URL in Requestparameter: Request-Name ausfüllen
- URL in Containerfeld: "Container-"-Felder ausfüllen

**Ausgabemodi:**

- Direkt streamen: Dokumentverwaltung = nein auswählen
- Speichern in Dokverwaltung: Dokumentverwaltung = ja auswählen

## Tips

Seitennummern rechts unten:

```css
@page {
  @bottom-right {
    content: "Seite " counter(page);
    font-family: Arial, Helvetica, Sans-Serif;
    font-size: 12pt;
  }
}
```

Seitengröße:

814 x 1134 Pixel (Größe für Hintergrundbilder, die die gesamte Seite ausfüllen sollen)

**PDF und Schriften**

Beispiel für CSS-Style zur Einbettung von Schriften in ein PDF-Dokument:

```xml
@font-face{
	font-family:Source Sans Pro Light;
	src:url(/static/<bx:pagedata.webdir/>/assets/fonts/SourceSansPro-Light.ttf) format("truetype");
	font-style:normal;
	font-weight:400;
	-fs-pdf-font-embed: embed;
	-fs-pdf-font-encoding: Identity-H;
}
```

Der Schriftname bei font-family muss identisch sein mit der Bezeichnung in der TrueType-Font-Datei.
Als Windows-User findest du die korrekte Bezeichnung mit Doppelklick auf die ttf-Datei.

![image2020-9-17_15-3-23.png](https://batix.help/uploads/images/gallery/2026-05/a5lct7Unk3NdkGjJ-28278815.png)

# Ressourcen & Plugins

Container, Mediendatenbank, Vorlagen, Plugin Newsletter, Zeitsteuerung.

# Container

<!-- last_modified: 11. Jan 2017 -->
In Containern können Daten (Artikeldaten, Kontaktdaten, Vorgangsdaten usw.) gespeichert und auf den Webseiten vollständig oder teilweise ausgewertet, kombiniert und ausgegeben werden. Sie bilden damit ein mächtiges, weil vielseitig verwendbares, unabhängiges Instrument zur Verwaltung und Abbildung beliebiger Daten über Projekte und Mandaten hinaus.

![cont1.jpg](https://batix.help/uploads/images/gallery/2026-05/1pfWVlz7a67chdSI-3932378.jpg)

## Erklärung anhand eines Beispiels

Sie möchten auf der Website Ihres Unternehmens eine Ansprechpartner-Seite einrichten. Die Daten dazu liefert Ihnen eine Excel-Liste:

![image2015-5-29 11:25:0.png](https://batix.help/uploads/images/gallery/2026-05/JpPe5vlryWDCgmwa-3932381.png)

Also legen Sie einen Container an, um diese Daten ins System zu bekommen. Zusätzlich wollen Sie diese noch anreichern mit einem Bild und den Aufgabenbereichen. Die Eingabe dazu erfolgt gleich im Container.

![image2015-5-29 12:55:36.png](https://batix.help/uploads/images/gallery/2026-05/G258cDMb7vFpJuOr-3932394.png)

Nach dem Import Ihrer Excel-Liste haben Sie die Daten nun im CMS.

![image2015-5-29 12:43:34.png](https://batix.help/uploads/images/gallery/2026-05/lEpgKgnjRYNbw4UT-3932390.png)

Dann brauchen Sie auch noch ein [Template](/books/cms-handbuch-entwickler/page/vorlagen), um diese Daten mittels [Tags](/books/cms-handbuch-entwickler/page/batix-tags-referenz) in eine Website zu bekommen. Für dieses Beispiel brauchen Sie die Tags [bx:containerfilter](/books/cms-handbuch-entwickler/page/bxcontainerfilter) und [bx:recordfield](/books/cms-handbuch-entwickler/page/bxrecordfield).

```xml
...
    <div id="content">
      <h1>Ansprechpartner</h1>
      <bx:textarea.Seitentext large comment="Dieser Text steht direkt unter der Überschrift."/>
      <bx:containerfilter.Abteilung pool="Abteilungen" orderby="Titel">
        <h3 class="streifen"><bx:recordfield.Titel/></h3>
        <br>
        <bx:containerfilter pool="Ansprechpartner" name="Abteilung" type="8" value="special:PARENTCONTAINER" orderby="Familienname">
          <div class="ansprechpartner">
            <img src="<bx:recordfield.Bild width="60" height="150" type="path"/>">
            <strong><bx:recordfield.Vorname/> <bx:recordfield.Familienname/></strong><br>
            Tel.: <bx:recordfield.Telefon/>
            <div class="floatclear"></div>
          </div>
        </bx:containerfilter>
        <br>
      </bx:containerfilter.Abteilung>
    </div> 
...
```

Das Ergebnis sieht dann - je nach [CSS-Styles](/books/cms-handbuch-entwickler/page/vorlagen) - ungefährt so aus:

![image2015-5-29 12:34:59.png](https://batix.help/uploads/images/gallery/2026-05/Xwj5KnX5ynQmkA2b-3932385.png)

## Grundlagen

Um Container zu verwenden, muss zwischen Daten und Darstellung unterschieden werden. Zum einen müssen die Daten erfasst und strukturiert werden, zum anderen müssen verschiedene Darstellungsformen vorbereitet und später den Daten zugeordnet werden.

### Die Inhalte werden definiert

Unter Definition im Menüpunkt Container werden eben diese definiert und verwaltet und es werden jedem angelegten Containertyp verschiedene Templates (=Gestaltungsvorlagen) zugeordnet. Das ist die Aufgabe des Administrators. Er legt fest, welche Container mit welchen Daten einem Redakteur zur Verfügung gestellt werden und welche vom Designer erstellten Vorlagen zur Darstellung der Informationen vom Redakteur verwendet werden dürfen.

Bei der Containerdefinition wird festgelegt, wieviele Datensätze der Container enthalten soll und welcher Art sie sind. Containerdefinitionen sind also Templates (Vorlagen) für Daten.

Beispiel: Zur Definiton des Containers Ansprechpartner speichern wir die einzeiligen Textfelder Titel, Vorname, Name, Telefonnummer, das mehrzeilige Textfeld Tätigkeitsbeschreibung und das Feld Foto vom Typ Bild. Zu unserer Containerdefinition Ansprechpartner gehören also sechs Datensätze.

Bei der Containerverwaltung werden Gruppen von Containerdefinitionen angelegt. In diesen Gruppen können dann die einzelnen Container bearbeitet werden.

Beispiel: Wir haben zwei Abteilungen, Einkauf und Verkauf. Jede dieser beiden Abteilungen verfügt über mehrere (beliebig viele) Ansprechpartner. Wir legen zwei Gruppen (Einkauf und Verkauf) an und weisen diesen Gruppen zu, aus welchen Containerdefinitionen ihre zu editierenden Datensätze stammen sollen. Hier handelt es sich um die oben angelegte Containerdefinition Ansprechpartner.

### Die Inhalte werden erstellt: Container editieren

Im Navigationsbereich auf der linken Seite sollten jetzt bei Verwaltung zwei Einträge vorhanden sein: *Einkauf* und *Verkauf*. Wir haben jetzt nichts anderes gemacht, als zwei Kategorien anzulegen, in denen künftig beliebig viele Einträge (Container, Ansprechpartner) editiert und verwaltet werden können. Die Container in beiden Kategorien können dabei mit Daten entsprechend der Containerdefinition (Vorlage) gefüllt werden.

In unserem Beispiel bedeutet dies, dass jeder dieser Container über maximal sechs Felder verfügt. Wir können nun beliebig viele Ansprechpartner in den beiden Kategorien anlegen.

### Die Darstellung

Wir haben nun alle Daten der Ansprechpartner eingegeben. Nun möchten wir, dass eine jeweils andere Auswahl der Ansprechpartner auf verschiedenen Bereichen der Webseite erscheint. Die Zusammenstellung dieser einzeln existierenden Ansprechpartner geschieht im jeweiligen Menüpunkt, also der Administration derjenigen Seite, auf welcher die Informationen erscheinen sollen. Nun könnte der Redakteur damit beginnen, die einzelnen Container auf der Seite *Ansprechpartner Einkauf* zusammenzustellen. Das kann er aber im Moment noch nicht. Er hat zwar die Daten an sich schon zur Verfügung, weiß aber noch nicht, wie diese dargestellt werden sollen - er hat zwar ein Datentemplate (Containerdefinition), aber noch kein Designtemplate (Darstellungsvorlage). Das ist Aufgabe des Designers.

Innerhalb des Punktes [Dokumentvorlagen](/books/cms-handbuch-entwickler/page/vorlagen#Dokumentvorlagen) bei [Vorlagen](/books/cms-handbuch-entwickler/page/vorlagen) im Bereich [Ressourcen](/books/cms-handbuch-entwickler/chapter/ressourcen-plugins) gibt es mehrere Kategorien: Komplettseiten, Designtemplates, Textbausteine und Sonstiges. Uns interessieren an dieser Stelle nur die ersten beiden Punkte:

#### Komplettseiten

Komplettseiten sind Vorlagen für komplette Webseiten - also inklusive Navigation, Platzhaltern, mehrfach verwendeten Grafiken, Modulen usw. Jedem Menüpunkt in einem Projekt wird eine solche Vorlage zugewiesen. Um nun Container abbilden zu können - von denen wir immer noch nicht wissen, wie sie konkret aussehen - muss der Designer nichts anderes tun, als in einer bestimmten Stelle des Quelltextes einer Komplettseite einen Platzhalter für Container einzufügen.

Beispiel: In unserem Projekt weist jede Seite dasselbe Schema auf: Links die Navigation, oben eine editierbare Grafik, darunter die Überschrift der Seite und darunter der spezifische Seiteninhalt. Der Designer entwickelt also einen Quelltext, der in der linken Tabellenzelle einen Platzhalter für die dynamisch auszulesende Navigation beinhaltet, oben mittels bx:Tag einen Platzhalter für ein Bild und darunter ebenfalls mittels bx:Tag einen Platzhalter für die Headline bereithält. Darunter würden gewöhnlich weitere Platzhalter für Schleifen, Texte, Bilder, Dokumente usw. folgen. Hier in der Quelltextvorlage für eine Komplettseite zur Darstellung von Containern ist das anders: Hier erscheint lediglich ein bx:Tag, der Platz für die Darstellung von Containern schafft - welche das auch sind und wie sie auch aussehen mögen. Der Vorteil liegt auf der Hand: Möchte der Designer zwar nichts an der Darstellung der Container, wohl aber etwas am "Drumherum" ändern (z.B. ein weiteres Textfeld unter der Headline), muss er nur noch eine Designvorlage ändern. Jedenfalls dann, wenn es sich um Menüpunkte handelt, die irgendwie auf Container zugreifen. Der Designer legt eine solche Seite an und nennt sie zum Beispiel Containerseite.

#### Designtemplates

Designtemplates sind nichts anderes als Code-Schnipsel. Hier benötigen wir keinen kompletten Quelltext, sondern nur die Informationen, die wir für die Darstellung der Container entsprechend ihrer Definition benötigen. Hier bei den Designtemplates wird nun das Aussehen der Container bestimmt - und zwar in beliebig vielen Formen und Formaten.

Beispiel: Wir möchten in den Menüpunkten Einkauf und Verkauf alle Ansprechpartner mit allen (also sechs) Datensätzen darstellen. In einem anderen Bereich der Webseite - zum Beispiel bei den FAQ - möchten wir den Text einfügen "Weitere Antworten finden Sie bei...", gefolgt vom Namen und der Telefonnummer des entsprechenden Ansprechpartners. Der Designer legt nun zwei Designtemplates an: Ansprechpartner_komplett umfasst einfach in einer Tabelle alle Datensätze des Ansprechpartners untereinander. Ansprechpartner_kurz umfasst lediglich vier Datensätze: Text ("Weitere Antworten finden Sie bei..."), Vorname, Name und Telefonnummer. Darüber hinaus ist der Name im ersten Designtemplate rot, im zweiten blau.

#### Ergebnis

Jetzt haben wir neben den Containern (Ansprechpartnern), die in verschiedene Kategorien unterteilt sind nun auch mehrere (genauer: zwei) Möglichkeiten, diese Container darzustellen: entweder komplett oder nur mit Name, Vorname und Telefonnummer. Der Designer hat seine Arbeit getan. Damit der Redakteur aber auch die verschiedenen Darstellungsformen nutzen kann, muss noch einmal der Administrator in Aktion treten.

Im Bereich Formatzuweisung in Container bei [Ressourcen](/books/cms-handbuch-entwickler/page/ressourcenplugins) werden den vorhandenen Containerdefinitionen die vom Designer erstellten Designtemplates zugewiesen. Nun sind Datenvorlagen (Containerdefinition) mit beliebig vielen passenden Darstellungsvorlagen (Designtemplates) verknüpft und können vom Redakteur benutzt werden.

### Inhalte und Darstellung werden zusammengeführt: Die Arbeit am Menüpunkt

Der Redakteur legt im Bereich Redaktion einen neuen Menüpunkt an. Nachdem er alle erforderlichen Eingaben getätigt hat, wird er darauf hingewiesen, dass er für diesen Menüpunkt noch keinen Quelltext (= Vorlage für eine Komplettseite) benutzt. Jetzt wählt der Redakteur die oben angelegte Vorlage *Containerseite*. Nun kann er den Menüpunkt (z.B. *Ansprechpartner Einkauf*) mit Inhalten füllen. Nachdem er die Überschrift eingegeben und ein Bild hochgeladen hat kann er nun darunter beliebig viele Container einfügen - natürlich prinzipiell auch andere als die bereits angelegten. In diesem Menüpunkt fügt er schrittweise alle Ansprechpartner ein, die zum Bereich Einkauf gehören. Bei jedem einzelnen Ansprechpartner wird er vom Programm gefragt, wie dieser Ansprechpartner dargestellt werden soll (es gibt zwei Möglichkeiten: komplett und verkürzt). Er entscheidet sich für die komplette Variante und verfährt anschließend analog im Bereich *Ansprechpartner Verkauf*.

Ergebnis: Der Webauftritt verfügt nun über zwei Menüpunkte mit allen verfügbaren Daten der jeweiligen Ansprechpartner.

### Container in anderen Menüpunkten verwenden

Wir haben oben davon gesprochen, einen Menüpunkt FAQ zu erstellen, in welchem verschiedene Fragen und Antworten erscheinen. Sollte zu einem Fragekomplex noch Klärungsbedarf bestehen, sollen ein Text sowie kurze Daten des kompetenten Ansprechpartners erscheinen. Die intelligenteste Lösung besteht darin, dass weitere Container definiert werden. Hier sind das beliebig viele FAQ (bestehend aus den zwei mehrzeiligen Textfeldern *Frage* bzw. *Antwort*). Auch hier gibt es natürlich ein entsprechendes Designtemplate. Der Redakteur hat nun im neu anzulegenden Menüpunkt nichts anderes zu tun, als diesem wiederum die Vorlage *Containerseite* zuzuweisen und die Inhalte zu integrieren.

Nur bedient er sich hier aus zwei Containern. Nachdem er beispielsweise die ersten fünf FAQ eingefügt hat, wählt er beim sechsten Eintrag einen Container aus der Kategorie "Ansprechpartner". Bei der Frage, wie dieser Container dargestellt werden soll, wählt er diesmal die kurze Variante. Mit den übrigen FAQ verfährt er genauso und weist den Themenkomplexen abschließend den entsprechenden Ansprechpartner zu. Sollte an einer Stelle eine weitere FAQ eingefügt werden, verschiebt der Redakteur den Eintrag im Administrationsbereich einfach an die entsprechende Stelle.

Nun kann der Redakteur diese Seite mit Aktionen verbinden: Versenden der Inhalte als eMail, Weiterempfehlen, Ausdrucken usw.

### Konsequenzen

1. Wenn sich zum Beispiel bei einem Ansprechpartner die Telefonnummer ändert, muss der Eintrag nur einmal geändert werden.
1. Sollen zum Beispiel die FAQ auf einer anderen Webseite dieses Clients in einer völlig anderen Form benutzt werden, müssen maximal nur zwei Dateien geändert werden: die entsprechende Komplettseite und das spezielle Designtemplate.
1. Soll diese Seite ausgedruckt werden, ist eine auf einen Drucker angepasste Ausgabe erforderlich. Auch hier muss nur eine neue Komplettseite (z.B. *Druckdesign*) angelegt werden. Im Administrationsbereich wird dieser neue Quelltext dem Menüpunkt zusätzlich zugewiesen. Nun hat diese Seite ein zweites - an einen Drucker angepasstes - Erscheinungsbild.
1. Die Daten müssen in einem völlig anderen Medium (z.B. PDA oder Belichtungsvorlage für Druck) dargestellt werden. Hier müssen nur entsprechende Designs mit speziellen Merkmalen angelegt und in weiteren Menüpunkten (z.B. Client->Webseite->PDA-Variante) mit den Containern verknüpft werden.
1. Alle Änderungen in einem Containerdatensatz wirken sich unmittelbar auf alle verschiedenen Ausgabemöglichkeiten (Druck, PDA usw.) aus.

## Definition und Verwaltung

### Definition/Anlegen eines Containers

Über den Knopf wird ein neuer Container angelegt.

![image2015-5-29 12:59:54.png](https://batix.help/uploads/images/gallery/2026-05/tOaiX1HZ0E546Yfu-3932400.png)

| Container in Administration sichtbar | Der Container taucht in der linken Navigationleiste unter "Container" auf. |
|--------------------------------------|---------------------------------------------------------------------------|
| Container globar freigeben | Wenn angehakt, können Sie auch von anderen Mandanten aus auf diesen Container zugreifen, ansonsten ist er nur innerhalb eines Mandanten für alle Projekte nutzbar. |
| Titel/Alias | Name des Containers, muß innerhalb eines Systems eindeutig sein |
| optionale Containerbezeichnung |  |
| kurze Beschreibung | ebensolche |
| Tabellenname | wird automatisch generiert anhand des Titels, füllt sich nach der Speicherung, kann aber überschrieben werden |
| Kategorie | Bei vielen Containern empfiehlt es sich, diese in Kategorien einzuteilen. Die Namen können frei vergeben werden. |

Nachdem Sie diese Felder ausgefüllt haben, bitte speichern mit **![image2017-1-11 9:23:40.png](https://batix.help/uploads/images/gallery/2026-05/5rUKQ9HD0NcGNWLH-6226211.png)/![image2017-1-11 7:48:54.png](https://batix.help/uploads/images/gallery/2026-05/x2rwSpkcJ7Hj0YlK-6226212.png)**

![image2015-5-29 13:29:8.png](https://batix.help/uploads/images/gallery/2026-05/2KLK5UQOkpSgmztE-3932402.png)

| Containerfeld | mit "neues Containerfeld anhängen" werden die benötigten Felder angelegt |
|---------------|-------------------------------------------------------------------------|
| Anzeigemuster | Anzeige in der Verwaltung, Pattern: %Feldname% |
| Sortierfeld | voreingestellte Sortierung in der Verwaltung. Standard: Reihenfolge der Erstellung (also nach ID) |

### Anlegen der Felder

![image2015-5-29 13:33:26.png](https://batix.help/uploads/images/gallery/2026-05/PG5ebDtndkI69bEE-3932405.png)

| Feldposition | auswählbare Sortierreihenfolge |
|--------------|-------------------------------|
| Feldname |  |
| optionale Feldbezeichnung |  |
| Feldbeschreibung | ebensolche |
| Feldtyp | Datentyp des Feldes, z.B. Text, Zahl o.ä. |
| Eigenschaften |  |
| SQL ausführen |  |

Folgende Feldtypen stehen zur Verfügung:

| einzeiliger Text |  |
|------------------|--|
| mehrzeiliger Text |  |
| HTML-Editor Feld |  |
| Bildverknüpfung |  |
| Dateiverknüpfung |  |
| Datum |  |
| Datum + Uhrzeit |  |
| Uhrzeit oder Zeitraum |  |
| Ganzzahl |  |
| Dezimalzahl |  |
| Preis (2 Nachkommastellen) |  |
| Wahrheitswert (Binär) |  |
| Pixelkoordinaten in Bild | Bei Vorlage einer entsprechenden Anwendung werden Koordinaten aus einer angeklickten Grafik in diese Textfelder geladen |
| Einzelverknüpfung | Bei einem Untercontainer legen Sie fest, dass **dessen** Definition in ihrer neuen Definition als Unterschleife verwandt wird. Bei einem Container *Ansprechpartner* könnten Sie so z.B. beliebig viele Adressen (definiert in einem Container *Adressen*) zuordnen. Diese Adressen werden dann in der Redaktion im entsprechenden Container - und nur in diesem - angelegt. |
| Mehrfachverknüpfung | Bei einer Einfachverknüpfung legen Sie fest, dass sie einen Datensatz aus einem anderen Container benutzen möchten. Die Pflege der Daten erfolgt im Gegensatz zum Untercontainer im verknüpften Container. Beispiel: Im Container Ansprechpartner gibt es eine Einzelverknüpfung zum Container Abteilung. So können Sie jedem Ansprechpartner genau eine Abteilung zuordnen (und bei der Ausgabe auf Webseiten nach diesem Kriterium filtern). |
| Liste aus Untertabelle | Manchmal machen sich Mehrfachverknüpfungen notwendig. Die Pflege der Daten erfolgt im Gegensatz zum Untercontainer im verknüpften Container. Beispiel: Sie haben einen Container Fachgebiete, dem Sie mehrere Sachgebiete zuordnen möchten. Dann wählen Sie diese Option. |

# Mediendatenbank

Die Mediendatenbank umfasst alle Grafiken und Dokumente, die in den Projekten eines Mandanten **dynamisch** zugewiesen werden können. Das bedeutet, dass diese Grafiken oder Dokumente in allen Bereichen (einzelne Menüpunkte, Containerdatensätze) angewählt und entsprechend der genutzten Vorlage (Dokumentvorlage, Containerdefinition) genutzt werden können.

Die Mediendatenbank umfasst folgende zwei Bereiche:

## Grafiken

### Galerieansicht

**bisheriges Design:**

![bildergalerie1.png](https://batix.help/uploads/images/gallery/2026-05/sRW8WCF92aoyMkGR-6226220.png)

**neues Design:**

![bildergaleri_neu.png](https://batix.help/uploads/images/gallery/2026-05/TRtiu3uWoPFEV3Ne-6226221.png)

#### Neues Bild hochladen

Hier erhalten Sie folgende Informationen und haben folgende Möglichkeiten:

- Titel der Galerie und Bezeichnung des Ansichtsmodus
- Auswahl des Ansichtsmodus (Galerie-, Liste-, Detailansicht) sowie Wechsel zwischen verschiedenen Projekten eines Mandanten über ein Auswahlfeld (nur vorhanden bei mehreren Projekten)
- Wechsel zu einer anderen Kategorie
- Toolbox mit verschiedenen Möglichkeiten je nach Ansichtsmodus

  Anmerkung: Der Supervisor verfügt hier zusätzlich über die Möglichkeit eines Massenuploades. Dabei wird eine gewählte ZIP-Datei, welche die gewünschten Grafiken enthält durch das System in der gewählten Kategorie entpackt.

- Grafikübersicht mit folgenden Informationen:

  = Metadaten der Grafik (es öffnet sich ein Extrafenster) = Darstellung der Grafik in Originalgröße in einem neuen Fenster x-mal verwendet = Klicken Sie auf die Zahl (=Anzahl der Verwendungen) und Sie gelangen zu einer verlinkten Liste der Verwendungszwecke.

- Upload einer neuen Grafik: Aussuchen der Grafik von einem lokalen Datenträger durch Betätigung des Buttons "Durchsuchen". Realisierung des Uploads durch das Betätigen des Buttons "upload".

  Anmerkung: Falls Sie aus einem Menüpunkt heraus die Galerie aufgerufen haben, um z.B. eine im Menüpunkt verwendete Grafik auszutauschen, gelangen Sie nach Betätigung des Buttons "upload" direkt zurück zur Dateneingabe des Menüpunktes.

### Listenansicht

**bisheriges Design:**

![image2015-5-28 13:9:9.png](https://batix.help/uploads/images/gallery/2026-05/kaLncWGxP7DKLheq-3932361.png)

**neues Design:**

![image2017-1-11 13:56:13.png](https://batix.help/uploads/images/gallery/2026-05/JwM4mtlUb1hjX1cO-6226223.png)

In der blätterbaren Listenansicht erhalten Sie überblicksweise folgende Informationen zu den einzelnen Grafiken:

- dynamisch generierte Bezeichnung zur Verwendung durch das CMS
- Originalname der Grafikdatei
- Originalgröße der Grafik

Mit dem Link "bearbeiten" wechseln Sie zur Bearbeitungsseite der Grafik. Auch hier können Sie in der Toolbox die Kategorien der Galerie bearbeiten.

### Detailansicht

**bisheriges Design:**

![image2015-5-28 13:9:32.png](https://batix.help/uploads/images/gallery/2026-05/5bt0l2bmlN0fiLth-3932362.png)

**neues Design:**

![image2017-1-11 13:57:17.png](https://batix.help/uploads/images/gallery/2026-05/AvIZ1wXskYbInPUq-6226224.png)

Eine andere Darstellung der Galerie finden Sie in der Detailansicht. Hier finden Sie ebenfalls zu jeder Grafik Links zu den Metadaten und der Vorschau in Originalgröße. Darüber hinaus erfahren Sie, wie oft die Grafik im Projekt verwendet wird und erhalten mit einem Klick auf die Zahl eine verlinkte Liste der einzelnen Verwendungen. Mit dem Link "bearbeiten" gelangen Sie zur Bearbeitungsseite für die Grafik. In der Toolbox haben Sie in dieser Ansicht die Möglichkeit, die Kategorien zu bearbeiten.

### Bearbeitenseite

**bisheriges Design:**

![image2015-5-28 13:12:11.png](https://batix.help/uploads/images/gallery/2026-05/4MeGFh1t7Au1twFs-3932363.png)

**neues Design:**

![image2017-1-11 13:59:3.png](https://batix.help/uploads/images/gallery/2026-05/ewTTCpmtZznZ9QFO-6226225.png)

Auf dieser Seite können Sie weitere Informationen zur Grafik hinterlegen

Titel Vergeben Sie hier einen Titel für die Grafik zur Verwendung im System und ordnen Sie die Grafik einer vorhandenen Kategorie zu. Kategorie Wählen Sie hier eine Kategorie für die Grafik. Beschreibung Tragen Sie hier nähere Beschreibungen für die Grafik ein. Von besonderer Bedeutung für externe Suchmaschinen (z.B. Google) sind die beiden nächsten Einträge: Autor und alternativer Text. Insbesondere der letzte Eintrag ist wichtig für die Erfüllung der Anforderungen an barrierefreies Webdesign. Datei austauschen Mit dem Punkt "Datei austauschen" können Sie die vorhandene Grafik durch eine andere Grafik von einem lokalen Datenträger ersetzen. Achtung: Damit tauschen Sie die Grafik auch auf allen verwendeten Menüpunkten oder in anderen Verwendungszwecken, denen die ursprüngliche Grafik zugewiesen war.

### Kategorien

**bisheriges Design:**

![image2015-5-28 13:13:25.png](https://batix.help/uploads/images/gallery/2026-05/1Y2FVkhDHLwWMgHc-3932364.png)

**neues Design:**

![image2017-1-11 14:1:29.png](https://batix.help/uploads/images/gallery/2026-05/GgDoWh2CyLtvJwdv-6226226.png)

Alle Grafiken lassen sich in beliebig viele Kategorien (auf einer Ebene) sortieren. In einzelnen Ansichtsmodis haben Sie über die Toolbox die Möglichkeit, die Kategorien zu bearbeiten.

**zuweisen**  
Bilder in den Kategorien zuweisen (s. u.)

**bearbeiten**  
Dabei wechseln Sie auf eine Seite, in der Sie den Titel der Kategorie ändern und über den Button Speichern in der Symbolleiste speichern können. Alternativ können Sie hier auch mit dem Button Neuer Datensatz in der Symbolleiste eine neue Kategorie anlegen oder über den Button diesen Datensatz löschen in der Symbolleiste die gewählte Kategorie entfernen. Die der gelöschten Kategorie zugewiesenen Grafiken werden dann der Kategorie "ohne Kategorie" zugewiesen.

### Bilder in den Kategorien zuweisen

bisheriges Design:

![image2015-5-28 13:16:12.png](https://batix.help/uploads/images/gallery/2026-05/fQ2FMxFdjJAOqiGP-3932366.png)

neues Design:

![image2017-1-11 14:2:35.png](https://batix.help/uploads/images/gallery/2026-05/FgDKH6lGK0e5N0bc-6226227.png)

Hier sehen Sie alle Grafiken der gewählten Kategorie. Klappen Sie das Menü der gewünschten Grafiken auf und wählen Sie die Kategorie, in der die Grafik gespeichert werden soll. Nachdem Sie alle Zuweisungen getätigt haben, klicken Sie auf "update". Den Grafiken werden nun die neuen Kategorien zugewiesen.

### Massenupload

Durch dieses Modul können mehrere Bilder gleichzeitig zur Bildergalerie hinzugefügt werden.

Im ersten Schritt wird eine zip-Datei, welche die Bilder enthält, hochgeladen. Im zweiten Schritt können die Bilder ausgewählt werden, die verwendet werden sollen. Im dritten Schritt werden die Bilder entpackt und der Bildergalerie hinzugefügt.

## Dokumente

Hier können Sie Dokumente (PDF, Word, JPG, o.a.) zentral speichern und dann auf Seiten oder im Container verknüpfen. Somit braucht eine Datei nur einmal gespeichert werden, kann aber an mehreren unterschiedlichen Stellen eingebunden werden.

![medien2.jpg](https://batix.help/uploads/images/gallery/2026-05/26TK5jkgHvzMkcxJ-3932369.jpg)

### Listenansicht

![image2015-5-29 9:14:55.png](https://batix.help/uploads/images/gallery/2026-05/xXbq2yn5HECdQKGt-3932370.png)

Hier können Sie nach verschiedenen Projekten und Mime-Typen filtern und zwischen Ordnern wechseln sowie diese anlegen bzw. bearbeiten (s.u.). Fahren Sie mit der Maus über die Zeile, in der das gewünschte Dokument steht. Die Hintergrundfarbe ändert sich und Sie können klicken, um auf die Bearbeitungsseite des Dokumentes zu gelangen (s.u.). Zu jedem Dokument finden Sie folgende Informationen: Originalname der Datei, Dateigröße, Erstellungsdatum (= Datum des Uploades in das CMS), Dokumententyp und Anzahl der Verwendungen im Projekt. **Anmerkung:** Sollten sich die Dokumente auf einem anderen Server befinden, ist der Hintergrund in einem Rot-Ton gehalten und einige Informationen sind nicht verfügbar.

### Ordner bearbeiten

![image2015-5-29 9:23:11.png](https://batix.help/uploads/images/gallery/2026-05/pM6GkI6IMuKXcFtG-3932371.png)

Mit einem Klick auf "bearbeiten" in der Ordneransicht der Übersichtsseite gelangen Sie auf die Bearbeitungsseite des Ordners. Hier verfügen Sie über folgende Möglichkeiten:

| aktiviert | Aktivieren Sie den Ordner, damit er in der Datenbank genutzt werden kann. |
|-----------|-------------------------------------------------------------------------|
| Name | Vergeben Sie einen aussagekräftigen Namen für den Ordner. |
| virtueller Verzeichnisname | Das CMS verwendet intern spezielle Bezeichnungen, die Sie bitte hier eintragen. Halten Sie sich dabei unbedingt an die aufgeführten Konventionen, verwenden Sie also nur Kleinbuchstaben und keine Leer- oder Sonderzeichen. |
| im Ordner | Hier können Sie festlegen, wo der Ordner in der Ordnerhierarchie platziert werden soll. Klicken Sie auf die Auswahlbox und Sie können in der vollständigen Liste den gewünschten übergeordneten Ordner auswählen. |

### Dokument bearbeiten

**![image2015-5-29 9:25:46.png](https://batix.help/uploads/images/gallery/2026-05/pAcjZo99zNPBnRWN-3932372.png)**

Hier finden Sie z.B. Informationen wie Dateiname, Upload-Datum, Verwendungen und Links. Beim Download vorgeschlagener Dateiname und Beschreibung helfen, wenn Sie das Dokument veröffentlichen wollen. Es ist auch möglich die Datei in einen neuen Ordner zu verschieben oder sie komplett auszutauschen (wählen Sie dazu die neue Datei mittels "Durchsuchen" von einem lokalen Datenträger aus und Betätigen Sie den Button ![ButtonSpeichern.png](http://wiki.batix.net/images/a/ab/ButtonSpeichern.png)*Speichern*).

### Tip

Es ist ratsam, bei PDF-Dokumenten immer einen aussagekräftigen Titel einzutragen, damit bei der Suche dieser angezeigt werden kann und der Crawler beim Indizieren der Seiten keinen Fehler bringt.

# Plugin Newsletter

<!-- last_modified: 24. Jul 2018 -->
Dieses Plugin ist zwar schon etwas älter, wird allerdings noch in vielen Projekten eingesetzt.

<a href="/books/cms-handbuch-redakteure/page/plugin-newsletter">Bedienungsanleitung für Redakteure</a>

Die Redakteure können Artikel, Rubriken und Abonnenten selbst anlegen und pflegen, aber das NL-Design ist doch etwas anspruchsvoller.

## Bisherige Methode mit Platzhaltern (wurde bei "HTML-Quellcode" eingefügt, siehe Bild unten)

**Quellcode vom Hauptteil**

```xml
<tr>
  <td width="200"><!-- PICTURE --></td>
  <td>
    <strong><!-- TITEL --></strong><br>
    <!-- TEXT --><br>
    <br>
    <!-- LINK -->
  </td>
</tr>
<tr>
  <td colspan="2"><hr class="dotted"></td>
</tr>
```

**HTML-Quellcode**

```xml
<html>
  <head>
      <style type="text/css">
          body{font-family:sans-serif;font-size:10pt;}
          hr{height:0;border-top:1px solid black;border-bottom:0;}
          hr.dotted{border-top:1px dotted black;}
        </style>
    </head>
  <body>
    <table width="700" align="center" style="background-color:#dedede;">
          <tr><td colspan="2"><img src="http://demo.batix.de/pic/164CB94635F.jpg?size=140x100" border="0"> NEWSLETTER</td></tr>
          <tr><td colspan="2"><hr><!-- HEAD --></td></tr>
          <tr><td colspan="2"><!-- ANKER --><hr class="dotted"></td></tr>
          <!-- MAIN -->
          <tr><td colspan="2"><!-- BOTTOM --></td></tr>
          <tr><td colspan="2"><hr><a href="http://demo.batix.de/www/wiki_web/nl_abmelden.htm?aboid=<!-- ABOID -->">vom Newsletter abmelden</a></td></tr>
        </table>
  </body>
</html>
```

Platzhalter für den Hauptteil, also der Teil, der den Artikel repräsentiert und sich wiederholt.

| Platzhalter | Feldname bei "Artikel bearbeiten" |
|-------------|----------------------------------|
| <!-- TITEL --> | Titel |
| <!-- DATUM --> | Datum |
| <!-- TEXT --> | Beitrag |
| <!-- PICTURE --><br><!-- PICTURE-L --> | (rechtsbündig) erstes Bild<br>(linksbündig) |
| <!-- PICTURE2 --><br><!-- PICTURE2-L --> | (rechtsbündig) zweites Bild<br>(rechtsbündig) |
| <!-- NUMMER --> | Nummer des Artikels, zum Bau einer Sprungmarke |
| <!-- LINK --> | baut aus den Feldern "Link-Text" und "Link" einen Link zusammen |
| <!-- TITEL2 --> | "Bildunterschrift / 2.Titel" - kann für genau diese Zwecke verwendet werden |

Platzhalter für den Seiten-Quellcode (der Teil für die Artikel wird gesondert behandelt)

| Platzhalter | Feldname |
|-------------|---------|
| <!-- HEAD --> | Kopftext (bei "Versand"/"Kopftext" oder beim Design) |
| <!-- MAIN--> | an dieser Stelle wird der Quelltext des Hauptteils eingefügt, der separat definiert wird (siehe oben) |
| <!-- BOTTOM --> | Impressumstext (bei "Versand"/"Kopftext" oder beim Design) |
| <!-- INHALT--> | Liste der Artikel ohne Link |
| <!-- ANKER--> | generiert eine Liste der Artikel aus den Titeln, Sprungmarke wird an den Titel im Artikel gepappt |
| <!-- URL--> |  |
| <!-- ABOID --> | in Verbindung mit Email zum Abmelden (Weiterleitung auf Abmelde-Action, Übergabe der Werte aboid und email |
| <!-- EMAIL --> | siehe oben |
| <!-- AES --> | um Rubriken zu ändern, beim Klick drauf kommt man auf die Website und ist gleich angemeldet und kann die Rubriken ändern. |

Dort kann jetzt auch ein Pfad zu einem HTML-Design mit Tags angegeben werden:

## ![nl.png](https://batix.help/uploads/images/gallery/2026-05/gdkgC357TI6NlqPO-15302683.png)

## Neue Methode mit Tags

Anstelle der Platzhalter kann auch ein Design angegeben werden, in dem Tags anstelle der Platzhalter eingesetzt werden können.

```xml
<!-- eigentliche Schleife über die Artikel -->
  <bx:newsletterdesign.articles> ... <bx:newsletterdesign.articles>  

<!-- einzelnen Elemente eines Newsletterartikels (Tabelle NLARTIKEL) -->
  <bx:newsletterdesign.datum [pattern="dd.MM.yyyy"] [locale="de"]/>
  <bx:newsletterdesign.titel/>
  <bx:newsletterdesign.subtitel/>
  <bx:newsletterdesign.text/>
  <bx:newsletterdesign.link/>
  <bx:newsletterdesign.picture width="..." height="..." [html-Attribute für img-Tag]/>
  <bx:newsletterdesign.picture2 width="..." height="..." [html-Attribute für img-Tag]/>

<!-- Befehle zu Schleifenverwaltung -->
  <bx:newsletterdesign.index/>
  <bx:newsletterdesign.first [not]> ... </bx:newsletterdesign.first>
  <bx:newsletterdesign.last [not]> ... </bx:newsletterdesign.last>

<!--  -->
  <bx:newsletterdesign.aes />
  <bx:newsletterdesign.aboid />
  <bx:newsletterdesign.email />

<!-- zusätzliche Befehle zum Ausgeben des Kopf und Fußtextes des Newsletterdesigns (Tabelle NLDESIGN) -->
  <bx:newsletterdesign.headfield/>
  <bx:newsletterdesign.bottomfield/>

<!-- Abonnenten-Angaben -->
  <bx:newsletterdesign.user field="{Feldname}" /> <!-- mögliche Werte für das Feld: "ansprech", "firma", "email", "id" -->

<!-- wäre auch noch möglich: -->
<bx:newsletterdesign.usermember rubrik="150ABCDEF987" not> User nicht in RubrikX </bx:newsletterdesign.usermember>
```

```xml
<bx:newsletterdesign.articles>

</bx:newsletterdesign.articles>
```

Die folgenden Platzhalter sind zusätzlich im Emailtext (der Optin-Email) verfügbar:

| <LIST> | eine mehrzeilige Liste der gebuchten Rubriken mit Anstrich davor |
|--------|------------------------------------------------------------------|
| <PASSWORD> | das Passwort (mittlerweile unüblich und meist nicht mehr vergeben) |
| [[aboid]] | Die Datensatz-ID der Abonnenten (für das Abo-aktivieren-Action) |
| [[activateid]] | ein verschlüsselt aussehender Wert für das Abo-aktivieren-Action (enthält Email-Adresse und aboid) |

## Test-Beispiel

**Beispiel Titel**

```xml
<html>
    <head>
        <style type="text/css">
        .kopf { border:1px solid darkred; background-color:mistyrose; padding:5px }
        .fuss { border:1px solid forestgreen; background-color:lightgreen; padding:5px }
        .mitte { border:1px solid silver; background-color:whitesmoke; padding:5px }
        .artikel { border:1px solid navy; background-color:lightblue; padding:5px }
        </style>
    </head>
    <body>
        <div class="kopf"><bx:newsletterdesign.headfield/></div>

        <div class="mitte">
            <ul>
                <bx:newsletterdesign.articles>
                    <li>#<bx:newsletterdesign.index/>: <a href="#anker<bx:newsletterdesign.index/>"><bx:newsletterdesign.titel/></a></li>
                </bx:newsletterdesign.articles>
            </ul>
            <bx:newsletterdesign.articles>
                <bx:newsletterdesign.first>[[begin-liste[<br></bx:newsletterdesign.first>
                <div class="artikel">
                    <bx:newsletterdesign.picture width="200" height="200" style="float:right"/>
                    <bx:newsletterdesign.picture2 width="50" height="50" style="float:left"/>
                    <a name="anker<bx:newsletterdesign.index/>">#</a>
                    <i>D="<bx:newsletterdesign.datum pattern="d. MMMMMM yyyy" locale="de"/>"</i><br>
                    <b>T="<bx:newsletterdesign.titel/>"</b><br>
                    <br>
                    <bx:newsletterdesign.text/>
                    <br><br>Bildtitel={<bx:newsletterdesign.subtitel/>}
                    <br>URL=[<bx:newsletterdesign.link/>]
                </div>
                <bx:newsletterdesign.last not><hr style="clear:both"></bx:newsletterdesign.last>
                <bx:newsletterdesign.last><br>]ende-liste]]</bx:newsletterdesign.last>
            </bx:newsletterdesign.articles>
        </div>

        <div class="fuss"><bx:newsletterdesign.bottomfield/></div>
    </body>
</html>
```

Test-Design mit allen Befehlen.

# Ressourcen/Plugins

<!-- last_modified: 03. Feb 2017 -->
Im Bereich Ressourcen finden Sie alle Daten, Vorlagen, Aktionen und andere Ressourcen, die Sie für Ihr Projekt benötigen. Dieser Bereich ist in folgende Teilbereiche gegliedert:

**Mediendatenbank**  
Die zweigeteilte Mediendatenbank beinhaltet, in frei einteilbarer Kategorisierung, alle dynamisch verwendeten Grafiken und Dokumente eines Mandanten.

**Container**  
Hier definieren Sie Container, erstellen Container auf Grundlage der angelegten Definitionen für die Verwendung in einem oder mehreren Projekten und weisen diesen nach Bedarf bestimmte Formate (Designvorlagen) zu.

**Vorlagen**  
Hier speichern und bearbeiten Sie Vorlagenressourcen (statische Elemente eines Projektes), Dokumentvorlagen (z.B. HTML-Templates oder Textbausteine) und Stilvorlagen (z.B. CSS-Dateien).

**Aktionen**  
Hier definieren und bearbeiten Sie Aktionen, die für Abläufe im Projekt von Bedeutung sind (z.B. Emailversand, Speichern von Datensätzen, Weiterleitungen ...).

**Zeitsteuerung**  
Nur für Administratoren - Hier definieren Sie zeitgesteuerte, projektspezifische Aktionen (z.B. regelmäßige Indizierung für die interne Suchmaschine oder automatisches Archivieren abgelaufener Meldungen).

# Vorlagen

Unter Vorlagen werden alle Daten (Grafiken, Dateien, Scripte u.a.) verstanden, die nicht dynamisch in Bestandteile des CMS integriert werden, sondern vielmehr die Grundlage für Gestaltung und Funktionalität z.B. einer Webseite bilden. Dazu gehören:

## Dokumentvorlagen

Dokumentvorlagen sind im Prinzip das Herzstück des CMS. Sie bilden die Grundlage für die Gestaltung eines Webauftrittes und seiner Menüpunkte. An diesen führen sie dynamische Inhalte (Texte, Bilder, Dateien) mit festen Bestandteilen (Vorlagenressourcen) und Inhalten von Containern zusammen. Sie greifen auf Stilvorlagen zurück und realisieren somit ein CI-gerechtes Erscheinungsbild. Im Zusammenwirken mit den Aktionen an einem Menüpunkt bewirken Sie außerdem die Realisierung erforderlicher Funktionalitäten. Darüber hinaus realisieren sie ebenfalls die Bearbeitungsmöglichkeiten im Arbeitsbereich der Administration - ist z.B. auf der Webseite das Erscheinen eines Bildes und eines Textes gewünscht, werden im Administrationsbereich entsprechende Eingabemöglichkeiten geschaffen.

![ressource3.jpg](https://batix.help/uploads/images/gallery/2026-05/Sd5dN6XaYKmX2qt6-3932335.jpg)

### Übersichtsseite

![image2015-5-28 10:50:50.png](https://batix.help/uploads/images/gallery/2026-05/BtQfzU9Ka32Vj03v-3932334.png)

Dokumentvorlagen sind in folgende Typen unterteilt:

| Komplettseiten | vollständige (HTML-)Seiten für den Gebrauch vor allem in Menüpunkten |
|---------------|----------------------------------------------------------------------|
| Designtemplates | Dokumentvorlagen für die Ausgabegestaltung von Containerinhalten (Formatzuweisung) |
| Textbausteine | "Codeschnippsel" zur Verwendung in Komplettseiten<br>Beispiel: Es gibt einen Textbaustein Navigation, welcher in allen Komplettseiten verwendet, aber nur hier einmalig angelegt und gepflegt wird. Machen sich Änderungen notwendig, muss nur an dieser einen Stelle eingegriffen werden.<br>Tipp: Überlegen Sie beim Aufbau der einzelnen Seiten Ihres Projektes genau, welche Inhalte (z.B. Banner oben, Navigation, Links, Impressum unten usw.) auf allen Seiten identisch sind. Diese Bestandteile sind geborene Kandidaten für Textbausteine. |
| JSP-Bausteine |  |
| Groovy |  |
| Plugins |  |
| sonstige | ein weiterer Typ zur Ablage von Dokumentvorlagen |

### Bearbeitungsseite

Hier speichern Sie den Quelltext (z.B. HTML-Template) der Dokumentvorlage und nehmen weitere Einstellungen vor. Diese sind im einzelnen:

- Aktivieren/Deaktivieren der Dokumentvorlage (eine deaktivierte Dokumentvorlage kann keinem Menüpunkt zugewiesen werden)
- Titel der Dokumentvorlage
- Beschreibung zur Dokumentvorlage - erscheint als Hinweistext auf der Übersichtsseite
- Sicherungen: Das System speichert verschiedene Versionen der Dokumentvorlage. Diese können Sie auswählen.
  - Fahren Sie mit der Maus über den Schriftzug *Sicherungen*. Ein Kontextmenü erscheint, dass Ihnen alle vorhandenen Versionen (Datum, Bearbeiter) auflistet.
  - Klicken Sie auf das Datum der gewünschten Vorlage und betätigen Sie anschließend den Button ![image2017-1-11 7:50:26.png](https://batix.help/uploads/images/gallery/2026-05/65CVrQ0ka9E5JhV5-6226100.png)*Speichern* in der Symbolleiste. Die gewählte Version ist nun übernommen.
- Jede Dokumentvorlage verwendet eine Stilvorlage (Stylesheet), die z.B. Schriftgröße, Hintergrundfarbe, Überschriften-Formatierungen usw. definiert. Hier suchen Sie eine vorhandene Stilvorlage aus.
- Jede Dokumentvorlage können Sie einer bestehenden Kategorie innerhalb des gewählten Typs zuordnen oder in einer neuen Kategorie abspeichern. Schreiben Sie dazu den Titel der neuen Kategorie in das dafür vorgesehen Feld, klicken Sie auf den Radiobutton vor diesem Feld und anschließend auf den Button *![image2017-1-11 7:50:26.png](https://batix.help/uploads/images/gallery/2026-05/65CVrQ0ka9E5JhV5-6226100.png)Speichern*.
- Im Feld Quelltext können Sie ein extern gespeichertes Template integrieren und bearbeiten.
- Für den Quelltext stehen Ihnen zwei Ansichtsmodi zur Verfügung:

  Überblick Sie gelangen auf eine Seite, auf der die im Quelltext vorhandenen Platzhalter des CMS (bx:Tags) farblich markiert sind. Änderungen am Quelltext können Sie in dieser Ansicht nicht vornehmen. Demo Anhand zufällig generierter Inhalte bietet Ihnen das System einen eingeschränkten Blick auf das ungefähre Aussehen einer Webseite, die die Dokumentvorlage verwendet.

- In der Toolbox stehen Ihnen folgende Möglichkeiten zur Verfügung:

  Verwendung Verlinkte Listung aller Menüpunkte, die die Dokmentvorlage verwenden. neu als Kopie Es wird eine komplette Kopie der Dokumentvorlage angelegt. Sie müssen nur noch den Titel ändern, alle anderen Einträge sind identisch.

Auch hier können Sie über die entsprechenden Buttons in der Symbolleiste eine neue Dokumentvorlage erstellen bzw. die vorhandene löschen.

**Achtung:** Das Löschen der Dokumentvorlage hat zur Folge, dass Menüpunkte, die diese Dokumentvorlage verwenden, in der Administration redaktionell nicht mehr bearbeitet werden können und im Webauftritt Fehlermeldungen verursachen.

### Volltextsuche in Dokumentvorlagen

Ab Version 2.4 ist es möglich, eine Volltextsuche über alle Dokumentvorlagen durchzuführen. Dabei werden diese nach der eingegebenen Zeichenkette durchsucht. Das Eingabefeld steht in der Toolbox zur Verfügung. Die passenden Dokumentvorlagen werden daraufhin unter dem Eingabefeld verlinkt aufgelistet.

## Statische Ressourcen

Der Punkt "statische Ressource" ersetzt den Punkt Vorlagenressourcen. Wie im Explorer können hier Ordner angelegt werden.

zweifache F-Tastenbelegung, Umschaltung mit "Strg"-Taste (Fokus muß auf dieser Seite sein)

![ressourcen2.jpg](https://batix.help/uploads/images/gallery/2026-05/ZULrX8XdAXGnaeqh-3932337.jpg)

## Stilvorlagen

Stilvorlagen realisieren den Ausgabestil von Dokumentvorlagen. Für Webseiten bedeutet dies, dass eine CSS-Datei (Stilvorlage) einem HTML-Template (Dokumentvorlage) mitteilt, welche Formatierungen für Schriften, Grafiken, Eingabefelder usw. verwendet werden sollen.

![ressourcen4.jpg](https://batix.help/uploads/images/gallery/2026-05/fOnozRqBEqhArOso-3932342.jpg)

### Übersichtsseite

![image2015-5-28 11:8:42.png](https://batix.help/uploads/images/gallery/2026-05/xPDU4VBBXu7HmnoO-3932343.png)

Sie sehen eine Listenform aller vorhanden Stilvorlagen, die den einzelnen Dokumentvorlagen zugeordnet werden können. An Informationen werden Ihnen die Bezeichnung der Stilvorlage, deren Größe in Bytes und der Status angezeigt. Inaktive Stilvorlagen können nicht verwendet werden. Die entsprechenden Einstellungen nehmen Sie auf der Bearbeitungsseite vor, die Sie durch einen Klick auf die Bezeichnung der gewünschten Stilvorlage erreichen.

### Bearbeitungsseite

![image2015-5-28 11:9:14.png](https://batix.help/uploads/images/gallery/2026-05/yF6kBklRP0Zp4CRt-3932344.png)

Auf der Bearbeitungsseite können Sie folgende Einstellungen vornehmen:

- Anzeigen bei Navigation/Quelltextvorlagen: Diese Stilvorlage kann, sofern das Kontrollkästchen aktiviert ist, auf der Bearbeitungsseite einer Dokumentvorlage dieser zugewiesen werden.
- eine aussagekräftige Bezeichnung für die Stilvorlage vergeben
- den Quelltext Ihrer Stilvorlage ändern
- In der Toolbox können Sie die Stilvorlage als CSS-Datei downloaden.

## Vorlagenressourcen

Vorlagenressourcen sind Dateien, die direkt aus Dokumentvorlagen angesprochen und nicht einem Menüpunkt dynamisch zugewiesen werden. Daher werden diese Vorlagenressourcen auch als "statisch" bezeichnet.

**<span style="color: rgb(255,0,0);">Zur Speicherung der statischen Quellen sollte "Vorlagenressourcen" nicht mehr verwendet werden, sondern stattdessen "statische Ressourcen" .</span>**

![ressourcen1.jpg](https://batix.help/uploads/images/gallery/2026-05/rqCbtSi75AZtBxhN-3932326.jpg)

![image2015-5-28 10:27:20.png](https://batix.help/uploads/images/gallery/2026-05/DBD4QUh4luVjkrCO-3932327.png)

Wählen Sie eine Datei von Ihrem lokalen Datenträger und speichern Sie diese in den Vorlagenressourcen durch Betätigung des Buttons "upload". Welche Dateitypen das CMS verwenden kann, entnehmen Sie bitte der Liste. Es besteht weiterhin die Möglichkeit, alle Dateien in den Vorlagenressourcen als ZIP-Datei zu exportieren. Klicken Sie auf den entsprechenden Link und Sie werden nach Abschluss des Komprimierungsvorganges zum Speichern der generierten Datei aufgefordert. In der unteren Liste werden Ihnen alle vorhandenen Dateien mit Originalname, Erstelldatum (= Datum des Uploads in das CMS) und Dateigröße präsentiert. Mit einem Klick auf "bearbeiten" können Sie verschiedene Details der Datei editieren:

- Originalname ändern
- (bei Bildern) Vorschaubild auf dieser Seite anzeigen? wenn ja wie groß?
- (bei Textdateien) Inhalt der Datei ändern

Mit einem Klick auf ![ButtonLöschen.png](http://wiki.batix.net/images/b/b7/ButtonL%C3%B6schen.png)*Datensatz löschen* können Sie die gerade ausgewählte Datei aus dem System entfernen. **Vorsicht:** Verwenden Sie diese Datei (z.B. in einer Dokumentvorlage) führt das Entfernen der Datei zu Fehlern auf der Webseite!

# Zeitsteuerung

<!-- last_modified: 09. Jul 2019 -->
Mit der Zeitsteuerung kann man bestimmte Abläufe zeitlich steuern. Bisher wurde ein einfacher Timer benutzt, mit dem Start- und Endzeit und die Intervalle einstellen konnte. Ab Version 2.6.1. ist ein neuer Timer eingebunden, mit dem dann auch solche Zeiten wie z.B. "jeden Freitag um neun Uhr" oder "jeden Wochentag um 9.30 Uhr" oder sogar "alle 5 Minuten zwischen 9.00 und 10.00 Uhr an jedem Montag, Mittwoch und Freitag im Januar" möglich sind.

## **in alten Versionen**

**TimerTaskKlassen:**

**veraltet: (nicht mehr benutzen)**  
com.batix.timer.ContainerDeActivatorTask (aktiviert/deeaktiviert alte Containerdatensätze wenn Datum herangekommen ist)  
com.batix.timer.ContainerRemoveTask (löscht alte Containerdatensätze wenn Datum herangekommen ist)  
com.batix.timer.DetailDeactivatorTask (bx:schleife deaktiviert einzelne Schleifen-Datensätze)  
com.batix.timer.NavDeActivatorTask ( aktiviert/deeaktiviert Navigationspunkte zu bestimmten Zeitpunkt)  
com.batix.timer.NewsArchiver (altes Newssmodul; verschiebt alte News ins Archiv)

**aktuelle Timerklassen:**

##### com.batix.timer.ContainerImportTimer (aktualisiert einen neuen Container mit Daten von einem anderen System)

**Steuerparameter**:  
container-id=125DA0FBA30  -  Container intern  
extern-id=10EA47412E6  -  Container extern  
extern-host=<a href="https://www.externer-server.de" target="_blank">https://www.externer-server.de</a>  -  Hostname des externen Systems  
img-kat=125A1311768  -  Bildergaleriekategorie für importierte Bilder  
doc-kat=125A2CE1376  -  Bildergalerieordner für importierte Dokumente  
flag=html  -  Editorfelder mit importieren

---

##### com.batix.timer.UserReactivation (aktiviert gesperrte User, wenn sie 3x falsches Passwort eingegeben hatten)

---

##### com.batix.timer.VisitorStatTimer (verkürzt Userstatistik)

**Steuerparameter**:  
days-to-keep=60

---

##### com.batix.timer.URLConnectionTimer (ruft URL auf (für gewöhnlich ein Action))

**Steuerparameter**:  
url=<a href="http://www.dein-web.de/aktionen/testaktion.act" target="_blank">http://www.dein-web.de/aktionen/testaktion.act</a> - ruft ein Aktion auf  
max-redirects=30 - Anzahl der Redirekts (optional)

---

##### com.batix.search.CrawlerTask (Keywords: Web indizieren, Indizierung, Crawler)

**Steuerparameter**:  
sleeptime=500  
report-to=Email-Adresse (liefert einen Report über die Seiten, die beim indizieren 404 zurückgeliefert haben, an die angegebenen E-Mail-Adresse, ab 2.6.1 RC15)  
report-from=Absender-Adresse (wenn report-from fehlt, wird <a href="mailto:noreply@batix.info" target="_blank">noreply@batix.info</a> verwendet)

Um auch Actions zu indizieren (z.B. Weiterleitungen usw. - wenn man sicher ist, daß nix gelöscht wird) kann man im Action in die Metadaten accept-crawler=true eintragen.

## ab Version 2.6.1 - Cron Trigger

Cron Trigger sind oft besser geeignet als SimpleTrigger, wenn man zu wiederkehrenden Zeiten Jobs starten will, im Gegensatz zu exakt angegebenen Zeitintervallen beim Simple Trigger. Mit dem Cron Trigger kann man Startzeiten festlegen wie z.B. "jeden Freitag um neun Uhr" oder "jeden Wochentag um 9.30 Uhr" oder sogar "alle 5 Minuten zwischen 9.00 und 10.00 Uhr an jedem Montag, Mittwoch und Freitag im Januar". Der Cron Trigger hat aber auch analog dem Simple Trigger eine Startzeit und Endzeit, die den Einsatz des Triggers steuert.

### Mode

Ausführlich: Zeiträume können über bestimmte Felder ausgewählt werden Expert: Zeiträume können mit Cron-Expressions im Feld "Cron-Trigger" angegeben werden

### Stunde

Innerhalb welcher Stunde(n)?

jede - innerhalb jeder Stunde Zahl auswählen - innerhalb der ausgewählten Stunde, z.B. 0 angegeben, dann von 0 .00 bis 0.59 zyklisch - alle 2,4,... Stunden starten (für je eine Stunde) Eingabe - spezielle Angaben mit Cron-Expressions Werte: '*' - gleichbedeutend mit Auswahl 'jede' 0 1 2 ... 23 - gleichbedeutend mit Zahl auswählen ',' - mehrere Stunden angeben z.B. '3,7,10': innerhalb der Stunde 3, 7 und 10 '-' - Zeitraum definieren, z.B. '10-20' bedeutet: ab Stunde 10 bis einschließlich Stunde 20 '/' - Inkremente (bei zyklischem Start) festlegen, z.B. 0/2 bedeutet: Start mit Stunde 0 alle 2 Stunden (gleichbedeutend mit Auwahl zyklisch und Angabe einer Zahl) oder 3/3 bedeutet: Start mit Stunde 3 alle 3 Stunden

### Minute

Zu welcher Minute innerhalb der Stunde(n) bzw. Alle wieviele Minuten innerhalb der Stunde(n)?

jede - startet jede Minute innerhalb der Stunde Zahl auswählen - z.B. Start zur Minute 15 innerhalb der Stunde zyklisch - alle 2, 5,... Minuten starten Eingabe - spezielle Angaben mit Cron-Expressions Werte: '*' - gleichbedeutend mit Auswahl 'jede' 0 1 2 3 .. 59 - gleichbedeutend mit Auswahl einer Zahl '/' - Inkremente (bei zyklischem Start) festlegen, z.B. 0/10 bedeutet: Start mit bei Minute 0 alle 10 Minuten (gleichbedeutend mit Auwahl zyklisch und Angabe einer Zahl) oder 30/2 bedeutet: Start mit Minute 30 alle 2 Minuten ',' - mehrere Werte angeben '2,20,45': Start zur Minute 2, 20 und 45 '-' - Zeitraum definieren, z.B. "10-20" bedeutet: ab Minute 10 bis Minute 20 jede Minute

### Tag

Innerhalb welchen Tages im Monat?

jeden - innerhalb jeden Tages im Monat Zahl auswählen - innerhalb des ausgewählter Tages im Monat Eingabe - spezielle Angaben mit Cron-Expressions Werte: '*' - gleichbedeutend mit Auswahl 'jeden' 1 2 3 4 ... 31 - gleichbedeutend mit 'Zahl auswählen' ',' - mehrere Tage angeben, z.B. '13,14,19': innerhalb des 13., 14. und 19. Tages im Monat '-' - Zeitraum angeben, z.B. '5-10': innerhalb des 5. bis einschließlich 10. Tages im Monat /' - Inkremente (bei zyklischem Start) festlegen, z.B. 1/4 bedeutet: (Start mit Tag 1) alle 4 Tage oder 3/3 bedeutet: Start mit Tag 3 alle 3 Tage 'L' - letzter Tag im Monat, egal ob 28. 30. oder 31. Tag, z.B. 'L-2': vor-vorletzer Tag im Monat 'W' - der nächste Wochentag zum angegebenen Tag im Monat, z.B. '13W': wenn der 13. ein Samstag ist, wird der Freitag genommen, wenn er ein Sonntag ist, dann der Montag '?' - kein spezieller Wert (als Art Platzhalter)

### Monat

Innerhalb welchen Monats?

jeden - jeden Monat Zahl auswählen - in welchem Monat aktiv? Eingabe - spezielle Angaben mit Cron-Expressions Werte: '*' - gleichbedeutend mit Auswahl 'jeden' 1 2 3 ... 12 oder JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC (gleichbedeutend mit der Auswahl einer Zahl) ',' - Angabe mehrerer Werte, mit Komma getrennt, "FEB,OCT" bedeutet: innerhalb der Monate Februar und Oktober

### Wochentag

Innerhalb welchen Wochentages?

jeden - Timer startet täglich Mo-Fr - Timer startet innerhalb dieses Tages Eingabe - spezielle Angaben mit Cron-Expressions Werte: '*' - gleichbedeutend mit Auswahl 'jeden' 1 2 3 ... 7 oder SUN, MON, TUE, WED, THU, FRI SAT - gleichbedeutend mit 'Zahl auswählen' (1=Sonntag) ',' - mehrere Wochentag angeben, z.B. 'MON,FRI': innerhalb Montags und Freitags '-' - Zeitraum angeben, z.B. 'MON-FRI' bedeutet 'wochentags' 'L' - alleinige Angabe: letzter Tag, also Sonnabend. In Verbindung mit einer Wochentagszahl: letzter x-Tag im Monat, z.B. '6L': letzter Freitag im Monat '?' - kein spezieller Wert (als Art Platzhalter) '/' - Inkremente (bei zyklischem Start) festlegen, z.B. 1/2 bedeutet: alle zwei (Wochen)Tage mit Start am Sonntag '#' - der wievielte Wochentag im Monat, z.B. '2#1': der erste Montag im Monat (auch so schreibbar: 'MON#1')

### Jahr

Innerhalb welchen Jahres?

jedes - in jedem Jahr Eingabe - es können individuelle Jahre angegeben werden

### Wechselwirkungen:

**zwischen Wochentag und Tag**

z.B. Wochentag "Mo" und Tag "4": jeden Montag, der ein 4. des Monats ist (bei Monat muß dann "jeder" eingestellt sein)

**zwischen Monat und Tag**

z.B. Monat "jeden" und Tag "31": an jedem 31. d. Monats, also nur in Monaten, die 31 Tage haben (Tag: "jeder")

**zwischen Monat, Tag und Wochentag**

z.B. Monat "9", Wochentag "Fr" und Tag "13": wenn der September eine Freitag, den 13. hat, dann startet der Timer, ansonsten nicht

Das ganze kann noch mit Jahr gekoppelt werden, ist aber m.E. nicht sinnvoll

### Aktion

Auswahl eines Timer-Actions (siehe oben unter "Aktuelle Timerklassen")

### Steuerparameter

siehe oben unter "aktuelle Timerklassen" unter jeweiliger Klasse

### Cron-Expressions

Cron-Expressions werden verwendet, um eine Instanz eines Cron-Triggers zu configurieren. Cron-Expressions sind Strings die aus 7 Einzelwerten bestehen, die die individuellen Einzelheiten des Ablaufplans beschreiben. Die Einzelwerten werden mit Leerzeichen getrennt und repräsentieren:

```text
0 0 5 * * ? *
┬ ┬ ┬ ┬ ┬ ┬ ┬
│ │ │ │ │ │ └── Jahr (optional) 
│ │ │ │ │ └──── Wochentag (1-7) (Sonntag=1)
│ │ │ │ └────── Monat (1-12)
│ │ │ └──────── Tag (1-31)
│ │ └────────── Stunde (0-23)
│ └──────────── Minute (0-59)
└────────────── Sekunde (0-59, meist 0)
```

Die zu verwendenden Werte stehen oben unter dem jeweiligen Feld (Tag, Monat usw.).

Beispiele: "0 0 12 ? * WED" - startet jeden Mittwoch um 12.00 Uhr "0 0/5 * * * ?" - startet alle 5 Minuten (beginnend mit Minute 0) "0 30 10-13 ? * WED,FRI" - startet um 10:30, 11:30, 12:30, and 13:30, jeden Mittwoch und Freitag "0 0/30 8-9 5,20 * ?" - startet halb zwischen 8 und 10 Uhr am 5. und 20. jeden Monats. Start also um 8.00, 8.30, 9.00 und 9.30, aber nicht um 10:00 Uhr Manche Startzeiten sind aber auch zu komplex, um sie in nur einem Ausdruck abhandeln zu können, z.B. alle 5 Minuten zwischen 9.00 und 10.00 Uhr und alle 20 Minuten zwischen 1.00 und 10.00 Uhr. Das kann man nur mit zwei Timern abhandeln.

# Snippets & Rezepte

Fertige Code-Bausteine für häufige Aufgaben.

# Action-Parameter anlegen

<!-- last_modified: 16. Jun 2016 -->
Es kann sein, daß man innerhalb eines Actions Parameter benötigt, die im Request nicht übergeben wurden. Hierzu kann man den Action-Baustein "[Batix Quelltext ausführen](/books/cms-handbuch-entwickler/page/batix-quelltext-ausfuhren)" im Zusammenhang mit dem Tag "[bx:pagedata.setscriptattribute](/books/cms-handbuch-entwickler/page/bxpagedata)" benutzen. Hierzu ein paar Beispiele:

**Umwidmen eines Request-Parameters**

```xml
<bx:pagedata.setscriptattribute name="Email"><bx:pagedata.request name="Imehl"/></bx:pagedata.setscriptattribute>
```

Bestandteil einer Botfalle

**Quelltext der Seite**

```xml
<bx:containerfilter.Mitarbeiter pool="Mitarbeiter" idfield="mid" force="single">
  <bx:pagedata.setscriptattribute name="Email"><bx:recordfield.Email/></bx:pagedata.setscriptattribute>
</bx:containerfilter.Mitarbeiter>
```

Wenn man im nachfolgenden Action die Email braucht, diese aber nicht übergeben wurde (z.B. für Email-Versand-Action)

**Link für Weiterleitung zusammenbasteln**

```xml
<bx:pagedata.setscriptattribute name="weiterleitung">
  <bx:pagedata.request name="abgeschlossen" value="j">/test/naechsteSeite.htm</bx:pagedata.request>
  <bx:pagedata.request name="abgeschlossen" value="n">/test/gleicheSeite.htm</bx:pagedata.request>
</bx:pagedata.setscriptattribute>
```

Im anschließenden Weiterleitungsaction kann der Parameter mit [[abgeschlossen]] eingesetzt werden.

# Blättern (Pagination)

<!-- last_modified: 26. Sep 2018 -->
## Einfaches Listenblättern

sieht so aus:

![liste.PNG](https://batix.help/uploads/images/gallery/2026-05/nT0ifWbI0Fkdan6A-2686977.png)

Die Leiste oben und unten kann in Bausteine ausgegliedert werden. Dann kann Sie für jede Liste im Web genutzt werden. Voraussetzung: die Liste heißt dann immer "Liste", also `<bx:containerfilter.Liste pool="...">`

**HTML in der Seite**

```xml
<bx:include modul="blaetternOben"/>

<bx:containerfilter.Liste pool="Witze" orderby="Titel" max="5">
  <div class="listitem"<bx:recorddata.if last> style="margin-bottom:0;"</bx:recorddata.if>>
    <a href="detail.htm?rezeptid=<bx:recorddata.id/>"><bx:recordfield.Titel/></a>
  </div>
</bx:containerfilter.Liste>

<bx:include modul="blaetternUnten"/>
```

**ausgelagertes Include "blaetternOben"**

```xml
<div class="blaetternoben">
  <bx:recorddata.nav object="Liste">
    <bx:recorddata.startindex/> - <bx:recorddata.endindex/> von <bx:recorddata.total/> Einträgen
  </bx:recorddata.nav>
</div>
```

**ausgelagertes Include "blaetternUnten"**

```xml
<div class="blaetternunten">
  <bx:recorddata.nav object="Liste">
    <bx:if><bx:recorddata.previouslist><< zurück</bx:recorddata.previouslist><bx:if.else><span style="color:#8f8f8f;"><< zurück</span></bx:if.else></bx:if>
    &nbsp;&nbsp;|&nbsp;<strong>Seite:</strong>&nbsp;
    <bx:recorddata.navlink move="-5"/>
    <bx:recorddata.navlist max="5" boundary="&nbsp;·&nbsp;"/>
    <bx:recorddata.navlink move="5"/>
    &nbsp;|&nbsp;&nbsp;
    <bx:if><bx:recorddata.nextlist>weiter >></bx:recorddata.nextlist><bx:if.else><span style="color:#8f8f8f;">weiter >></span></bx:if.else></bx:if>
  </bx:recorddata.nav>
</div>
```

**wenn nichts zum Blättern da ist, nicht anzeigen**

```xml
<bx:tabledata.nav object="Aktuelles">
  <bx:iF type="any">
    <div class="blaetternunten">
      <bx:iF.ignore>
        <bx:if><bx:tabledata.previouslist><< zurück</bx:tabledata.previouslist><bx:if.else><span style="color:#8f8f8f;"><< zurück</span></bx:if.else></bx:if>
      </bx:iF.ignore>
      &nbsp;&nbsp;|&nbsp;<strong>Seite:</strong>&nbsp;
      <bx:tabledata.navlink move="-5"/>
      <bx:tabledata.navlist max="5" boundary="&nbsp;·&nbsp;"/>
      <bx:tabledata.navlink move="5"/>
      &nbsp;|&nbsp;&nbsp;
      <bx:iF.ignore>
        <bx:if><bx:tabledata.nextlist>weiter >></bx:tabledata.nextlist><bx:if.else><span style="color:#8f8f8f;">weiter >></span></bx:if.else></bx:if>
      </bx:iF.ignore>
    </div>
  </bx:iF>
</bx:tabledata.nav>
```

**zugehöriges CSS**

```css
.blaetternunten,.blaetternoben{
  background-color:#999999;
  text-align:center;
  padding:5px;
  color:#ffffff;
  }
```

## Etwas ausführlicheres Stylen

sieht so aus:

![liste1.PNG](https://batix.help/uploads/images/gallery/2026-05/aGIjWE3HnhzCoN1e-2686979.png)

**Code**

```xml
<bx:recorddata.nav object="Liste">
  <div id="blaetterbox">
    <div id="blaetterelements">
      <span id="blaettern-left">
       <bx:if><bx:recorddata.previouslist>« zurück</bx:recorddata.previouslist><bx:if.else><span style="color:#B2B2B2;">« zurück</span></bx:if.else></bx:if>
      </span>
      <span id="blaettern-middle">
        <bx:recorddata.navlist max="5" boundary="">
          <bx:recorddata.navlistcurrent><span><bx:recorddata.navlistpage/></span></bx:recorddata.navlistcurrent>
          <bx:recorddata.navlistcurrent not><a href="?index=<bx:recorddata.navlistindex/>"><bx:recorddata.navlistpage/></a></bx:recorddata.navlistcurrent>
        </bx:recorddata.navlist>
      </span>
      <span id="blaettern-right">
        <bx:if><bx:recorddata.nextlist>weiter »</bx:recorddata.nextlist><bx:if.else><span style="color:#B2B2B2;">weiter »</span></bx:if.else></bx:if>
      </span>
    </div>
  </div>
</bx:recorddata.nav>
```

**zugehöriges CSS**

```css
#blaetterbox {
  width:100%;
  height:28px;
  background-color:#b2b2b2;
  -moz-border-radius: 3px;
  -webkit-border-radius: 3px;
  border-radius: 3px;
  }
#blaetterbox #blaetterelements {
  width:365px; margin:auto;
  font-size:10pt;
  font-weight:bold;
  padding-top:6px;
  text-align:center;
  }
#blaetterbox #blaetterelements #blaettern-middle{#
  padding:0 20px;
  }
#blaetterbox #blaetterelements #blaettern-left a, #blaetterbox #blaetterelements #blaettern-right a{
  text-decoration:none;
  color:#605639;
  filter: dropshadow(color=#949494, offx=-1, offy=-1);
  }
#blaetterbox #blaetterelements #blaettern-left span, #blaetterbox #blaetterelements #blaettern-right span{
  text-decoration:none;
  color:#ffffff;
  text-shadow: -1px -1px 0px #949494;
  filter: dropshadow(color=#949494, offx=-1, offy=-1);
  }
#blaetterbox #blaetterelements #blaettern-middle span{
  text-decoration:none;
  letter-spacing:5px;
  color:#ffffff;
  background-color:#968659;
  padding:6px 1px 5px 7px;
  -webkit-border-radius: 3px;
  -moz-border-radius: 3px;
  border-radius: 3px;
  }
#blaetterbox #blaetterelements #blaettern-middle a{
  text-decoration:none;
  letter-spacing:5px;
  color:#605639;
  padding:6px 1px 7px 7px;
  }
```

## Springe-zu-Funktion

Ergänzung mit:

**Code**

```xml
<br><br>springe zu: 
<select name="change" size="1" style="width:50px;" onchange="">
  <bx:recorddata.navlist object="MeineSuchergebnisliste" max="0">
    <option value="<bx:recorddata.navlistpath encoding="html" />"><bx:recorddata.navlistpage/></option> 
  </bx:recorddata.navlist>
</select>
```

sieht dann so aus:

![fff.png](https://batix.help/uploads/images/gallery/2026-05/GYXxlmultXAQv55q-2686980.png)

Dieser Quelltext-Schnipsel kann beliebig außerhalb des recorddata.nav-Blocks in das HTML-Template eingebunden werden (auf Wunsch auch innerhalb, kein Ding) und baut eine SELECT-Box in den HTML-Quellcode ein inkl. aller verfügbaren Seitenergebnisse und dem entsprechenden Blätter-Parameter.

**Hinweis:**  
Man muss abschließend nur noch die SELECT-Box via JavaScript animieren etwas zu tun, wenn eine Auswahl getroffen wurde (Parameter versteckt setzen+Form abschicken oder URL-Aufruf …)

Zusätzlich kann eine kleine Abfrage um die Select-Box gebaut werden, dass diese bspw. nur angezeigt wird, wenn es mehr als 5 Seiten zu blättern gibt. Somit bleibt die Webseite schön clean und wenn es wirklich mehrere Suchseiten gibt die auch nicht mehr über die bisherige Darstellung sinnvoll angezeigt werden, dann ist die Springe-zu-Funktion hilfreich. Bei 2 Seiten ist diese neue Erweiterung nicht so hilfreich wie bei 15 Suchergebnisseiten.

## Bootstrap4-Pagination

```xml
<bx:recorddata.empty object="{listenname}" not>
  <bx:recorddata.nav object="Telefonate" indexparam="{parametername_index}">
    <nav aria-label="Page navigation" class="mt-4">
      <ul class="pagination">
        <li class="page-item"><a class="page-link" href="./?parametername_index=0<bx:if>&searchvalue=<bx:pagedata.request name="searchvalue"/></bx:if>" title="zur ersten Seite"><i class="fa fa-fast-backward" aria-hidden="true"></i> zur Seite 1</a></li>

        <bx:recorddata.previouslist type="if"><li class="page-item"><a class="page-link" href="./?parametername_index=<bx:Recorddata.previouslist type="index"/><bx:if>&searchvalue=<bx:pagedata.request name="searchvalue"/></bx:if>" title="eine Seite zurück"><i class="fa fa-backward" aria-hidden="true"></i></a></li></bx:recorddata.previouslist>
      
        <bx:recorddata.navlist max="5">
          <bx:recorddata.navlistcurrent not>
            <li class="page-item"><a class="page-link" href="./?parametername_index=<bx:recorddata.navlistindex/><bx:if>&searchvalue=<bx:pagedata.request name="searchvalue"/></bx:if>" title="Zur Seite <bx:recorddata.navlistpage/>"><bx:recorddata.navlistpage/></a></li>
          </bx:recorddata.navlistcurrent>
          <bx:recorddata.navlistcurrent>
            <li class="page-item active"><a class="page-link" href="#"><bx:recorddata.navlistpage/> <span class="sr-only">(current)</span></a></li>
          </bx:recorddata.navlistcurrent>
        </bx:recorddata.navlist>
      
        <bx:recorddata.nextlist type="if"><li class="page-item"><a class="page-link" href="./?parametername_index=<bx:Recorddata.nextlist type="index"/><bx:if>&searchvalue=<bx:pagedata.request name="searchvalue"/></bx:if>" title="eine Seite vor"><i class="fa fa-forward" aria-hidden="true"></i></a></li></bx:recorddata.nextlist>
    
        <li class="page-item"><a class="page-link" href="./?parametername_index=<bx:recorddata.lastlist type="index"/><bx:if>&searchvalue=<bx:pagedata.request name="searchvalue"/></bx:if>" title="zur letzten Seite">zur Seite <bx:recorddata.totalpages/> <i class="fa fa-fast-forward" aria-hidden="true"></i></a></li>
      </ul>
    </nav>
  </bx:recorddata.nav>
</bx:recorddata.empty>
```

# CSS-Menü

<!-- last_modified: 20. Jun 2016 -->
Beispielcode für ein einfaches Menü

```xml
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<title>Batix Testmenü mit CSS</title>
<link rel="stylesheet" href="batix-css-menue.css" type="text/css">
</head>
<body>
 
<div class="BX_cssmenue">
  <ul>
    <bx:sitemap.0>
     <li><!--[if IE]><!--><a<bx:sitemap.if hasChilds> class="submenue"</bx:sitemap.if> href="/www/<bx:pagedata.webdir/>/<bx:navigation.path/>/" target="<bx:navigation.target default="_self"/>" title="<bx:navigation.meta name="meta"/>"><!--<![endif]--><bx:sitemap.name/>
      <!--[if gt IE 6]><!--></a><!--<![endif]--><!--[if lte IE 6]><table><tr><td><![endif]-->
        <bx:sitemap.if hasChilds><ul></bx:sitemap.if>
          <bx:sitemap.1>
           <li class="<bx:sitemap.if first>firstitem</bx:sitemap.if><bx:sitemap.if last>lastitem</bx:sitemap.if>"><a<bx:sitemap.if hasChilds> class="submenue"</bx:sitemap.if> href="/www/<bx:pagedata.webdir/>/<bx:navigation.path/>/" target="<bx:navigation.target default="_self"/>" title="<bx:navigation.meta name="meta"/>"><bx:sitemap.name/>
            <!--[if gt IE 6]><!--></a><!--<![endif]--><!--[if lte IE 6]><table><tr><td><![endif]-->
              <bx:sitemap.if hasCHilds><ul></bx:sitemap.if>
                <bx:sitemap.2>
                 <li class="<bx:sitemap.if first>firstitem</bx:sitemap.if><bx:sitemap.if last>lastitem</bx:sitemap.if>"><a<bx:sitemap.if hasChilds> class="submenue"/</bx:sitemap.if> href="/www/<bx:pagedata.webdir/>/<bx:navigation.path/>/" target="<bx:navigation.target default="_self"/>" title="<bx:navigation.meta name="meta"/>"><bx:sitemap.name/></a></li>
                </bx:sitemap.2>
              <bx:sitemap.if hasCHilds></ul></bx:sitemap.if>
            <!--[if lte IE 6]></td></tr></table></a><![endif]-->
           </li>
          </bx:sitemap.1>
        <bx:sitemap.if hasChilds></ul></bx:sitemap.if>
      <!--[if lte IE 6]></td></tr></table></a><![endif]-->
     </li>
   </bx:sitemap.0>
  </ul>
</div>
 
</body>
</html>
```

Beispiel für die dazugehörige css-Datei

```xml
 .BX_cssmenue {
  width:600px;
  height:25px;
  border:1px solid #98b1c4;
  background:#bdcedc;
  z-index:100;
  position:relative;
}
.BX_cssmenue ul {
  float:left;
  list-style-type:none;
  position:relative;
  margin:0;
  padding:0;
}
.BX_cssmenue li {
  float:left;
}
.BX_cssmenue li:hover,.BX_cssmenue li a:hover {
  position:relative;
}
.BX_cssmenue a {
  display:block;
  float:left;
  height:25px;
  white-space:nowrap;
  padding:0 10px 0 10px;
  line-height:25px;
  font-size:12px;
  font-weight:bold;
  font-family:Arial,Helvetica,sans-serif;
  text-align:center;
  color:#293d6b;
  text-decoration:none;
}
.BX_cssmenue li:hover a,.BX_cssmenue a:hover {
  background:#98b1c4;
}
.BX_cssmenue a.submenue {
  background:url(/static/dev/css-menu/top-sub.gif) no-repeat center right;
  padding:0 20px 0 10px;
}
.BX_cssmenue li:hover a.submenue,.BX_cssmenue a.submenue:hover {
  background:#98b1c4 url(/static/dev/css-menu/top-sub.gif) no-repeat center right;
}
.BX_cssmenue ul ul {
  position:absolute;left:-5000px;
  top:-5000px;
  width:202px;
  height:auto;
  border:none;
  background:#bdcedc;
}
.BX_cssmenue table {
  margin-top:-1px;
  border-collapse:collapse;
}
.BX_cssmenue ul :hover ul {
  left:0px;
  top:25px;
}
.BX_cssmenue li li {
  width:200px;
  border:1px solid #98b1c4;
  border-width:0 1px;
  padding:0
}
.BX_cssmenue li li.firstitem {
  border-top:1px solid #98b1c4;
}
.BX_cssmenue li li.lastitem {
  border-bottom:1px solid #98b1c4;
}
.BX_cssmenue ul ul a,.BX_cssmenue ul :hover ul a,.BX_cssmenue ul :hover ul :hover ul a {
  float:none;
  margin:0;
  width:180px;
  height:auto;
  white-space:normal;
  padding:4px 10px 5px 10px;
  font:bold 12px Arial,Helvetica,sans-serif;
  text-decoration:none;
  text-align:left;
  color:#293d6b;
  background:none;
}
.BX_cssmenue ul ul :hover a,.BX_cssmenue ul ul a:hover,.BX_cssmenue ul ul :hover ul :hover a,.BX_cssmenue ul ul :hover ul a:hover {
  background:#98b1c4;
}
.BX_cssmenue ul ul a.submenue,.BX_cssmenue ul :hover ul a.submenue {
  width:180px;
  padding:4px 10px 5px 10px;
  background:url(/static/dev/css-menu/sub-sub.gif) no-repeat center right;
}
.BX_cssmenue ul ul :hover a.submenue,.BX_cssmenue ul ul a.submenue:hover  {
  background:#98b1c4 url(/static/dev/css-menu/sub-sub.gif) no-repeat center right;
}
.BX_cssmenue ul :hover ul ul {
  position:absolute;
  left:-5000px;
  top:-5000px;
}
.BX_cssmenue ul :hover ul :hover ul {
  left:190px;
  top:-1px;
}
.BX_cssmenue br {
  clear:both;
  height:0;
  font-size: 1px;
  line-height: 0px;
 }
```

Link zur Demo-Seite mit diesem Code <a href="http://dev.batix.local/www/dev/purecssmenu/" target="_blank">http://dev.batix.local/www/dev/purecssmenu/</a>

# CSV-Import in Container

<!-- last_modified: 20. Jun 2016 -->
Die Daten einer zuvor hochgeladene CSV-Datei werden in einen Container gespeichert. Es ist auch möglich, eine ZIP-Datei mit verschiedenen CSV-Dateien hochzuladen.

Datei  
    Feldname der zuvor hochgeladenen Datei  
ID_ZielContainer  
    Angabe der ID, wenn der Name nicht anderweitig ermittelt werden kann (z.B. durch Dateiname oder 1. Zeile in der Datei)  
ZielContainer_aus_Datei  
    noch nicht benutzt  
ZielContainer_aus_Dateiname  
    wenn angehakt, dann wird als Zielcontainer der Name der Datei genommen.  
ZielContainer_in_Zeile  
    Angabe der Zeile, in der der Name des Zielcontainers steht (im Beispiel unten wäre das die 1)  
Feldnamen_in_Zeile  
    Zeilennummer der Zeile, in der die Feldname stehen (im Beispiel unten wäre das die 2)  
Trennzeichen  
    Trennzeichen, mit der die Dateifelder getrennt sind (z.B. , )  
Daten_ab_Zeile  
    Nummer der Zeile, ab der die Daten beginnen (im Beispiel unten wäre das die 3)  
Feldnamenliste  
    Wenn in der Importdatei keine Feldnamen enthalten sind, dann können diese hier angegeben werden.  
Namens-Umwandlung  
    Zeilenweise Liste: CSV-Feldname=Feldname im Container oder Dateiname=ZielContainerID  

Beispielaufbau einer CSV-Datei:

Kontakt  
Name,Vorname,Abteilung,Telefon,Email  
Mustermann,Paul,Datensicherheit,03671/223344,test@<a href="http://batix.com" target="_blank">batix.com</a>  
Wurst,Hans,Marketing,090/345678,hawu@<a href="http://dotcom.com" target="_blank">dotcom.com</a>  
...

# Eingeloggt bleiben

<!-- last_modified: 10. Mar 2017 -->
## Variante 1 - über Sessiongültigkeit

Im Login-Action trägt man im Baustein "Login" im Feld "minimale Sessionlänge" ein, wie lange die Session haltbar ist (in Minuten, 1 Monat = 43200 Minuten).

Danach legt man einen Groovy-Baustein an, wo geprüft wird, ob das Häkchen "eingeloggt bleiben" gesetzt ist. Wenn ja, wird ein Cookie "JSESSIONID" geschrieben, der dann im Browser mit der gleichen Haltbarkeit wie im vorherigen Login-Baustein gespeichert wird (in Sekunden, 1 Monat = 2592000 Sekunden).

```xml
import javax.servlet.http.Cookie;

if (action.getParameter("remember") == "j") {
  Cookie c = new Cookie("JSESSIONID", session.id)
  c.maxAge = 2592000 // Sekunden
  c.path ="/"
  action.originalResponse.addCookie(c)
}
```

Allerding liegen dann viele offene Sessions auf dem Server rum - ist dann wohl eher für kleinere Projekte interessant.

# Formularversand mit Ajax

<!-- last_modified: 20. Jun 2016 -->
Dieses Beispiel veranschaulicht die Möglichkeit Formulardaten mittels jQuery per Ajax versenden. Voraussetzung hierfür ist das Einbinden des jQuery-Frameworks und des speziellen Scriptes jquery.form.js

```xml
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<title>Beispieldokument</title>
 
<script type="text/javascript" src="jquery-1.4.1.min.js"></script>
<script type="text/javascript" src="jquery.form.js"></script>
<script type="text/javascript">
  // warten bis die DOM-Struktur geladen ist 
  $(document).ready(function() {
    var options = { 
      target:        '#div_suchergebnisse'   // Element in das die Serverantwort geschrieben wird
      //beforeSubmit:  showRequest,  // optionale Funktion vor dem Absenden des Formulares 
      //success:       showResponse  // optionale Funktion nach dem Absenden des Formulares 
    };
    // Anbindung des betreffenden Formulares, dass per Ajax versendet werden soll (mehrere möglich) 
    $('#testform').ajaxForm(options) 
  });
</script>
 
</head>
<body>
 
  <form name="testform" id="testform" method="post" action="zieladresse.htm">
    <input type="hidden" name="field1"  id="field1" value="">
    <input type="text" name="field2"  id="field2" value=""><br>
    <input type="text" name="field3"  id="field3" value="">
    <input type="submit" value="absenden">
  </form>
 
  <div id="div_suchergebnisse">
    Hier landet das Ergebnis der Suche
  </div>
 
</body>
</html>
```

Es sind noch wesentlich mehr Optionen für diese Funktion verfügbar.  
Mehr Informationen und Script-Download unter <a href="http://jquery.malsup.com/form/#getting-started" target="_blank">http://jquery.malsup.com/form/#getting-started</a>

# Google-Sitemap Datei erzeugen

<!-- last_modified: 17. Jun 2016 -->
Diese Beispiel realisiert folgende Funktionen:

- eine dynamische Sitemap im XML-Format generieren, die Suchmaschinen beim Indizieren hilft

Folgende Tags wurde verwendet:

- [Bx:pagedata](/books/cms-handbuch-entwickler/page/bxpagedata)
- [Bx:sitemap](/books/cms-handbuch-entwickler/page/bxsitemap)
- [Bx:tools](/books/cms-handbuch-entwickler/page/bxtools)

## Quellcode

Dieser Code wird als Designtemplate gespeichert und im Startseiten-Menüpunkt z.B. als sitemap.xml eingebunden. Es ist wichtig, dass diese Datei im obersten Verzeichnis des Projektes liegt, da immer nur URLs unterhalb des Pfades dieser Datei indiziert werden.

```xml
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<bx:sitemap.1>
	<url>
		<loc>http://<bx:pagedata.hostname/>/www/<bx:pagedata.webdir/>/<bx:sitemap.path/>/</loc>
		<lastmod><bx:tools.lastmodified pattern="yyyy-MM-dd" />T<bx:tools.lastmodified pattern="hh:mm:ss" />+00:00</lastmod>
		<changefreq>weekly</changefreq>
		<priority>1</priority>
	</url>
<bx:sitemap.2>
	<url>
		<loc>http://<bx:pagedata.hostname/>/www/<bx:pagedata.webdir/>/<bx:sitemap.path/>/</loc>
		<lastmod><bx:tools.lastmodified pattern="yyyy-MM-dd" />T<bx:tools.lastmodified pattern="hh:mm:ss" />+00:00</lastmod>
		<changefreq>weekly</changefreq>
		<priority>0.75</priority>
	</url>
<bx:sitemap.3>
	<url>
		<loc>http://<bx:pagedata.hostname/>/www/<bx:pagedata.webdir/>/<bx:sitemap.path/>/</loc>
		<lastmod><bx:tools.lastmodified pattern="yyyy-MM-dd" />T<bx:tools.lastmodified pattern="hh:mm:ss" />+00:00</lastmod>
		<changefreq>weekly</changefreq>
		<priority>0.5</priority>
	</url>
<bx:sitemap.4>
	<url>
		<loc>http://<bx:pagedata.hostname/>/www/<bx:pagedata.webdir/>/<bx:sitemap.path/>/</loc>
		<lastmod><bx:tools.datum pattern="yyyy-MM-dd" day="-3"/></lastmod>
		<changefreq>weekly</changefreq>
		<priority>0.25</priority>
	</url>
<bx:sitemap.5>
	<url>
		<loc>http://<bx:pagedata.hostname/>/www/<bx:pagedata.webdir/>/<bx:sitemap.path/>/</loc>
		<lastmod><bx:tools.datum pattern="yyyy-MM-dd" day="-3"/></lastmod>
		<changefreq>weekly</changefreq>
		<priority>0.20</priority>
	</url>
</bx:sitemap.5>
</bx:sitemap.4>
</bx:sitemap.3>
</bx:sitemap.2>
</bx:sitemap.1>
</urlset>
```

Es werden alle Menüpunkte bis zu einer Tiefe von 5 Ordnern ausgegeben. `priority` ist lediglich eine relative, projekt-interne Angabe und wird von Suchmaschinen genutzt, um bestimmte Links bei einer Auswahl von mehreren Links im Projekt zu priorisieren, diese Angabe hat keine Auswirkung auf das Ranking in der Suchmaschine.

Bei `lastmod` wurden 2 verschiedene Implementierungen genutzt. Mittels [bx:tools.lastmodified](/books/cms-handbuch-entwickler/page/bxtools) wird allerdings nur das Bearbeitungsdatum des Hauptmenüpunktes zurückgegeben (nicht das der einzelnen Menüpunkte), [bx:tools.datum](/books/cms-handbuch-entwickler/page/bxtools) dagegen liefert immer "Heute - 3 Tage". Welche Möglichkeit genutzt wird, kann nicht verallgemeinert werden (optimal wäre das Bearbeitungsdatum des jeweiligen Menüpunktes).

# HTML-Mails für MS-Outlook

<!-- last_modified: 20. Jun 2016 -->
E-Mails im HTML-Format benötigen ein sehr spezielles Design, um in Outlook korrekt angezeigt zu werden. Es gibt eine ganze Reihe HTML- und CSS-Elemente, die nicht erlaubt sind (z.B. Div's, Hintergrundbilder, Positionierungen etc.).

Eine komplette Liste aller erlaubten/nicht erlaubten Elemente und Parameter finden Sie unter <a href="http://msdn.microsoft.com/en-us/library/aa338201.aspx" target="_blank">http://msdn.microsoft.com/en-us/library/aa338201.aspx</a>.

Die große Kunst beim HTML-Mail-Design besteht darin, dass die Mails nicht nur in allen Browsern, sondern auch in allen E-Mail-Clients aussehen müssen. Während fast alle Mail-Clients und Webmailer keine Probleme mit der Darstellung haben, kommt Outlook mit modernem HTML-Design überhaupt nicht zurecht und verlangt nach Quellcode, wie er in den frühen 90er Jahren zu finden war. Mail-Designs müssen für Outlook wieder umständlich mit Tabellen, zerschnippelten Bildern und Platzhalter-GIF's erzeugt werden.

Wer hierfür Beispiele braucht, sollte die Newsletter von ALTEC Solartechnik oder Waldbad Brunn abonnieren.

# Kalender bauen

<!-- last_modified: 07. Oct 2014 -->
Benutzt werden die beiden Tags [`bx:calendarloop`](/books/cms-handbuch-entwickler/page/bxcalendarloop) und [`bx:calenderfield`](/books/cms-handbuch-entwickler/page/bx-calenderfield)

```xml
<table class="calendar1">
    <tr class="head">
      <td colspan="7">
        <div class="month">
          <span><a href="./?<bx:calendarfield.month link="prev" object="Kalender"/>" title="einen Monat zurück">&laquo;</a></span>
          <span><bx:calendarfield.month object="Kalender"/></span>
          <span><a href="./?<bx:calendarfield.month link="next" object="Kalender"/>" title="einen Monat vor" >&raquo;</a></span>
        </div>
        <div class="year">
          <span><a href="./?<bx:calendarfield.year link="prev" object="Kalender"/>" title="ein Jahr zurück">&laquo;</a></span>
          <span><bx:calendarfield.year object="Kalender"/></span>
          <span><a href="./?<bx:calendarfield.year link="next" object="Kalender"/>" title="ein Jahr vor">&raquo;</a></span>
        </div>
        <div style="clear:both;"></div>
      </td>
    </tr>
    <tr class="daynames">
      <td>Mo</td>
      <td>Di</td>
      <td>Mi</td>
      <td>Do</td>
      <td>Fr</td>
      <td class="we">Sa</td>
      <td class="we">So</td>
    </tr>
  <bx:calendarloop.Kalender activedayrequest="filter" pool="12549B83FF8" datestart="Startdatum" dateend="Endedatum">
    <bx:calendarfield.if firstweekday><tr class="days"></bx:calendarfield.if>
      <td class="
      <bx:calendarfield.if currentmonth="false">othermonth</bx:calendarfield.if>
      <bx:calendarfield.if weekend>we</bx:calendarfield.if>
      <bx:calendarfield.if mark>marked</bx:calendarfield.if>
      <bx:calendarfield.if today>today</bx:calendarfield.if>">
        <a href="./?filter=<bx:calendarfield.day pattern="dd."/><bx:calendarfield.month pattern="MM."/><bx:calendarfield.year pattern="yyyy"/>"><bx:calendarfield.day pattern="d"/></a>
      </td>
    <bx:calendarfield.if lastweekday></tr></bx:calendarfield.if>
  </bx:calendarloop.Kalender>
  <tr class="footer">
    <td colspan="7">
      <a href="">Heute</a>
    </td>
  </tr>
</table>
```

**zugehöriges CSS**

```css
table.calendar1 a{color:#555555;}
table.calendar1 td{width:20px;height:20px;text-align:center;}
table.calendar1 .head td{background-color:#FFB689;}
table.calendar1 .head .month{float:left;padding-left:5px;}
table.calendar1 .head .year{float:right;padding-right:5px;}
table.calendar1 .daynames td{background-color:#aaaaaa;}
table.calendar1 .daynames .we{color:#962420;font-weight:bold;}
table.calendar1 .days td{background-color:#cccccc;}
table.calendar1 .days td.marked{background-color:#FBD9CA;}
table.calendar1 .days td.today{outline:1px solid red;}
table.calendar1 .days td.active{outline:1px solid green;}
table.calendar1 .days td.othermonth{background-color:#eeeeee;}
table.calendar1 .days td.othermonth a{color:#ffffff !important;}
table.calendar1 .days td.we a{color:#962420;font-weight:bold;}
table.calendar1 .footer td{background-color:#FFB689;}
```

# Locale bei Date-Pattern hinzufügen

<!-- last_modified: 29. Sep 2016 -->
1. Projekt auswählen
2. bei **Dokumentvorlagen** rechts unter Tools auf **Quelltext ersetzen** klicken
3. in das erste Textfeld (**Suchbegriff**) eintragen:  
`pattern="([^"]*(?:MMM|E)[^"]*)"(?! locale)`
4. in das zweite Textfeld (**Ersetzen durch**) eintragen:  
`pattern="$1" locale="de"`
5. Haken **regulärer Ausdruck** setzen
6. auf **Vorschau** klicken und prüfen, ob alles passt
7. auf **jetzt ersetzen** klicken
8. ggf. Schritte 6 und 7 wiederholen, falls viele Quelltexte betroffen sind

# Manipulationsgeschützte Formulare mit Secureform

<!-- last_modified: 17. Mar 2017 -->
Vom System generierte Werte in Formularen sind leicht veränderbar. Falls in den Aktionen keine Überprüfungen dieser Werte vorhanden sind, entstehen schnell Sicherheitslecks. Parameter können dann beliebig manipuliert werden und die Aktionsbausteine verrichten unbedarft ihren Dienst mit gefälschten Daten. So können z.B. IDs ausgetauscht werden und somit fremde Datensätze überschrieben werden.

Damit nicht in jeder Aktion selbst eine Überprüfung in JSP oder Groovy geschrieben werden muss, gibt es das Tag [`bx:secureform`](/books/cms-handbuch-entwickler/page/bxsecureform) und die Aktion [Sicheres Formular überprüfen (SecureformAction)](/books/cms-handbuch-entwickler/page/sicheres-formular-uberprufen-secureformaction-secureformaction). Im Zusammenspiel stellen diese beiden Komponenten sicher, dass ausgewählte Parameter nicht manipuliert werden können.

Dieser Artikel bietet eine detaillierte Erklärung der Funktion und Vorgehensweise. Es sollten zusätzlich die Seiten des Tags und der Aktion durchgelesen werden.

## Parameter sammeln

### Im Formular

Im ersten Schritt werden die zu sichernden Formularelemente gesammelt. Das sind jene Parameter, die später an das Action geschickt werden. Es müssen nicht alle Parameter abgesichert werden, nur jene die im Action als zu sichern angegeben wurden.

Zunächst wird um das gesamte Formular ein `<bx:secureform>` Tag gesetzt. Dies definiert einen Bereich, in dem Parameter gesammelt werden. Dadurch können auf einer Seite mehrere solche Bereiche definiert werden, falls es mehrere Formulare gibt.

**Bereich definieren**

```xml
<bx:secureform>
  <form action="...">
  </form>
</bx:secureform>
```

Danach werden die zu schützenden Parameterwerte gesammelt. In den meisten Fällen wird der `value` eines `<input type="hidden">` einfach mit `<bx:secureform.field>` umschlossen.

**Parameter sammeln**

```xml
<bx:secureform>
  <form action="...">
    <input type="hidden" name="Besitzer" value="<bx:secureform.field name="Besitzer"><bx:userdata.id /></bx:secureform.field>">
  </form>
</bx:secureform>
```

Falls ein Parameter im Formular geschützt wird, muss er auf jeden Fall auch in den Aktionseinstellungen angegeben werden (s.u.) - da die Prüfung im Baustein sonst fehlschlägt.

Parameter, die nicht mitgesendet werden, falls sie keinen Wert haben, dürfen nicht mit zur Hashbildung herangezogen werden. Das sind z.B. Datensatz-ID Felder, die nur bei fehlerhaften Validierungen gefüllt werden, damit beim erneuten Absenden des Formulars kein neuer Datensatz erzeugt wird. Meist kommt dabei `<bx:containerfilter dummy>` oder `<bx:record dummy>` zum Einsatz. Der Parameter `hidden-when-empty` bewirkt, dass ein Feld mit leerem Wert von `<bx:secureform.field>` ignoriert wird.

**hidden-when-empty**

```xml
 <bx:secureform>
  <form action="...">
    <bx:if><input type="hidden" name="kid" value="<bx:secureform.field name="kid" hidden-when-empty><bx:recorddata.id /></bx:secureform.field>"></bx:if>
    <input type="hidden" name="Besitzer" value="<bx:secureform.field name="Besitzer"><bx:userdata.id /></bx:secureform.field>">
  </form>
</bx:secureform>
```

Zum Schluss wird der Hash generiert und in das Formular geschrieben. Die einfachste Methode ist vom System direkt ein `<input type="hidden">` generieren zu lassen.

**Hash ausgeben**

```xml
<bx:secureform>
  <form action="...">
    <bx:if><input type="hidden" name="kid" value="<bx:secureform.field name="kid" hidden-when-empty><bx:recorddata.id /></bx:secureform.field>"></bx:if>
    <input type="hidden" name="Besitzer" value="<bx:secureform.field name="Besitzer"><bx:userdata.id /></bx:secureform.field>">
    <bx:secureform.hash />
  </form>
</bx:secureform>
```

Dies erzeugt ein verstecktes Formularfeld mit passendem Name und Wert. Alternativ kann der Name oder Wert auch einzeln ausgegeben werden, siehe dazu die [Tag Doku](/books/cms-handbuch-entwickler/page/bxsecureform).

### Im Link

Das Tag kann auch benutzt werden, um einen Link / Button abzusichern:

```xml
<bx:secureform>
  <a href="delete.act?kid=<bx:secureform.field name="kid"><bx:recorddata.id /></bx:secureform.field>&<bx:secureform.hash name />=<bx:secureform.hash value />">löschen</a>
</bx:secureform> 
```

Hier werden die Parameter `name` und `value` von `bx:securefom.hash` benutzt, denn beide Werte sind dynamisch.

Falls URL-Parameter mit z.B. `bx:if` umschlossen sind, muss auch wieder `hidden-when-empty` benutzt werden (s.o.).

## Erlaubte Werte festlegen

Falls ein Parameter mehrere, bestimmte Werte annehmen darf, ist dies mit `bx:secureform.values` abbildbar. In diesem Fall wird nicht das Feld mit dem Wert gehasht (da es vom Nutzer ja geändert werden kann), sondern ein zweites Feld eingefügt. Es enthält die erlaubten Werte und wird anstelle des veränderlichen Feldes mitgehasht.

So kann sich der Inhalt des Feldes (z.B. ein `<select>`) ändern, es wird aber trotzdem eine abgesicherte Information über die erlaubten Werte mitgeschickt.

Der Parametername wird normal in die Aktion eingetragen, diese unterscheidet aber, ob ein Info-Parameter mit den erlaubten Werten übergeben wurde oder nur der Normale und zieht dann den entsprechenden Parameter zur Hashbildung heran.

### Im Formular

**mehrere erlaubte Werte (Formular)**

```xml
<select name="Anrede">
  <option value="<bx:secureform.values name="Anrede">m</bx:secureform.values>">Herr</option>
  <option value="<bx:secureform.values name="Anrede">w</bx:secureform.values>">Frau</option>
</select>
<bx:secureform.values name="Anrede" />
```

Das Tag in der geschlossenen Variante erzeugt automatisch ein `<input type="hidden">` mit passenden `name` und `value` Attributen.

### Im Link

**mehrere erlaubte Werte (Link)**

```javascript
var url = "save.act?";
// ...andere (ggf. abgesicherte) Parameter, wie z.B. ID...
url += "&Anrede=" + encodeURIComponent($("[name=Anrede]").val());
url += "&<bx:secureform.values name="Anrede" param encode="javascript" />=<bx:secureform.values name="Anrede" values encode="javascript" />"
```

## Aktion absichern

Um eine Aktion abzusichern, wird ein neuer [Sicheres Formular überprüfen (SecureformAction)](/books/cms-handbuch-entwickler/page/sicheres-formular-uberprufen-secureformaction-secureformaction) Baustein eingefügt. **Dieser muss an erster Stelle stehen**, damit bei Manipulation die Aktion direkt abgebrochen wird und nachgelagerte Bausteine nicht ausgeführt werden.

In der *Liste der abzusichernden Request-Parameter* werden all die Parameter aufgezählt, die (falls übergeben) abgesichert sein müssen - d.h. diese Parameter werden zur Hashbildung im Baustein herangezogen. Das bedingt natürlich, dass diese Parameter auch im Formular eingesammelt wurden. Umgedreht gilt dasselbe: Parameter, die im Formular gesammelt wurden, müssen auch im Aktionsbaustein gelistet sein.

Im unteren Feld kann eine URL für den Fehlerfall spezifiziert werden. Hierhin wird weitergeleitet, sobald die Prüfung fehlschlägt. Wurde keine URL angegeben und die Prüfung schlägt fehl, so wird die gesamte Aktion mit einer Fehlermeldung abgebrochen.

![image2016-4-24 21:56:43.png](https://batix.help/uploads/images/gallery/2026-05/wAn4GyBzj8ju60nP-4489684.png)

Steht ein Parameter in der Liste, wurde aber nicht übergeben, so wird er vom Baustein nicht zu Hashbildung herangezogen.

<p class="callout info">Die Liste kann auch für Parameter verwendet werden, die der Aktion niemals übergeben werden dürfen (falls z.B. andere Bausteine schlecht darauf reagieren).<br><br>Da diese nicht im Formular gesammelt werden und somit nicht in den Hash einfließen, wird vom Formular ein anderer Hash erzeugt, als von der Aktion (da diese den Parameter mit in die Berechnung integriert, da er in der Liste steht).</p>

## Seite absichern

Analog zum Absichern einer Aktion existiert die Möglichkeit ein Template abzusichern. Dies kann z.B. verwendet werden, um bestimmte Parameter einer Listen- oder Detail-Seite abzusichern ("Kontakttyp darf nur Kunde sein" oder "Gruppe muss 123ABC oder 456DEF sein").

Hierfür gibt es das Tag [`<bx:secureform.check>`](/books/cms-handbuch-entwickler/page/bxsecureform), welches ganz oben in der Seite eingebaut wird und die Abarbeitung der Seite abbricht, sobald etwas manipuliert wurde. Optional kann auch eine URL angegeben werden, auf die weitergeleitet wird.

**einfache Prüfung in Template**

```xml
<bx:secureform.check securelist="Kategorie" />
<!DOCTYPE html>
<html>
...
```

## Funktionsweise

Das Verfahren beruht auf kryptografischen Hashes. Dies sind Einwegfunktionen, die einen beliebigen Input in einen Output bestimmter Länge transformieren. Diese Berechnung ist nicht umkehrbar und somit ist der Input nicht rekonstruierbar.

Es fließen verschiedene Sachen in die Berechnung des Hashes ein. Allein die Parameternamen und -werte genügen nicht, da sonst der Hash von einem Angreifer selbst gebildet werden könnte. Der Algorithmus ist im Allgemeinen bekannt oder kann rekonstruiert werden.

Daher werden zusätzlich serverseitig generierte bzw. gespeicherte Werte für die Berechnung des Hashes benutzt. Diese Werte werden dem Client nicht mitgeteilt und er kann diese auch nicht auslesen. Nur das Tag und das Action kennen diese und können damit den korrekten Hash bilden.

Alle Parameter, die im Formular zum Hashen gesammelt und im Request mitgeschickt wurden, müssen auch in den Aktioneinstellungen angegeben werden. Umgekehrt müssen aber nicht alle Parameter, die im Aktionsbaustein stehen, auch im Request vorhanden sein. Falls sie vorhanden sind, müssen sie allerdings auch abgesichert sein. Das Formular und die Aktion müssen im Grunde denselben Satz an Parametern zur Hashbildung benutzen, sonst sind die Ergebnisse verschieden.

# Menü mit CSS

<!-- last_modified: 17. Jun 2016 -->
Ein CSS-basiertes Menü, das zur Not auch ohne JavaScript funktioniert und beliebig viele Ebenen darstellen kann.

Zum Betrieb des Menüs sind nur zwei Textbausteine in den HTML-Quelltext zu integrieren.

**Textbaustein 1 für den HTML-Body**

```xml
<!-- #################### Beginn CSS-Menü #################### -->

<ul id="qm0" class="qmmc">
  <bx:sitemap.0>
    <li><a class="<bx:sitemap.if hasChilds>qmparent</bx:sitemap.if><bx:sitemap.IF open> qmactive</bx:sitemap.IF>" href="/www/<bx:pagedata.webdir/>/<bx:navigation.path/>/"><bx:sitemap.name/></a>
    <bx:sitemap.iF hasChilds>
      <ul>
        <bx:sitemap.1>
          <li><a<bx:sitemap.if hasChilds> class="qmparent<bx:sitemap.IF open> qmactive</bx:sitemap.IF>"</bx:sitemap.if> href="/www/<bx:pagedata.webdir/>/<bx:navigation.path/>/"><bx:sitemap.name/></a>
            <bx:sitemap.IF hasChilds>
              <ul style="width:auto;">
                <bx:sitemap.2>
                  <li><a<bx:sitemap.if hasChilds> class="qmparent"</bx:sitemap.if> href="/www/<bx:pagedata.webdir/>/<bx:navigation.path/>/"><bx:sitemap.name/></a>
                    <bx:sitemap.if hasChilds>
                      <ul>
                        <bx:sitemap.3>
                          <li><a href="/www/<bx:pagedata.webdir/>/<bx:navigation.path/>/"><bx:sitemap.name/></a></li>
                        </bx:sitemap.3>
                      </ul>
                    </bx:sitemap.if>
                  </li>
                </bx:sitemap.2>
              </ul>
            </bx:sitemap.IF>
          </li>
        </bx:sitemap.1>
      </ul>
    </bx:sitemap.iF>
    </li>
  </bx:sitemap.0>
  <li class="qmclear"> </li>
</ul>

<!-- ##################### Ende CSS-Menü ##################### -->

<!-- Create Menu Settings: (Menu ID, Is Vertical, Show Timer, Hide Timer, On Click ('all' or 'lev2'), Right to Left, Horizontal Subs, Flush Left, Flush Top) -->
<script type="text/javascript">qm_create(0,false,100,500,false,false,false,false,false);</script>
```

**Textbaustein 2 für den HTML-Head**

```xml
<!-- #################### Beginn Styles für CSS-Menü #################### -->
<style type="text/css">


/*!!!!!!!!!!! Diese Styles nicht ändern !!!!!!!!!!!!!*/
.qmmc .qmdivider{display:block;font-size:1px;border-width:0px;border-style:solid;position:relative;z-index:1;}.qmmc .qmdividery{float:left;width:0px;}.qmmc .qmtitle{display:block;cursor:default;white-space:nowrap;position:relative;z-index:1;}.qmclear {font-size:1px;height:0px;width:0px;clear:left;line-height:0px;display:block;float:none !important;}.qmmc {position:relative;zoom:1;z-index:10;}.qmmc a, .qmmc li {float:left;display:block;white-space:nowrap;position:relative;z-index:1;}.qmmc div a, .qmmc ul a, .qmmc ul li {float:none;}.qmsh div a {float:left;}.qmmc div{visibility:hidden;position:absolute;}.qmmc li {z-index:auto;}.qmmc ul {left:-10000px;position:absolute;z-index:10;}.qmmc, .qmmc ul {list-style:none;padding:0px;margin:0px;}.qmmc li a {float:none}.qmmc li:hover>ul{left:auto;}#qm0 ul {top:100%;}#qm0 ul li:hover>ul{top:0px;left:100%;}


/*!!!!!!!!! Diese Styles zur individuellen Anpassung verändern !!!!!!!!!*/

  /*"""""""" (MAIN) Container"""""""""""*/	
  #qm0	
  {	
    padding:0px;
    margin:20px 0 0 15px;
  }

  /*"""""""" (MAIN) Items"""""""""""*/	
  #qm0 a	
  {	
    padding:2px 40px 2px 10px;
    background-color:#A20002;
    color:#FFFFFF;
    font-family:Arial;
    font-size:12px;
    text-decoration:none;
    font-weight:bold;
    text-align:left;
    border-width:1px 0px 1px 2px;
    border-style:solid;
    border-color:#7C0000;
    -moz-border-top-left-radius:7px;
    border-top-left-radius:7px;
    -moz-border-top-right-radius:7px;
    border-top-right-radius:7px;
  }

  /*"""""""" (MAIN) Hover State"""""""""""*/	
  #qm0 a:hover	
  {	
    background-color:#7C0000;
    color:#FFFC85;
  }

  /*"""""""" (MAIN) Active State"""""""""""*/	
  body #qm0 .qmactive, body #qm0 .qmactive:hover	
  {	
    background-color:#7C0000;
    color:#FFFC85;
  }

  /*"""""""" (MAIN) Persistent State"""""""""""*/	
  body #qm0 .qmpersistent, body #qm0 .qmpersistent:hover	
  {	
    background-color:#7C0000;
  }

  /*"""""""" (SUB) Container"""""""""""*/	
  #qm0 div, #qm0 ul	
  {	
    background-color:#A20002;
    border-width:1px;
    border-style:solid;
    border-color:#7C0000;
  }

  /*"""""""" (SUB) Items"""""""""""*/	
  #qm0 div a, #qm0 ul a	
  {	
    padding:4px 20px 4px 15px;
    color:#FFFFFF;
    font-size:12px;
    font-weight:normal;
    text-align:left;
    border-width:0px 0px 1px;
    border-style:solid;
    border-color:#7C0000;
  }

  /*"""""""" (SUB) Hover State"""""""""""*/	
  #qm0 div a:hover, #qm0 ul a:hover	
  {	
    color:#FFFC85;
    border-color:#7C0000;
  }

  /*"""""""" (SUB) Active State"""""""""""*/	
  body #qm0 div .qmactive, body #qm0 div .qmactive:hover	
  {	
    color:#FFFC85;
  }

  /*"""""""" (SUB) Persistent State"""""""""""*/	
  body #qm0 div .qmpersistent, body #qm0 div .qmpersistent:hover	
  {	
    background-color:#7C0000;
  }


</style>

<!-- ##################### Ende Styles für CSS-Menü ##################### -->

<!-- #################### Beginn Scripts für CSS-Menü ################### -->

<!-- Core MyCSSMenu Code -->
<script type="text/javascript">/* <![CDATA[ */var qm_si,qm_li,qm_lo,qm_tt,qm_th,qm_ts,qm_la,qm_ic,qm_ib;var qp="parentNode";var qc="className";var qm_t=navigator.userAgent;var qm_o=qm_t.indexOf("Opera")+1;var qm_s=qm_t.indexOf("afari")+1;var qm_s2=qm_s&&qm_t.indexOf("ersion/2")+1;var qm_s3=qm_s&&qm_t.indexOf("ersion/3")+1;var qm_n=qm_t.indexOf("Netscape")+1;var qm_v=parseFloat(navigator.vendorSub);;function qm_create(sd,v,ts,th,oc,rl,sh,fl,ft,aux,l){var w="onmouseover";var ww=w;var e="onclick";if(oc){if(oc=="all"||(oc=="lev2"&&l>=2)){w=e;ts=0;}if(oc=="all"||oc=="main"){ww=e;th=0;}}if(!l){l=1;qm_th=th;sd=document.getElementById("qm"+sd);if(window.qm_pure)sd=qm_pure(sd);sd[w]=function(e){qm_kille(e)};document[ww]=qm_bo;if(oc=="main"){qm_ib=true;sd[e]=function(event){qm_ic=true;qm_oo(new Object(),qm_la,1);qm_kille(event)};document.onmouseover=function(){qm_la=null;clearTimeout(qm_tt);qm_tt=null;};}sd.style.zoom=1;if(sh)x2("qmsh",sd,1);if(!v)sd.ch=1;}else  if(sh)sd.ch=1;if(oc)sd.oc=oc;if(sh)sd.sh=1;if(fl)sd.fl=1;if(ft)sd.ft=1;if(rl)sd.rl=1;sd.style.zIndex=l+""+1;var lsp;var sp=sd.childNodes;for(var i=0;i<sp.length;i++){var b=sp[i];if(b.tagName=="A"){lsp=b;b[w]=qm_oo;if(w==e)b.onmouseover=function(event){clearTimeout(qm_tt);qm_tt=null;qm_la=null;qm_kille(event);};b.qmts=ts;if(l==1&&v){b.style.styleFloat="none";b.style.cssFloat="none";}}else  if(b.tagName=="DIV"){if(window.showHelp&&!window.XMLHttpRequest)sp[i].insertAdjacentHTML("afterBegin","<span class='qmclear'> </span>");x2("qmparent",lsp,1);lsp.cdiv=b;b.idiv=lsp;if(qm_n&&qm_v<8&&!b.style.width)b.style.width=b.offsetWidth+"px";new qm_create(b,null,ts,th,oc,rl,sh,fl,ft,aux,l+1);}}};/* ]]> */</script>

<!-- Add-On Core Code (Remove when not using any add-on's) -->
<style type="text/css">.qmfv{visibility:visible !important;}.qmfh{visibility:hidden !important;}</style>
<script type="text/JavaScript">var qmad = new Object();qmad.bvis="";qmad.bhide="";</script>


  <!-- Add-On Settings -->
  <script type="text/JavaScript">

    /*******  Menu 0 Add-On Settings *******/
    var a = qmad.qm0 = new Object();

    // Sub Menu Fade Animation Add On
    a.fade_in_frames = 10;
    a.fade_out_frames = 20;

    // Item Bullets (CSS - Imageless) Add On
    a.ibcss_apply_to = "parent";
    a.ibcss_main_type = "arrow";
    a.ibcss_main_direction = "down";
    a.ibcss_main_size = 5;
    a.ibcss_main_position_x = -16;
    a.ibcss_main_position_y = -5;
    a.ibcss_main_align_x = "right";
    a.ibcss_main_align_y = "middle";
    a.ibcss_sub_type = "arrow";
    a.ibcss_sub_direction = "right";
    a.ibcss_sub_size = 5;
    a.ibcss_sub_position_x = -22;
    a.ibcss_sub_align_x = "right";
    a.ibcss_sub_align_y = "middle";

    // Drop Shadow Add On
    a.shadow_offset = 3;
    a.shadow_color = "#AFAFAF";
    a.shadow_opacity = 1;

    // Keyboard Access Add On
    a.keyboard_access_active = true;

  </script>
```

# Passwort vergessen

<!-- last_modified: 17. Jun 2016 -->
Nach Drücken von "Paßwort vergessen" wird auf eine Seite geleitet (pwvergessen.htm), wo man die E-Mail, mit der man angemeldet ist, eingeben muß. Nach Prüfung wird ein DS im Container "Token" angelegt und eine E-Mail mit einem Link (Token und Email im Request) an die angegebene Adresse geschickt. Nach Klicken des Links öffnet sich eine Seite mit Paßwort-Eingabefeldern. Nach Prüfung der Token-Daten wird das neue PW in der Benutzerverwaltung gespeichert.

## Containeraufbau:

Token - einfaches Textfeld  
Erstelldatum - Datumsfeld  
Email - einfaches Textfeld  
BC - BC-Verknüpfung  
Kontakt - Einzelverknüpfung mit Kontakt-Container

## Actions anlegen:

**pwvergessen.act**

- Filteraction: prüft, ob's die angegebenen Email im Kontakt-Container gibt und ruft *savetoken.act* auf
- Weiterleitung auf Info-Seite

### Beispiele

#### 1.) Actionbaustein "Container-Daten Filteraction" - Prüfen, ob's Email im "Kontakte" gibt

**list:** ID des Kontakte-Containers

**xml:**

&lt;filter&gt;  
  &lt;filter-object required="true"&gt;  
    &lt;field&gt;Kontakt_Email&lt;/field&gt;  
    &lt;type&gt;4&lt;/type&gt;  
    &lt;request-value&gt;email&lt;/request-value&gt;  
  &lt;/filter-object&gt;  
  &lt;limit max="1"/&gt;  
&lt;/filter&gt;

**url:**

savetoken.act?Token=&lt;bx:tools.uuid/&gt;&amp;Kontakt=&lt;bx:recorddata.id/&gt;&amp;BCVerknuepfung=&lt;bx:recordfield.Kontakt_BC&gt;&lt;bx:recorddata.id/&gt;&lt;/bx:recordfield.Kontakt_BC&gt;&amp;Erstelldatum=&lt;bx:tools.urlencode&gt;&lt;bx:tools.datum pattern="dd.MM.yyyy HH:mm"/&gt;&lt;/bx:tools.urlencode&gt;&amp;Email=&lt;bx:recordfield.Kontakt_Email/&gt;

**failurl:**

pwvergessen.htm?fehler=1&amp;email=`[[`email`]]`

#### 2.) Actionbaustein "Weiterleitung" - Weiterleitung

**destination:** mailverschickt.htm

**savetoken.act**

- Speicheraction: erzeugt neuen Token-DS
- CMS-Seite verschicken: mit Link (mit Token und Email)

### Beispiele

#### 1.) Actionbaustein "Container-Daten speichern" - Neuen Token-DS anlegen

**listid:** ID des Token-Containers

**recordidfield:** tokenid

**active**: ja

#### 2.) Actionbaustein "CMS-Seite versenden" - Email mit Token versenden

alle vorherigen Felder ensprechend ausfüllen

**file:** pwemail.htm?tokid=`[[`tokenid`]]`

**checkpw.act**

- prüft, ob Paßwörter da und gleich sind
- Filteraction: sucht Token anhand von Parametern und Datum raus (prüfen, ob noch gültig), ruft *changepw.act* auf

### Beispiele

#### 1.) Aktionsbaustein "vorhandene Bedingung abfragen" - Paßwörter da?

**requestField:** Passwort

**compareValue:** #nodata

**conditionTrue:** changepw.htm?fehler=1&amp;token=`[[`token`]]`&amp;email=`[[`email`]]`

#### 2.) Aktionsbaustein "vorhandene Bedingung abfragen" - Paßwörter gleich?

**requestField:** Passwort

**compareValue:** `[[`Passwortwdhlg`]]`

**conditionFalse:** changepw.htm?fehler=2&amp;token=`[[`token`]]`&amp;email=`[[`email`]]`

#### 3.) Aktionsbaustein "Container-Daten Filteraction" - prüfen, ob Token-DS gültig ist

**list:** ID des Token-Containers

**xml:**

```xml
<filter>
  <filter-object required="true">
    <field>Token</field>
    <type>4</type>
    <request-value>token</request-value>
  </filter-object>
  <filter-object required="true">
    <field>Email</field>
    <type>4</type>
    <request-value>email</request-value>
  </filter-object>
  <filter-object>
    <field>Erstelldatum</field>
    <type>4</type>
    <special-value days="-1">TODAY</special-value>
  </filter-object>
</filter>
```

**url:** changepw.act?user=&lt;bx:recordfield.BCVerknuepfung type="id"/&gt;&amp;Token=&amp;tokid=&lt;bx:recorddata.id/&gt;&amp;password=`[[`Passwort`]]`

**failurl:** changepw.htm?fehler=3

#### 4.) Aktionsbaustein "Weiterleitung" - Weiterleitung

**destination:** ok.htm

**changepw.act**

- PW ändern: ändert in der Benutzerverwaltung das Paßwort
- speichern: löscht den Token im Token-DS, DS selbst bleibt aber erhalten
- Weiterleitung an Info-Seite (Benutzer muß sich nun mit neuem Paßwort einloggen)

### Beispiele

#### 1.) Actionbaustein "Intranet-User anlegen/ändern" - geändertes PW speichern

**Parametername des Benutzer-ID-Feldes:** user

**Parametername des Passwortfeldes:** password

#### 2.) Actionbaustein "Container-Datensatz speichern" - Container-Daten speichern

**listid:** ID des Token-Containers

**recordidfield:** tokid

## Seiten bauen

**pwvergessen.htm:** Seite mit E-Mail-Eingabe, ruft *pwvergessen.act* auf, Ausgabe, wenn Email nicht gefunden

### Beispiele

```html
<form action="pwvergessen.act" method="post">
  <label for="email">Ihre E-Mail-Adresse: </label>
  <input type="text" id="email" name="email" value="<bx:pagedata.request name="email"/>">
  <bx:pagedata.request name="fehler" value="1">Bitte geben Sie Ihre E-Mail-Adresse an.</bx:pagedata.request>
  <bx:pagedata.request name="fehler" value="2">Mit dieser Email sind Sie nicht angemeldet.</bx:pagedata.request>
  <br>
  <input type="submit" value="abschicken">
</form>
```

**mailverschickt.htm:** Info-Seite, "So geht' weiter...", nachdem Email mit dem Token verschickt wurde

**changepw.htm:** Seite mit Feldern zur Paßwortänderung, ruft checkpw.act auf, Ausgabe, wenn Token nicht mehr gültig

### Beispiele

```html
<bx:pagedata.request name="fehler" value="3">Der Link aus der E-Mail ist nicht mehr gültig. Bitte fordern Sie einen neuen Link an.</bx:pagedata.request>
<form action="checkpw.act" method="post">
  <input type="hidden" name="token" value="<bx:pagedata.request name="token"/>">
  <input type="hidden" name="email" value="<bx:pagedata.request name="email"/>">
  <label for="Passwort">neues Paßwort:*</label>
  <input id="Passwort" type="text" name="Passwort" value=""> <bx:pagedata.request name="fehler" value="1">Bitte geben Sie Ihr Paßwort incl. Wiederholung an.</bx:pagedata.request><br>
  <label for="Passwortwdhlg" style="width:145px;">Paßwortwiederholung:*</label>
  <input id="Passwortwdhlg" type="text" name="Passwortwdhlg" value=""> <bx:pagedata.request name="fehler" value="2">Die beiden Paßwörter sind nicht gleich.</bx:pagedata.request><br>
  <input type="submit" value="speichern" style="margin-left:145px;">
</form>
```

**ok.htm:** Info-Seite, "So geht' weiter...", nachdem PW erfolgreich geändert wurde

**pwemail.htm:** Mail mit dem Token

### Beispiele

```html
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  <title>Paßwort vergessen</title>
</head>
<body>
<bx:containerloop.User pool="132AF649539" idfield="tokid" force="single">
<bx:recordfield.Kontakt>
Guten Tag, <bx:recordfield.Kontakt_Anrede/> <bx:if><bx:recordfield.Kontakt_Vorname/> </bx:if><bx:recordfield.Kontakt_Vorname/> <bx:recordfield.Kontakt_Name/>,
<br><br>
</bx:recordfield.Kontakt>
Sie hatten auf "Paßwort vergessen" geklickt. Wenn nicht, dann ignorieren Sie diese Mail.
<br><br>
Bitte folgenden Link anklicken - Sie können dann ein neues Paßwort vergeben. Dieser Link ist einen Tag gültig und nur einmal verwendbar.
<br>
**********************************************************************************************************************<br>
http://mrp.batix.net/www/nab/mitgliederbereich/changepw.htm?token=<bx:recordfield.Token/>&amp;email=<bx:recordfield.Email/>
**********************************************************************************************************************<br>
Bitte beachten Sie: Bei einigen Browsern und E-Mail-Programmen lässt sich der Link nicht anklicken. Sollte dies der Fall sein, kopieren Sie bitte den kompletten Link in die Adresszeile Ihres Browsers und bestätigen mit der Return-Taste.
<br><br>
Mit freundlichen Grüßen<br>
Das Notarzt-Börse-Team
</bx:containerloop.User>
</body>
</html>
```

# Records – Hilfsklasse für einfaches Filtern

<!-- last_modified: 07. Jul 2021 -->
Für die programmatische Erstellung einer Datensatz-Filterung gab es bisher nur die Klasse `SQLGenerator`, welche teilweise schwierig zu bedienen war. Nun gibt es eine einfachere Möglichkeit mit besserer Typunterstüzung: die Klasse `com.batix.table.Records`. In Groovy-Code gibt es einen ähnlichen Helfer ([findRecords](/books/cms-handbuch-entwickler/page/cms-spezifische-helfer)), aber auch dort sollte `Records` vorgezogen werden.

Diese hat z. B. den Vorteil, dass die möglichen Filter für die unterschiedlichen Feldtypen ausdefiniert sind - man bekommt sie also per Code-Completion von der IDE vorgeschlagen und muss sich keine Zahlen merken. Außerdem wurden bestimmte Filter nochmals unterteilt, um beispielsweise `NULL` Werte zuzulassen oder nicht.

Auch in Bezug auf Sicherheit sollte der Einsatz von `Records` favorisiert werden: Es können aus Versehen keine Filter definiert werden, die in manchen Fällen dazu führen, dass die Filterung ausgehebelt wird (also man alle Datensätze sieht). Das war z. B. bisher der Fall, wenn man davon ausging, dass bestimmte Requestparameter immer da sind, es dann aber durch einen Fehler oder gezielten Angriff doch nicht so war.

<p class="callout info">Verfügbar ab CMS Version 2.7.3</p>

## Beispiel

Zur schnellen Übersicht ist hier ein Beispiel, in dem viele Methoden verwendet werden.

```java
tmd.records()
  .connection(conn) // optional
  .activeOrInactive() // default active()
  .asc("timestamp").descNullsLast("sent_at") // nach mehreren Sachen sortieren
  .index(10)
  .limit(5)
  .exclude("123ABC") // bestimmte DS-IDs includen/excluden
  .filterCheckbox("valid", "ignoreValid").checked() // mehrere Felder mit oder verknüpft, d. h. mind. eins von beiden muss angehakt sein
  .filterSingleLink("Kategorie").anyId(collectionOfStrings)
  .filterMultipleLink("docs").containsAny("123ABC", "456DEF")
  .filterInteger("age").nullOr().greaterOrEquals(18)
  .filterFloat("price").lesser(100)
  .filterString("Vorname").notNullAnd().contains("test")
  .filterString("Nachname").nullOr().startsWith("test")
  .filterDate("Geburtsdatum").onYear(2000)
  .filterDate("Geburtsdatum").onMonthDay(MonthDay.now())
  .filterTime("wann").onHour(14)
  .filterTime("wann").later(LocalTime.of(13, 37))
  .filterDocument("doc").id("123ABC")
  //.count() -> int
  //.firstOrNull() -> ContainerRecord
  .forEach(rec -> { /*...*/ });
```

## Allgemeines

Um den Zusammenbau der Konfiguration zu starten, wird eine Instanz von `TableMetadata` benötigt (im Beispiel oben `tmd`). Dann kann einfach `tmd.records()` oder `Records.from(tmd)` aufgerufen werden.

Die Klasse ist im Builder-Style gehalten. Es können also mehrere Bedingungen hintereinander definiert werden. Die Reihenfolge ist egal, da noch nichts ausgeführt, sondern nur die Abfrage-Konfiguration erstellt wird. Es sollte auf sinnvolle Zeilenumbrüche zur besseren Lesbarkeit geachtet werden (wie im Beispiel oben).

<p class="callout success">Es muss nicht zwangsläufig alles hintereinander geschrieben werden. Man kann sich die `Records` Instanz auch auf eine Variable legen und die Methoden nur in bestimmten Fällen aufrufen, z. B. anhand von Request-Parametern.<br><br>

```java
final Records.RecordsBuilder recs = tmd.records()
  .filterCheckbox("deleted").notChecked()
  .asc("Titel")
  .limit(10);

if (reqSuche != null && reqSuche.length() > 0) {
  recs.filterString("Beschreibung").notNullAnd().contains(reqSuche);
}

int cnt = recs.count();
```

In Kotlin kann auch z. B. `apply` benutzt werden:

```java
val cnt = tmd.records().apply {
  filterCheckbox("deleted").notChecked()

  if (!reqSuche.isNullOrEmpty()) {
    filterString("Beschreibung").notNullAnd().contains(reqSuche)
  }

  asc("Titel")
  limit(10)
}.count()
```
</p>

<p class="callout warning">Man kann sich keinen alten Stand der Konfiguration merken, da von der `Records` Instanz, die man konfiguriert bei den einzelnen Methoden keine Kopie erzeugt wird, sondern diese direkt verändert wird.</p>

Damit die Abfrage ausgeführt wird, ist als letztes eine der [Ergebnis-Methoden](#bkmrk-ergebnisse-laden) aufzurufen. Diese können auch mehrfach aufgerufen werden, die Abfrage wird dann immer wieder mit den aktuellen Einstellungen neu gestartet.

<p class="callout success">Bei Methoden, die mehrere Testwerte entgegennehmen, kann auch eine Collection des entsprechenden Typs anstatt einzelner Parameter übergeben werden.</p>

## Connection

```java
.connection(/* Connection */)
.connection(request)
```

Mittels `.connection()` kann eine Datenbank-Connection übergeben werden. Dies ist nicht unbedingt nötig, da `Records` ansonsten selbst eine Connection im Hintergrund aufmacht. Das kann aber bei vielen Abfragen zu Performance-Problemen führen, da immer wieder eine neue Connection aufgemacht wird. Daher sollte man sich angewöhnen, eine Connection zu übergeben. Das geht direkt mit `.connection(conn)` oder, falls man nur einen Request zur Hand hat, mit `.connection(request)`.

## Filtern

Eine Suche nach Feldwerten kann mit den `.filter...()` Methoden definiert werden. Für jeden Feldtyp gibt es eine entsprechende Methode.

Der `.filter...()` Methode wird dann der Name des zu filternden Feldes übergeben.

<p class="callout info">Einer `.filter...()` Methode können auch mehrere Feldnamen übergeben werden (als einzelne Parameter). Das führt zu einer ODER-Verknüpfung der Felder: Mindestens eins dieser Felder muss also die Bedingung erfüllen.<br>Das entspricht im <a href="/books/cms-handbuch-entwickler/page/filter">XML-Filter</a> der Angabe mehrerer `&lt;field&gt;` Elemente.<br><br>

**Beispiel**

```java
.filterString("Vorname", "Nachname").notNullAnd().contains("muster")
```
</p>

<p class="callout warning">Alle Filtermethoden prüfen ihre Argumente auf `null` bzw. leer (z. B. bei Strings) und lehnen solche Werte mit einer Exception ab.<br>Das bedeutet man kann weder explizit, noch aus Versehen, einen Testwert übergeben, der nicht filtert (beispielsweise einen Leerstring beim Filtern einer "Besitzer" Verknüpfung).<br>Somit werden bestimmte Bugs und Angriffe zur Laufzeit verhindert. Soll ein Feld nur in manchen Fällen gefiltert werden, ist das obige Beispiel unter [Allgemeines](#bkmrk-allgemeines) anzuwenden.</p>

Nachfolgend sind die Feldtypen mit ihren zugehörigen Filter-Methoden aufgeführt.

### Text

```java
.filterString("Feldname")...
```

#### Leer abfragen

```java
.filterString("Feldname").empty()
.filterString("Feldname").notEmpty()
```

#### Leer erlaubt oder nicht erlaubt

```java
.filterString("Feldname").notNullAnd()...
.filterString("Feldname").nullOr()...
```

Der Text-Filter teilt sich in zwei Unterbereiche, die aber im Prinzip dieselben Methoden unterstützen. Sie unterscheiden sich dadurch, dass leere Felder entweder von vornherein ausgeschlossen werden, oder alternativ, dass leere Felder auch die Bedingung erfüllen (diese Variante wird z. B. angewendet, falls es ein einschränkendes Feld gibt, das aber auch leer sein kann, was dann bedeutet, dass die Einschränkung nicht greift und demzufolge der Datensatz auch mit gelistet werden soll).

#### Gleichheit

```java
.filterString("Feldname").notNullAnd().value("Testwert")
.filterString("Feldname").notNullAnd().valueAny("Testwert 1", "Testwert 2")

.filterString("Feldname").notNullAnd().notValue("Testwert")
.filterString("Feldname").notNullAnd().notValueAny("Testwert 1", "Testwert 2")

.filterString("Feldname").nullOr().value("Testwert")
.filterString("Feldname").nullOr().valueAny("Testwert 1", "Testwert 2")

.filterString("Feldname").nullOr().notValue("Testwert")
.filterString("Feldname").nullOr().notValueAny("Testwert 1", "Testwert 2")
```

Um den kompletten Feldinhalt zu prüfen, wird eine der `value` Methoden verwendet.

<p class="callout warning">Da die `...Any()` Methoden intern die multiplen Testwerte in einen kommagetrennten String schreiben, ist die Verwendung eines Kommas in Testwerten für diese Methoden nicht möglich bzw. führt zu fehlerhaften Ergebnissen!</p>

#### Partielle Übereinstimmung

```java
.filterString("Feldname").notNullAnd().contains("Testwert")
.filterString("Feldname").notNullAnd().containsAny("Testwert 1", "Testwert 2")
.filterString("Feldname").notNullAnd().containsAll("Testwert 1", "Testwert 2")
.filterString("Feldname").notNullAnd().startsWith("Testwert")
.filterString("Feldname").notNullAnd().endsWith("Testwert")
.filterString("Feldname").notNullAnd().regex("Pattern")

.filterString("Feldname").notNullAnd().notContains("Testwert")
.filterString("Feldname").notNullAnd().notContainsAny("Testwert 1", "Testwert 2")
.filterString("Feldname").notNullAnd().notContainsAll("Testwert 1", "Testwert 2")
.filterString("Feldname").notNullAnd().notStartsWith("Testwert")
.filterString("Feldname").notNullAnd().notEndsWith("Testwert")
.filterString("Feldname").notNullAnd().notRegex("Pattern")

.filterString("Feldname").nullOr().contains("Testwert")
.filterString("Feldname").nullOr().containsAny("Testwert 1", "Testwert 2")
.filterString("Feldname").nullOr().containsAll("Testwert 1", "Testwert 2")
.filterString("Feldname").nullOr().startsWith("Testwert")
.filterString("Feldname").nullOr().endsWith("Testwert")
.filterString("Feldname").nullOr().regex("Pattern")

.filterString("Feldname").nullOr().notContains("Testwert")
.filterString("Feldname").nullOr().notContainsAny("Testwert 1", "Testwert 2")
.filterString("Feldname").nullOr().notContainsAll("Testwert 1", "Testwert 2")
.filterString("Feldname").nullOr().notStartsWith("Testwert")
.filterString("Feldname").nullOr().notEndsWith("Testwert")
.filterString("Feldname").nullOr().notRegex("Pattern")
```

Teile des Feldinhaltes können mit diesen Methoden überprüft werden.

<p class="callout warning">Da die `...Any()` und `...All()` Methoden intern die multiplen Testwerte in einen kommagetrennten String schreiben, ist die Verwendung eines Kommas in Testwerten für diese Methoden nicht möglich bzw. führt zu fehlerhaften Ergebnissen!</p>

### Bild

```java
.filterPicture("Feldname")...
```

#### Leer abfragen

```java
.filterPicture("Feldname").empty()
.filterPicture("Feldname").notEmpty()
```

#### Ziel-Datensatz existiert

```java
.filterPicture("Feldname").exists()
.filterPicture("Feldname").notExists()
```

Diese Filter überprüfen, ob es ein Bild mit der im Feld hinterlegten ID auch wirklich gibt.

#### ID abfragen

```java
.filterPicture("Feldname").id("123456ABCDEF")
```

### Datei

```java
.filterDocument("Feldname")...
```

#### Leer abfragen

```java
.filterDocument("Feldname").empty()
.filterDocument("Feldname").notEmpty()
```

#### ID abfragen

```java
.filterDocument("Feldname").id("123456ABCDEF")
```

### Datum mit oder ohne Uhrzeit

```java
.filterDate("Feldname")...
```

<p class="callout success">Die Filtermethoden nehmen aus Sicherheitsgründen keinen String entgegen, da dieser evtl. nicht im vom Filter erwarteten Format ist. Es muss also eine Instanz von `Date | LocalDate | LocalDateTime` übergeben werden. Bei Feldern ohne Uhrzeit wird nur der Datumsteil des Testwertes gelesen.<br>Falls man nur einen String hat, muss man diesen vorher in ein `LocalDate(Time)` Objekt umwandeln. Man erstellt dazu einen Formatter mit dem passenden Pattern und parst den String zum gewünschten Objekt.<br><br>

**Beispiele**

```java
LocalDateTime.parse("zu parsender String", DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm:ss"))
LocalDate.parse("zu parsender String", DateTimeFormatter.ofPattern("dd.MM.yyyy"))
```
</p>

#### Leer abfragen

```java
.filterDate("Feldname").empty()
.filterDate("Feldname").notEmpty()
```

#### (Teil)Gleichheit

```java
.filterDate("Feldname").onDate(/* Date | LocalDate | LocalDateTime */)
.filterDate("Feldname").onDay(/* int (1-31) */)
.filterDate("Feldname").onMonth(/* int (1-12) */)
.filterDate("Feldname").onMonthDay(/* MonthDay */)
.filterDate("Feldname").onYear(/* int */)
.filterDate("Feldname").onYearMonth(/* YearMonth */)

.filterDate("Feldname").notOnDate(/* Date | LocalDate | LocalDateTime */)
```

#### Abfrage neuer / älter bzw. gleich

```java
.filterDate("Feldname").newer(/* Date | LocalDate | LocalDateTime */) // Feld > Testwert
.filterDate("Feldname").newerEquals(/* Date | LocalDate | LocalDateTime */) // Feld >= Testwert

.filterDate("Feldname").older(/* Date | LocalDate | LocalDateTime */) // Feld < Testwert
.filterDate("Feldname").olderEquals(/* Date | LocalDate | LocalDateTime */) // Feld <= Testwert
```

#### Abfrage neuer / älter oder Leer

```java
.filterDate("Feldname").nullOr().newerEquals(/* Date | LocalDate | LocalDateTime */)
.filterDate("Feldname").nullOr().olderEquals(/* Date | LocalDate | LocalDateTime */)
```

### Uhrzeit

```java
.filterTime("Feldname")...
```

<p class="callout success">Auch hier nehmen die Methoden - wie oben bei Datum mit oder ohne Uhrzeit - keinen String entgegen. Dieser muss zunächst in ein passendes Objekt umgewandelt werden. Bei Objekten vom Typ `Date` oder `LocalDateTime` wird nur der Uhrzeitteil gelesen.<br><br>

**Beispiele**

```java
LocalTime.parse("zu parsender String", DateTimeFormatter.ofPattern("HH:mm:ss"))
LocalDateTime.parse("zu parsender String", DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm:ss"))
```
</p>

#### Leer abfragen

```java
.filterTime("Feldname").empty()
.filterTime("Feldname").notEmpty()
```

#### (Teil)Gleichheit

```java
.filterTime("Feldname").onTime(/* Date | LocalTime | LocalDateTime */)
.filterTime("Feldname").onHour(/* int (0-23) */)
.filterTime("Feldname").onMinute(/* int (0-59) */)
.filterTime("Feldname").onSecond(/* int (0-59) */)
      
.filterTime("Feldname").notOnTime(/* Date | LocalTime | LocalDateTime */)
```

#### Abfrage neuer / älter bzw. gleich

```java
.filterTime("Feldname").later(/* Date | LocalTime | LocalDateTime */) // Feld > Testwert
.filterTime("Feldname").laterEquals(/* Date | LocalTime | LocalDateTime */) // Feld >= Testwert

.filterTime("Feldname").earlier(/* Date | LocalTime | LocalDateTime */) // Feld < Testwert
.filterTime("Feldname").earlierEquals(/* Date | LocalTime | LocalDateTime */) // Feld <= Testwert
```

#### Abfrage neuer / älter oder Leer

```java
.filterTime("Feldname").nullOr().laterEquals(/* Date | LocalTime | LocalDateTime */)
.filterTime("Feldname").nullOr().earlierEquals(/* Date | LocalTime | LocalDateTime */)
```

### Ganzzahl

```java
.filterInteger("Feldname")...
```

#### Leer abfragen

```java
.filterInteger("Feldname").empty()
.filterInteger("Feldname").notEmpty()
```

#### Gleichheit

```java
.filterInteger("Feldname").value(/* Number */)
.filterInteger("Feldname").notValue(/* Number */)

.filterInteger("Feldname").nullOr().value(/* Number */)
.filterInteger("Feldname").nullOr().notValue(/* Number */)
```

#### Abfrage größer / kleiner

```java
.filterInteger("Feldname").greater(/* Number */)
.filterInteger("Feldname").greaterOrEquals(/* Number */)
.filterInteger("Feldname").lesser(/* Number */)
.filterInteger("Feldname").lesserOrEquals(/* Number */)

.filterInteger("Feldname").nullOr().greater(/* Number */)
.filterInteger("Feldname").nullOr().greaterOrEquals(/* Number */)
.filterInteger("Feldname").nullOr().lesser(/* Number */)
.filterInteger("Feldname").nullOr().lesserOrEquals(/* Number */)
```

### Dezimalzahl, Preis

```java
.filterFloat("Feldname")...
```

Die Methoden sind identisch zu Ganzzahl, es muss lediglich `filterFloat` als Methode verwendet werden.

<p class="callout warning">Alle Vergleiche auf Gleichheit bzw. Ungleichheit verwenden eine maximale Genauigkeit von 0,00001.<br>Das bedeutet, dass z. B. 0,000004 und 0,000005 für den Filter gleich sind.</p>

### Wahrheitswert (Checkbox)

```java
.filterCheckbox("Feldname")...
```

#### Prüfen ob angehakt

```java
.filterCheckbox("Feldname").checked()
.filterCheckbox("Feldname").notChecked()
```

#### Prüfen ob leer

```java
.filterCheckbox("Feldname").empty()
.filterCheckbox("Feldname").notEmpty()
```

<p class="callout warning">Dies ist in den meisten Fällen nicht der richtige Filter und es sollte "Prüfen ob angehakt" benutzt werden.<br>Hier wird nur geprüft, ob noch kein expliziter Wert im Feld steht, egal ob angehakt oder nicht angehakt.<br>Wurde die Checkbox also als **nicht angehakt** gespeichert, ist das Feld **nicht leer** (da "n" oder 0 drin steht).</p>

### Koordinaten

```java
.filterCoordinate("Feldname")...
```

<p class="callout info">Dieser Feldtyp ist veraltet und wird nicht mehr benutzt. Er wird hier nur der Vollständigkeit halber erwähnt.</p>

#### Prüfen ob leer

```java
.filterCoordinate("Feldname").empty()
.filterCoordinate("Feldname").notEmpty()
```

#### Gleichheit der Koordinaten

```java
.filterCoordinate("Feldname").x(/* Number */)
.filterCoordinate("Feldname").y(/* Number */)
```

### Einzelverknüpfung

```java
.filterSingleLink("Feldname")...
```

#### Prüfen ob leer

```java
.filterSingleLink("Feldname").empty()
.filterSingleLink("Feldname").notEmpty()
```

#### Prüfen ob Datensatz existiert

```java
.filterSingleLink("Feldname").exists()
.filterSingleLink("Feldname").notExists()
```

Es wird geprüft, ob es auch einen Datensatz mit der hinterlegten ID gibt bzw. nicht gibt.

#### Prüfen ob Datensatz aktiv

```java
.filterSingleLink("Feldname").active()
.filterSingleLink("Feldname").notActive()
```

Es wird geprüft, ob es den Datensatz gibt. Dieser muss außerdem aktiviert bzw. deaktiviert sein.

#### Nach ID suchen

```java
.filterSingleLink("Feldname").id("123456ABCDEF")
.filterSingleLink("Feldname").notId("123456ABCDEF")

.filterSingleLink("Feldname").anyId("123456ABCDEF", "ABCDEF123456")
```

### Mehrfachverknüpfung

```java
.filterMultipleLink("Feldname")...
```

#### Prüfen ob leer

```java
.filterMultipleLink("Feldname").empty()
.filterMultipleLink("Feldname").notEmpty()
```

#### Nach ID suchen

```java
.filterMultipleLink("Feldname").contains("123456ABCDEF")
.filterMultipleLink("Feldname").notContains("123456ABCDEF")

.filterMultipleLink("Feldname").containsAny("123456ABCDEF", "ABCDEF123456")
.filterMultipleLink("Feldname").containsAll("123456ABCDEF", "ABCDEF123456")
```

Bei `containsAny` reicht es, wenn eine der übergebenen IDs im Feld verknüpft ist. Für `containsAll` müssen alle übergebenen IDs verknüpft sein. In beiden Fällen können aber auch noch andere IDs verknüpft sein.

### Untertabelle (Untercontainer)

```java
.filterSubList("Feldname")...
```

#### Prüfen ob leer

```java
.filterSubList("Feldname").empty()
.filterSubList("Feldname").notEmpty()
```

## Aktiv / Inaktiv

```java
.active()
.activeOrInactive()
.inactive()
```

Standardmäßig werden nur aktive Datensätze zurückgegeben. Dies lässt sich aber anpassen.

## IDs inkludieren / exkludieren

```java
.include("123456ABCDEF", "ABCDEF123456")
.exclude("123456ABCDEF", "ABCDEF123456")
```

Zusätzlich zu den Feldfiltern besteht die Möglichkeit nur bestimmte Datensätze anhand ihrer ID zuzulassen oder auszuschließen.

Werden Feldfilter **und** ID-Filter benutzt, müssen beide zutreffen. Ein mittels `include` angegebener Datensatz taucht also nicht zwangsläufig auf, sondern nur wenn alle anderen Bedingungen auch passen (sofern welche definiert wurden).

## Paginierung

```java
.limit(/* Integer */)
.index(/* Integer */) // 0-basiert
```

Die Anzahl der Ergebnisse kann mit `limit` begrenzt werden. Ebenso kann die Startposition mit `index` festgelegt werden.

<p class="callout warning">Da `index` nullbasiert ist, startet man bei einer beispielhaften Seitenanzahl von zehn Ergebnissen mit dem elften Ergebnis (also Seite zwei), indem man `index(10)` angibt und nicht etwa `11` .</p>

## Sortierung

```java
.asc("Feldname") // aufsteigend
.desc("Feldname") // absteigend
      
.ascNullsLast("Feldname")
.descNullsLast("Feldname")
```

Es kann nach mehreren Feldern sortiert werden. Dabei ist die Reihenfolge entscheidend. Es wird zuerst nach dem ersten angegebenen Sortierfeld sortiert, dann nach dem zweiten, usw. für alle angegebenen Sortierfelder.

Standardmäßig werden `NULL` Werte an den Anfang sortiert. Dies kann mit den `...NullsLast()` Methoden geändert werden.

Im folgenden Beispiel wird also zunächst nach `timestamp` aufsteigend sortiert. Datensätze mit leerem `timestamp` Feld werden zuerst zurückgegeben.  
Danach werden Datensätze mit gleichem Wert bei `timestamp` nochmals anhand `sent_at` absteigend sortiert. Dabei werden solche mit leerem `sent_at` ans Ende der Untersortierung gesetzt.

```java
.asc("timestamp")
.descNullsLast("sent_at")
```

## Ergebnisse laden

Es gibt verschiedene Möglichkeiten die Ergebnisse abzurufen. Wie bereits erwähnt kann dies auch mehrfach geschehen, indem man sich den `Records` Builder auf eine Variable legt und dessen Ergebnismethoden mehrfach aufruft.

### Anzahl

```java
.count() // int
```

Diese Methode gibt lediglich die Anzahl der gefundenen Datensätze zurück.

### Erster Datensatz

```java
.firstOrNull() // ContainerRecord oder null
```

Um nur den ersten Datensatz zu laden, kann diese Methode benutzt werden. Entspricht kein Datensatz dem Filter, wird `null` zurückgegeben, ansonsten ein `ContainerRecord`.

### Datensätze durchgehen

```java
.forEach((ContainerRecord record) -> {
  // ...
});
```

Hier werden die Datensätze aus der Datenbank gestreamt und dem Lambda (der Closure) einzeln übergeben. Die Methode `forEach` blockiert solange, bis alle Datensätze vom Lambda verarbeitet wurden.  
Es werden dabei **nicht** zunächst alle Datensätze in den Speicher geladen, was der Performance zuträglich ist. Daher ist dies die präferierte Methode um Ergebnisse zu durchlaufen.

### Stream

```java
.stream() // Stream<ContainerRecord>
```

Genau wie bei `forEach` werden hier die Datensätze aus der Datenbank gestreamt. Man erhält allerdings direkten Zugriff auf den Stream.

<p class="callout warning">Der Stream muss geschlossen werden, da sonst Leaks entstehen, da die Datenbankobjekte nicht aufgeräumt werden (weil der Stream ja nicht weiß, dass er fertig ist).<br>Das geschieht z. B. automatisch durch <a href="https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html#package.description" target="_blank">terminale Stream-Methoden</a> oder manuell mittels `close()`.</p>

### Alle Datensätze laden

```java
.loadAll() // ContainerRecord[]
```

Es wird ein Array zurückgegeben. Falls keine Elemente gefunden wurden, ist das Array leer (nicht `null`).

<p class="callout danger">Diese Methode lädt alle gefundenen Datensätze in den Speicher, was zu Abstürzen fehlen kann. Daher sind die anderen Methoden vorzuziehen.</p>

# Regelmäßiges Neuladen von DIVs

<!-- last_modified: 16. Jun 2016 -->
Aufbau der Hauptseite

```xml
<html>
<head>
<script type="text/javascript" src="mootools-1.2.js"></script>
<script type="text/javascript">
function registerRedirect(timeout, url, target){
  target.callUpdate = function(){
    new Request.HTML({
      url: url,
      noCache: true,
      update: target,
      onFailure: function(){
        setTimeout(target.callUpdate, 5 * 1000)
      }
    }).get();
  }
  setTimeout(target.callUpdate, timeout * 1000)
}
 
window.addEvent('domready', function() {
  registerRedirect(2, "oben.html", $("div1"))
  registerRedirect(2, "unten.html", $("div2"))
});
</script>
</head>
<body>
<div id="div1">div 1</div>
<br><hr><br>
<div id="div2">div 2</div>
</body>
</html>
```

Der Inhalt einer nachgeladenen Seite sieht so aus:

```xml
<script type="text/javascript">
registerRedirect(2, "oben.html", $("div1"))
</script>
... Content für oben steht hier ...
```

# Sitemap bauen

<!-- last_modified: 17. Jun 2016 -->
Einfaches Sitemap, kann noch verschönert werden.

**Styles**

```xml
.ebene0{
  font-weight:bold;
  text-decoration:underline;
  }
.ebene1{
  margin-left:30px;
  }
.ebene2{
  margin-left:60px;
  }
```

**Quellcode**

```xml
<bx:sitemap.0>
  <div class="ebene0"><a href="<bx:navigation.target default="http://" /><bx:pagedata.hostname />/www/<bx:pagedata.webdir/>/<bx:navigation.path/>"><bx:navigation.name/></a></div>
  <bx:sitemap.1>
    <div class="ebene1"><a href="<bx:navigation.target default="http://" /><bx:pagedata.hostname />/www/<bx:pagedata.webdir/>/<bx:navigation.path/>"><bx:navigation.name/></a></div>
    <bx:sitemap.2>
      <div class="ebene2"><a href="<bx:navigation.target default="http://" /><bx:pagedata.hostname />/www/<bx:pagedata.webdir/>/<bx:navigation.path/>"><bx:navigation.name/></a></div>
    </bx:sitemap.2>
  </bx:sitemap.1>
</bx:sitemap.0>
```

# Support für „not" hinzufügen

<!-- last_modified: 16. Jun 2016 -->
Dieses Beispiel realisiert folgende Funktionen:

- `not` für ein Tag emulieren, dass `not` nicht unterstützt

Folgende Tags wurden verwendet:

- [Bx:clipboard](/books/cms-handbuch-entwickler/page/bxclipboard)
- [Bx:if](/books/cms-handbuch-entwickler/page/bxif)
- [Bx:pagedata](/books/cms-handbuch-entwickler/page/bxpagedata)

## Quellcode

Als Beispiel dient hier das Tag [bx:pagedata.navid](/books/cms-handbuch-entwickler/page/bxpagedata), welches `not` für seine Bedingung nicht unterstützt.

```xml
<bx:clipboard.cut name="check">
	<bx:pagedata.navid is="12345678901"><!-- --></bx:pagedata.navid>
</bx:clipboard.cut>
<bx:clipboard.cut name="content">
	Inhalt der bei allen Menüpunkten außer dem Gesuchten angezeigt wird
</bx:clipboard.cut>
<bx:if type="one">
	<bx:clipboard.paste name="check" />
	<bx:clipboard.paste name="content" />
</bx:if>
```

Das "check" Clipboard wird nur gefüllt, wenn ein bestimmter Menüpunkt aufgerufen wird. Dagegen wird das "content" Clipboard immer mit dem gewünschten Inhalt gefüllt. Da &lt;bx:if&gt; aber im Modus `"one"` läuft, wird der Inhalt auch nur ausgegeben, wenn sich nur im "content" Clipboard etwas befindet, d.h. wenn die NavID des aktuellen Menüpunktes **nicht** mit der zu überprüfenden übereinstimmt!

# Validation

<!-- last_modified: 20. Jun 2016 -->
## Validation eines Container-Datensatzes

Mit einem Aktionsbaustein vom Typ [ValidationAction](/books/cms-handbuch-entwickler/page/containerinhalt-validieren) werden die zu validierenden Felder und ihre Gültigkeitsbedingungen konfiguriert. Danach folgt ein Aktionsbaustein vom Typ [ValidationResultAction](/books/cms-handbuch-entwickler/page/validierungsergebnis-ausgeben) der das Validationsergebnis im XML-Format in ein Feld des Containerdatensatzes schreibt.

Auf der Formularseite können durch das Tag [bx:validation](/books/cms-handbuch-entwickler/page/bxvalidation) die fehlerhaften Eingabefelder markiert, oder ein Kommentar angezeigt werden.

## Validation von übergebenen Requestparametern

Der Aktionsbaustein [FormValidatorAction](/books/cms-handbuch-entwickler/page/formulardaten-validieren) validiert Requestparameter gegen reguläre Ausdrücke. Die regulären Ausdrücke werden als `<input type="hidden">`-Felder an die Action-URL übergeben.

## Validation eines einzelnen Requestparameters

Der Aktionsbaustein [ConditionAction](/books/cms-handbuch-entwickler/page/vorhandene-bedingung-abfragen) dient eigentlich zur Verzweigung des Ablaufs innerhalb einer Aktion. Ein übergebener Requestparameter wird auf einen in der Aktion festgelegen wert geprüft. Abhängig von Ergebnis kann an andere URLs weitergeleitet werden.

# Websuche

<!-- last_modified: 16. Jun 2016 -->
Voraussetzung für ein Funktionieren der Websuche ist eine Indizierung der Seiten, z.B. via [Zeitsteuerung](/books/cms-handbuch-entwickler/page/zeitsteuerung). Dies geht erst, wenn das Web fertig, also ungeschützt und unter der endgültigen Url erreichbar ist.

**Suchformular**

```xml
<div id="suchdiv">
  Suche:
  <form action="/www/<bx:pagedata.webdir/>/sonstiges/suche/suche.act" method="post">
    <input type="text" name="search" size="18" value="<bx:websearch.query/>"><input type="submit" value="los">
  </form>
</div>
```

Action:

**suche.act**

Typ der Aktion: [Suche im Web](/books/cms-handbuch-entwickler/page/suche-im-web)

resultpage: Pfad zur Ausgabeseite, z.B. /suche/

**Ausgabeseite**

```xml
<strong>Sie suchten nach: <bx:websearch.query/></strong><br>

<div style="text-align:center;">
  <div style="float:left;"><bx:websearch.previous hide/></div>
  <div style="float:right;"><bx:websearch.next hide/></div>
  <bx:websearch.if not empty>
  Ergebnis <bx:websearch.firstshown/> bis <bx:websearch.lastshown/> von insgesamt <bx:websearch.totalhits/>
  </bx:websearch.if>&nbsp; 
</div>
<hr>
<bx:websearch.if empty>Es wurden leider keine Ergebnisse gefunden.</bx:websearch.if>
<bx:websearch.if not empty> 
  <bx:websearch max="10">
    <strong><bx:websearch.rank/>.</strong>&nbsp;<bx:websearch.link><bx:websearch.title/></bx:websearch.link>&nbsp;&nbsp;<bx:websearch.stars max="5"><img src="star.jpg">&nbsp;</bx:websearch.stars><br>
    <div style="margin-left:30px;"><bx:websearch.description/></div><br><br>
  </bx:websearch>
</bx:websearch.if> 
```

# Encodings

Zeichenkodierungen und Escape-Funktionen.

# Encodings – Übersicht

<!-- last_modified: 06. Feb 2017 -->
Bestimmte Tags unterstützen Encodings (Maskierungen) um die Ausgabe in bestimmten Situationen anders aussehen zu lassen. So werden z.B. für HTML spitze Klammern durch ihre entsprechenden HTML-Entites ersetzt oder für JavaScript Steuerzeichen escaped (ein Backslash vorangestellt).

Die meisten Tags unterstützen auch eine Angabe der gewünschten Kodierung via `encoding` Parameter, z.B.: &lt;bx:recordfield.Name encode="..." /&gt;
Falls explizit kein Encoding angegeben wurde, versucht das Tag automatisch passen zu encoden (z.B. HtmlEncode bei Mime-Type text/html). Die folgenden Umwandlungen können angegeben werden:

- javascript
- url
- xml
- html
- sql
- sql-like
- sql-rlike
- htmltext
- plain

Informationen zu den einzelnen Encodings:

- [HtmlEncode](/books/cms-handbuch-entwickler/page/htmlencode)
- [HtmlMask](/books/cms-handbuch-entwickler/page/htmlmask)
- [ScriptEncode](/books/cms-handbuch-entwickler/page/scriptencode)
- [UrlEncode](/books/cms-handbuch-entwickler/page/urlencode)
- [XmlEncode](/books/cms-handbuch-entwickler/page/xmlencode)

Auf jeder Seite steht ganz unten, welche Tags oder sonstigen Funktionen diese Umwandlung benutzen bzw. unterstützen.

# HtmlEncode

<!-- last_modified: 26. Jan 2014 -->
Es werden folgende Ersetzungen vorgenommen:

| Originalwert | ausgegebener Wert |
|---|---|
| `<` | `&lt;` |
| `>` | `&gt;` |
| `"` | `&quot;` |
| `'` | `&#039;` |
| `&` | `&amp;` |

# HtmlMask

<!-- last_modified: 05. Mar 2014 -->
Hierbei werden sämtliche Zeichen durch HTML-Entities der Form `&#dd;` ersetzt, wobei `d` für eine dezimale Ziffer steht.

Aus `Hallo` wird somit `&#72;&#97;&#108;&#108;&#111;`.

# ScriptEncode

<!-- last_modified: 26. Jan 2014 -->
Einige Sonderzeichen und besondere Zeichen werden durch JavaScript Escape-Sequenzen ersetzt.

Den folgenden Zeichen wird ein \ (Backslash) vorangestellt:

- Newline / Zeilenumbruch (`\n` / 0x0a)
- Carriage return / Wagenrücklauf (`\r` / 0x0d)
- Tab (`\t` / 0x09)
- Single-Quote / Apostroph (`'` / 0x27)
- Double-Quote / Anführungszeichen (`"` / 0x22)
- Backslash (`\` / 0x5c)

## Strict / Non-Strict

Standardmäßig ist der Strict-Modus aktiviert, das heißt jeder Backslash wird verdoppelt.

Im Non-Strict-Modus werden Backslashes, die sich vor den oben aufgelisteten Zeichen (außer Single-Quote) befinden nicht verdoppelt (außer der Backslash steht ganz am Ende).

# UrlEncode

<!-- last_modified: 26. Jan 2014 -->
Es wird die Java Klasse <a href="http://docs.oracle.com/javase/7/docs/api/java/net/URLEncoder.html" target="_blank">URLEncoder</a> benutzt. Dabei werden "unsichere" Zeichen durch ein oder mehrere Blöcke `%hh` ersetzt, wobei `h` für eine hexadezimale Ziffer steht.

Je nach verwendetem Zeichensatz können die Hexadezimalen Blöcke anders aussehen, so wird ein kleines `ö` z.B. mit ISO-8859-1 zu `%f6`, mit UTF-8 allerdings wird es zu `%c3%b6`.

Es gelten folgende Regeln:

- Die Bereiche a-z, A-Z und 0-9 werden nicht ersetzt
- . (Punkt), - (Minus), * (Stern) und _ (Underscore) werden nicht ersetzt
- Leerzeichen wird durch + (Plus) ersetzt
- Alle anderen Zeichen sind "unsichere" Zeichen und werden in Hexadezimal dargestellt

# XmlEncode

<!-- last_modified: 26. Jan 2014 -->
Es werden folgende Ersetzungen vorgenommen:

| Originalwert | ausgegebener Wert |
|---|---|
| `<` | `&lt;` |
| `>` | `&gt;` |
| `"` | `&quot;` |
| `&` | `&amp;` |
| Zeichen zwischen dezimal 32 und 127<br>(beides inklusive) | *(unverändert)* |
| Alle restlichen Zeichen | `&#ddd;`<br>d = dezimale Ziffer<br><br>je nach Plattform, auf der das CMS läuft,<br>können unterschiedliche Werte entstehen |

# Groovy

Groovy-Scripting im CMS.

# API

<!-- last_modified: 20. Jan 2020 -->
eine gekapselte Klasse mit statischen Methoden, die zusammengehörige Funktionalitäten enthältMyApi (bei `class` und `logName` muss noch angepasst werden.

```groovy
import com.batix.Log
import com.batix.action.GroovyAction
import com.batix.modul.Customer
import com.batix.modul.SystemVariables
import com.batix.table.TableMetadata
import com.batix.tags.GroovyTag

import javax.servlet.ServletContext
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse
import javax.servlet.http.HttpSession
import java.sql.Connection

class MyApi {
  private static GroovyAction.GroovyContext getContext() {
    return GroovyAction.context
  }

  private static GroovyTag getIncludeTag() {
    return context.includeTag
  }

  private static GroovyAction getAction() {
    return context.action
  }

  private static ServletContext getApplication() {
    return context.application
  }

  private static HttpServletRequest getRequest() {
    return context.request
  }

  private static HttpServletResponse getResponse() {
    return context.response
  }

  private static HttpSession getSession() {
    return context.session
  }

  private static Customer getWeb() {
    return context.web
  }

  private static SystemVariables getVariables() {
    return context.variables
  }

  private static Connection getConn() {
    return action?.connection ?: includeTag?.checkConnection()
  }

  /* Logging start */
  private static def logName = "MyApi"
  //noinspection GroovyUnusedAssignment
  private static void logD(String msg, HttpServletRequest request = null) { Log.debug("[${logName}] ${msg}", request) }
  //noinspection GroovyUnusedAssignment
  private static void logI(String msg, HttpServletRequest request = null) { Log.info("[${logName}] ${msg}", request) }
  //noinspection GroovyUnusedAssignment
  private static void logN(String msg, HttpServletRequest request = null) { Log.notice("[${logName}] ${msg}", request) }
  //noinspection GroovyUnusedAssignment
  private static void logW(String msg, HttpServletRequest request = null) { Log.warn("[${logName}] ${msg}", request) }
  //noinspection GroovyUnusedAssignment
  private static void logE(String msg, Exception ex = null, HttpServletRequest request = null) { Log.error("[${logName}] ${msg}", request, ex) }
  /* Logging end */

  // Beispiel: öffentliche Konstante
  public static final def ID_STATUS_OFFEN = "15FBFE52655"

  // Beispiel: öffentliche Methode
  static Map info(String vid) { return null }
}
```

# Bibliothek – Übersicht

<!-- last_modified: 20. Apr 2017 -->
Hier werden wiederverwendbare Code-Schnipsel und Helferlein gesammelt. Diese müssen, falls nicht anders angegeben, einfach nur rauskopiert werden und im eigenen Code (am besten ganz oben) eingefügt werden.

- [API](/books/cms-handbuch-entwickler/page/api) — eine gekapselte Klasse mit statischen Methoden, die zusammengehörige Funktionalitäten enthält
- [BatixUtils](#)
- [Logging](/books/cms-handbuch-entwickler/page/logging) — um einfach Logausgaben zu erzeugen, die den Name des Scripts vorangestellt haben
- [Timings](/books/cms-handbuch-entwickler/page/timings) — nützlich, um einzelne Code-Teile zu profilen und so herauszufinden, was genau langsam ist

# CMS-spezifische Helfer

<!-- last_modified: 27. Mar 2020 -->
Bestimmte CMS-Klassen wurden um Utilities zur einfacheren Verwendung erweitert.

## Importe

Einige häufig genutzte Klassen werden automatisch importiert, z.B. `java.sql.Connection`, `TableMetadata` und `BatixRecord`.

## Objekte

Dem Groovy-Script stehen automatisch folgende Objekte zur Verfügung:

- `includeTag` - Referenz zum ausführenden `bx:groovy` Tag, ansonsten `null`
    - es können hier z.B. Tag-Parameter gelesen werden:

      **Template**

      ```xml
      <bx:groovy includes="MyReport" format="html" />
      ```

      **Groovy-Baustein**

      ```groovy
      String format = includeTag.getStringParameter("format")
      println("gewähltes Format: $format")
      ```

- `action` - Referenz zum ausführenden Groovy-Action, ansonsten `null`
    - kann z.B. benutzt werden, um Script-Attribute zu setzen oder das Action abzubrechen

      ```groovy
      action.setScriptAttribute("thing", "value")
      action.cancel = true
      ```

- `application` - der `ServletContext`
- `request` - der aktuelle `HttpServletRequest`
    - z.B. um Request-Parameter auszulesen, die der Seite oder dem Action übergeben wurden

      ```groovy
      String kid = request.getParameter("kid")
      ```

- `response` - die aktuelle `HttpServletResponse`
    - falls ein Action verwendet wird: `action.originalResponse` benutzen, um z.B. direkt Bytes zu schreiben

- `session` - die aktuelle Session, falls vorhanden

- `pageData` - enthält Infos zum Aufruf

    ```groovy
    String file = pageData.filename // z.B. "detail.htm"
    ```

- `navElement` - der aufgerufene Menüpunkt (`NavigationElement`)

- `web` - das Projekt (`Customer`)

- `variables` - die Systemeinstellungen (`SystemVariables`)
    - Das sind die pro Projekt überschreibbaren Variablen

      ```groovy
      String portalId = variables.getVariable("PortalID")
      ```

## Connection

Um einfach an eine Datenbank-Connection zu kommen, egal ob der Groovy-Baustein in einem Action oder Tag (oder sogar den Entwickler-Tools) verwendet wird, kann folgender Block verwendet werden:

```groovy
Connection.with { conn ->
  // hier Code, der conn benutzt
}
```

Die Connection wird nach dem Block automatisch wieder geschlossen bzw. zurückgegeben.

## TableMetadata holen

Eine Instanz von `TableMetadata` lässt sich einfach zu einem Container erzeugen, in dem Entweder der Titel, der Tabellenname oder die ID des Containers benutzt wird (es wird eine `TableMetadata`-Instanz zurückgegeben):

```groovy
// funktioniert alles gleich
def tmdKunden = TableMetadata["Kunden"]
def tmdKunden = TableMetadata["bxc_kunden"]
def tmdKunden = TableMetadata["15525037CCA"]
 
// auch mit Punkt-Schreibweise verfügbar
def tmdKunden = TableMetadata.Kunden
def tmdKunden = TableMetadata.bxc_kunden
def tmdKunden = TableMetadata."15525037CCA" // als String, da sonst Syntax Error wegen Ziffer am Anfang
```

## BatixRecord holen

Ein bestimmter Datensatz aus einem Container, kann durch seine ID einfach geholt werden (es wird eine `BatixRecord`-Instanz zurückgegeben):

```groovy
def recKunde = tmdKunden["15525037CCB"]
```

Einen neuen Datensatz erzeugt man mit den üblichen Methoden:

```groovy
def recKunde = tmdKunden.createNewRecord(conn, com.batix.util.UniqueID.createHexId(), true)
```

## Datensatz-Felder lesen / schreiben

Hat man einen `BatixRecord` kann man auf einfache Art und Weise die Datensatz-Felder lesen und ändern:

```groovy
// Text
String name = recKunde.Name.string
recKunde.Titel.string = "Dr."
 
// Zahl
int alter = recKunde.Alter.number // Ganzzahl-Feld
recKunde.Alter.number = 18
double rabatt = recKunde.Rabatt.number // Dezimalzahl-Feld
recKunde.Rabatt.number = 5.83
 
// Datum, Datum + Uhrzeit, Uhrzeit oder Zeitraum
Date bday = recKunde.Geburtstag.date
recKunde.lastUpdate.date = new Date()
 
// Häkchen
boolean archived = recKunde.archiviert.state
recKunde.Newsletter.state = false
 
// Einzelverknüpfung (Bild, Dokument, Datensatz)
String picId = recKunde.Foto.string
String statusId = recKunde.Status.string
recKunde.Rolle.string = "15525037CCC"
 
// Mehrfachverknüpfung
MultipleLinkField leistungen = recKunde.Leistungen
 
// Untercontainer
SubListField vertraege = recKunde.Vertraege
 
// zum Schluss Update nicht vergessen
recKunde.updateRecordInDatabase(conn)
// oder Anlegen, falls es ein neuer Datensatz war
recKunde.createRecordInDatabase(conn, false) // false = Default-Werte der Container-Felder übernehmen
```

<p class="callout warning">Durch die angesprochenen Probleme mit Typ-Infos, kann es passieren, dass bei Datum/Zeit-Feldern der Setter uneindeutig ist, falls <code>null</code> übergeben wird (da es dort mehrere <code>setDate</code> Methoden gibt).<br><br>Falls eine Variable übergeben wird, die auch <code>null</code> sein kann, wird daher beim Setzen von Datum/Zeit Feldern empfohlen, die <code>setDate</code> Methode aufzurufen und einen expliziten Cast hinzuzufügen:</p>

```groovy
Date birthday = ...
recKunde.Geburtstag.setDate(birthday as Date)
```

## Mehrere Datensätze filtern

Ähnlich dem XML-Filter mit bx:containerfilter können in Groovy Datensätze gefiltert werden. Der Methode werden als erster Parameter eine Liste an Kriterien (bestehend aus einer drei-Elementigen Liste pro Kriterium mit: Feld(ern), Vergleichstyp und Vergleichswert) und als zweiter Parameter eine Map von Optionen übergeben. Das Ergebnis is ein (evtl. leeres) Array aus `BatixRecord`s.

Ab Version 2.6.8 kann bei der Kriterien-Liste jeweils ein vierter Parameter angegeben werden (`true` oder `false`), welcher dem `required`-Attribut in der XML entspricht. Das ist nützlich, falls man direkt Sachen aus dem Request o.ä. als Vergleichswert angibt: `["Name", 1, request.getParameter("name"), true]` (in späteren Versionen führt ein leerer Vergleichswert ohne explizite required-Angabe dann zum Abbruch)

```groovy
BatixRecord[] recs = tmdKunden.findRecords([
  ["Leistungen", 5, 0], // Feld darf nicht leer sein
  ["Newsletter", 4, 1], // Feld muss angehakt sein
  [["Name", "Vorname"], 1, "muster"] // mindestens eins der beiden Felder muss "muster" enthalten
], [
  orderby: "Kundennummer", // optional, Sortierungsfeld (Standard ID)
  desc: true, // optional, Sortierrichtung (Standard aufsteigend)
  index: 5, // optional, Startindex (Null-basiert)
  limit: 20, // optional, maximale Anzahl Ergebnisse
  active: true, // optional, aktive Datensätze suchen? (Standard ja)
  inactive: true // optional, inaktive Datensätze suchen? (Standard nein)
])
```

Die Zahlen entsprechen den Typen des [normalen Filters](#). Es müssen nicht alle Parameter angegeben werden, ein kurzes Beispiel ist (in Groovy steht `[:]` für eine leere Map):

```groovy
BatixRecord[] recs = tmdKunden.findRecords([
  ["archived", 4, 1] // alle archivierten Kunden finden
], [:])
```

Ab Version 2.7.0 können auch mehrere Sortierungs-Kriterien angegeben werden. Dabei sind folgende Formate für `orderby` möglich (`desc` wird dann ignoriert):

```groovy
BatixRecord[] recs = tmdKunden.findRecords([], [
  orderby: [
    "Firma", // aufsteigend
    ["Name"], // aufsteigend
    ["Vorname", true] // absteigend
  ]
])
```

## Einen Datensatz filtern

Ab Version 2.7.0 ist es auch möglich nur den ersten Datensatz zu laden, anstatt alle:

```groovy
BatixRecord rec = tmdKunden.findRecord([
  // siehe oben
], [
  // siehe oben
])
```

Rückgabewert ist entweder ein `BatixRecord` oder `null`.

## Batix-Quelltext ausführen

Will man schnell einen String evaluieren, der Batix-Tags enthält, kann diese Methode benutzt werden:

```groovy
String code = '<bx:math>1 + 1</bx:math>'
String result = code.evaluateAsBatixSource()
```

Der Standard Mime-Typ ist text/html, um einen anderen zu benutzen (manche Tags machen unterschiedliche Sachen, je nach Mime-Typ der Seite) kann dieser als Parameter mitgegeben werden: `evaluateAsBatixSource("text/plain")`.

# Groovy Syntax und Beispiele

<!-- last_modified: 30. Aug 2017 -->
Nebst den hier am häufigsten genutzten Elementen gibt es noch viele weitere Funktionen und Helfer, siehe dazu auch die <a href="http://www.groovy-lang.org/documentation.html" target="_blank">offizielle Doku</a> (auf die Version achten).

## Syntax

Klammern um Parameter sowie das Semikolon am Ende der Zeile können weggelassen werden.
Empfehlung: Klammern verwenden, Semikolon weglassen.

```groovy
println "Hello, World"
println("Hello, World") // Empfehlung
println("Hello, World");
```

Typen müssen nicht explizit angegeben werden (`def` entspricht quasi `Object` in Java bzw. `var` in JavaScript).
Empfehlung: Typen explizit angeben, falls die IDE sie nicht automatisch erkennt und demtentsprechend keine sinnvollen Vorschläge für Syntax-Completion macht.

```groovy
def x = 11.8 // erst Zahl
println(x)

x = "Test" // dann String
println(x.toUpperCase())
```

Typen werden, soweit möglich automatisch umgewandelt, es müssen keine expliziten Casts verwendet werden (hier kann aber das Schlüsselwort `as` verwendet werden).
Es erfolgt auch ein automatisches Boxing / Unboxing (int <--> Integer etc.).

```groovy
def i = "5" as int
eineListe.add(12)
```

Der Gleichheits-Operator in Groovy (`==`) wird im Hintergrund zu einem `.equals()` Aufruf umgewandelt.

```groovy
String a = "test"
String b = "te" + "st"
println(a == b) // true, in Java: a.equals(b)
```

Strings können von Anführungszeichen (`"`), Apostrophen (`'`) oder Slashes (`/`) umschlossen sein.
Empfehlung: Das verwenden, was im String nicht vorkommt, um nicht escapen zu müssen (Slashes, falls Anführungszeichen und Apostrophe vorkommen bzw. für Reguläre Ausdrücke).

```groovy
"str" == 'str' == /str/ 
```

Es gibt auch Mehrzeilige Strings. Ein Backslash (`\`) bewirkt, dass der Zeilenumbruch vor der ersten Zeile im Code nicht mit ausgegeben wird.

```groovy
println("""
Zeile 1
Zeile 2
"""
 
println("""\
einzige Zeile"""
```

In Strings mit Anführungszeichen (einfach oder dreifach für mehrzeilige Strings) können Code-Platzhalter verwendet werden, die durch ihren Wert ersetzt werden.

```groovy
def user = "alice"
println("Hi $user")
println("aktueller Timestamp: ${new Date().time}")
```

## Closures

Closures entsprechen in etwa den `function`s in JavaScript oder Lambda-Funktionen in Java 8. Es muss dabei nicht explizit `return` angegeben werden, der Rückgabewert des letzten Statements wird als Rückgabewert der Closure benutzt. Parameter müssen nicht typisiert werden.

```groovy
// keine Parameter
def c1 = {
  "Hello"
}
c1()
 
def c2 = { name ->
  "Hello, $name!"
}
c2("World")
```

Methoden, die eine Closure als einzigen oder letzten Parameter akzeptieren, kann die Closure direkt übergeben werden (keine runden Klammern nötig).

```groovy
"...".eachLine { line ->
  println(line.reverse())
}
```

Falls die Closure genau ein Parameter übergeben bekommt, so muss dieser nicht benannt werden, der Standardname ist "`it`".

```groovy
"...".eachLine {
  println(it.reverse())
}
```

## Spaceship-Operator

Vergleiche (`compareTo`) erledigt der Spaceship-Operator, das vereinfacht die Implementation eines `Comparator`s.

```groovy
println 5 <=> 10         // Java: 5.compareTo(10)
println "def" <=> "abc"  // Java: "def".compareTo("abc")
println null <=> 10      // gibt keine Exception
```

**Beispiel: System Properties filtern**

```groovy
System.properties
  .findAll { it.key.startsWith("user") }
  .sort { x, y -> x.key <=> y.key }
  .each { println it }
```

## Get / Set

Es werden automatisch JavaBeans-Accessors erzeugt bzw. angesprochen, d.h. man muss nicht `getProp()` oder `setProp()` aufrufen, sondern kann einfach `prop` schreiben.

```groovy
// Lesen
println(obj.thing)   // entspricht obj.getThing()
println("...".empty) // entspricht "...".isEmpty()
 
// Schreiben
obj.thing = null     // entspricht obj.setThing(null)
```

## Arrays / Lists / Maps / Ranges / Collections

Für Listen und Maps gibt es eine native Syntax.

**Liste**

```groovy
def a = [1, 2, 3]  // eine ArrayList im Hintergrund
println(a[1])      // einfach auf Elemente zugreifen

println([].size()) // eine leere Liste
```

**Map**

```groovy
def m = [language: "Groovy", version: 2.1] // eine LinkedHashMap
println m["language"]  // einfach auf Elemente zugreifen
println m.version      // einfach auf Elemente zugreifen

println([:].size())    // eine leere Map
```

Mit Ranges kann man einfach Zahlenbereiche generieren.

```groovy
(1..10).each { println(it) }  // 1 bis 10
(1..<10).each { println(it) } // 1 bis 9
(5..-5).each { println(it) }  // absteigend
```

Außerdem können mittels Ranges teile von Strings und Collections extrahiert werden.

```groovy
def a = [1, 2, 3, "a", "b", "c"]
println a[-2]     // b
println a[2..4]   // [3, a, b]
println a[2..1]   // [3, 2]
println a[-2..2]  // [b, a, 3]

def s = "the quick brown fox"
println s[4..9, -3..-1]   // quick fox
```

Um zu überprüfen, ob eine Collection ein Element enthält, kann der `in` Operator verwendet werden.

```groovy
println(5 in [1, 5, 10]) // true
```

Diesen gibt es auch in der verkürzten Variante der `for`-Schleife.

```groovy
def a = [1, 5, 10]
for (i in a) {
  println(i)
}
```

Groovy bringt viele Hilfsmethoden für Collections mit.

```groovy
[5, 4, 8, 1, 4, 5, 2].sort().unique().reverse()   // Sortieren, Doppler entfernen, Reihenfolge invertieren
(1..10).take(3).drop(1)                           // nur die ersten 3 Elemente nehmen und davon dann das erste wegschmeißen
[4, 7, 1].min()                                   // Minimum finden
[cents: 5, dime: 2, quarter: 3].max { it.value }  // Maximum finden und dabei festlegen, was verglichen werden soll pro Element
(1..100).sum()                                    // Summe bilden
["abc", "def", "abcdef"].findAll { it.startsWith("a") }  // alle Elemente finden, die einer Bedingung entsprechen
["abc", "abcdef"].collect { it.length() } == [3, 6]      // Elemente transformieren
 
['a', 'b'] << [1, 2]    // [a, b, [1, 2]]   Element anhängen
['a', 'b'] + [1, 2]     // [a, b, 1, 2]     Listen zusammenführen
[1, 2, 3].join("~")   // 1~2~3     Elemente mittels Trenner zusammenführen
 
def a = [1, 2, 3, 4, 5]
println(a.any { it > 3 })    // true, erfüllt mindestens ein Element die Bedingung?
println(a.every { it < 5 })  // false, erfüllen alle Elemente die Bedingung?
```

Wenn man nicht immer prüfen will, ob ein Key in einer Map ist, bevor man ihn benutzt, kann man ein Default-Wert festlegen. Dieser wird dann unter dem Key automatisch in der Map angelegt, sobald das erste Mal auf ihn zugegriffen wird.

```groovy
def map = [:].withDefault {
  new Date()
}

println map.test  // Zeit 1
sleep(2000);
println map.test  // immer noch Zeit 1
println map.test2 // Zeit 2
```

## RegEx

Reguläre Ausdrücke haben auch eine verkürzte Syntax.
Slashes werden hier nur der Lesbarkeit / Identifizierbarkeit verwendet, es sind immer noch normale Strings (nicht wie in JavaScript, wo mit Slashes direkt reguläre Ausdrücke erzeugt werden).

```groovy
// Pattern erzeugen
Pattern p = ~/\d+/
println(p.matcher("123").matches())
 
// Matcher erzeugen
Matcher m = "123" =~ /\d(\d)\d/
println(m.matches())
println(m.group(1))
 
// Direkt matchen
println("123" ==~ /\d+/) // true
```

## Null-Dereferenzierung

Um NullPointerExceptions vorzubeugen, ohne dauernd mit `if` auf `null` prüfen zu müssen, empfiehlt sich der `?.` Operator. Dieser stoppt, sobald der Ausdruck vor dem Fragezeichen `null` ist und gibt `null` zurück.

```groovy
class Person {
  def name
}

def p
println(p?.name?.length())  // null

p = new Person()
println(p?.name?.length())  // null

p.name = "Tester"
println(p?.name?.length())  // 6
```

## Elvis-Operator

Default Werte können mit dem Elvis-Operator (`?:`) vereinfacht werden. Dies entspricht dem Ternary-If, wobei die Bedingung und der True-Teil identisch sind.

```groovy
null ?: 5        // 5         -->  null ? null  :      5
false ?: "test"  // test      --> false ? false : "test"
4 ?: 8           // 4         -->     4 ?     4 :      8
```

## Switch

Das switch Statement wurde auch erweitert.

```groovy
def testSwitch(val) {
  switch (val) {
    case ~/^Switch.*Groovy$/: return 'Pattern match'
    case BigInteger: return 'Class isInstance'
    case 60..90: return 'Range contains'
    case [21, 'test', 9.12]: return 'List contains'
    case 42.056: return 'Object equals'
    case { it instanceof Integer && it < 50 }:
      return 'Closure boolean'
    default: return 'Default'
  }    
}

println testSwitch("Switch to Groovy")
println testSwitch(42G)
println testSwitch(70)
println testSwitch('test')
println testSwitch(42.056)
println testSwitch(20)
println testSwitch('default')
```

## JSON

Mit JSON kann sehr einfach gearbeitet werden.

**JSON lesen**

```groovy
def slurper = new groovy.json.JsonSlurper()
def json = slurper.parseText("""
{
  "name": "Mustermann",
  "ids": [5, 10, 11]
}
""")
println(json.name)   // Mustermann
println(json.ids[1]) // 10
```

<p class="callout warning">In neueren Groovy-Versionen liefert der <code>JsonSlurper</code> eine <code>LazyMap</code> zurück, die nicht serialisiert werden kann (falls etwas in der Session gespeichert werden soll). Die Variante mit <code>HashMap</code> ist noch als <code>JsonSlurperClassic</code> verfübar.</p>

Ein JSON-String ist auch schnell aus normalen Objekten (Strings, Lists, Maps, ...) erzeugt:

**JSON schreiben**

```groovy
def builder = new groovy.json.JsonBuilder()
def obj = [
  name: "Mustermann",
  ids: [5, 10, 11]
]
builder(obj)
println(builder.toPrettyString()) // JSON von oben
```

Als Abkürzung kann die Hilfsklasse `JsonOutput` verwendet werden.

**JsonOutput**

```groovy
import groovy.json.JsonOutput

def obj = [
  name: "Mustermann",
  ids: [5, 10, 11]
]
def jsonStr = JsonOutput.toJson(obj)
println(jsonStr) // alles auf einer Zeile, spart Bytes
println(JsonOutput.prettyPrint(jsonStr)) // lesbar
```

## XML

Für XML-Input gibt es 2 Verarbeitungsmöglichkeiten: `XMLParser` und `XMLSlurper` (siehe dazu auch die <a href="http://groovy-lang.org/processing-xml.html" target="_blank">Groovy Doku</a>).

`XmlParser` parst das komplette XML und baut eine Struktur im RAM auf, was es erlaubt Teile der XML oft und dabei schnell abzufragen (falls dem XML-Dokument <a href="http://groovy-lang.org/processing-xml.html#_manipulating_xml" target="_blank">Nodes aktualisiert oder hinzugefügt</a> werden sollen, wird auch `XmlParser` empfohlen):

**XML lesen (mit XmlParser)**

```groovy
def parser = new XmlParser()
def root = parser.parseText("""
<person>
  <access read='true' write='false' />
  <data>
    <name>Mustermann</name>
  </data>
  <data>
    <name>Musterfrau</name>
  </data>
</person>
""")
println(root.access.@write[0])     // false
println(root.data[1].name.text())  // Musterfrau
```

`XmlSlurper` hingegen wertet das XML nur partiell und on-demand aus - somit wird RAM gespart, häufige Zugriffe hingegen dauern ggf. länger (dafür können Abfragen aber etwas kürzer geschrieben werden):

**XML lesen (mit XmlSlurper)**

```groovy
def slurper = new XmlSlurper()
def root = slurper.parseText("""
<person>
  <access read='true' write='false' />
  <data>
    <name>Mustermann</name>
  </data>
  <data>
    <name>Musterfrau</name>
  </data>
</person>
""")
println(root.access.@write)     // false
println(root.data[1].name)      // Musterfrau
```

Um XML-Dokumente programmatisch zusammenzubauen, bietet such `MarkupBuilder` an:

**XML schreiben**

```groovy
def writer = new StringWriter()
def builder = new groovy.xml.MarkupBuilder(writer)

builder.person {
  access(read: true, write: false)
  data {
    name("Mustermann")
  }
  data {
    name("Musterfrau")
  }
}

println(writer.toString()) // XML von oben
```

Um schnell einzelne Teile einer XML zu ändern und wieder in einen String zu überführen, kann der `XmlParser` und die Hilfsklasse `XmlUtil` verwendet werden. Hier ein Beispiel, um Werte zum Validation-Feld hinzuzufügen:

**XML parsen, bearbeiten, zurückschreiben**

```groovy
import groovy.xml.XmlUtil

// XML parsen
def rootNode = new XmlParser().parseText("""
<result size="1">
  <field name="Kontakt_Email" resultcode="1" bin="00000001" hex="0x01" />
</result>
""")

// Attribut ändern
rootNode.@size++

// Node hinzufügen (Parameter sind Name der Node sowie Attribute als Map)
rootNode.appendNode("field", [
  "name": "Kontakt_Name",
  "resultcode": "1",
  "bin": "00000001",
  "hex":"0x01"
])

// wieder XML-String erzeugen
println(XmlUtil.serialize(rootNode))
/* Ergebnis:
<?xml version="1.0" encoding="UTF-8"?><result size="2">
  <field name="Kontakt_Email" resultcode="1" bin="00000001" hex="0x01"/>
  <field name="Kontakt_Name" resultcode="1" bin="00000001" hex="0x01"/>
</result>
 */
```

## SQL

Auch mit SQL kann einfacher gearbeitet werden.

```groovy
java.sql.Connection conn = ...
def sql = new groovy.sql.Sql(conn)

def foo = "fruit"
sql.eachRow("SELECT * FROM food WHERE type=${foo}") {  // Parameter werden automatisch SQL-Encoded
  println("I like ${it.name}")                         // gibt Spalte "name" aus
}
```

<p class="callout warning">Um ein automatisches SQL-Encoden zu gewährleisten, darf der Query-String nicht aus mehreren Strings zusammengebaut werden, sondern darf nur ein String mit Platzhaltern sein.</p>

## Überladene Methoden und Typen

Da Groovy Methoden dynamisch aufruft, zur Laufzeit aber nicht mehr die genauen Typen aus dem Quellcode kennt (wegen Type Erasure etc.), kann es vorkommen, dass mehrere Methoden gefunden werden, die zum Aufruf passen.

Das ist meistens der Fall, wenn `null` übergeben wird, hier weiß Groovy nur, dass es ein `NullObject` ist, kennt aber nicht den genauen Typ:

```groovy
String str = null
println(str.getClass().simpleName) // NullObject
```

Beispielsweise gibt es diese zwei Methoden:

```java
void setDate(String str) { ... }
void setDate(Date date) { ... }
```

Erfolgt nun in Groovy der Aufruf folgendermaßen:

```groovy
// null als Literal
obj.setDate(null)
obj.date = null
 
// oder als Variable
String str = null
obj.date = str
```

Dann weiß Groovy nicht, welche Methode es genau aufrufen soll, das sowohl `String` als auch `Date` zu `NullObject` passen (`null` bzw. `NullObject` kann in beides umgewandelt werden).

Frühere Groovy-Versionen haben einfach irgendeine Methode genommen, neue Versionen werfen eine Exception. Da dies nicht rückwärts-kompatibel ist, bringen CMS-Versionen, welche neuere Groovy-Versionen enthalten, stattdessen einen Fehler im Log, funktionieren aber weiterhin mit altem Code (es wird irgendeine Methode genommen).

Falls so ein Szenario auftritt, kann man Groovy aber helfen, in dem man beim Aufruf den Typ explizit als Cast hinzufügt (es muss hier die Methode aufgerufen werden, beim Property-Setter geht die Typ-Info wieder verloren):

```groovy
obj.setDate(str as String) // OK
obj.setDate((String)str)   // OK
 
// obj.date = str as String // geht nicht
// obj.date = (String)str   // geht nicht
```

# Groovy – Übersicht

<!-- last_modified: 06. Jun 2016 -->
Seit Version 2.6.2 ist es möglich die Scriptsprache <a href="http://www.groovy-lang.org/" target="_blank">Groovy</a> im CMS zu verwenden (sowohl in Actions als auch in Templates). Zu beachten ist, dass je CMS-Version ggf. eine andere Groovy-Version eingebunden ist - dazu die .jar Datei im lib-Verzeichnis prüfen oder in Entwickler-Tools ausführen: `println(GroovySystem.version)`.

Groovy ist eine dynamische Sprache mit vereinfachter Syntax und Funktionalitäten (ähnlich JavaScript) und vielen schon eingebauten Utilities. Außerdem wurden bestimmte Sachen des CMS erweitert, damit man sie einfach in Groovy benutzen kann (z.B. Datensätze bearbeiten).

- [Verwendungsmöglichkeiten](/books/cms-handbuch-entwickler/page/verwendungsmoglichkeiten)
- [Groovy Syntax und Beispiele](/books/cms-handbuch-entwickler/page/groovy-syntax-und-beispiele)
- [CMS-spezifische Helfer](/books/cms-handbuch-entwickler/page/cms-spezifische-helfer)
- [Tips](/books/cms-handbuch-entwickler/page/tips)
- [Bibliothek – Übersicht](/books/cms-handbuch-entwickler/page/bibliothek-ubersicht)

# Logging

<!-- last_modified: 01. Mar 2018 -->
Es können `logI("text")` für INFO-Meldungen etc. verwendet werden. `logE` kann als zweiter Parameter zusätzlich noch eine Exception übergeben werden.

Zur besseren Übersicht im Log wird immer der Scriptname vorangestellt.

`logName` noch anpassen

es muss noch `com.batix.Log` importiert werden

## Zum Kopieren (für Script)

```groovy
/* Logging start */
def logName = "myScript"
//noinspection GroovyUnusedAssignment
def logD = { String msg, HttpServletRequest request = null -> Log.debug("[${logName}] ${msg}", request) }
//noinspection GroovyUnusedAssignment
def logI = { String msg, HttpServletRequest request = null -> Log.info("[${logName}] ${msg}", request) }
//noinspection GroovyUnusedAssignment
def logN = { String msg, HttpServletRequest request = null -> Log.notice("[${logName}] ${msg}", request) }
//noinspection GroovyUnusedAssignment
def logW = { String msg, HttpServletRequest request = null -> Log.warn("[${logName}] ${msg}", request) }
//noinspection GroovyUnusedAssignment
def logE = { String msg, Exception ex = null, HttpServletRequest request = null -> Log.error("[${logName}] ${msg}", request, ex) }
/* Logging end */
```

## Zum Kopieren (für Klassen)

```groovy
/* Logging start */
private static def logName = "myScript"
//noinspection GroovyUnusedAssignment
private static void logD(String msg, HttpServletRequest request = null) { Log.debug("[${logName}] ${msg}", request) }
//noinspection GroovyUnusedAssignment
private static void logI(String msg, HttpServletRequest request = null) { Log.info("[${logName}] ${msg}", request) }
//noinspection GroovyUnusedAssignment
private static void logN(String msg, HttpServletRequest request = null) { Log.notice("[${logName}] ${msg}", request) }
//noinspection GroovyUnusedAssignment
private static void logW(String msg, HttpServletRequest request = null) { Log.warn("[${logName}] ${msg}", request) }
//noinspection GroovyUnusedAssignment
private static void logE(String msg, Exception ex = null, HttpServletRequest request = null) { Log.error("[${logName}] ${msg}", request, ex) }
/* Logging end */ 
```

## Beispiel

```groovy
def user = BxUser.findInstance(request)
if (!user) {
  logE("no user found")
  return
}
 
logI("found user ${user.id}")
```

# Timings

<!-- last_modified: 22. Oct 2018 -->
Zwischendrin immer `addTiming("kleine Info was gemacht wurde")` aufrufen.

Es können auch einzelne Durchläufe einer Schleife gemessen werden: `addTiming("Info zur Schleife", "Info zum Durchlauf")`.
So werden die aufeinanderfolgende Timings, bei denen der erste Parameter identisch ist, gruppiert.

Am Ende gibt `getTimings()` eine Zusammenfassung als `String` zurück.
Für Schleifen wird die Gesamtdauer sowie die Anzahl der Durchläufe und die mittlere Dauer ausgegeben. Außerdem werden die Top und Flop 3 der Durchläufe (nach Dauer) angezeigt.

## Zum Kopieren

```groovy
/* Timings start */
def timings = []
def timingLast = new Date().time
def addTiming = { String title, String subTitle = null ->
  def duration = new Date().time - timingLast
  if (subTitle) {
    def value = [
      duration: duration,
      title: subTitle
    ]
    if (!timings || timings[-1].title != title) {
      timings << [
        title: title,
        values: []
      ]
    }
    timings[-1].values << value
    value.index = timings[-1].values.size()
  } else {
    timings << [
      duration: duration,
      title: title
    ]
  }
  timingLast = new Date().time
}
Closure<String> getTimings = {
  def res = new StringBuilder()
  res << "Timings:\n"
  def timingTotal = 0
  def emptyPrefix = " " * 27
  def maxDetails = 6
  timings.each { t ->
    if (t.values) {
      List vals = t.values.sort { a, b ->
        a.duration <=> b.duration ?:
          a.index <=> b.index
      }
      long sum = vals.sum { it.duration } as long
      double avg = sum / t.values.size()
      timingTotal += sum
      res << String.format("%8d ms (+%8d ms) %s (%dx ~%.2f ms)\n", timingTotal, sum, t.title, t.values.size(), avg)
      if (vals.size() > maxDetails) vals = [*vals[0..(maxDetails / 2 - 1)], null, *vals[-(maxDetails / 2)..-1]]
      vals.each { val ->
        res << emptyPrefix
        if (val) res << String.format("#%-4d %4dms %s\n", val.index, val.duration, val.title)
        else res << "[...]\n"
      }
    } else {
      timingTotal += t.duration
      res << String.format("%8d ms (+%8d ms) %s\n", timingTotal, t.duration, t.title)
    }
  }
  def lastDuration = new Date().time - timingLast
  timingTotal += lastDuration
  res << String.format("%8d ms total\n", timingTotal)
  return res.toString()
}
/* Timings end */
```

## Beispiel

```groovy
// do stuff
addTiming("startup")
// do more stuff
addTiming("init")
// do loop stuff 1
addTiming("fetch info", "load one...")
// do loop stuff 2
addTiming("fetch info", "load two...")
// ...
// do database stuff
addTiming("finalizing")
// do final stuff
```

Erzeugt dann z.B. mit `logI(getTimings())` sowas:

```text
Timings:
       1 ms (+       1 ms) startup
      94 ms (+      93 ms) init
     753 ms (+     659 ms) fetch info (7x ~94,14 ms)
                           #4      15ms load 15F53263D95
                           #5      16ms load 15F53263DA5
                           #3      17ms load 15F53263D86
                           [...]
                           #2      20ms load 15F53263D75
                           #6      78ms load 15F53263DF3
                           #1     496ms load 15F53263D61
    2598 ms (+    1845 ms) finalizing
    2605 ms total 
```

# Tips

<!-- last_modified: 11. Jan 2021 -->
Hier gibt es lose gesammelte Tricks und Kniffe.

## Bessere Exceptions im Log

Um Stacktraces von unnötigem Groovy-Meta-Ballast zu befreien und so direkt lesbar zu machen, gibt es `StackTraceUtils.deepSanitize`. Statt die Exception direkt an `Log` o.ä. zu übergeben, einfach diese Methode drumherum packen und schon verschwinden unnötige Zeilen aus dem Stacktrace.

```groovy
import com.batix.Log
import org.codehaus.groovy.runtime.StackTraceUtils
// ...
try {
  // ...
} catch (Exception ex) {
  Log.error("my error message", StackTraceUtils.deepSanitize(ex))
}
```

## Session

Manchmal gibt es Probleme in **Groovy**, wenn es keine Session gibt, weil standardmäßig kein Sessioncookie mehr erzeugt wird. Dadurch ist die Groovy-Variable session nun manchmal leer und muß im GroovyAction mit if (!session) session = request.session gefüllt werden und in &lt;bx:groovy&gt; mit session = includeTag.forceSession() Das müßte auch noch irgendwo in die Hilfe eingetragen werden.

Wenn man keine Session im **JSP** braucht sollte man oben &lt;%@page session="false"%&gt; hinzufügen. Sonst wird auf der Seite, auf der das JSP eingebunden ist, ein Session-Cookie erzeugt.

# Verwendungsmöglichkeiten

<!-- last_modified: 06. Jun 2016 -->
Groovy-Code kann in Actions (Actionbaustein "Groovy ausführen") oder in Quelltexten ([bx:groovy](/books/cms-handbuch-entwickler/page/bxgroovy)) eingesetzt werden. Es gibt auch die Möglichkeit in den Entwickler-Tools schnell Groovy-Code auszuführen.

Um Ausgaben zu erzeugen, kann einfach `println` verwendet werden:

- Tag: der Text wird in die Seite geschrieben
- Action: der Text wird ausgegeben, falls `action.sendJSPOutput()` aufgerufen wurde, ansonsten kann auch `action.originalResponse` verwendet werden
- Entwickler-Tools: der Text wird im Output auf der Seite angezeigt

Außerdem ist es jeweils möglich zentrale Groovy-Bausteine aus dem aktuellen Projekt einzubinden (unter Dokumentvorlagen > Groovy), um Code nachzunutzen - dies ist das gleiche Prinzip wie bei Textbausteinen.

# Werkzeuge & Integrationen

# Abgleichtool

<!-- last_modified: 07. Nov 2019 -->
## Anleitung Abgleichtest

Ist auf dem empfangenden System auszuführen.

Zu finden unter:

Entwicklertools / Abgleichtest

Zum Anmelden die Server- und Zugangsdaten des sendenden Systems angeben.

z.B.  URL:  https//84-xxxxxxxxx.batix.cloud

       Benutzer : ADMIN

       Passwort: 123456789

Es werden jetzt alle Tabellen angezeigt mit Anzahl der Datensätze und Differenzen angezeigt.

z.B. Design

![image2019-11-5_8-8-13.png](https://batix.help/uploads/images/gallery/2026-05/Yd0NXHytRNsdbjjT-19300565.png)

Mit einem Klick auf Daten werden die Details angezeigt.

Wahrscheinlich unvollständige Liste der interessanten Einträge:

| | |
|---|---|
| Action | Einzelbestandteile der Actionscripte |
| Actionscript | Actionbausteine |
| Designs | Alles unter Dokumentenvorlagen(Komplettseiten, Designtemplates,   Textbausteine, JSP-Bausteine, Groovy, Plugins, sonstiges) |
| EZT | Einzeiliger Text |
| Felder | Verknüpfung EZT zu Menü |
| MZT | Mehrzeiliger Text |
| NAVFILES | Bestandteile der Navigationspunkte |
| Navigation | Navigationspunkte |
| Styles | CSS - DAtein |
| Tabledef | Containerliste |
| Tablefields | Containerfelderinformationen z.B. Verknüpfungen , Untercontainer usw. |
| <span style="color: rgb(51,51,51);">ADMINGROUP</span> | Gruppen der User |
| <span style="color: rgb(51,51,51);">IMGARCHIV</span> | Bilder für Navigation |
| <span style="color: rgb(51,51,51);">IMGKAT</span> | Kategorien der Bildergalerie |
| <span style="color: rgb(51,51,51);">IMG</span> | Bilderverknüpfung |
| <span style="color: rgb(51,51,51);">LOOP</span> | BX-Schleife |
| <span style="color: rgb(51,51,51);">LOOPELEMENT</span> | Element des LOOP |
| <span style="color: rgb(51,51,51);">DOC</span> | Verknüpfung der Dokumente |
| <span style="color: rgb(51,51,51);">DOCARCHIV</span> | Dokument |
| <span style="color: rgb(51,51,51);">DOCFOLDER</span> | Baumstruktur der Dokumente |

Anschließend kann es sinnvoll sein unter Entwicklertools  zu klicken.

![image2019-11-5_8-8-35.png](https://batix.help/uploads/images/gallery/2026-05/7EAbU47dx0u7Mb2Q-19300566.png)

Es können jetzt die Einträge ausgewählt werden, welche auf das empfangende System übertragen werden sollen. Anschließend ganz unten auf  „ausgewählte ändern" klicken und auf der Folgeseite bestätigen.

Um sich die Unterschiede der beiden Dateien anzeigen zu lassen besteht die Möglichkeit ganz link auf Details zu klicken.

Es werden dann beide Stände zum Vergleichen angezeigt.

![image2019-11-5_8-9-25.png](https://batix.help/uploads/images/gallery/2026-05/D2T191eXhhg8ZuLH-19300567.png)

# VUE

<!-- last_modified: 05. Feb 2020 -->
## Intro

Wie schon mehrfach bemerkt, ist es sehr umständlich ein dynamisches Frontend von Grund auf per Hand in HTML und JavaScript umzusetzen. Abhilfe schaffen z.B. Frameworks wie <a href="https://vuejs.org/" target="_blank">Vue</a> (ausgesprochen wie das englische „View", manch einer nennt es auch eingedeutscht „Wü"). Diese kümmern sich um die Dynamisierung einer Ansicht anhand von Daten.

Ein ersten Projekt war die <a href="https://crm-dev.batix.com/planung/tools/#fzk" target="_blank">Reisekostenabrechnung im neuem CRM</a>. Wer das noch nicht kennt, darf gern in den Feldern rumschreiben und die bunten Knöpfchen drücken (keine Angst, es wird nichts gespeichert oder gelöscht). Es wurde dabei nur der Frontend-Code angefasst (das Formular sendet immer noch an dasselbe Action) und in knapp einer Stunde war das Thema erledigt.

Dabei ist sogar eine neue Funktion (Live-Anzeige der Summe der Posten) rausgesprungen. Zu Demozwecken habe ich unten drunter noch die aktuellen Daten ausgegeben, die sich bei Änderungen live aktualisieren!

Es werden hier nicht alle Begriffe erklärt, sondern nur das, was für das Beispiel nötig ist. Wer mag kann gern Google bemühen oder den weiterführenden Links folgen. Manches ist vielleicht nicht 100% Best Practice, das würde aber sonst den Rahmen sprengen.

## Installation

Vue ist fix <a href="https://vuejs.org/v2/guide/installation.html#Direct-lt-script-gt-Include" target="_blank">installiert</a>. Man muss lediglich eine .js Datei via `<script>` einbinden. Während der Entwicklung empfiehlt sich die *Development Version*, da man hier hilfreiche Warnungen und genaue Fehler erhält, sollte mal etwas schief gehen. Die Dateigröße hält sich in Grenzen:

- Development Version (also unminified): **283 KB** (ca. wie jQuery UI minified)
- Production Version (minified): **85 KB** (wie jQuery minified) [**31 KB**, wenn sie vom Server noch mit GZIP komprimiert übertragen wird]

Wer einfach mal etwas mit Vue testen will, kann z.B. hier einfach live rumprobieren: <a href="http://jsfiddle.net/filipelinhares/2eAqE/" target="_blank">http://jsfiddle.net/filipelinhares/2eAqE/</a> (nach Änderungen oben auf Run drücken)

## Grundlegendes

Oberste Priorität bei der Entwicklung mit Vue (und auch anderen MVC/MVVM/etc.-Frameworks) hat die **Trennung von Daten (Model) und Anzeige (View)**.

Das bedeutet, dass alle Daten, die für den Aufbau der Anzeige nötig sind, im JavaScript als Objekte vorhanden sind, bzw. daraus berechnet werden können. In erweiterten Szenarien können Daten auch asynchron nachgeladen werden.

Ist das erledigt, definiert man die Anzeige mittels einem Template. Das erfolgt größtenteils mit normalen HTML-Tags. Hier und da können spezielle Platzhalter verwendet werden, ähnlich unseren Batix-Tags. Diese unterscheiden sich in Interpolationen und Direktiven wie z.B. Schleifen (genaue Infos dazu weiter unten).

Das Besondere an Vue ist nun, dass es die Daten nimmt und anhand derer den View zusammenbaut. Es wird also kein HTML-Code beim Server angefragt. So weit, so schnell selbst gebaut. Jetzt kommt aber der Clou! Werden nun die Daten geändert (das kann u.a. das Ändern eines Strings oder das Hinzufügen/Entfernen von Array-Elementen sein) bekommt Vue das **direkt** mit und passt die Anzeige entsprechend an. Es rendert also den View neu. Hierbei ist Vue auch auf Performance bedacht und rendert nur die nötigen Teile neu, die sich geändert haben. Wow! Man kann das im CRM-Beispiel ganz gut sehen, wenn man irgendwo tippt und es aktualisiert sich die Debug-Ausgabe oder die Summe.

Das ist aber noch nicht alles, denn Vue kann auch vom User gemachte Eingaben in Textfelder oder via Checkboxen etc. **wieder zurück in die Daten schreiben**. Vue benötigt dafür kein jQuery oder sonstige Libraries.

## Model (Daten)

Im Beispiel habe ich die User-Daten der Einfachheit halber größtenteils mit Batix-Tags gefüllt. Das Objekt sieht so aus:

```xml
var fzkData = {
 date: moment().format("DD.MM.YYYY"),
  lastMonth: moment().subtract(1, 'month').format("MM.YYYY"),
  settings: {
    kennzeichen: "<bx:recordfield.FZK_Kennzeichen encode="javascript" />",
    iban: "<bx:recordfield.FZK_IBAN encode="javascript" />",
    bic: "<bx:recordfield.FZK_BIC encode="javascript" />",
    kontoinhaber: "<bx:recordfield.FZK_Kontoinhaber encode="javascript" />"
  },
  rows: []
};
```

Dabei ist `lastMonth` eine Hilfsvariable, `settings` und `date` entsprechen den Feldern im linken Bereich und `rows` sind die Tabellenzeilen im rechten Bereich.

Die Daten werden beim Erzeugen einer Vue-Instanz übergeben und sind dann innerhalb der Instanz sowie im Template verfügbar.

## View (Anzeige)

Das komplette Template habe ich ein div mit der ID `fzkApp` gepackt. Ich zeige hier ein paar Ausschnitte davon. Die ganzen Bootstrap Klassen und das Beiwerk lasse ich dabei zwecks Lesbarkeit weg.

Die linke Seite sieht im Quelltext so aus

```xml
<h5>Daten</h5>
<div>
  <label for="Kennzeichen">Kennzeichen</label>
  <input type="text" name="Kennzeichen" v-model="settings.kennzeichen">
</div>
<div>
  <label for="IBAN">IBAN</label>
  <input type="text" name="IBAN" v-model="settings.iban">
</div>
<div>
<label for="BIC">BIC</label>
  <input type="text" name="BIC" v-model="settings.bic">
</div>
<div>
  <label for="Kontoinhaber">Kontoinhaber</label>
  <input type="text" name="Kontoinhaber" v-model="settings.kontoinhaber">
</div>
<div>
  <label for="Datum">Datum</label>
  <input type="text" name="Datum" v-model="date">
</div>
```

Der einzige Unterschied zu normalem HTML ist die <a href="https://vuejs.org/v2/api/#v-model" target="_blank">v-model</a> Direktive. Damit man diese von normalen Attributen unterscheiden kann, fangen die Direktiven übrigens mit `v-` (für Vue) an.

Dank `v-model` wird von Vue für dieses Element ein sogenanntes **Two-Way-Binding** zu den Daten erzeugt. Das bedeutet die folgenden Prozesse laufen automatisch ab:

- ändern sich die Daten -> ändert sich das angezeigte Input
- ändert sich das Input (durch User-Interaktion) -> ändern sich die Daten

Man sieht hier schön, dass der Wert von `v-model` dem „Pfad" in den Daten entspricht. Am Ende ist es quasi JavaScript-Code, der die gewünschte Variable holt.

Die rechte Seite sieht so aus:

```xml
<h5>Posten</h5>

<table>
  <thead>
    <tr>
      <th>Belegdatum</th>
      <th>Ausgabe (z.B. Menge + Kraftstoffart)</th>
      <th>Betrag [€]</th>
      <th></th>
    </tr>
  </thead>
  <tbody>
    <tr v-for="(row, index) in rows">
      <td><input type="text" :name="'ph_' + index + '_datum'" v-model="row.datum"></td>
      <td><input type="text" :name="'ph_' + index + '_ausgabe'" v-model="row.ausgabe"></td>
      <td><input type="text" :name="'ph_' + index + '_betrag'" v-model="row.betrag"></td>
      <td><button @click="removeRow(index)">x</button></td>
    </tr>
  </tbody>
</table>

<span>Summe: {{ sum }} €</span>

<button @click="addRow()">+</button>
<button type="submit">erstellen</button>
```

Hier gibt es einige neue Sachen! Zum einen wäre da <a href="https://vuejs.org/v2/api/#v-for" target="_blank">v-for</a>, was man sich wie eine for-Schleife z.B. in JavaScript vorstellen kann. Diese Direktive sorgt dafür, dass ein `<tr>` für jedes Element im `rows`-Array erzeugt wird. Hier hilft es sich die Daten gefüllt vorzustellen, nehmen wir also mal an:

```xml
"rows": [
  { // = row, index 0
    "datum": "12.10.2018",
    "ausgabe": "23,5 l Diesel",
    "betrag": "33,44"
  },
  { // = row, index 1
    "datum": "20.10.2018",
    "ausgabe": "Waschen",
    "betrag": "4,99"
  }
]
```

Für diesen Fall werden also bei Benutzung von `<tr v-for="(row, index) in rows">` zwei `<tr>`s erzeugt werden. In der Direktive gibt man der Laufvariable einen Name (hier `row`), optional kann man auch noch den aktuellen Schleifendurchlauf bekommen (hier `index`). Innerhalb der Schleife kann auf Daten des aktuellen Array-Elements mittels `row` (der Laufvariable) zugegriffen werden, was man hier mit dem bekannten `v-model` sieht (`v-model="row.datum"`). In diesem Fall kommt `v-model` auch nicht mit den Array-Elementen durcheinander – Änderungen landen beim richtigen Objekt, ohne dass man extra nochmal einen Index o.ä. angeben muss.

Ein weiteres neues Konstrukt ist der Doppelpunkt. Das ist nichts weiter als eine Abkürzung für <a href="https://vuejs.org/v2/api/#v-bind" target="_blank">v-bind</a>. Statt `:name="..."` könnte man also auch `v-bind:name="..."` schreiben. Im Gegensatz zu `v-model` erzeugt `v-bind` nur ein **One-Way-Binding**, die Anzeige wird also nur aktualisiert, falls sich die Daten ändern, nicht andersrum.

Zu beachten ist, dass der Wert von `v-bind` kein reiner Text, sondern JavaScript Code ist! Das ist übrigens bei fast allen Direktiven der Fall. Möchte man also einen dynamischen String zusammenbasteln, müssen z.B. Quotes und Plusse verwendet werden.

Kurz dazu, warum ich den `name` der Inputs so dynamisch zusammenbaue: Im Beispiel wird eine `<form>` an den Server geschickt und dabei müssen die Elemente natürlich sinnvoll gruppiert sein (ähnlich new-1/Feldname beim Save-Action). Man kann den `name` auch weglassen und später die Daten direkt irgendwo hin schicken, diese spiegeln ja den Stand im View wider. Ich habe hier wie gesagt die Backend-Logik nicht angefasst und nur das Frontend analog zum Alten gebaut.

Eine weitere Abkürzung bei `@click="addRow()"` ist das @, nämlich für <a href="https://vuejs.org/v2/api/#v-on" target="_blank">v-on</a>. Anstatt `@click="..."` könnte man also auch `v-on:click="..."` schreiben. Hiermit lassen sich Events binden und auch hier ist der Wert der Direktive im Prinzip wieder JavaScript-Code (man kann die runden Klammern auch weglassen). Alle Variablen, die im Scope sind, können natürlich verwendet werden – hier z.B. `index`, um zu übergeben, welche Zeile (also welches Array-Element) gelöscht werden soll. Wo die Methoden `removeRow` und `addRow` herkommen, sehen wir weiter unten.

Als letztes, zentrales Syntax-Element ist die Interpolation, ausgedrückt durch die geschweiften Klammern, zu nennen. Innerhalb dieser, man ahnt es vielleicht schon, wird wieder JavaScript-Code geschrieben. Im einfachsten Fall ist das nur eine Variable, die dann eben ausgegeben wird. Im Beispiel steht da `sum`, was keine Variable, sondern eine „Computed Property". Details dazu gibt es auch weiter unten.

Die Ausgabe der Live-Daten funktioniert ebenfalls über Interpolation und eine Computed Property:

```xml
Live-Data:<br>
<small><pre>{{ dataAsJson }}</pre></small>
```

Es ist vielleicht aufgefallen, dass hier nicht darauf geachtet werden muss, irgendwo `htmlencode` o.ä. einzubauen. Vue kümmert sich selbst darum, dass die Daten passend escaped werden und so nicht zur Sicherheitslücke werden können (zumindest was XSS angeht).

## Vue-Instanz erzeugen

Das Template wird folgendermaßen mit den Daten verbunden und „reaktiv" gemacht:

```xml
new Vue({
  el: "#fzkApp",
  data: fzkData
})
```

Das reicht schon und man erhält seine fertige Komponente. Natürlich gibt es noch mehr <a href="https://vuejs.org/v2/api/#Options-Data" target="_blank">Optionen</a>, ein paar davon brauchen wir auch noch, um z.B. die Methoden und Computed Properties zu definieren.

## Methoden

Im Template oben wurden ja die Funktionen `addRow` und `removeRow` aufgerufen. Diese müssen natürlich noch definiert werden. Das geschieht über die Option `methods`. Hier sollten Funktionen rein, die in der Komponente (entweder im Template oder in anderen Methoden) gebraucht werden und nur spezifisch für diese Komponente sind. Ich habe die zwei Methoden folgendermaßen definiert:

```xml
new Vue({
  // ...
  methods: {
    addRow: function() {
      this.rows.push({
        datum: "__." + this.lastMonth,
        ausgabe: "",
        betrag: ""
      });
    },
    removeRow: function(index) {
      this.rows.splice(index, 1);
    }
  }
})
```

(<a href="https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Array/splice" target="_blank">splice</a> ist vielleicht nicht so bekannt: es entfernt hier einfach die angegebene Anzahl an Elementen vom übergebenen Index an)

Das `this` in solchen Methoden ist automatisch die Vue-Instanz. Darüber erhält man direkten Zugriff auf z.B. die Daten, Methoden und Computed Properties. Wie man sieht bearbeite ich hier auch nur die Daten, den Rest (das Rendern des entsprechenden HTMLs) übernimmt Vue!

Damit nach dem Laden der Seite direkt eine Zeile mit leeren Inputs zum Eingeben erscheint, wird `addRow` dann noch im `created` <a href="https://vuejs.org/v2/guide/instance.html#Instance-Lifecycle-Hooks" target="_blank">Lifecycle Hook</a> aufgerufen, welcher feuert, sobald die Vue-Instanz angelegt wurde:

```xml
new Vue({
  // ...
  created: function() {
    this.addRow();
  }
})
```

## Computed Properties

Computed Properties sind den Methoden ähnlich. Sie werden über die Option `computed` definiert. Der Unterschied zu Methoden ist, dass sie ein Ergebnis zurückliefern. Dieses kann dann im Template ausgegeben werden. Auch hier ist Vue so schlau den View zu aktualisieren, wenn sich das Ergebnis ändert. Das kann ja der Fall sein, da man in den Computed Properties irgendetwas anhand der Daten der Instanz berechnet.

Im Template oben wurden zwei Stück benutzt: `dataAsJson` gibt einfach die aktuellen Daten als JSON formatiert aus und `sum` berechnet die Summe der Tabellenzeilen. Das ist in wenigen Zeilen niedergeschrieben:

```xml
new Vue({
  // ...
  computed: {
    dataAsJson: function() {
      return JSON.stringify(this.$data, null, 2);
    },
    sum: function() {
      var s = 0;
      this.rows.forEach(function(row) {
        var amount = row.betrag ? parseFloat(row.betrag.replace(/,/, ".")) : 0;
        s += amount;
      });
      return s.toFixed(2).replace(/\./, ",");
    }
  }
});
```

Man sieht hier, dass auf `this.$data` zugegriffen wird. Das ist eine von diversen <a href="https://vuejs.org/v2/api/#Instance-Properties" target="_blank">Spezial-Properties</a> der erzeugten Vue-Instanz (die ja als `this` verfügbar ist). Ich hätte genauso gut auch `fzkData` nehmen können, da wir diese Daten im Beispiel als globales Objekt haben. Das ist aber nicht schön. Im Normalfall sollte man die Daten inline beim Instanz Erzeugen angeben, damit diese nicht aus Versehen noch von einer anderen Instanz mitbenutzt werden. Natürlich kann man auch Instanzen/Komponenten verschachteln und Daten rumreichen, das würde aber hier wieder den Rahmen sprengen. Es gibt mit <a href="https://vuex.vuejs.org/" target="_blank">Vuex</a> auch eine State Management Library für komplexere Anwendungen, das aber nur am Rande.

## Weiterführende Infos und Features

Vue bietet noch viele Features, die hier nur ganz kurz oder gar nicht erwähnt wurden. Ein paar picke ich hier extra nochmal raus. Als Dokumentation gibt ansonsten z.B. den <a href="https://vuejs.org/v2/guide/installation.html" target="_blank">Guide</a> (beschreibt die Features und erklärt, wie man etwas macht) und die <a href="https://vuejs.org/v2/api/" target="_blank">API Referenz</a> (welche alle möglichen Optionen, Properties, etc. auflistet).

### v-if / v-show

Mit `v-if` oder `v-show` kann man dynamisch Blöcke verstecken oder anzeigen, ähnlich unserem `bx:if`. So können z.B. Abschnitte in Formularen zugeschalten werden, wenn eine bestimmte Checkbox angehakt wird. Zu den Unterschieden von if und show siehe <a href="https://vuejs.org/v2/guide/conditional.html#v-if-vs-v-show" target="_blank">die Doku</a>.

Beispiel (`ok` wäre dann z.B. ein Boolean in den Daten):

```xml
<h1 v-if="ok">Yes</h1>
<h1 v-show="ok">Hello!</h1>
```

### v-on mit Modifiern

Beim Event-Binden kann man noch bestimmte Modifier setzen. Das reduziert Boilerplate-Code, wenn man z.B. nur an Rechtsklicks oder Enter-Tasten interessiert ist und/oder man das Event preventen will. Ein paar Beispiele aus der Doku:

```xml
<!-- prevent default -->
<button @click.prevent="doThis"></button>
<!-- prevent default without expression -->
<form @submit.prevent></form>
<!-- key modifier using keyAlias -->
<input @keyup.enter="onEnter">
<!-- the click event will be triggered at most once -->
<button @click.once="doThis"></button>
```

### Filter

Ausgaben im Template oder mit v-bind können mittels Filtern angepasst werden. Denkbar ist z.B. eine schicke Preisformatierung mit zwei Nachkommastellen oder das Großschreiben des ersten Buchstabens einer Meldung:

```xml
{{ message | capitalize }}
```

### Components

Man kann nachnutzbare Komponenten definieren. Ein einfacher Anwendungsfall ist z.B. ein Listenelement. Hat man z.B. eine Kontaktliste, so kann man für den einzelnen Kontakt-Eintrag eine extra Komponente definieren. Das hilft beim Organisieren von größeren Projekten und ist vergleichbar mit Textbausteinen. Jede Komponente bekommt dabei ihre eigene Vue-Instanz, das sieht man z.B. hier in einem <a href="https://vuejs.org/v2/guide/components.html#Reusing-Components" target="_blank">Beispiel</a>.

Apropos Components: Es gibt sehr viele <a href="https://github.com/vuejs/awesome-vue#awesome-vuejs-" target="_blank">vorgefertigte Komponenten</a> für Vue! Das reicht von Datepickern und Kalendern bis hin zu <a href="https://bootstrap-vue.js.org/docs/components/progress" target="_blank">Bootstrap-Komponenten</a>.

**Weitere Links:**

<a href="https://vuejs.org/" target="_blank">https://vuejs.org/</a> - offizielle Website

<a href="https://entwickler.de/online/javascript/vue-js-javascript-framwork-einfuehrung-579850224.html" target="_blank">https://entwickler.de/online/javascript/vue-js-javascript-framwork-einfuehrung-579850224.html</a> - Einführung auf Deutsch