CMS Handbuch – Entwickler
Technische Referenz und Entwicklerdokumentation für das batix® CMS
- Einführung & Grundlagen
- Batix-Tags Referenz
- Batix-Tags Referenz
- bx:access
- bx:admincomment
- bx:barcode
- bx:bild
- bx:browse
- bx:calendarfield
- bx:calendarloop
- bx:choice
- bx:clipboard
- bx:cmpageinclude
- bx:contact
- bx:containerdata
- bx:containerfilter
- bx:containerkat
- bx:containerloop
- bx:containersearch
- bx:cookie
- bx:datum
- bx:designloop
- bx:dezimal
- bx:directorylisting
- bx:document
- bx:documentlist
- bx:editbutton
- bx:email
- bx:evaluate
- bx:frame
- bx:gif
- bx:groovy
- bx:head
- Bx:i18n
- bx:if
- bx:ignore
- bx:include
- bx:internlink
- bx:javainclude
- bx:json
- bx:jspinclude
- bx:link
- bx:login
- bx:loop
- bx:mapping
- bx:math
- bx:navdata
- bx:navigation
- bx:navlink
- bx:news
- bx:option
- bx:optional
- bx:pagedata
- bx:pageinclude
- bx:paypal
- bx:plugin
- bx:record
- bx:recordchoice
- bx:recorddata
- bx:recordfield
- bx:relativelink
- bx:scanner
- bx:schleife
- bx:search
- bx:secureform
- bx:sessiondata
- bx:sitemap
- bx:statistik
- bx:submenu
- bx:submenulist
- bx:systemdata
- bx:tablechoice
- bx:tabledata
- bx:tablefield
- bx:tablefilter
- bx:tablekat
- bx:tableloop
- bx:tablerecord
- bx:tablesqlfilter
- bx:text
- bx:textarea
- bx:titel
- bx:tools
- bx:userdata
- bx:userrecord
- bx:validation
- bx:websearch
- bx:xml
- Actions
- Actions – Übersicht
- Batix Quelltext ausführen
- Benutzergruppe anlegen
- Bild hochladen
- Captcha Abfrage
- CMS-Seite versenden
- Container-Filteraction
- Container kopieren
- Containerdaten aus Email importieren
- Containerdaten speichern
- Containerdatensatz löschen
- Containerinhalt validieren
- Dokument hochladen
- Excel-Action
- Formular als Mail versenden
- Formulardaten validieren
- Intranet Login
- Intranet Logout
- Intranet-User anlegen/ändern
- JSP-Baustein ausführen
- Newsletter – Abo abmelden
- Newsletter – Abo ändern
- Newsletter – Abonnentenlogin
- Newsletter aktivieren
- Newsletter – Newsletter abonnieren
- Newsletter – Passwort vergessen (1)
- Newsletter – Passwort vergessen (2)
- Passwort des angemeldeten Users ändern
- Shop – Bestellung versenden
- Shop – Hinzufügen zu Warenkorb
- Shop – Löschen im Warenkorb
- Shop – Zusatzgebühr zum Warenkorb
- Sicheres Formular überprüfen (SecureformAction)
- Suche im Web
- Validierungsergebnis ausgeben
- Vorhandene Bedingung abfragen
- Weiterleitung
- Wert in Session speichern
- XHTML 2 PDF
- Ressourcen & Plugins
- Snippets & Rezepte
- Action-Parameter anlegen
- Blättern (Pagination)
- CSS-Menü
- CSV-Import in Container
- Eingeloggt bleiben
- Formularversand mit Ajax
- Google-Sitemap Datei erzeugen
- HTML-Mails für MS-Outlook
- Kalender bauen
- Locale bei Date-Pattern hinzufügen
- Manipulationsgeschützte Formulare mit Secureform
- Menü mit CSS
- Passwort vergessen
- Records – Hilfsklasse für einfaches Filtern
- Regelmäßiges Neuladen von DIVs
- Sitemap bauen
- Support für „not" hinzufügen
- Validation
- Websuche
- Encodings
- Groovy
- API
- Bibliothek – Übersicht
- CMS-spezifische Helfer
- Groovy Syntax und Beispiele
- Groovy – Übersicht
- Logging
- Timings
- Tips
- Verwendungsmöglichkeiten
- Werkzeuge & Integrationen
Einführung & Grundlagen
Konzepte, Tag-Grundlagen, Filter, Datums-Patterns, Redakteurs-Tags.
Filter
Um mittels Code einfacher zu filtern, gibt es die Hilfsklasse Records (siehe Beschreibung).
Filter können z.B. in Zusammenhang mit bx:containerfilter oder Container-Filteraction verwendet werden, um bestimmte Datensätze anzuzeigen.
Aufbau eines Filters
Filter werden in XML angegeben. Der grundlegende Aufbau ist folgender:
<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:
<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.
<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: 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 (Wörter durch Leerzeichen oder Kommas trennen, findet auch Teilstrings) |
|
| 8 | ist eines der Wörter von (Wörter durch Leerzeichen oder Kommas trennen, nur ganze Wörter) |
|
| 9 | enthält alle Wörter (Wörter durch Leerzeichen oder Kommas trennen) |
|
| 11 - 19 | leer ODER Bedingung Bedingung auch erfüllen, falls Feld leer ist (außer für type 5) z.B.: type 14 für "ist gleich oder leer" |
|
| 21 - 29 | NICHT-Bedingung kehrt die Bedingung um (außer für type 5) z.B.: type 23 für "endet nicht mit" |
|
| 31 - 39 | leer ODER NICHT-Bedingung Kombination von 11 - 19 und 21 - 29 z.B.: type 32 für "beginnt nicht mit oder ist leer" |
|
| 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 | Feld ist größer (später) |
| 2 | Feld ist kleiner (früher) | |
| 3 | Feld ist gleich | |
| 4 | Feld ist ungleich | |
| 11 | Feld ist größer/gleich | |
| 12 | Feld ist kleiner/gleich | |
| 21 | Feld ist leer oder größer/gleich | |
| 22 | Feld ist leer oder kleiner/gleich | |
| 6 | Feld ist in Stunde (0-23) | |
| 7 | Feld ist in Minute (0-59) | |
| 8 | Feld ist in Sekunde (0-59) | |
| 5 | Feld ist leer (Feld soll leer sein: static-value: 1, Feld soll nicht leer sein: static-value: 0) | |
| 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 Bei mehreren IDs, Filter mehrmals verwenden. |
|
| 9 | Datenlisten-ID ist gleich (nur bei alten Containern) | |
| 12 | enthält eine der Datensatz-IDs von (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 | enthält Datensatz-ID nicht (ab v2.6.2) | |
| 12 | enthält eine der Datensatz-IDs von (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.
<request-value>Request-Parameter-Name</request-value>
request-attribute
Der Vergleich findet mit dem Wert eines Request-Attributes statt.
<request-attribute>Request-Attribut-Name</request-attribute>
session-attribute
Ein Session-Attribut wird mit dem Feld verglichen.
<session-attribute>Session-Attribut-Name</session-attribute>
static-value
Der Wert zum Vergleichen wird direkt übergeben.
<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).<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).<special-value [days="n"] [hours="n"] [minutes="n"]>NOW</special-value> |
| USERID | Es wird mit der UserID des aktuellen (eingeloggten) Betrachters verglichen.<special-value>USERID</special-value> |
| SESSIONID | Die aktuelle SessionID wird abgeglichen.<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).<special-value>USERGROUPS</special-value> |
| PARENTCONTAINER | Es wird mit der ID des übergeordneten Containers verglichen.<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 "Systemeinstellungen" angelegt und gespeichert.
order
Hier wird ein Sortierfeld definiert.
<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
<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 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.
<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
<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
<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
<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)
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:
- 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
| Pattern | Entsprechung |
|---|---|
| d | Tages im Monat ohne vorangestellter 0 bei einstelligen Zahlen (z.B. 5.12.2013) |
| dd | Tages im Monat mitvorangestellter = (z.B. 05.12.2013) |
| M | Monatsangabe ohne vorangestellter 0 bei einstelligen Zahlen (z.B. 12.5.2016) |
| MM | Monatsangabe mit vorangestellter 0 (z.B. 12.05.2016) |
| MMM | Monatsangebe als Text (z.B. 12.Mai.2016) |
| yy | Zahresangabe zweistellig (z.B. 12.05.16), führt evtl. zu Missverständnissen (2016 oder 1916?) |
| yyyy | Jahresangabe vierstellig (z.B. 12.05.2016) |
| 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. 3:40 Uhr) |
| HH | Ausgabe der Stunde ab 0 Uhr mit vorangestellter 0 (z.B. 03:40 Uhr) |
| mm | augabe der minuten (z.B. 03:40 Uhr) |
| ss | Ausgabe der Sekunden (z.B. 03:23:34 Uhr) |
Weitere Infos und Ausgabemöglichkeiten auf der offiziellen JavaDoc-Seite
Beispiele
<bx:tools.datum pattern="dd.MM.yyyy HH:mm:ss"/>
Ausgabe eines Zeitstempels, z.B. 13.03.2016 13:48:33
Angebote im Monat <bx:recordfield.Datum pattern="MMM"/>
Ausgabe des Monatsnamen
Redakteurs-Tags
Titel
<bx:tag.{titel} />
Alle Unterstriche / Underscores ( _ ) im {titel} Platzhalter werden in der Verwaltung durch Leerzeichen ersetzt. Zum Beispiel wird dann aus
<bx:text.Haupt_Titel />
dieses Feld in der Verwaltung:
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.
Es ist darauf zu achten, nur gleichartige Tags mit dem selben {titel} zu versehen. So machen z.B. <bx:text.Titel /> und <bx:bild.Titel /> im selben Menüpunkt keinen Sinn.
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:
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
<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
<bx:text.Titel comment="Dies ist der große Titel direkt unter dem Headerbild." />
Admin-Mode
<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
<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
<bx:tagname.Titel admin-title="{anderer Titel}" />
In Verwaltung wird ein anderer Titel ausgeben als der beim Tag angegebene.
Beispiele
<bx:bild.picture admin-title="Großes Logo"/>
genauere Bezeichnung des "picture"
<bx:textarea.Haedline admin-title="Headline"/>
im Nachhinein einen Schreibfehler zu korrigieren, wenn das Design schon oft in Gebrauch ist
Batix-Tags Referenz
Vollständige Referenz aller bx: Tags, alphabetisch.
Batix-Tags Referenz
Hinweis für (fast) alle Tags: für Parameterwerte können auch Präfix-Variablen eingesetzt werden.
Syntax-Konventionen
<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:
<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):
<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
<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
<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.
<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.
<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
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
<bx:barcode.qr width="250" height="250" [type="path"] [rotate="90"]> Inhalt </bx:barcode.qr>
Parameter für alle Typen
| width und height | Geben die Größe des Barcodes an. 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. path: es wird nur der Pfad zum Bild ab "/" zurückgegeben (ohne Host, falls Haupthost-Haken im Projekt nicht gesetzt wurde). 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). Die Größe des erzeugten Bildes wird neu berechnet, um den rotierten Barcode unterzubringen (Hintergrund ggf. transparent). |
Es ist generell empfehlenswert einen minimalen Kontrast-Rand (z.B. in weiß) zu setzen, damit Barcodeleser den Code einfacher identifizieren können.
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.
Typ-spezifische Informationen
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!
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).
Typ |
Ausgabe |
Einschränkungen |
|---|---|---|
<bx:barcode.codabar> |
Beginnt und endet mit einem Guard-Zeichen aus: ABCD.ODER beginnt und endet mit einem Guard-Zeichen aus: TN*E.Falls keine Guards gesetzt sind, wird automatisch A genommen.Enthält nur Zeichen aus: 0123456789-$:/.+ |
|
<bx:barcode.code_39> |
maximal 80 Zeichen aus: 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. *$/+% |
|
<bx:barcode.code_93> |
maximal 80 Zeichen aus: 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%abcd* |
|
<bx:barcode.code_128> |
maximal 80 Zeichen | |
<bx:barcode.itf>(Interleaved Two of Five) |
Weniger als 80 Ziffern, gerade Anzahl Am besten 6, 10, 12, 14, 16, 24, oder 44 Ziffern |
|
<bx:barcode.ean_8> |
genau 8 Ziffern | |
<bx:barcode.ean_13> |
genau 13 Ziffern Prüfziffer muss stimmen |
|
<bx:barcode.upc_a> |
genau 11 Ziffern (ohne Prüfziffer, wird automatisch berechnet) ODER genau 12 Ziffern (mit Prüfziffer) |
|
<bx:barcode.upc_e> |
genau 8 Ziffern |
2-Dimensionale Codes
<bx:barcode.qr>
Ausgabe
"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.
<bx:barcode.datamatrix>
Ausgabe
"http:/batix.de" (rechts mit shape=square)
"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)
<bx:barcode.aztec>
Ausgabe
"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.
<bx:barcode.pdf_417>
Ausgabe
"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
<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 ausgegeben werden.
Beispiele
<bx:barcode.qr>Hallo</bx:barcode.qr>
<bx:barcode.datamatrix shape="rectangle">Hallo</bx:barcode.datamatrix>
bx:bild
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
<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
<bx:bild.Seitenbild width="700" height="150" alt="Seitenbild dieser Seite" />
Anzeige mit Kommentar in der Verwaltung
<bx:bild.Seitenbild width="200" height="300" align="right" comment="nichts ausgewählt: Text zieht sich über die gesamte Breite" />
Ausgabeart festlegen
<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
<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
<bx:bild.{titel} [hspace="{n}"] [vspace="{n}"] [kategorie="{kat}"] [force] [nogifshrink] [border="{n}"] [noborder] />
| 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.
<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"
calendarfield.if
<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
...
<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"
calendarfield.day
<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
<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
<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
<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
<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
<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 (www.obtineo.de). |
bx:calendarloop
Das Tag calendarloop benötigt man zur Erzeugung eines Kalenders mit Container-Anbindung. Siehe auch Kalender bauen
<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 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 (www.obtineo.de). |
bx:choice
Das Tag choice zeigt seinen Inhalt abhängig vom aktuellen Hauptmenüpunkt an (z.B. für mehrsprachige Templates).
<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
<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
<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
<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
<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
<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
<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
<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
<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 Bx:include. 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.
<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
<div id="teaser">
<bx:schleife.Teaser list="Titel">
<!-- <bx:text.Titel/> -->
<bx:cmpageinclude.Teaser_auswaehlen navid="14304C19DD0"/>
</bx:schleife.Teaser>
</div>
bx:contact
<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
<bx:containerdata.id />
Diese Funktion gibt die ID des Datensatzes aus.
Titel
<bx:containerdata.titel />
Es wird der Titel des Datensatzes angezeigt.
ID = Request-Parameter
<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 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)
<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. 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 |
| 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 |
| 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
<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".
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
<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
<bx:containerfilter.Mitglieder pool="Mitglieder" sql>
<bx:recordfield.Name/><br>
</bx:containerfilter.Mitglieder>
zugehöriger Filter
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
<bx:containerfilter.Mitglieder pool="Mitglieder" sql evalbx>
<bx:recordfield.Name/><br>
</bx:containerfilter.Mitglieder>
zugehöriger Filter
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
<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
<bx:containerfilter.Name orderby="Kategorie/Titel;-Preisgruppe/Nummer">
Dreimal anders und doch das Gleiche
zugehöriger Filter
<bx:containerloop orderby="-Datum,+Titel">
<bx:containerloop orderby="-Datum,Titel" [asc]>
<bx:containerloop orderby="Datum,+Titel" desc>
noch ein Beispiel
zugehöriger Filter
<bx:containerloop orderby="-Jahr -Monat -Tag"> ist das gleiche wie
<bx:containerloop orderby="Jahr Monat Tag" desc>
mehrere Elemente (dynamische Angaben im Request)
<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
<bx:containerfilter.aktuelleAngebote pool="Artikel" force="list" maxparam="max" orderbyparam="titel" directionparam="direction" indexparam="index">
<bx:recordfield.Titel/> <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.
<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)
<bx:containerfilter.{titel} pool="(ContainerID | Containername)" force="single" idfield="{param}" [dummy]>
Inhalt
</bx:containerfilter.{titel}>
| {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
<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: Elster
ein zufälliges Element
<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
<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
<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
<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
<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") |
| type | Art des Vergleiches (siehe auch "Filter") |
| value | gesuchter Wert (siehe auch "Filter") statisch: einfach gesuchten Wert angeben (z.B. eine ID) dynamisch: mit Präfix (siehe auch "Präfixe") |
| 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
<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
<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
<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
<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.
<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
<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".
<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
<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: Erzwinge Einzelanzeige eines Zufallsdatensatzes choice: Erzwinge Listenanzeige einer im Request übergebenen Auswahl von Datensätzen, braucht idfield=... (oder der Requestparameter heißt recordid) |
Beispiele
Containeranzeige: Listen- und Detailseite
Listenseite
<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
<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
<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
<bx:containerloop orderby="Kategorie/Titel;-Preisgruppe/Nummer">
ein zufälliges Element
<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
<bx:tag.feature param="value" />
ein bestimmtes Element
<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
<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 eine Anzahl an Elementen
Verweise auf diese Seite:
bx:recorddata bx:tableloop bx:tableloop bx:recorddata
(4 Verweise)
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.
<!-- 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
<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
<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
<bx:containersearch.rank/>
Innerhalb der obigen Schleife gibt dieses Tag den Rang des aktuellen Suchergebnisses zurück.
containersearch.relevanz
<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
<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
<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
<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
<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
<bx:cookie name="sprache" not >
<bx:cookie.cut name="sprache">de</bx:cookie.cut>
</bx:cookie>
Keine Verweise gefunden.
Suchbegriffe
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.
<bx:datum.{titel} [size="{n}"] [maxlength="{n}"] />
size - Feldgröße in der Administration
maxlength - maximale Eingabelänge des Feldes in der Administration

bx:designloop
Das Tag designloop erzeugt eine Schleife von sortierbaren Designbausteinen.
Früher mit Tabellen-Layout und alten Containern war das so gedacht
<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:
<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 |
Zu beachten: 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. |
<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
<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
<bx:schleife.Inhalte admin-mode="config">
<a href="#<bx:loop.id/>"><bx:text.MenuTitel/></a>
</bx:schleife.Inhalte>
eigentliche Schleife
<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.
<bx:dezimal.{bezeichner} [size="{n}"] [maxlength="{n}"] [nachkomma="{n}"] [minnachkomma="{n}"] [maxnachkomma="{n}"] [noformat] />
| Parameter für Anzeige in der Verwaltung | Parameter für Anzeige im Frontend | ||
|---|---|---|---|
| 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
<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
bx:directorylisting
<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
<bx:directorylisting.isfile> Inhalt </bx:directorylisting.isfile>
Der Inhalt wird nur ausgegeben, wenn das aktuelle Element eine Datei ist.
directorylisting.isfolder
<bx:directorylisting.isfolder> Inhalt </bx:directorylisting.isfolder>
Der Inhalt wird nur ausgegeben, wenn das aktuelle Element ein Verzeichnis ist.
directorylisting.isparent
<bx:directorylisting.isparent> Inhalt </bx:directorylisting.isparent>
Der Inhalt wird nur ausgegeben, wenn das aktuelle Element das übergeordnete Verzeichnis ("..") ist.
directorylisting.link
<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
<bx:directorylisting.filename/>
Falls das Element eine Datei ist, wird der Dateiname ausgegeben.
directorylisting.filesize
<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
<bx:directorylisting.filedata [pattern="<format>"] />
Falls das Element eine Datei ist, wird das Uploaddatum ausgegeben.
| pattern | Ausgabeformat, Standard ist: "dd.MM.yyyy". |
|---|
directorylisting.titel
<bx:directorylisting.titel />
Falls das Element eine Datei ist, wird der Dateiname ausgegeben.
directorylisting.description
<bx:directorylisting.description />
Falls das Element eine Date ist, wird die Beschreibung ausgegeben.
directorylisting.previous
<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
<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
Dieses Tag kann sich in der Verwaltung darstellen.
<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
Bewerbungsunterlagen als PDF: <bx:document.Bewerbungsunterlagen/>
Ausgabe innerhalb eines a-Tags
<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
<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
<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
<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
<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
<bx:documentlist.id />
Dieser Befehl gibt die ID des Eintrags aus.
documentlist.link
<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
<bx:documentlist.filename />
Der Dateiname aus dem System wird ausgegeben.
documenlist.filesize
<bx:documentlist.filesize [unit="b | k | m"] />
Die Dateigröße wird ausgegeben.
| unit | Größeneinheit ( Byte (b), Kilobyte (k), Megabyte (m) ) |
|---|
documentlist.filedate
<bx:documentlist.filedate [pattern="<format>"] />
Gibt das Uploaddatum der Datei aus.
| pattern | Anzeigeformat (Standard: "dd.MM.yyyy") |
|---|
documentlist.titel
<bx:documentlist.titel />
Der Download-Dateiname wird geschrieben.
documentlist.description
<bx:documentlist.description />
Die Beschreibung der Datei wird ausgegeben.
documentlist.previous
<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
<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
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.
<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, wenn der Benutzer Schreibzugriff (= Recht zum Speichern der Seite) auf den aktuellen Navigationspunkt hat.
| 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 Schleifendurchlaufsinnerhalb 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
``
<bx:editbutton label="✐">
schreibt ein ✐ als Buttontext
<bx:containerloop pool="Galerien">
...
<bx:editbutton[.link] type="container" sub="BilderListe" label="neues Bild" />
</bx:containerloop>
Link in statischer Mail:
http://www.meine-domain.de/verwaltung/?client=12E2D639293&table=12EE71ADC48&record=[[recordid]]
Anmeldeformular im Frontend (Anmeldung bei Verwaltung wird vermieden)
Folgendes Input-Feld muß ins Anmeldeformular:
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.
<bx:email.{bezeichner} [size="{n}"] />
| bezeichner | Name des Feldes in der Verwaltung |
|---|---|
| size | Größe des Eingabefeldes in der Verwaltung |
| . |
Beispiele
<bx:email.Email size="<n>"] />
Wir in der Verwaltung in das Feld "Email" "test@batix.com" eingegeben, wird das zu: test@batix.com im Quelltext und auf der Website wird eine verlinkte Email-Adresse ausgegeben.
bx:evaluate
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.
<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
<bx:evaluate><bx:recordfield.QuellcodeSnippet type="plain" /></bx:evaluate>
Darauf achten, dass Benutzer keine willkürlichen Quelltexte in dem Containerfeld speichern können!
Ein Tag wird im Request übergeben: `test.htm?datum=Batix-Code im Request (nicht empfohlen)
<bx:evaluate><bx:pagedata.request name="datum" /></bx:evaluate>
Dies ist gefährlich, da der Benutzer im Normalfall den Request-Parameter beliebig manipulieren und somit sämtlichen Batix-Code ausführen kann!
bx:frame
Das Tag frame stellt Funktionen für Framesets zur Verfügung.
<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
<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 http://IhreAdresse.de/www/webname/ 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.
<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
<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
<bx:groovy>
println("Hello, World")
</bx:groovy>
Include und Code
<bx:groovy includes="MyLib">
MyLib.doStuff()
</bx:groovy>
Nur Include
<bx:groovy includes="MyLib,OtherLib" />
Parameter übergeben und auslesen
<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
<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:
Verwendungsmöglichkeiten Verwendungsmöglichkeiten
(2 Verweise)
bx:head
Der Befehl head schreibt diverse Angaben zum Projekt in den Headbereich.
head.style
<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
<bx:head.setstatus code="statuscode"/>
Setzt den Status-Code der Seite (normalerweise "200")
head.setheader
<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
<bx:head.setheader name="Cache-Control" value="no-cache"/>
Angabe, daß die Seite nicht gecacht werden soll.
<bx:head.setheader name="Expires" type="date"><bx:tools.datum day="+7"/></bx:head.setheader>
head.cancelpage
<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
<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.
<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.
<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
<bx:head.localblock/>
Schreibt die Angaben vom Feld "Include im Head" beim Projekt an die angegebene Stelle, anstatt direkt vor </head>.
head.metatags
<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)
Bx:i18n
Das Tag i18n ist zur Unterscheidung von Text in unterschiedlichen Sprachen.
<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.
<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
<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
- ) soll ausgegeben werden, wenn mindestens ein Ansprechpartner verknüpft ist (ist die Ebene 1)
if.else
<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:
<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
<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
<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
<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
<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
<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.
<bx:ignore> nicht auszuwertender Bereich </bx:ignore>
Bei einem auskommentierten Bereich im HTML-Code (mit ) 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 bx:cmpageinclude oder bx:jspinclude.
<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.
<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
<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
...
<bx:javainclude modul="Baustein-Name" maxdays="14"><div>neu!</div></bx:javainclude>
...
Quelltext des JSP-Bausteins
<%@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
<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).
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:
<bx:clipboard.cut name="json_data"><bx:jspinclude>/intern/api.json</bx:jspinclude></bx:clipboard.cut>
<bx:json data="clipboard:json_data">
...
</bx:json>
Der JSON-Parser akzeptiert auch nicht RFC-konformeres JSON, also z.B. Kommentare oder Keys, die nicht mit Anführungszeichen umgeben sind (Details siehe hier).
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.).
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 }
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:
<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:
<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.
<!-- 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>
<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).
<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.
<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 (siehe Java-Docs für mögliche Werte).
<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). |
<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-Patterns unterstützt:
<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:
<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:
<bx:json.mydate date pattern="dd.MM. HH:mm" />
Werden z.B. Tages- oder Monatsnamen ausgegeben, wird über locale die gewünschte Sprache eingestellt:
<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):
<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 dentrueund/oderfalseParametern genutzt werden. Beispiele:
<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 für andere Encoding-Möglichkeiten).
<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. |
<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).
<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).
<bx:json.Liste [index="20"] [max="10"]>
<bx:json />
</bx:json.Liste>
Es können die meißten Funktionen von bx:recorddata verwendet werden:
<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:
<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 entsprechende Passage bei bx:recorddata.
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.
<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.
<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).
<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 GitHub Seite 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:
<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.
<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". |
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.
Beispiele
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>
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
<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
<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
<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
<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
<bx:link recordfield="{param}" [href="{url}"]> Inhalt </bx:link>
Dieses Tag steht innerhalb von bx:record und erzeugt einen Link aufurlbzw 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.
<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 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.
<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.
Die folgenden Tags werden weiterhin in [bx:schleife](/books/cms-handbuch-entwickler/page/bx-schleife) genutzt
loop.count (ab v2.6.6. deprecated) --> neu: loop.index
<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)
<bx:loop.index[add="{anzahl}"] />
Ist jetzt besser benannt. loop.count geht noch wegen Kompatibilität)
loop.id
<bx:loop.id />
Diese Funktion gibt die ID des aktuellen Datensatzes zurück.
loop.if
<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
<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
<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. <bx:loop.cols num="3" equals="1"> Inhalt </bx:loop.cols> spricht die zweite Spalte an.
num gibt die Spaltenanzahl und equals die gesuchte Spalte an. not kehrt die Bedingung um.
loop.previous / loop.next
Nur auf Detailseiten möglich!
<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
Nur auf Detailseiten möglich!
<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).
<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)
<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)
<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
<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
<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
<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
...
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.
<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")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 | |
| 5,5 | 6 |
| 2,5 | 3 |
| 1,6 | 2 |
| 1,1 | 2 |
| 1,0 | 1 |
| -1,0 | -1 |
| -1,1 | -2 |
| -1,6 | -2 |
| -2,5 | -3 |
| -5,5 | -6 |
Beispiele
<bx:math pattern="0.00">8*(-3+7)</bx:math>
gibt "32,00" aus
<bx:math pattern="#,##0.00"><bx:recordfield.Preis/>+<bx:recordfield.Versandkosten/></bx:math>
gibt einen Preis incl. Versandkosten aus
<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
<bx:math.debug pattern="">{Aufgabe}</bx:math.debug>
gibt nicht nur das Ergebnis aus, sondern die gesamte Formel
Beispiele
<bx:math.debug pattern="0.00">8*(-3+7)</bx:math.debug>
gibt "calc{8*(-3+7)}=32.0" aus
Rechnen mittels Datenbank
<bx:math.mysql pattern="...">{Aufgabe}</bx:math.mysql>
Rechenoperationen werden mittels einer SQL-Formel gemacht.
Beispiele
<bx:math.mysql pattern="0">POW(3,4)</bx:math.mysql>
gibt "81" aus ( 34 )
Vergleich von Zahlen
<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 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 verwendet werden |
Beispiele
<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
<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
<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
<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.
[<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.
<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
<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
<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.
<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
<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
<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
<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
<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
<bx:math.modifydate in-pattern="yyyyMMdd" month="+1" day="15" out-pattern="dd. MMMM yy">20110922</bx:math.modifydate>
gibt „15. Oktober 11“ aus
<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”
<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”
<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**”
<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”
<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.)
<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
<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.)
<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 angegeben |
|---|---|
| pattern | Eingangsformat (Standard ist "dd.MM.yyyy") |
| not | kehrt die Bedingung um |
Beispiele
<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
<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
<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
<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
navdata.id
<bx:navdata.id />
Die Id des Menüpunkts wird ausgegeben.
navdata.name
<bx:navdata.name [type="plain] />
Der Name des Menüpunkts wird ausgegeben. type="plain" z.B. für csv-Datei
navdata.dir
<bx:navdata.dir />
Der virtuelle Verzeichnisname des Menüpunkts wird ausgegeben.
navdata.path
<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
<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
<bx:navdata.target/>
Das eventuell beim Menüpunkt eingetragene Target wird ausgegeben.
navdata.meta
<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
<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.
<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.
<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
<bx:sitemap.2>
<a href="<bx:sitemap.path/>" <bx:navdata.robots nofollow>rel="nofollow"</bx:navdata.robots>> … </a>
</bx:sitemap.2>
navdata.visible
<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
<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
<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: |
(2 Verweise)
bx:navigation
Allgemeine Syntax
<bx:navigation.{level} [normal | protected | showcurrentinactive] [open]>Inhalt</bx:navigation.<level>>
| level | Navigationstiefe (beginnt mit 0 = Root-Ebene) um darunterliegende Menüpunkte anzuzeigen, werden bx:navigation-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
<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
<bx:navigation.path/>
Der virtuelle Pfad wird ohne "/www/webname/" und ohne "/" am Ende ausgegeben (siehe Beispiel oben).
navigation.dir
<bx:navigation.dir/>
Es wird nur der aktuelle Verzeichnisname ausgegeben.
navigation.name
<bx:navigation.name/>
Dieses Tag gibt den angezeigten Name des Menüpunktes aus.
navigation.target
<bx:navigation.target [default="{ziel}"] />
Das Zielframe wird ausgegeben.
| ziel | Standard-Zielframe, wenn im Menüpunkt kein Zielframe angegeben wurde |
|---|
navigation.id
<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
<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
<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
<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
<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>
Ausgabe: 1 | 2 | 3 | 4 - beim Hover auf die Zahlen erscheint der Menüpunktname. Der letzte Trennstrich wurde ausgeklammert.
navigation.meta
<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 benutzt werden.
bx:navlink
Innerhalb eines Navigations-Tags
<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
<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)
<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
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
<strong>Achtung:</strong> <bx:navlink path="/konfigtexte/"><bx:text.Warnhinweis/></bx:navlink>
bx:news
Momentan nur für alte Container
<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
<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
<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.)
Dieses Tag kann sich in der Verwaltung darstellen.
<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
<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
pagedata.parentnavid
<bx:pagedata.parentnavid/>
pagedata.webid
<bx:pagedata.webid/>
<bx:pagedata.customerid/> <!-- veraltet -->
Gibt die ID des Webs (Projekts) aus
pagedata.webdir
<bx:pagedata.webdir/>
<bx:pagedata.customerdir/> <!-- veraltet -->
gibt das virtuelle Verzeichnis des Webs aus.
pagedata.webhost
<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
<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
<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" -->
| level | Ebene des gewünschten Navigationspunktes Hauptmenüpunkt entspricht level="0", Untermenüpunkte liegen jeweils eine Ebene höher |
|---|---|
| is | vorgegebene ID |
| NOT | funktioniert hier nicht, bitte pagedata.nav verwenden |
pagedata.navpath
<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 next |
sucht den vorherigen bzw. nächsten Menüpunkt im gleichen Level |
|---|---|
| active inactive all |
nur aktive anzeigen (Standard) nur inactive anzeigen alle anzeigen |
Beispiele
<div style="float:left;width:100px;">
<a href="<bx:pagedata.navpath previous/>">« vorherige Seite</a>
</div>
<bx:pagedata.navname />
<div style="float:right;width:100px;text-align:right;">
<a href="<bx:pagedata.navpath/>">nächste Seite »</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
<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) Hauptmenüpunkt entspricht level="0", Untermenüpunkte liegen jeweils eine Ebene höher |
|---|
pagedata.nav
<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 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ö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.
<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 kann auch einen Platzhalter in der Form name="[platz]id"enthalten (siehe Beispiel) |
|---|---|
| encode | Codierung des Wertes, für JavaScript-Code (Sonderzeichen werden escaped) oder als URL (%nn) Hiermit kann der ausgegebene Text für verschiedene Formate kodiert werden: - 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) Das erspart ein bx:tools, was ansonsten um das bx:pagedata gepackt werden müsste. |
| boundary | Falls der Parameter mehrfach vorkommt (?para=wert1¶=wert2) wird ohne Angabe vonboundarynur der Erste ausgegeben, andernfalls wird der Wert von boundaryals Trennzeichen benutzt. |
| not empty |
Falls empty gesetzt ist, wird ein leerer Request-Parameter wie ein nicht vorhander behandelt.| | 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 | |
<bx:pagedata.request name="p">... |
leer |
<bx:pagedata.request name="p" not>... |
angezeigt |
<bx:pagedata.request name="p" empty>... |
leer |
<bx:pagedata.request name="p" not empty>... |
angezeigt |
| value | Text, den der Request-Parameter enthalten soll |
| true 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).ab v2.6.6: es kann auch abgefragt werden, ob der Parameter übergeben wurde oder nicht (siehe Beispiel) |
Beispiele
Fall 1 true/false
<bx:pagedata.request name=“test“ value=“3“ true=”ist drei” false=”ist nicht drei” />
Fall 2 true/false
<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
<bx:pagedata.request name=“test“ encode=”htmltext”/>
Eingabe: test.htm?test=erste+Zeile%0azweite+Zeile («%0a» ist ein Zeilenumbruch) → schreibt «erste Zeile
zweite Zeile» und damit sieht man einen Zeilenumbruch im Browser
pagedata.attribute
Beispiele
speichern.act?feld=[]/Name[containerID]&containerID=12345
Bissl weit hergeholtes Beispiel: ... ich hab keine Ahnung!
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 beinot) |
pagedata.setattribute
<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
<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 beinot) |
pagedata.setscriptattribute
<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
<bx:pagedata.listrequest/>
alle Request-Parameter werden als 'hidden' Formularfeld in die Seite geschrieben
pagedata.querystring
<bx:pagedata.querystring [original]/>
QueryString ausgeben
Ein '?' am Anfang ist in der Ausgabe nicht enthalten. GePOSTete Parameter sind nicht enthalten! Falls dieses Tag im HTML-Quelltext (z.b. für Links) verwendet wird, muss die Ausgabe noch durch bx:tool.urlencode umgewandelt werden.
| original | es wird der ursprüngliche QueryString ausgegeben (bei forwards) |
|---|
pagedata.meta
<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 beinot) |
pagedata.cookie
<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 beinot) |
pagedata.hostname
<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 https://) des aktuellen Seitenaufrufs aus |
Beispiele
Wenn man im Web von batix. com folgende Tags einbindet:
<bx:pagedata.hostname/>
wir ausgegeben: www.batix.com
<bx:pagedata.hostname addscheme/>
wird ausgegeben: http://www.batix.com (ab v2.5.8)
<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
<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
<bx:pagedata.sessionurl/>
Session-URL-Komponente (;jsessionid=) ausgeben, falls Cookies ausgeschaltet sind
pagedata.url
<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
<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
<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
<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
<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
<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
<bx:pagedata.scheme/>
Gibt das Protokoll zurück. ("http" oder "https") (ab* v2.5.8*)
pagedata.compressed
<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
<bx:pagedata.status type="{dev | prod | debug}"> ... </bx:pagedata.status>
Zeigt abhängig vom Projektstatus den Taginhalt an (ab* v2.6.2*).
Beispiele
<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
<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
<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
<bx:pagedata.header name="..." (value|matches|contains)="[Vergleichswert]" [not]>
Beispiele
<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:
- Container-Filteraction
- bx:tools
- bx:tools
- Support für not hinzufügen
- Google-Sitemap Datei erzeugen
- Container-Filteraction
- Google-Sitemap Datei erzeugen
- Support für not hinzufügen
(8 Verweise)
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.
<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
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:
<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: https://www.paypalobjects.com/de_DE/html/IntegrationCenter/ic_button-encryption.html (Schritt 2 und 3 muß der Kunde mit seinem Paypal-Zugang durchführen) siehe auch: https://cms.paypal.com/us/cgi-bin/?cmd=_render-content&content_ID=developer/e_howto_html_encryptedwebpayments
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:
<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
<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
<bx:plugin.css/>
Es werden die nötigen Styles in den Head geschrieben, die der Pluginseite ihr Aussehen geben. und zwar:
<link rel="STYLESHEET" href="/verwaltung/style.css" type="text/css">
<link rel="STYLESHEET" href="/verwaltung/control/css.jsp" type="text/css">
plugin:headline
<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
<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
<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
<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 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 Falls |
| sub | bestimmer Untercontainer kann als Basis für die Datensätze festgelegt werden (gilt für alte Container) |
| 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
<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 in der Verwaltung entsprechend des Filters ein.
| name | Name des zu überprüfenden Feldes (siehe auch " Filter ") |
|---|---|
| type | Art des Vergleiches (siehe auch " Filter ") |
| value | gesuchter Wert (siehe auch " Filter ") statisch : einfach gesuchten Wert angeben (z.B. eine ID) dynamisch : mit Präfix (siehe auch " Präfixe ") |
Beispiel
<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
<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
<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
<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
<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
<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
<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
<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>> <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
<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
<bx:recordchoice.if (empty | unknown) [not]> Inhalt </bx:recordchoice.if>
Dieses Tag gibt seinen Inhalt nur bei bestimmten Bedingungen aus.
| empty 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
<bx:recordchoice.poolid/>
Die unter pool (im umgebenden Tag) angegebene ID wird ausgegeben.
recordchoice.loop
<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 Bx:recorddata oder Bx:recordfield auf Daten zugegriffen werden. Hinweis: Es empfiehlt sich bx:recordchoice.loop durch z.B. Bx:containerloop oder Bx:containerfilter 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.
<bx:recordchoice.if [not] current value="<text>" />
<bx:recordchoice.if [not] current> Inhalt </bx:recordchoice.if>
| current | |
|---|---|
| value | Der Inhalt bzw. der Text vonvaluewird nur ausgegeben, wenn das Schleifenelement aktuell zugewiesen ist bzw. nicht ist ( not). |
Beispiele
Einzelverknüpfung
<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
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 oder bx:containerfilter) aus oder steuert die Ausgabe von Daten in verschiedenen Abhängigkeiten.
recorddata.id
<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, wobei "0" die äußerste Containerliste ist und alle weiteren inneren Containerlisten jeweils um 1 erhöht werden (0,1,2,...). |
|---|---|
| parent parent=... |
hat die selbe Wirkung wielevel, nur dass hier von der aktuellen Containerliste mit "0" ausgegangen wird und für jede weiter übergeordnete Containerliste 1 addiert wird (...,2,1,0). parentist identisch mit parent="1". |
| baseloop | übergeordneten Containerliste direkt mit Namen ansprechen, vorausgesetzt, es wurde auch ein Name vergeben (siehe Bx:containerloop und Bx:containerfilter ). |
| filter dynamicfilter |
es kann ein JSP-Baustein als Filter angegeben werden |
| quiet | Fehlermeldungen des Filters wird unterdrückt |
recorddata.creationdate
<bx:recorddata.creationdate [pattern=""] [locale=""] />
Wandelt die ID in Datum um.
| pattern | Ausgabe-Pattern, Standard: dd.MM.yyyy |
|---|---|
| locale | Sprachausgabe, Standard: de |
recorddata.containerid
<bx:recorddata.containerid />
Gibt die Container-ID aus (ab Version 2.6.2).
recorddata.titel
<bx:recorddata.titel />
Gibt den Titel des aktuellen Datensatzes einer Containerliste aus. Der Titel ist der Selbe, der auch in der Containerdefinition als Anzeigeelement angegeben wurde.
recorddata.if
<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{name}kann auch einen Platzhalter in der Form request="[platz]"enthalten. In diesem Fall wird [platz]durch den Wert des Requestparameters platzersetzt. |
| baseloop | Angabe |
| id | Angabe der gesuchten IDs (mit Komma oder Leerzeichen getrennt), entweder direkt oder mit einem Präfix Abfrage, ob Dummy-Datensatz: id=""ab V2.5.9: Abfrage dummy mit #null |
| not | kehrt die Bedingung um |
| true | false | Im Tag ohne Inhalt wird der Wert vontruebei Übereinstimmung ausgegeben, sonst der Wert von false. |
Beispiele
<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.
<bx:containerfilter.Mitglieder pool="Mitglieder" force="list">
<bx:recorddata.if request="[platz]">......<bx:recorddata.if>
</bx:containerfilter.Mitglieder>
Browseraufruf: http://www.musterseiten.de/menuepunkt1/?platz=id2&id1=xxxxxxx&id2=yyyyyyyy&id3=zzzzzzzzzz 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:
<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:
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):
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
<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 vonaddausgegeben 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 ). |
|---|---|
| baseloop | Index einer übergeordneten Liste abfragen |
recorddata.pageindex
<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
<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 (die Spalten können hier entweder 1, 2, 3 oder col1, col2, col3 heißen) |
Beispiele
<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.
<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
<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
<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
recorddata.nav
<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 labelname |
Name bzw. den Labelname des Containerloops |
|---|---|
| param | Name des Request-Parameters mit der Datensatz-ID (bei Blättern Einzeldatensatz) Standard:param |
| indexparam | Name des Request-Parameter, der die Index-Position enthält (bei Listenblättern) Standard:index |
| filename | (nur für alte Container) bezeichnet die Datei, auf die verlinkt wird (z.B. bei.previouslist). |
Beispiele
Listenblättern
<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
<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
<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.
<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 (zurück) 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 | setzttypeauf "url" |
| show | zeigt den Text auch dann an, wenn keine Vorgängerseite existiert |
| encode | kodiert jedes Zeichen des Links bei Angabe vonhtmlals &#nnn; (ist standardmäßig gesetzt, um dies abzustellen encode="plain"angeben) |
| not | kehrt den Effekt beitype="if"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)
<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)
<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)
<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.
<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, 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"(nur bei type="url"unterstützt) bewirkt, dass jedes Zeichen in &#nnn; umgewandelt wird (ist standardmäßig gesetzt, um dies abzustellen encode="plain"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)
<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)
<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)
<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.
<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.
<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.
<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.
<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.
<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.
<bx:recorddata.totalpages/>
Dieses Tag gibt die Anzahl der Anzeigeseiten aus.
recorddata.navlist / recorddata.navdetail
<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>
| max | Wennmaxnicht 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): 3 | 4 | 5 | 6 | 7
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
<bx:recorddata.navlistpage/>
<bx:recorddata.navdetailpage/>
gibt die Nummer der Seite bzw. Detailseite aus
recorddata.navlistindex
<bx:recorddata.navlistindex/>
gibt die Indexnummer zurück, die zum Aufruf der im Schleifendurchlauf repräsentierten Seite benötigt wird
recorddata.navdetailid
<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
<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
<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
<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
<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.
<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.
<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.
<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
<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
<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
<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
<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
<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
<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
<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
<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 Zugriff auf die Felder des übergeordneten Containers (zur Zeit nur direkt-übergeordnet möglich) sollte nicht mehr verwendet werden, lieber parent |
| baseloop | Name der Containerschleife (wie er nach dem Punkt im Tag steht) 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 Dazu darf beim Speicher-Action weder ja noch nein bei createnew gewählt sein. |
Beispiele
<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/>&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.
<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/>&kat=<bx:recorddata.id parent="1"/>&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
<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 |
Beispiele für Filter
Filtername im Feld
...
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
...
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
<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 quoted-printable:** das Format in einer Email, siehe entsprechenden Wikipedia-Eintrag javascript: Den Zeichen "\n \r \t " ' " wird ein Backslash vorangestellt. url: zum Kodieren von Request-Parametern. Es wird java.net.URLEncoder benutzt. urlpath: zum Kodieren von Pfadbestandteilen (z. B. Dateiname) 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. ellipsis=" usw." (mit Parameterwert) fügt usw. an den Text an oder halt irgendwas anderes sinnvolles. |
Feldinhalt vergleichen
<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}>
| matches | Regulärer Ausdruck auf "leer" prüfen: 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
<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:
<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.
<bx:recordfield.Email contains="batix.com">class="intern"</bx:recordfield.Email>
Jedem Link, der den String "batix.com" enthält, wird die Klasse "intern" zugewiesen (um ihn z.B. auf www.batix.com von externen Links zu unterscheiden)
mehrzeiliger Text
<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 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 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. ellipsis=" usw." (mit Parameterwert) fügt usw. an den Text an oder halt irgendwas anderes sinnvolles. |
Beispiele
<bx:recordfield.Titel/>
<bx:recordfield.Text maxwords="20" ellipsis />
<a href="detail.htm?beitragsid=<bx:recorddata.id/>">mehr</a>
Datum/Zeit
<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")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
<bx:recordfield.Datumsfeld day="15" month="+1" />
zeigt anstatt des gespeicherten Datums den 15. des folgenden Monats an.
Abfrage
<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
<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
<bx:recordfield.{field} weekday="{angabe}"/>
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. 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.
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
<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
<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. |
<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 gte lt lte |
größer größer gleich kleiner kleiner gleich |
|---|
Alternativwert
<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).
<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
<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: ![]() |
Datenansicht: ![]() |
| not | Ausgabe, wenn das Feld nicht angehakt wurde (ohne: Ausgabe, wenn das Feld angehakt wurde) veraltet für not: invert und else |
|---|---|
| empty | Ausgabe, wenn Status "nicht gewählt" zutriffe (Erklärung siehe Text oben) |
Beispiele
<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.
<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“.
<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>zeigt Block an, wenn das Feld angehakt ist |
<bx:recordfield.häkchen not alt="false">zeigt Block an, wenn das Feld nicht angehakt oder leer ist |
<bx:recordfield.häkchen not>zeigt Block an, wenn das Feld als nicht angehakt gespeichert ist |
<bx:recordfield.häkchen alt="true">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
...
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
<bx:recordfield.{field} [width="{n}"] [height="{n}"] [nogifshrink] [cover]/>
Es wird das Bild (also ein 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) 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 |
Beispiele
Beispiel 1
<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
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

Bild-Daten ausgeben
<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
<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.
<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
<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
<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 mittype="size")Formatierung der Zahl (Standardwert ist "#,##0") |
| locale | (nur in Verbindung mittype="size")Sprachen-Formatierung der Zahl (standardmäßig "de_DE") |
| disposition | siehe Beispiele |
Beispiele
<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
<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
<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
<bx:recordfield.{field} type="(x | y) [multiply="{n}"] [add="{n}"] [alt="{n}"] />
| type | Je nachtypewird 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
<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>>
| 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
<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
<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: 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ßtype="ids"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:
<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 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) 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
<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.) 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 Filter , standardmäßig auf 8 gestellt) |
| filtervalue | Static-Wert oder Parameter-Werte |
| filterrequired | required-Flag für das Filter-Objektsetzen (standardmäßig false) |
| type not |
empty: Abfrage, ob der UK leer ist.notkehrt die Abfrage um 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
<bx:recordfield.Sub filterfield="Text" filtertype="1" filtervalue="request:suche">
<bx:recordfield.Text />
</bx:recordfield.Sub>
Beispiel für den Einsatz von nofilter
<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).):
<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.
<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:
- Container-Filteraction
- bx:tablefield
- Container
- bx:recordfield
- Container
- bx:tablefield
- Container-Filteraction
- bx:recordfield
(8 Verweise)
bx:relativelink
Das Tag relativelink dient zum Erzeugen relativer Links.
Unterpunkt des aktuellen Hauptmenüpunktes
<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 mittelshrefangegeben werden, die an den Pfad angehängt wird. |
| ifempty | showbody: Taginhalt wird ausgegeben (Standard) hide: bei Nichtfinden wird auch nichts angezeigt |
Hauptmenüpunkt wechseln
<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
<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 Beispiel). 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:
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:

Webseite:

bx:scanner
scanner.skip
<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
<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
<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. 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 oder bx:bild.
Um innerhalb der Schleife zu navigieren, benutzt man die Eigenschaften von bx:loop.
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.
Listausgabe
<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 dient auch zum Unterscheiden von mehreren Schleifen einer Seite in der Datenbank 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 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
<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
<bx:schleife.Cats>
<h1><bx:text.Name/></h1>
<bx:textarea.Beschreibung/>
<bx:bild.Bild/>
</bx:schleife.Cats>
Die Detailseite.
Record
<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
**Achtung!**
Dieses Tag ist deprecated (missbilligt), es wird nicht mehr weiterentwickelt oder in zukünftigen Versionen nicht mehr unterstützt. Bitte stattdessen bx:websearch benutzen.
<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.
[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.
secureform
<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
<bx:secureform>
<form action="save.act">
...
</form>
</bx:secureform>
secureform.field
<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)).
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.
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.
| parametername | entspricht dem Name des Parameters, der vom Browser später mitgeschickt wird ist meistens gleich dem name-Attribut eines <input>s |
|---|
Beispiele
<!-- 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
<bx:secureform.values name="{parametername}" [cut]>...</bx:secureform.values>
In dieser Form wird ein erlaubter Wert eines Parameters gesammelt (siehe Mehrere erlaubte Werte). 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:
<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".
Falls keine Werte für den Parameter gesammelt wurden, geben alle drei Varianten nichts aus.
secureform.hash
<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).
Nach `
secureform.check
<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.
| parameterliste | Dies ist eine komma-getrennte Liste der Parameternamen, welche zur Hashbildung herangezogen werden. Tauchen hier Parameternamen auf, die nicht im Request sind, so werden diese Parameter nicht zur Hashbildung benutzt. 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. 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).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. 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).
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.
Erlaubte Werte
Falls ein spezieller Parameter für mehrere erlaubte Werte mitgeschickt wurde, wird zusätzlich geprüft, ob der originale Parameter einem dieser Werte entspricht.
Verweise auf diese Seite:
- Sicheres Formular überprüfen (SecureformAction)
- Sicheres Formular überprüfen (SecureformAction)
- Manipulationsgeschützte Formulare mit Secureform
- Manipulationsgeschützte Formulare mit Secureform
(4 Verweise)
bx:sessiondata
Das Tag sessiondata setzt, liest und vergleicht Werte von Session-Variablen.
Auslesen eine Attributes, das mit dem Action geschrieben wurde
<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
<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
<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: - 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
<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
<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
<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
**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)**.
Allgemeine Syntax
<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<level>> 0 und kein <bx:sitemap.0>-Tag außen herum steht) |
sitemap.text
<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
<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.
veraltet: <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
<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
<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
<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
<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
<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
<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
<bx:statistik.url/>
Diese Funktion erfordert eine umgebende .pagelist. Es wird die URL des aktuellen Schleifenelements ausgegeben.
statistik.name
<bx:statisik.name/>
Diese Funktion erfordert eine umgebende .pagelist.
Beispiele
<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> </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
submenu.list
<bx:submenu.list [all]> Inhalt </bx:submenu.list>
| all | um auch nicht aktivierte Menupünkte anzuzeigen |
|---|
submenu.name
<bx:submenu.name />
Der Name des Menüpunktes wird ausgegeben.
submenu.link
<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
<bx:submenu.description [maxwords="{n}"] />
Dieses Tag gibt die Beschreibung des Menüpunktes aus,
| maxwords | optional auf {n} Wörter begrenzt |
|---|
submenu.path
<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
<bx:submenu.target alt="_self" />
Das Target aus dem Menüpunkt wird ausgegeben.
submenu.meta
<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
<bx:submenu.cols num="{n}" equals="{n}">...</bx:submenu.cols>
Zeigt abhängig von einer Spaltennummer einer Menüpunktliste Daten an.
Beispiele
<bx:submenu.cols num="3" equals="3">style="margin-right:0;"</bx:submenu.cols>
Nur Spalte drei soll kein Rechts-Margin haben
<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
<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
<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
<bx:submenu.redirected> ... </bx:submenu.redirected>
<bx:submenu.redirected not> ... </bx:submenu.redirected>
Abfrage, ob der Punkt weitergeleitet ist
Beispiele
<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
<bx:redirecturl />
Rückgabe der Redirect-URL
Schachtelung und Geschwister
Beispiel
<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).
<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>
bx:submenulist
**Achtung!**
Dieses Tag ist deprecated (missbilligt), es wird nicht mehr weiterentwickelt oder in zukünftigen Versionen nicht mehr unterstützt. Bitte stattdessen bx:submenu benutzen.
Dieses Tag stellt Untermenüpunkte des aktuellen Menüpunktes mittels einer Schleife dar.
<bx:submenulist [all]> Inhalt </bx:submenulist>
Um auch inaktive Punkte anzuzeigen, muss all angegeben werden. Folgende Tags können im Inhalt verwendet werden:
submenuname
<bx:submenuname />
Gibt den Name des Menüpunktes aus.
submenudir
<bx:submenudir />
Gibt den virtuellen Verzeichnisnamen des Menüpunktes aus.
Verweise auf diese Seite:
Keine Verweise gefunden.
bx:systemdata
systemdata.attribute
<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 * (seit v2.5.9)* |
| not | kehrt die Bedingung um |
systemdata.variable
<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.:
<bx:containerloop pool="system:newslistid">
wenn in jedem Projekt eine Variable namens newslistid definiert wird, die eine passende Container-ID enthält
oder:
<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:
<%@taglib prefix="batix" uri="/batix"%>
<batix:taginfo>
<%
String wert = variables.getVariable("test");
%>
</batix:taginfo>
in Jsp-Action geht der Aufruf so:
<%@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. Alles was in 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.
bx:tabledata
Dieses Tag ist eine Erweiterung von bx:recorddata. Alles was in 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.
bx:tablefield
Dieses Tag ist eine Erweiterung von bx:recordfield. Alles was in 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.
bx:tablefilter
Dieses Tag ist eine Erweiterung von bx:containerfilter. Alles was in bx:containerfilter 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.
bx:tablekat
Dieses Tag ist eine Erweiterung von bx:containerkat. Alles was in 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.
bx:tableloop
Dieses Tag ist eine Erweiterung von bx:containerloop. Alles was in 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.
bx:tablerecord
Dieses Tag ist eine Erweiterung von bx:record. Alles was in 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.
bx:tablesqlfilter
Das Tag tablesqlfilter filtert einen Container über eine SQL-Anweisung, die in den Tag-Einstellungen der Administraton angegeben ist.
<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
Die einzelnen Funktionen können kombiniert werden.
Dieses Tag kann sich in der Verwaltung darstellen.
Textfeld anzeigen
<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. |
Für `{titel}` und `{kommentar}` siehe die allgemeinen Hinweise zu [Redakteurs-Tags](/books/cms-handbuch-entwickler/page/redakteurs-tags).
Länge begrenzen
<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
<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 |
url |
UrlEncode mit Projekt-Zeichensatz |
javascript |
Non-Strict ScriptEncode |
entitymask |
HtmlMask |
xml |
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.
<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.
<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 medium lage xlarge |
| Vorlage | cols | rows | | --- | --- | --- | | small | 21 | 5 | | medium | 42 | 8 | | large | 63 | 20 | | xlarge | 63 | 35 | |
| Vorlage | cols |
| small | 21 |
| medium | 42 |
| large | 63 |
| xlarge | 63 |
| 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 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 erweiterbar mit encode="htmltext" |
| encode="htmltext" | zeigt plain-Feld in Verwaltung aber macht s im Frontend rein |
| wrap="wrap" | Art des Zeilenumbruchs des Textfeldes in der Verwaltung, Standardwert ist hier virtual. (siehe auch SELFHTML Dokumentation ) |
Beispiele
Code:
<bx:textarea.Seitentext large comment="Dieser Text steht direkt unter der Überschrift."/>
Ansicht in der Verwaltung (Formatierungen werden über den zweiten Balken oben vorgenommen):

.......

Ansicht auf der Seite:

Bilder mittels Platzhalter einfügen
Legen Sie dazu im Quelltext der Seite ein Bx:schleife Tag an, welches ein Bx:bild 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 Bx:bild Tags in der Schleife. Jetzt können Sie die Seite im Projektmenü 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 Beispiel.
Beispiele
Code:
<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:

Auf der Seite:

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"
<bx:textarea.demotextarea medium imgloop="bilder" left="Bild-links" right="Bild-rechts" />
Code in Bilder-Detailseite "bilder.htm"
...
<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"
<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"
<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
**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)**.
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.
<bx:titel/>
bx:tools
Das Tag tools vereint kleine Hilfen, um häufig auftretende Aufgaben zu vereinfachen.
Hilfsmittel für Requestparameter
tools.request
<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.
tools.listrequest
<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
<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
<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 |
|---|---|
| < | < |
| > | > |
| " | " |
| & | & |
| ' | ' |
| äöüÄÖÜß§€, deutsche Anführungszeichen unten und oben und langen Bindestrich |
|
| alles ab ASCII-Code 128 |
zu "&#[code];" |
tools.urlencode
<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 java.net.URLEncoder benutzt.
tools.urlpathencode
<bx:tools.urlpathencode [charset="{set}"]> Inhalt </bx:tools.urlencode>
Zum Kodieren von Pfadbestandteilen (z. B. Dateiname). 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 URLEncoder.encode(String, String) verwendet.
tools.entityencode
<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
<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
<![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
<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 | | Leerzeichen | |
| ü | ü | Ü | Ü | |
| ä | ä | Ä | Ä | |
| ö | ö | Ö | Ö | |
| ß | ß | " | " (gerade Anführungsz. oben) | |
| < | < | > | > | |
| & | & | „ | " (dopp. Anführungsz. unten) | |
| “ | " (dopp. Anführungsz.oben) | – | - (Breite n) | |
| … | ... | – | - (Breite n) | |
| € | € | ´ | ´ | |
| ’ | ' | § | § |
Zuletzt wird noch eventueller Whitespace am Anfang und Ende des Textes entfernt.
tools.plain2html
<bx:tools.plain2html> Inhalt </bx:tools.plain2html>
Wandelt den plain-Text im body in HTML-Code um, indem er HTML encoded wird und bei jeden Zeilenumbruch ein
oder
gesetzt wird
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ünfte Zeile»
tools.csvfield
<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
<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
<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 |
| & | & |
| " | " |
| ' | \' |
| \t | \\t |
| \ | \\ |
tools.umlautencode
<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
<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
... 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
<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 steuern (Standard ist "dd.MM.yyyy HH:mm").
tools.positiontracker
<bx:tools.positiontracker [boundary="{text}"] [showall] [startlevel="{n}"] />
| boundary | Text zwischen den einzelnen Ausgaben (Standard-Wert ist " >> ") |
|---|---|
| showall | auch inaktive Hauptmenüpunkte werden ausgegeben |
| startlevel | Angabe, wenn in einem anderen Level gestartet werden soll (Hauptmenü = Level 0) |
Beispiele
<bx:tools.positiontracker boundary=" | " startlevel="1"/>
Ausgabe der Menüpunkte ab der 2. Ebene, Trenner ist ein Pipe-Zeichen zwischen zwei Leerzeiche.
tools.datum
<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 bx:recordfield) 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) ohne Angabe von show: jetzt |
|---|---|
| year month day hour minute 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")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 Formatierung des Datums fest (Standard ist "dd.MM.yyyy") |
Beispiele
<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
<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. So steht z.B. "1111100" für nur werktags oder "1010100" für montags, mittwochs, freitags . |
| not | zur Umkehrung der Uhrzeitangaben. Es beeinflußt nur die Uhrzeit und nicht den Parameter 'week' |
| 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
<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
<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
<bx:tools.timeframe after="22:00" now="7.3.2018 22:01">Bettruhe!!!</bx:tools.timeframe>
tools.for / tools.forchar
<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 bzw. angegebenem Zeichen (z.B. a) |
|---|---|
| end | Endet bei angegebener Zahl bzw. angegebenem Zeichen (z.B. z) |
| inkrement | der Wert, um den erhöht werden soll (Standard: 1) falls start> endist, muss hier eine negative Zahl eingetragen werden! |
Beispiele
<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 zwischengespeichert) werden in einem Drop-Down ausgegeben (value mit vorangestellter 0, wenn unter 10)
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
<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
<bx:tools.for-split source="Hallo Welt" regex=" "> :{i}: </bx:tools.for-split>
ergibt " :Hallo: :Welt: "
<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
<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
<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.
Es muss mindestens eine Charakter-Klasse angegeben werden.
| 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
<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
<bx:tools.uuid />
Hiermit wird eine zufällige UUID (Typ 4) erzeugt (z.B. f3910a2f-63cf-433b-8117-1ac0d22bb4f5).
tools.id
<bx:tools.id />
Dieses Tag erzeugt eine neue Batix-ID und gibt diese aus (z.B. 12E241E47CB).
Fehlersuche (Debugging)
tools.showrequest
<bx:tools.showrequest/>
Erzeugt eine Debug-Ausgabe des Request-Typs sowie sämtlicher Parameter, die im Request enthalten sind.
tools.duration
<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 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
<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
<bx:tools.log level="{stufe}" [copy]>zu loggender Text</bx:tools.log>
Schreibt den Inhalt in die Logdatei, anstatt in die Seite.
| level | Logstufeerror, warn, infooder debugStandard: info |
|---|---|
| copy | Text soll auch auf der Seite angezeigt werden |
Beispiele
<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
<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 String.replaceAll verwendet, dadurch ergeben sich vielfältige Möglichkeiten.
| regex | regulärer Ausdruck, nach dem im Text gesucht werden soll |
|---|---|
| replacement | Ersetzungs-Text |
Beispiele
<bx:tools.replacetext regex="World" replacement="Batix">Hello, World!</bx:tools.replacetext>
Hier wird aus "Hello, World!" der Text "Hello, Batix!"
<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".
<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 http://www.regular-expressions.info (englisch). *
Schleifen-Modus
<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. 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. Im ersten Durchlauf steht also "0" im Clipboard, danach "1", usw.. |
replacetext_group_<n> |
<n> ist eine ZahlFü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:
<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:
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
sourceanreplacetextübergeben wird. - Der Regex lautet:
(\d+)#([^#]+)?#(.*)- Gruppe:
\d+(nur Ziffern) [^#]+(alles außer #).*(egal was)
- Gruppe:
- 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
<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
<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
<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) Standard: 0 (bei Fehlen des Parameters) |
| fillbefore fillafter |
optionales Füllzeichen (keine Entity) wenn Text kürzer ist als bei maxlengthangegeben, wird er mit dem angegeben Zeichen aufgefüllt |
Beispiele
<bx:tools.substring maxlength="5" startindex="6">Hello World</bx:tools.substring>
Gibt "World" aus
<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
<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 | reduziert mehrfache Leerzeichen zu einem einzelnen |
| single-line | entfernt alle Zeilenumbrüche und schreibt alles leerzeichengetrennt in eine Zeile |
Beispiele
<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
<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
<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
<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
<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
<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
<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
<bx:userdata.id />
Die ID des Benutzers wird zurückgegeben.
userdata.name
<bx:userdata.name />
Der vollständige Name (Anrede + Vorname + Nachname) wird ausgegeben.
userdata.email
<bx:userdata.email />
Die Email-Adresse des Users wird ausgegeben.
userdata.isintrauser
<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
<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
<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
<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
<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
<bx:userdata.username/>
Gibt den Username des angemeldeten Benutzers zurück.
userdata.meta
<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 ohne value: Ob Metaeigenschaft überhaupt vorhanden ist |
|---|---|
| value | Vergleichswert der Megaeigenschaft. Bei Übereinstimmung wird Inhalt ausgewertet 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
<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, wird ein Dummy-Datensatz angezeigt |
| type="id" | Ausgabe der DS-IDs |
| seperator="," | Trenner zwischen den IDs (siehe Beispiel) |
Beispiele
<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
<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
<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, dessen Inhalt wird dann mit der UserID verglichen. |
| dummy | falls kein User angemeldet ist oder kein passender Datensatz gefunden wurde, wird ein Dummy-Datensatz angezeigt |
Beispiele
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
<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
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
<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
Falls mehrere Fehlertypen auftreten, werden die Zahlen vom ValidationAction 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
<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
<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
Eingabefeld
<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
<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 * (ab Version 2.5.9)* |
| indexparam | Name des Blätterparameters |
websearch.title
<bx:websearch.title/>
gibt den Titel der Seite (<title> HTML-Tag) oder, falls dieser nicht existiert, "<ohne Titel>" aus
websearch.rank
<bx:websearch.rank/>
Rangfolge des Ergebnisses, beginnend mit 1
websearch.score
<bx:websearch.score/>
die Wertung des Suchergebnisses als Gleitkommazahl
websearch.relevanz
<bx:websearch.relevanz/>
eine Wertung des Ergebnisses als Ganzzahl mit Prozentzeichen
websearch.stars
<bx:websearch.stars [max="<n>"]> Inhalt </bx:websearch.stars>
Symbole als Relevanzanzeige ausgeben
| max | maximale Anzahl an Symbolen (Standard: 5) Der Inhalt bestimmt das Symbol, er kann z.B. ein bx:bild -Tag enthalten |
|---|
websearch.link
<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
<bx:websearch.url/>
gibt die URL der Fundstelle an. ab Version 2.5.8
websearch.path
<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
<bx:websearch.description/>
die Beschreibung des Dokuments (HTML <meta> Wert "description")
websearch.navname
<bx:websearch.navname/>
der Name des entsprechenden Navigationspunktes
websearch.navid
<bx:websearch.navid/>
die ID des entsprechenden Navigationspunktes
websearch.previous
<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
<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
<bx:websearch.totalhits/>
(steht außerhalb der Schleife) Gesamtzahl der Ergebnisse
websearch.firstshown
<bx:websearch.firstshown/>
(steht außerhalb der Schleife) Nummer des ersten Ergebnisses auf der Seite
websearch.lastshown
<bx:websearch.lastshown/>
(steht außerhalb der Schleife) Nummer des letzten Ergebnisses auf der Seite
websearch.query
<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: - 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
<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 darf auch innerhalb der Schleife verwendet werden. Um das Gegenteil abzufragen, wird notverwendet. |
|---|---|
| scrollable | es sind mehr Seiten vorhanden (Anzahl Ergebnisse >max) |
| morethan lessthan |
es wurden mehr als<n>Ergebnisse gefunden es wurden weniger als <n>Ergebnisse gefunden |
Eingabefeld
<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
<bx:tag.feature param="value" />
Weitere Beispiele unter Snippets/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
<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).
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:
<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-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.
<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>
<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.
<! -- 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.
<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 (siehe Java-Docs für mögliche Werte). ).
<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).
<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-Patterns unterstützt:
<bx:xml.mydate date />
Es wird folgende Liste in dieser Reihenfolge durchprobiert:
dd.MM.yy HH:mm:ssdd.MM.yy HH:mmdd.MM.yy HH.mmdd.MM.yyyyyy-MM-dd'T'HH:mm:ssZ(ISO 8601)
Alternativ kann ein eigenes Pattern angegeben werden:
<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:
<bx:xml.mydate date pattern="dd.MM. HH:mm" />
Werden z.B. Tages- oder Monatsnamen ausgegeben, wird über locale die gewünschte Sprache eingestellt:
<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):
<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:
<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 für andere Encoding-Möglichkeiten).
<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), 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.
<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)).
<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 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:
<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:
<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 entsprechende Passage bei bx:recorddata.
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.
<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.
<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 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:
<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
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.
Übersicht
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:
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.
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 /
in der Symbolleiste. Hier müssen Sie noch die Felder ausfüllen und die Aktion abspeichern (
/
). Anschließend werden Sie aufgefordert, einen neuen Aktionsbaustein hinzuzufügen. Klicken Sie auf diese Zeile und Sie sehen folgenden Assistenten:
Klicken Sie auf den Auswahlbutton neben der gewünschten Aktion und anschließend zum Speichern auf /
.
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
Führt Batix Quelltext aus
Werte können mit bx:pagedata.setscriptattribute an den nächsten Action-Baustein übergeben werden.
<bx:pagedata.setscriptattribute name="<name>"> Inhalt </bx:pagedata.setscriptattribute>
Ausgabe im Log: <bx:tools.log>...</bx:tools.log>
Benutzergruppe anlegen
Dieses Action erzeugt eine neue Benutzergruppe.
Parameter
| groupname | Feld mit Gruppennamen Parametername des Feldes, in dem der Benutzergruppenname steht (nur angeben, wenn Anlegen einer Gruppe) |
| field-id | Parametername des Gruppen-ID-Feldes 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 Attributname, in dem die ID der neuen Gruppe gespeichert werden soll |
Bild hochladen
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
<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
fileparammuß "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
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:
<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 <bx:pagedata.sessionurl/> angehängt werden.
Beispiel: <form action="save.htm<bx:pagedata.sessenurl/>">...</form>
CMS-Seite versenden
Eine normale Seite im Projekt wird gelesen und dann als HTML-Email versendet.
Da diese Aktion auf 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:
<![ATTACHMENT[Dokument-ID]]>
oder
<![ATTACHMENT[Anhang-Dateiname|URL für Anhangsdaten]]>
Um die Anhänge zu parsen muß im Action bei weitere Eigenschaften eine Einstellung eingetragen werden.
parse-attachments=true
Beispiel
<![ATTACHMENT[<bx:pagedata.request name="pdf" />]]>
wenn die Dokument-ID mit dem Request-Parameter "pdf" übergeben wird
<![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.
<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):
reply-to=[[Kontakt_Mail]]
Container-Filteraction
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) 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:
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 benutzt werden, z.B. bx:pagedata um der Aktion übergebene Parameter weiterzuleiten oder bx:recordfield bzw. bx:recorddata 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
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:
<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 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
<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 Batix-Tags benutzt werden, um den Inhalt von Textfeldern im Zieldatensatz aus mehreren Feldern des Quelldatensatzes zusammenzusetzen. An <bx>-Tags können nur einige verwendet werden, z. B. bx:pagedata um der Aktion übergebene Parameter weiterzuleiten oder bx:recordfield bzw. bx:recorddata 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
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
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 update-active=n |
Datensatz aktivieren oder deaktivieren es ist auch möglich den Wert via Platzhalter zu übergeben: update-active=[[paramName]]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
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
<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
<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
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
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 alternativ auch Dateiname, wo die Regeln drin stehen |
XML-Syntax der Validierungsregeln
<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 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
...
<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
...
<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
...
<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
...
<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
...
<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:
<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)
{Vergleichswert}: 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)
{Operator}:
- "=" 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
{Vergleichswert}
- 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.)
{Operator}
- "<" (<) - Prüft, ob Feld zeitlich vor dem Testwert liegt
- ">" (>) - 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
{Vergleichswert}
- Als Vergleichswert ist bisher (v2.5.8) nur ein fester Wert möglich. Als Dezimaltrenner muß das Komma verwendet werden.
{Operator}
- "<" 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)
{Vergleichswert}
- '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
{Operator}
- "=" 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
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.
.
Excel-Action
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) 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) ACHTUNG! "ordnerid" muß mit angegebenw werden. |
| ordnerid | ID des Ordners in der Dokumentenverwaltung, in der die fertige Datei abgelegt werden soll Muß mit angegeben werden, wenn in der Dokumentenverwaltung gespeichert werden soll. |
| xml | XML Daten direkt eingeben (wenn leer wird xmlfile genommen) 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). 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 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 hier, nur Farbnamen |
| widthA, widthB ... | Spaltenbreite nach Spaltenname |
Formular als Mail versenden
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
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) 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: http://www.regular-expressions.info/email.html):
[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
<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 reguläre Ausdrücke
Intranet Login
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
Diese Aktion invalidiert die Session und loggt damit den Benutzer aus.
Parameter
| nextpage | auf diese Seite wird anschließend weitergeleitet |
Intranet-User anlegen/ändern
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 Feldname mit dem der Benutzername übergeben wird (nur wenn neuer Benutzer) |
| field-id | Parametername des Benutzer-ID-Feldes Feldname mit dem die Benutzer-ID übergeben wird (nur wenn Änderung eines Benutzers) |
| field-password | Parametername des Passwortfeldes Feldname mit dem das Passwort übergeben wird |
| activate | Benutzer aktiv schalten, Standard: ja |
| attribute-userid | Name für neue Benutzer-ID 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
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
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
Einstellungen des Newsletterabo werden geändert.
Parameter
| nextpage | die Folgeseite |
Request-Parameter
id access rubrik email htmlmail passwort1 passwort2
Newsletter – Abonnentenlogin
Authentifizierung um Newsletterabo zu ändern.
Parameter
| login | Folgeseite, wenn Login OK war |
| error | Folgeseite, wenn der Login fehlgeschlagen ist |
Request-Parameter
| die Email-Adresse | |
| password | das Passwort |
Newsletter aktivieren
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.:
https://www.testseite.de/optin.act?nlid=[[activateid]]
Newsletter – Newsletter abonnieren
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
| die Email-Adresse | |
| rubrik | (optional) mehrmals angeben, um die Rubriken zu spezifizieren (Standard: alle) |
| passwort1 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)
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: "./") |
| (Request-Parameter) die Email-Adresse |
Newsletter – Passwort vergessen (2)
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
Das Passwort des gerade angemeldeten Users kann mittels dieser Aktion geändert werden.
Parameter
| oldpassword-field | Feld für altes Passwort 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 Request-Feldname, der Passwortfeld enthält. |
| password2-field | Feld für Passwortwiederholung Request-Feldname, die Passwortwiederholung enthält. |
| failpage | Fehlerseite 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
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
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
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
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)
Das SecureForm-Action wird benutzt, um Formulare gegen Manipulationen abzusichern. Es ist verfügbar ab Version 2.6.5.
Unter diesem Link gibt es eine ausführliche Anleitung, wie dieses Action mit dem zugehörigen Tag zu benutzen ist.
Parameter
| securelist | Dies ist eine komma-getrennte Liste der Parameternamen, welche zur Hashbildung herangezogen werden. Tauchen hier Parameternamen auf, die nicht im Request sind, so werden diese Parameter nicht zur Hashbildung benutzt. 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. 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. 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 mehrere erlaubte Werte mitgeschickt wurde, wird zusätzlich geprüft, ob der originale Parameter einen dieser Werte entspricht.
Actionklasse: com.batix.action.SecureformAction
Suche im Web
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 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
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 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
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 es können auch Spezailwerte verwendet werden: #null - Feld ist nicht im Request enthalten #empty - Feld ist leer im Request #nodata - Feld ist nicht im Request oder ist leer Ferner ist es möglich, reguläre Ausdrücke der Form ^regex hier$ zu verwenden. 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
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
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) 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
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 [1])
Funktionen:
Parameter
| Dokumentverwaltung | in Dokumentverwaltung speichern (Standard = nein) Wenn hier nein angegeben wird, dann wird das PDF-Dokument direkt zum Browser gestreamt |
| Verzeichnis-Id Eingabe bei weitere Eigenschaften: folderparam=parametername folderpath=/pfad/ targetweb=Projekt-ID |
ID des Zielordners in des Dokumentenverwaltung 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 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 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 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 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 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 (z.B. Session-ID prüfen) |
| Eingabe bei weitere Eigenschaften: info=irgendeine Info infoparam=parametername |
Dateiname des erzeugten PDF 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:
@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:
@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.
Ressourcen & Plugins
Container, Mediendatenbank, Vorlagen, Plugin Newsletter, Zeitsteuerung.
Container
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.
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:
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.
Nach dem Import Ihrer Excel-Liste haben Sie die Daten nun im CMS.
Dann brauchen Sie auch noch ein Template, um diese Daten mittels Tags in eine Website zu bekommen. Für dieses Beispiel brauchen Sie die Tags bx:containerfilter und bx:recordfield.
...
<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 - ungefährt so aus:
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
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 bei Vorlagen im Bereich Ressourcen 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 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
- Wenn sich zum Beispiel bei einem Ansprechpartner die Telefonnummer ändert, muss der Eintrag nur einmal geändert werden.
- 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.
- 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.
- 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.
- 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.

| 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
/

| 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

| 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:

neues Design:

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:

neues Design:

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:

neues Design:

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:

neues Design:

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:

neues Design:

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:

neues Design:

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.

Listenansicht

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

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

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
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
Dieses Plugin ist zwar schon etwas älter, wird allerdings noch in vielen Projekten eingesetzt.
Bedienungsanleitung für Redakteure
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
<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
<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 | |
| Datum | |
| Beitrag | |
| (rechtsbündig) erstes Bild (linksbündig) |
|
| (rechtsbündig) zweites Bild (rechtsbündig) |
|
| Nummer des Artikels, zum Bau einer Sprungmarke | |
| baut aus den Feldern "Link-Text" und "Link" einen Link zusammen | |
| "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 |
|---|---|
| Kopftext (bei "Versand"/"Kopftext" oder beim Design) | |
| an dieser Stelle wird der Quelltext des Hauptteils eingefügt, der separat definiert wird (siehe oben) | |
| Impressumstext (bei "Versand"/"Kopftext" oder beim Design) | |
| Liste der Artikel ohne Link | |
| generiert eine Liste der Artikel aus den Titeln, Sprungmarke wird an den Titel im Artikel gepappt | |
| in Verbindung mit Email zum Abmelden (Weiterleitung auf Abmelde-Action, Übergabe der Werte aboid und email | |
| siehe oben | |
| 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:
Neue Methode mit Tags
Anstelle der Platzhalter kann auch ein Design angegeben werden, in dem Tags anstelle der Platzhalter eingesetzt werden können.
<!-- 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>
<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
<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
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.

Übersichtsseite

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 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. 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
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
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)

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.

Übersichtsseite

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

Auf der Bearbeitungsseite können Sie folgende Einstellungen vornehmen:
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.
Zur Speicherung der statischen Quellen sollte "Vorlagenressourcen" nicht mehr verwendet werden, sondern stattdessen "statische Ressourcen" .


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
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
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=https://www.externer-server.de - 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=http://www.dein-web.de/aktionen/testaktion.act - 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 noreply@batix.info 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:
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
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" im Zusammenhang mit dem Tag "bx:pagedata.setscriptattribute" benutzen. Hierzu ein paar Beispiele:
Umwidmen eines Request-Parameters
<bx:pagedata.setscriptattribute name="Email"><bx:pagedata.request name="Imehl"/></bx:pagedata.setscriptattribute>
Bestandteil einer Botfalle
Quelltext der Seite
<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
<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)
Einfaches Listenblättern
sieht so aus:
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
<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"
<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"
<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>
| <strong>Seite:</strong>
<bx:recorddata.navlink move="-5"/>
<bx:recorddata.navlist max="5" boundary=" · "/>
<bx:recorddata.navlink move="5"/>
|
<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
<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>
| <strong>Seite:</strong>
<bx:tabledata.navlink move="-5"/>
<bx:tabledata.navlist max="5" boundary=" · "/>
<bx:tabledata.navlink move="5"/>
|
<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
.blaetternunten,.blaetternoben{
background-color:#999999;
text-align:center;
padding:5px;
color:#ffffff;
}
Etwas ausführlicheres Stylen
sieht so aus:
Code
<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
#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
<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:
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
<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ü
Beispielcode für ein einfaches Menü
<!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
.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 http://dev.batix.local/www/dev/purecssmenu/
CSV-Import in Container
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@batix.com
Wurst,Hans,Marketing,090/345678,hawu@dotcom.com
...
Eingeloggt bleiben
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).
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
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
<!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 http://jquery.malsup.com/form/#getting-started
Google-Sitemap Datei erzeugen
Diese Beispiel realisiert folgende Funktionen:
- eine dynamische Sitemap im XML-Format generieren, die Suchmaschinen beim Indizieren hilft
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 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 wird allerdings nur das Bearbeitungsdatum des Hauptmenüpunktes zurückgegeben (nicht das der einzelnen Menüpunkte), bx:tools.datum 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
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 http://msdn.microsoft.com/en-us/library/aa338201.aspx.
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
Benutzt werden die beiden Tags bx:calendarloop und bx:calenderfield
<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">«</a></span>
<span><bx:calendarfield.month object="Kalender"/></span>
<span><a href="./?<bx:calendarfield.month link="next" object="Kalender"/>" title="einen Monat vor" >»</a></span>
</div>
<div class="year">
<span><a href="./?<bx:calendarfield.year link="prev" object="Kalender"/>" title="ein Jahr zurück">«</a></span>
<span><bx:calendarfield.year object="Kalender"/></span>
<span><a href="./?<bx:calendarfield.year link="next" object="Kalender"/>" title="ein Jahr vor">»</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
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
- Projekt auswählen
- bei Dokumentvorlagen rechts unter Tools auf Quelltext ersetzen klicken
- in das erste Textfeld (Suchbegriff) eintragen:
pattern="([^"]*(?:MMM|E)[^"]*)"(?! locale) - in das zweite Textfeld (Ersetzen durch) eintragen:
pattern="$1" locale="de" - Haken regulärer Ausdruck setzen
- auf Vorschau klicken und prüfen, ob alles passt
- auf jetzt ersetzen klicken
- ggf. Schritte 6 und 7 wiederholen, falls viele Quelltexte betroffen sind
Manipulationsgeschützte Formulare mit Secureform
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 und die Aktion Sicheres Formular überprüfen (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
<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
<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.
<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
<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.
Im Link
Das Tag kann auch benutzt werden, um einen Link / Button abzusichern:
<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)
<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)
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) 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.
Steht ein Parameter in der Liste, wurde aber nicht übergeben, so wird er vom Baustein nicht zu Hashbildung herangezogen.
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).
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).
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>, 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
<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
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
<!-- #################### 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
<!-- #################### 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
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:
<filter>
<filter-object required="true">
<field>Kontakt_Email</field>
<type>4</type>
<request-value>email</request-value>
</filter-object>
<limit max="1"/>
</filter>
url:
savetoken.act?Token=<bx:tools.uuid/>&Kontakt=<bx:recorddata.id/>&BCVerknuepfung=<bx:recordfield.Kontakt_BC><bx:recorddata.id/></bx:recordfield.Kontakt_BC>&Erstelldatum=<bx:tools.urlencode><bx:tools.datum pattern="dd.MM.yyyy HH:mm"/></bx:tools.urlencode>&Email=<bx:recordfield.Kontakt_Email/>
failurl:
pwvergessen.htm?fehler=1&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&token=[[token]]&email=[[email]]
2.) Aktionsbaustein "vorhandene Bedingung abfragen" - Paßwörter gleich?
requestField: Passwort
compareValue: [[Passwortwdhlg]]
conditionFalse: changepw.htm?fehler=2&token=[[token]]&email=[[email]]
3.) Aktionsbaustein "Container-Daten Filteraction" - prüfen, ob Token-DS gültig ist
list: ID des Token-Containers
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=<bx:recordfield.BCVerknuepfung type="id"/>&Token=&tokid=<bx:recorddata.id/>&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
<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
<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
<!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/>&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
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), 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.
Verfügbar ab CMS Version 2.7.3
Beispiel
Zur schnellen Übersicht ist hier ein Beispiel, in dem viele Methoden verwendet werden.
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).
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.
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:
val cnt = tmd.records().apply {
filterCheckbox("deleted").notChecked()
if (!reqSuche.isNullOrEmpty()) {
filterString("Beschreibung").notNullAnd().contains(reqSuche)
}
asc("Titel")
limit(10)
}.count()
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.
Damit die Abfrage ausgeführt wird, ist als letztes eine der Ergebnis-Methoden aufzurufen. Diese können auch mehrfach aufgerufen werden, die Abfrage wird dann immer wieder mit den aktuellen Einstellungen neu gestartet.
Bei Methoden, die mehrere Testwerte entgegennehmen, kann auch eine Collection des entsprechenden Typs anstatt einzelner Parameter übergeben werden.
Connection
.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.
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.
Das entspricht im XML-Filter der Angabe mehrerer `<field>` Elemente.
Beispiel
.filterString("Vorname", "Nachname").notNullAnd().contains("muster")
Alle Filtermethoden prüfen ihre Argumente auf `null` bzw. leer (z. B. bei Strings) und lehnen solche Werte mit einer Exception ab.
Das bedeutet man kann weder explizit, noch aus Versehen, einen Testwert übergeben, der nicht filtert (beispielsweise einen Leerstring beim Filtern einer "Besitzer" Verknüpfung).
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.
Nachfolgend sind die Feldtypen mit ihren zugehörigen Filter-Methoden aufgeführt.
Text
.filterString("Feldname")...
Leer abfragen
.filterString("Feldname").empty()
.filterString("Feldname").notEmpty()
Leer erlaubt oder nicht erlaubt
.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
.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.
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!
Partielle Übereinstimmung
.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.
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!
Bild
.filterPicture("Feldname")...
Leer abfragen
.filterPicture("Feldname").empty()
.filterPicture("Feldname").notEmpty()
Ziel-Datensatz existiert
.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
.filterPicture("Feldname").id("123456ABCDEF")
Datei
.filterDocument("Feldname")...
Leer abfragen
.filterDocument("Feldname").empty()
.filterDocument("Feldname").notEmpty()
ID abfragen
.filterDocument("Feldname").id("123456ABCDEF")
Datum mit oder ohne Uhrzeit
.filterDate("Feldname")...
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.
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.
Beispiele
LocalDateTime.parse("zu parsender String", DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm:ss"))
LocalDate.parse("zu parsender String", DateTimeFormatter.ofPattern("dd.MM.yyyy"))
Leer abfragen
.filterDate("Feldname").empty()
.filterDate("Feldname").notEmpty()
(Teil)Gleichheit
.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
.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
.filterDate("Feldname").nullOr().newerEquals(/* Date | LocalDate | LocalDateTime */)
.filterDate("Feldname").nullOr().olderEquals(/* Date | LocalDate | LocalDateTime */)
Uhrzeit
.filterTime("Feldname")...
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.
Beispiele
LocalTime.parse("zu parsender String", DateTimeFormatter.ofPattern("HH:mm:ss"))
LocalDateTime.parse("zu parsender String", DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm:ss"))
Leer abfragen
.filterTime("Feldname").empty()
.filterTime("Feldname").notEmpty()
(Teil)Gleichheit
.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
.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
.filterTime("Feldname").nullOr().laterEquals(/* Date | LocalTime | LocalDateTime */)
.filterTime("Feldname").nullOr().earlierEquals(/* Date | LocalTime | LocalDateTime */)
Ganzzahl
.filterInteger("Feldname")...
Leer abfragen
.filterInteger("Feldname").empty()
.filterInteger("Feldname").notEmpty()
Gleichheit
.filterInteger("Feldname").value(/* Number */)
.filterInteger("Feldname").notValue(/* Number */)
.filterInteger("Feldname").nullOr().value(/* Number */)
.filterInteger("Feldname").nullOr().notValue(/* Number */)
Abfrage größer / kleiner
.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
.filterFloat("Feldname")...
Die Methoden sind identisch zu Ganzzahl, es muss lediglich filterFloat als Methode verwendet werden.
Alle Vergleiche auf Gleichheit bzw. Ungleichheit verwenden eine maximale Genauigkeit von 0,00001.
Das bedeutet, dass z. B. 0,000004 und 0,000005 für den Filter gleich sind.
Wahrheitswert (Checkbox)
.filterCheckbox("Feldname")...
Prüfen ob angehakt
.filterCheckbox("Feldname").checked()
.filterCheckbox("Feldname").notChecked()
Prüfen ob leer
.filterCheckbox("Feldname").empty()
.filterCheckbox("Feldname").notEmpty()
Dies ist in den meisten Fällen nicht der richtige Filter und es sollte "Prüfen ob angehakt" benutzt werden.
Hier wird nur geprüft, ob noch kein expliziter Wert im Feld steht, egal ob angehakt oder nicht angehakt.
Wurde die Checkbox also als **nicht angehakt** gespeichert, ist das Feld **nicht leer** (da "n" oder 0 drin steht).
Koordinaten
.filterCoordinate("Feldname")...
Dieser Feldtyp ist veraltet und wird nicht mehr benutzt. Er wird hier nur der Vollständigkeit halber erwähnt.
Prüfen ob leer
.filterCoordinate("Feldname").empty()
.filterCoordinate("Feldname").notEmpty()
Gleichheit der Koordinaten
.filterCoordinate("Feldname").x(/* Number */)
.filterCoordinate("Feldname").y(/* Number */)
Einzelverknüpfung
.filterSingleLink("Feldname")...
Prüfen ob leer
.filterSingleLink("Feldname").empty()
.filterSingleLink("Feldname").notEmpty()
Prüfen ob Datensatz existiert
.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
.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
.filterSingleLink("Feldname").id("123456ABCDEF")
.filterSingleLink("Feldname").notId("123456ABCDEF")
.filterSingleLink("Feldname").anyId("123456ABCDEF", "ABCDEF123456")
Mehrfachverknüpfung
.filterMultipleLink("Feldname")...
Prüfen ob leer
.filterMultipleLink("Feldname").empty()
.filterMultipleLink("Feldname").notEmpty()
Nach ID suchen
.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)
.filterSubList("Feldname")...
Prüfen ob leer
.filterSubList("Feldname").empty()
.filterSubList("Feldname").notEmpty()
Aktiv / Inaktiv
.active()
.activeOrInactive()
.inactive()
Standardmäßig werden nur aktive Datensätze zurückgegeben. Dies lässt sich aber anpassen.
IDs inkludieren / exkludieren
.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
.limit(/* Integer */)
.index(/* Integer */) // 0-basiert
Die Anzahl der Ergebnisse kann mit limit begrenzt werden. Ebenso kann die Startposition mit index festgelegt werden.
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` .
Sortierung
.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.
.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
.count() // int
Diese Methode gibt lediglich die Anzahl der gefundenen Datensätze zurück.
Erster Datensatz
.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
.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
.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.
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).
Das geschieht z. B. automatisch durch terminale Stream-Methoden oder manuell mittels `close()`.
Alle Datensätze laden
.loadAll() // ContainerRecord[]
Es wird ein Array zurückgegeben. Falls keine Elemente gefunden wurden, ist das Array leer (nicht null).
Diese Methode lädt alle gefundenen Datensätze in den Speicher, was zu Abstürzen fehlen kann. Daher sind die anderen Methoden vorzuziehen.
Regelmäßiges Neuladen von DIVs
Aufbau der Hauptseite
<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:
<script type="text/javascript">
registerRedirect(2, "oben.html", $("div1"))
</script>
... Content für oben steht hier ...
Sitemap bauen
Einfaches Sitemap, kann noch verschönert werden.
Styles
.ebene0{
font-weight:bold;
text-decoration:underline;
}
.ebene1{
margin-left:30px;
}
.ebene2{
margin-left:60px;
}
Quellcode
<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
Dieses Beispiel realisiert folgende Funktionen:
notfür ein Tag emulieren, dassnotnicht unterstützt
Quellcode
Als Beispiel dient hier das Tag bx:pagedata.navid, welches not für seine Bedingung nicht unterstützt.
<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 <bx:if> 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
Validation eines Container-Datensatzes
Mit einem Aktionsbaustein vom Typ ValidationAction werden die zu validierenden Felder und ihre Gültigkeitsbedingungen konfiguriert. Danach folgt ein Aktionsbaustein vom Typ ValidationResultAction der das Validationsergebnis im XML-Format in ein Feld des Containerdatensatzes schreibt.
Auf der Formularseite können durch das Tag bx:validation die fehlerhaften Eingabefelder markiert, oder ein Kommentar angezeigt werden.
Validation von übergebenen Requestparametern
Der Aktionsbaustein FormValidatorAction 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 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
Voraussetzung für ein Funktionieren der Websuche ist eine Indizierung der Seiten, z.B. via Zeitsteuerung. Dies geht erst, wenn das Web fertig, also ungeschützt und unter der endgültigen Url erreichbar ist.
Suchformular
<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
resultpage: Pfad zur Ausgabeseite, z.B. /suche/
Ausgabeseite
<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>
</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> <bx:websearch.link><bx:websearch.title/></bx:websearch.link> <bx:websearch.stars max="5"><img src="star.jpg"> </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
- javascript
- url
- xml
- html
- sql
- sql-like
- sql-rlike
- htmltext
- plain
Informationen zu den einzelnen Encodings:
Auf jeder Seite steht ganz unten, welche Tags oder sonstigen Funktionen diese Umwandlung benutzen bzw. unterstützen.
HtmlEncode
Es werden folgende Ersetzungen vorgenommen:
| Originalwert | ausgegebener Wert |
|---|---|
< |
< |
> |
> |
" |
" |
' |
' |
& |
& |
HtmlMask
Hierbei werden sämtliche Zeichen durch HTML-Entities der Form &#dd; ersetzt, wobei d für eine dezimale Ziffer steht.
Aus Hallo wird somit Hallo.
ScriptEncode
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
Es wird die Java Klasse URLEncoder 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
Es werden folgende Ersetzungen vorgenommen:
| Originalwert | ausgegebener Wert |
|---|---|
< |
< |
> |
> |
" |
" |
& |
& |
| Zeichen zwischen dezimal 32 und 127 (beides inklusive) |
(unverändert) |
| Alle restlichen Zeichen | &#ddd;d = dezimale Ziffer je nach Plattform, auf der das CMS läuft, können unterschiedliche Werte entstehen |
Groovy
Groovy-Scripting im CMS.
API
eine gekapselte Klasse mit statischen Methoden, die zusammengehörige Funktionalitäten enthältMyApi (bei class und logName muss noch angepasst werden.
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
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 — eine gekapselte Klasse mit statischen Methoden, die zusammengehörige Funktionalitäten enthält
- BatixUtils
- Logging — um einfach Logausgaben zu erzeugen, die den Name des Scripts vorangestellt haben
- Timings — nützlich, um einzelne Code-Teile zu profilen und so herauszufinden, was genau langsam ist
CMS-spezifische Helfer
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ührendenbx:groovyTag, ansonstennull-
es können hier z.B. Tag-Parameter gelesen werden:
Template
<bx:groovy includes="MyReport" format="html" />Groovy-Baustein
String format = includeTag.getStringParameter("format") println("gewähltes Format: $format")
-
-
action- Referenz zum ausführenden Groovy-Action, ansonstennull-
kann z.B. benutzt werden, um Script-Attribute zu setzen oder das Action abzubrechen
action.setScriptAttribute("thing", "value") action.cancel = true
-
-
application- derServletContext -
request- der aktuelleHttpServletRequest-
z.B. um Request-Parameter auszulesen, die der Seite oder dem Action übergeben wurden
String kid = request.getParameter("kid")
-
-
response- die aktuelleHttpServletResponse- falls ein Action verwendet wird:
action.originalResponsebenutzen, um z.B. direkt Bytes zu schreiben
- falls ein Action verwendet wird:
-
session- die aktuelle Session, falls vorhanden -
pageData- enthält Infos zum AufrufString 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
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:
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):
// 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):
def recKunde = tmdKunden["15525037CCB"]
Einen neuen Datensatz erzeugt man mit den üblichen Methoden:
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:
// 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
Durch die angesprochenen Probleme mit Typ-Infos, kann es passieren, dass bei Datum/Zeit-Feldern der Setter uneindeutig ist, falls null übergeben wird (da es dort mehrere setDate Methoden gibt).
Falls eine Variable übergeben wird, die auch null sein kann, wird daher beim Setzen von Datum/Zeit Feldern empfohlen, die setDate Methode aufzurufen und einen expliziten Cast hinzuzufügen:
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 BatixRecords.
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)
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):
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):
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:
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:
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
Nebst den hier am häufigsten genutzten Elementen gibt es noch viele weitere Funktionen und Helfer, siehe dazu auch die offizielle Doku (auf die Version achten).
Syntax
Klammern um Parameter sowie das Semikolon am Ende der Zeile können weggelassen werden. Empfehlung: Klammern verwenden, Semikolon weglassen.
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.
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.).
def i = "5" as int
eineListe.add(12)
Der Gleichheits-Operator in Groovy (==) wird im Hintergrund zu einem .equals() Aufruf umgewandelt.
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).
"str" == 'str' == /str/
Es gibt auch Mehrzeilige Strings. Ein Backslash (\) bewirkt, dass der Zeilenumbruch vor der ersten Zeile im Code nicht mit ausgegeben wird.
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.
def user = "alice"
println("Hi $user")
println("aktueller Timestamp: ${new Date().time}")
Closures
Closures entsprechen in etwa den functions 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.
// 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).
"...".eachLine { line ->
println(line.reverse())
}
Falls die Closure genau ein Parameter übergeben bekommt, so muss dieser nicht benannt werden, der Standardname ist "it".
"...".eachLine {
println(it.reverse())
}
Spaceship-Operator
Vergleiche (compareTo) erledigt der Spaceship-Operator, das vereinfacht die Implementation eines Comparators.
println 5 <=> 10 // Java: 5.compareTo(10)
println "def" <=> "abc" // Java: "def".compareTo("abc")
println null <=> 10 // gibt keine Exception
Beispiel: System Properties filtern
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.
// 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
def a = [1, 2, 3] // eine ArrayList im Hintergrund
println(a[1]) // einfach auf Elemente zugreifen
println([].size()) // eine leere Liste
Map
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.
(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.
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.
println(5 in [1, 5, 10]) // true
Diesen gibt es auch in der verkürzten Variante der for-Schleife.
def a = [1, 5, 10]
for (i in a) {
println(i)
}
Groovy bringt viele Hilfsmethoden für Collections mit.
[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.
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).
// 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.
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.
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.
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
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
In neueren Groovy-Versionen liefert der JsonSlurper eine LazyMap zurück, die nicht serialisiert werden kann (falls etwas in der Session gespeichert werden soll). Die Variante mit HashMap ist noch als JsonSlurperClassic verfübar.
Ein JSON-String ist auch schnell aus normalen Objekten (Strings, Lists, Maps, ...) erzeugt:
JSON schreiben
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
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 Groovy Doku).
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 Nodes aktualisiert oder hinzugefügt werden sollen, wird auch XmlParser empfohlen):
XML lesen (mit XmlParser)
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)
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
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
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.
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
}
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.
Ü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:
String str = null
println(str.getClass().simpleName) // NullObject
Beispielsweise gibt es diese zwei Methoden:
void setDate(String str) { ... }
void setDate(Date date) { ... }
Erfolgt nun in Groovy der Aufruf folgendermaßen:
// 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):
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
Seit Version 2.6.2 ist es möglich die Scriptsprache Groovy 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
- Groovy Syntax und Beispiele
- CMS-spezifische Helfer
- Tips
- Bibliothek – Übersicht
Logging
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)
/* 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)
/* 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
def user = BxUser.findInstance(request)
if (!user) {
logE("no user found")
return
}
logI("found user ${user.id}")
Timings
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
/* 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
// 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:
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
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.
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 <bx:groovy> 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 <%@page session="false"%> hinzufügen. Sonst wird auf der Seite, auf der das JSP eingebunden ist, ein Session-Cookie erzeugt.
Verwendungsmöglichkeiten
Groovy-Code kann in Actions (Actionbaustein "Groovy ausführen") oder in Quelltexten (bx:groovy) 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 auchaction.originalResponseverwendet 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
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
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. |
| ADMINGROUP | Gruppen der User |
| IMGARCHIV | Bilder für Navigation |
| IMGKAT | Kategorien der Bildergalerie |
| IMG | Bilderverknüpfung |
| LOOP | BX-Schleife |
| LOOPELEMENT | Element des LOOP |
| DOC | Verknüpfung der Dokumente |
| DOCARCHIV | Dokument |
| DOCFOLDER | Baumstruktur der Dokumente |
Anschließend kann es sinnvoll sein unter Entwicklertools zu klicken.
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.
VUE
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 Vue (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 Reisekostenabrechnung im neuem CRM. 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 installiert. 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: http://jsfiddle.net/filipelinhares/2eAqE/ (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:
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
<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 v-model 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:
<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 v-for, 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:
"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 v-bind. 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 v-on. 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:
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:
new Vue({
el: "#fzkApp",
data: fzkData
})
Das reicht schon und man erhält seine fertige Komponente. Natürlich gibt es noch mehr Optionen, 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:
new Vue({
// ...
methods: {
addRow: function() {
this.rows.push({
datum: "__." + this.lastMonth,
ausgabe: "",
betrag: ""
});
},
removeRow: function(index) {
this.rows.splice(index, 1);
}
}
})
(splice 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 Lifecycle Hook aufgerufen, welcher feuert, sobald die Vue-Instanz angelegt wurde:
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:
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 Spezial-Properties 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 Vuex 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 Guide (beschreibt die Features und erklärt, wie man etwas macht) und die API Referenz (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 die Doku.
Beispiel (ok wäre dann z.B. ein Boolean in den Daten):
<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:
<!-- 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:
{{ 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 Beispiel.
Apropos Components: Es gibt sehr viele vorgefertigte Komponenten für Vue! Das reicht von Datepickern und Kalendern bis hin zu Bootstrap-Komponenten.
Weitere Links:
https://vuejs.org/ - offizielle Website
https://entwickler.de/online/javascript/vue-js-javascript-framwork-einfuehrung-579850224.html - Einführung auf Deutsch

