
    // 2 Tabs mit Loader bestücken, da noch keine Inhalte...
    // _('users').innerHTML=_('loader_template').innerHTML;
    // _('chat_inner').innerHTML=_('loader_template').innerHTML;

    function scrollzu(wohin)
    {
      if(wohin=="unten")
      {
        _('chat_scroll').scrollTo(0,top._('chat_scroll').scrollHeight);
      }
      else
      {
        //_(wohin).scrollIntoView({ behavior: `smooth`});
        _(wohin).scrollIntoView();
      }
    }

    function markiere(push_id,farbe)
    {
      farbclass1="";
      farbclass2="";
      farbclass3="";

      if(farbe=="rot")
      {
        farbclass1="marked_red";
        farbclass2="marked_green";
        farbclass3="marked_yellow";
      }
      if(farbe=="gruen")
      {
        farbclass1="marked_green";
        farbclass2="marked_red";
        farbclass3="marked_yellow";
      }
      if(farbe=="gelb")
      {
        farbclass1="marked_yellow";
        farbclass2="marked_red";
        farbclass3="marked_green";
      }
      if(farbclass1!="")
      {
        _('push_'+push_id).classList.remove(farbclass2);
        _('push_'+push_id).classList.remove(farbclass3);
        _('push_'+push_id).classList.toggle(farbclass1);
      }
    }

    function lade(initial=0)
    {
      // Tab-Link Checker pausieren, damit der nicht die URL umschreibt in Zwischenzeit
      document.data.pause_interval.value='1';

      if(typeof(aufloese_timeout)==="number")
      {
        window.clearTimeout(aufloese_timeout);
        aufloese_timeout = null;
        // console.log('alle aufloese_timeouts AUFGELÖST!');
      }

      h=document.location.pathname;
      h=h.replace(/^\//ig,"");
      h=h.replace(/\/$/ig,"");

      // Teilen am "/" in Seite und Partner:
      teile=h.split("/");
      partner=teile[0];
      partner_aus_url=partner;
      text=teile[1];

      // Standard-Div? Users!
      seite="users";

      if(partner!="")
      {
        seite="chat";
        if(text!="" && text!==undefined)
        {
          _('eingabefeld').value=decodeURIComponent(text);
          _('eingabefeld').focus();
        }
      }

      if(partner=="" && initial==1)
      {
        // wenn GARKEIN Partner: ich
        partner=ich;
        seite="users";
      }

      if(initial==1)
      {
        // nur 1 mal initial User laden!
        ajax("users","/tab_users.php?sel="+partner,{loader_custom:_('loader_template').innerHTML}); // MIT Loader, also OHNE Options!
      }

      // zum mitgegebenen DIV scrollen:
      if(typeof(siw_timeout)==="number")siw_timeout=null;
      eval("siw_timeout=window.setTimeout('scrollzu("+seite+");',100);"); // ja, das EVAL ist hier LEBENSWICHTIG!

      // anderer Name mitgegeben als der aktuelle?
      //console.log("Partner: "+document.data.partner.value+ " <> " +partner);
      if(document.data.partner.value!=partner && partner!="")
      {
        // Users IMMER laden, wenn sich das User ändert!
        //ajax("users","/tab_users.php?sel="+partner,{loader_custom:_('loader_template').innerHTML}); // MIT Loader, also OHNE Options!

        // nur wenn ich noch NICHT bei diesem Partner bin:

        if(_("#plink_"+partner))
        {
          // alle Partner links de-selecten:
          all_partners=_('.user');
          for(i=0;i<all_partners.length;i++)
          {
            all_partners[i].classList.remove('user_selected');
          }
          // Partner links selecten:
          _("#plink_"+partner).classList.add('user_selected');
        }
        // Title bestücken:
        document.title=partner;
        // Profil des Partners laden:
        ajax("chat_profil","/tab_profile.php?p="+partner,{loader_custom:_('loader_template').innerHTML});
        // rechter Tablink mit Namen beschriften:
        // _('tablink_profile').innerHTML=partner;
        // Ueb bestücken:
        _('tablink_chat').innerHTML=partner;
        // Tablinks ändern:
        _('tablink_chat').href="/"+partner;
        // Hidden-Feld bei Eingabe bestücken:
        document.data.partner.value=partner;

        // nachlade-Button zeigen:
        _z("#nachladen_button");

        // placeholder bestücken:
        _('eingabefeld').setAttribute("placeholder","schreib an "+partner);
        // Refresher-Form bestücken:
        document.data.partner.value=partner;
        // First und Last leeren, da neuer Partner:
        document.data.first_id.value="";
        document.data.last_id.value="";
        // Chat leeren, damit Nachricht "noch keine" weggeht:
        _('chat_inner').innerHTML=_('loader_template').innerHTML;
        // dann erst Chat refreshen:
        refresh_chats(0);
      }

      // Pause am Ende auflösen:
      aufloese_timeout=window.setTimeout("document.data.pause_interval.value='0';",1000);
    }

    // _('chat_scroll').addEventListener("ASDASDASDASD_scroll",
    //   function()
    //   {
    //     h1=_('chat_scroll').scrollHeight;
    //     h2=screen.height-200;
    //     h3=Math.floor(_('chat_scroll').scrollTop);

    //     //console.log("H:"+h1+","+h2+","+h3);
    //     NIEMALS_NACHLADEN=1;
    //     if(h1>h2 && h3==0 && NIEMALS_NACHLADEN==1)
    //     {
    //       console.log("OBEN nachladen!");
    //       // alle Loader im Chat oben erstmal verstecken:
    //       _r("#chat_inner > .loader");
    //       // Loader oben einsetzen (wird von hirn wieder versteckt):
    //       _('chat_inner').insertAdjacentHTML("afterbegin",_('loader_template').innerHTML);
    //       refresh_chats(1);
    //     }
    //   }
    // );

    function log_add(was)
    {
      jetzt = new Date();
      zeit=jetzt.getDate()+" "+jetzt.getHours()+":"+jetzt.getMinutes()+":"+jetzt.getSeconds();
      //_('logdiv').innerHTML=_('logdiv').innerHTML+"<br>"+zeit+": "+was;
      //alert(was);
    }

    // Tab-Links oben überwachen:

    function isInViewport(el)
    {
      const rect = el.getBoundingClientRect();
      return (
        rect.top >= 0 &&
        rect.left >= 0 &&
        rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
        rect.right <= (window.innerWidth || document.documentElement.clientWidth)
      );
    }

    function replace_buttons(txt)
    {
      return txt.replace(/\[(.+?)\]/g, '<a class=button href=\"javascript:close_malert();_(`eingabefeld`).value=`$1`;_(`eingabefeld`).focus();void(0);\" onClick=\"event.cancelBubble=true;\">$1</a>');
    }

    function update_zeiten()
    {
      zeiten_felder=_('.zeit');
      if(!zeiten_felder)return false;
      for(i=0;i<zeiten_felder.length;i++)
      {
        ts=zeiten_felder[i].getAttribute('timestamp');
        zeiten_felder[i].innerHTML=zeit_her(ts);
      }
      // Knaub, weil das Feld erst per Ajax nachgeladen wird:
      if(document.getElementById('inp_file'))document.getElementById('inp_file').addEventListener('change', fileChange, false);
    }

    function check_tablinks()
    {
      // console.log('in check_tablinks');
      if(!isInViewport(_('chat')) && !isInViewport(_('users')))
      {
        console.log('isInViewPort: KEINER!');
        lade();
        return false;
      }

      // erst alle inaktiv machen:
      alle_tabs=_(".tablink");
      for(i=0;i<alle_tabs.length;i++)
      {
        alle_tabs[i].classList.remove("aktiv");
      }

      h=document.location.pathname;
      h=h.replace(/^\//ig,"");
      h=h.replace(/\/$/ig,"");
      h="/"+h;

      // console.log('DERZEIT: '+h);

      welcher_tablink="users";
      soll_link="/";

      if(isInViewport(_('chat'))){welcher_tablink="chat";soll_link="/"+document.data.partner.value;}
      // wenn NIX genau im Viewport is:
      // if(!isInViewport(_('chat')) && !isInViewport(_('users')))scrollzu('users');

      // console.log('isInViewPort:'+welcher_tablink);

      if(welcher_tablink!="") // nur wenn genau 1 in ViewPort!
      {
        _("tablink_"+welcher_tablink).classList.add("aktiv");

        if(document.data.pause_interval.value=="1")
        {
          console.log("SKIP weil Pause!");
          return false;
        }

        // nicht verlinken, nur history ändern:
        if(h!=soll_link)history.replaceState({}, '', soll_link);//document.location.href="#"+soll_link;
      }
    }

    var timeout_diff_reloader=null;

    function update_js_uhrzeit()
    {
      // momentan deaktiviert!
      return false;

      // jetzt = new Date();
      //zeit=jetzt.getDate()+" "+jetzt.getHours()+":"+jetzt.getMinutes()+":"+jetzt.getSeconds();
      zeit2=Math.floor(Date.now()/1000);
      _("uhrzeit2").innerHTML=zeit2;

      // Differenz berechnen:
      zeit1=_('uhrzeit').innerHTML;
      if(zeit1=="")diff=0;
      else
      {
        diff=zeit2-zeit1;
        if(diff>10)
        {
          // console.log('Diff größer als 10!!! Gleich neuladen!');
          if(timeout_diff_reloader==null)
          {
            // timeout_diff_reloader=window.setTimeout("alert('Fehler!\\nTime-Diff zu groß seit 10 Sek...\\n=>Neuladen!');document.location.reload();",10000);
            timeout_diff_reloader=window.setTimeout("document.location.reload();",10000);
            // console.log("TA GESETZT:",timeout_diff_reloader);
          }

        }
        else
        {
          window.clearTimeout(timeout_diff_reloader);
          timeout_diff_reloader=null;
          // console.log('Diff-Timeout gelöscht:',timeout_diff_reloader);
        }
      }
      _('uhrzeit_diff').innerHTML=diff;
    }

    function refresh_events()
    {
      ajax("event_refresher","/hirn.php?event_refresh=1&v="+my_version);
    }

    function refresh_chats(oben=0)
    {
      if(oben==1)
      {
        // console.log("OBEN nachladen!");
        // alle Loader im Chat oben erstmal verstecken:
        _r("#chat_inner > .loader");
        // Loader oben einsetzen (wird von hirn wieder versteckt):
        _('chat_inner').insertAdjacentHTML("afterbegin",_('loader_template').innerHTML);
      }
      ajax("chat_refresher","/hirn.php?chat_refresh=1&partner="+document.data.partner.value+"&first_id="+document.data.first_id.value+"&last_id="+document.data.last_id.value+"&oben="+oben);
    }

    // Links:
    var merke_alle_links=[];
    function alle_links_aendern()
    {
      alle_links=_("a");
      for(i=0;i<alle_links.length;i++)
      {
        //console.log('attr:'+alle_links[i].getAttribute("href"));
        if(merke_alle_links.includes(alle_links[i])!==true) // nur wenn er noch NICHT gesetzt wurde!!!
        {
          merke_alle_links.push(alle_links[i]);

          alle_links[i].addEventListener("click",
            function (event)
            {
                // console.log('komplettes Event zum Analysieren:',event);
                if(event.srcElement.attributes.href) // nur wenn es ein richtiger Link ist mit ZIEL!!!!
                {
                  if(event.srcElement.attributes.href.value.search(/javascript:/)!==0)
                  {
                    event.preventDefault(); // damit der Klick nicht wirklich stattfindet!

                    href_ziel=event.srcElement.attributes.href.value;

                    // console.log('clicked:',href_ziel);

                    window.history.pushState( {} , '', href_ziel );
                    lade();
                  }
                }
            },
          false);
        }
      }
    }

    // wenn jemand über die Browsertasten navigiert:
    window.addEventListener(
      "popstate",
      function(event) {
        btasten_ziel=event.target.location.pathname;

        // console.log("per Browsertaste zu:",btasten_ziel);

        lade();
      },
      false
    );

    // Eingabefeld:
    function focus_eg()
    {
      window.setTimeout("_('eingabefeld').style.height=_('eingabefeld').style.maxHeight;_z('anhang');scrollzu('unten');",100);
    }

    function blur_eg()
    {
      if(_('eingabefeld').value=="")window.setTimeout("_('eingabefeld').style.height=_('eingabefeld').style.minHeight;_v('anhang');",100);
    }

    function sende_form()
    {
      get_shared_key(document.data.public_key_partner.value).then(
        function(key)
        {
          encrypt(key).then(
            function(true_or_false)
            {
              if(true_or_false==true)
              {
                ajax("post_absenden","/hirn.php?partner="+encodeURIComponent(document.data.partner.value)+"&iv="+encodeURIComponent(document.eingabe.iv.value)+"&cipher="+encodeURIComponent(document.eingabe.cipher.value));
              }
              else
              {
                // alert("Kein Text eingegeben");
              }
            }
          );
        }
      );
    }

    _('#eingabefeld').addEventListener ("keydown", function (e) {
      if (e.keyCode == 13 && (navigator.platform.match("Mac") ? e.metaKey : e.ctrlKey))
      {
        e.preventDefault();
        sende_form();
        return;
      }

    });
    // / Eingabefeld

    // INTERVALLE:
    // müssen im äußersten Scope definiert werden, damit sie in allen Funktionen erreichbar sind...
    var intv_event_refresher;
    var intv_update_zeiten;
    var intv_js_uhrzeit;
    var intv_decrypt_all_c;
    var intv_alle_links_aendern;

    function stop_intervals()
    {
      window.clearTimeout(timeout_diff_reloader);
      window.clearInterval(intv_js_uhrzeit);
      window.clearInterval(intv_event_refresher);
      window.clearInterval(intv_update_zeiten);
      window.clearInterval(intv_decrypt_all_c);
      window.clearInterval(intv_alle_links_aendern);

      console.log('Intervals STOPPED!');
      // window.clearInterval(intv_decrypt_all_l);
    }

    function start_intervals()
    {
      // Intervalle erst killen (sonst existieren sie evl mehrfach):
      stop_intervals();

      // Sofort ausführen (dumm, das setInterval das nicht macht):
      update_js_uhrzeit();
      refresh_events();
      update_zeiten();
      decrypt_all_c();
      decrypt_all_l();
      alle_links_aendern();

      // JS-Uhrzeit immer sekündlich updaten:
      intv_js_uhrzeit=window.setInterval('update_js_uhrzeit();',1000);

      // alle 3 Sek Events checken:
      intv_event_refresher=window.setInterval('refresh_events();',3000);

      // Alle Zeiten immer sekündlich updaten:
      intv_update_zeiten=window.setInterval('update_zeiten();',1000);

      // alles decrypten:
      intv_decrypt_all_c=window.setInterval('decrypt_all_c();',100);
      // alles decrypten: KEIN INTERVAL!
      // intv_decrypt_all_l=window.setInterval('decrypt_all_l();',10);

      // alle Links umschreiben:
      intv_alle_links_aendern=window.setInterval("alle_links_aendern()",100);

      //alert('Intervals started!');
      console.log('Intervals STARTED!');
    }

    // EVENT-Listener:
    document.addEventListener("DOMContentLoaded", function(event){
      // statt im body "onhashchange", hier besser weil später
      // window.addEventListener('hashchange', lade, false);

      // initial ALLE laden:
      window.setTimeout("lade(1);",300);
      start_intervals();
    });

    // Stoppen der Intervalle:
    document.addEventListener('freeze', function() {
      log_add("freeze");
      //stop_intervals();
    });

    window.addEventListener('blur', function() {
      log_add("blur");
      stop_intervals();
    });

    // Starten der Intervalle:
    document.addEventListener('resume', function() {
      log_add("resume");
      //start_intervals();
    });

    window.addEventListener('focus', function() {
      log_add("focus");
      try
      {
        start_intervals();
      }
      catch(e)
      {
        // Anweisungen für jeden Fehler
        fehler=JSON.stringify(e);
        log_add("FEHLER:"+fehler);
        //alert("Fehler beim Refresh, daher NEULADEN!\n"+fehler);
        document.location.reload();
      }
      log_add("nach focus");
    });

    // beides kombiniert:
    document.addEventListener('visibilitychange', function() {
      if(document.hidden) {
          log_add("vc: hidden");
          //stop_intervals();
      }
      else {
          log_add("vc: visible");
          //start_intervals();
      }
    });

    _('#content').addEventListener('scrollend', function() {
      check_tablinks();
    });
