ulrich
2018-03-30 403f2ffa55f68f4b6c4dfa6cb168227b24cb501c
Vorlage fertig und dokumentiert
5 files modified
332 ■■■■■ changed files
app.css 7 ●●●● patch | view | raw | blame | history
app.js 6 ●●●●● patch | view | raw | blame | history
index.html 21 ●●●● patch | view | raw | blame | history
jslib/app-menu/app-menu.js 256 ●●●● patch | view | raw | blame | history
readme.md 42 ●●●●● patch | view | raw | blame | history
app.css
@@ -3,6 +3,7 @@
  padding: 0;
  height: 100%; /* Anmerkung 2 */
  font-size: larger;
  font-family: 'Roboto Condensed';
}
body {
  min-height: 0; /* Anmerkung 1 */
@@ -14,6 +15,7 @@
  flex-flow: row;
  height: 100%; /* Anmerkung 2 */
  min-height: 0; /* Anmerkung 1 */
  background-color: #ededed;
}
.nord {
  background-color: black;
@@ -37,7 +39,7 @@
.ost {
  flex-grow: 0;
  flex-shrink: 0;
  flex-basis: 10em;
  flex-basis: 6em;
  background-color: antiquewhite;
}
.zentrum {
@@ -45,6 +47,7 @@
  height: 100%;
  overflow: auto;
  -webkit-overflow-scrolling: touch;
  padding: 0.5em;
}
/*
@@ -56,6 +59,6 @@
*/
.app-titel {
  margin-left: 2em;
  margin-left: 0.6em;
  color: white;
}
app.js
@@ -1,8 +1,10 @@
function AppVorlage() {
  var self = this;
  var appMenu;
  this.init = function() {
    app_menu_init(
    self.appMenu = new AppMenu();
    self.appMenu.init(
      "data/menu/",
      "hauptmenue.json",
      "jslib/app-menu/app-menu.tpl",
@@ -16,6 +18,6 @@
  this.app_menue_umschalten = function() {
    $(".hamburger").toggleClass("is-active"); // hamburger-icon umschalten
    app_menu_toggle(); // menue oeffnen/schliessen
    self.appMenu.toggle(); // menue oeffnen/schliessen
  };
}
index.html
@@ -1,10 +1,10 @@
<!DOCTYPE html>
<html>
  <head>
    <title>App-Layout</title>
    <title>App-Vorlage</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" type="text/css" href="jslib/app-menu/nav-toggle.css">
    <link href="https://fonts.googleapis.com/css?family=Roboto+Condensed" rel="stylesheet">
    <link rel="stylesheet" type="text/css" href="jslib/app-menu/app-menu.css">
    <link rel="stylesheet" type="text/css" href="hamburger.css">
    <link rel="stylesheet" type="text/css" href="app.css">
@@ -20,7 +20,7 @@
        </div>
      </div>
      <div class="app-titel">
        <span id="app-titel">App-Titel</span>
        <span id="app-titel">App-Vorlage</span>
      </div>
    </div>
    <div class="inhalt">
@@ -31,7 +31,18 @@
      <!-- zentraler Inhaltsbereich -->
      <div class="zentrum">
        <p>
          Inhalt hier...
          Hier kann beliebiger Inhalt erscheinen.
        </p>
        <p>
          Wenn dessen Darstellung mehr
          Platz ben&ouml;tigt als das Anzeigeger&auml;t bietet wird ein
          Rollbalken eingeblendet. Beim Rollen zu anfangs nicht sichtbaren
          Teilen des Inhalts bleiben die den Inhaltsbereich
          umschlie&szlig;enden Elemente sichtbar.
        </p>
        <p>
          Ein Klick auf das Hamburger-Piktogramm oben links bzw. dessen
          Antippen blendet ein Men&uuml; ein.
        </p>
      </div>
      <!-- oestliche Seitenleiste -->
@@ -43,7 +54,7 @@
    <div class="sued">
      Fußzeile
    </div>
    <!-- Skripte -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/mustache.js/2.3.0/mustache.min.js"></script>
    <script src="jslib/app-menu/app-menu.js"></script>
jslib/app-menu/app-menu.js
@@ -1,141 +1,137 @@
/*
 * die nachfolgenden Funktionen steuern das ein- und
 * ausblenden des menues
 */
function app_menu_init(url_prefix, mdesc, mtpl, mselector, mbreite) {
  _app_menu_selector = mselector;
  _app_menu_mbreite = mbreite;
  /*document.querySelector( "#nav-toggle" ).addEventListener("click", function() {
    app_menu_toggle();
  });*/
  $(_app_menu_selector).css("flex-basis", "0em");
  _app_menu_url_prefix = url_prefix;
  $.get(mtpl, function(template) {
    _app_menu_template = template;
    Mustache.parse(_app_menu_template);   // optional, speeds up future uses
function AppMenu() {
  var self = this;
  var _app_menu_selector;
  var _app_menu_mbreite;
  var _app_menu_url_prefix = "";
  var _app_menu_template;
  /*
   * die nachfolgenden Funktionen steuern das ein- und
   * ausblenden des menues
   */
  this.init = function (url_prefix, mdesc, mtpl, mselector, mbreite) {
    self._app_menu_selector = mselector;
    self._app_menu_mbreite = mbreite;
    /*document.querySelector( "#nav-toggle" ).addEventListener("click", function() {
      app_menu_toggle();
    });*/
    $(self._app_menu_selector).css("flex-basis", "0em");
    self._app_menu_url_prefix = url_prefix;
    $.get(mtpl, function(template) {
      self._app_menu_template = template;
      Mustache.parse(self._app_menu_template);   // optional, speeds up future uses
      var menuDiv = $("<div/>");
      $(menuDiv).addClass('app-menu-content');
      $(menuDiv).css('position', "relative");
      $(menuDiv).css('left', '-300px');
      $(menuDiv).css('right', '0px');
      $(self._app_menu_selector).append(menuDiv);
      self.app_menu_laden(mdesc);
    });
  };
  this.app_menu_do_toggle = function(elem) {
    /*document.querySelector( "#nav-toggle" ).classList.toggle( "active" );
    document.querySelector( "#nav-toggle" ).blur();*/
    self.toggle();
  };
  this.toggle = function() {
    /*document.querySelector( "#nav-toggle" ).classList.toggle( "active" );
    document.querySelector( "#nav-toggle" ).blur();*/
    var menuDiv = $(self._app_menu_selector);
    if($(menuDiv).hasClass('app-menu-open')) {
      $(menuDiv).removeClass('app-menu-open');
      $(menuDiv).css("flex-basis", "0em");
    } else {
      $(menuDiv).addClass('app-menu-open');
      $(menuDiv).css("flex-basis", self._app_menu_mbreite); // z.B. "16em"
    }
  };
  /*
   * ab hier Steuerung des Menueinhalts
   */
  /*
   * mdesc: der URL einer JSON-Datei mit einer Menuebeschreibung
   */
  this.app_menu_laden = function(mdesc, richtung) {
    $.ajax({
      url: self._app_menu_url_prefix + mdesc,
      type: "GET",
      dataType : "json"
    }).done(function( json ) {
      self.app_menu_bauen(json, richtung);
    });
  };
  this.app_menu_bauen = function(menuejs, richtung) {
    // Endposition des bestehenden Menues beim Wechsel herauf
    var linksEndeAlt = "500px";
    var rechtsEndeAlt = "600px";
    // Anfangsposition des neuen Menues beim Wechsel herauf
    var linksAnfangNeu = "-300px";
    var rechtsAnfangNeu = "-1px";
    // Endposition des neuen Menues beim Wechsel herauf
    var linksEndeNeu = "0px";
    var rechtsEndeNeu = "300px";
    if(richtung === 'herunter') {
      // Endposition des bestehenden Menues beim Wechsel herunter
      linksEndeAlt = "-300px";
      rechtsEndeAlt = "-1px";
      // Anfangsposition des neuen Menues beim Wechsel herunter
      linksAnfangNeu = "500px";
      rechtsAnfangNeu = "600px";
      // Endposition des neuen Menues beim Wechsel herunter
      linksEndeNeu = "0px";
      rechtsEndeNeu = "300px";
    }
    var menuDiv = $("<div/>");
    $(menuDiv).addClass('app-menu-content');
    $(menuDiv).css('position', "relative");
    $(menuDiv).css('left', '-300px');
    $(menuDiv).css('right', '0px');
    $(_app_menu_selector).append(menuDiv);
    $(menuDiv).css('left', linksAnfangNeu);
    $(menuDiv).css('right', rechtsAnfangNeu);
    $(menuDiv).html(Mustache.render(self._app_menu_template, menuejs));
    app_menu_laden(mdesc);
  });
}
    $('.app-menu-content').delay(100).animate(
      {left: linksEndeAlt },
      100,
      function() {
        $('.smenu').attr('onclick','').unbind('click');
        $('.bitem').attr('onclick','').unbind('click');
        $('.mitem').attr('onclick','').unbind('click');
        $(self._app_menu_selector).empty();
function app_menu_do_toggle(elem) {
  /*document.querySelector( "#nav-toggle" ).classList.toggle( "active" );
  document.querySelector( "#nav-toggle" ).blur();*/
  app_menu_toggle();
}
        $(self._app_menu_selector).append(menuDiv);
        $('.smenu').on('click', self.app_menu_klick_herunter);
        $('.bitem').on('click', self.app_menu_klick_herauf);
        $('.mitem').on('click', self.app_menu_ausfuehren);
function app_menu_toggle() {
  /*document.querySelector( "#nav-toggle" ).classList.toggle( "active" );
  document.querySelector( "#nav-toggle" ).blur();*/
  var westDiv = $(_app_menu_selector);
  if($(westDiv).hasClass('app-menu-open')) {
    $(westDiv).removeClass('app-menu-open');
    $(westDiv).css("flex-basis", "0em");
  } else {
    $(westDiv).addClass('app-menu-open');
    $(westDiv).css("flex-basis", _app_menu_mbreite); // z.B. "16em"
  }
}
        $('.app-menu-content').delay(100).animate({left: linksEndeNeu });
        $('.app-menu-content').animate({right: rechtsEndeNeu });
      }
    );
    $('.app-menu-content').animate({right: rechtsEndeAlt });
  };
/*
 * ab hier Steuerung des Menueinhalts
 */
  this.app_menu_klick_herunter = function() {
    self.app_menu_laden($(this).attr('data-verweis'), 'herunter');
  };
var _app_menu_url_prefix = "";
var _app_menu_template;
var _app_menu_selector;
var _app_menu_mbreite;
  this.app_menu_klick_herauf = function() {
    self.app_menu_laden($(this).attr('data-verweis'), 'herauf');
  };
/*
 * mdesc: der URL einer JSON-Datei mit einer Menuebeschreibung
 */
function app_menu_laden(mdesc, richtung) {
  $.ajax({
    url: _app_menu_url_prefix + mdesc,
    type: "GET",
    dataType : "json"
  }).done(function( json ) {
    app_menu_bauen(json, richtung);
  });
  this.app_menu_ausfuehren = function() {
    var functionName = $(this).attr('data-verweis');
    eval(functionName + "(this)");
  };
}
function app_menu_bauen(menuejs, richtung) {
  // Endposition des bestehenden Menues beim Wechsel herauf
  var linksEndeAlt = "500px";
  var rechtsEndeAlt = "600px";
  // Anfangsposition des neuen Menues beim Wechsel herauf
  var linksAnfangNeu = "-300px";
  var rechtsAnfangNeu = "-1px";
  // Endposition des neuen Menues beim Wechsel herauf
  var linksEndeNeu = "0px";
  var rechtsEndeNeu = "300px";
  if(richtung === 'herunter') {
    // Endposition des bestehenden Menues beim Wechsel herunter
    linksEndeAlt = "-300px";
    rechtsEndeAlt = "-1px";
    // Anfangsposition des neuen Menues beim Wechsel herunter
    linksAnfangNeu = "500px";
    rechtsAnfangNeu = "600px";
    // Endposition des neuen Menues beim Wechsel herunter
    linksEndeNeu = "0px";
    rechtsEndeNeu = "300px";
  }
  var menuDiv = $("<div/>");
  $(menuDiv).addClass('app-menu-content');
  $(menuDiv).css('position', "relative");
  $(menuDiv).css('left', linksAnfangNeu);
  $(menuDiv).css('right', rechtsAnfangNeu);
  $(menuDiv).html(Mustache.render(_app_menu_template, menuejs));
  $('.app-menu-content').delay(100).animate(
    {left: linksEndeAlt },
    100,
    function() {
      $('.smenu').attr('onclick','').unbind('click');
      $('.bitem').attr('onclick','').unbind('click');
      $('.mitem').attr('onclick','').unbind('click');
      $(_app_menu_selector).empty();
      $(_app_menu_selector).append(menuDiv);
      $('.smenu').on('click', app_menu_klick_herunter);
      $('.bitem').on('click', app_menu_klick_herauf);
      $('.mitem').on('click', app_menu_ausfuehren);
      $('.app-menu-content').delay(100).animate({left: linksEndeNeu });
      $('.app-menu-content').animate({right: rechtsEndeNeu });
    }
  );
  $('.app-menu-content').animate({right: rechtsEndeAlt });
}
function app_menu_klick_herunter() {
  app_menu_laden($(this).attr('data-verweis'), 'herunter');
}
function app_menu_klick_herauf() {
  app_menu_laden($(this).attr('data-verweis'), 'herauf');
}
function app_menu_ausfuehren() {
  var functionName = $(this).attr('data-verweis');
  eval(functionName + "(this)");
}
function app_menu_test() {
  alert("Test");
}
function app_menu_test_2() {
  alert("Test 2");
}
readme.md
@@ -1,3 +1,43 @@
# App-Vorlage
Eine Vorlage für Webanwendungen
Eine nur aus HTML, CSS und Javascript bestehende Bedienoberfläche für Apps, die ohne Anpassung am Code auf verschiedenen Geräten funktioniert.
## Eigenschaften
Diese Vorlage etabliert eine Bedienoberfläche für Apps. Sie gruppiert Menü, Kopf- und Fußzeile sowie eine Seitenleiste um einen zentralen Bereich, dessen Inhalt nach unten aus dem sichtbaren Teil der Anzeige herausläuft, wenn der Platz auf der Anzeige nicht ausreicht. Beim Rollen des Inhalts bleiben die umliegenden Elemente sichtbar.
Der Inhalt des Menüs kann über Beschreibungsdateien an unterschiedliche Belange angepasst  und über eine Schaltfläche ein- und ausgeblendet werden. Die Menübeschreibungen müssen in der Javascript Object Notation (JSON) verfasst sein und können beliebig in eine hierarchische Struktur von Untermenüs verschachtelt werden.
## Demo
Aussehen und Funktionsweise der App-Vorlage kann mit der [Demo](/data/ulrich/test/app-vorlage/) angesehen und ausprobiert werden.
## Verwendung
Zur Verwendung der App-Vorlage wird der Inhalt dieses Repository auf einem HTTP-Server wie z.B. [Tomcat](https://de.wikipedia.org/wiki/Apache_Tomcat) oder [lighttpd](https://de.wikipedia.org/wiki/Lighttpd) hinterlegt. Anschließend kann die App-Vorlage mit dem Uniform Resource Locator (URL) im Webbrowser aufgerufen und ausgeführt werden, der sich aus ihrem Ablageort auf dem Server ergibt.
#### Add to Home Screen
Die App-Vorlage schafft die Grundlage für Apps, die sich neben der universellen Ausführbarkeit in einem Webbrowser auch in einem Schritt auf einem Schlaufon oder Tafelrechner installieren und ausführen lassen, wie es gewöhnlich nur Apps aus dem App Store des Geräteherstellers erlauben.
Wird die App-Vorlage beispielsweise mit Safari auf einem iPhone oder iPad aufgerufen, kann mit folgenden Schritten die App dem Startbildschirm des Gerätes hinzugefügt werden:
+ Schritte
+ hier
+ noch
+ aufzählen
Anschließend ist die App durch einfaches Antippen ihres Piktogrammes direkt vom Startbildschirm  ausführbar wie eine App aus dem App Store. Diese Vorgehensweise funktioniert in vergleichbarer Weise mit Chrome auf Android-Geräten.
## Abhängigkeiten
Damit der Code der App-Vorlage einfach geladen und so wie er ist ausprobiert werden kann sind folgende Abhängigkeiten aus dem Content Delivery Network [CDNJS](https://cdnjs.com/) eingebunden:
+ [jQuery](https://jquery.com)
+ [Mustache](https://mustache.github.io/)
Ferner ist folgender Zeichensätz aus [Google Fonts](https://fonts.google.com/) eingebunden
+ [Roboto Condensed](https://fonts.google.com/specimen/Roboto+Condensed)
Diese Abhängigkeiten sollten während dem produktiven Einsatz auf dem Server hinterlegt werden, von dem aus die App-Vorlage ausgeliefert wird und von dort eingebunden sein.