EventTrigger.ts

  1. import { isObject, isArray, toArray } from "@daybrush/utils";
  2. import { CallbackType, EventParameter } from "./types";
  3. /**
  4. * attach and trigger event handlers.
  5. */
  6. class EventTrigger {
  7. public events: { [name: string]: CallbackType[] };
  8. /**
  9. * @example
  10. const et = new Scene.EventTrigger();
  11. const scene = new Scene();
  12. scene.on("call", e => {
  13. console.log(e.param);
  14. });
  15. et.on("call", e => {
  16. console.log(e.param);
  17. });
  18. scene.trigger("call", {param: 1});
  19. et.trigger("call", {param: 1});
  20. */
  21. constructor() {
  22. this.events = {};
  23. }
  24. public _on(name: string | EventParameter, callback?: CallbackType | CallbackType[], once?: boolean) {
  25. const events = this.events;
  26. if (isObject(name)) {
  27. for (const n in name) {
  28. this._on(n, name[n], once);
  29. }
  30. return;
  31. }
  32. if (!(name in events)) {
  33. events[name] = [];
  34. }
  35. if (!callback) {
  36. return;
  37. }
  38. if (isArray(callback)) {
  39. callback.forEach(func => this._on(name, func, once));
  40. return;
  41. }
  42. events[name].push(once ? function callback2(...args) {
  43. callback(...args);
  44. this.off(name, callback2);
  45. } : callback);
  46. }
  47. /**
  48. * Attach an event handler function for one or more events to target
  49. * @param - event's name
  50. * @param - function to execute when the event is triggered.
  51. * @return {EventTrigger} An Instance itself.
  52. * @example
  53. target.on("animate", function() {
  54. console.log("animate");
  55. });
  56. target.trigger("animate");
  57. */
  58. public on(name: string | EventParameter, callback?: CallbackType | CallbackType[]) {
  59. this._on(name, callback);
  60. return this;
  61. }
  62. /**
  63. * Dettach an event handler function for one or more events to target
  64. * @param - event's name
  65. * @param - function to execute when the event is triggered.
  66. * @return {EventTrigger} An Instance itself.
  67. * @example
  68. const callback = function() {
  69. console.log("animate");
  70. };
  71. target.on("animate", callback);
  72. target.off("animate", callback);
  73. target.off("animate");
  74. */
  75. public off(name?: string, callback?: CallbackType) {
  76. if (!name) {
  77. this.events = {};
  78. } else if (!callback) {
  79. this.events[name] = [];
  80. } else {
  81. const callbacks = this.events[name];
  82. if (!callbacks) {
  83. return this;
  84. }
  85. const index = callbacks.indexOf(callback);
  86. if (index !== -1) {
  87. callbacks.splice(index, 1);
  88. }
  89. }
  90. return this;
  91. }
  92. /**
  93. * execute event handler
  94. * @param - event's name
  95. * @param - event handler's additional parameter
  96. * @return {EventTrigger} An Instance itself.
  97. * @example
  98. target.on("animate", function(a1, a2) {
  99. console.log("animate", a1, a2);
  100. });
  101. target.trigger("animate", [1, 2]); // log => "animate", 1, 2
  102. */
  103. public trigger(name: string, ...data: any[]) {
  104. const events = this.events;
  105. if (!(name in events)) {
  106. return this;
  107. }
  108. const args = data || [];
  109. !args[0] && (args[0] = {});
  110. const event = events[name];
  111. const target = args[0];
  112. target.type = name;
  113. target.currentTarget = this;
  114. !target.target && (target.target = this);
  115. toArray(events[name]).forEach(callback => {
  116. callback.apply(this, data);
  117. });
  118. return this;
  119. }
  120. public once(name: string | EventParameter, callback?: CallbackType | CallbackType[]) {
  121. this._on(name, callback, true);
  122. return this;
  123. }
  124. }
  125. export default EventTrigger;