PrimeFaces Dialog: Größe (Breite & Höhe) dynamisch am Viewport (Browserfenster) anpassen

Verwendet eine Webanwendung Dialoge, kann es sinnvoll sein, die Größe dynamisch am Viewport (Anzeigebereich) des Browserfensters anpassen zu lassen. Die JSF Bibliothek PrimeFaces liefert bereits eine fertige Dialog Komponente als Overlay mit, bei der die Größe eingestellt werden kann.

Größenangabe in Prozent (%)

Leider nützt es nichts, einfach die Angaben der Breite und/oder Höhe in Prozent anzugeben, da dies nicht den gewünschten Effekt mit sich bringt. Die Höhe richtet sich nicht nach der Relation zum Browserfenster, sondern nach dem Inhalt des Dialogs.

Facelet

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:p="http://primefaces.org/ui">

    <h:head>
        <title>Viewport height/width example</title>
    </h:head>

    <h:body style="background-color: #cacaca">
        <p:dialog visible="true" height="80%" width="80%">
            dialog with percentage height (80%) and width (80%)
        </p:dialog>     
    </h:body>  
</html>

Ergebnis:

Größenangabe in Prozent (%)

Größenanpassung mit JavaScript

Um die Größe trotzdem dynamisch am Viewport anpassen zu können, musste bisher eine Lösung über JavaScript erstellt werden, womit die Größe dynamisch berechnet und angepasst wird. Zusätzlich musste auch auf die Größenänderung des Viewports reagiert werden, wenn z. B. die Größe es Browserfensters verändert wurde. Diese Methode funktioniert zwar, ist aber umständlich. Deshalb werde ich hier nicht detailierter darauf eingehen.

Größenangabe mit CSS3 Viewport Units

In CSS3 gibt es einige neue Einheiten für relative Maße, womit u. a. die Breite beziehungsweise die Höhe in Relation zum Anzeigebereich angegeben werden kann.

  • vw (Viewport-Breite)
    100vw entspricht der vollen Breite des Viewports (Anzeigebereichs).
  • vh (Viewport-Höhe)
    100vh entspricht der vollen Höhe des Viewports (Anzeigebereichs).

Mit diesen Möglichkeiten erziehlt man dann auch sehr einfach den gewünschten Effekt.

Facelet

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:p="http://primefaces.org/ui">

    <h:head>
        <title>Viewport height/width example</title>
    </h:head>

    <h:body style="background-color: #cacaca">
        <p:dialog visible="true" height="80vh" width="80vw">
            dialog with viewport height (80vh) and width (80vh)
        </p:dialog>       
    </h:body>  
</html>

Ergebnis:

Größenangabe mittels Viewport Unit (vh/vw)

Browser Support
Die Viewport Units „vw“ und „vh“ werden von allen modernen Browsern unterstützt. Im Microsoft Internet Explorer funktioniert dies ab Version 9, im Mozilla Firefox ab Version 19 und im Google Chrome ab Version 20.
Weitere Informationen findet man hier.

Vergleich Prozent vs. Viewport Units

Hier noch der direkte Vergleich zwischen der Angabe in Prozent und der Viewport Units.

Vergleich Prozent vs. Viewport Units

Live Beispiel
Primefaces Dialog – Vergleich Prozent vs. Viewport Units

Mehrere (Sub)-Projekte / Unterverzeichnisse als einzelne Jobs mit Travis CI ausführen

Eine einfache und kostengünstige Methode, um eine kontinuierliche Integration für öffentliche Projekte auf GitHub durchzuführen, ist mittels der Travis CI Continuous Integration (CI) Plattform. Zur Ausführung muss im Wurzelverzeichnis des Git-Repositories eine YAML-Datei mit dem Namen .travis.yml erstellt werden, welche die Travis Konfiguration für das Projekt enthält.

Manchmal befinden sich aber mehrere (Sub)-Projekte in einem Git-Repository, welche in unterschiedliche Unterverzeichnisse zu finden sind.

Verzeichnisstruktur

Repository
|
|– Project1
|– Project2

Mittels Travis CI ist es möglich, auch für diese (Sub)-Projekte eine kontinuierliche Integration sicherzustellen.

Einfache Lösungsmöglichkeit

Als einfachste Möglichkeit, führt man die entsprechenden Build-Befehle im „Build Lifecycle“ für jedes (Sub)-Projekt nacheinander aus. Wichtig ist hierbei, dass vorher immer in den entsprechenden Projektordner mittels „cd ../ProjektOrdner“ Befehl gewechselt wird.

script: cd project1 && npm install && npm test && cd ../project2 && npm install && npm test

Elegantere Lösungsmöglichkeit

Eine deutlich elegantere Lösung ist es, für die einzelnen Projekte die Möglichkeit der Build Matrix von Travis zu nutzen. Der große Vorteil dabei ist, dass für jedes (Sub)-Projekt ein eigener Build-Job erstellt wird, welcher seinen eigenen Status bzw. Ergebniss besitzt.

Hierzu werden die Pfade der einzelnen (Sub)-Projekte als Umgebungsvariablen im Abschnit „env“ angegeben.

env:
  - PROJECT_DIR=project1
  - PROJECT_DIR=project2

script: cd $PROJECT_DIR && npm install && npm test

Zu beachten ist hier, dass immer der gleiche Schlüssel wie z. B. „PROJECT_DIR“ verwendet wird. Anstelle des eigentlichen Projektpfades wird dieser dann als Variable „$PROJECT_DIR“ im „script“ Befehl angegeben. Travis führt nun den Build Lifecycle mehrmals mit jeder definierten Umgebungsvariable als eigenen Build-Job (parallel) aus.

Beispiel-Projekt

Projekt: https://github.com/mesche/angular-collection
Travis CI Konfiguration: https://github.com/mesche/angular-collection/blob/master/.travis.yml
Travis CI Build: https://travis-ci.org/mesche/angular-collection

Status-Bilder (Badges) je Build-Job

Leider bietet Travis CI nur die Möglichkeit, ein Status-Bild (auch Badge genannt) pro Repository zu erzeugen, welches man dann z. B. in der Readme.md Datei auf GitHub einfügen kann.

Möchte man aber für jeden einzelnen Build-Job ein Badge erzeugen, kann man folgendes GitHub-Projekt verwenden: Travis Matrix Build Badges

Veeam Endpoint Backup Free – Einstellungen und Daten komplett zurücksetzen

Nachdem ich auf eine neue Windows Version geupdated hatte, funktionierte bei mir Veeam Endpoint Backup Free nicht mehr korrekt. Daher entfernte ich die vorhandene Installation, um das Programm komplett neu zu installieren. Ich musste dann aber feststellen, dass nicht alles komplett zurückgesetzt wurde. Die Einstellungen und die Anzeige von bereits erstellen Backups waren immer noch vorhanden.

Ich habe aber folgende Möglichkeit gefunden, um Veeam Endpoint Backup komplett zurückzusetzen.

Warnung: Dabei gehen auch alle Einstellungen / Log-Information etc. verloren.

1. Veeam Endpoint Backup Windows-Dienst/Service stoppen

  • „Windows-Taste + R“ drücken
  • „services.msc“ eingeben und mit „OK“ bestätigen
  • In der Dienste-Verwaltung von Windows den Eintrag „Veeam Endpoint Backup“ suchen und mittels rechter Maustaste und „Stop“ den Dienst beenden.

2. Registry-Schlüssel Eintrag „Recreatedatabase“ ändern

  • „Windows-Taste + R“ drücken
  • „regedit.exe“ eingeben und mit „OK“ bestätigen
  • Folgenden Schlüssel suchen:
    Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Veeam\Veeam Endpoint Backup

  • Eintrag „Recreatedatabase“ öffnen und den Wert (DWORD (32 bit) auf „1“ ändern. Sollte der Eintrag nicht vorhanden sein, muss dieser als DWORD (32 bit) neu angelegt werden.

3. Veeam Endpoint Backup Dienst starten

Jetzt kann der Windows-Dienst wieder gestartet werden. Hierzu kann wie bei Schritt 1 vorgegangen werden. Anstelle von „Stop“ muss „Start“ ausgeführt werden.

4. Ein paar Minuten warten, damit die Datenbank neu erstellt werden kann

5. Wert des Eintrags „Recreatedatabase“ prüfen

Es sollte geprüft werden, ob der Wert des Eintrags „Recreatedatabase“ wieder korrekt auf „0“ zurückgesetzt wurde. Sollte dies nicht der Fall sein, muss dies manuell geändert werden. Hierzu muss der Windows-Dienst nochmal gestoppt werden. Dann kann der Wert wie in Schritt 2 beschrieben auf „0“ gesetzt werden und der Windows-Dienst wieder gestartet werden.

6. Starten von Veeam Endpoint Backup

Beim nächsten Start von Veeam Endpoint Backup sollten jetzt alle Einstellungen und Daten zurückgesetzt worden sein.

Das entsprechende Ticket zu diesem Problem findet man unter:
https://www.veeam.com/kb2057

Aktuelle Wetterdaten über Wunderground Service abrufen und in der Homematic CCU speichern – Homematic-Script

Update 30.07.2018: Wunderground vergibt inzwischen keine kostenlosen API-Keys mehr.

To improve our services and enhance our relationship with our users, we will no longer provide free weather API keys as part of our program. If you have been directed to download our Weather Underground free API key by a third party provider, please contact your vendor for resolution

Um immer Zugriff auf aktuelle Wetterdaten in der Homematic CCU zu haben, wird nicht unbedingt die entsprechende Hardware zur Messung benötigt. Man kann auch einfach über einen Wetterdienst die benötigten Daten aus dem Internet laden. Eine schöne API für diesen Zweck bietet der Dienst Wunderground.

Um die Abfrage der Wetterdaten zu automatisieren, habe ich ein kleines Homematic-Script entwickelt, welches sich die Daten über den angeboteten HTTP-Webservice herunterlädt und in eigene Systemvariablen auf der Homematic CCU abspeichert. Somit können diese Werte dann für unterschiedliche Aktionen weiterverarbeitet werden.

Installation

Das Script kann direkt in einem Programm eingebunden werden, welches z. B. alle 30 Minuten automatisch ausgeführt wird. Die Systemvariablen müssen nicht manuell erzeugt werden, dies erledigt das Homematic-Script automatisiert.

Voraussetzung

Neben der Homematic CCU, muss auf dieser der CUx-Daemon installiert und eingerichtet sein.
Zusätzlich wird zur Abfrage über den Wunderground HTTP-Webservice ein individueller API-Key benötigt, welcher kostenlos nach einer Registrierung über die Wunderground Webseite erstellt werden kann.

Konfiguration

Folgende Einstellungen müssen bei den entsprechenden Variablen individuell im Script vorgenommen werden, damit dies funktioniert:

CUXD_ID Seriennummer des CUx-Daemon Kanals
API_KEY Wunderground API Key
API_QUERY Ort für dem die Wetterdaten geladen werden sollen

Homematic-Script

Das aktuelle Script kann über GitHub heruntergeladen werden

Service – Weather Data – Wunderground auf GitHub

Code-Snippet: Homematic Systemvariablen über ein Script automatisch erzeugen

Viele Homematic Scripte greifen auf Systemvariablen zu, um einen Status auzulesen, Werte abzufragen oder zu hinterlegen. Um diese nicht manuell anlegen zu müssen, besteht die Möglichkeit im Script zu prüfen, ob eine Variable existiert. Falls nicht, kann diese dann direkt automatisch angelegt werden.

Leider ist auch hierzu die API Dokumentation nicht vollständig. Daher habe ich die möglichen Werte und Methoden (soweit möglich) mit aufgelistet.

Typen und Werte

ValueType

  • ivtBinary (2)
  • ivtFloat (4)
  • ivtInteger (16)
  • ivtString (20)

ValueSubType

  • istPresent (23) – Anwesenheit
  • istAlarm (6) – Alarm
  • istGeneric (0) – Zahl
  • istBool (2) – Logikwert
  • istEnum (29) – Werteliste
  • istChar8859 (11) – Zeichenkette

Beispiele – Systemvariable erstellen

Zeichenkette

string  svName = "testVarPresent";
object  svObj  = dom.GetObject(svName);

if (!svObj){   
    object svObjects = dom.GetObject(ID_SYSTEM_VARIABLES);

    svObj = dom.CreateObject(OT_VARDP);

    svObjects.Add(svObj.ID());

    svObj.Name(svName);   
    svObj.ValueType(ivtString);
    svObj.ValueSubType(istChar8859);
	
    svObj.DPInfo("Variable string for test");
    svObj.ValueUnit("");
    svObj.State("some text");
    svObj.Internal(false);
    svObj.Visible(true);

    dom.RTUpdate(false);
}

WriteLine(svObj.Value().ToString());

Zahl

string  svName = "testVarNumber";
object  svObj  = dom.GetObject(svName);

if (!svObj){   
    object svObjects = dom.GetObject(ID_SYSTEM_VARIABLES);

    svObj = dom.CreateObject(OT_VARDP);

    svObjects.Add(svObj.ID());

    svObj.Name(svName);   
    svObj.ValueType(ivtFloat);
    svObj.ValueSubType(istGeneric);
	
    svObj.DPInfo("Variable number for test");
    svObj.ValueUnit("°C");
    svObj.ValueMin(-100);
    svObj.ValueMax(100);
    svObj.State(15);
    svObj.Internal(false);
    svObj.Visible(true);

    dom.RTUpdate(false);
}

WriteLine(svObj.Value().ToString());

Alarm

string  svName = "testVarAlarm";
object  svObj  = dom.GetObject(svName);

if (!svObj){   
    object svObjects = dom.GetObject(ID_SYSTEM_VARIABLES);

    svObj = dom.CreateObject(OT_VARDP);

    svObjects.Add(svObj.ID());

    svObj.Name(svName);   
    svObj.ValueType(ivtBinary);
    svObj.ValueSubType(istAlarm);
    svObj.ValueName0("nicht ausgelöst");
    svObj.ValueName1("ausgelöst");    
    !svObj.AlType(atSystem);
    !svObj.AlArm(true);

    svObj.ValueUnit("");   

    dom.RTUpdate(false);
}

WriteLine(svObj.State().ToString());
WriteLine(svObj.ValueName());

! Alarm auslösen
svObj.State(true);
svObj.DPInfo("Alarm - aktiv");

WriteLine(svObj.State().ToString());
WriteLine(svObj.ValueName());

Logikwert

string  svName = "testVarBool";
object  svObj  = dom.GetObject(svName);

if (!svObj){   
    object svObjects = dom.GetObject(ID_SYSTEM_VARIABLES);

    svObj = dom.CreateObject(OT_VARDP);

    svObjects.Add(svObj.ID());

    svObj.Name(svName);   
    svObj.ValueType(ivtBinary);
    svObj.ValueSubType(istBool);
    svObj.ValueName0("nicht anwesend");
    svObj.ValueName1("anwesend");    
    svObj.State(true);

    svObj.DPInfo("Logikwert test");
    svObj.ValueUnit("");

    dom.RTUpdate(false);
}

WriteLine(svObj.State().ToString());
WriteLine(svObj.ValueName());

Werteliste

string  svName = "testVarEnum";
object  svObj  = dom.GetObject(svName);

if (!svObj){   
    object svObjects = dom.GetObject(ID_SYSTEM_VARIABLES);

    svObj = dom.CreateObject(OT_VARDP);

    svObjects.Add(svObj.ID());

    svObj.Name(svName);   
    svObj.ValueType(ivtInteger);
    svObj.ValueSubType(istEnum);
    svObj.ValueList("val1;val2;val3");
    svObj.State(1);

    svObj.DPInfo("Werteliste test");

    dom.RTUpdate(false);
}

var valList = svObj.ValueList();
var val = valList .StrValueByIndex(";",svObj.Value());
WriteLine(val);

Systemvariable löschen

Muss aus irgendeinem Grund eine Systemvariable gelöscht werden, kann dies auch direkt über Homematic-Script erledigt werden.

string  svName = "testVarAlarm";
object  svObj  = dom.GetObject(svName);

WriteLine(svObj);
dom.DeleteObject(svObj.ID());
WriteLine(svObj);