Problem mit scrollevent und matchMedia

Status
Dieses Thema wurde gelöst! Zur Lösung gehen…

Jan-Frederik Stieler

Monsterator
Moderator
Hi,
entweder ich steh aufm Schalu oder ich bin zu blöd.

ich bekomm es nicht hin das der ScrollEvent Code aufm größer Bildschirm 992px removed wird inklusive der Klassen.
Was ich auch versucht habe das mobile.matches im Event abzufragen um mir das resize zu sparen aber das wollte auch nicht so wirklich und ich wußte dann auch nicht wie ich den Event wieder vernüünftig entferne.

https://codepen.io/janstieler-the-bashful/pen/QWJvPKx
Das ist nicht perfekt von den Größen aber man sieht das nachm klein und wieder großziehen des Bidlschirmes das scrollevent noch aktiv ist.

Javascript:
function headerLogoScroll() {
    const logoHeader        = document.getElementById('headerLogo');
    const mobile            = window.matchMedia('(max-width:992px)');
    let scrollListenerAdded = false;
    let lastScrollTop       = 0;
    let logoHeight          = logoHeader.offsetHeight;
    let logoTop             = logoHeader.offsetTop;
    let logoScrollPosHide   = logoTop + (logoHeight - (logoHeight / 3));
    let logoBottomPos       = logoTop + logoHeight;

    function scrollHandler() {
        let st = window.scrollY || document.documentElement.scrollTop;

        if (st > lastScrollTop) {
            console.log('downscroll');

            if (st < logoBottomPos) {
                logoHeader.classList.remove('sticky-logo');
                logoHeader.classList.remove('sticky-logo__animated');
                logoHeader.classList.remove('sticky-logo__show');
            }

            if (st > logoScrollPosHide) {
                logoHeader.classList.remove('sticky-logo__show');
                logoHeader.classList.add('sticky-logo');
            }
        } else if (st < lastScrollTop) {
            console.log('upscroll');

            if (st < logoScrollPosHide && st > lastScrollTop) {
                logoHeader.classList.remove('sticky-logo');
                logoHeader.classList.remove('sticky-logo__animated');
                logoHeader.classList.remove('sticky-logo__show');
            }

            if (st > logoScrollPosHide) {
                logoHeader.classList.remove('sticky-logo');
                logoHeader.classList.add('sticky-logo__animated');
                logoHeader.classList.add('sticky-logo__show');
            }
        }

        lastScrollTop = st <= 0 ? 0 : st; // For Mobile or negative scrolling
    }

    if (mobile.matches) {
        if (!scrollListenerAdded) {
            window.addEventListener('scroll', scrollHandler, false);
            scrollListenerAdded = true;
        }
    } else {
        console.log('notMobile');

        if (scrollListenerAdded) {
            window.removeEventListener('scroll', scrollHandler, false);
            scrollListenerAdded = false;
        }

        logoHeader.classList.remove('sticky-logo');
        logoHeader.classList.remove('sticky-logo__show');
        logoHeader.classList.remove('sticky-logo__animated');
    }
}

document.addEventListener('DOMContentLoaded', (event) => {
    headerLogoScroll();
});

window.addEventListener('resize', (event) => {
    headerLogoScroll();
});
 
Zustandsvariablen sind immer ein wenig tricky und fehleranfällig aber hiernach:
How to check whether dynamically attached event listener exists or not?
führt bei den Eventlistenern kein Weg daran vorbei.
Du führst die Variable scrollListenerAdded im Scope der Funktion headerLogoScroll. Diese Funktion wird jedes Mal aufgerufen wenn das resize-Event feuert und wird dabei auf false gesetzt. D. h. sie ist immer false und diese Abfrage: if (scrollListenerAdded) { ist nie erfüllt.
Wenn Du die Variable global machst müsste es funktionieren.
 
Du gibst einem aber auch harte Nüsse auf ;)

Es gab noch ein Problem mit dem Scoping:
Die Funktion scrollHandler hattest Du innerhalb von headerLogoScroll definiert. Dadurch wurde sie bei jedem Aufruf von headerLogoScroll neu angelegt. D. h. die Funktion, die Du beim Entfernen des Listeners übergabst, war nicht die selbe wie die, die Du beim Hinzufügen übergeben hattest (auch wenn sie den selben Namen hatte).
Ich dachte zunächst daran, am Anfang eine leere globale Variable mit dem Funktionsnamen zu definieren und innerhalb von headerLogoScroll dieser die Funktion zuzuweisen aber auch in dem Fall erzeugt Javascript zwei Instanzen, die leere globale und die lokale.
Blieb nur noch, die Funktion scrollHandler aus headerLogoScroll heraus zu ziehen. Das ist das Ergebnis, nicht intensiv getestet aber scheint zu funktionieren:
Code:
        function handleScrolling() {
            var scrollListenerAdded = false;
            var logoHeader = document.getElementById('headerLogo');
            let lastScrollTop = 0;

            const scrollHandler = function () {
                let logoHeight = logoHeader.offsetHeight;
                let logoTop = logoHeader.offsetTop;
                let logoScrollPosHide = logoTop + (logoHeight - (logoHeight / 3));
                let logoBottomPos = logoTop + logoHeight;
                let st = window.scrollY || document.documentElement.scrollTop;

                if (st > lastScrollTop) {
                    console.log('downscroll');

                    if (st < logoBottomPos) {
                        logoHeader.classList.remove('sticky-logo');
                        logoHeader.classList.remove('sticky-logo__animated');
                        logoHeader.classList.remove('sticky-logo__show');
                    }

                    if (st > logoScrollPosHide) {
                        logoHeader.classList.remove('sticky-logo__show');
                        logoHeader.classList.add('sticky-logo');
                    }
                } else if (st < lastScrollTop) {
                    console.log('upscroll');

                    if (st < logoScrollPosHide && st > lastScrollTop) {
                        logoHeader.classList.remove('sticky-logo');
                        logoHeader.classList.remove('sticky-logo__animated');
                        logoHeader.classList.remove('sticky-logo__show');
                    }

                    if (st > logoScrollPosHide) {
                        logoHeader.classList.remove('sticky-logo');
                        logoHeader.classList.add('sticky-logo__animated');
                        logoHeader.classList.add('sticky-logo__show');
                    }
                }

                lastScrollTop = st <= 0 ? 0 : st; // For Mobile or negative scrolling
            }

            function headerLogoScroll() {
                const mobile = window.matchMedia('(max-width:992px)');

                console.log(scrollListenerAdded)
                if (mobile.matches) {
                    console.log('isMobile');
                    if (!scrollListenerAdded) {
                        window.addEventListener('scroll', scrollHandler, false);
                        scrollListenerAdded = true;
                    }
                } else {
                    console.log('notMobile');

                    if (scrollListenerAdded) {
                        window.removeEventListener('scroll', scrollHandler, false);
                        scrollListenerAdded = false;
                    }

                    logoHeader.classList.remove('sticky-logo');
                    logoHeader.classList.remove('sticky-logo__show');
                    logoHeader.classList.remove('sticky-logo__animated');
                }
            }
            window.addEventListener('resize', (event) => {
                headerLogoScroll();
            });
        }
        document.addEventListener('DOMContentLoaded', (event) => {
            handleScrolling();
        });
 
Scheint zu funktionieren!
Wenns keine harten Nüsse wären könnte ich sie ja selbst lösen ;) .

Wenn ich etwas zeit habe versuche ich noch das resize da rauszubekommen. Den eigentlich müsste ja eine matchMaedia Überprüfung reichen wenn der Event startet.

Wie hattest Du das rasugefunden das die Funktion jedesmal neu angelegt wurde?
Idee oder hast dudas durchs Debuggen rasugefunden?

Grüße
 
Zuletzt bearbeitet:
Status
Dieses Thema wurde gelöst! Zur Lösung gehen…

Neue Beiträge

Zurück