Montag, 21. Mai 2012

Generierte Styles

Ein Content Management System ist ein typisches Einsatzfeld für domänenspezifische Sprachen: Administratoren sollen bestimmte Aspekte einer Webanwendung, die ihnen wichtig erscheinen oder deren spezielle Gestaltung sich nicht festlegen lässt, nach eigenen Vorstellungen steuern können.

Zum Beispiel die Farben. Der Administrator hat sich für ein bestimmtes Farbschema entschieden, das ihm stimmig erscheint. Am nächsten Morgen, vielleicht nach einem Gespräch mit der Partnerin, kommt ihm plötzlich ein anderes Farbschema besser vor. Und übermorgen, nach einem weiteren Gespräch, wird ihm ein wieder anderes, drittes Schema empfohlen. So wird es weitergehen - bis zur Abschaltung der Seite.

Der Administrator soll also einen Satz von Farbwerten pflegen können, die dann in das CSS zur Seite eingehen. Zur Realisierung gibt es zwei Möglichkeiten (mindestens):

  1. Vom Administrator generiertes CSS-File. Beim Sichern seiner Einstellungen, oder durch Ausführung eines zusätzlichen Schrittes, wird das CSS-File anhand der Einstellungen neu generiert und gespeichert. Mein Perl-Beispiel bei Codepad zeigt die Idee. Durch Ausführen des Perl-Scripts wird das CSS-File gemäss den Einstellungen neu erzeugt.
  2. Dynamisch beim Request erzeugtes CSS Die Einstellungen des Administrators werden in einer Datenbanktabelle gesichert. Bei Anforderung des CSS-Files werden die Daten von dort gelesen und als Parameter in den CSS-Code eingemischt.
Die zweite Variante, der Zugriff auf die gepflegten Parameter zur Laufzeit, hat den Vorteil, dass sie dem on demand-Prinzip folgt, den Rechner nur dann zu einer Arbeit zu zwingen, wenn diese auch wirklich benötigt wird. Wenn aber die Aufbereitung der Ressource aus den Parametern sehr aufwendig ist und das Ergebnis nicht gepuffert werden kann oder darf, ist die erste Variante mit dem zusätzlichen Generierungsschritt besser.

Man kann das mit einem beliebigen Serversystem realisieren – zum Beispiel auch mit einem SAP Web AS mit Business Server Pages. Es folgt hier ein Beispiel unter Verwendung meines MVC-Frameworks.

Pflegetransaktion für die Farbwerte

Mit der Transaktion ZPARAM kann man die Werte einer beliebigen Datenstruktur zur Pflege anbieten.[1] In diesem Fall mehrere Farbwerte (jeder Farbwert ist eine Komponente der Struktur ZPARAM_CSS vom eingebauten Typ RAW der Länge 3). Die Pflegetransaktion für die Werte dieser Struktur bekommt man vom ZPARAM-Mechanismus geschenkt. Auch die Konvertierung und Verprobung der Hexadezimalziffern sind aus der Typisierung der Komponenten automatisch abgeleitet, müssen nicht extra programmiert werden:

Test-BSP

Wie üblich, durch Kopieren von der Vorlageapplikation ZMVC_TEMPLATE hergestellt und mit einigen Bereichen für die Anzeige vorgesehen. Das Beispiel hat folgende Struktur:

<%@page language="abap"%>
<%@extension name="Z" prefix="z"%>
<html>
<%-- HTML Header ----------------------------------------------%>
  <head>
    <title>CSS-Beispiel</title>
    <link href="css.do" rel="stylesheet" type="text/css">
  </head>
<%-- HTML Body ------------------------------------------------%>
  <body>
    <div class="head">Kopfbereich</div>
    <div class="nav">Navigationsbereich</div>
    <div class="content"><div>Contentbereich</div></div>
    <div class="foot">Fussbereich</div>
  </body>
</html>

Das Stylesheet anlegen

Ungewöhnlich an obigem HTML-Code ist nur, dass die URL des Stylesheets auf einen Controller verweist:

  <link href="css.do" rel="stylesheet" type="text/css">
Die in der config.xml-Datei hinterlegte Logik steuert den Aufruf eines Views:
<controller id="css" name="css.do" class="zcl_co_css">
  <callsView name="main.css" /> 
</controller>
Dieser View main.css hat nun ein Seitenattribut css vom Typ zparam_css. Damit ist das Ziel erreicht, dass der Style statische und dynamische Angaben kombinieren kann:
.head {
  width:100%;
  height:10%;
  font-size:200%;
  background-color: #<%=css-head_color%>;
  }

.nav {
  width:100%;
  height:10%;
  font-size:150%;
  background-color: #<%=css-nav_color%>;
  }

.content {
  background-color: #<%=css-bg_color%>;
  position:relative;
  width:100%;
  height:70%;
  }

Den CSS-Controller ausprägen

Der Controller, der das CSS aufruft, hat drei spezielle Funktionen:

  1. Er muss die gespeicherten Parameterwerte einlesen und dem View zur Verfügung stellen. Hierzu lesen wir in der redefinierten do_init()-Methode die Parameterwerte in eine Struktur gs_css ein:
      data: lo_param type ref to zcl_param.
      super->do_init( ).
      lo_param ?= zcl_param=>get_instance_ext('ZPARAM_CSS').
      lo_param->get_structure( importing es_structure = gs_css ).
    Später, in der redefinierten Methode set_view_attributes(), übergeben wir diese Struktur an den View
    method set_view_attributes.
      data: lo_view type ref to if_bsp_page.
      call method super->set_view_attributes
        exporting
          iv_instance = iv_instance
          iv_type     = iv_type.
      if iv_type eq zmvc_type-view.
        lo_view ?= iv_instance.
        lo_view->set_attribute( name = 'css' value = gs_css ).
      endif.
    endmethod.
  2. Den richtigen Content-Type text/css an den Client senden. Auch dies erfolgt in do_init() mit dem Aufruf
    response->set_header_field( 
      name  = if_http_header_fields=>content_type
      value = 'text/css' ).
  3. Er sollte gepuffert sein, wenigstens serverseitig. Denn die von ihm erzeugte Antwort ändert sich nur, wenn der Administrator Änderungen an den Parametern vorgenommen hat. Wenn man auch eine clientseitige Pufferung einstellt, hat man für die angegebene Pufferzeit keinen Einfluss darauf, dass der Client die neuen Werte bereits erhält. Das sollte aber für Stylesheet-Änderungen kein Problem sein.

Testaufruf und Kontrolle

Nun ist der Grundstein gelegt. Ab jetzt kann man die Seite im Browser aufrufen und das CSS und HTML so lange anpassen, bis das gewünschte Design erreicht ist. Während der Entwicklung empfiehlt es sich, die Pufferung des Controllers noch ausgeschaltet zu lassen, damit Änderungen immer sofort wirksam werden.

An den variabel gehaltenen Stellen des Stylesheets kann der Administrator später noch herumdrehen, wie er will — was ja der Sinn der Übung war.

[1] Eine detaillierte Beschreibung der Transaktion ZPARAM gibt das 19. Kapitel des BSP-Praxisbuchs

Keine Kommentare :