Ankündigung

Einklappen
Keine Ankündigung bisher.

Contentladen wenn hoch gescrollt, ist diese Lösung gut?

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Contentladen wenn hoch gescrollt, ist diese Lösung gut?

    Hallo,

    in meinem Fall geht es darum im Chatverlauf ältere Chatnachrichten zu laden, das hat die Besonderheit das man hoch scrollen muss und der neue Content ebenfalls über dem alten (DOM) hinzugefügt wird.
    Das Grundmodell lief gut (PC & Mobile) hatte jedoch die Schwachstelle das wenn der Nutzer den Scrollbalken feshält (PC) und nach oben schiebt und weiterhin festhält, ein xhr-event nach dem anderen gefeuert wird, weil auch nach dem Hinzufügen des Content die Position weiterhin top (0) ist (Scrollbar springt ja direkt wieder zum Cursor).

    Eine Lösung wäre gewesen das festhalten der Scrollbar zu unterbrechen (gelang mir aber nur im Chrome).
    Nun habe ich diese Lösung umgesetzt und hätte dazu gern etwas Feedback.

    PHP-Code:
    /** [-on (left)mouse down-] */
    const omd = {
        
    isfalse,
        
    events: [], // events die nach dem loslassen ausgeführt werden
        
    busyfalse,
        
    run: function(){
            
    // console.debug('mous is down',  this.events);
            
    this.exeomd.events.shift() );
            if( 
    this.events.length == ){ this.busy false; }else{ this.run(); }
        },
        
    exeasync function(func){
            
    func();
        }
    };
    document.onmousedown = function(e){
        
    console.debug('mous is down',  e.button);
        if( 
    e.button == ){ omd.is true; }
    };
    document.onmouseup = function(e){
        if( 
    e.button == ){
            
    omd.is false;
            if( 
    omd.events.length && !omd.busy ){ omd.busy trueomd.run(); }
        }
    };

    // der onScroll handler...
    this.appear.sl this.el.find('.messageWrapper').on('scroll', function(e){
        
    // fetch for enable loadOldMsg
        
    if( _this.loadMore === true && $(this).scrollTop() == ){
            if( !
    omd.is ){
                
    _this.loadOldMsg();
            }else{
                
    // position ist top aber Maus noch immer gedrückt, also omd event hinzufügen und auf loslassen warten
                
    if( omd.events.indexOf(_this.loadOldMsg) == -){ omd.events.push(_this.loadOldMsg); }
            }
        }
    }); 
    Nun habe ich die Möglichkeit in anderen Skripten stets abzufragen ob die Maustaste aktuell noch immer gehalten wird.
    Dadurch kann das Scroll-Event entsprechend entscheiden was zu tun ist.


    LG: Paykoman

  • #2
    Du musst doch nur auf das Loslassen reagieren.

    Beispiel kopieren und ausprobieren.

    PHP-Code:
    <?php
    $chat_content 
    '<p>hi</p>
        <p>hallo</p>
        <p> wie geht`s?</p>
        <p>gut und dir?</p>'
    ;
    ?>
    <!DOCTYPE html>
    <html>
        <head>
        <meta charset="utf-8">
        <style>
        form#chat div{
            width: 16em;
            height: 5em;
            overflow-y: scroll;
            border: 1px solid blue;
            padding: 0 5px;  
        }
        form#chat div p {
            line-height: 20px;
            font-size: 16px;
            margin:0;
            padding:0;
        }

        </style>
        <title>Scrolltest</title>
        </head>
    <body>  
        <h1>Chat</h1>
        <form id="chat" method="post">
        <div>
        <p>-- ältere Nachrichten --</p>
        <?= $chat_content?>
        </div>
        <input type="text">
        <input type="submit">
        </form>
    <script>
    var el = document.querySelector('div');
        el.scrollTop = 100;

        el.onmouseup = function(e){
            if( el.scrollTop == 0 ){
                el.innerHTML = '<p>weiter nach oben</p>' + el.innerHTML;
                el.scrollTop = 20;
            }
        };
    </script>
    </body>
    </html>

    Kommentar


    • #3
      Leider nicht, denn in dem onScroll-event werden nicht nur das nachladen alter Nachrichten gehändelt sondern auch andere Aufgaben erledigt (wird also eh benötigt).
      Außerdem würde es Mobile nicht funktionieren, da es keine Maus gibt, hier wäre eh das onScroll-Event nötig...

      Kommentar


      • #4
        Für mobile Geräte mit Touch-Unterstütung gibt es auch touchend.
        Aber was hast du bei einem Chat zu erledigen während gescrollt wird?

        Das Nachladen der alten Nachrichten macht man, nachdem nicht mehr gescrollt wird und du weisst an welcher Position sich der Scrollbalken befindet.
        Irgendwie scheinst du noch Probleme mit dem Feuern der Ereignisse und deren Behandlung zu haben, das solltest du mal nachlesen.

        Kommentar


        • #5
          Naja da es aber verschiedene Möglichkeiten gibt zu scrollen (Arrows, Mausrad, Anklicken und schieben der Scrollbar, Touch), ist nun mal ein einfaches "gucken ob die Maus losgelassen wird und dann die Scroll-position checken" nicht ausreichend.

          Um alle Möglichkeiten gleichzeitig zu erfassen, ist onScroll() nun mal das Beste (denke ich).
          Genau und darum habe ich ja jetzt einen Listner gebaut mit dem es Möglich ist auf das los lassen der Maus zu warten.

          Der Chatverlauf hat eine Höhe von 260px, daher wird z.B. bereits während des Scrollen geprüft ob neue (ungelesene) Nachricht sich im Sichtbaren Feld befinden und als als gelesen erfasst.
          Des weiteren gibt es mehrere Chats, von denen nur einer aktiv geöffnet sein kann und alles per Klick zu Händeln wäre glaube ich deutlich umständlicher.

          Hier gerne mal das gesamte Scroll-Zeugs
          PHP-Code:
          // ...
           
          _listnerSet: function(){
              var 
          loop = {exenullleft50};
              
          this.appear.sl this.el.find('.messageWrapper').on('scroll', function(e){
                  
          _this.sTop = $(this).scrollTop();
                  if( 
          loop.exe === null ){
                      
          loop.exe setInterval(function(){
                          
          // console.log('check loop', loop);
                          
          if( loop.left == ){
                              
          clearInterval(loop.exe);
                              
          loop.exe null;
                              
          loop.left 50;
                              
          _this._listnerCheck();
                          }else{
                              
          loop.left -= 10;
                          }
                      }, 
          10);
                  }else{
                      
          // console.log('interval exists, start timer again');
                      
          loop.left 50;
                  }

                  
          // fetch for enable loadOldMsg
                  
          if( _this.loadMore === null && $(this).scrollTop() > ){ _this.loadMore true; }
                  if( 
          _this.loadMore === true && $(this).scrollTop() == ){
                      
          _this.loadMore false;
                      if( 
          omd.is ){
                          
          _this.loadOldMsg();
                      }else{
                          
          omd.events.push(_this.loadOldMsg);
                      }
                  }
              });
          },
              
          _listnerCheck: function(){
              var 
          top this.appear.sl.scrollTop(),
                  
          vpHeight Math.round(this.appear.sl.height()); // viewport height (div height)
              // console.log('scroll check', top, vpHeight, this.appear.sl[0].scrollHeight );

              // fetch unread items
              
          if( !this.appear.busy && this.appear.items.length ){
                  if( (
          top vpHeight) == this.appear.sl[0].scrollHeight ){
                      
          // scroll disabled or is bottom, set all new messages as read
                      // console.log('all msg read', this.appear.items.length, that.messenger.conv[_this.id]['new']);
                      
          that.alert.update(_profile_type'ccm''+'that.messenger.conv[_this.id]['new']); // substract the new items from ccm counter
                      
          that.messenger.conv[_this.id]['new'] = 0// set new counter to zero
                      
          this.appear.counter(); // update html-counter
                      
          var newMid this.appear.items[this.appear.items.length-1].id;
                          
          this.appear.items = [];

                      if( 
          newMid this.mid ){
                          
          this.mid newMid;
                          if( 
          this.appear.inter === null ){
                              
          this.appear.inter setInterval(function(){
                                  if( 
          _this.appear.left == ){
                                      
          clearInterval(_this.appear.inter);
                                      
          _this.appear.update();
                                  }else{
                                      
          _this.appear.left -= 500;
                                  }
                              }, 
          500);
                          }else{
                              
          _this.appear.left 1500;
                          }
                      }
                  }else{
                      
          // scroll enabled, chek each item if visble
                      
          for( var 0this.appear.items.lengthi++ ){
                          var 
          msg this.appear.items[i];

                          
          // console.log('check item pos', top + vpHeight, msg.el[0].offsetTop + msg.el.height() -30, msg.el.height() );
                          
          if( (msg.el[0].offsetTop msg.el.height()) -30 < (top vpHeight) ){ // only check boottom of msg
                              // console.log('msg id is read:', msg.id);
                              
          that.messenger.conv[_this.id]['new']--;
                              
          that.alert.update(_profile_type'ccm''+');
                              
          this.appear.counter(); // update html-counter

                              
          if( msg.id this.mid ){
                                  
          this.mid msg.id;
                                  if( 
          this.appear.inter === null ){
                                      
          this.appear.inter setInterval(function(){
                                          if( 
          _this.appear.left == ){
                                              
          clearInterval(_this.appear.inter);
                                              
          _this.appear.update();
                                          }else{
                                              
          _this.appear.left -= 500;
                                          }
                                      }, 
          500);
                                  }else{
                                      
          _this.appear.left 6000;
                                  }
                              }
                              
          this.appear.items.splice(i1);
                              
          i--;
                          }
                      };
                  }
              }
          },
          / ... 
          Aber naja wie gesagt, das Problem ist halt das man ja nicht nur per schieben der Scrollbar scrollen kann, sondern eben auch andere Auslöser dafür gibt, da müsste man dann für jede Art des Scrollens Events beobachten.
          Der Loop im _listnerSet ist übrigens dafür zuständig auf das aufhören des Scrollens zu warten, führte aber beim festhalten der Maus zu oben genannten Problemen (führte).

          Kommentar


          • #6
            Dann schau die mal die Hilfsfunktion scrollstop.js an.
            Das dürfte das sein, was du suchst.

            Kommentar


            • #7
              Ach manchmal komm ich mir vor als würde ich ne andere Sprache sprechen. Und überhaupt.

              Kommentar


              • #8
                Beschäftige dich mal mit "passive Event Listener", diese set- und clearInterval Geschichten sind sehr grenzwertig.

                Kommentar


                • #9
                  https://developer.mozilla.org/en-US/...n_Observer_API
                  I like cooking my family and my pets.
                  Use commas. Don't be a psycho.
                  [URL="http://jscouch.de"]Blog[/URL] - [URL="http://coverflowjs.github.io/coverflow/"]CoverflowJS[/URL]

                  Kommentar


                  • #10
                    rudygotya
                    Ich denke, diese API sollte man besser noch nicht einsetzen, da der Status auf Working Draft steht und es derzeit von einigen Browsern am Markt nicht unterstützt wird.

                    Kommentar


                    • #11
                      Bis Paykoman fertig ist....

                      Kommentar


                      • #12
                        protestix verwende ich schon länger zusammen mit polyfill.io: https://cdn.polyfill.io/v3
                        Polyfill.io mirror Lässt sich auch super selbst hosten.

                        -> https://polyfill.io/v2/polyfill.min....ectionObserver

                        Und außer iOS/mac unterstützen alle großen Browser das feature
                        I like cooking my family and my pets.
                        Use commas. Don't be a psycho.
                        [URL="http://jscouch.de"]Blog[/URL] - [URL="http://coverflowjs.github.io/coverflow/"]CoverflowJS[/URL]

                        Kommentar

                        Lädt...
                        X