Bedienoberfläche für Webradio
ulrich
2018-02-21 d5964df47de25159c8591f1fbe86ce7801d75009
app.js
@@ -3,69 +3,351 @@
var TPL_SENDER = 'sender';
var TPL_DLG_MSG = 'dlg-msg';
var TPL_DLG_INFO = 'dlg-info';
var TPL_DLG_SENDER = 'dlg-sender';
var TPL_DLG_SENDER_NEU = 'dlg-sender-neu';
var TPL_DLG_SENDER_EDIT = 'dlg-sender-edit';
var TPL_DLG_SENDER_DEL = 'dlg-sender-del';
var TPL_SENDER_EDIT_FORM = 'sender-edit-form';
var TPL_SENDER_KACHEL = 'sender-kachel';
var TPL_ABSPIELER = 'abspieler';
var TPL_DLG_ABSPIELER_NEU = 'dlg-abspieler-neu';
var TPL_DLG_ABSPIELER_EDIT_FORM = 'dlg-abspieler-edit-form';
var TPL_DLG_ABSPIELER_DEL = 'dlg-abspieler-del';
var TPL_ABSPIELER_EINTRAG = 'abspieler-eintrag';
var templateCache = {}; // mustache templates
var prefsRendered = false;
var senderKlickModus = "1"; // 1=abspielen, 2=bearbeiten, 3=loeschen
var ID_UNDEFINED = -1;
var A_ID_UNDEFINED = -1;
var suchTimeout;
function app_init() {
  $('.sued').text('Initialisieren..');
  $('.dialog').hide();
  $('.ost').hide();
  app_menu_init("data/menu/", "hauptmenue.json", "../jslib/app-menu/app-menu.tpl", ".west", "8em");
  // Menü initialisieren
  app_menu_init(
    "data/menu/",
    "hauptmenue.json",
    "../jslib/app-menu/app-menu.tpl",
    ".west",
    "8em");
  // Templates laden
  app_get_template('data/tpl/dlg-msg.tpl', TPL_DLG_MSG);
  app_get_template('data/tpl/dlg-info.tpl', TPL_DLG_INFO);
  app_get_template('data/tpl/sender.tpl', TPL_SENDER);
  app_get_template('data/tpl/dlg-sender-edit.tpl', TPL_DLG_SENDER);
  //app_get_template('tpl/prefs.tpl', 'prefs');
  $('.sued').text('Bereit.');
  app_get_template('data/tpl/dlg-sender-neu.tpl', TPL_DLG_SENDER_NEU);
  app_get_template('data/tpl/dlg-sender-edit.tpl', TPL_DLG_SENDER_EDIT);
  app_get_template('data/tpl/dlg-sender-loeschen.tpl', TPL_DLG_SENDER_DEL);
  app_get_template('data/tpl/dlg-sender-edit-form.tpl', TPL_SENDER_EDIT_FORM);
  app_get_template('data/tpl/kachel.tpl', TPL_SENDER_KACHEL);
  app_get_template('data/tpl/abspieler.tpl', TPL_ABSPIELER);
  app_get_template('data/tpl/dlg-abspieler-neu.tpl', TPL_DLG_ABSPIELER_NEU);
  app_get_template('data/tpl/abspieler-eintrag.tpl', TPL_ABSPIELER_EINTRAG);
  app_get_template('data/tpl/dlg-abspieler-loeschen.tpl', TPL_DLG_ABSPIELER_DEL);
  app_get_template('data/tpl/dlg-abspieler-edit-form.tpl', TPL_DLG_ABSPIELER_EDIT_FORM);
  // Klicks auf das Hamburger-Menü-Icon an eine Funktion leiten
  $(".hamburger").on("click", function(e) {
    app_menue_umschalten();
  });
  // Eingaben ins Suchfeld an eine Funktion leiten
  $(".sendersuche-eingabe").on('keyup', function() {
    clearTimeout(suchTimeout);
    suchTimeout = setTimeout('app_sendersuche()', 500);
  });
  // Abspieler und Sender laden
  setTimeout(function() {
    app_get_abspieler();
    app_get_sender();
    $('.sued').text('Bereit.');
  }, 200);
}
function app_sendersuche() {
  var suchbegriff = $(".sendersuche-eingabe").val();
  app_meldung_mit_timeout(
    'Suchbegriff: ' + suchbegriff,
    1500
  );
  /*
    nachfolgend wird ueber alle divs der Klasse sender-kachel
    iteriert und diejenigen mit .hide() ausgeblendet, die nicht
    den Suchbegiff im Namen tragen
    evtl. findet sich spaeter noch eine elegantere Suchfunktion..
  */
  var divs = $(".sender-kachel");
  if(suchbegriff.length > 0) {
    divs.each(function(index, element) {
      if ($(element).html().indexOf(suchbegriff) < 0) {
        $(element).hide();
      } else {
        $(element).show();
      }
    });
  } else {
    $(divs).show();
  }
}
function app_menue_umschalten() {
  $(".hamburger").toggleClass("is-active"); // hamburger-icon umschalten
  app_menu_toggle(); // menue oeffnen/schliessen
}
/* Abspieler und abspielen */
function app_get_abspiel_ziel() {
  var opt = $(".abspieler-auswahl :selected");
  var atyp = opt.attr("atyp");
  var aname = opt.text();
  var aurl = opt.attr("aurl");
  var zustand = opt.attr("standardzustand");
  return new Abspieler(-1, aname, aurl, atyp, "", zustand);
}
/*
  Abspiel-URL für Raspi:
  http://raspi:8080/pirc/sys/rpc?c=de.uhilger.pirc.App&m=abspielen&p=http://bob.hoerradar.de/radiobob-live-mp3-hq&p=
  der folgende Aufruf übergibt zusätzlich einen Parameter zum Abspielen über
  das Audiokabel (nicht das HDMI-Kabel) des Raspi (sofern angeschlossen)
  http://raspi-wz:8080/pirc/sys/rpc?c=de.uhilger.pirc.App
  &m=abspielenMitParametern&p=http://bob.hoerradar.de/radiobob-live-mp3-hq
  &p=-o%20local&p=
*/
function app_abspielen(sender, abspieler) {
  var url;
  if(abspieler.typ === 'pirc') {
    url =
      abspieler.url +
      '/sys/rpc?c=de.uhilger.pirc.App&m=abspielenMitParametern&p=' +
      sender.url +
      '&p=-o%20local&p=';
    app_radio_kommando_senden(url);
  } else {
    url = sender.url;
    var win = window.open(url, '_blank');
    win.focus();
  }
}
function app_abspielen_stoppen() {
  var abspieler = app_get_abspiel_ziel();
  if(abspieler.typ === 'pirc') {
    var url =
      abspieler.url +
      '/sys/rpc?c=de.uhilger.pirc.App&m=kommando&p=q';
    app_radio_kommando_senden(url);
  } else {
    // 'hier abspielen' stoppen muss noch gebaut werden
  }
}
function app_abspieler_neu(abspieler) {
  var html = Mustache.render(templateCache[TPL_ABSPIELER_EINTRAG], abspieler);
  if(abspieler.zustand === 'selected') {
    $.each($(".abspieler-auswahl option:selected"), function() {
       $(this).prop('selected', false);
    });
  }
  $(".abspieler-auswahl").append(html);
}
function app_abspieler_entfernen(abspieler) {
  $(".abspieler-auswahl :selected").remove();
}
/* Senderliste */
function app_kachel_anpassen(sender) {
  var kachel = $( "div[sid='" + sender.id + "']" );
  kachel.find(".sender-name").text(sender.name);
  kachel.attr("data-verweis", sender.url);
  kachel.find("img").attr("src", sender.logo);
}
function app_kachel_neu(sender) {
  var html = Mustache.render(templateCache[TPL_SENDER_KACHEL], sender);
  $("#sender").append(html);
  var kachel = $( "div[sid='" + sender.id + "']" );
  kachel.on('click', app_kachel_klick);
}
function app_kachel_entfernen(sender) {
  $( "div[sid='" + sender.id + "']" ).remove();
}
function app_kachel_klick() {
  var kachel = $( this );
  var senderId = kachel.attr("sid");
  var senderName = kachel.find(".sender-name").text();
  var senderUrl = kachel.attr("data-verweis");
  var senderLogo = kachel.find("img").attr("src");
  var s = new Sender(senderId, senderName, senderUrl, senderLogo);
  switch (senderKlickModus) {
      case "1":
        app_abspielen(s, app_get_abspiel_ziel());
        break;
      case "2":
        $(".dlg-behaelter").html(
          Mustache.render(templateCache[TPL_SENDER_EDIT_FORM], s)
        );
        $('#sender-speichern').on('click', function() {
          $('#sender-speichern').off('click');
          app_kachel_anpassen(app_sender_dialog_lesen(senderId));
          app_dialog_schliessen();
          app_meldung_mit_timeout('Speichern gewaehlt', 1500);
        });
        break;
      case "3":
        app_dialog_zeigen(templateCache[TPL_DLG_SENDER_DEL], s);
        /*
        $(".dlg-behaelter").html(
          Mustache.render(templateCache[TPL_DLG_SENDER_DEL], s)
        );
        */
        $('#sender-loeschen').on('click', function() {
          $('#sender-loeschen').off('click');
          app_kachel_entfernen(s);
          app_dialog_schliessen();
          app_meldung_mit_timeout('Loeschen gewaehlt ' + s.name, 1500);
        });
        //app_menue_umschalten();
        break;
      default:
        app_meldung_mit_timeout(
          'Sender ' + s.name + ', ID ' + s.id,
          1500
        );
        break;
  }
}
/* --- Menüfunktionen --- */
function app_nachricht_test() {
  app_dialog_laden_und_zeigen(templateCache[TPL_DLG_MSG], 'data/msg-test.json');
  app_menu_toggle();
  app_dialog_laden_und_zeigen(
    templateCache[TPL_DLG_MSG], 'data/msg-test.json');
  app_menue_umschalten();
}
function app_info_dialog_zeigen() {
  app_dialog_laden_und_zeigen(templateCache[TPL_DLG_INFO], '');
  app_menu_toggle();
  app_menue_umschalten();
}
function app_neuer_sender() {
  app_dialog_laden_und_zeigen(templateCache[TPL_DLG_SENDER], '');
  app_dialog_laden_und_zeigen(templateCache[TPL_DLG_SENDER_NEU], '');
  $('#sender-speichern').on('click', function() {
    $('#sender-speichern').attr('onclick','').unbind('click');
    $('#sender-speichern').off('click');
    app_kachel_neu(app_sender_dialog_lesen(--ID_UNDEFINED));
    app_dialog_schliessen();
    app_meldung_mit_timeout('Speichern gewaehlt', 1500);
  });
  app_menu_toggle();
  app_menue_umschalten();
}
function app_sender_bearbeiten() {
  app_meldung_mit_timeout('Nicht implementiert: Sender bearbeiten.', 1500);
  app_menu_toggle();
  senderKlickModus = "2"; // bearbeiten
  app_dialog_laden_und_zeigen(templateCache[TPL_DLG_SENDER_EDIT], '');
  app_menue_umschalten();
}
function app_sender_loeschen() {
  app_meldung_mit_timeout('Nicht implementiert: Sender loeschen.', 1500);
  app_menu_toggle();
  senderKlickModus = "3"; // loeschen
  app_dialog_laden_und_zeigen(templateCache[TPL_DLG_SENDER_EDIT], '');
  app_menue_umschalten();
}
function app_abspieler_loeschen() {
  var abspieler = app_get_abspiel_ziel();
  app_dialog_zeigen(templateCache[TPL_DLG_ABSPIELER_DEL], abspieler);
  $('#abspieler-loeschen').on('click', function() {
    $('#abspieler-loeschen').off('click');
    app_abspieler_entfernen(abspieler);
    app_dialog_schliessen();
    app_meldung_mit_timeout('Loeschen gewaehlt ' + abspieler.name, 1500);
  });
  app_menue_umschalten();
}
function app_neuer_abspieler() {
  app_dialog_laden_und_zeigen(templateCache[TPL_DLG_ABSPIELER_NEU], '');
  $('#abspieler-speichern').on('click', function() {
    $('#abspieler-speichern').off('click');
    app_abspieler_neu(app_abspieler_dialog_lesen(--A_ID_UNDEFINED));
    app_dialog_schliessen();
    app_meldung_mit_timeout('Speichern gewaehlt', 1500);
  });
  app_menue_umschalten();
}
function app_abspieler_bearbeiten() {
  var abspieler = app_get_abspiel_ziel();
  app_dialog_zeigen(templateCache[TPL_DLG_ABSPIELER_EDIT_FORM], abspieler);
  $("#abspieler-typ").val(abspieler.typ);
  $("#abspieler-zustand").val(abspieler.zustand);
  $('#abspieler-speichern').on('click', function() {
    $('#abspieler-speichern').off('click');
    // Aenderungen auf die Bedienoberflaeche uebernehmen
    var abspieler = app_abspieler_dialog_lesen();
    if(abspieler.zustand === 'selected') {
      $(".abspieler-auswahl").children().attr("standardzustand", "");
    }
    var opt = $(".abspieler-auswahl :selected");
    opt.attr("atyp", abspieler.typ);
    opt.attr("aurl", abspieler.url);
    opt.attr("standardzustand", abspieler.zustand);
    opt.text(abspieler.name);
    /*
      hier fehlt noch eine Funktion zum Speichern
      der Aenderungen
    */
    app_dialog_schliessen();
    app_meldung_mit_timeout('Speichern gewaehlt', 1500);
  });
  app_menue_umschalten();
}
/* --- Dialogfunktionen --- */
function app_dialog_zeigen(vorlage, inhalt) {
  $(".dialog").html(Mustache.render(vorlage, inhalt));
  var dlg = $(".dialog");
  dlg.html(Mustache.render(vorlage, inhalt));
  $(".close-btn").on('click', function() {
    app_dialog_schliessen();
  });
  $('.dialog').slideDown(300);
  dlg.slideDown(300);
}
function app_sender_dialog_lesen(senderId) {
  var nameNeu = $("#sender-name").val();
  var logoNeu = $("#sender-logo").val();
  var urlNeu = $("#sender-url").val();
  return new Sender(senderId, nameNeu, urlNeu, logoNeu);
}
function app_abspieler_dialog_lesen(abspielerId) {
  var aName = $("#abspieler-name").val();
  var aUrl = $("#abspieler-url").val();
  var aTyp = $("#abspieler-typ").val();
  var aBild = $("#abspieler-bild").val();
  var aZustand = $("#abspieler-zustand").val();
  return new Abspieler(abspielerId, aName, aUrl, aTyp, aBild, aZustand);
}
function app_dialog_schliessen() {
  $('.close-btn').attr('onclick','').unbind('click');
  senderKlickModus = "1";
  $('.close-btn').off('click');
  $('.dialog').slideUp(300);
}
@@ -78,9 +360,10 @@
  timeout - die Anzahl Millisekunden, die eine Meldung zu sehen sein soll
*/
function app_meldung_mit_timeout(meldung, timeout) {
  $('.sued').text(meldung);
  var s = $('.sued');
  s.text(meldung);
  setTimeout(function() {
    $('.sued').text('Bereit.');
    s.text('Bereit.');
  }, timeout);
}
@@ -92,14 +375,33 @@
    type: "GET",
    dataType : "json"
  }).done(function( senderliste ) {
    $(".sender-behaelter").html(Mustache.render(templateCache[TPL_SENDER], senderliste));
    $(".sender-kachel").off("click");
    $(".sender-behaelter").html(
      Mustache.render(templateCache[TPL_SENDER], senderliste));
    $('.sender-kachel').on('click', app_kachel_klick);
  });
}
function app_dialog_laden_und_zeigen(vorlage, adresse) {
  if(adresse !== '') {
function app_get_abspieler() {
  $.ajax({
    url: "data/abspieler.json",
    type: "GET",
    dataType : "json"
  }).done(function( abspielerliste ) {
    $(".abspieler-behaelter").html(
      Mustache.render(templateCache[TPL_ABSPIELER], abspielerliste));
    $("#abspielen-stoppen").on('click', app_abspielen_stoppen);
  });
}
/*
  vorlage - die Dialogvorlage
  msgTpl - eine Vorlage mit einem Mitteilungstext (optional)
*/
function app_dialog_laden_und_zeigen(vorlage, msgTpl) {
  if(msgTpl !== '') {
    $.ajax({
      url: adresse,
      url: msgTpl,
      type: "GET",
      dataType : "json"
    }).done(function( msg ) {
@@ -108,6 +410,35 @@
  } else {
    app_dialog_zeigen(vorlage, '');
  }
}
function app_radio_kommando_senden(kommando) {
  $.ajax({
    url: kommando,
    type: "GET",
    dataType : "text",
    crossDomain: true
  }).done(function( antwort ) {
    /*
      der folgende Schritt wird nicht erreicht, weil beim Aufruf
      aus dem Browser heraus keine Adresse aufgerufen werden darf,
      die nicht von der Domain kommt, von der aus das radio-ui
      ausgeliefert wird.
      Kommt das radio-ui z.B. von der Domain uhilger.de, wird ein Aufruf
      zur Domain raspi-az blockiert.
      Das laesst sich vermeiden, wenn der Server den Aufruf zum Raspi
      uebernimmt.
      Interessanterweise kommt der Aufruf zum Raspi durch und löst auch
      das Abspielen des Radiosenders aus. Nur die Antwort vom Raspi wird
      blockiert und hier nicht ausgegeben.
    */
    app_meldung_mit_timeout(antwort, 2000);
  }).fail(function(xhr, status, errorThrown ) {
    app_meldung_mit_timeout(errorThrown + " " + status, 2000);
  });
}
/*
@@ -124,3 +455,21 @@
    templateCache[tname] = template;
  });
}
/* Objekte */
function Sender(i, n, u, l) {
  this.id = i;
  this.name = n;
  this.url = u;
  this.logo = l;
}
function Abspieler(i, n, u, t, b, z) {
  this.id = i;
  this.name = n;
  this.url = u;
  this.typ = t;
  this.bild = b;
  this.zustand = z;
}