简体   繁体   中英

Update event listeners when page switches

I'm in a bit of a predicament, because I need to somehow update event listeners, when the page changes using ajax. I have a specific element that I need to update based on what page the ajax call injects. Here's my issue:

I have this slider control constructor:

UI.CONTROLS.SLIDER = function (select, action, actionWhenActive, actionWhenSet) {
    'use strict';
    var self = this;
    this.action = action;
    this.select = select;
    this.area = select.find($('area-'));
    this.fill = select.find($('fill-'));
    this.value = 0;
    this.active = false;
    this.actionWhenActive = actionWhenActive;
    this.actionWhenSet = actionWhenSet;

    function eventlisteners(self) {
        $(document).on('mousemove', function (event) {
            self.move(event, self);
        });
        $(document).on('mouseup', function (event) {
            self.drop(event, self);
        });
        self.area.on('mousedown', function (event) {
            self.grab(event, self);
        });
    }
    eventlisteners(self);

    this.reselect = function (element) {
        self.area = element.find($('area-'));
        self.fill = element.find($('fill-'));
        eventlisteners(self);
    };
};

UI.CONTROLS.SLIDER.prototype = {
    action: this.action,
    width: function () {
        'use strict';
        var calcWidth = ((this.value * 100) + '%');
        this.fill.width(calcWidth);
    },
    update: function (event, self) {
        'use strict';
        if (this.actionWhenActive === true) {
            this.action();
        }
        var direction, percent, container, area;
        direction = event.pageX - this.area.offset().left;
        percent = Math.min(Math.max(direction / this.area.width(), 0), 1.0);
        this.value = percent;
        this.width();
    },
    move: function (event, self) {
        'use strict';
        if (this.active === true) {
            this.update(event);
        }
    },
    grab: function (event, self) {
        'use strict';
        this.active = true;
        self.update(event);
        event.preventDefault();
    },
    drop: function (event, self) {
        'use strict';
        if (this.active === true) {
            this.active = false;
            this.action();
        }
    },
    setValue: function (value) {
        'use strict';
        if (this.active === false) {
            this.value = value;
            this.width();
            if (this.actionWhenSet === true) {
                this.action();
            }
        }
    }
};

This can create new sliders based on the container ( select ) specified. In my website, I have an audio player. So using ajax you can navigate while this audio player plays. I have two states, viewing a track, and not viewing a track. When you're not viewing the track that is playing, a transport bar will pop down from the header containing the scrubber (slider control), this scrubber is also inside the track view (viewing the track) page.

This code checks if you're viewing the track that is playing. audioFromView gets updated on the ajax calls, it basically replaces it with what track you're viewing. It then compares it with audioCurrent which is the track currently playing, UI.PAGE.TYPE is what type of page you're viewing, in this instance a track:

var audioViewIsCurrent = function () {
    'use strict';
    if (audioCurrent.src === audioFromView.src && UI.PAGE.TYPE === 'track') {
        return true;
    } else {
        return false;
    }
};

So this code then updates the scrubber based on the above code's output (audioElementTrackView is the scrubber inside the track page, and audioElementTransport is the scrubber inside the transport panel):

var audioScrubber = {
    element: {},
    active: false,
    action: function () {
        'use strict';
        audioScrubber.active = this.active;
        var time = audioSource.duration * this.value;
        if (this.active === false) {
            audioCurrent.time(this.value * duration);
        }
    },
    set: function () {
        'use strict';
        var container, slider;
        if (audioElementTrackView.length === 1) {
            container = audioElementTrackView.find(audioElementScrubber);
        } else {
            container = audioElementTransport.find(audioElementScrubber);
        }
        this.element = new UI.CONTROLS.SLIDER(container, this.action, true);
    },
    reselect: function () {
        if (audioElementTrackView.length === 1) {
            container = audioElementTrackView.find(audioElementScrubber);
        } else {
            container = audioElementTransport.find(audioElementScrubber);
        }
        this.element.reselect(container)
    }
};

audioScrubber.reselect()

So this works fine with how I'm currently doing it, HOWEVER since I am adding new event listeners everytime I update my scrubber object (inside the ajax call) in order to keep the scrubber working I am also piling them up, making the old event listeners take up space and RAM eventually making the site slow down to a halt (if you navigate enough)

I tested this using console.log on mouseup, everytime I switched page, it would log it twice, and then thrice and so on.

How can I avoid this?

You can delegate events to the nearest static ancestor, so you don't need to rebind them everyime.

Read this article

https://davidwalsh.name/event-delegate

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM