Single Page Applikationen und Open Text Web Site Management, geht das überhaupt? Dies war eine Fragestellung eines Proof of Concepts, den ich zuletzt durchgeführt habe. Die Antwort? Ja. Aber fangen wir ganz am Anfang an.
Hier kann man Wikipedia gut zitieren: "Als Single-Page-Webanwendung [...] wird eine Webanwendung bezeichnet, die aus einem einzigen HTML-Dokument besteht und deren Inhalte dynamisch nachgeladen werden. ... Diese Webseite wird lediglich zur Laufzeit der Applikation dynamisch erweitert. ...", unter https://de.wikipedia.org/wiki/Single-Page-Webanwendung (abgerufen am 22.02.2017).
Eine Single Page Applikation baut sehr stark auf JavaScript auf und lädt alle Inhalte per AJAX nach. Trotzdem möchte man die Usability nicht einschränken und dem Nutzer ermöglichen, direkt auf bestimmte Seiten zuzugreifen und sich auch Bookmarks setzen zu können.
Um beiden Anforderungen gerecht zu werden, können AngularJS v1.2.13 und UI Router v0.2.8 genutzt werden. Diese zwei Frameworks bzw. Erweiterungen habe ich auch für den PoC genutzt.
Den Klick-Dummy habe ich für meine Zwecke sehr übersichtlich gehalten. Nach dem der Rahmen erstellt ist, kommt nur noch ein DIV in das HTML
HTML <div class="container"> <div ui-view></div> </div>
der Rest wird über das JavaScript gelöst.
JavaScript var app = angular.module("routing", ['ui.router']); app.config(function ($stateProvider, $urlRouterProvider) { $urlRouterProvider.otherwise('/home'); $stateProvider .state('home', { url: '/home', templateUrl: 'partial/home.html' }) .state('about', { url: '/about', templateUrl: 'partial/about.html' }); })
Wie man hier sieht, sind zwei Seiten definiert. Bei Klick auf den gewünschten Navigationspunkt
HTML <a ui-sref="about">About</a>
wird die im Parameter templateUrl definierte Seite in das DIV geladen.
Die erste Schwierigkeit im Zusammenhang mit dem CMS besteht darin, dass das CMS darauf ausgelegt ist, komplette Webseiten darzustellen. Hier muss man von diesem Konzept abweichen und die Masterpage nur noch mit dem Inhalt bestücken, welcher in dem DIV dargestellt wird. Zusätzlich dazu benötigt man dann eine Rahmen-Seite, die das HTML-Body-Tag zu Verfügung stellt.
Bei den Masterpage Instanzen kann man wie gewohnt mit dem Navigation Manager das Projekt strukturieren. Somit bleiben noch drei Herausforderungen die gelöst werden müssen:
Als erstes ist zu beachten, dass der Name jedes Navigationspunktes eineindeutig sein muss. Für den PoC habe ich es mir an der Stelle einfach gemacht und habe mich entschieden, hier die GUID zu verwenden. Da das JavaScript im Grunde die Navigation wiederspiegelt, fiel die Entscheidung sehr schnell, diese komplett über RenderTags schreiben zu lassen.
JavaScript var app = angular.module("routing", ['ui.router']); app.config(function ($stateProvider, $urlRouterProvider) { $urlRouterProvider.otherwise('/<%!! Context:Pages.GetPage(Guid:A7DC6CC5060A4CC9A1F8B404BCF76D42).Id !!%>'); $stateProvider <reddot:cms><navigation areaname="appRoutes" pageguid="Guid:A7DC6CC5060A4CC9A1F8B404BCF76D42" usehiddenindexes="Bool:True" /></reddot:cms>; })
Hier ist nur zu beachten, dass die JavaScript-Datei selbst nicht in der Navigationsstruktur hängt und somit über den Parameter pageguid
der Startpunkt der Navigation festgelegt werden muss.
JavaScript .state('<%!! Context:CurrentIndex.Page.Id !!%>', { url: '/<%!! Context:CurrentIndex.Page.Id !!%>', templateUrl: '<%!! Context:CurrentIndex.GetUrl() !!%>' }) <navigation:nextlevel>
Wenn man die einzelnen Seiten aufruft, bekommt man nur den Content angezeigt. Dies ist ja nicht gewünscht, und es sollte auch möglich sein in der Seiten-Vorschau den Auftritt komplett durchnavigieren zu können. Hierfür machen wir uns zu Nutze, dass mit UI Router mit der #
-Notation ein direkter Sprung zu jeder beliebigen Seite möglich ist und bauen in die Masterpage folgenden Script-Tag ein.
HTML <script type="text/javascript"> window.location.href = "<%!! Context:Pages.GetPage(Guid:CA43D1900A2341C98F9C7EC10838D48D).GetUrl() !!%>#/<%!! Context:CurrentPage.Id !!%>"; </script>
Die hier aufgerufene Page ist die Instanz im Projekt mit dem HTML-Body. Damit hat der Aufruf der gewünschten Seite in dem vollständigen Rahmen einwandfrei funktioniert. Bei der Navigation gab es noch eine Schwierigkeit, die URLs im CMS sind mit sehr vielen Übergabeparameter versehen.
URL http://[SERVERNAME]/cms/WebClient/PreviewHandler.ashx?Action=RedDot&Mode=0&PageGuid=A7DC6CC5060A4CC9A1F8B404BCF76D42&LinkFromGuid=039DE11E4FF44590A21A1D9BE242793C&WithCache=1&Type=page&Isolated=0&PageLocked=0&Rights1=-33673217&DummyTime=1487948828027
Das &
verträgt sich nicht mit dem templateUrl
-Aufruf im JavaScript. Deshalb ist hier noch eine Erweiterung des Navigation-Templates erforderlich:
JavaScript templateUrl: (function(){ return '<%!! Context:CurrentIndex.GetUrl() !!%>'.replace(/&/g,"&");})()
Hier verfolgen wir bei all unseren Projekten den Ansatz, dass die Redakteure sich komplett auf ihre Arbeit konzentrieren sollen und Inhalte, die nicht bearbeitet werden können, weggeblendet werden. Was ja in diesem Fall die Navigation und der HTML-Body wären. Navigiert wird über den Strukturbereich im SmartEdit. Hier ist jede Seite durch den Redakteur erreichbar und er muss sich nicht im Bearbeitungsbereich durch die gesamte Webseite durchklicken, um zu der einen Seite zu gelangen, die er bearbeiten möchte.
Trotzdem sollte die Seite im WYSIWYG-Modus dargestellt werden. Dafür wird im SmartEdit-Modus in jede Seite ein HTML-Body eingefügt und auch das StyleSheet geladen.
... ist Senior Developer und technischer Projektleiter bei der I-D Media AG in Köln. Seit 1999 betreut sie zusammen mit ihrem Team OpenText- (vormals RedDot-) basierte Webseiten nationaler und internationaler Kunden.
Neben dem klassischem Content-Klassen und Projektbau entwickelt sie Erweiterungen in Form von Plug-Ins und führt Proof of Concepts durch um neue Technologien und Wege im CMS zu etablieren.