Mobile Navigation

Für mobile Geräte wird oft ein aufklappbares Menü verwendet das mit dem sogenannten “Hamburger” (≡ die drei Balken erinnern daran) als Erkennung versehen ist. Praktisch ist, wenn das über den “Hamburger” aufgeklappte Menü wieder geschlossen werden kann. Da im css das hover bei Touchscreens nicht nutzbar ist wird das mit JavaScript umgesetzt. Der responsive Ansatz ist in meinem Beispiel berücksichtigt.
Als Hilfsbibliothek wird jQuery verwendet.

So sieht das HTML aus:


<!doctype html>
<html>
  <head>
    <!-- auf mobilen Geräten die volle Größe ausfüllen-->
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <script src="js/jquery_1_12_2.js" type="text/javascript"></script>
    <script src="js/functions.js" type="text/javascript"></script>
    <link rel="stylesheet" type="text/css" href="css/main.css" />
    <!-- folgendes css wird per JavaScript bestimmt -->
    <link id="select-style" rel="stylesheet" type="text/css" href="css/desktop.css" />
  </head>
  <body>
    
    <div id="header">
      <h1>Test für eine mobile Navigation mit "Hamburger" Button</h1>
      <div id="navigation">
        <div id="menu-hamburger" class="hidden">
          <a href="#" class="create-hamburger" onclick="toggle_menu()"></a>
        </div>
        <div id="menu-container" class="hidden">
          <ul id="menu">
            <li><a href="#">Link 1</a></li>
            <li><a href="#">Link 2</a></li>
            <li><a href="#">Link 3</a></li>
            <li><a href="#">Link 4</a></li>
          </ul>
        </div>
      </div>
    </div>
    <!-- Versuch, das Flackern beim neu Laden der Seite zu verhindern-->
    <script type="text/javascript">
      $("#menu-container").addClass("hidden");
    </script>
    <div id="content">
      ...
    </div>
    
    <div id="footer">
      <div id="js-debug"></div>
    </div>
    
  </body>
</html>

Die JavaScript Funktionen laden je nach Browserbreite das entsprechende css Stylesheet. Das lässt sich ohne Javascript auch mit css Media Queries lösen.
Ist bei schmalem Bildschirm die mobile Navigation eingeblendet klappt die Funktion toggle_menu() die Menüpunkte auf oder zu.


//jQuery muss eingebunden sein
function adjust_style(width, height) {
  width = parseInt(width);
  height = parseInt(height);
  if (width < 601) {
    $("#select-style").attr("href", "css/mobile.css");
  } else {
     $("#select-style").attr("href", "css/desktop.css"); 
  }
  //nach dem Laden des passenden Stylesheets die Elemente wieder einblenden (wird für eins der beiden überschrieben)
  $("#menu-hamburger").removeClass("hidden");
  $("#menu-container").removeClass("hidden");
}
//wird ausgeführt nach laden des Dokuments
$(function() {
  adjust_style($(this).width(), $(this).height());
  $(window).resize(function() {
    adjust_style($(this).width(), $(this).height());
  });
});

function toggle_menu()
{
  if($("#menu-hamburger").hasClass("expanded")){
    //wird nur der Text / html gesetzt, dann sind die 
    //Klassen create-close und create-hamburger überflüssig
    //$('#menu-hamburger a').html("≡");
    $('#menu-hamburger a').removeClass("create-close");
    $('#menu-hamburger a').addClass("create-hamburger");
    $("#menu-hamburger").removeClass("expanded");
    $("#menu-container").removeClass("expanded");
    $("#navigation").removeClass("expanded");
  }else{
    //$('#menu-hamburger a').text("x");
    $('#menu-hamburger a').removeClass("create-hamburger");
    $('#menu-hamburger a').addClass("create-close");
    $("#menu-hamburger").addClass("expanded");
    $("#menu-container").addClass("expanded");
    $("#navigation").addClass("expanded");
  }
}

Basisformatierung:


* {
  margin: 0; 
  padding: 0;
}
body {
  background-color:#FFFFFF;
  font-size: 1em;
  font-family: Verdana,Arial,Helvetica,sans-serif;
}
h1 { 
  font-size: 1.2em; 
  padding: 2px 0 5px 2px;
}
a { 
  text-decoration: none;
  color: #272727;
}
a:hover { color: #555555; }
li { list-style: none; }
#header {
  margin-top: 1em;
}
#navigation {
  background-color:#EEEEEE;
  height: 30px;
}
#content {
  padding: 1em;
  background-color: #DDDDDD;
  min-height: 300px;
}
#footer {
  background-color:#CCCCCC;
  padding: 1em;
}
.hidden { display: none; }

Bei breiten Bildschirmen wird ein horizontales Menü verwendet


/* Navigation für Desktop bzw Bildschirme breiter 600px */
#menu-hamburger {
  display: none;
}
#menu-container {
  background: #999999;
}
ul#menu li  {
  display: inline-block;
  width: 8em;
}
ul#menu li a {
  background: #888888;
  display: block;
  padding: 5px 0;
  color: #FFFFFF;
  font-weight: bold;
  border-right: 5px solid #999999;
  text-align: center;
  width: 100%;
}
ul#menu li a:hover {
  background: #777777;
}

Formatierungen für die mobile Navigation
Öffnen / Schliessen Button formatieren


#menu-container {
  visibility: hidden;
}
#menu-container.expanded {
  visibility: visible;
}
#navigation.expanded {
  height: auto;
}
ul#menu {
  background:#BBBBBB;
}
ul#menu a {
  display:block;
  padding: 0.5rem 0 0.5rem 1rem;
  color:#FFFFFF;
  border: 1px solid #CCCCCC;
}
ul#menu a:hover {
  background:#AAAAAA;
}
#menu-hamburger {
/*  display: block;*/
  width: 30px;
  height: 30px;
  margin-left: auto;
  margin-right: auto;
  background-color: #BBBBBB;
  border-radius:4px;
  position:relative;
}
#menu-hamburger a {
  display: block;
  font-size: 2em;
  line-height: 0.6;
  height: 30px;
  font-weight: bold;
}
#menu-hamburger a:hover {
  background-color: #AAAAAA;
  border-radius:4px;
}
/* wenn im JavaScript nur der Text gesetzt wird sind folgende Anweisungen überflüssig */
#menu-hamburger .create-hamburger:before {
  content: "";
  position: absolute;
  left: 5px;
  top: 5px;
  width: 20px;
  height: 4px;
  background: #111111;
  border-radius: 1px;
  box-shadow: 1px 1px 1px 0 #444444, 
              0 8px 0 0 #111111, 1px 9px 1px 0 #444444,
              0 16px 0 0 #111111, 1px 17px 1px 0 #444444;
}
#menu-hamburger .create-close:before, #menu-hamburger .create-close:after{
  content: '';
  position: absolute;
  width: 26px;
  height: 4px;
  background-color: #111111;
  border-radius: 1px;
  top: 13px;
  box-shadow: 0 0 2px 0 #444444;
}
#menu-hamburger .create-close:before{
  -webkit-transform: rotate(45deg);
  -moz-transform: rotate(45deg);
  transform: rotate(45deg);
  left: 2px;
}
#menu-hamburger .create-close:after{
  -webkit-transform: rotate(-45deg);
  -moz-transform: rotate(-45deg);
  transform: rotate(-45deg);
  right: 2px;
}

Und das ganze im Beispiel

Join on Function Returning Type

Manchmal ist es praktisch Daten aus einer Funktion mit den Spalten einer Tabelle / Abfrage zu kombinieren.
Die Herausforderung liegt darin, die Werte aus der Tabelle der Funktion passend pro Record als Parameter zu übergeben.
In PostgreSQL ab Version 9.3 kann dazu der Lateral Join verwendet werden, für Versionen davor ist aber eine andere Variante notwendig.
Beispieldaten:


Create table angebote (angebotsid integer, kundenid integer, gueltigab date);
insert into angebote values 
(1, 4711, '2015-01-01'),
(2, 4711, '2015-03-01'),
(3, 4711, '2015-05-01');
Create Type typePreis as (wert numeric(6,2), gueltigab date);
Create Function get_preis(inAngebotsid integer, inGueltigam date) Returns typePreis as $$
Declare
  p typePreis;
Begin
  --Dummydaten statt wirklicher Preisermittlung
  p.wert := 9.99 * inAngebotsid;
  p.gueltigab := inGueltigam;
  Return p;
End;
$$
LANGUAGE plpgsql;

Mit einer Unterabfrage gelingt der Trick, den zurückgegebenen Record der Funktion in der select-Liste zu verwerten. In der übergeordneten Abfrage wird auf die Funktion mithilfe der Klammer um den Alias referenziert.


select angebotsid, (p).*
  from (select angebotsid, get_preis(angebotsid, gueltigab) as p 
          from angebote) sub

Oder ausführlich referenziert:


select sub.angebotsid, (sub.p).wert, (sub.p).gueltigab
  from (select angebotsid, get_preis(angebotsid, gueltigab) as p 
          from angebote) sub

Siehe dazu auch:
stackoverflow.com

Java Sicherheitszertifikate

Wenn über java eine Webseite mit https angesprochen dann wird wie im Browser das Sicherheitszertifikat benötigt.

Ist das Zertifikat nicht im Standard vorhanden, dann wird es folgende Exception werfen:

javax.net.ssl.SSLHandshakeException: 
  sun.security.validator.ValidatorException: 
  PKIX path building failed: 
  sun.security.provider.certpath.SunCertPathBuilderException: 
  unable to find valid certification path to requested target

Java Standardzertifikatsdatei

Die Standardzertifikate (werden immer geladen) liegen bei Java hier:

JAVA_HOME/lib/security/cacerts


Sie können zum ansehen exportiert werden (nochmal prüfen, ob das Zertifikat wirklich fehlt).

keytool -list -v -keystore JAVA_HOME/lib/security/cacerts  > java_cacerts.txt


Für Windows; keytool liegt hier:

JAVA_HOME/bin/keytool


Nach dem ansehen sollte die Datei wieder gelöscht werden.

Zertifikate nachrüsten

Ist das Zertifikat nicht vorhanden muss Java das entsprechende Zertifikat bekannt gemacht werden. Es gibt zwei Möglichkeiten das zu hinterlegen.

  • 1. In der Standardzertifikatsdatei cacerts hinzufügen
  • 2. In einer eigenen Datei hinterlegen, die später dem Java Programm bekannt gemacht wird.

Die Vorgehensweise ist fast identisch:

Zuerst die fragliche https-Webseite ansurfen. Im Browser auf das Sicherheitsschloss klicken (meist bei der URL Leiste). Beim Firefox links der Adresse. Die Beschreibung entspricht dem Vorgehen im Firefox.

  • Die Seiteninformationen anzeigen
  • Darin die Zertifikate anzeigen
  • Tabreiter Details wählen
  • Den Button "Exportieren" klicken
  • Dateityp X.509-Zertifikat(DER)(*.der) wählen
  • Einen sprechenden Namen für die Webseite wählen (www.beispiel.der)

Variante 1: In der Standardzertifikatsdatei cacerts hinzufügen

keytool -import -alias www_beispiel -keystore "pfad/zur/cacerts" -file "pfad/zum/zertifikat/www.beispiel.der" -trustcacerts


Es erfolgt eine Abfrage nach dem Passwort der cacerts Datei. Das Standardpasswort von Java ist: changeit

Variante 2: In einer eigenen Datei hinterlegen

keytool -import -alias www_beispiel -keystore "pfad/zur/eigenen/my_cacerts" -file "pfad/zum/zertifikat/www.beispiel.der" -trustcacerts


Es erfolgt eine mehrfache Abfrage nach dem Passwort. Bei Verwendung des Standardpassworts (changeit) muss in Java das Passwort nicht zur Verfügung gestellt werden.

Zertifikat verwenden

Wurde das Zertifikat in die Standarddatei geschrieben, dann ist es unter Java sofort verfügbar. Nachteil: Das Zertifikat muss auf jedem Rechner installiert werden.

Liegt das Zertifikat in einer eigenen Datei vor, dann kann es auf zwei Wegen verwendet werden:

Beim Programmstart:

java.exe -Djavax.net.ssl.trustStore="pfad/zur/eigenen/my_cacerts" -jar my_program.jar


bzw mit Debug Informationen wenn nicht alles wie gewünscht läuft

java.exe -Djavax.net.ssl.trustStore="pfad/zur/eigenen/my_cacerts" -Djavax.net.debug=ssl -jar my_program.jar

Innerhalb des Java Programms:

System.setProperty("javax.net.ssl.trustStore", "pfad/zur/eigenen/my_cacerts");


Der Vorteil der eigenen Datei liegt klar bei der Verwendung im Netzwerk.

Links

Kontaktformular einrichten

3 Plugins empfehle ich für WordPress um ein Kontaktformular einzubauen:

Flamingo speichert die Anfragen in der Datenbank. Damit gehen keine Daten verloren sollte der E-Mail Versand fehl schlagen.

Entweder werden die Plugins über den Adminbereich installiert oder per FTP in den Pluginordner (wp-content/plugins) hochgeladen. Danach können sie in Plugins aktiviert werden.
Die Einrichtung des Kontaktformulars erfolgt im Pluginbereich unter Einstellungen. Unter Tag generieren wird hier das Captcha erzeugt.

Galerie zum Scrollen

Ein nettes Feature ist eine Galerie die bei Mouseover nach rechts oder links scrollen kann. Dafür brauchen wir die jquery.js und von der Seite von Kelvin Luck aus dem Downloadbereich die jquery.jscrollpane.min.js, und die jquery.jscrollpane.css

Diese Dateien werden im Header der Html Datei eingebunden, zusammen mit zwei eigenen Dateien die hier zu finden sind:
scrl-functions.js
scrollcustom.css


<link type="text/css" href="css/jquery.jscrollpane.css" rel="stylesheet" media="all" />
<script type="text/javascript" src="js/jquery.js"></script>
<script type="text/javascript" src="js/jquery.jscrollpane.min.js"></script>
<script type="text/javascript" src="js/scrl-functions.js"></script>
<link type="text/css" href="css/scrollcustom.css" rel="stylesheet" media="all" />

Am rechten und linken Rand der Galerie fangen bei mouseover die Bilder an zu scrollen


So werden die divs eingesetzt:


<div class="scrlcontainer">
  <!-- mouseover Scrollbereich links -->
  <div class="leftscroll"></div>
  <div class="objlistwidth hidden">1608</div>
  <div class="scroll-pane horizontal-only">
    <div class="objlist">
      <div class="objitem">
        <img src ="sonnenuntergang1,jpg"
                width="400" height="300">
      </div>
      <div class="objitem">
        ....
      </div>
    </div>
  </div>
  <div class="rightscroll"></div>
</div>

 
Da üblicherweise die Galerie dynamisch zusammengestellt wird, z.B. aus einer WordPressgalerie muss entsprechend die class=”objlistwidth” ebenfalls per php gesetzt werden. Der Wert ist die Breite aller Bilder plus dem Zwischenabstand. Ist der Wert zu klein, dann bricht der Fluss in eine zweite Zeile (in den unsichtbaren Bereich) um.

Highlight Code

Um auf einer Webseite Quellcode farblich anzupassen kann die highlight.js verwendet werden.

Dort get version klicken, Sprachen auswählen und auf download klicken. Im Zip gibts die javascript Datei sowie alle möglichen styles zur Formatierung. Im Beispiel hier ist die googlecode.css gewählt.

Unter usage finden sich Verwendungsbeispiele. Die einfachste Variante ist gleich hier zu sehen.

Im Header der Html Datei sind folgende 3 Zeilen als Minimum einzubinden. Die Ordnerstruktur muss entsprechend angelegt sein.


<link rel="stylesheet"  type="text/css" href="css/googlecode.css">
<script src="js/highlight.pack.js"></script>
<script>hljs.initHighlightingOnLoad();</script>

In der header.php Datei von WordPress wird der Pfad folgendermaßen angegeben:


href="<?php echo esc_url( home_url( '/' )) ?>wp-content/themes/mytheme/css/googlecode.css"

Damit die farbliche Markierung funktioniert muss der Code in


<pre><code>....</code></pre>

eingebettet werden.