Widgets
Calendar Timeline (Beta)
Custom Calendar Timeline
AI Defaults (read first)
uniqueId: Required,
"timeline-" + Nr.height: Use
"700px"or"100%"when embedded.timeZoneBalance: Set
-1for German timezone.header:
dateSettings.header.days(Tages-Labels, Uhrzeit: gleiches Objekt statttitle); optionalheader.months/header.weeks(übergeordnete Zeilen). OptionalalignX,sticky: "left",stickyPadding.columns: Label-Spalten links (Titel im Header, optional
width); mindestens eine Spalte.items: Ressourcen-Zeilen; jedes Item braucht
id(eindeutig pro Zeile) undtimeEntries. Verschachtelung überitems(max. eine Ebene unterhalb des Parents).dateFrom/dateTo: Actual date values in timeEntries, not strings.
dayWidth: Default
"120px", increase for detailed timelines.dragAction:
recordId+ optionalresourceFieldfür vertikal; nur gleiche Verschachtelungstiefe (_depth, z. B. Mitarbeiter ↔ Mitarbeiter auch über Teams hinweg). Optionalenabled: falseschaltet Drag für diesen Balken aus.Uhrzeit mode: Activated by
timeSettings, usescolumnWidthinstead ofdayWidth.timeFrom/timeToin milliseconds.Zellen-Hintergrund:
dateSettings.highlights[]mit optionalapplyToRows: true; optionalitems[].highlightspro Zeile (date,dateFrom/dateTobzw.timeFrom/timeTo).Ghost (Neueinträge): Optional pro Zeile
items[].ghostmittitle,actions, optionalposition(DefaultbottomRight: kleiner Plus-Button unten rechts in der Spalte), optionalstyles. Klick führtghost.actionsaus. Positionen außertimeEntry: Plus erscheint erst bei Maus über der Spalte (Spalte wird per Zeilen-mousemoveerkannt); Touch: Ghost bleibt sichtbar.timeEntry: siehe Abschnitt ghost (Idle nur in leeren Spalten). Details im Abschnitt ghost.
Mit dem Widget Custom Calendar Timeline bringst du eine ressourcenbasierte Kalenderansicht in deine Ninox-Datenbank. Ressourcen (z. B. Mitarbeiter, Räume, Fahrzeuge) werden als Zeilen dargestellt, die Tage oder Uhrzeiten als Spalten. Termine erscheinen als horizontale Balken – ideal für Einsatzplanung, Kapazitätsübersicht oder Ressourcenplanung.
💡 Was du mit Custom Calendar Timeline machen kannst:
Ressourcen als Zeilen: Jede Zeile steht für eine Ressource (Person, Raum, Team, Fahrzeug).
Termine als Balken: Einträge werden horizontal über die Tage gespannt – mit oder ohne Uhrzeit.
Uhrzeitmodus: Zeige statt Tagen Uhrzeitspalten an – ideal für Flottendiagramme und Tageseinsatzplanung.
Hierarchische Einträge:
itemsmit Unter-items(eine Ebene), flache Zeilen mit Einrückung – Datenmodell wie Gantt.Drag & Drop: Verschiebe Termine horizontal (Datum/Uhrzeit ändern) oder vertikal (Ressource/Zeile wechseln).
Mehrtägige Einträge: Zeige Projekte, Urlaub oder längere Blöcke über mehrere Tage.
Hervorhebung: Markiere Wochenenden, bestimmte Stunden oder besondere Tage farblich.
Individuelles Styling: Passe Farben, Breiten und Höhen an dein Design an.
📅 Custom Calendar Timeline eignet sich besonders für Einsatzplanung, Schichtpläne, Kapazitätsübersichten und Flottendiagramme – überall dort, wo du Ressourcen und Termine im Zeitverlauf im Blick behalten willst.
Anwendungscode
Allgemeine Settings
uniqueId
Eindeutige Kennung des Widgets. Wichtig, wenn mehrere Timeline-Widgets auf einer Seite verwendet werden.
timeZoneBalance
Zeitzonenkorrektur in Stunden. Für Deutschland oft -1, um die Anzeige an MEZ/MESZ anzupassen.
lang
Sprache für Datumsformatierung (z. B. Wochentagsnamen).
height
Höhe des Widget-Containers.
styles
Individuelle Styles für den äußeren Container (z. B. Hintergrundfarbe).
dateSettings – Zeitraum & Darstellung
startDate
Startdatum der Timeline. Ab diesem Tag werden die Spalten angezeigt.
duration
Anzahl der angezeigten Tage. Wird ignoriert, wenn endDate gesetzt ist.
endDate
(Optional) Enddatum der Timeline. Hat Vorrang vor duration.
highlights
Farbliche Hervorhebung bestimmter Tage – z. B. Wochenenden oder Feiertage.
weekday: 0 = Sonntag, 6 = Samstagdate: Konkretes DatumdateFrom/dateTo: Datumsbereich (optional statt einzelnemdate)color: CSS-Farbe (HEX oder rgba)applyToRows(optional):true– dieselbe Hervorhebung wird in der Zeilenfläche (hinter den Termin-Balken) für alle Ressourcen-Zeilen gezeichnet, nicht nur in der Kopfzeile. Ohne dieses Flag bleibt das Verhalten wie bisher (nur Header).
Im Uhrzeitmodus zusätzlich:
hour: Stunde (0–23) für Hervorhebung bestimmter Stunden-SpaltentimeFrom/timeTo: Zeitbereich in Millisekunden (wie beitimeEntries), z. B. Mittagspause
highlights pro Zeile (items[].highlights)
Neben den globalen dateSettings.highlights kann jede Ressourcen-Zeile ein eigenes Array highlights haben – z. B. Urlaub oder Krankenstand nur für einen Mitarbeiter. Die gleichen Felder wie oben gelten; applyToRows ist hier nicht nötig (gilt immer nur für diese Zeile).
Uhrzeitmodus: z. B. Sperr- oder Wartungsfenster mit timeFrom / timeTo.
header
Der header-Block steuert alle Kopfzeilen der Timeline. Er besteht aus drei optionalen Unterblöcken: months, weeks und days. Alle drei haben dieselbe Struktur und können unabhängig voneinander aktiviert werden. Die Reihenfolge im Widget ist immer: Monate → Kalenderwochen → Tage (von oben nach unten).
Alle drei Unterblöcke sind optional. Wird ein Block weggelassen, ist er nicht aktiv. days entspricht dem bisherigen header.title-Verhalten (Backward-Kompatibilität: header.title wird weiterhin unterstützt).
Gemeinsame Properties (je Unterblock):
Property | Beschreibung |
|---|---|
|
|
| Anzeigetext mit Platzhaltern (s. u.) |
|
|
| Schriftgröße, z. B. |
| Schriftfarbe |
| Schriftstärke, z. B. |
| Hintergrund der gesamten Zeile bzw. Monats-/KW-Gruppe. |
| Hervorhebungen pro Monats- bzw. KW-Gruppe (s. u.) – nur für |
| Optional für |
| Zusätzlicher Abstand in px (Zahl) oder z. B. |
Hinweis: dateSettings.highlights färben pro Tag die Tages-Headerzelle (div, optional mit applyToRows auch die Zeilenfläche). In Kombination mit header.days.sticky: "left" bitte backgroundColor-Hinweis in der Tabelle beachten.
Platzhalter für days.label:
##weekDayShort##– Kurzer Wochentag (Mo, Di, …)##weekDayLong##– Langer Wochentag (Montag, Dienstag, …)##day##– Tag (1–31)##monthShort##– Kurzer Monat (Jan, Feb, …)##monthLong##– Langer Monat (Januar, Februar, …)##year##– Jahr
Platzhalter für weeks.label:
##week##– Kalenderwochennummer (01–53, zweistellig mit führender Null)##year##– Jahr
Platzhalter für months.label:
##monthLong##– Langer Monatsname (Januar, Februar, …)##monthShort##– Kurzer Monatsname (Jan, Feb, …)##year##– Jahr
highlights pro Unterblock:
months.highlights:{ month: N }– N = 1 (Januar) bis 12 (Dezember)weeks.highlights:{ week: N }– N = ISO-Kalenderwochennummer
Layout-Parameter
dayWidth
Breite einer Tages-Spalte.
rowHeight
Höhe einer Ressourcen-Zeile. "auto" passt sich dem Inhalt an.
labelWidth
Standard-Breite für eine Label-Spalte, wenn columns fehlt oder wenn in columns[i] kein width gesetzt ist. Standard: "120px".
currentTime
Farbe des Balkens, der die aktuelle Uhrzeit markiert. Leer oder false blendet ihn aus.
items – Ressourcen und Termine
items ist ein Array von Ressourcen-Zeilen. Jede Zeile hat timeEntries (Balken). Optional: items (Kinder, eine Ebene) und columns (Zelltexte pro Label-Spalte).
Struktur einer Zeile
id (Pflicht): Eindeutige ID (z. B. Record-Nr). Wird für Drag & Drop (
resourceField) und collapsible benötigt.title / subtitle: Fallback für die erste Label-Spalte, wenn
columnsfehlt oder die erste Zelle leer ist.fontSize / fontWeight (optional, Item-Ebene): Standard-Typo für alle Label-Zellen dieser Zeile, sofern weder Top-Level-Spalte noch
columns[i]etwas setzen. Reihenfolge der Priorität (höher zuerst):columns[i]→ ItemfontSize/fontWeight→styles.fontSize/styles.fontWeight.columns (pro Zeile): Ein Objekt pro Label-Spalte (gleiche Anzahl wie Top-Level
columns):title,subtitle, optionalcustomLayout(HTML für diese Zelle),actions, optionalalignX,alignY,fontSize,fontWeight.styles: Optional (z. B. Zeilen-Hintergrund;
fontSize/fontWeighthier wirken als letzte Typo-Fallbacks).highlights (optional): Zellen-Hintergrund für diese Zeile (Abwesenheiten, Sperrzeiten); siehe Abschnitt highlights pro Zeile.
timeEntries: Termine/Balken in dieser Zeile. Horizontaler Abstand: fest 4px zur Spaltenkante (wie das Zeilen-Padding oben/unten); bei mehrspaltigen Balken nur am äußeren Anfang und Ende, nicht zwischen den Tagen (nicht über
timeEntries[].stylesänderbar).items: Optional. Unterzeilen (eine Ebene).
Struktur eines timeEntry (Termin/Balken)
title: Text im Balken, oder Objekt
{ value: …, width: … }(siehe unten). Bei Zeitangaben kann##entrytime##verwendet werden.subtitle: Optional. Zweiter Textblock im Balken (String oder Objekt wie bei title).
direction (optional):
"horizontal"(Standard) oder"vertical"– legt fest, ob Titel- und Subtitle-Block nebeneinander oder untereinander stehen.dateFrom, dateTo: Start- und Enddatum (Pflicht).
timeFrom, timeTo: Optional. Uhrzeit in Millisekunden (0 = Mitternacht). Ohne Angabe wird der Eintrag als ganztägig dargestellt.
styles: CSS-ähnliche Eigenschaften (backgroundColor, color, borderRadius, padding).
dragAction: Konfiguration für Drag & Drop.
actions: Array von Aktionen beim Klick auf den Balken (wie bei anderen Widgets). Das frühere einzelne Feld
clickActionwird weiterhin unterstützt und wie ein Eintrag inactionsausgeführt.customLayout: Optional. Eigenes Layout statt title/subtitle/value.
value: Optional. Zusätzlicher HTML-Inhalt im Balken (nach dem Titel/Subtitle-Block).
Objekt-Form für title / subtitle: { value: TextOderHtml, width: "fraction" | "auto" | CSS-Länge }
value: Anzuzeigender Text oder HTML (wie bisher);##entrytime##möglich.width*(optional, Default"fraction")**:"fraction"– nutzt den verbleibenden Platz in der Zeile; langer Text wird mit Ellipsis gekürzt."auto"– Inhaltsbreite; schrumpft nicht zugunsten des Partners (z. B. für Uhrzeiten, die voll sichtbar bleiben sollen). Sehr langer Text kann am Balkenrand trotzdem mit Ellipsis enden.CSS-Länge (z. B.
"72px","4.5rem") – feste Basisbreite (flex-basis) für diesen Block.
Sind title und subtitle nur Strings (ohne Objekt) und ist direction nicht gesetzt, entspricht die Darstellung dem bisherigen Verhalten (inkl. Ellipsis). Sobald mindestens ein Feld die Objekt-Form nutzt oder direction: "vertical" gesetzt ist, steuert das Widget die Aufteilung per Flex.
styles – Styling der Termin-Balken
dragAction – Verschieben von Terminen
Definiert, welche Felder beim Ziehen aktualisiert werden.
recordId: Record-ID des Termins (meist
Nr).dateFrom, dateTo: Feld-IDs für Start- und Enddatum. Werden beim horizontalen Verschieben aktualisiert.
resourceField: Optional. Feld-ID für die Ressource (z. B. Bearbeiter). Wird beim vertikalen Verschieben (Zeilenwechsel) mit der
idder Ziel-Zeile aktualisiert – nur wenn Start- und Zielzeile dieselbe Tiefe in deritems-Hierarchie haben (_depthgleich). Erforderlich z. B., damit kein Termin von einer Team-Zeile auf eine Mitarbeiter-Zeile (oder umgekehrt) gezogen wird; Mitarbeiter unter Team A → Mitarbeiter unter Team B ist erlaubt.enabled: Optional.
false: kein Drag für diesen Balken (z. B. Parent-Summen). Wenn weggelassen, ist Drag aktiv, sobalddragActiongesetzt ist.
⚠️ Hinweis: Ohne dragAction ist Drag & Drop deaktiviert. Vertikales Ziehen zwischen verschiedenen Tiefen (z. B. Team-Zeile ↔ Mitarbeiter-Zeile) ist nicht möglich; innerhalb derselben Tiefe (z. B. nur Mitarbeiter-Zeilen) auch über verschiedene Parents (Teams).
actions – Klick auf Termin
type:
"popup"öffnet den Datensatz in einem Popup.recordId: Record-ID des angeklickten Termins.
Mehrere Einträge im Array werden nacheinander ausgeführt. Legacy: Ein einzelnes clickAction-Objekt (ohne Array) funktioniert weiterhin.
actions – Klick auf Label-Zelle
In items[].columns[i] kann optional actions gesetzt werden. Ist das Array nicht leer, löst ein Klick auf die Zelle dieselben Ninox-Aktionen aus. Hinweis: In der ersten Label-Spalte hat bei eingeklappten Gruppen (collapsible) der Klick Vorrang zum Auf-/Zuklappen; dort werden keine zusätzlichen actions auf der Zelle ausgeführt.
columns gehört zur jeweiligen Zeile unter items. Ein Klick auf die zweite Spalte (hier ⌂) öffnet den Datensatz der Zeile (Nr). Beliebig viele Einträge im actions-Array werden nacheinander ausgeführt.
ghost – Zeilen-Balken für Neueinträge (Wrapper)
Auf Ebene jedes Eintrags in items[] (nicht in columns[]) kann optional ein Objekt ghost gesetzt werden – unabhängig pro Zeile (Ressource). Eine Zeile ohne ghost hat keinen Anlege-Streifen.
Felder:
title– optional, wird als Browser-Tooltip (title-Attribut) auf dem Plus-Button genutzt (z. B. „Termin anlegen“).position– optional, steuert Anzeige und Layout des Ghost-Buttons pro Spalte:bottomRight(Default, kann weggelassen werden) – kleiner quadratischer Button (28×28 px), absolut in der jeweiligen Spalte unten rechts; nimmt keine volle Spaltenbreite ein. Der Button sitzt außerhalb des CSS-Grids der Zeile (absolut zur Zeile), damit timeEntries in derselben Grid-Zeile bleiben wie ohne Ghost. Stacking: der Button liegt knapp über normalen Balken (z-index11), unter Balken-Hover (10) und aktivem/Drag-Balken (100).bottomLeft,topRight,topLeft– gleicher Button, andere Ecke der Spalte.timeEntry– klassisches Verhalten: volle Spaltenbreite in der ersten Grid-Zeile (mit 4px horizontalem Abstand wie die Termin-Balken), schiebt sichtbare Termin-Balken in die nächste Zeile (align-content: startauf der Zeile).
actions– Pflicht, mindestens eine Ninox-Aktion; typischerweisetype: "create"mit vorbefüllten Feldern. Ein Klick auf den Plus-Button führt diese Aktionen mit dem Wert dieser Spalte aus (siehe Platzhalter).styles– optional, Objekt mit CSS-Eigenschaften in camelCase (wie beitimeEntries[].styles), z. B.backgroundColor,fontColor(Textfarbe inkl. Plus-Icon übercurrentColor),fontSize,fontWeight,borderRadius,paddingX/paddingY(werden zupaddingzusammengesetzt) oderpadding(Shorthand),border,boxShadow. Legacy-colorwird wiefontColorauf die Schriftfarbe gemappt; istfontColorgesetzt, hat es Vorrang. Werden auf den Button gelegt;gridColumn/gridRowsetzt das Widget für die Rasterplatzierung (überschreibt ggf. eigene Werte instyles).
Darstellung (Default bottomRight u. a.): Pro Spalte ein absolut positionierter, klick-durchlässiger Bereich über der Zeile (kein Grid-Item – verhindert Verschiebung der Balken). Der Plus-Button ist weiß, mit leichtem Schatten, Ecke per position. Spalten-Hover (Maus in der Spalte): Button wird sichtbar mit halbtransparentem weißem Hintergrund und backdrop-filter-Weichzeichnung (Frosted-Glass). Direkt über dem Button: undurchsichtiges Weiß, kein Blur – volle Lesbarkeit. Über styles kannst du z. B. backgroundColor setzen (überschreibt die Standardfarben).
Darstellung (timeEntry): Wie ein schmaler Balken über die Spaltenbreite in Zeile 1 (mit 4px Rand links/rechts wie die Termin-Balken); timeEntries der Zeile beginnen darunter.
Sichtbarkeit / Hover:
Alle Positionen außer
timeEntry: Der Plus-Button ist standardmäßig unsichtbar und erscheint erst, wenn die Maus irgendwo in dieser Tag-/Zeitspalte ist (auch über einem Balken); die Spalte wird anhand der Mausposition auf der Zeile ermittelt. Auf Touch-Geräten (kein präzises Hover) bleiben die Ghost-Buttons sichtbar.timeEntry: Für jede Spalte wird getrennt geprüft, ob ein sichtbarer Termin-Balken in die Spalte reicht. Ohne Balken: bei@media (hover: hover)ist der Ghost-Balken zunächst per Opacity verborgen, bis die Maus über die Ghost-Zelle fährt. Mit Balken in der Spalte: der Ghost-Balken bleibt sichtbar. Auf Touch bleiben Ghost-Elemente sichtbar.
Platzhalter (in beliebigen String-Werten innerhalb der Action, rekursiv):
##columnValue##– Millisekundenwert der Spalte unter dem Klick: im Tag-Modus Tagesbeginn (startDate+ Spaltenindex), im Uhrzeit-Modus Beginn des Zeitslots (startTime+ Index ×amount).##clickedDate##– Alias mit gleicher Semantik (Kompatibilität zu Calendar Grid / Week).
Klicks auf Termin-Balken (timeEntries) lösen weiterhin nur die actions des jeweiligen Balkens aus, nicht ghost.actions.
Beispiel – Uhrzeitmodus: ##columnValue## ist der Beginn des geklickten Zeitslots in Millisekunden (wie bei timeFrom in den Balken).
Alternativ kannst du ##clickedDate## statt ##columnValue## verwenden – beide werden gleich aufgelöst.
weekStart
Starttag der Woche (0 = Sonntag, 1 = Montag, …). Beeinflusst die Sortierung der Tage.
timeSettings – Uhrzeitmodus (Time Mode)
Wenn du statt Tagen Uhrzeiten als Spalten anzeigen möchtest, kannst du den Uhrzeitmodus aktivieren. Das ist ideal für Flottendiagramme, Schichtpläne oder Tageseinsatzplanung, bei denen die X-Achse einen einzelnen Tag darstellt.
Der Uhrzeitmodus wird automatisch aktiviert, sobald timeSettings gesetzt ist – oder explizit mit mode: "time".
startTime
Ab welcher Stunde die Zeitleiste beginnt (z. B. 6 = 06:00 Uhr).
duration
Wie viele Stunden angezeigt werden (z. B. 12 = 12 Stunden ab startTime).
amount
Spaltenintervall in Stunden. Bestimmt die Feinheit der Zeiteinteilung.
1= Stundenspalten (08:00, 09:00, …)0.5= 30-Minuten-Spalten (08:00, 08:30, 09:00, …)0.25= 15-Minuten-Spalten (08:00, 08:15, 08:30, …)
Header-Platzhalter im Uhrzeitmodus
Im Uhrzeitmodus stehen zusätzliche Platzhalter für dateSettings.header.title.label zur Verfügung:
##hour##– Stunde mit führender Null (06, 07, …)##minute##– Minute mit führender Null (00, 15, 30, …)##time##– Vollständige Uhrzeit (06:00, 08:15, …)
columnWidth
Breite einer Zeitspalte (Alias für dayWidth im Uhrzeitmodus).
timeEntries im Uhrzeitmodus
Im Uhrzeitmodus verwenden timeEntries statt dateFrom/dateTo die Felder timeFrom/timeTo (in Millisekunden ab Mitternacht):
💡 Umrechnung: Stunden × 3600000 (z. B. 07:30 = 7.5 × 3600000 = 27000000)
Drag & Drop im Uhrzeitmodus
Im Uhrzeitmodus werden beim Drag & Drop timeFrom/timeTo statt dateFrom/dateTo aktualisiert:
columns (Top-Level)
Definiert die linken Label-Spalten (neben dem Zeitbereich). Pro Eintrag im Array: title (erscheint im Header links oben), optional subtitle, optional width (CSS-Breite, z. B. "200px"). Fehlt width, gilt labelWidth (Standard 120px).
Optional: alignX: "left" "center" "right" (Standard left), alignY: "top" "center" "bottom" (Standard center) – Ausrichtung von Header und Zellinhalt in dieser Spalte. fontSize und fontWeight (CSS-Werte, z. B. "13px", "600" oder "bold") gelten für Header und Zellen dieser Spalte, sofern weder items[].columns[i] noch Item-fontSize/fontWeight gesetzt sind. Pro Zelle kann in items[].columns[i] jeweils alignX, alignY, fontSize, fontWeight überschrieben werden.
Ohne columns oder leeres Array: eine Spalte mit labelWidth.
items – Datenzeilen und Verschachtelung
Alle Ressourcen werden einheitlich items genannt. Flache Liste: items: [{ id, title, subtitle, timeEntries, … }].
Verschachtelung (eine Ebene): Ein Item kann items: [...] enthalten. Parent und Kinder werden als eigene Zeilen untereinander gerendert; die erste Label-Spalte ist bei Kindern eingerückt. Tiefer als eine Ebene ist in der Timeline aktuell nicht vorgesehen (Datenstruktur kann später erweitert werden).
items[].columns (pro Zeile): Array mit einem Eintrag pro Label-Spalte (gleiche Länge wie Top-Level columns). Felder pro Zelle: title, subtitle, optional customLayout, optional actions, optional alignX / alignY, optional fontSize / fontWeight (höchste Priorität für Typo). Danach greifen Item-fontSize/fontWeight, dann Top-Level-Spalte, dann styles. Fehlende Einträge → leere Zelle. Fallback: Fehlt columns oder die erste Zelle hat keinen Inhalt, werden title/subtitle des Items nur für die erste Spalte verwendet.
Parent mit Unterzeilen: Die Parent-Zeile hat timeEntries wie jede andere Zeile (z. B. Summen-Balken). Kinder stehen in items und haben eigene columns-Werte.
collapsible – Gruppen ein- und ausklappen
Wenn du hierarchische Einträge (items mit Unter-items) nutzt, kannst du die Parent-Zeile (z. B. Team- oder Fahrzeugname) per Widget-Prop ein- und ausklappen. Der Zustand wird pro uniqueId im Browser persistiert (localStorage).
Konfiguration
Property | Bedeutung |
|---|---|
|
|
| (Optional) |
| (Optional) HTML/SVG für aufgeklappt (Standard: Chevron unten). |
| (Optional) HTML/SVG für eingeklappt (Standard: Chevron rechts). |
Gilt für Zeilen mit
items(Kinder).iddes Parent-Items muss eindeutig sein (Klappzustand).stylesam Parent/Kind wirken auf die gesamte Label-Zeile (Hintergrund der Zellen).
Mit dem Custom Calendar Timeline bringst du ressourcenbasierte Planung und volle Flexibilität in deine Ninox-Datenbank – ideal für Einsatzplanung, Kapazitätsübersicht, Ressourcenmanagement und Flottendiagramme.
Happy Widgeting 🥳