@newrelic/video-core 3.1.0 → 3.2.0-beta-0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,15 +2,27 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## [3.2.1] - 2025/07/30
6
+
7
+ ### Breaking Change
8
+
9
+ - Decoupled from browser agent, now uses its own harvesting system for independent data collection.
10
+
11
+ ## [3.1.1] - 2025/06/09
12
+
13
+ ### Fix
14
+
15
+ - Updated event type for `AD_ERROR` to `VideoErrorAction`
16
+
5
17
  ## [3.1.0] - 2025-05-26
6
18
 
7
19
  ### Enhancements
8
20
 
9
- * **Publishing to npm:** The package can now be published to npm, making it easily accessible.
21
+ - **Publishing to npm:** The package can now be published to npm, making it easily accessible.
10
22
 
11
23
  ### Build
12
24
 
13
- * **Distribution Formats:** Added `cjs`, `esm`, and `umd` builds to the `dist` folder, ensuring compatibility with CommonJS, ES Modules, and UMD module formats.
25
+ - **Distribution Formats:** Added `cjs`, `esm`, and `umd` builds to the `dist` folder, ensuring compatibility with CommonJS, ES Modules, and UMD module formats.
14
26
 
15
27
  ## [3.0.0] - 2025/02/20
16
28
 
@@ -186,7 +186,7 @@
186
186
  same "printed page" as the copyright notice for easier
187
187
  identification within third-party archives.
188
188
 
189
- Copyright 2019 New Relic, Inc.
189
+ Copyright New Relic, Inc. All rights reserved.
190
190
 
191
191
  Licensed under the Apache License, Version 2.0 (the "License");
192
192
  you may not use this file except in compliance with the License.
@@ -198,4 +198,4 @@
198
198
  distributed under the License is distributed on an "AS IS" BASIS,
199
199
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
200
  See the License for the specific language governing permissions and
201
- limitations under the License.
201
+ limitations under the License.
package/README.md CHANGED
@@ -2,6 +2,9 @@
2
2
 
3
3
  # New Relic Video Core - JavaScript
4
4
 
5
+ > **⚠️ BETA VERSION NOTICE**
6
+ > This version is currently in **beta phase** and is under active development. Features and APIs may change without notice. Use with caution in production environments and expect potential breaking changes in future releases.
7
+
5
8
  The New Relic video tracking core library is the base for all video trackers in the browser platform. It contains the classes and core mechanisms used by the player specific trackers.
6
9
  It segregates the events into different event types based on action, such as video-related events going to `VideoAction`, ad-related events to `VideoAdAction`, errors to `VideoErrorAction`, and custom actions to `VideoCustomAction`.
7
10
 
@@ -36,10 +39,20 @@ Add **scripts** inside `dist` folder to your page.
36
39
  `nrvideo` provides a class called `VideoTracker` that will serve as an interface with
37
40
  _Browser Agent_, allowing you to manage and send events to New Relic.
38
41
 
39
- First of all, you have to add a tracker in the core class:
42
+ First, configure the authentication options and initialize a tracker:
40
43
 
41
44
  ```javascript
42
- var tracker = new VideoTracker(player);
45
+ const options = {
46
+ info: {
47
+ beacon: "your-beacon-url.nr-data.net",
48
+ errorBeacon: "your-beacon-url.nr-data.net",
49
+ licenseKey: "your-license-key",
50
+ applicationID: "your-application-id",
51
+ sa: 1,
52
+ },
53
+ };
54
+
55
+ const tracker = new VideoTracker(player, options);
43
56
  ```
44
57
 
45
58
  Once the tracker is added, any event it emits will be sent to New Relic and processed by the following functions:
@@ -51,27 +64,14 @@ tracker.sendVideoErrorAction("ErrorEvent", { data: "error-test" });
51
64
  tracker.sendVideoCustomAction("CustomEvent", { data: "custom-test" });
52
65
  ```
53
66
 
54
- Of course, you may want to use built-in events for video. Luckily for you, this core library
55
- provides an easy way of sending video-related content, using `tracker.sendXXXXX` methods.
56
-
57
- ```javascript
58
- tracker.sendRequest(); // Will send CONTENT_REQUEST
59
- ```
60
-
61
- Search for `Tracker#sendXXXX` events in the documentation to read more about it.
62
-
63
67
  ## Data Model
64
68
 
65
- To understand which actions and attributes are captured and emitted by the tracker under different event types, see [DataModel.md](./DATAMODEL.md).
69
+ To understand which actions and attributes are captured and emitted by the tracker under different event types, see [DataModel.md](DATAMODEL.md).
66
70
 
67
71
  ## Documentation
68
72
 
69
73
  All classes are documented using autodocs. The documents, generated with [jsdoc](https://github.com/jsdoc/jsdoc), can be found in the `documentation` directory of the current repo.
70
74
 
71
- # Open source license
72
-
73
- This project is distributed under the [Apache 2 license](LICENSE).
74
-
75
75
  # Support
76
76
 
77
77
  New Relic has open-sourced this project. This project is provided AS-IS WITHOUT WARRANTY OR DEDICATED SUPPORT. Issues and contributions should be reported to the project here on GitHub.
@@ -93,3 +93,9 @@ Issues and enhancement requests can be submitted in the [Issues tab of this repo
93
93
  Contributions are encouraged! If you submit an enhancement request, we'll invite you to contribute the change yourself. Please review our [Contributors Guide](CONTRIBUTING.md).
94
94
 
95
95
  Keep in mind that when you submit your pull request, you'll need to sign the CLA via the click-through using CLA-Assistant. If you'd like to execute our corporate CLA, or if you have any questions, please drop us an email at opensource+videoagent@newrelic.com.
96
+
97
+ # License
98
+
99
+ This project is distributed under the [Apache 2.0](https://apache.org/licenses/LICENSE-2.0.txt) License.
100
+
101
+ The video-core also uses source code from third-party libraries. Full details on which libraries are used and the terms under which they are licensed can be found in the [third-party notices document](THIRD_PARTY_NOTICES.md).
@@ -45,7 +45,7 @@ code, the source code can be found at [https://github.com/newrelic/video-core-js
45
45
 
46
46
  ### @babel/core
47
47
 
48
- This product includes source derived from [@babel/core](https://github.com/babel/babel) ([v7.26.10](https://github.com/babel/babel/tree/v7.26.10)), distributed under the [MIT License](https://github.com/babel/babel/blob/v7.26.10/LICENSE):
48
+ This product includes source derived from [@babel/core](https://github.com/babel/babel) ([v7.27.4](https://github.com/babel/babel/tree/v7.27.4)), distributed under the [MIT License](https://github.com/babel/babel/blob/v7.27.4/LICENSE):
49
49
 
50
50
  ```
51
51
  MIT License
@@ -75,7 +75,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
75
75
 
76
76
  ### @babel/plugin-transform-modules-commonjs
77
77
 
78
- This product includes source derived from [@babel/plugin-transform-modules-commonjs](https://github.com/babel/babel) ([v7.26.3](https://github.com/babel/babel/tree/v7.26.3)), distributed under the [MIT License](https://github.com/babel/babel/blob/v7.26.3/LICENSE):
78
+ This product includes source derived from [@babel/plugin-transform-modules-commonjs](https://github.com/babel/babel) ([v7.27.1](https://github.com/babel/babel/tree/v7.27.1)), distributed under the [MIT License](https://github.com/babel/babel/blob/v7.27.1/LICENSE):
79
79
 
80
80
  ```
81
81
  MIT License
@@ -105,7 +105,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
105
105
 
106
106
  ### @babel/preset-env
107
107
 
108
- This product includes source derived from [@babel/preset-env](https://github.com/babel/babel) ([v7.26.9](https://github.com/babel/babel/tree/v7.26.9)), distributed under the [MIT License](https://github.com/babel/babel/blob/v7.26.9/LICENSE):
108
+ This product includes source derived from [@babel/preset-env](https://github.com/babel/babel) ([v7.27.2](https://github.com/babel/babel/tree/v7.27.2)), distributed under the [MIT License](https://github.com/babel/babel/blob/v7.27.2/LICENSE):
109
109
 
110
110
  ```
111
111
  MIT License
@@ -135,7 +135,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
135
135
 
136
136
  ### @babel/register
137
137
 
138
- This product includes source derived from [@babel/register](https://github.com/babel/babel) ([v7.25.9](https://github.com/babel/babel/tree/v7.25.9)), distributed under the [MIT License](https://github.com/babel/babel/blob/v7.25.9/LICENSE):
138
+ This product includes source derived from [@babel/register](https://github.com/babel/babel) ([v7.27.1](https://github.com/babel/babel/tree/v7.27.1)), distributed under the [MIT License](https://github.com/babel/babel/blob/v7.27.1/LICENSE):
139
139
 
140
140
  ```
141
141
  MIT License
@@ -851,7 +851,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
851
851
 
852
852
  ### webpack
853
853
 
854
- This product includes source derived from [webpack](https://github.com/webpack/webpack) ([v5.98.0](https://github.com/webpack/webpack/tree/v5.98.0)), distributed under the [MIT License](https://github.com/webpack/webpack/blob/v5.98.0/LICENSE):
854
+ This product includes source derived from [webpack](https://github.com/webpack/webpack) ([v5.99.9](https://github.com/webpack/webpack/tree/v5.99.9)), distributed under the [MIT License](https://github.com/webpack/webpack/blob/v5.99.9/LICENSE):
855
855
 
856
856
  ```
857
857
  Copyright JS Foundation and other contributors
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@newrelic/video-core",
3
- "version": "3.1.0",
3
+ "version": "3.2.0-beta-0",
4
4
  "description": "New Relic video tracking core library",
5
5
  "main": "./dist/cjs/index.js",
6
6
  "module": "./dist/esm/index.js",
@@ -23,7 +23,7 @@
23
23
  "contributors": [
24
24
  "Andreu Santarén Llop"
25
25
  ],
26
- "license": "MIT",
26
+ "license": "Apache-2.0",
27
27
  "devDependencies": {
28
28
  "@babel/core": "^7.24.5",
29
29
  "@babel/plugin-transform-modules-commonjs": "^7.24.1",
@@ -45,11 +45,13 @@
45
45
  "files": [
46
46
  "THIRD_PARTY_NOTICES.md",
47
47
  "dist",
48
+ "src",
48
49
  "CHANGELOG.md",
50
+ "LICENSE",
49
51
  "README.md",
50
52
  "!test"
51
53
  ],
52
- "publishConfig": {
54
+ "publishConfig": {
53
55
  "access": "public"
54
56
  }
55
57
  }
package/src/agent.js ADDED
@@ -0,0 +1,6 @@
1
+ import { NRVideoEventAggregator } from "./eventAggregator.js";
2
+ import { NRVideoHarvester } from "./harvester.js";
3
+
4
+ export const customEventAggregator = new NRVideoEventAggregator();
5
+ const harvester = new NRVideoHarvester(customEventAggregator);
6
+ harvester.startTimer();
@@ -0,0 +1,138 @@
1
+ import Constants from "./constants";
2
+
3
+ const { COLLECTOR } = Constants;
4
+
5
+ /**
6
+ * Validates and initializes New Relic video tracking information.
7
+ * @param {object} info - The options object containing authentication information.
8
+ * @param {string} info.licenseKey - The New Relic license key.
9
+ * @param {string} [info.appName] - The name of the application (required if no applicationID).
10
+ * @param {string} [info.region] - The region for the New Relic collector (required if no beacon).
11
+ * @param {string} [info.beacon] - Custom beacon URL (optional, overrides region-based beacon).
12
+ * @param {string} [info.sa] - Security attributes (optional).
13
+ * @param {string} [info.applicationID] - Application ID for beacon-based configuration (optional).
14
+ * @returns {boolean} True if configuration was set successfully, false otherwise.
15
+ * @throws {Error} Throws error for invalid configuration parameters.
16
+ */
17
+ export function setAuthConfig(info) {
18
+ try {
19
+ // Input validation
20
+ if (!info || typeof info !== "object" || Array.isArray(info)) {
21
+ throw new Error("setAuthConfig: info parameter must be a valid object");
22
+ }
23
+
24
+ if (isAuthorised(info)) {
25
+ const { licenseKey, appName, region, beacon, sa, applicationID } = info;
26
+
27
+ // Initialize NRVIDEO global object
28
+ window.NRVIDEO = window.NRVIDEO || {};
29
+
30
+ // Determine beacon URL with fallback
31
+ let beaconUrl = beacon;
32
+ if (!beaconUrl && region) {
33
+ if (!COLLECTOR[region]) {
34
+ throw new Error(
35
+ `setAuthConfig: Invalid region '${region}'. Valid regions: ${Object.keys(
36
+ COLLECTOR
37
+ ).join(", ")}`
38
+ );
39
+ }
40
+ beaconUrl = COLLECTOR[region];
41
+ }
42
+
43
+ window.NRVIDEO.info = {
44
+ beacon: beaconUrl,
45
+ licenseKey,
46
+ applicationID: applicationID || null,
47
+ appName: appName || null,
48
+ sa: sa || 0,
49
+ };
50
+
51
+ return true;
52
+ } else {
53
+ const validationError = getValidationError(info);
54
+ throw new Error(`setAuthConfig: ${validationError}`);
55
+ }
56
+ } catch (error) {
57
+ console.error("setAuthConfig:", error.message);
58
+ return false;
59
+ }
60
+ }
61
+
62
+ /**
63
+ * Checks if the provided information contains valid authentication parameters.
64
+ * @param {object} info - The options object.
65
+ * @returns {boolean} True if authorized, false otherwise.
66
+ */
67
+ function isAuthorised(info) {
68
+ if (!info || typeof info !== "object") {
69
+ return false;
70
+ }
71
+
72
+ const { licenseKey, appName, region, applicationID, beacon } = info;
73
+
74
+ // License key is always required
75
+ if (
76
+ !licenseKey ||
77
+ typeof licenseKey !== "string" ||
78
+ licenseKey.trim().length === 0
79
+ ) {
80
+ return false;
81
+ }
82
+
83
+ // Two valid configuration modes:
84
+ // 1. applicationID + beacon (for direct beacon configuration)
85
+ // 2. appName + region (for region-based beacon resolution)
86
+ if (applicationID) {
87
+ return !!(beacon && typeof beacon === "string" && beacon.trim().length > 0);
88
+ }
89
+
90
+ return !!(
91
+ appName &&
92
+ typeof appName === "string" &&
93
+ appName.trim().length > 0 &&
94
+ region &&
95
+ typeof region === "string" &&
96
+ region.trim().length > 0
97
+ );
98
+ }
99
+
100
+ /**
101
+ * Provides detailed validation error message for debugging.
102
+ * @param {object} info - The options object.
103
+ * @returns {string} Detailed error message.
104
+ */
105
+ function getValidationError(info) {
106
+ if (!info || typeof info !== "object") {
107
+ return "info parameter must be a valid object";
108
+ }
109
+
110
+ const { licenseKey, appName, region, applicationID, beacon } = info;
111
+
112
+ if (
113
+ !licenseKey ||
114
+ typeof licenseKey !== "string" ||
115
+ licenseKey.trim().length === 0
116
+ ) {
117
+ return "licenseKey is required and must be a non-empty string";
118
+ }
119
+
120
+ if (applicationID) {
121
+ if (!beacon || typeof beacon !== "string" || beacon.trim().length === 0) {
122
+ return "beacon URL is required when using applicationID";
123
+ }
124
+ } else {
125
+ if (
126
+ !appName ||
127
+ typeof appName !== "string" ||
128
+ appName.trim().length === 0
129
+ ) {
130
+ return "appName is required when not using applicationID";
131
+ }
132
+ if (!region || typeof region !== "string" || region.trim().length === 0) {
133
+ return "region is required when not using applicationID";
134
+ }
135
+ }
136
+
137
+ return "configuration validation failed";
138
+ }
package/src/chrono.js ADDED
@@ -0,0 +1,78 @@
1
+ /**
2
+ * This class calculates time lapses between two points on time.
3
+ */
4
+ class Chrono {
5
+ /**
6
+ * Constructor
7
+ */
8
+ constructor() {
9
+ this.reset();
10
+ }
11
+
12
+ /** Reset chrono values. */
13
+ reset() {
14
+ /** Start time */
15
+ this.startTime = 0;
16
+
17
+ /** Stop time */
18
+ this.stopTime = 0;
19
+
20
+ /**
21
+ * If you set an offset in a chrono, its value will be added getDeltaTime and stop.
22
+ *
23
+ * @example
24
+ * let chrono = new Chrono()
25
+ * chrono.offset = 500
26
+ * chrono.start()
27
+ * process.sleep(500)
28
+ * chrono.stop() // Will return 1000
29
+ *
30
+ * @type {number}
31
+ */
32
+ this.offset = 0;
33
+ }
34
+
35
+ /**
36
+ * Returns the time between start() and the last stop() in ms. Returns null if start wasn't
37
+ * called.
38
+ * @return {(number|null)} Time lapse in ms.
39
+ */
40
+ getDeltaTime() {
41
+ if (this.startTime) {
42
+ return this.offset + (new Date().getTime() - this.startTime);
43
+ } else {
44
+ return null;
45
+ }
46
+ }
47
+
48
+ /**
49
+ * Starts the chrono.
50
+ */
51
+ start() {
52
+ this.startTime = new Date().getTime();
53
+ this.stopTime = 0;
54
+ }
55
+
56
+ /**
57
+ * Stops the timer and returns delta time.
58
+ * @return {(number|null)} Returns the delta time
59
+ */
60
+ stop() {
61
+ this.stopTime = new Date().getTime();
62
+ return this.getDeltaTime();
63
+ }
64
+
65
+ /**
66
+ * Creates a copy of the chrono.
67
+ * @returns {Chrono} Cloned chrono
68
+ */
69
+ clone() {
70
+ var chrono = new Chrono();
71
+ chrono.startTime = this.startTime;
72
+ chrono.stopTime = this.stopTime;
73
+ chrono.offset = this.offset;
74
+ return chrono;
75
+ }
76
+ }
77
+
78
+ export default Chrono;
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Constants for the library.
3
+ * @class Constants
4
+ * @static
5
+ */
6
+ class Constants {}
7
+
8
+ /**
9
+ * Enum for types/positions of ads.
10
+ * @example var type = Constants.AdPositions.PRE
11
+ * @enum {String}
12
+ */
13
+ Constants.AdPositions = {
14
+ /** For ads shown before the content. */
15
+ PRE: "pre",
16
+ /** For ads shown during the content. */
17
+ MID: "mid",
18
+ /** For ads shown after the content. */
19
+ POST: "post",
20
+ };
21
+
22
+ Constants.INTERVAL = 10000;
23
+ Constants.MAX_EVENTS_PER_BATCH = 1000;
24
+ Constants.MAX_PAYLOAD_SIZE = 1; // 1mb
25
+ Constants.MAX_BEACON_SIZE = 0.0625; // 64kb
26
+ Constants.MAX_EVENT_SIZE = 0.0625; // 64kb
27
+ Constants.VALID_EVENT_TYPES = [
28
+ "VideoAction",
29
+ "VideoAdAction",
30
+ "VideoErrorAction",
31
+ "VideoCustomAction",
32
+ ];
33
+
34
+ Constants.COLLECTOR = {
35
+ US: "bam-cell.nr-data.net",
36
+ EU: "bam.eu01.nr-data.net",
37
+ Stage: "staging-bam-cell.nr-data.net",
38
+ GOV: "gov-bam.nr-data.net",
39
+ };
40
+
41
+ // "bam.nr-data.net",
42
+
43
+ export default Constants;
package/src/core.js ADDED
@@ -0,0 +1,100 @@
1
+ import Log from "./log";
2
+ import { recordEvent } from "./recordEvent";
3
+ import { setAuthConfig } from "./authConfiguration";
4
+
5
+ /**
6
+ * Static class that sums up core functionalities of the library.
7
+ * @static
8
+ */
9
+ class Core {
10
+ /**
11
+ * Add a tracker to the system. Trackers added will start reporting its events to NR's backend.
12
+ *
13
+ * @param {(Emitter|Tracker)} tracker Tracker instance to add.
14
+ */
15
+ static addTracker(tracker, options) {
16
+ setAuthConfig(options.info);
17
+ if (tracker.on && tracker.emit) {
18
+ trackers.push(tracker);
19
+ tracker.on("*", eventHandler);
20
+ if (typeof tracker.trackerInit == "function") {
21
+ tracker.trackerInit();
22
+ }
23
+ } else {
24
+ Log.error("Tried to load a non-tracker.", tracker);
25
+ }
26
+ }
27
+
28
+ /**
29
+ * Disposes and remove given tracker. Removes its listeners.
30
+ *
31
+ * @param {Tracker} tracker Tracker to remove.
32
+ */
33
+ static removeTracker(tracker) {
34
+ tracker.off("*", eventHandler);
35
+ tracker.dispose();
36
+ let index = trackers.indexOf(tracker);
37
+ if (index !== -1) trackers.splice(index, 1);
38
+ }
39
+
40
+ /**
41
+ * Returns the array of trackers.
42
+ *
43
+ * @returns {Tracker[]} Array of trackers.
44
+ */
45
+ static getTrackers() {
46
+ return trackers;
47
+ }
48
+
49
+ static send(eventType, actionName, data) {
50
+ data["timeSinceLoad"] = window.performance.now() / 1000;
51
+ recordEvent(eventType, { actionName, ...data });
52
+ }
53
+
54
+ /**
55
+ * Sends an error event. This may be used for external errors launched by the app, the network or
56
+ * any external factor. Note that errors within the player are normally reported with
57
+ * tracker.sendError, so this method should not be used to report those.
58
+ *
59
+ * @param {object} att attributes to be sent along the error.
60
+ */
61
+ static sendError(att) {
62
+ Core.send("ERROR", att);
63
+ }
64
+ }
65
+
66
+ let trackers = [];
67
+ let isErrorShown = false;
68
+
69
+ /**
70
+ * Logs and sends given event.
71
+ *
72
+ * @private
73
+ * @param {Event} e Event
74
+ */
75
+ function eventHandler(e) {
76
+ let data = cleanData(e.data);
77
+ if (Log.level <= Log.Levels.DEBUG) {
78
+ Log.notice("Sent", e.type, data);
79
+ } else {
80
+ Log.notice("Sent", e.type);
81
+ }
82
+
83
+ Core.send(e.eventType, e.type, data);
84
+ }
85
+
86
+ /**
87
+ * Cleans given object, removing all items with value === null.
88
+ * @private
89
+ * @param {Object} data Data to clean
90
+ * @returns {Object} Cleaned object
91
+ */
92
+ function cleanData(data) {
93
+ let ret = {};
94
+ for (let i in data) {
95
+ if (data[i] !== null && typeof data[i] !== "undefined") ret[i] = data[i];
96
+ }
97
+ return ret;
98
+ }
99
+
100
+ export default Core;
package/src/emitter.js ADDED
@@ -0,0 +1,81 @@
1
+ /**
2
+ * This base class implements a basic behavior of listeners and events. Extend this object to have
3
+ * this feature built-in inside your classes.
4
+ *
5
+ * @class Emitter
6
+ */
7
+ class Emitter {
8
+ /**
9
+ * Sets a listener to a given event. Use {@link emit} to trigger those events.
10
+ * Pass '*' to listen ALL events.
11
+ *
12
+ * @param {string} event Name of the event.
13
+ * @param {function} callback Callback of the event. Receives event and data.
14
+ * @return this
15
+ */
16
+ on(event, callback) {
17
+ this._listeners = this._listeners || {};
18
+ if (typeof callback === "function") {
19
+ this._listeners[event] = this._listeners[event] || [];
20
+ this._listeners[event].push(callback);
21
+ return this;
22
+ }
23
+ }
24
+
25
+ /**
26
+ * Removes given callback from the listeners of this object.
27
+ *
28
+ * @param {string} event Name of the event.
29
+ * @param {function} callback Callback of the event.
30
+ * @return this
31
+ */
32
+ off(event, callback) {
33
+ this._listeners = this._listeners || {};
34
+
35
+ if (this._listeners[event]) {
36
+ var index = this._listeners[event].indexOf(callback);
37
+ if (index !== -1) {
38
+ this._listeners[event].splice(index, 1);
39
+ }
40
+ }
41
+ return this;
42
+ }
43
+
44
+ /**
45
+ * Emits given event, triggering all the associated callbacks.
46
+ *
47
+ * @param {string} event Name of the event.
48
+ * @param {object} [data] Custom data to be sent to the callbacks.
49
+ * @return this
50
+ */
51
+ emit(eventType, event, data) {
52
+ this._listeners = this._listeners || {};
53
+ data = data || {};
54
+
55
+ if (Array.isArray(this._listeners[event])) {
56
+ this._listeners[event].forEach((callback) => {
57
+ callback.call(this, {
58
+ eventType,
59
+ type: event,
60
+ data: data,
61
+ target: this,
62
+ });
63
+ });
64
+ }
65
+
66
+ if (Array.isArray(this._listeners["*"])) {
67
+ this._listeners["*"].forEach((callback) => {
68
+ callback.call(this, {
69
+ eventType,
70
+ type: event,
71
+ data: data,
72
+ target: this,
73
+ });
74
+ });
75
+ }
76
+
77
+ return this;
78
+ }
79
+ }
80
+
81
+ export default Emitter;