Source: lib/util/event_manager.js

  1. /**
  2. * @license
  3. * Copyright 2016 Google Inc.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. goog.provide('shaka.util.EventManager');
  18. goog.require('goog.asserts');
  19. goog.require('shaka.util.IDestroyable');
  20. goog.require('shaka.util.MultiMap');
  21. /**
  22. * Creates a new EventManager. An EventManager maintains a collection of "event
  23. * bindings" between event targets and event listeners.
  24. *
  25. * @struct
  26. * @constructor
  27. * @implements {shaka.util.IDestroyable}
  28. */
  29. shaka.util.EventManager = function() {
  30. /**
  31. * Maps an event type to an array of event bindings.
  32. * @private {shaka.util.MultiMap.<!shaka.util.EventManager.Binding_>}
  33. */
  34. this.bindingMap_ = new shaka.util.MultiMap();
  35. };
  36. /**
  37. * @typedef {function(!Event)}
  38. */
  39. shaka.util.EventManager.ListenerType;
  40. /**
  41. * Detaches all event listeners.
  42. * @override
  43. */
  44. shaka.util.EventManager.prototype.destroy = function() {
  45. this.removeAll();
  46. this.bindingMap_ = null;
  47. return Promise.resolve();
  48. };
  49. /**
  50. * Attaches an event listener to an event target.
  51. * @param {EventTarget} target The event target.
  52. * @param {string} type The event type.
  53. * @param {shaka.util.EventManager.ListenerType} listener The event listener.
  54. */
  55. shaka.util.EventManager.prototype.listen = function(target, type, listener) {
  56. if (!this.bindingMap_) return;
  57. let binding = new shaka.util.EventManager.Binding_(target, type, listener);
  58. this.bindingMap_.push(type, binding);
  59. };
  60. /**
  61. * Attaches an event listener to an event target. The listener will be removed
  62. * when the first instance of the event is fired.
  63. * @param {EventTarget} target The event target.
  64. * @param {string} type The event type.
  65. * @param {shaka.util.EventManager.ListenerType} listener The event listener.
  66. */
  67. shaka.util.EventManager.prototype.listenOnce =
  68. function(target, type, listener) {
  69. // Install a shim listener that will stop listening after the first event.
  70. this.listen(target, type, function(event) {
  71. // Stop listening to this event.
  72. this.unlisten(target, type);
  73. // Call the original listener.
  74. listener(event);
  75. }.bind(this));
  76. };
  77. /**
  78. * Detaches an event listener from an event target.
  79. * @param {EventTarget} target The event target.
  80. * @param {string} type The event type.
  81. */
  82. shaka.util.EventManager.prototype.unlisten = function(target, type) {
  83. if (!this.bindingMap_) return;
  84. let list = this.bindingMap_.get(type) || [];
  85. for (let i = 0; i < list.length; ++i) {
  86. let binding = list[i];
  87. if (binding.target == target) {
  88. binding.unlisten();
  89. this.bindingMap_.remove(type, binding);
  90. }
  91. }
  92. };
  93. /**
  94. * Detaches all event listeners from all targets.
  95. */
  96. shaka.util.EventManager.prototype.removeAll = function() {
  97. if (!this.bindingMap_) return;
  98. let list = this.bindingMap_.getAll();
  99. for (let i = 0; i < list.length; ++i) {
  100. list[i].unlisten();
  101. }
  102. this.bindingMap_.clear();
  103. };
  104. /**
  105. * Creates a new Binding_ and attaches the event listener to the event target.
  106. * @param {EventTarget} target The event target.
  107. * @param {string} type The event type.
  108. * @param {shaka.util.EventManager.ListenerType} listener The event listener.
  109. * @constructor
  110. * @private
  111. */
  112. shaka.util.EventManager.Binding_ = function(target, type, listener) {
  113. /** @type {EventTarget} */
  114. this.target = target;
  115. /** @type {string} */
  116. this.type = type;
  117. /** @type {?shaka.util.EventManager.ListenerType} */
  118. this.listener = listener;
  119. this.target.addEventListener(type, listener, false);
  120. };
  121. /**
  122. * Detaches the event listener from the event target. This does nothing if the
  123. * event listener is already detached.
  124. */
  125. shaka.util.EventManager.Binding_.prototype.unlisten = function() {
  126. goog.asserts.assert(this.target, 'Missing target');
  127. this.target.removeEventListener(this.type, this.listener, false);
  128. this.target = null;
  129. this.listener = null;
  130. };