remove event listeners in destroy, add once method
This commit is contained in:
parent
0b09b8ee6f
commit
87170ab460
@ -367,6 +367,7 @@ player.fullscreen.enter(); // Enter fullscreen
|
|||||||
| `airplay()` | - | Trigger the airplay dialog on supported devices. |
|
| `airplay()` | - | Trigger the airplay dialog on supported devices. |
|
||||||
| `toggleControls(toggle)` | Boolean | Toggle the controls (video only). Takes optional truthy value to force it on/off. |
|
| `toggleControls(toggle)` | Boolean | Toggle the controls (video only). Takes optional truthy value to force it on/off. |
|
||||||
| `on(event, function)` | String, Function | Add an event listener for the specified event. |
|
| `on(event, function)` | String, Function | Add an event listener for the specified event. |
|
||||||
|
| `once(event, function)` | String, Function | Add an event listener for the specified event once. |
|
||||||
| `off(event, function)` | String, Function | Remove an event listener for the specified event. |
|
| `off(event, function)` | String, Function | Remove an event listener for the specified event. |
|
||||||
| `supports(type)` | String | Check support for a mime type. |
|
| `supports(type)` | String | Check support for a mime type. |
|
||||||
| `destroy()` | - | Destroy the instance and garbage collect any elements. |
|
| `destroy()` | - | Destroy the instance and garbage collect any elements. |
|
||||||
|
@ -80,7 +80,7 @@ const captions = {
|
|||||||
// Watch changes to textTracks and update captions menu
|
// Watch changes to textTracks and update captions menu
|
||||||
if (this.isHTML5) {
|
if (this.isHTML5) {
|
||||||
const trackEvents = this.config.captions.update ? 'addtrack removetrack' : 'removetrack';
|
const trackEvents = this.config.captions.update ? 'addtrack removetrack' : 'removetrack';
|
||||||
utils.on(this.media.textTracks, trackEvents, captions.update.bind(this));
|
utils.on.call(this, this.media.textTracks, trackEvents, captions.update.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update available languages in list next tick (the event must not be triggered before the listeners)
|
// Update available languages in list next tick (the event must not be triggered before the listeners)
|
||||||
@ -107,7 +107,7 @@ const captions = {
|
|||||||
track.mode = 'hidden';
|
track.mode = 'hidden';
|
||||||
|
|
||||||
// Add event listener for cue changes
|
// Add event listener for cue changes
|
||||||
utils.on(track, 'cuechange', () => captions.updateCues.call(this));
|
utils.on.call(this, track, 'cuechange', () => captions.updateCues.call(this));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
4
src/js/controls.js
vendored
4
src/js/controls.js
vendored
@ -1063,12 +1063,10 @@ const controls = {
|
|||||||
container.style.width = '';
|
container.style.width = '';
|
||||||
container.style.height = '';
|
container.style.height = '';
|
||||||
|
|
||||||
// Only listen once
|
|
||||||
utils.off(container, utils.transitionEndEvent, restore);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Listen for the transition finishing and restore auto height/width
|
// Listen for the transition finishing and restore auto height/width
|
||||||
utils.on(container, utils.transitionEndEvent, restore);
|
utils.once(container, utils.transitionEndEvent, restore);
|
||||||
|
|
||||||
// Set dimensions to target
|
// Set dimensions to target
|
||||||
container.style.width = `${size.width}px`;
|
container.style.width = `${size.width}px`;
|
||||||
|
@ -62,13 +62,13 @@ class Fullscreen {
|
|||||||
|
|
||||||
// Register event listeners
|
// Register event listeners
|
||||||
// Handle event (incase user presses escape etc)
|
// Handle event (incase user presses escape etc)
|
||||||
utils.on(document, this.prefix === 'ms' ? 'MSFullscreenChange' : `${this.prefix}fullscreenchange`, () => {
|
utils.on.call(this.player, document, this.prefix === 'ms' ? 'MSFullscreenChange' : `${this.prefix}fullscreenchange`, () => {
|
||||||
// TODO: Filter for target??
|
// TODO: Filter for target??
|
||||||
onChange.call(this);
|
onChange.call(this);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Fullscreen toggle on double click
|
// Fullscreen toggle on double click
|
||||||
utils.on(this.player.elements.container, 'dblclick', event => {
|
utils.on.call(this.player, this.player.elements.container, 'dblclick', event => {
|
||||||
// Ignore double click in controls
|
// Ignore double click in controls
|
||||||
if (utils.is.element(this.player.elements.controls) && this.player.elements.controls.contains(event.target)) {
|
if (utils.is.element(this.player.elements.controls) && this.player.elements.controls.contains(event.target)) {
|
||||||
return;
|
return;
|
||||||
|
@ -63,9 +63,8 @@ const html5 = {
|
|||||||
// Restore time
|
// Restore time
|
||||||
const onLoadedMetaData = () => {
|
const onLoadedMetaData = () => {
|
||||||
player.currentTime = currentTime;
|
player.currentTime = currentTime;
|
||||||
player.off('loadedmetadata', onLoadedMetaData);
|
|
||||||
};
|
};
|
||||||
player.on('loadedmetadata', onLoadedMetaData);
|
player.once('loadedmetadata', onLoadedMetaData);
|
||||||
|
|
||||||
// Load new source
|
// Load new source
|
||||||
player.media.load();
|
player.media.load();
|
||||||
|
@ -197,39 +197,36 @@ class Listeners {
|
|||||||
// Add touch class
|
// Add touch class
|
||||||
utils.toggleClass(this.player.elements.container, this.player.config.classNames.isTouch, true);
|
utils.toggleClass(this.player.elements.container, this.player.config.classNames.isTouch, true);
|
||||||
|
|
||||||
// Clean up
|
|
||||||
utils.off(document.body, 'touchstart', this.firstTouch);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Global window & document listeners
|
// Global window & document listeners
|
||||||
global(toggle = true) {
|
global(toggle = true) {
|
||||||
// Keyboard shortcuts
|
// Keyboard shortcuts
|
||||||
if (this.player.config.keyboard.global) {
|
if (this.player.config.keyboard.global) {
|
||||||
utils.toggleListener(window, 'keydown keyup', this.handleKey, toggle, false);
|
utils.toggleListener.call(this.player, window, 'keydown keyup', this.handleKey, toggle, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Click anywhere closes menu
|
// Click anywhere closes menu
|
||||||
utils.toggleListener(document.body, 'click', this.toggleMenu, toggle);
|
utils.toggleListener.call(this.player, document.body, 'click', this.toggleMenu, toggle);
|
||||||
|
|
||||||
// Detect touch by events
|
// Detect touch by events
|
||||||
utils.on(document.body, 'touchstart', this.firstTouch);
|
utils.once(document.body, 'touchstart', this.firstTouch);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Container listeners
|
// Container listeners
|
||||||
container() {
|
container() {
|
||||||
// Keyboard shortcuts
|
// Keyboard shortcuts
|
||||||
if (!this.player.config.keyboard.global && this.player.config.keyboard.focused) {
|
if (!this.player.config.keyboard.global && this.player.config.keyboard.focused) {
|
||||||
utils.on(this.player.elements.container, 'keydown keyup', this.handleKey, false);
|
utils.on.call(this.player, this.player.elements.container, 'keydown keyup', this.handleKey, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Detect tab focus
|
// Detect tab focus
|
||||||
// Remove class on blur/focusout
|
// Remove class on blur/focusout
|
||||||
utils.on(this.player.elements.container, 'focusout', event => {
|
utils.on.call(this.player, this.player.elements.container, 'focusout', event => {
|
||||||
utils.toggleClass(event.target, this.player.config.classNames.tabFocus, false);
|
utils.toggleClass(event.target, this.player.config.classNames.tabFocus, false);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Add classname to tabbed elements
|
// Add classname to tabbed elements
|
||||||
utils.on(this.player.elements.container, 'keydown', event => {
|
utils.on.call(this.player, this.player.elements.container, 'keydown', event => {
|
||||||
if (event.keyCode !== 9) {
|
if (event.keyCode !== 9) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -242,7 +239,7 @@ class Listeners {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Toggle controls on mouse events and entering fullscreen
|
// Toggle controls on mouse events and entering fullscreen
|
||||||
utils.on(this.player.elements.container, 'mousemove mouseleave touchstart touchmove enterfullscreen exitfullscreen', event => {
|
utils.on.call(this.player, this.player.elements.container, 'mousemove mouseleave touchstart touchmove enterfullscreen exitfullscreen', event => {
|
||||||
const { controls } = this.player.elements;
|
const { controls } = this.player.elements;
|
||||||
|
|
||||||
// Remove button states for fullscreen
|
// Remove button states for fullscreen
|
||||||
@ -276,20 +273,20 @@ class Listeners {
|
|||||||
// Listen for media events
|
// Listen for media events
|
||||||
media() {
|
media() {
|
||||||
// Time change on media
|
// Time change on media
|
||||||
utils.on(this.player.media, 'timeupdate seeking seeked', event => controls.timeUpdate.call(this.player, event));
|
utils.on.call(this.player, this.player.media, 'timeupdate seeking seeked', event => controls.timeUpdate.call(this.player, event));
|
||||||
|
|
||||||
// Display duration
|
// Display duration
|
||||||
utils.on(this.player.media, 'durationchange loadeddata loadedmetadata', event => controls.durationUpdate.call(this.player, event));
|
utils.on.call(this.player, this.player.media, 'durationchange loadeddata loadedmetadata', event => controls.durationUpdate.call(this.player, event));
|
||||||
|
|
||||||
// Check for audio tracks on load
|
// Check for audio tracks on load
|
||||||
// We can't use `loadedmetadata` as it doesn't seem to have audio tracks at that point
|
// We can't use `loadedmetadata` as it doesn't seem to have audio tracks at that point
|
||||||
utils.on(this.player.media, 'loadeddata', () => {
|
utils.on.call(this.player, this.player.media, 'loadeddata', () => {
|
||||||
utils.toggleHidden(this.player.elements.volume, !this.player.hasAudio);
|
utils.toggleHidden(this.player.elements.volume, !this.player.hasAudio);
|
||||||
utils.toggleHidden(this.player.elements.buttons.mute, !this.player.hasAudio);
|
utils.toggleHidden(this.player.elements.buttons.mute, !this.player.hasAudio);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Handle the media finishing
|
// Handle the media finishing
|
||||||
utils.on(this.player.media, 'ended', () => {
|
utils.on.call(this.player, this.player.media, 'ended', () => {
|
||||||
// Show poster on end
|
// Show poster on end
|
||||||
if (this.player.isHTML5 && this.player.isVideo && this.player.config.resetOnEnd) {
|
if (this.player.isHTML5 && this.player.isVideo && this.player.config.resetOnEnd) {
|
||||||
// Restart
|
// Restart
|
||||||
@ -298,20 +295,20 @@ class Listeners {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Check for buffer progress
|
// Check for buffer progress
|
||||||
utils.on(this.player.media, 'progress playing seeking seeked', event => controls.updateProgress.call(this.player, event));
|
utils.on.call(this.player, this.player.media, 'progress playing seeking seeked', event => controls.updateProgress.call(this.player, event));
|
||||||
|
|
||||||
// Handle volume changes
|
// Handle volume changes
|
||||||
utils.on(this.player.media, 'volumechange', event => controls.updateVolume.call(this.player, event));
|
utils.on.call(this.player, this.player.media, 'volumechange', event => controls.updateVolume.call(this.player, event));
|
||||||
|
|
||||||
// Handle play/pause
|
// Handle play/pause
|
||||||
utils.on(this.player.media, 'playing play pause ended emptied timeupdate', event => ui.checkPlaying.call(this.player, event));
|
utils.on.call(this.player, this.player.media, 'playing play pause ended emptied timeupdate', event => ui.checkPlaying.call(this.player, event));
|
||||||
|
|
||||||
// Loading state
|
// Loading state
|
||||||
utils.on(this.player.media, 'waiting canplay seeked playing', event => ui.checkLoading.call(this.player, event));
|
utils.on.call(this.player, this.player.media, 'waiting canplay seeked playing', event => ui.checkLoading.call(this.player, event));
|
||||||
|
|
||||||
// If autoplay, then load advertisement if required
|
// If autoplay, then load advertisement if required
|
||||||
// TODO: Show some sort of loading state while the ad manager loads else there's a delay before ad shows
|
// TODO: Show some sort of loading state while the ad manager loads else there's a delay before ad shows
|
||||||
utils.on(this.player.media, 'playing', () => {
|
utils.on.call(this.player, this.player.media, 'playing', () => {
|
||||||
if (!this.player.ads) {
|
if (!this.player.ads) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -334,7 +331,7 @@ class Listeners {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// On click play, pause ore restart
|
// On click play, pause ore restart
|
||||||
utils.on(wrapper, 'click', () => {
|
utils.on.call(this.player, wrapper, 'click', () => {
|
||||||
// Touch devices will just show controls (if we're hiding controls)
|
// Touch devices will just show controls (if we're hiding controls)
|
||||||
if (this.player.config.hideControls && this.player.touch && !this.player.paused) {
|
if (this.player.config.hideControls && this.player.touch && !this.player.paused) {
|
||||||
return;
|
return;
|
||||||
@ -353,7 +350,7 @@ class Listeners {
|
|||||||
|
|
||||||
// Disable right click
|
// Disable right click
|
||||||
if (this.player.supported.ui && this.player.config.disableContextMenu) {
|
if (this.player.supported.ui && this.player.config.disableContextMenu) {
|
||||||
utils.on(
|
utils.on.call(this.player,
|
||||||
this.player.elements.wrapper,
|
this.player.elements.wrapper,
|
||||||
'contextmenu',
|
'contextmenu',
|
||||||
event => {
|
event => {
|
||||||
@ -364,13 +361,13 @@ class Listeners {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Volume change
|
// Volume change
|
||||||
utils.on(this.player.media, 'volumechange', () => {
|
utils.on.call(this.player, this.player.media, 'volumechange', () => {
|
||||||
// Save to storage
|
// Save to storage
|
||||||
this.player.storage.set({ volume: this.player.volume, muted: this.player.muted });
|
this.player.storage.set({ volume: this.player.volume, muted: this.player.muted });
|
||||||
});
|
});
|
||||||
|
|
||||||
// Speed change
|
// Speed change
|
||||||
utils.on(this.player.media, 'ratechange', () => {
|
utils.on.call(this.player, this.player.media, 'ratechange', () => {
|
||||||
// Update UI
|
// Update UI
|
||||||
controls.updateSetting.call(this.player, 'speed');
|
controls.updateSetting.call(this.player, 'speed');
|
||||||
|
|
||||||
@ -379,19 +376,19 @@ class Listeners {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Quality request
|
// Quality request
|
||||||
utils.on(this.player.media, 'qualityrequested', event => {
|
utils.on.call(this.player, this.player.media, 'qualityrequested', event => {
|
||||||
// Save to storage
|
// Save to storage
|
||||||
this.player.storage.set({ quality: event.detail.quality });
|
this.player.storage.set({ quality: event.detail.quality });
|
||||||
});
|
});
|
||||||
|
|
||||||
// Quality change
|
// Quality change
|
||||||
utils.on(this.player.media, 'qualitychange', event => {
|
utils.on.call(this.player, this.player.media, 'qualitychange', event => {
|
||||||
// Update UI
|
// Update UI
|
||||||
controls.updateSetting.call(this.player, 'quality', null, event.detail.quality);
|
controls.updateSetting.call(this.player, 'quality', null, event.detail.quality);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Caption language change
|
// Caption language change
|
||||||
utils.on(this.player.media, 'languagechange', () => {
|
utils.on.call(this.player, this.player.media, 'languagechange', () => {
|
||||||
// Update UI
|
// Update UI
|
||||||
controls.updateSetting.call(this.player, 'captions');
|
controls.updateSetting.call(this.player, 'captions');
|
||||||
|
|
||||||
@ -400,7 +397,7 @@ class Listeners {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Captions toggle
|
// Captions toggle
|
||||||
utils.on(this.player.media, 'captionsenabled captionsdisabled', () => {
|
utils.on.call(this.player, this.player.media, 'captionsenabled captionsdisabled', () => {
|
||||||
// Update UI
|
// Update UI
|
||||||
controls.updateSetting.call(this.player, 'captions');
|
controls.updateSetting.call(this.player, 'captions');
|
||||||
|
|
||||||
@ -410,7 +407,7 @@ class Listeners {
|
|||||||
|
|
||||||
// Proxy events to container
|
// Proxy events to container
|
||||||
// Bubble up key events for Edge
|
// Bubble up key events for Edge
|
||||||
utils.on(this.player.media, this.player.config.events.concat([
|
utils.on.call(this.player, this.player.media, this.player.config.events.concat([
|
||||||
'keyup',
|
'keyup',
|
||||||
'keydown',
|
'keydown',
|
||||||
]).join(' '), event => {
|
]).join(' '), event => {
|
||||||
@ -452,7 +449,7 @@ class Listeners {
|
|||||||
const customHandler = this.player.config.listeners[customHandlerKey];
|
const customHandler = this.player.config.listeners[customHandlerKey];
|
||||||
const hasCustomHandler = utils.is.function(customHandler);
|
const hasCustomHandler = utils.is.function(customHandler);
|
||||||
|
|
||||||
utils.on(element, type, event => proxy(event, defaultHandler, customHandlerKey), passive && !hasCustomHandler);
|
utils.on.call(this.player, element, type, event => proxy(event, defaultHandler, customHandlerKey), passive && !hasCustomHandler);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Play/pause toggle
|
// Play/pause toggle
|
||||||
@ -727,11 +724,6 @@ class Listeners {
|
|||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset on destroy
|
|
||||||
clear() {
|
|
||||||
this.global(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Listeners;
|
export default Listeners;
|
||||||
|
@ -245,6 +245,8 @@ class Plyr {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.eventListeners = [];
|
||||||
|
|
||||||
// Create listeners
|
// Create listeners
|
||||||
this.listeners = new Listeners(this);
|
this.listeners = new Listeners(this);
|
||||||
|
|
||||||
@ -271,7 +273,7 @@ class Plyr {
|
|||||||
|
|
||||||
// Listen for events if debugging
|
// Listen for events if debugging
|
||||||
if (this.config.debug) {
|
if (this.config.debug) {
|
||||||
utils.on(this.elements.container, this.config.events.join(' '), event => {
|
utils.on.call(this, this.elements.container, this.config.events.join(' '), event => {
|
||||||
this.debug.log(`event: ${event.type}`);
|
this.debug.log(`event: ${event.type}`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -961,9 +963,16 @@ class Plyr {
|
|||||||
* @param {function} callback - Callback for when event occurs
|
* @param {function} callback - Callback for when event occurs
|
||||||
*/
|
*/
|
||||||
on(event, callback) {
|
on(event, callback) {
|
||||||
utils.on(this.elements.container, event, callback);
|
utils.on.call(this, this.elements.container, event, callback);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Add event listeners once
|
||||||
|
* @param {string} event - Event type
|
||||||
|
* @param {function} callback - Callback for when event occurs
|
||||||
|
*/
|
||||||
|
once(event, callback) {
|
||||||
|
utils.once(this.elements.container, event, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove event listeners
|
* Remove event listeners
|
||||||
* @param {string} event - Event type
|
* @param {string} event - Event type
|
||||||
@ -1014,8 +1023,7 @@ class Plyr {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Unbind listeners
|
// Unbind listeners
|
||||||
this.listeners.clear();
|
utils.cleanupEventListeners.call(this);
|
||||||
|
|
||||||
// Replace the container with the original element provided
|
// Replace the container with the original element provided
|
||||||
utils.replaceElement(this.elements.original, this.elements.container);
|
utils.replaceElement(this.elements.original, this.elements.container);
|
||||||
|
|
||||||
|
@ -494,14 +494,14 @@ const utils = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (toggle) {
|
if (toggle) {
|
||||||
utils.on(this.elements.container, 'keydown', trap, false);
|
utils.on.call(this, this.elements.container, 'keydown', trap, false);
|
||||||
} else {
|
} else {
|
||||||
utils.off(this.elements.container, 'keydown', trap, false);
|
utils.off(this.elements.container, 'keydown', trap, false);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// Toggle event listener
|
// Toggle event listener
|
||||||
toggleListener(elements, event, callback, toggle = false, passive = true, capture = false) {
|
toggleListener(elements, event, callback, toggle = false, passive = true, capture = false, once = false) {
|
||||||
// Bail if no elemetns, event, or callback
|
// Bail if no elemetns, event, or callback
|
||||||
if (utils.is.empty(elements) || utils.is.empty(event) || !utils.is.function(callback)) {
|
if (utils.is.empty(elements) || utils.is.empty(event) || !utils.is.function(callback)) {
|
||||||
return;
|
return;
|
||||||
@ -512,7 +512,7 @@ const utils = {
|
|||||||
// Create listener for each node
|
// Create listener for each node
|
||||||
Array.from(elements).forEach(element => {
|
Array.from(elements).forEach(element => {
|
||||||
if (element instanceof Node) {
|
if (element instanceof Node) {
|
||||||
utils.toggleListener.call(null, element, event, callback, toggle, passive, capture);
|
utils.toggleListener.call(this, element, event, callback, toggle, passive, capture, once);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -538,13 +538,35 @@ const utils = {
|
|||||||
|
|
||||||
// If a single node is passed, bind the event listener
|
// If a single node is passed, bind the event listener
|
||||||
events.forEach(type => {
|
events.forEach(type => {
|
||||||
|
if (this && this.eventListeners && toggle && !once) {
|
||||||
|
// cache event listener
|
||||||
|
this.eventListeners.push({ elements, type, callback, options });
|
||||||
|
}
|
||||||
elements[toggle ? 'addEventListener' : 'removeEventListener'](type, callback, options);
|
elements[toggle ? 'addEventListener' : 'removeEventListener'](type, callback, options);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
// remove all cached event listeners
|
||||||
|
cleanupEventListeners() {
|
||||||
|
if (this && this.eventListeners) {
|
||||||
|
this.eventListeners.forEach(item => {
|
||||||
|
const { elements, type, callback, options } = item;
|
||||||
|
elements.removeEventListener(type, callback, options);
|
||||||
|
});
|
||||||
|
this.eventListeners = [];
|
||||||
|
}
|
||||||
|
},
|
||||||
// Bind event handler
|
// Bind event handler
|
||||||
on(element, events = '', callback, passive = true, capture = false) {
|
on(element, events = '', callback, passive = true, capture = false) {
|
||||||
utils.toggleListener(element, events, callback, true, passive, capture);
|
utils.toggleListener.call(this, element, events, callback, true, passive, capture);
|
||||||
|
},
|
||||||
|
|
||||||
|
// Bind event handler once
|
||||||
|
once(element, events = '', callback, passive = true, capture = false) {
|
||||||
|
function onceCallback(...args) {
|
||||||
|
utils.off(element, events, onceCallback, passive, capture);
|
||||||
|
callback.apply(this, args);
|
||||||
|
}
|
||||||
|
utils.toggleListener(element, events, onceCallback, true, passive, capture, true);
|
||||||
},
|
},
|
||||||
|
|
||||||
// Unbind event handler
|
// Unbind event handler
|
||||||
|
Loading…
x
Reference in New Issue
Block a user