mumpel: "Nach oben scrollen" unter AngularJS

Hallo!

Ich versuche vergeblich auf unserer Seite (Coyo) eine "Nach oben scrollen"-Funktion per Userscript (Tampermonkey) zu integrieren. Aber alles was ich probiere funktioniert nicht.

Das ist mein aktueller Testcode:

// ==UserScript==
// @name         Scroll-to-top
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  Nach oben scrollen
// @author       Ich
// @match        https://seite.de/workspaces*
// @grant        none
// ==/UserScript==


function setScrollToTp() {
    'use strict';
    var observer = new MutationObserver(function(mutations) {
        mutations.forEach(function(mutation) {
            if (mutation.addedNodes !== null) {
               var scEl = document.getElementsByClassName("body"); /*state-main-workspace*/
                   scEL.scrollIntoView();
                 }
            });
       });
    observer.observe($('body')[0], { childList: true, subtree: true });
  }

Gibt es eine Lösung? Danke!

Gruß, René

P.S.: Schlechte Codedarstellung hier. Ich hoffe man kann ihn trotzdem lesen.

akzeptierte Antworten

  1. Hallo

    P.S.: Schlechte Codedarstellung hier.

    Wenn man die angebotenen Funktionen nutzt, nicht.

    Ich hoffe man kann ihn trotzdem lesen.

    Nach der erfolgten Korrektur ist davon auszugehen.

    Tschö, Auge

    --
    Wenn man ausreichende Vorsichtsmaßnahmen trifft, muss man keine Vorsichtsmaßnahmen mehr treffen.
    Toller Dampf voraus von Terry Pratchett
    1. Klicke ich auf "Quelltext" wird Markdown verwendet. Soll man hier "Zitat" nutzen für Quellcode?

      1. Hallo @mumpel,

        schaue ich oberhalb des speichern-Buttons, steht da Hilfe bei der Formatierung Ihrer Beiträge.

        Viele Grüße
        Robert

        1. Danke! Aha, mit Tilden und Schlüsselwörtern. Ich mag Markdown nicht. 😉

      2. Hallo

        Klicke ich auf "Quelltext" wird Markdown verwendet.

        Ja, natürlich. So, wie in anderen Foren- oder Boardsystemen BB-Code verwendet wird, ist es hier Markdown.

        Soll man hier "Zitat" nutzen für Quellcode?

        Warum? Nein, natürlich soll man für Quellcode „Quellcode“ verwenden. Was denn sonst?

        Tschö, Auge

        --
        Wenn man ausreichende Vorsichtsmaßnahmen trifft, muss man keine Vorsichtsmaßnahmen mehr treffen.
        Toller Dampf voraus von Terry Pratchett
  2. Tach!

    Ich versuche vergeblich auf unserer Seite (Coyo) eine "Nach oben scrollen"-Funktion per Userscript (Tampermonkey) zu integrieren. Aber alles was ich probiere funktioniert nicht.

    observer.observe($('body')[0], { childList: true, subtree: true });
    

    Den Body kann man auch einfach über document.body erreichen.

    Gibt es eine Lösung? Danke!

    Vermutlich, aber die muss zur Ursache passen. Am besten fängst du an, diese Ursache zu ermitteln. Dazu bieten sich die üblichen Mittel des Debuggings an. Im einfachsten Fall kann man dazu Testausgaben mit console.log(delinquent) einfügen, um zu prüfen, ob der Wunsch zur Wirklichkeit passt. Schöner wird es aber mit dem Debugger in den Entwicklertools, aber da musst du erstmal finden, wo sich da der von Greasemonkey eingebundenen Code aufhält.

    dedlfix.

    1. Es werden keine Fehler ausgegeben. Der scrollt einfach nicht. Ein anderes Script (zum Ändern des h4-Tags) funktioniert problemlos.

      1. Tach!

        Es werden keine Fehler ausgegeben. Der scrollt einfach nicht. Ein anderes Script (zum Ändern des h4-Tags) funktioniert problemlos.

        Es gibt auch Fehler logischer Art. Code kann technisch gesehen völlig korrekt sein, aber trotzdem nicht machen, was man sich als Autor so vorstellt. Auch um solche Ursachen zu finden, ist das Debugging hilfreich.

        dedlfix.

    2. "body" ist bei Coyo übrigens ein Klassenname, der zusätzlich zum Body-Tag existiert.

      1. Tach!

        "body" ist bei Coyo übrigens ein Klassenname, der zusätzlich zum Body-Tag existiert.

        Macht nichts. Klassennamen kommen mit document.body nicht in Konflikt. Wenn du jedoch einen Klassennamen meinst, musst du den Selektor auch entsprechend schreiben, mit . davor, also .body statt body. Letzteres bezieht sich auf das Element mit dem Namen body, egal welche Klassen es hat oder welche Klassen von anderen Elementen gleich benannt sind.

        dedlfix.

        1. Auch mit ".body" tut sich nichts.

          Hier mal ein funktionierendes Script.

          // ==UserScript==
          // @name         Gruppen-Langname anzeigen
          // @namespace    http://tampermonkey.net/
          // @version      0.1
          // @description  In den Gruppen den Langnamen anzeigen
          // @author       Ich
          // @match        https://db-planet.deutschebahn.com/workspaces*
          // @grant        none
          // ==/UserScript==
          
          (function() {
              'use strict';
              var css = `
                  /* CSS-Regeln hierhin */
          
          
          /* Links optisch aufbessern */
          div.description-container a{
          margin: 1px 0 6px;
          position: relative;
          font-size: 20px;
          line-height: 26px;
          white-space: nowrap;
          overflow: hidden;
          text-overflow: ellipsis;
          display:block;
          color:black;
          
          }
          
          
                  /* Ende der CSS-Regeln */
              `;
              $('<style>' + css + '</style>').appendTo($('head'));
          })();
          
          var timeoutTitle;
          function setTitleAttribute() {
              'use strict';
              var observer = new MutationObserver(function(mutations) {
                  mutations.forEach(function(mutation) {
                      if (mutation.addedNodes !== null) {
                          $('h4').each(function() {
                              var a = $('<a target="_blank"></a>');
                              a.attr('href', $(this).attr('href'));
                              a.attr('title', $(this).text());
                              a.text($(this).text());
                              $(this).replaceWith(a);
                          });
                          //Scrollfunktion hier?
                      }
                  });
              });
              observer.observe($('body')[0], { childList: true, subtree: true });
          }
          timeoutTitle = window.setTimeout(setTitleAttribute, 3000);
          

          Füge ich da die Scrollfunktion hinzu scrollt er trotzdem nicht.

          1. Tach!

            Auch mit ".body" tut sich nichts.

            Ich kann dir da nicht unbedingt anders weiterhelfen als dir die Wege zu erklären, über die ich meistens die Fehler finde. Du zeigst hier Javascript-Code, jetzt auch noch CSS dazu, aber das DOM, auf das sich dieser Code bezieht, ist nicht dabei. Ich sehe nur Code, der in sich schlüssig ist, kann aber nicht beurteilen, ob er zum Problem passt.

            Was du prüfen solltest ist vor allem, ob alle Selektionsversuche auch die Elemente finden, die beabsichtigt sind. Die Kontrollausgaben können dabei behilflich sein. Wenn jQuery nämlich nichts findet, gibt es ein leeres Array zurück. Zu dem kann man zwar forEach() aufrufen, aber ohne Inhalt im Array findet dabei nichts wirksames statt. Deswegen prüfen, ob die Selektion im Sinne der Aufgabenstellung erfolgreich war. Und so weiter und so fort. Irgendwann offenbart sich das Problem.

            dedlfix.

            1. Ich habe schon alle möglichen Selektoren durchprobiert. Es scrollt einfach nicht. Das Einzige was funktioniert ist ein permanentes Scrollen. Wenn ich die Codezeile zum Scrollen losgelöst von allem nutze kann ich, ist ja logisch, nicht mehr nach unten scrollen. Kann es sein dass das Scrollen irgendwie durch Angular deaktiviert wurde?

              aber das DOM, auf das sich dieser Code bezieht, ist nicht dabei.

              Was meinst Du damit?

              1. Tach!

                Kann es sein dass die Scrollfunktion deaktiviert wurde?

                Kann ich dir nicht beantworten. Ich kenne die Anwendung nicht, und kann daher nicht einschätzen, ob das dafür sinnvoll wäre oder nicht.

                aber das DOM, auf das sich dieser Code bezieht, ist nicht dabei. Was meinst Du damit?

                Aus HTML wird im Browser das DOM, also eine Baumstruktur aus dem "flachen" HTML-Textdokument. Mit Javascript greifst du auf Elemente im DOM zu und manipulierst sie oder fügst neue hinzu. Zumindest das HTML muss man sehen, um DOM-manipulierenden Javascript-Code beurteilen zu können.

                Mir scheint, dass du dich um das Debugging drücken möchtest. Das möchte vermutlich jeder. Aber stattdessen Rumprobieren, ohne die Ursache zu kennen, ist zwar mitunter erfolgreich, oft aber auch nur vergeudete Zeit.

                dedlfix.

                1. Debuggen kann ich nicht weil ich nicht weiss wonach ich suchen muss. Wenn Fehler angezeigt würden wäre es leicht. Aber ohne Fehlermeldung kann man keine Fehler finden.

                  Gibt es in Angular keine eigene Scrollfunktion die ich testen könnte?

                  1. Tach!

                    Debuggen kann ich nicht weil ich nicht weiss wonach ich suchen muss. Wenn Fehler angezeigt würden wäre es leicht. Aber ohne Fehlermeldung kann man keine Fehler finden.

                    Debuggen ist das Vergleichen von Wunsch und Wirklichkeit, weniger ein Suchen nach bereits bekannten Dingen. Du hast beispielswiese eine Funktion, die ein bestimmtes Ergebnis liefern soll, also wäre das Ergebnis anzuschauen, ob es dem erwarteten entspricht. Wenn nicht, bekommt die Funktion vielleicht falsche Daten übergeben, also wären die zu überprüfen. und so weiter. Irgendwo gibts dann die Diskrepanz. Und auf diese Erkenntnis kann man dann weitere Untersuchungen aufbauen.

                    In deinem Fall sind es hier die Selektoren-Funktionen, die du prüfen solltest, ob sie die gesuchten Elemente ergeben.

                    dedlfix.

                2. console.log(delinquent)

                  Was ist der "delinquent"?

                  1. Tach!

                    console.log(delinquent)

                    Was ist der "delinquent"?

                    Das zu untersuchende Objekt. Wenn du zum Beispiel prüfen möchtest, ob document.getElementsByClassName("body") die richtigen Elemente liefert, dann wird das zu console.log(document.getElementsByClassName("body")); oder auch console.log(scEl); weil du das ja dieser Variable zugewiesen hast.

                    dedlfix.

                    1. console.log($(document.body).animate({scrollTop:1}, 800));

                      gibt aus:

                      Object [ body.state-main-workspace ]

                      und darunter alle Kindelemente. Anfangen kann ich damit nichts.

                      Es muss doch möglich sein eine Funktion (mit Observer) zu schreiben die auf ein "ReadyState" wartet und dann zum Seitenanfang scrollt. Als Javascript-Laie tut man sich da schwer. Das ist leider das Problem wenn man mit einem schlecht programmierten "Social Intranet" konfrontiert wird und sich selber Funktionen zusammenbasteln muss. Das Probelm ist dass die Seite nicht automatisch nach oben scrollt und die Seitenauswahl nur am Ende der Seite ist, man muss also erstmal nach oben scrollen um alles lesen zu können und dann wieder zum Seitenende scrollen damit man auf die nächste Seite kommt. In Google finde ich keine passenden Beispielcodes.

                      1. Tach!

                        console.log($(document.body).animate({scrollTop:1}, 800)); gibt aus: Object [ body.state-main-workspace ] und darunter alle Kindelemente. Anfangen kann ich damit nichts.

                        Das ist beim body auch nicht verwunderlich. Und dass document.body tatsächlich das body-Element ergibt, sollte man auch ohne Test annehmen können. Es geht beim Debuggen darum das weniger offensichtliche zu prüfen.

                        Hier nochmal dein Code mit ein paar Anmerkungen von mir als Kommentare eingefügt

                            var observer = new MutationObserver(function(mutations) {
                        // hier könnte man den Inhalt von mutations prüfen
                                mutations.forEach(function(mutation) {
                        // hier könnte man mutation prüfen, vor allem, ob es addedNodes enthält, denn das ist ja das Kriterium, um zum nächsten Teil vorzudringen.
                                    if (mutation.addedNodes !== null) {
                                       var scEl = document.getElementsByClassName("body"); /*state-main-workspace*/
                        // hier könnte man scEl testen
                                           scEL.scrollIntoView();
                        // und hier gibts keine Fehlermeldung, wo doch scEL nicht existiert, sondern nur eins mit kleinem L? Nun, vielleicht kommt der Code gar nicht bis hierhin. Oder scEL existiert im globalen Scope und verweist auf ein anderes Element. Kann man auch prüfen.
                                         }
                                    });
                               });
                            observer.observe($('body')[0], { childList: true, subtree: true });
                        

                        dedlfix.

                        1. Diesen Code hatte ich gestern schon getestet, auch mit einem kleinen L und "getElementsByTagName". Scrollt aber einfach nicht. Allerdings gibt es da die Meldung "scrollIntoView" sei keine Funktion. Aber es funktioniert auch kein anderer "Scrollcode".

                          1. Tach!

                            Diesen Code hatte ich gestern schon getestet, auch mit einem kleinen L und "getElementsByTagName". Scrollt aber einfach nicht. Allerdings gibt es da die Meldung "scrollIntoView" sei keine Funktion.

                            Es kann nur dann keine Methode sein, wenn das Objekt kein Element ist. Bei einem Tippfehler im Variablennamen greifst du auf eine nicht vorhandene Variable zu. Der Zugriff ergibt dann undefined und das hat keine Methoden, weswegen diese Fehlermeldung kommt.

                            dedlfix.

                            1. Es funktioniert auch nicht mit korrektem Variablennamen. Da kommt die selbe Fehlermeldung. Kann es sein dass "scrollIntoView" nur mit "getElementById" funktioniert? Sollte dem so sein wird es nie funktionieren, da es in Coyo keine IDs gibt.

                              1. Hallo mumpel,

                                Kann es sein dass "scrollIntoView" nur mit "getElementById" funktioniert?

                                Kann ich mir nicht vorstellen.

                                Aber es funktioniert auch kein anderer "Scrollcode".
                                Es funktioniert auch nicht …
                                Auch … funktioniert … nicht

                                Dein unstrukturiertes Umherprobieren ist nicht zielführend. Warum ignorierst du die dir gegebenen Hinweise zum Debugging?

                                Bis demnächst
                                Matthias

                                --
                                Rosen sind rot.
                              2. Tach!

                                Es funktioniert auch nicht mit korrektem Variablennamen. Da kommt die selbe Fehlermeldung. Kann es sein dass "scrollIntoView" nur mit "getElementById" funktioniert?

                                Ach, ja klar, getElements... (Mehrzahl) liefert ja eine Liste. Und die Liste als solche hat die Funktion natürlich nicht, nur die Elemente in der Liste. scEl[0].scrollIntoView(); müsste gehen (oder wie auch immer du nun den Variablennamen geschrieben hast). Eigentlich müsste man auch noch testen, ob das Element existiert. Oder noch besser, man lässt gleich ein forEach arbeiten.

                                Array.from(scEl).forEach(e => e.scrollIntoView());
                                

                                Aber bei einem scrollIntoView ergibt das keinen Sinn. Dann doch lieber den einfachen Test:

                                if (scEl[0]) {
                                  scEl[0].scrollIntoView();
                                }
                                

                                dedlfix.

                                1. Keine Chance. Es scrollt einfach nicht.

                                  1. Immernoch die selbe Fehlermeldung

                                    TypeError: document.getElementsByTagName(...).scrollIntoView is not a function

                                    1. Tach!

                                      Immernoch die selbe Fehlermeldung

                                      TypeError: document.getElementsByTagName(...).scrollIntoView is not a function

                                      Selbes Problem wie bei getElementsByClassName(). Es ist auch eine Methode, die eine Liste und nicht nur ein Einzelelement liefert.

                                      dedlfix.

                                      1. Mit "scEl[0]" habe ich es ja versucht, also den obersten Index.

                                      2. Jetzt ist es mir doch noch gelungen. Weshalb das vorher (mit selben Parametern) nicht funktionierte weiss ich nicht.

                                        1. Ein kleines Problem gibt es dann aber doch. Wenn man auf ein "Label" zeigt scrollt er gleich nach oben. Gibt es da eine Möglichkeit eine Klasse nicht zu berücksichtigen, also beim Zeigen auf ein Label nicht zu scrollen?

                                          1. Tach!

                                            Ein kleines Problem gibt es dann aber doch. Wenn man auf ein "Label" zeigt scrollt er gleich nach oben. Gibt es da eine Möglichkeit eine Klasse nicht zu berücksichtigen, also beim Zeigen auf ein Label nicht zu scrollen?

                                            Ich kenne mich mit MutationObserver nicht aus. Aber in dem addedNodes wird laut Beschreibung eine NodeList übergeben. Die Elemente darin kann man ja auf bestimmte Eigenschaften testen und nur scrollen, wenn die Bedingungen passen. Ich vermute, dass du darüber dein Ziel erreichen kannst.

                                            dedlfix.

                                            1. MutationObserver ist auch nicht mein Gebiet. Ich brauche nur eine Möglichkeit das Mouseover zu ignorieren, da dieses ja auch eine Änderung im Content hervorruft.

                                              1. Tach!

                                                MutationObserver ist auch nicht mein Gebiet. Ich brauche nur eine Möglichkeit das Mouseover zu ignorieren, da dieses ja auch eine Änderung im Content hervorruft.

                                                Es scheint mir nicht zu gehen, dass du das Auslösen des Events unterbinden kannst. Aber du kannst innerhalb des Eventhandlers die Bedingungen testen und die weitere Verarbeitung mit return beenden. Auch hier kann Debugging helfen, Regelmäßigkeiten zu erkennen, auf die man aufsetzen kann, besonders in Fällen, in denen man nicht weiß, was man da genau übergeben bekommt.

                                                Eine wichtige zu klärenden Fragen wäre also: Was ist in den MutationRecords (also in der Variable mutation) an Information drin, mit der man die guten von den schlechten unterscheiden kann?

                                                dedlfix.

                                                1. <li role="menuitem" ng-repeat="anweisung" ng-class="anweisung" class="anwesiung">
                                                      <a href="" ng-click="selectPage(page.number, $event)" ng-disabled="anweisung" 
                                                         uib-tabindex-toggle="">3
                                                      </a>
                                                  </li>
                                                  

                                                  Das ist da Gute. Der Rest muss ignoriert werden.

                                                  Eine andere Möglichkeit wäre, den Link-Tags innerhalb des li-Tags ein onclick-Ereignis einzbauen. Was auch funktioniert. Aber da weiss ich nicht wie ich nur die Link-Tags innerhalb li-Tag ansprechen kann. Derzeit kann ich das nur mit allen Link-Tags. Damit das alles funktioniert muss ich in den Head-Tag eine Funktion einschleusen (hatte ich vor ein paar Tagen schon probiert, da ging das nicht. Heute funktioniert es plötzlich. Wo der Fehler lag weiss ich nicht).

                                                  1. Tach!

                                                    Aber da weiss ich nicht wie ich nur die Link-Tags innerhalb li-Tag ansprechen kann.

                                                    In Javascript? Zuerst das li finden und dann hat das Element auch die Methoden getElementsByClassName() und getElementsByTagName(), die in dessen Kindern suchen. Wenn es dir aber generell um alle a in allen li geht, dann gibts mit document.querySelector() beziehungsweise document.querySelectorAll() die Möglichkeit, mit CSS-Selektoren-Syntax Elemente auszuwählen. (jQuery macht das ja ähnlich.)

                                                    dedlfix.

                                                    1. Ich habe es schon mit "document.getElementsByTagName('li').getElementsByTagName('a')" probiert, funktioniert jedoch nicht.

                                                      1. Tach!

                                                        Ich habe es schon mit "document.getElementsByTagName('li').getElementsByTagName('a')" probiert, funktioniert jedoch nicht.

                                                        Natürlich nicht, weil getElements[beachte die Mehrzahl]ByTagName() eine Liste liefert und kein einzelnes Element. Die Liste selbst hat keine Methode getElementsByTagName().

                                                        dedlfix.

                                                        1. Wie könnte das mit querySelector aussehen?

                                                          1. Tach!

                                                            Wie könnte das mit querySelector aussehen?

                                                            Genauso wie du mit CSS eine Style-Information erstellen würdest:

                                                            document.querySelectorAll('li a')

                                                            Oder ohne All, wenn nur das erste Element gewünscht ist.

                                                            dedlfix.

                                                            1. So habe ich es probiert. Funktioniert nicht.

                                                            2. Kommando zurück. Funktioniert doch, dauert nur ein wenig länger. Ich habe das timeout reduziert. Danke für Deine Hilfe!

                                2. Coyo ist ohnehin verbuggt. Source-Map-Fehler, XML-Verarbeitungsfehler. Und dafür zahlt der Arbeitgeber auch noch Geld.

                        2. Auch als Funktion eingebunden funktioniert "scrollIntoView" nicht.