Funktionsumfang der Shell-App
Die Shell-App stellt einen äußeren Rahmen zur Darstellung, Navigation und Interaktion mehrerer Ressourcen dar. Du kannst das Bedienkonzept der Ressourcen mithilfe der Shell-App vereinheitlichen.
Technische Hintergrundinformationen
Die Shell-App stellt die Schnittstelle d.api bereit. Apps verwenden diese API u.a. für die Navigation innerhalb der Shell-App.
Verwenden der API-Funktionen
Im Folgenden lernst du die unterschiedlichen Möglichkeiten kennen, die Schnittstellen der Shell-App für deine Anforderungen zu verwenden.
Anzeigen einer Ressource in der Shell-App
Um eine Ressource in der Shell-App anzuzeigen, musst du die d.api im Head-Element der Ressource per Script-Tag einbinden. Beim Laden der Ressource wird während der Initialisierung der d.api kontrolliert, ob um die Ressource herum schon eine Shell-App geladen wurde.
Wenn keine Shell-App gefunden wird, versucht die d.api unter https://_SYSTEMBASE_URI_/shell
die Shell-App aufzurufen und übergibt den relativen Pfad der eigenen Ressource als Fragment. Daraufhin wird die Shell-App geladen, die dann als erste Ressource die ursprünglich aufgerufene Ressource mithilfe des URI-Fragmentes lädt. Die Ressource wird erneut geladen, wodurch auch die d.api erneut initialisiert wird.
Da nun eine Shell-App geladen ist bzw. schon war, wird diese Shell-App in der d.api referenziert und die Funktionsaufrufe an die d.api weitergeleitet.
Einbinden der d.api als Weblink
Die d.api wird über ein CDN (Content Delivery Network) ausgeliefert. Du kannst eine konkrete Version wie folgt einbinden:
<html>
<head>
...
<script src="https://cdn.service.d-velop.cloud/dapi/v2.13.1/dapi.js"></script>
</head>
<body></body>
</html>
Du kannst die neueste Version folgendermaßen einbinden:
<html>
<head>
...
<script src="https://cdn.service.d-velop.cloud/dapi/latest/dapi.js"></script>
</head>
<body></body>
</html>
Hinweis
Für eine konkrete Version wird ein Cache-Header von einem Jahr verwendet, da sich diese Dateien nicht mehr ändern. Für die neueste Version wird der Cache-Header auf 30 Sekunden eingestellt, damit Änderungen spätestens nach 30 Sekunden übernommen werden.
|
Ändern des Titels einer Ressource
Mit der d.api-Funktion dapi.publishTitle(title: string)
kannst du den Titel deiner Ressource jederzeit ändern.
dapi.publishTitle('new resource title');
Hinweis
Wenn ein leerer String übermittelt wird (z.B. wenn ein anzuzeigender Wert nicht eingetragen ist), dann wird in der alten Shell-App anstatt des leeren Strings [ ] angezeigt.
|
Ändern der URI einer Ressource in der Browserhistorie
Mit der d.api-Funktion dapi.publishLocation(uri: string)
kannst du die URI deiner Ressource in der Browserhistorie ändern.
dapi.publishLocation('new resource uri');
Hinweis
Die Uri muss absolut sein.
|
Anzeigen eines globalen Dialogs
Mit der Funktion dapi.openDialog(uri: string, height: number, width: number, absoluteValues?: boolean)
kannst du einen globalen Dialog anzeigen. Ein globaler Dialog wird über die gesamte Shell-App hinweg angezeigt. Dazu musst du eine URI zu den Inhalten im Dialog sowie die Höhe und die Breite des Dialogs angeben. Wenn du für den optionalen Parameter absoluteValue den Wert true übermittelst, werden die Werte für Höhe und Breite als absolute Werte interpretiert (d.h. sie werden direkt in Pixel übersetzt).
dapi.openDialog('/app/dialogresource.html', 30, 40);
Dieser Aufruf erzeugt einen Dialog mit einer Höhe von 30 Prozent und einer Breite von 40 Prozent.
dapi.openDialog('/app/dialogresource.html', 300, 400, true);
Dieser Aufruf erzeugt einen Dialog mit einer Höhe von 300 und einer Breite von 400 Pixeln.
Wichtig
Du solltest globale Dialoge nur verwenden, wenn sich der Inhalt des Dialogs auf die gesamte Shell-App und deren Inhalte bezieht. Für Inhalte, die sich auf die Ressource beziehen, solltest du Dialoge innerhalb von Ressourcen verwenden. So wissen Anwendende, zu welcher Ressource der Dialog gehört. info: Die übermittelten Werte für Höhe und Breite werden beim Erzeugen des Dialogs in entsprechende CSS-Klassen übersetzt. Dadurch können die tatsächlich verwendeten Werte im Browser von den in der Funktion übergebenen Werten abweichen. Wenn für absoluteValue der Wert true angegeben ist, werden die Werte direkt als Pixelwerte verwendet.
|
Um den Dialog zu schließen, können Benutzer einfach neben den Dialog auf den Backdrop (Bereich im Hintergrund) klicken.
Um den Dialog zu schließen, nachdem der Benutzer im Dialog eine Aktion ausgeführt hat, muss deine App dapi.closeDialog()
aufrufen. Wenn diese Funktion aufgerufen wird, ohne dass ein Dialog angezeigt wird, geschieht nichts.
Starten eines Downloads aus einer Ressource heraus
Mit der d.api-Funktion dapi.download( href: string )
wird ein Download in einem versteckten iFrame gestartet.
Hinweis
Der Download darf nur von Haupt- oder Nebenressourcen ausgelöst werden. Ob die Hauptressource im Vollbildmodus ist, spielt keine Rolle.
|
Ermitteln, ob eine Ressource aktuell die Hauptressource ist
Verwende die d.api-Funktion dapi.isMainResource()
, um zu prüfen, ob deine Ressource aktuell die Hauptressource ist. Die Funktion gibt einen boolean-Wert zurück.
Navigieren zur nächsten Ressource
Du kannst die Navigation zu einer anderen Ressource mit einem einfachen Anchor-Tag auslösen, das in der Target-Eigenschaft den Wert dapi_navigate einfügt.
<a href="/path/to/new/resource" target="dapi_navigate">other resource</a>
Du kannst du Funktion auch für Anchor-Tags mit enthaltenen Kindelementen verwenden.
<a href="/path/to/new/resource" target="dapi_navigate">
<div>
<p>
Click me!
</p>
</div>
</a>
Natürlich kannst du auch mit der Funktion dapi.navigate(uri: string)
aus JavaScript heraus eine Navigation auslösen.
dapi.navigate('/path/to/resource');
Schließen einer Ressource
Verwende die d.api-Funktion dapi.closeResourceIfMainResource()
, um eine Ressource per API zu schließen.
dapi.closeResourceIfMainResource();
Die Funktion wird nur dann ausgeführt, wenn die aufrufende Ressource als Hauptressource angezeigt wird. Die Eigenschaft dapi.isMainResource() muss also den Wert true liefern. Ansonsten passiert nichts.
Verhindern, dass eine Ressource geschlossen wird
Mit der d.api-Funktion dapi.setClosable(false)
kannst du festlegen, ob eine Ressource einfach verlassen werden kann. Du kannst einen Callback registrieren, der aufgerufen wird, wenn die Ressource geschlossen werden soll (z.B. in einem Bestätigungsdialog).
Innerhalb dieses Bestätigungsdialogs können Benutzer dann z.B. bestätigen, dass sie die Ressource wirklich verlassen möchten.
dapi.setClosable(false);
dapi.setInterruptNavigationCallback(( invokeFinish ) => { } )
Wenn das Verlassen z.B. nach dem Bestätigen des Dialogs ermöglicht werden soll, muss deine App nacheinander die Funktionen dapi.setClosable( true );
und invokeFinish()
aufrufen.
Diese Funktion wird automatisch von der Shell-App als Parameter übergeben. Die Shell-App versucht dann erneut, die Hauptressource zu schließen.
Der Callback kann aber auch nur eine einfache Ausgabe sein, dass die Ressource nicht verlassen werden kann.
Hinweis
Bitte verwende
|
Anzeigen einer Ressource im Vollbildmodus
Verwende die d.api-Funktion dapi.activateSingleResourceMode()
, um du eine Ressource im Vollbildmodus anzuzeigen.
dapi.activateSingleResourceMode();
Wichtig
Verwende diese Funktion immer mit der
|
Verlassen des Vollbildmodus
Verwende die Funktion dapi.deactivateSingleResourceMode()
, um den Vollbildmodus zu verlassen und in das benutzerspezifische Layout zu wechseln.
dapi.deactivateSingleResourceMode();
Wichtig
Verwende diese Funktion nur, wenn du zuvor mit der Funktion
|
Erhalten einer Benachrichtigung, dass deine Ressource angezeigt wird
Mit der dapi-Funktion dapi.setResourceVisibilityChangedCallback(callback: (isResourceVisible: boolean) => void)
kannst du der Shell-App eine Funktion übergeben, die immer bei Änderungen der Sichtbarkeit der Ressource aufgerufen wird. Dadurch kannst du z.B. nachvollziehen, ob die Ressource ein- oder ausgeblendet wird.
dapi.setResourceVisibilityChangedCallback((isResourceVisible) => {
if (isResourceVisible) {
console.log(`the resource is visible`);
} else {
console.log(`the resource is invisible`);
}
});
Beim Aufruf wird ein Parameter als boolescher Wert an den Callback übergeben. Der Parameter enthält den Wert true, wenn die Ressource sichtbar ist und false, wenn sie nicht angezeigt wird. Mit diesem Aufruf kannst du beispielsweise ein automatisches Aktualisieren der Ressource aussetzen, solange die Ressource ausgeblendet ist.
Wissenswertes zu Kontextaktionen (ContextActions)
In der Shell-App gibt es das Konzept der Kontextaktionen. Das sind Aktionen, die alle in Bezug auf die angezeigte Ressource verwendet werden können. Es gibt navigierende und nicht navigierende Aktionen. Eine navigierende Aktion ist z.B. das Wechseln von einem Dokument aus zu der übergeordneten Akte.
Außerdem gibt es nicht-navigierende Kontextaktionen. Diese Kontextaktionen lösen Aktionen innerhalb der angezeigten Ressource aus, die sich aber nur auf die Ressource selbst auswirken. Eine nicht-navigierende Aktion ist z.B. eine Aufgabe als gelesen zu markieren.
Bereitstellen von Kontextaktionen
Du kannst Kontextaktionen mit dem Link-Tag im Header der Ressource registrieren.
<html>
<head>
...
<link rel="ctxaction" type="text/html" href="/Shell-App/docs/details.html" title="context action name" data-icon="/relative/path/to/ctxAct.png">
</head>
<body></body>
</html>
Du kannst Kontextaktionen auch aus JavaScript heraus registrieren. Verwende für diese Registrierung die d.api-Funktion dapi.setContextActions(contextActions: IContextAction[])
. Du kannst dieser Funktion ein Array von Kontextaktionen übergeben, die dann den Benutzern angezeigt werden. Eine Kontextaktion kann folgende Attribute haben:
interface IContextAction {
/**
* URI of navigation target
*/
href?: string;
/**
* Function to execute if contextAction is invoked.
* @returns {}
*/
callback?: () => void;
/**
* Name of the function to execute if contextAction is invoked.
* NOTE: A function with the corresponding callbackName must be registered first and currently only bridges can register such functions. It is not possible for regular resources.
*/
callbackName? : string;
/**
* Arguments for the callback invocation.
*/
callbackArgs?: any[];
/**
* Title of ContextAction
*/
title: string;
/**
* URI of icon
*/
icon: string;
/**
* Open the reference target of the context action in the outer supply.
*/
openInOuterSupply?: boolean;
}
dapi.setContextActions( [
{
type: "text/html",
href: "relative/path/to/resource[.html]",
title: "ContextActionName",
icon: "relative/path/to/ContextActionIcon.png"
}
] );
Du kannst Javascript verwenden, um auch nicht-navigierende Kontextaktionen zu registrieren.
dapi.setContextActions([
{
title: "Say hello",
icon: "relative/path/to/ContextActionIcon.png",
callback: (args) => {
alert("Hello "+args[0]+"!")
},
callbackArgs: ["you"]
}
]);
Wenn die Kontextaktion Say hello angeklickt wird, wird ein Benachrichtigungsdialog mit der Nachricht "Hello you!" angezeigt.
Hinweis
Das Attribut callbackArgs ist optional und kann auch den Wert undefined enthalten.
|
Ausblenden von Kontextaktionen
Um Kontextaktionen auszublenden, rufe die Funktion dapi.setContextActions()
mit einem leeren Array auf.
dapi.setContextActions([])
Verwenden von d.api-Events
Mitteilen von Änderungen an einer Ressource
Wenn sich der Status einer Ressource geändert hat oder eine Ressource gelöscht wurde, sollten andere Ressourcen mit einer inhaltlichen Abhängigkeit zu dieser Ressource darüber informiert werden. Das ist z.B. hilfreich, damit sich diese anderen Ressourcen selber aktualisieren können.
Mit der Funktion dapi.dispatchResourceEvent(event: IResourceEvent)
kannst du ein entsprechendes Event abschicken. Andere Ressourcen können dann darauf reagieren, wenn sie sich auf diese Events registriert haben. Dazu musst du ein ResourceEvent-Ereignis erzeugen. Das Ereignis erwartet den Eventtyp (changed oder deleted) und die URI der Ressource als Parameter. Mit der dispatchResourceEvent
-Funktion wird das Ereignis anschließend an die registrierten Event-Listener gesendet.
Die URI der Ressource ist notwendig, damit registrierte Event-Listener entscheiden können, ob das Ereignis relevant ist oder ignoriert werden kann.
Reagieren auf Änderungen in anderen Ressourcen
Du kannst auf Änderungen in anderen Ressourcen reagieren, indem du dich mit der Funktion dapi.addResourceEventListener(eventType: string, callback: (event: IResourceEvent) => void)
auf ResourceEvent-Ereignisse registrierst.
Der Eventtyp hat folgende Attribute:
interface IResourceEvent {
/**
* Name of the event.
* - changed : the resource has been changed
* - deleted : the resource has been deleted
*/
name: string;
/**
* uri of affected resource.
*/
uri: string;
}
Wenn ein entsprechendes Ereignis abgeschickt wird, wird der Callback aufgerufen. Darin kannst du dann auf die Änderungen an der Ressource oder das Löschen reagieren.
Als Beispiel nehmen wir an, es gibt eine Ressource /app/todos.html
, in der Aufgaben aufgelistet sind.
Ein Klick auf eine Aufgabe ruft eine d.api-Navigation zu der jeweiligen Detailressource auf.
Die Ressource /app/todos.html
hat folgende Event-Listener für Ressourcen registriert:
dapi.addResourceEventListener( 'deleted', function ( resourceEvent ){
var $todos = dux.query( 'tr' );
$todos.each( function ( idx, todo ){
var link = dux.query( todo ).data( 'href' );
if ( link === resourceEvent.uri ) {
dux.query( todo ).remove();
dapi.navigate( 'dapi_blank' );
}
} );
} );
dapi.addResourceEventListener( 'changed', function ( resourceEvent ){
var $todos = dux.query( 'tr' );
$todos.each( function ( idx, todo ){
var link = dux.query( todo ).data( 'href' );
if ( link === resourceEvent.uri ) {
var $task = dux.query( todo ).children( 'td' ).eq( 1 );
if ( !dux.query( todo ).hasClass( 'text-muted' ) ) {
dux.query( todo ).addClass( 'text-muted' );
$task.html( '<p class="small">Done</p>' + $task.text() );
}
}
} );
} );
In der Detailressource /app/task1.html
gibt es eine Kontextaktion Löschen, die ein deleted-Event auslöst. Mit diesem Event wird folgende Funktion aufgerufen:
dapi.dispatchResourceEvent( new dapi.ResourceEvent( 'deleted', window.location.pathname ) );
Es gibt außerdem eine Schaltfläche Aufgabe erledigt, welche beim Anklicken folgende Funktion aufruft:
dapi.dispatchResourceEvent(new dapi.ResourceEvent('changed', window.location.pathname));
Beim Klick auf Aufgabe erledigt wird in der /app/todos.html
-Ressource das Element in der Liste, welches auf /app/task1.html
verweist, als erledigt markiert.
Beim Klick auf die Kontextaktion Löschen wird das Listenelement entfernt und es wird zu einer leeren Ressource navigiert.
Hinweis
Die Umsetzung orientiert sich an der Implementierung der Ereignisverarbeitung im Browser (vgl. Creating and triggering events).
|
Verwenden des neuen Bedienkonzepts
Anzeigen einer Ressource im neuen Bedienkonzept
Mittlerweile gibt es ein neues, moderneres Bedienkonzept der Shell-App. Dieses basiert auf Googles Material Design, weshalb wir empfehlen, auch für die Ressourcen Material Design zu verwenden.
Eine Ressource wird im neuen Bedienkonzept angezeigt, wenn im Header das Attribut window.nextGenerationApp den Wert true enthält.
<script>
window.nextGenerationApp = true;
</script>
Du musst dieses Attribut vor der Einbindung der d.api einfügen.
Verwenden der Seitenleiste
Die Seitenleiste (sidebar) ist der Bereich, der am Rand der Shell-App angezeigt wird.
Anzeigen eigener Inhalte in der Seitenleiste
Jede Ressource kann eine Seite als Inhalt für die Seitenleiste definieren. Verwende zum Anzeigen von Inhalten in der Seitenleiste die d.api-Funktion dapi.setSidebarContent(uri: href)
.
dapi.setSidebarContent('/app/Sidebar.html');
Leeren der Seitenleiste
Du kannst die Seitenleiste leeren, um sie in den Zustand vor dem Hinzufügen des Inhalts zu versetzen. Verwende zum Leeren der Seitenleiste die Funktion dapi.setSidebarContent(uri: href)
mit der URI about:blank
:
dapi.setSidebarContent('about:blank');
Öffnen der Seitenleiste
Verwende die d.api-Funktion dapi.openSidebar()
zum Öffnen der Seitenleiste. Mit dieser Funktion wird die Seitenleiste aufgeklappt.
Minimieren der Seitenleiste
Verwende die d.api-Funktion dapi.closeSidebar()
zum Minimieren der Seitenleiste. Mit dieser Funktion wird die Seitenleiste eingeklappt.
Reagieren auf Änderungen der Sichtbarkeit der Seitenleiste
Verwende die d.api-Funktion dapi.setSidebarVisualStateChangedCallback( callback: (visual: boolean) => void )
, um auf Änderungen an der Sichtbarkeit zu reagieren. Der Callback wird immer ausgeführt, wenn die Seitenleiste geöffnet oder geschlossen wird.
Austauschen von Daten zwischen der Seitenleiste und der angezeigten Ressource
Mit der d.api-Funktion dapi.transferDataObject( dataObj: object )
kann ein beliebiges Objekt von der Seitenleiste zur Hauptressource oder von der Hauptressource zur Seitenleiste übermittelt werden.
Mithilfe der d.api-Funktion dapi.addDataObjectListener( callback: (dataObj) => void )
kannst du auf diese Übermittlung reagieren.
Verwenden des Inner Supply (Anzeigebereich)
Der Inner Supply wird neben der Hauptressource angezeigt. Er kann z.B. eine geöffnete Aufgabe sein. Der Inner Supply befindet sich unter der App-Leiste (TopAppBar) der Shell-App und beinhaltet eine automatisch benannte App-Leiste mit dem Titel der ausgewählten Ressource (z.B. der Titel einer Aufgabe). Verwende den Inner Supply für Inhalte, die sich direkt auf die Hauptressource beziehen, wie z.B. eine Detailansicht. Die Inhalte sollten möglichst nur darstellend sein und keine größeren Aktionen beinhalten. Falls solche Aktionen oder eine direkte Weiternavigation nötig sind, verwende den Outer Supply.
Hinweis
Eine Navigation aus dem Inner Supply heraus ist nicht möglich. Die Ansicht dient lediglich zur Darstellung von weiteren Informationen und ist für sich genommen keine Ressource.
|
Öffnen des Inner Supply
Du kannst den Inner Supply mit der d.api-Funktion dapi.openInnerSupply(uri: string)
öffnen.
dapi.openInnerSupply('/app/InnerSupply.html');
Hinweis
Falls der Outer Supply noch geöffnet ist, wird er mit dieser Funktion geschlossen.
|
Schließen des Inner Supply
Du kannst den Inner Supply mit der d.api-Funktion dapi.closeInnerSupply()
schließen.
Verwenden des Outer Supply (Anzeigebereich)
Der Outer Supply befindet sich ebenfalls neben der Hauptressource, im Gegensatz zum Inner Supply wird der entsprechende Inhalt aber über die App-Leiste hinaus angezeigt. Er dient als eine Art kleinere Ressource. Der Inhalt muss sich nicht direkt auf die Hauptressource beziehen. Eine Navigation aus dem Outer Supply heraus ist möglich.
Öffnen des Outer Supply
Du kannst den Outer Supply mit der d.api-Funktion dapi.openOuterSupply(uri: string)
öffnen.
dapi.openOuterSupply('/app/OuterSupply.html');
Hinweis
Wenn der Inner Supply noch geöffnet ist, wird er mit dieser Funktion geschlossen.
|
Schließen des Outer Supply
Du kannst den Outer Supply mit der d.api-Funktion dapi.closeOuterSupply()
schließen.