
  var stdPlanZeitContainer;
  
  // Konstruktor fuer das Handling der Tabelle Stundenplanuhrzeit
  function StundenplanuhrzeitContainer () {
    var WT_TRENNER = '|';
    var WT_LEERZEICHEN = ' ';
    
    //Diese Quasi Klassenvariablen existieren auch in den inneren Funktionen und sind dort verwendbar
    var markedRow = 0;
    var markedUpdateRow = 0;
   
    // Click Event oder Double Klick Event
    var eventObj4Stundenplanuhrzeit;
    
    //Anzeige, ob OK Button im Dialog disabled wird
    var disableOkButton = false;
    
    //Instanzvariablen
    this.oddcolor = '#FFFFFF';
    this.evencolor = '#EBEBEB';
    this.aktcolor = '#FFFF00';  //Gelb
    this.aktborder = '2px solid #6C66A4';   // '#FF00FF';
    this.normalborder = '1px solid #58b548'; //grüne Rahmenlinien
    // Tabelle hier als Attribut festlegen
    this.$stdPlanzeitTable = $('#stdplanuhrzeit table.setting-htmltable');
    //
    //Hinterlegungs Tabelle ???
    /** this.hltablecolor = '#C9C9C9';
    this.hltableborder = '1px solid  #828177'; */
    
    this.initReadyhandling = initReadyhandling;
    
    // Referenz auf das Instanz-Objekt anlegen, da sich this bei der Ausführung auf die Aufrufumgebung,
    // also z.B. das window-Object oder das Element, dem der entspr. Eventhandler anhängt, bezieht und nicht auf das
    // Instanzobjekt; thisObject dagegen zeigt immer auf das Instanzobjekt (hier Stundenplanuhrzeitcontainer))
    var thisObject = this;
    //this.initTableLayout = initTableLayout;
    
    // nur Funktion initReadyhandling() soll oeffentlich sein 
    /********************************************************************************
    Initialisiert das Handling für das Laden des Dokuments mit $(..)
    *********************************************************************************/
    function initReadyhandling() {

      // initialisieren des Tabellen-Layouts
      initTableLayoutPrivat();
    
      /* Achtung: für die Initialisierung der Zeit in der Slidebar des Timepickers wird keine Einschränkung
      auf eine Kurstagzeit (von, bis) benötigt; falls doch ein vordef. Wert verwendet werden soll wie z.B.
      (beginUhrzeit = window.kurstagzeit[0]) ist zu beachten: die Variable window.kurstagzeit ist bei der initialisierung der 
      Stundenplanuhrzeit noch undefined; sie wird erst später in initAnwesenheitenary() (das aufgerufen wird in getDialogAnzeige
      im AnwesenheitAPI) belegt.
      Der Zeitbereich für die Auswahl mit Timepicker wird hier NICHT eingeschränkt
       */
           
      $('.hasTimePicker','div#dialog_stundenplanuhrzeit').timepicker({ });

       //Öffnen Button für den Dialog mit den Stundenplanuhrzeiten
      $('#button_insert').on('click', function(event) {
        // Event hier in globaler Variable speichern (ist nötig für den Dialog)
        eventObj4Stundenplanuhrzeit = event;
        //Beim Insert Datum und Uhrzeit auf alle Fälle neu Vorbesetzen

        var $inputVon = $('input#von','#dialog_stundenplanuhrzeit');
        var $inputBis = $('input#bis','#dialog_stundenplanuhrzeit');
        var $inputHoehe = $('input#hoehe','#dialog_stundenplanuhrzeit');    
        var $inputPause = $('input#pause','#dialog_stundenplanuhrzeit');

        // Vorbesetzung beim Klick auf insert    
        var jetzt = new Date();
        $inputVon.val(FormatTime(jetzt));
        var bistime = jetzt.getTime() + (60*60*1000);
        var bis = new Date(bistime);
        $inputBis.val(FormatTime(bis));
        $inputHoehe.val('48');
        $inputPause.prop('checked',false);
        openDialog('Eintragen');  
        // prevent the default action, e.g., following a link
        return false;
      }); //end Insert Clickhandler
	
      // Submithandler zum Abschicken des Formulars; damit kann man sich  UpdateHiddenObjectField() und das Sortieren beim initialisieren sparen
     //TODO evtl. mit ajax machen ????
     /**
     jQuery('document').on('submit','#settingsform',function() {
      // $('form').on('submit', function() {
        generiereHiddenString();
      }); // End submithandler  **/
   
     //AjaxPost Klickhandler ist bereits eingebunden an dioeser Stelle (siehe tools.js)
   
     // jQuery('input.ajaxpost').on('click', ajaxPost);
   
	
      //Check auf gültige Einträge mit Hilfe des mouseleave-Events (change event führt zu Problemen beim Timepicker)
      $('input.hasTimePicker','#dialog_stundenplanuhrzeit').on('mouseleave', checkEntriesAreValid);
      $('#ui-datepicker-div').on('mouseleave', checkEntriesAreValid);

      $('input#hoehe','#dialog_stundenplanuhrzeit').on('mouseleave', checkEntriesAreValid);


      // Achtung: Die Events für Update und delete (also $('#button_update').on('click', function(event) {..}); werden jetzt nicht mehr als
      // anonyme Funktionen ausgegeben. Die dafür relevanten Funktionen deleteEntryhandler (etc.) werden nur bei nicht leerer Tabelle als
      // Clickevents an die entspr. Buttons gebunden

      // Dialog für Einfügen bzw. Bearbeiten von Stundenplanuhrzeiten
      $('#dialog_stundenplanuhrzeit').dialog({ 
        autoOpen:  false, 
        title:     '', 
        width: 380,
        modal:     true,
        buttons:   {
            "Ok": function() {
                  //alert("disableButton: " + disableOkButton + "|");
                  if (!disableOkButton) { 
                          // Event hier in globaler Variable speichern
                          var eventobj = eventObj4Stundenplanuhrzeit;				
                          //alert("eventtype ind dialogupd= " + eventobj.handleObj.type + "; eventtarget: " + eventobj.target + " event tar id: " + eventobj.target.id);
                          var tableName = '#stdplanuhrzeit table.setting-htmltable';
                          //Bei vorausgehendem Click auf das  Bearbeiten Symbol wird ein Eintrag eingefügt
                          if (eventobj.handleObj.type == "click" && eventobj.target.id == "button_insert") 
                            insertEntry2ObjectTable($(this),$('tbody', tableName));
                          else  //bei dblclick bzw.live Event oder Klick auf #button_update wird nur Update durchgeführt
                          updateEntryofObjectTable($(this),$(tableName));

                        //  Nach dem Insert/ Update werden die Tabelenwerte noch nach der Zeit sortiert
                        sortTableEntries();

                          $(this).dialog("close");
                  } //end disableOkButton

          },  //end function
            "Abbrechen": function() { $(this).dialog("close"); }
	} //end buttons
      }); //end dialog
      
	
      /** Handling der Klick-Events: Bei einfachem Klick nur die gewählte Tabellenzelle highlighten (markieren)
      /**  bei Doppelklick: Zelle markieren und Dialog aufrufen 
      /** hierbei: eventhandler an tbody knüpfen; dann muss NICHT fuer jedes neu erzeugte tr Element
          ein Eventhandler angehängt werden;
        Achtung:      
	Auch bereits gespeicherte Werte werden bearbeitet (im Ggs. zur Unterrichtsmittelarea in klassebuch.js: dort
         werden Einträge, die bereits in der DB stehen nicht mehr bearbeitet (erkennbar am Wert in td.blockimg)
      */
      var clicks = 0;
      $(document).on('click', '#stdplanuhrzeit .setting-htmltable tbody', function(event) {
        clicks++;
        if (clicks == 1) {
          setTimeout(
            function(){
              if(clicks == 1) {
                // $('#log').text('Single-Click Action');
                  myHighlight(event);
                  eventObj4Stundenplanuhrzeit = event; // Event hier in globaler Variable speichern
              } 
              else {
                // $('#log').text('Double-Click Action');
                myHighlight(event);
                eventObj4Stundenplanuhrzeit = event; // Event hier in globaler Variable speichern
                //alert("eventtype dblclick in clicks= " + event.handleObj.type);

                // markiertes TR Element aus der Objekttabelle
                var $source = $('#zeile_' + markedRow,'#stdplanuhrzeit .setting-htmltable');
                var $target = $('#dialog_stundenplanuhrzeit');
                // kopiert die Werte von aus der Tabelle der Unterrichtsdmittelarea in die Inputfelder des Dialogs
                getObjFieldsfromTable2Dialog($source,$target);
                openDialog('Bearbeiten');
              } //end else
              //event.preventDefault();
              clicks = 0;
            }, //end function
          400); //end setTimeout(..)
				}
      }); //end Clickhandler
	 
  } //end initReadyhandling
  
  //****************************************************************************************************
  /* Alle anderen Methoden (außer initReadyHandling) im StundenplanuhrzeitContainer sollen privat bleiben
  /*  daher nicht mit this....   zur Verfuegung stellen                                       **********/
 
   //öffnet den Dialog für StundenplanUhrzeiten
  function openDialog(pHandling) {
    //Check erfolgt vor dem Öffnen, damit die richtigen Fehlerausgaben nicht erst nach dem  ersten Mouseleave Event erscheinen
    checkTimeEntriesValid(); 
    
    KuferTools.InitAllgemeineHandler($('#dialog_stundenplanuhrzeit'));
    
    $('#dialog_stundenplanuhrzeit').dialog('open');
    // Dialog Titel überschreiben
    $('#dialog_stundenplanuhrzeit').dialog('option','title',pHandling + ' von Uhrzeiten:');
  }
 
 /**
 * Initialisiert allgemeine Handler, z. B. Datepicker.
 * 
 * Kann z.B. nach dem Aufruf von Dialogen aufgerufen werden, damit 
 * die neuen Elemente ebenfalls mit z.B. Datepicker initialisiert werden.
 * 
 * @param Selector $pContainer Selector auf das Containerelement mit den 
 *                             noch nicht selektierten Elementen
 */
KuferTools.InitAllgemeineHandler = function( $pContainer )
{
  //Allgemeinen Kalender zuweisen.
  KuferTools.InitDatePicker($('.hasDatePicker', $pContainer));
  
  //Kalender für die Anwesenheiten
  KuferTools.InitDatePicker($('input.date', $pContainer));
  
  //Kalender für vierstellige Jahreszahl
  KuferTools.InitDatePicker($('input.val_date', $pContainer));
  
  //Kalender mit Uhrzeit
  KuferTools.InitDateTimePicker($('input.val_datetime', $pContainer));
  
  //Kalender für zweistellige Jahreszahl
  $('input.val_date_jahrkurz', $pContainer).datepicker( {
    changeYear: true,
    constrainInput: true,
    dateFormat: "dd.mm.y",
    yearRange: 'c-80:c+10'
    //dateFormat: "D., dd.mm.y" //angezeigtes Datumsformat
  });
  
  $('input.hasTimePicker').timepicker({});
  $('input.val_time').timepicker({});
  
  $('textarea[maxlength]', $pContainer).on('input', function(){
    var max = parseInt($(this).prop('maxlength'));
    if($(this).val().length > max) {
      $(this).val($(this).val().substring(0, $(this).prop('maxlength')));
    }
  });
};

 
  // wird hier anonym deklariert; waere auch anders mgl.
  function initTableLayoutPrivat() {
    var $aktTabcontent = $('#stdplanuhrzeit .setting-htmltable');

    // alert("in initTableLayout evencolor: " + thisObject.evencolor);
   // $('tr',$aktTabcontent).css('border',thisObject.normalborder);
    /**
    $('tr:even',$aktTabcontent).css('background-color',thisObject.evencolor);
    $('tr:odd',$aktTabcontent).css('background-color',thisObject.oddcolor); */

    var zeilenid = 0;
    $aktelem = $('tr#zeile_' + zeilenid, $aktTabcontent);
    $aktelem.css({'border':thisObject.aktborder});
    //$('td:not(.blockimg)',$aktelem).css('background-color','yellow');
    $aktelem.css('background-color',thisObject.aktcolor); //gelb

    // Falls kein Eintrag in der Tabelle vorhanden ist, ist Löschen bzw. Bearbeiten nicht möglich; dann wird nur der
    //  Einfügen Button angezeigt 

    //global einmal setzen:
    //Die Buttons für Updaten und Löschen, die nicht angezeigt werden, wenn kein Eintrag vorhanden ist
    $buttons4FilledTable = $('.onlyForEntries','div#buttonleiste4stdplan_vert');
    $buttonclasses =  [];
    $buttons4FilledTable.each(function(i) {
      $buttonclasses[i] = $($buttons4FilledTable[i]).prop('class');
    })
  
    var $aktTrElemsinTbody = $aktTabcontent.children('tbody').find('tr');
    // var akttrlen = $aktTrElemsinTbody.length;
    
    //Clickhandler müsssen noch an den Buttons gehängt werde; daher ist 2ter Parameter: true
    showRequiredTableButtons($aktTrElemsinTbody, true);
    markedRow = zeilenid;
  } // end initTableLayoutPrivat()

  /*
    Holt die Werte aus der Tabelle für Stundenplanuhrzeit und schreibt sie in die Inputfelder des  Dialog
  */
  function getObjFieldsfromTable2Dialog($source,$target) {
    // Holt Werte aus der Tabelle; Objekt id wird versteckt im td.blockimg mitgeschleppt
    var id = $('td.blockimg',$source).text();
    var von = $('td.von',$source).text();
    var bis = $('td.bis',$source).text();
    var hoehe = $('td.hoehe',$source).text();
    var pause = $('td.pause',$source).text();
    // Besetzt die Inputfelder im Dialog
    $('#von',$target).val(von);
    $('#bis',$target).val(bis); 
    $('#hoehe',$target).val(hoehe);
    $('#pause',$target).prop('checked', pause == 'ja');
  }  
    
    
  /*
   * Funktion für den Delete Click event (nicht mehr anonym)
   *  Löschen ist hier moeglich,denn ein Eintrag ist noch vorhanden (ansonsten ist der Event nicht angehängt)
   *  keine Unterscheidung auf neu eingetragene Werte ( wie bei den Unterrichtsmitteln in klassenbuch.js)        
   */     
  function deleteEntryHandler() {
 
    // if (!isempty($target.children('tr').html()))
    deleteEntryfromObjectTable(markedRow, '#zeile_');
    // else
    //   showMessage('Löschen ist nicht möglich: kein Eintrag vorhanden', 'Hinweis');
    return false; 
  }

   //Funktion für den DeleteAll Click event
  function deleteEntryHandler4All() {
    var $target = $('tbody','#stdplanuhrzeit table.setting-htmltable');
    while (!isempty($target.children('tr').html())) {
      
       deleteEntryfromObjectTable(markedRow,'#zeile_');
    }
    return false; 
  }
    
  /*
   * Funktion für den Update Click event (nicht mehr anonym)
   *  Update ist hier immer moeglich (ein Eintrag ist hier nämlich vorhanden; ansonsten ist der Event nicht angehängt);
   *  keine Unterscheidung auf neu eingetragene Werte ( wie bei den Unterrichtsmitteln  in klassenbuch.js)        
   */          
  function updateEntryHandler(event) {
     // Event hier in globaler Variable speichern (ist nötig für den Dialog)
     eventObj4Stundenplanuhrzeit = event;
     // markiertes TR Element aus der Stundenplanuhrzeittabelle
     var $source = $('#zeile_' + markedRow,'#stdplanuhrzeit table.setting-htmltable');
     var $target = $('#dialog_stundenplanuhrzeit');
     // kopiert die Werte aus der Tabelle stdplanuhrzeiten in die Inputfelder des Dialogs
     getObjFieldsfromTable2Dialog($source,$target);
     openDialog('Bearbeiten');
           return false;  
  }


  // Löscht einen Eintrag aus der Objekt Tabelle und reorganisiert diese
  function deleteEntryfromObjectTable(zeilenindex,id4ObjZeile) {
    // z.B. id4ObjZeile = '#zeile_'
    var $target = $('tbody','#stdplanuhrzeit table.setting-htmltable');
    var $table = $('#stdplanuhrzeit table.setting-htmltable');
    var removestr = id4ObjZeile + zeilenindex;
    var $tableTr = $table.find('tr');
    var $delTrValue = $(removestr,$target);
    // Dieser Wert muß evtl. noch aus anderen Input Einträgen entfernt werden
    //var $delTdInhalt = $('td.Stundenplanuhrzeit',$delTrValue);
    $tableTr.remove(removestr);

    //Tabelle reorganisieren, falls noch ein Eintrag vorhanden ist 
    //jetzt die neuen Kinder zum Ermitteln der übriggebliebenen TableRows 
    $tableTrNew = $target.children();
    tablelen = $tableTrNew.length;

    //hier z.B.: 'zeile' statt '#zeile' verwenden, d.h. 1tes Zeichen aus String weglassen
    zeilenstr = id4ObjZeile.substring(1);
    $tableTrNew.each( function(index) {
       $(this).prop('id',zeilenstr + index);
    });
     
    //Standardfärbung
    $target.find('tr').even().css('background-color',thisObject.evencolor);
    $target.find('tr').odd().css('background-color',thisObject.oddcolor);
    // Nach dem Löschen die Markierung auf das 1te Element in der Tabelle setzen, da das bisher markierte
    // dann nicht mehr vorhanden ist
    markedRow = 0;
    $aktTrNew =  $target.find(id4ObjZeile + markedRow);
    $aktTrNew.css({'border':thisObject.aktborder});
    $aktTrNew.css('background-color',thisObject.aktcolor);
    //Clickhandler hängen noch an den Buttons und werden daher nicht benötigt; daher ist 2ter Parameter: false
    showRequiredTableButtons($tableTrNew, false);
    
    stdPlanZeitContainer.generiereHiddenString();
  } //end deleteEntryfromObjectTable()

  /**
   * Gibt die für die Tabelle benötigten Clickbuttons aus
   * Wenn die Tabelle leer ist, wird nur ein Insert Button ausgegeben. Update- und Deletebuttons werden
   * in diesem Fall nicht benötigt.
   * 
   * @param jQuery Objekt $pTableRows
   * @param boolean pAttachHandler gibt an, ob die Clickhandler an die Buttons angehängt werden sollen
   * @returns {undefined}
   */
  function showRequiredTableButtons($pTableRows, pAttachHandler) {
    var rowLen = $pTableRows.length;
    // Falls die Tabelle leer ist,  werden die Update und Delete Buttons ausgehängt
    if (rowLen == 0) {
      $buttons4FilledTable.detach();
    }
    else {
      // Tabelle enthält Einträge: wieder alle Buttons anzeigen; das erste Kindelement ist der 
      // Button zum Einfügen eines Elements
     
      $('#buttonleiste4stdplan_vert').children().first().after($buttons4FilledTable);
      
      //setzt die Clickhandler für die Delete und Update Buttons nur, falls diese vorhanden sind
      if (pAttachHandler === true)
        setClickhandler4DeleteAndUpdate();
    } //end else  
  } //end showRequiredTableButtons()


  //Setzt die Klickhandler für die Delete und Update Buttons, die zur Tabelle gehören
  function setClickhandler4DeleteAndUpdate() {
    
    var $img4update = $('#button_update','div#buttonleiste4stdplan_vert');
    var $img4delete = $('#button_delete','div#buttonleiste4stdplan_vert');
    var $img4deleteall = $('#button_deleteall','div#buttonleiste4stdplan_vert');
   
    $img4delete.on('click', deleteEntryHandler);
    $img4update.on('click', updateEntryHandler);
    $img4deleteall.on('click', deleteEntryHandler4All); 
    
  } //end setClickhandler4DeleteAndUpdate()


  // ACHTUNG!!!! bezieht sich auf TBODY Element
  // Markiert das aktuell ausgewählte Tabellenfeld
  // hier wird zum Ermitteln des aktuell angeklickten Elements event.target verwendet
  function myHighlight(eventobj) {
    //Hier gilt: $(this) ist ein  Tbody Element
    // event.target bezieht sich auf das aktuell angeklickte DOM Element, also tr#zeile_i
    // (hier nicht event.currentTarget verwenden; das bezieht sich auf das DOM Element des Clickhandlers,
    //  also tbody)
    $aktTBody = $(eventobj.currentTarget);
    
    // var $target = $('tbody','#stdplanuhrzeit table.setting-htmltable');
     
    $aktTrElem = $(eventobj.target).parents('table.setting-htmltable tr');
    // alert ('eventtyp in highlight:  ' + eventobj.handleObj.type + ' //  aktbody: ' + $aktTBody.html());
    var zeile = $aktTrElem.prop('id');
    var zeilenid = zeile.split('_')[1];

    //aktTable ersetzt this
    var $aktTable = $('tbody','#stdplanuhrzeit table.setting-htmltable');
    //Hier wird die Markierung fuer alle Geschwister zurueckgesetzt; mgl. waere auch ein Ruecksetzen aller
    //Tr Elemente durch Auswahl von $(this).parent().children();
    var $allTrElemensinTable = $aktTable.children();
    $allTrElemensinTable.each( function() { 
      $(this).css('border',thisObject.normalborder);
    });
    //Standardfärbung
    $aktTBody.find('tr').even().css('background-color',thisObject.evencolor);
    $aktTBody.find('tr').odd().css('background-color',thisObject.oddcolor);
    //Das ausgewählte Tabellenelement  gesondert markieren
    $aktTrElem.css({'border':thisObject.aktborder});
    //$('td:not(.blockimg)',$aktelem).css('background-color','yellow');
    $aktTrElem.css('background-color',thisObject.aktcolor);
    markedRow = zeilenid;
  } // end myHighlight
	 
	
  /* Speichert die Werte aus dem Dialog für Stundenplanuhrzeit im Objekt-Eintrag i ab
     hier: Objekt für Stundenplanuhrzeit                    
     Achtung!!: die Objekt id wird hier nicht gebraucht  
   */
  function _restoreInput2Array($source) { 
    var objentry = new StundenplanuhrzeitEintrag();

    /* TODO:  hier spaeter die Objekt variablen direkt aus dem Objekt holen mit get_object_vars(objEntry)
        evtl. noch foreach verwenden
    objpropertyAry =   get_object_vars(objEntry);
    objproplen = objpropertyAry.length;
    for (var i = 0; i < objproplen; i++) {
      alert(" Objektvar_ " + i + " : " + objpropertyAry[i]);
      //dann eine Zuweisung wie z.B hier, das dann die Zuweisungen unten ersetzt
      objentry.objpropertyAry[i] = $('#' + objpropertyAry[i],$source);
      // hier:  evtl die ids noch per Fkt. anpassen
    }
    /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

    var objary = new Array();
    var $voninput = $('#von',$source);
    var $bisinput = $('#bis',$source);
    var $hoeheinput = $('#hoehe',$source);
    var $pauseinput = $('#pause',$source);  

    // alert ("vonval: " + $voninput.val() + "bisval: " + $bisinput.val() + "pauseval: " + $pauseinput.prop('checked'));
    objentry.von = $voninput.val();
    objentry.bis = $bisinput.val();
    objentry.hoehe = $hoeheinput.val();
    if ($pauseinput.filter(':checked').length === 0)
      objentry.pause = 'nein'; 
    else //False checkbox gesetzt ist 
       objentry.pause = 'ja'; 
    objary[0] = objentry;
      return objary;
  } //end _restoreInput2Array(..)
	
  /**
   *  Checkt ob der Input im Dialog OK ist und damit upgedatet werden kann
   * @param $source enthält den Dialog (also dialog_stundenplanuhrzeit)td
   */   	
  function checkDialogInput($source) {
    if ($('#von',$source).val() <= $('#bis',$source).val())
      return 1;
    else 
      return 0; 
  }
	
	
  // Konstruktorfunktion fuer einen einzelnen Stundenplanuhrzeiteintrag
  function StundenplanuhrzeitEintrag() {
    this.von = '';
    this.bis = '';
    this.hoehe = '';
    this.pause = '';
    this.getObjlength = getObjlength;
  }
  
  /*
    liefert die Länge des Objekts (hier: StundenplanuhrzeitEintrag)
  */
  function getObjlength() {
    return 4;
  }
  
  /* Fügt die Werte aus dem Dialog für das Objekt (hier: Stundenplanuhrzeit) in die Tabelle der ausgewählten 
     Stundenplanuhrzeit ein  */
  function insertEntry2ObjectTable($source, $target) {
    var ObjAry = new Array();
    
    if (checkDialogInput($source) === 1) {
      ObjAry = _restoreInput2Array($source);

      //Danach Objekte aus dem Array in die ObjektTable übernehmen (hier: Stundenplanuhrzeit)
      fillObjTablefromArray(ObjAry,$target);
    }
    else 
      showMessage('Unpassender Wert im Dialog', 'Hinweis'); 
  }//end insertEntry2ObjectTable
    
  //  
  this.generiereHiddenString = function() {  
  
  // function generiereHiddenString() {
    var hiddenstring = ''; 
    $('#stdplanuhrzeit table.setting-htmltable').find('tr.zeilenindex').each(function(index, item) {
      $item = $(item);
      hiddenstring += $item.find('td.von').html() + WT_TRENNER;
      hiddenstring += $item.find('td.bis').html() + WT_TRENNER;
      hiddenstring += $item.find('td.hoehe').html() + WT_TRENNER;
      hiddenstring += $item.find('td.pause').html() + WT_TRENNER;
    });
    $('#stdplanuhrzeit_hidden').val(hiddenstring);
    console.log(hiddenstring);
    // Returnwert für Submithandler bei erfolgreichem Aufbau des Hiddenstrings
    return true;
  }
 
  /* Holt die Werte aus dem Objekt Array und fügt sie in die Tabelle der ausgewählten Objekte ein  
    hier: verwendet als Input ein Array von Stundenplanuhrzeit Einträgen
  */ 
  function fillObjTablefromArray(objary,$target) {
    // hier objary ist Array von Stundenplanuhrzeiten, wobei es nur ein Element ist, da nur je
    // ein Stundenplanuhrzeiteintrag eingefügt bzw. bearbeitet wird
    var objlen = objary.length;
    /* Beste Variante:   last-child Selektor  */
    var $lasttrchild = $('tr:last-child',$target);
   
    var removelastentry = false;
    if ($lasttrchild.is(':not(' + null + ')')) {
      // Gibt die Position an ab der die Indizes als zeilen id attribut in das <tr> Element eingefügt werden sollen
      var position4insert = $('tr',$target).index($lasttrchild);

      // Hier muss das tr- Element vorher korrekt angelegt worden sein, also z.B. <tr id = "zeile_1">
      // Ein Zeileneintrag ohne <td>s oder mit leeren tds wird entfernt, da er falsch ist
      if ($lasttrchild.has('td').html() != null) {
        //falls das einzige tr Element leer ist, wird zunächst dieses aufgefüllt;
        if (isEmptyTdinLastTrElem($lasttrchild)) {
          if (objlen >=1)
            removelastentry = true;      
        }
      }  //end if lasttrchild has td
     
      var offset4remove = 0
        //alert ("lasttrchild cmp: " + $lasttrchild.is(':not(' + null +')') + " objlen: " + objlen); 
        //letzten Eintrag nur einmal entfernen
      if (removelastentry == true) {
        $lasttrchild.remove();
        //jetzt das letzte Kind nach dem Enfernen nehmen (also das voher vorletzte)
        $lasttrchild = $('tr:last-child',$target);
        removelastentry = false;
        offset4remove = 1;
      }
      // alert("position4ins: " + position4insert + "  objlen: " + objlen + " offset4remove: " + offset4remove);        
      if (position4insert > 0 ) {
        for (var i = objlen -1 ; i >= 0; i--) {
          var zeilind = position4insert + i + 1 - offset4remove;
          // HTML-String Darstellung fuer das neue TR Element, das hinten angehängt wird 
          var $neuesTr = getNewTrElement(objary[i],zeilind);

         //  $neuesTr.on('click', myHighlight4singleTr);
           $lasttrchild.after($neuesTr);   
        }
      } //end if position4insert > 0
     
      // jetzt ist ein leeres tr Element (ohne td Inhalt) enthalten das zunächst gelöscht wird
      else {
        //hier wurde das Element enfernt, wenn es leer war (s.o.)
        for (i=0 ; i < objlen; i++) {
          var zeilind = position4insert + i + 1 - offset4remove;
          var $neuesTr = getNewTrElement(objary[i],zeilind);

          //$neuesTr.on('click', myHighlight4singleTr);                
          $target.append($neuesTr);   
        }    //end for  
      } //end else
    } // end if is(':not(null)')
    // Tabelle mit Objekten (hier: Stundenplanuhrzeiten) ist  komplett leer (enthält nicht mal tr Elemente)
    else {
      for (i=0 ; i < objlen; i++) {
        var $neuesTr = getNewTrElement(objary[i],i);
        // $neuesTr.on('click', myHighlight4singleTr);
        $target.append($neuesTr);
      } //end for
     
      //die Buttons zum Updaten und löschen wieder hinzufügen, falls noch nicht vorhanden
      //Clickhandler hängen noch an den Buttons und werden daher nicht benötigt; daher ist 2ter Parameter: false
      showRequiredTableButtons($('tr',$target), false);
    } //end else
   
    //ungerade und gerade Zeilen farblich markieren
    $('tr:even',$target).css('background-color',thisObject.evencolor);
    $('tr:odd',$target).css('background-color',thisObject.oddcolor);
    $('tr',$target).css('border',thisObject.normalborder);
    $aktelem = $('#zeile_' + markedRow, $target);
    $aktelem.css({'border':thisObject.aktborder});
    //$('td:not(.blockimg)',$aktelem).css('background-color','yellow');
    $aktelem.css('background-color',thisObject.aktcolor);
    
    stdPlanZeitContainer.generiereHiddenString();
  } //end fillObjTablefromArray(  )


  /**
  * Checkt, ob bestimmte TD El4emente im letzten TR Element leer sind
  * diese TDs sollten nicht leer sein; Falls sie leer sind wird dieses TR-Element entfernt
  */
  function isEmptyTdinLastTrElem($pLasttrchild) {
    if ($('td.von',$pLasttrchild).text() === '' || $('td.bis',$pLasttrchild).text() === '') 
      return true;
    return false; 
  }


  /**
    liefert ein neu angelegtes <TR> Element für die Tabelle
    AryElem ist hier ein StundenplanuhrzeitEintrag
    die Objekt id wird im td.blockimg versteckt
  */
  function getNewTrElement(AryElem,index) {
    /* TODO: hier evtl. spaeter auch get_object_vars() verwenden; dazu:
    var objEntry = new StundenplanuhrzeitEintrag();
    var objpropertyAry =   get_object_vars(objEntry);
    var  objproplen = objpropertyAry.length;
    var tdelemspart = '';
    foreach (objpropertyAry as prop) {
      
      tdelemspart += '<td class="' + prop + '">' + AryElem.prop + '</td>' ;
     //diesen dann ins <tr..> einfügen 
    }
    *************************************************************************************/
    // Man könnte noch eine versteckte id im td.blockimg abspeichern (wird aber nicht gebraucht)
    $newtr = $('<tr id = "zeile_' + index + '" class="zeilenindex">' + "\n" +
                        '<td class="blockimg"></td>' + "\n" +
                        '<td class="von">' + AryElem.von + '</td>' + "\n" +
                        '<td class="bis">' + AryElem.bis + '</td>' + "\n" +
                        '<td class="hoehe">' + AryElem.hoehe + '</td>' + "\n" +
                        '<td class="pause">' + AryElem.pause + '</td>' + "\n" +
                        '</tr>' + "\n");
    markedRow = index;                    
    return $newtr;
  } //end getNewTrElement(..)


  /**
  ändert den Inhalt der Tabellenobjekte
  das sind hier Zeilen mit Stundenplanuhrzeit Elementen
  Achtung!!: die Objekt id wird hier nicht gebraucht
  */
  function updateEntryofObjectTable($source,$target) {
    if (checkDialogInput($source) === 1) {
      var $updateelement = $('tr#zeile_' + markedRow,$target);
      //alert ("markedRow: " + markedRow + "updateelem: " + $updateelement.html());
      var objentry = new StundenplanuhrzeitEintrag();
      objentry.von = $('#von',$source).val();
      objentry.bis = $('#bis',$source).val();
      objentry.hoehe = $('#hoehe',$source).val();
      if ($('#pause',$source).filter(':checked').length === 0)
        objentry.pause = 'nein'; 
      else //False checkbox gesetzt ist 
        objentry.pause = 'ja'; 
      $('td.von',$updateelement).text(objentry.von);
      $('td.bis',$updateelement).text(objentry.bis);
      $('td.hoehe',$updateelement).text(objentry.hoehe);
      $('td.pause',$updateelement).text(objentry.pause);    
      
      stdPlanZeitContainer.generiereHiddenString();
    } //end  if (checkDialogInput($source)...
    else 
      showMessage('Unpassender Wert im Dialog', 'Hinweis'); 
  }  //end updateEntryofObjectTable



  /**
   *  Prüft, ob die im Dialog eingegebenen Werte gültig sind
   *  Prüft alle vorhandenen Input Werte ab
   */
  function checkEntriesAreValid() {
    var checkresult = true;
    // Falls das gecheckte Feld Input#hoehe ist: zuerst die eingegebene Zahl und dann ggf. die Zeitwerte prüfen
    if ($(this).prop('id') == 'hoehe') {
      checkresult = checkNumberIsValid();
      if (checkresult)
        checkresult = checkTimeEntriesValid();
    }
    else {
     // Jetzt die Zeitwerte und dann ggf. die eingegebene Zahl  prüfen
      checkresult = checkTimeEntriesValid();
      if (checkresult)
        checkresult = checkNumberIsValid();
      }
  } //end checkEntriesAreValid()
  

  
  /**
   *  Prüft, ob die eingegebene Zeitwerte im zulässigen Bereich liegen und konsistent sind
   *  Verhindert eine Überlagerung mit bereits in der Tabelle angegebenen Zeitbereichen
   *  Bei fehlerhafter Eingabe wird der OK Button blockiert
   */
  function checkTimeEntriesValid(event) {  
    var isInsertEvent = false;
    var eventobj = eventObj4Stundenplanuhrzeit;
    if (eventobj.handleObj.type == "click" && eventobj.target.id == "button_insert")
      isInsertEvent = true;
   // alert("Event: Type " + eventobj.handleObj.type + " target id: " + eventobj.target.id + "  isinsertevent: " + isInsertEvent);

    $inputvon = $('#von');
    $inputbis = $('#bis');
    var eingabe = true;
    var errortext = '';
    var vonZeitval = $inputvon.val();
    var bisZeitval = $inputbis.val();

    //Wichtig: Regexp mit new generieren und global weglassen
    var regexp4time = new RegExp('(([0-2][0-9])(:)([0-5][0-9]))');
    var testvon = regexp4time.test(vonZeitval);
    var testbis = regexp4time.test(bisZeitval);
    if (testvon && testbis) {
      if (vonZeitval <= bisZeitval) {
        var checkresult = checkTimesinTable(vonZeitval,bisZeitval,isInsertEvent);
        // Falls eine Zeitüberlappung vorliegt: entsprechenden Fehlertext ausgeben
        if (checkresult[0]) {
          errortext = checkresult[1];
          eingabe = false;
        }    
      }
      else {
        eingabe = false;
        errortext = 'Falsches Zeitintervall: Bitte wählen Sie für die "Von Uhrzeit" einen kleineren Wert als für die "Bis Uhrzeit".'; 
      }
    } //end if (testvon...
    else {
      var startOrEnd = '';
      eingabe = false; 
      if (!testvon) 
        startOrEnd = 'Start';
      else
        startOrEnd = 'End';
      errortext = 'Ungültige ' + startOrEnd + 'uhrzeit angegeben';    
    }
    //checkresult[0] ist overlap; Bei Überschneidung (overlap= true) ist Eingabewert false
    showFaultMessageinDialog(eingabe,errortext);   
    return eingabe;   
  } // end checkTimeEntriesValid()
  
  
  
  /**
   *  Prüft, ob die angegebene Zeit innerhalb eines bereits vorhandenen Zeitintervalls der Stundenplanzeit Tabelle liegt
   *  Bei Überlappung mit einem bereits vorhandenem Zeitintervall wird eine entspr. Fehlermeldung ausgegeben
   */
  function checkTimesinTable(pVonZeit, pBisZeit, pIsInsertEvent) {
    var $tabrows = thisObject.$stdPlanzeitTable.find('tr.zeilenindex');
    var overlap = false;
    var errortext = '';
    var tdvonzeit = '';
    var tdbiszeit = '';
    var tdbiszeitprevious ='';
    var tdvonzeitnext = '';
    /* $firstTrElemen etc. werden jetzt doch NICHT benötigt
    var $firstTrElement = $('tr:first',$stdplanzeittable);
    */
    var anzahlTrElems = $tabrows.length;

    //zunächst muss man ein Array der  Beginn und Endzeiten zu den einzelnen Zeileneinträgen aufbauen
    var tableRowTimeAry = new Array();
      $tabrows.each(function(rowindex,row) {
      tdvonzeit = $(row).find('td.von').text();
      tdbiszeit = $(row).find('td.bis').text();
      tableRowTimeAry[rowindex] = new Array (tdvonzeit,tdbiszeit); 
    });
     
    // Danach werden die Überschneidungen des aktuellen Zeiteintrags mit den Tabelleneinträgen gecheckt
    $tabrows.each(function(rowindex,row) {
      tdvonzeit = $(row).find('td.von').text();
      tdbiszeit = $(row).find('td.bis').text();
      // Grenzen für das Updaten sind durch die Zeiten der benachbarten Intervalle gegeben
      if (rowindex > 0)
        tdbiszeitprevious = tableRowTimeAry[rowindex-1][1];
      if (rowindex < anzahlTrElems-1)
        tdvonzeitnext = tableRowTimeAry[rowindex+1][0];  
      // Update ist innerhalb der Grenzen, die durch die durch benachbarter Zeitintervalle gegeben sind, möglich
      if (markedRow > 0 && markedRow < anzahlTrElems-1) {
        if (tdbiszeitprevious <= pVonZeit && pBisZeit <= tdvonzeitnext) {
          //return false ist hier notwendig, um die Schleife zu beenden
          if (markedRow == rowindex && !pIsInsertEvent)
            return false;
        }
      //Hier gibt es Überschneidungen mit einem oder mehreren Vorgänger bzw. Nachfolgerintervall(en) -> weiter mit 
      // Sammeln aller Zeitüberschneidungen
      }
         
      // Sonderfall für Update : NUR für den ersten bzw. letzten Eintrag, kann man das Zeitintervall nach vorne bzw. hinten 
      // verlängern;  aktuelle Zeile ist in markedRow gespeichert (via myHighlight)
      if ((markedRow == 0 &&  pBisZeit <= tdvonzeitnext) || ( markedRow == anzahlTrElems-1 && tdbiszeitprevious <= pVonZeit)) {
        if (markedRow == rowindex) {
          //   alert("marked: " + markedRow + "  bisprevious: " + tdbiszeitprevious + "rowind: " + rowindex);
          if (!pIsInsertEvent)  
            return false;
        }
      }
        
      // Sammeln der Zeitüberschneidungen:
      //Wenn Einfügeintervall (beim Insert) innerhalb irgendeines vorhandenen Tabellenintervalls liegt: Überschneidung 
      if (tdvonzeit <= pVonZeit && pBisZeit <= tdbiszeit) {
        if (pIsInsertEvent) {
          overlap = true;
          errortext = 'Zeitraum überschneidet sich mit: <br>' + tdvonzeit + ' - ' + tdbiszeit;
          return false;
        }
      }
         
      // Sammeln aller anderen Zeitüberschneidungen; keine Unterscheidung zwischen Insert und Update nötig (via pIsInsertEvent)
      if ((tdvonzeit <= pVonZeit && pVonZeit < tdbiszeit && pBisZeit > tdbiszeit)  ||
          (pVonZeit  < tdvonzeit && pBisZeit > tdvonzeit && pBisZeit < tdbiszeit)  ||
          (pVonZeit < tdvonzeit && pBisZeit > tdbiszeit)) {
        overlap = true;
        if (errortext == '') {
          errortext = 'Zeitraum überschneidet sich mit: ';
        }
        errortext += '<br> ' + tdvonzeit + ' - ' + tdbiszeit;   
        //hier wird die Schleife nicht abgebrochen, um alle Zeitüberschneidungen zu sammeln  
      }
      if (pBisZeit <= tdbiszeit) 
        return false;
    }); // end each(function)
     
     
    // alert("overlap: " + overlap + " nach each tdvonbis: " + tdvonzeit + " - " + tdbiszeit);
    var retourary = new Array();
    retourary[0] = overlap;
    retourary[1] = errortext;
    return retourary;
  } //end checkTimesinTable(
  
  
  
  /**
  *  Prüft, ob die eingegebene Zahl im zulässigen Bereich liegt
  *  Bei fehlerhafter Eingabe wird der OK Button blockiert
  */
  function checkNumberIsValid() {
    var inputZahl = $('#hoehe').val();
    var maxwert = 100;
    var errortext = '';
    var errortex4wrongNumber = " Eingabewert  " + inputZahl + " ist fehlerhaft. Bitte geben Sie einen Wert zwischen 1 und " + maxwert + " ein.";
    var eingabe = false
    //Checkt ob Eingabe ein Integer ist
    if (inputZahl != '') { 
      if(parseInt(inputZahl) == inputZahl-0) { 
        inputZahl = inputZahl-0;
        if (inputZahl >= 1 && inputZahl <= maxwert)
          eingabe = true;
        else
          errortext = errortex4wrongNumber;
      }
      else 
        errortext = errortex4wrongNumber;
    }
    else 
      errortext = "Leere Eingabe ist nicht zulässig. Bitte geben Sie einen Wert zwischen 1 und " + maxwert + " ein.";

    showFaultMessageinDialog(eingabe,errortext);
    return eingabe;
  } // end checkNumberIsValid
    
    
  /**
   * Gibt eine Fehlermeldung im Dialog aus und blockiert gleichzeitig den OK Button
   * @param boolean pEingabe Angabe, Eingabewert fehlerhaft ist
   * @param string Error Text
   */
  function showFaultMessageinDialog(pEingabe,pErrortext) {
    var $dialogfaultfield = $('#dialogfault','#dialog_stundenplanuhrzeit');
    if (pEingabe == false) { 
      //alert("dialogfaulfield: " + $dialogfaultfield.html());
      //Falls noch kein Faultfield im DOM Baum hängt
      if ($dialogfaultfield.length == 0) {
        var dialogfaultfield = '<div id="dialogfault">' + pErrortext + '</div>';
        $('#dialog_stundenplanuhrzeit').append(dialogfaultfield);
      }
      else
        $dialogfaultfield.html(pErrortext);
      disableOkButton = true;    
    }
    else {
      if ($dialogfaultfield.length != 0)
        $dialogfaultfield.html('');   
      disableOkButton = false;  
    }       
  } //end showFaultMessageinDialog
    
  /*
   * Vergleicht zwei HTML-Objekte aufgrund der  Zeiteinträge
   * returnwert -1 bedeutet a >= b 
   */
  function compareByTimevalues(a, b) {
    var $a = $(a);
    var $b = $(b);
    var a_von = $a.find('td.von').text();
    var a_bis = $a.find('td.bis').text();
    var b_von = $b.find('td.von').text();
    var b_bis = $b.find('td.bis').text();
    if(a_von == b_von ) {
      if (a_bis <= b_bis)
        return -1;
      return 1;
    } 
    else {
      if (a_von <= b_von)
        return -1;
      return 1;
    }
  } //end compareByTimevalues(..)
  
 
  /**
  *   Sortiert die Tabelleneinträge aufsteigend nach der Zeit
  *  Hierbei zu beachten: Die neu sortierte Menge der <tr> Elemente muss (nach Enfernen der alten Elemente) an das TBody 
  *   Element angehängt werden; danach werden die Zeilenindizes der TR Elemente noch umkopiert
  */
  function sortTableEntries() { 
    var $sortableTableTrFields = thisObject.$stdPlanzeitTable.find('tr.zeilenindex','table.stdplanuhrzeiten');
    // alert("markedRow in sort: " + markedRow);

    $sortableTableTrFields.sort(compareByTimevalues);
    // Entfernen der alten  und Anhängen der neuen, sortierten TR Elemente
    $('tbody',thisObject.$stdPlanzeitTable).remove('tr.zeilenindex');
    $('tbody',thisObject.$stdPlanzeitTable).append($sortableTableTrFields);  

    // Umkopieren der Zeilenindizes; hierbei muss auch der markierte Index markeRow umkopiert werden
    var markedRowAfterSortfound = false;
    var idAttributValue = '';
    $sortableTableTrFields.each(function(rowindex,row) {
      //Wert aus dem id Attribute des Elements; ist  z.B. 9 für #zeile_9
      idAttributValue = $(row).prop('id').split('_')[1] - 0;
      //markedRow auf den Index des markierten Elements nach der Sortierung setzen
      if (idAttributValue == markedRow && !markedRowAfterSortfound) {
        markedRow = rowindex;
        //an dieser Stelle wurde die markierte Zeile zum ersten Mal gefunden und bleibt dort auch
        markedRowAfterSortfound = true;
      }
      $(row).prop('id', 'zeile_' + rowindex);
    }); //end each
  }  // end sortTableEntries
} //end StundenplanuhrzeitContainer



/*************************************************************************************************************
 Jquery Events die beim Laden des Dokuments bereitgestellt werden und beim entspr. Handling (z.B. Anklicken)
 ausgeloest werden 
***************************************************************************************************************/

// Methode zum Bereitstellen von Stundenplanuhrzeiten und Events dazu; wird durch PHP Methode initJS4StundenplanUhrzeit()
// in Klasse libSettingDruckliste beim Laden der Seite aufgerufen
function loadJSHandling4Stundenplanuhrzeit() {
  /** Via Stundenplanuhrzeitcontainer werden die Events und Funktionen zur Bearbeitung von Stundenplanuhrzeiten bereitgestellt */
  /**************************************************************************************************/
  if (typeof stdPlanZeitContainer === 'undefined')
    stdPlanZeitContainer = new StundenplanuhrzeitContainer();
 
  // Ready Handler muß beim Neuladen der Seite neu initialisiert werden, um die Clickhandler und den Eingabedialog
  //anzubinden
  stdPlanZeitContainer.initReadyhandling();
  
  //Achtung: generateHiddenString4Post wird beim Klick auf ein neues Navigationselement in Methode loadContent (in global.js)
  //auf null zurückgesetzt 
  if (KuferTools.generateHiddenString4Post === null) {
    // Die Funktion wird nur für den StundenplanZeitContainer (also bei Verwenden der StundenplanUhrzeit Tabelle) gebraucht;
    // wird beim Absenden des Formulars für die ganze Seite in Methode ajaxPost gebraucht (in global.js)
    KuferTools.generateHiddenString4Post = function() {
      // der Hiddenstring wird nur für den stundenplanuhrzeitContainer in Tool Kursübersicht für Firmen erzeugt
      // if (typeof stdPlanZeitContainer !== 'undefined')
      stdPlanZeitContainer.generiereHiddenString();
    }
  }
} // end loadJSHandling4Stundenplanuhrzeit()