@microsoft/applicationinsights-core-js 2.8.0-beta.2203-01 → 2.8.0-beta.2203-04

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.
Files changed (128) hide show
  1. package/browser/applicationinsights-core-js.integrity.json +9 -9
  2. package/browser/applicationinsights-core-js.js +1137 -484
  3. package/browser/applicationinsights-core-js.js.map +1 -1
  4. package/browser/applicationinsights-core-js.min.js +2 -2
  5. package/browser/applicationinsights-core-js.min.js.map +1 -1
  6. package/dist/applicationinsights-core-js.api.json +6529 -2784
  7. package/dist/applicationinsights-core-js.api.md +290 -30
  8. package/dist/applicationinsights-core-js.d.ts +481 -89
  9. package/dist/applicationinsights-core-js.js +1137 -484
  10. package/dist/applicationinsights-core-js.js.map +1 -1
  11. package/dist/applicationinsights-core-js.min.js +2 -2
  12. package/dist/applicationinsights-core-js.min.js.map +1 -1
  13. package/dist/applicationinsights-core-js.rollup.d.ts +481 -89
  14. package/dist-esm/JavaScriptSDK/AppInsightsCore.js +1 -1
  15. package/dist-esm/JavaScriptSDK/BaseCore.js +248 -32
  16. package/dist-esm/JavaScriptSDK/BaseCore.js.map +1 -1
  17. package/dist-esm/JavaScriptSDK/BaseTelemetryPlugin.js +50 -5
  18. package/dist-esm/JavaScriptSDK/BaseTelemetryPlugin.js.map +1 -1
  19. package/dist-esm/JavaScriptSDK/ChannelController.js +105 -73
  20. package/dist-esm/JavaScriptSDK/ChannelController.js.map +1 -1
  21. package/dist-esm/JavaScriptSDK/Constants.js +1 -1
  22. package/dist-esm/JavaScriptSDK/CookieMgr.js +3 -4
  23. package/dist-esm/JavaScriptSDK/CookieMgr.js.map +1 -1
  24. package/dist-esm/JavaScriptSDK/CoreUtils.js +6 -122
  25. package/dist-esm/JavaScriptSDK/CoreUtils.js.map +1 -1
  26. package/dist-esm/JavaScriptSDK/DataCacheHelper.js +93 -0
  27. package/dist-esm/JavaScriptSDK/DataCacheHelper.js.map +1 -0
  28. package/dist-esm/JavaScriptSDK/DbgExtensionUtils.js +1 -1
  29. package/dist-esm/JavaScriptSDK/DiagnosticLogger.js +12 -12
  30. package/dist-esm/JavaScriptSDK/DiagnosticLogger.js.map +1 -1
  31. package/dist-esm/JavaScriptSDK/EnvUtils.js +8 -7
  32. package/dist-esm/JavaScriptSDK/EnvUtils.js.map +1 -1
  33. package/dist-esm/JavaScriptSDK/EventHelpers.js +472 -0
  34. package/dist-esm/JavaScriptSDK/EventHelpers.js.map +1 -0
  35. package/dist-esm/JavaScriptSDK/HelperFuncs.js +32 -59
  36. package/dist-esm/JavaScriptSDK/HelperFuncs.js.map +1 -1
  37. package/dist-esm/JavaScriptSDK/InstrumentHooks.js +1 -1
  38. package/dist-esm/JavaScriptSDK/InternalConstants.js +28 -0
  39. package/dist-esm/JavaScriptSDK/InternalConstants.js.map +1 -0
  40. package/dist-esm/JavaScriptSDK/NotificationManager.js +8 -11
  41. package/dist-esm/JavaScriptSDK/NotificationManager.js.map +1 -1
  42. package/dist-esm/JavaScriptSDK/PerfManager.js +1 -1
  43. package/dist-esm/JavaScriptSDK/ProcessTelemetryContext.js +195 -107
  44. package/dist-esm/JavaScriptSDK/ProcessTelemetryContext.js.map +1 -1
  45. package/dist-esm/JavaScriptSDK/RandomHelper.js +3 -2
  46. package/dist-esm/JavaScriptSDK/RandomHelper.js.map +1 -1
  47. package/dist-esm/JavaScriptSDK/TelemetryHelpers.js +32 -13
  48. package/dist-esm/JavaScriptSDK/TelemetryHelpers.js.map +1 -1
  49. package/dist-esm/JavaScriptSDK/TelemetryInitializerPlugin.js +4 -6
  50. package/dist-esm/JavaScriptSDK/TelemetryInitializerPlugin.js.map +1 -1
  51. package/dist-esm/JavaScriptSDK/UnloadHandlerContainer.js +32 -0
  52. package/dist-esm/JavaScriptSDK/UnloadHandlerContainer.js.map +1 -0
  53. package/dist-esm/JavaScriptSDK.Enums/EventsDiscardedReason.js +1 -1
  54. package/dist-esm/JavaScriptSDK.Enums/LoggingEnums.js +90 -96
  55. package/dist-esm/JavaScriptSDK.Enums/LoggingEnums.js.map +1 -1
  56. package/dist-esm/JavaScriptSDK.Enums/SendRequestReason.js +1 -1
  57. package/dist-esm/JavaScriptSDK.Enums/TelemetryUnloadReason.js +8 -0
  58. package/dist-esm/JavaScriptSDK.Enums/TelemetryUnloadReason.js.map +1 -0
  59. package/dist-esm/JavaScriptSDK.Interfaces/IAppInsightsCore.js +1 -1
  60. package/dist-esm/JavaScriptSDK.Interfaces/IChannelControls.js +1 -1
  61. package/dist-esm/JavaScriptSDK.Interfaces/IConfiguration.js +1 -1
  62. package/dist-esm/JavaScriptSDK.Interfaces/ICookieMgr.js +1 -1
  63. package/dist-esm/JavaScriptSDK.Interfaces/IDbgExtension.js +1 -1
  64. package/dist-esm/JavaScriptSDK.Interfaces/IDiagnosticLogger.js +1 -1
  65. package/dist-esm/JavaScriptSDK.Interfaces/IInstrumentHooks.js +1 -1
  66. package/dist-esm/JavaScriptSDK.Interfaces/INotificationListener.js +1 -1
  67. package/dist-esm/JavaScriptSDK.Interfaces/INotificationManager.js +1 -1
  68. package/dist-esm/JavaScriptSDK.Interfaces/IPerfEvent.js +1 -1
  69. package/dist-esm/JavaScriptSDK.Interfaces/IPerfManager.js +1 -1
  70. package/dist-esm/JavaScriptSDK.Interfaces/IProcessTelemetryContext.js +1 -1
  71. package/dist-esm/JavaScriptSDK.Interfaces/ITelemetryInitializers.js +1 -1
  72. package/dist-esm/JavaScriptSDK.Interfaces/ITelemetryItem.js +1 -1
  73. package/dist-esm/JavaScriptSDK.Interfaces/ITelemetryPlugin.js +1 -1
  74. package/dist-esm/JavaScriptSDK.Interfaces/ITelemetryPluginChain.js +1 -2
  75. package/dist-esm/JavaScriptSDK.Interfaces/ITelemetryPluginChain.js.map +1 -1
  76. package/dist-esm/JavaScriptSDK.Interfaces/ITelemetryUnloadState.js +8 -0
  77. package/dist-esm/JavaScriptSDK.Interfaces/ITelemetryUnloadState.js.map +1 -0
  78. package/dist-esm/applicationinsights-core-js.js +9 -4
  79. package/dist-esm/applicationinsights-core-js.js.map +1 -1
  80. package/package.json +1 -1
  81. package/src/JavaScriptSDK/BaseCore.ts +312 -33
  82. package/src/JavaScriptSDK/BaseTelemetryPlugin.ts +90 -5
  83. package/src/JavaScriptSDK/ChannelController.ts +107 -61
  84. package/src/JavaScriptSDK/CookieMgr.ts +4 -4
  85. package/src/JavaScriptSDK/CoreUtils.ts +6 -143
  86. package/src/JavaScriptSDK/DataCacheHelper.ts +106 -0
  87. package/src/JavaScriptSDK/DiagnosticLogger.ts +12 -11
  88. package/src/JavaScriptSDK/EnvUtils.ts +7 -6
  89. package/src/JavaScriptSDK/EventHelpers.ts +542 -0
  90. package/src/JavaScriptSDK/HelperFuncs.ts +35 -54
  91. package/src/JavaScriptSDK/InternalConstants.ts +26 -0
  92. package/src/JavaScriptSDK/NotificationManager.ts +7 -11
  93. package/src/JavaScriptSDK/ProcessTelemetryContext.ts +248 -121
  94. package/src/JavaScriptSDK/RandomHelper.ts +2 -1
  95. package/src/JavaScriptSDK/TelemetryHelpers.ts +47 -15
  96. package/src/JavaScriptSDK/TelemetryInitializerPlugin.ts +5 -15
  97. package/src/JavaScriptSDK/UnloadHandlerContainer.ts +44 -0
  98. package/src/JavaScriptSDK.Enums/LoggingEnums.ts +184 -87
  99. package/src/JavaScriptSDK.Enums/SendRequestReason.ts +5 -0
  100. package/src/JavaScriptSDK.Enums/TelemetryUnloadReason.ts +27 -0
  101. package/src/JavaScriptSDK.Interfaces/IAppInsightsCore.ts +49 -2
  102. package/src/JavaScriptSDK.Interfaces/IChannelControls.ts +9 -2
  103. package/src/JavaScriptSDK.Interfaces/IProcessTelemetryContext.ts +55 -16
  104. package/src/JavaScriptSDK.Interfaces/ITelemetryPlugin.ts +16 -9
  105. package/src/JavaScriptSDK.Interfaces/ITelemetryPluginChain.ts +9 -11
  106. package/src/JavaScriptSDK.Interfaces/ITelemetryUnloadState.ts +10 -0
  107. package/types/JavaScriptSDK/BaseCore.d.ts +21 -1
  108. package/types/JavaScriptSDK/BaseTelemetryPlugin.d.ts +26 -1
  109. package/types/JavaScriptSDK/ChannelController.d.ts +4 -0
  110. package/types/JavaScriptSDK/CoreUtils.d.ts +1 -42
  111. package/types/JavaScriptSDK/DataCacheHelper.d.ts +13 -0
  112. package/types/JavaScriptSDK/EventHelpers.d.ts +152 -0
  113. package/types/JavaScriptSDK/HelperFuncs.d.ts +8 -17
  114. package/types/JavaScriptSDK/InternalConstants.d.ts +20 -0
  115. package/types/JavaScriptSDK/ProcessTelemetryContext.d.ts +12 -3
  116. package/types/JavaScriptSDK/TelemetryHelpers.d.ts +8 -0
  117. package/types/JavaScriptSDK/TelemetryInitializerPlugin.d.ts +0 -7
  118. package/types/JavaScriptSDK/UnloadHandlerContainer.d.ts +11 -0
  119. package/types/JavaScriptSDK.Enums/LoggingEnums.d.ts +91 -2
  120. package/types/JavaScriptSDK.Enums/SendRequestReason.d.ts +4 -0
  121. package/types/JavaScriptSDK.Enums/TelemetryUnloadReason.d.ts +21 -0
  122. package/types/JavaScriptSDK.Interfaces/IAppInsightsCore.d.ts +41 -1
  123. package/types/JavaScriptSDK.Interfaces/IChannelControls.d.ts +9 -2
  124. package/types/JavaScriptSDK.Interfaces/IProcessTelemetryContext.d.ts +49 -14
  125. package/types/JavaScriptSDK.Interfaces/ITelemetryPlugin.d.ts +15 -8
  126. package/types/JavaScriptSDK.Interfaces/ITelemetryPluginChain.d.ts +9 -10
  127. package/types/JavaScriptSDK.Interfaces/ITelemetryUnloadState.d.ts +6 -0
  128. package/types/applicationinsights-core-js.d.ts +7 -3
@@ -0,0 +1,542 @@
1
+ // Copyright (c) Microsoft Corporation. All rights reserved.
2
+ // Licensed under the MIT License.
3
+ import { createElmNodeData, createUniqueNamespace } from "./DataCacheHelper";
4
+ import { getDocument, getWindow } from "./EnvUtils";
5
+ import { arrForEach, arrIndexOf, isArray, objForEachKey, objKeys } from "./HelperFuncs";
6
+
7
+ // Added to help with minfication
8
+ const strOnPrefix = "on";
9
+ const strAttachEvent = "attachEvent";
10
+ const strAddEventHelper = "addEventListener";
11
+ const strDetachEvent = "detachEvent";
12
+ const strRemoveEventListener = "removeEventListener";
13
+ const strEvents = "events"
14
+ const strVisibilityChangeEvt: string = "visibilitychange";
15
+ const strPageHide: string = "pagehide";
16
+ const strPageShow: string = "pageshow";
17
+ const strUnload: string = "unload";
18
+ const strBeforeUnload: string = "beforeunload";
19
+
20
+ const strPageHideNamespace = createUniqueNamespace("aiEvtPageHide");
21
+ const strPageShowNamespace = createUniqueNamespace("aiEvtPageShow");
22
+
23
+ let _guid = 1;
24
+
25
+ interface IEventDetails {
26
+ type: string,
27
+ ns: string
28
+ }
29
+
30
+ interface IRegisteredEvent {
31
+ guid: number;
32
+ evtName: IEventDetails;
33
+ handler: any,
34
+ capture: boolean
35
+ }
36
+
37
+ interface IAiEvents {
38
+ [name: string]: IRegisteredEvent[]
39
+ }
40
+
41
+ const elmNodeData = createElmNodeData("events");
42
+ const eventNamespace = /^([^.]*)(?:\.(.+)|)/
43
+
44
+ function _normalizeNamespace(name: string) {
45
+ if (name && name.replace) {
46
+ return name.replace(/^\s*\.*|\.*\s*$/g, "");
47
+ }
48
+
49
+ return name;
50
+ }
51
+
52
+ function _getEvtNamespace(eventName: string, namespaces: string | string[]): IEventDetails {
53
+ if (namespaces) {
54
+ let theNamespace: string = "";
55
+ if (isArray(namespaces)) {
56
+ theNamespace = "";
57
+ arrForEach(namespaces, (name) => {
58
+ name = _normalizeNamespace(name);
59
+ if (name) {
60
+ if (name[0] !== ".") {
61
+ name = "." + name;
62
+ }
63
+
64
+ theNamespace += name;
65
+ }
66
+ });
67
+ } else {
68
+ theNamespace = _normalizeNamespace(namespaces);
69
+ }
70
+
71
+ if (theNamespace) {
72
+ if (theNamespace[0] !== ".") {
73
+ theNamespace = "." + theNamespace;
74
+ }
75
+
76
+ // We may only have the namespace and not an eventName
77
+ eventName = (eventName || "") + theNamespace;
78
+ }
79
+ }
80
+
81
+ let parsedEvent: any[] = (eventNamespace.exec(eventName) || []);
82
+
83
+ return {
84
+ type: parsedEvent[1],
85
+ ns: ((parsedEvent[2] || "").split(".").sort()).join(".")
86
+ };
87
+ }
88
+
89
+
90
+ export interface _IRegisteredEvents {
91
+ name: string;
92
+ handler: any;
93
+ }
94
+
95
+ /**
96
+ * Get all of the registered events on the target object, this is primarily used for testing cleanup but may also be used by
97
+ * applications to remove their own events
98
+ * @param target - The EventTarget that has registered events
99
+ * @param evtName - [Optional] The name of the event to return the registered handlers and full name (with namespaces)
100
+ */
101
+ export function __getRegisteredEvents(target: any, evtName?: string): _IRegisteredEvents[] {
102
+ let theEvents: _IRegisteredEvents[] = [];
103
+ let eventCache = elmNodeData.get<IAiEvents>(target, strEvents, {}, false);
104
+ objForEachKey(eventCache, (evtType, registeredEvents) => {
105
+ arrForEach(registeredEvents, (value) => {
106
+ if (!evtName || evtName === value.evtName.type) {
107
+ theEvents.push({
108
+ name: value.evtName.type + (value.evtName.ns ? "." + value.evtName.ns : ""),
109
+ handler: value.handler
110
+ });
111
+ }
112
+ });
113
+ });
114
+
115
+ return theEvents;
116
+ }
117
+
118
+ // Exported for internal unit testing only
119
+ function _getRegisteredEvents(target: any, evtName: string, addDefault: boolean = true): IRegisteredEvent[] {
120
+ let aiEvts = elmNodeData.get<IAiEvents>(target, strEvents, {}, addDefault);
121
+ let registeredEvents = aiEvts[evtName];
122
+ if (!registeredEvents) {
123
+ registeredEvents = aiEvts[evtName] = [];
124
+ }
125
+
126
+ return registeredEvents;
127
+ }
128
+
129
+ function _doDetach(obj: any, evtName: IEventDetails, handlerRef: any, useCapture: boolean) {
130
+ if (obj && evtName && evtName.type) {
131
+ if (obj[strRemoveEventListener]) {
132
+ obj[strRemoveEventListener](evtName.type, handlerRef, useCapture);
133
+ } else if (obj[strDetachEvent]) {
134
+ obj[strDetachEvent](strOnPrefix + evtName.type, handlerRef);
135
+ }
136
+ }
137
+ }
138
+
139
+ function _doAttach(obj: any, evtName: IEventDetails, handlerRef: any, useCapture: boolean): boolean {
140
+ let result = false;
141
+
142
+ if (obj && evtName && evtName.type && handlerRef) {
143
+ if (obj[strAddEventHelper]) {
144
+ // all browsers except IE before version 9
145
+ obj[strAddEventHelper](evtName.type, handlerRef, useCapture);
146
+ result = true;
147
+ } else if (obj[strAttachEvent]) {
148
+ // IE before version 9
149
+ obj[strAttachEvent](strOnPrefix + evtName.type, handlerRef);
150
+ result = true;
151
+ }
152
+ }
153
+
154
+ return result;
155
+ }
156
+
157
+ function _doUnregister(target: any, events: IRegisteredEvent[], evtName: IEventDetails, unRegFn: (regEvent: IRegisteredEvent) => boolean) {
158
+ let idx = events.length;
159
+ while(idx--) {
160
+ let theEvent: IRegisteredEvent = events[idx];
161
+ if (theEvent) {
162
+ if (!evtName.ns || evtName.ns === theEvent.evtName.ns) {
163
+ if (!unRegFn || unRegFn(theEvent)) {
164
+ _doDetach(target, theEvent.evtName, theEvent.handler, theEvent.capture);
165
+ // Remove the registered event
166
+ events.splice(idx, 1);
167
+ }
168
+ }
169
+ }
170
+ }
171
+ }
172
+
173
+ function _unregisterEvents(target: any, evtName: IEventDetails, unRegFn: (regEvent: IRegisteredEvent) => boolean) {
174
+ if (evtName.type) {
175
+ _doUnregister(target, _getRegisteredEvents(target, evtName.type), evtName, unRegFn);
176
+ } else {
177
+ let eventCache = elmNodeData.get<IAiEvents>(target, strEvents, {});
178
+ objForEachKey(eventCache, (evtType, events) => {
179
+ _doUnregister(target, events, evtName, unRegFn);
180
+ });
181
+
182
+ // Cleanup
183
+ if (objKeys(eventCache).length === 0) {
184
+ elmNodeData.kill(target, strEvents);
185
+ }
186
+ }
187
+ }
188
+
189
+ export function mergeEvtNamespace(theNamespace: string, namespaces: string | string[]): string | string[] {
190
+ let newNamespaces: string | string[];
191
+
192
+ if (namespaces) {
193
+ if (isArray(namespaces)) {
194
+ newNamespaces = [theNamespace].concat(namespaces);
195
+ } else {
196
+ newNamespaces = [ theNamespace, namespaces ];
197
+ }
198
+ } else {
199
+ newNamespaces = theNamespace;
200
+ }
201
+
202
+ return newNamespaces;
203
+ }
204
+
205
+ /**
206
+ * Binds the specified function to an event, so that the function gets called whenever the event fires on the object
207
+ * @param obj Object to add the event too.
208
+ * @param eventName String that specifies any of the standard DHTML Events without "on" prefix, if may also include an optional (dot "." prefixed)
209
+ * namespaces "click" "click.mynamespace" in addition to specific namespaces.
210
+ * @param handlerRef Pointer that specifies the function to call when event fires
211
+ * @param evtNamespace - [Optional] Additional namespace(s) to append to the event listeners so they can be uniquely identified and removed based on this namespace,
212
+ * if the eventName also includes a namespace the namespace(s) are merged into a single namespace
213
+ * @param useCapture [Optional] Defaults to false
214
+ * @returns True if the function was bound successfully to the event, otherwise false
215
+ */
216
+ export function eventOn<T>(target: T, eventName: string, handlerRef: any, evtNamespace?: string | string[], useCapture: boolean = false) {
217
+ let result = false;
218
+
219
+ if (target) {
220
+ try {
221
+ let evtName = _getEvtNamespace(eventName, evtNamespace);
222
+ result = _doAttach(target, evtName, handlerRef, useCapture);
223
+
224
+ if (result && elmNodeData.accept(target)) {
225
+ let registeredEvent: IRegisteredEvent = {
226
+ guid: _guid++,
227
+ evtName: evtName,
228
+ handler: handlerRef,
229
+ capture: useCapture
230
+ };
231
+
232
+ _getRegisteredEvents(target, evtName.type).push(registeredEvent);
233
+ }
234
+ } catch (e) {
235
+ // Just Ignore any error so that we don't break any execution path
236
+ }
237
+ }
238
+
239
+ return result;
240
+ }
241
+
242
+ /**
243
+ * Removes an event handler for the specified event
244
+ * @param Object to remove the event from
245
+ * @param eventName {string} - The name of the event, with optional namespaces or just the namespaces,
246
+ * such as "click", "click.mynamespace" or ".mynamespace"
247
+ * @param handlerRef {any} - The callback function that needs to be removed from the given event, when using a
248
+ * namespace (with or without a qualifying event) this may be null to remove all previously attached event handlers
249
+ * otherwise this will only remove events with this specific handler.
250
+ * @param evtNamespace - [Optional] Additional namespace(s) to append to the event listeners so they can be uniquely identified and removed based on this namespace,
251
+ * if the eventName also includes a namespace the namespace(s) are merged into a single namespace
252
+ * @param useCapture [Optional] Defaults to false
253
+ */
254
+ export function eventOff<T>(target: T, eventName: string, handlerRef: any, evtNamespace?: string | string[], useCapture: boolean = false) {
255
+ if (target) {
256
+ try {
257
+ let evtName = _getEvtNamespace(eventName, evtNamespace);
258
+ let found = false;
259
+ _unregisterEvents(target, evtName, (regEvent) => {
260
+ if ((evtName.ns && !handlerRef) || regEvent.handler === handlerRef) {
261
+ found = true;
262
+ return true;
263
+ }
264
+
265
+ return false;
266
+ });
267
+
268
+ if (!found) {
269
+ // fallback to try and remove as requested
270
+ _doDetach(target, evtName, handlerRef, useCapture);
271
+ }
272
+ } catch (e) {
273
+ // Just Ignore any error so that we don't break any execution path
274
+ }
275
+ }
276
+ }
277
+
278
+
279
+ /**
280
+ * Binds the specified function to an event, so that the function gets called whenever the event fires on the object
281
+ * @param obj Object to add the event too.
282
+ * @param eventNameWithoutOn String that specifies any of the standard DHTML Events without "on" prefix and optional (dot "." prefixed) namespaces "click" "click.mynamespace".
283
+ * @param handlerRef Pointer that specifies the function to call when event fires
284
+ * @param useCapture [Optional] Defaults to false
285
+ * @returns True if the function was bound successfully to the event, otherwise false
286
+ */
287
+ export function attachEvent(obj: any, eventNameWithoutOn: string, handlerRef: any, useCapture: boolean = false) {
288
+ return eventOn(obj, eventNameWithoutOn, handlerRef, null, useCapture);
289
+ }
290
+
291
+ /**
292
+ * Removes an event handler for the specified event
293
+ * @param Object to remove the event from
294
+ * @param eventNameWithoutOn {string} - The name of the event, with optional namespaces or just the namespaces,
295
+ * such as "click", "click.mynamespace" or ".mynamespace"
296
+ * @param handlerRef {any} - The callback function that needs to be removed from the given event, when using a
297
+ * namespace (with or without a qualifying event) this may be null to remove all previously attached event handlers
298
+ * otherwise this will only remove events with this specific handler.
299
+ * @param useCapture [Optional] Defaults to false
300
+ */
301
+ export function detachEvent(obj: any, eventNameWithoutOn: string, handlerRef: any, useCapture: boolean = false) {
302
+ eventOff(obj, eventNameWithoutOn, handlerRef, null, useCapture);
303
+ }
304
+
305
+ /**
306
+ * Trys to add an event handler for the specified event to the window, body and document
307
+ * @param eventName {string} - The name of the event
308
+ * @param callback {any} - The callback function that needs to be executed for the given event
309
+ * @param evtNamespace - [Optional] Namespace(s) to append to the event listeners so they can be uniquely identified and removed based on this namespace.
310
+ * @return {boolean} - true if the handler was successfully added
311
+ */
312
+ export function addEventHandler(eventName: string, callback: any, evtNamespace?: string | string[]): boolean {
313
+ let result = false;
314
+ let w = getWindow();
315
+ if (w) {
316
+ result = eventOn(w, eventName, callback, evtNamespace);
317
+ result = eventOn(w["body"], eventName, callback, evtNamespace) || result;
318
+ }
319
+
320
+ let doc = getDocument();
321
+ if (doc) {
322
+ result = eventOn(doc, eventName, callback, evtNamespace) || result;
323
+ }
324
+
325
+ return result;
326
+ }
327
+
328
+ /**
329
+ * Trys to remove event handler(s) for the specified event/namespace to the window, body and document
330
+ * @param eventName {string} - The name of the event, with optional namespaces or just the namespaces,
331
+ * such as "click", "click.mynamespace" or ".mynamespace"
332
+ * @param callback {any} - - The callback function that needs to be removed from the given event, when using a
333
+ * namespace (with or without a qualifying event) this may be null to remove all previously attached event handlers
334
+ * otherwise this will only remove events with this specific handler.
335
+ * @param evtNamespace - [Optional] Namespace(s) to append to the event listeners so they can be uniquely identified and removed based on this namespace.
336
+ */
337
+ export function removeEventHandler(eventName: string, callback: any, evtNamespace?: string | string[]) {
338
+ let w = getWindow();
339
+ if (w) {
340
+ eventOff(w, eventName, callback, evtNamespace);
341
+ eventOff(w["body"], eventName, callback, evtNamespace);
342
+ }
343
+
344
+ let doc = getDocument();
345
+ if (doc) {
346
+ eventOff(doc, eventName, callback, evtNamespace);
347
+ }
348
+ }
349
+
350
+ /**
351
+ * Bind the listener to the array of events
352
+ * @param events An string array of event names to bind the listener to
353
+ * @param listener The event callback to call when the event is triggered
354
+ * @param excludeEvents - [Optional] An array of events that should not be hooked (if possible), unless no other events can be.
355
+ * @param evtNamespace - [Optional] Namespace(s) to append to the event listeners so they can be uniquely identified and removed based on this namespace.
356
+ * @returns true - when at least one of the events was registered otherwise false
357
+ */
358
+ function _addEventListeners(events: string[], listener: any, excludeEvents: string[], evtNamespace: string | string[]): boolean {
359
+ let added = false;
360
+
361
+ if (listener && events && events.length > 0) {
362
+ arrForEach(events, (name) => {
363
+ if (name) {
364
+ if (!excludeEvents || arrIndexOf(excludeEvents, name) === -1) {
365
+ added = addEventHandler(name, listener, evtNamespace) || added;
366
+ }
367
+ }
368
+ });
369
+ }
370
+
371
+ return added;
372
+ }
373
+
374
+ /**
375
+ * Bind the listener to the array of events
376
+ * @param events An string array of event names to bind the listener to
377
+ * @param listener The event callback to call when the event is triggered
378
+ * @param excludeEvents - [Optional] An array of events that should not be hooked (if possible), unless no other events can be.
379
+ * @param evtNamespace - [Optional] Namespace(s) to append to the event listeners so they can be uniquely identified and removed based on this namespace.
380
+ * @returns true - when at least one of the events was registered otherwise false
381
+ */
382
+ // export function addEventListeners(events: string[], listener: any, excludeEvents?: string[], evtNamespace?: string): boolean {
383
+ export function addEventListeners(events: string[], listener: any, excludeEvents?: string[], evtNamespace?: string | string[]): boolean {
384
+ let added = false;
385
+
386
+ if (listener && events && isArray(events)) {
387
+ added = _addEventListeners(events, listener, excludeEvents, evtNamespace);
388
+
389
+ if (!added && excludeEvents && excludeEvents.length > 0) {
390
+ // Failed to add any listeners and we excluded some, so just attempt to add the excluded events
391
+ added = _addEventListeners(events, listener, null, evtNamespace);
392
+ }
393
+ }
394
+
395
+ return added;
396
+ }
397
+
398
+ /**
399
+ * Remove the listener from the array of events
400
+ * @param events An string array of event names to bind the listener to
401
+ * @param listener The event callback to call when the event is triggered
402
+ * @param evtNamespace - [Optional] Namespace(s) to append to the event listeners so they can be uniquely identified and removed based on this namespace.
403
+ */
404
+ export function removeEventListeners(events: string[], listener: any, evtNamespace?: string | string[]) {
405
+ if (events && isArray(events)) {
406
+ arrForEach(events, (name) => {
407
+ if (name) {
408
+ removeEventHandler(name, listener, evtNamespace);
409
+ }
410
+ });
411
+ }
412
+ }
413
+
414
+ /**
415
+ * Listen to the 'beforeunload', 'unload' and 'pagehide' events which indicates a page unload is occurring,
416
+ * this does NOT listen to the 'visibilitychange' event as while it does indicate that the page is being hidden
417
+ * it does not *necessarily* mean that the page is being completely unloaded, it can mean that the user is
418
+ * just navigating to a different Tab and may come back (without unloading the page). As such you may also
419
+ * need to listen to the 'addPageHideEventListener' and 'addPageShowEventListener' events.
420
+ * @param listener - The event callback to call when a page unload event is triggered
421
+ * @param excludeEvents - [Optional] An array of events that should not be hooked, unless no other events can be.
422
+ * @param evtNamespace - [Optional] Namespace(s) to append to the event listeners so they can be uniquely identified and removed based on this namespace.
423
+ * @returns true - when at least one of the events was registered otherwise false
424
+ */
425
+ //export function addPageUnloadEventListener(listener: any, excludeEvents?: string[], evtNamespace?: string): boolean {
426
+ export function addPageUnloadEventListener(listener: any, excludeEvents: string[], evtNamespace?: string | string[]): boolean {
427
+ // Hook the unload event for the document, window and body to ensure that the client events are flushed to the server
428
+ // As just hooking the window does not always fire (on chrome) for page navigation's.
429
+ return addEventListeners([strBeforeUnload, strUnload, strPageHide], listener, excludeEvents, evtNamespace);
430
+ }
431
+
432
+ /**
433
+ * Remove any matching 'beforeunload', 'unload' and 'pagehide' events that may have been added via addEventListener,
434
+ * addEventListeners, addPageUnloadEventListener or addPageHideEventListener.
435
+ * @param listener - The specific event callback to to be removed
436
+ * @param evtNamespace - [Optional] Namespace(s) uniquely identified and removed based on this namespace.
437
+ * @returns true - when at least one of the events was registered otherwise false
438
+ */
439
+ export function removePageUnloadEventListener(listener: any, evtNamespace?: string | string[]) {
440
+ removeEventListeners([strBeforeUnload, strUnload, strPageHide], listener, evtNamespace);
441
+ }
442
+
443
+ /**
444
+ * Listen to the pagehide and visibility changing to 'hidden' events, because the 'visibilitychange' uses
445
+ * an internal proxy to detect the visibility state you SHOULD use a unique namespace when if you plan to call
446
+ * removePageShowEventListener as the remove ignores the listener argument for the 'visibilitychange' event.
447
+ * @param listener - The event callback to call when a page hide event is triggered
448
+ * @param excludeEvents - [Optional] An array of events that should not be hooked (if possible), unless no other events can be.
449
+ * @param evtNamespace - [Optional] A Namespace to append to the event listeners so they can be uniquely identified and removed
450
+ * based on this namespace. This call also adds an additional unique "pageshow" namespace to the events
451
+ * so that only the matching "removePageHideEventListener" can remove these events.
452
+ * Suggestion: pass as true if you are also calling addPageUnloadEventListener as that also hooks pagehide
453
+ * @returns true - when at least one of the events was registered otherwise false
454
+ */
455
+ //export function addPageHideEventListener(listener: any, excludeEvents?: string[], evtNamespace?: string): boolean {
456
+ export function addPageHideEventListener(listener: any, excludeEvents: string[], evtNamespace?: string | string[]): boolean {
457
+
458
+ function _handlePageVisibility(evt: any) {
459
+ let doc = getDocument();
460
+ if (listener && doc && doc.visibilityState === "hidden") {
461
+ listener(evt);
462
+ }
463
+ }
464
+
465
+ // add the unique page show namespace to any provided namespace so we can only remove the ones added by "pagehide"
466
+ let newNamespaces = mergeEvtNamespace(strPageHideNamespace, evtNamespace);
467
+ let pageUnloadAdded = _addEventListeners([strPageHide], listener, excludeEvents, newNamespaces);
468
+
469
+ if (!excludeEvents || arrIndexOf(excludeEvents, strVisibilityChangeEvt) === -1) {
470
+ pageUnloadAdded = _addEventListeners([strVisibilityChangeEvt], _handlePageVisibility, excludeEvents, newNamespaces) || pageUnloadAdded;
471
+ }
472
+
473
+ if (!pageUnloadAdded && excludeEvents) {
474
+ // Failed to add any listeners and we where requested to exclude some, so just call again without excluding anything
475
+ pageUnloadAdded = addPageHideEventListener(listener, null, evtNamespace);
476
+ }
477
+
478
+ return pageUnloadAdded;
479
+ }
480
+
481
+ /**
482
+ * Removes the pageHide event listeners added by addPageHideEventListener, because the 'visibilitychange' uses
483
+ * an internal proxy to detect the visibility state you SHOULD use a unique namespace when calling addPageHideEventListener
484
+ * as the remove ignores the listener argument for the 'visibilitychange' event.
485
+ * @param listener - The specific listener to remove for the 'pageshow' event only (ignored for 'visibilitychange')
486
+ * @param evtNamespace - The unique namespace used when calling addPageShowEventListener
487
+ */
488
+
489
+ export function removePageHideEventListener(listener: any, evtNamespace?: string | string[]) {
490
+ // add the unique page show namespace to any provided namespace so we only remove the ones added by "pagehide"
491
+ let newNamespaces = mergeEvtNamespace(strPageHideNamespace, evtNamespace);
492
+ removeEventListeners([strPageHide], listener, newNamespaces);
493
+ removeEventListeners([strVisibilityChangeEvt], null, newNamespaces);
494
+ }
495
+
496
+ /**
497
+ * Listen to the pageshow and visibility changing to 'visible' events, because the 'visibilitychange' uses
498
+ * an internal proxy to detect the visibility state you SHOULD use a unique namespace when if you plan to call
499
+ * removePageShowEventListener as the remove ignores the listener argument for the 'visibilitychange' event.
500
+ * @param listener - The event callback to call when a page is show event is triggered
501
+ * @param excludeEvents - [Optional] An array of events that should not be hooked (if possible), unless no other events can be.
502
+ * @param evtNamespace - [Optional/Recommended] A Namespace to append to the event listeners so they can be uniquely
503
+ * identified and removed based on this namespace. This call also adds an additional unique "pageshow" namespace to the events
504
+ * so that only the matching "removePageShowEventListener" can remove these events.
505
+ * @returns true - when at least one of the events was registered otherwise false
506
+ */
507
+ //export function addPageShowEventListener(listener: any, excludeEvents?: string[], evtNamespace?: string): boolean {
508
+ export function addPageShowEventListener(listener: any, excludeEvents: string[], evtNamespace?: string | string[]): boolean {
509
+
510
+ function _handlePageVisibility(evt: any) {
511
+ let doc = getDocument();
512
+ if (listener && doc && doc.visibilityState === "visible") {
513
+ listener(evt);
514
+ }
515
+ }
516
+
517
+ // add the unique page show namespace to any provided namespace so we can only remove the ones added by "pageshow"
518
+ let newNamespaces = mergeEvtNamespace(strPageShowNamespace, evtNamespace);
519
+ let pageShowAdded = _addEventListeners([strPageShow], listener, excludeEvents, newNamespaces);
520
+ pageShowAdded = _addEventListeners([strVisibilityChangeEvt], _handlePageVisibility, excludeEvents, newNamespaces) || pageShowAdded;
521
+
522
+ if (!pageShowAdded && excludeEvents) {
523
+ // Failed to add any listeners and we where requested to exclude some, so just call again without excluding anything
524
+ pageShowAdded = addPageShowEventListener(listener, null, evtNamespace);
525
+ }
526
+
527
+ return pageShowAdded;
528
+ }
529
+
530
+ /**
531
+ * Removes the pageShow event listeners added by addPageShowEventListener, because the 'visibilitychange' uses
532
+ * an internal proxy to detect the visibility state you SHOULD use a unique namespace when calling addPageShowEventListener
533
+ * as the remove ignores the listener argument for the 'visibilitychange' event.
534
+ * @param listener - The specific listener to remove for the 'pageshow' event only (ignored for 'visibilitychange')
535
+ * @param evtNamespace - The unique namespace used when calling addPageShowEventListener
536
+ */
537
+ export function removePageShowEventListener(listener: any, evtNamespace?: string | string[]) {
538
+ // add the unique page show namespace to any provided namespace so we only remove the ones added by "pageshow"
539
+ let newNamespaces = mergeEvtNamespace(strPageShowNamespace, evtNamespace);
540
+ removeEventListeners([strPageShow], listener, newNamespaces);
541
+ removeEventListeners([strVisibilityChangeEvt], null, newNamespaces);
542
+ }
@@ -4,15 +4,11 @@ import {
4
4
  strShimUndefined, strShimObject, strShimFunction, throwTypeError,
5
5
  ObjClass, ObjProto, ObjAssign, ObjHasOwnProperty, ObjDefineProperty, strShimPrototype
6
6
  } from "@microsoft/applicationinsights-shims";
7
+ import { strEmpty } from "./InternalConstants";
7
8
 
8
9
  // RESTRICT and AVOID circular dependencies you should not import other contained modules or export the contents of this file directly
9
10
 
10
11
  // Added to help with minfication
11
- const strOnPrefix = "on";
12
- const strAttachEvent = "attachEvent";
13
- const strAddEventHelper = "addEventListener";
14
- const strDetachEvent = "detachEvent";
15
- const strRemoveEventListener = "removeEventListener";
16
12
  const strToISOString = "toISOString";
17
13
  const cStrEndsWith = "endsWith";
18
14
  const cStrStartsWith = "startsWith";
@@ -123,54 +119,8 @@ export function isFunction(value: any): value is Function {
123
119
  return !!(value && typeof value === strShimFunction);
124
120
  }
125
121
 
126
- /**
127
- * Binds the specified function to an event, so that the function gets called whenever the event fires on the object
128
- * @param obj Object to add the event too.
129
- * @param eventNameWithoutOn String that specifies any of the standard DHTML Events without "on" prefix
130
- * @param handlerRef Pointer that specifies the function to call when event fires
131
- * @param useCapture [Optional] Defaults to false
132
- * @returns True if the function was bound successfully to the event, otherwise false
133
- */
134
- export function attachEvent(obj: any, eventNameWithoutOn: string, handlerRef: any, useCapture: boolean = false) {
135
- let result = false;
136
- if (!isNullOrUndefined(obj)) {
137
- try {
138
- if (!isNullOrUndefined(obj[strAddEventHelper])) {
139
- // all browsers except IE before version 9
140
- obj[strAddEventHelper](eventNameWithoutOn, handlerRef, useCapture);
141
- result = true;
142
- } else if (!isNullOrUndefined(obj[strAttachEvent])) {
143
- // IE before version 9
144
- obj[strAttachEvent](strOnPrefix + eventNameWithoutOn, handlerRef);
145
- result = true;
146
- }
147
- } catch (e) {
148
- // Just Ignore any error so that we don't break any execution path
149
- }
150
- }
151
-
152
- return result;
153
- }
154
-
155
- /**
156
- * Removes an event handler for the specified event
157
- * @param Object to remove the event from
158
- * @param eventNameWithoutOn {string} - The name of the event
159
- * @param handlerRef {any} - The callback function that needs to be executed for the given event
160
- * @param useCapture [Optional] Defaults to false
161
- */
162
- export function detachEvent(obj: any, eventNameWithoutOn: string, handlerRef: any, useCapture: boolean = false) {
163
- if (!isNullOrUndefined(obj)) {
164
- try {
165
- if (!isNullOrUndefined(obj[strRemoveEventListener])) {
166
- obj[strRemoveEventListener](eventNameWithoutOn, handlerRef, useCapture);
167
- } else if (!isNullOrUndefined(obj[strDetachEvent])) {
168
- obj[strDetachEvent](strOnPrefix + eventNameWithoutOn, handlerRef);
169
- }
170
- } catch (e) {
171
- // Just Ignore any error so that we don't break any execution path
172
- }
173
- }
122
+ export function isPromiseLike<T>(value: any): value is PromiseLike<T> {
123
+ return value && isFunction(value.then);
174
124
  }
175
125
 
176
126
  /**
@@ -665,6 +615,18 @@ function _doNothing<T>(value: T): T {
665
615
  return value;
666
616
  }
667
617
 
618
+ export function deepFreeze<T>(obj: T): T {
619
+ if (_objFreeze) {
620
+ objForEachKey(obj, (name, value) => {
621
+ if (isArray(value) || isObject(value)) {
622
+ _objFreeze(value);
623
+ }
624
+ });
625
+ }
626
+
627
+ return objFreeze(obj);
628
+ }
629
+
668
630
  export const objFreeze: <T>(value: T) => T = _objFreeze || _doNothing;
669
631
  export const objSeal: <T>(value: T) => T = _objSeal || _doNothing;
670
632
 
@@ -686,7 +648,7 @@ export function getExceptionName(object: any): string {
686
648
  return object.name;
687
649
  }
688
650
 
689
- return "";
651
+ return strEmpty;
690
652
  }
691
653
 
692
654
  /**
@@ -863,6 +825,25 @@ export function createClassFromInterface<T>(defaults?: T) {
863
825
  } as new () => T;
864
826
  }
865
827
 
828
+ /**
829
+ * Create an enum style object which has both the key => value and value => key mappings
830
+ * @param values - The values to populate on the new object
831
+ * @returns
832
+ */
833
+ export function createEnumStyle<T>(values: T) {
834
+ let enumClass: any = {};
835
+ objForEachKey(values, (field, value) => {
836
+ enumClass[field] = value;
837
+ // Add Reverse lookup
838
+ if (!isUndefined(enumClass[value])) {
839
+ throwError("[" + value + "] exists for " + field);
840
+ }
841
+ enumClass[value] = field;
842
+ });
843
+
844
+ return objFreeze(enumClass as T);
845
+ }
846
+
866
847
  /**
867
848
  * A helper function to assist with JIT performance for objects that have properties added / removed dynamically
868
849
  * this is primarily for chromium based browsers and has limited effects on Firefox and none of IE. Only call this