@openfin/core 30.73.2 → 30.73.4
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/package.json +1 -1
- package/src/api/interop/fdc3/PrivateChannelClient.js +4 -6
- package/src/api/interop/fdc3/fdc3-1.2.d.ts +0 -1
- package/src/api/interop/fdc3/fdc3-1.2.js +1 -27
- package/src/api/interop/fdc3/fdc3-2.0.d.ts +0 -2
- package/src/api/interop/fdc3/fdc3-2.0.js +1 -63
- package/src/api/interop/fdc3/utils.d.ts +4 -0
- package/src/api/interop/fdc3/utils.js +106 -2
- package/src/api/view/Instance.d.ts +31 -1
- package/src/api/view/Instance.js +31 -1
package/package.json
CHANGED
|
@@ -9,7 +9,7 @@ class PrivateChannelClient {
|
|
|
9
9
|
this.listeners = new Map();
|
|
10
10
|
}
|
|
11
11
|
async broadcast(context) {
|
|
12
|
-
this.client.dispatch('broadcast', { context });
|
|
12
|
+
return this.client.dispatch('broadcast', { context });
|
|
13
13
|
}
|
|
14
14
|
async getCurrentContext(contextType) {
|
|
15
15
|
return this.client.dispatch('getCurrentContext', { contextType });
|
|
@@ -70,12 +70,10 @@ class PrivateChannelClient {
|
|
|
70
70
|
return listener;
|
|
71
71
|
}
|
|
72
72
|
async disconnect() {
|
|
73
|
-
const promises = [];
|
|
74
73
|
const listenerUnsubscribers = Array.from(this.listeners.values());
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
}
|
|
74
|
+
const promises = listenerUnsubscribers.map(async (listenerUnsubscriber) => {
|
|
75
|
+
await listenerUnsubscriber.unsubscribe();
|
|
76
|
+
});
|
|
79
77
|
await Promise.all(promises);
|
|
80
78
|
await this.client.dispatch('clientDisconnecting');
|
|
81
79
|
await this.client.disconnect();
|
|
@@ -329,7 +329,7 @@ class Fdc3Module extends base_1.Base {
|
|
|
329
329
|
// we do not want to expose this error, just continue if this analytics-only call fails
|
|
330
330
|
});
|
|
331
331
|
const sessionContextGroup = await this.fin.me.interop.joinSessionContextGroup(channelId);
|
|
332
|
-
return
|
|
332
|
+
return utils_1.buildAppChannelObject(sessionContextGroup);
|
|
333
333
|
}
|
|
334
334
|
/**
|
|
335
335
|
* Returns metadata relating to the FDC3 object and its provider, including the supported version of the FDC3 specification and the name of the provider of the implementation.
|
|
@@ -397,31 +397,5 @@ class Fdc3Module extends base_1.Base {
|
|
|
397
397
|
}
|
|
398
398
|
};
|
|
399
399
|
}
|
|
400
|
-
// eslint-disable-next-line class-methods-use-this
|
|
401
|
-
buildAppChannelObject(sessionContextGroup) {
|
|
402
|
-
return {
|
|
403
|
-
id: sessionContextGroup.id,
|
|
404
|
-
type: 'app',
|
|
405
|
-
broadcast: sessionContextGroup.setContext,
|
|
406
|
-
getCurrentContext: async (contextType) => {
|
|
407
|
-
const context = await sessionContextGroup.getCurrentContext(contextType);
|
|
408
|
-
return context === undefined ? null : context;
|
|
409
|
-
},
|
|
410
|
-
addContextListener: (contextType, handler) => {
|
|
411
|
-
let listener;
|
|
412
|
-
if (typeof contextType === 'function') {
|
|
413
|
-
console.warn('addContextListener(handler) has been deprecated. Please use addContextListener(null, handler)');
|
|
414
|
-
listener = sessionContextGroup.addContextHandler(contextType);
|
|
415
|
-
}
|
|
416
|
-
else {
|
|
417
|
-
listener = sessionContextGroup.addContextHandler(handler, contextType === null ? undefined : contextType);
|
|
418
|
-
}
|
|
419
|
-
return {
|
|
420
|
-
...listener,
|
|
421
|
-
unsubscribe: () => listener.then((l) => l.unsubscribe())
|
|
422
|
-
};
|
|
423
|
-
}
|
|
424
|
-
};
|
|
425
|
-
}
|
|
426
400
|
}
|
|
427
401
|
exports.default = Fdc3Module;
|
|
@@ -249,8 +249,6 @@ export default class Fdc3Module2 extends Base implements FDC3v2.DesktopAgent {
|
|
|
249
249
|
* @tutorial fdc3v2.createPrivateChannel
|
|
250
250
|
*/
|
|
251
251
|
createPrivateChannel(): Promise<FDC3v2.PrivateChannel>;
|
|
252
|
-
connectPrivateChannel(channelId: string): Promise<FDC3v2.PrivateChannel>;
|
|
253
|
-
private buildPrivateChannelObject;
|
|
254
252
|
/**
|
|
255
253
|
* Retrieves a list of the User Channels available for the app to join.
|
|
256
254
|
* @returns { Promise<Channel[]>}
|
|
@@ -393,69 +393,7 @@ class Fdc3Module2 extends base_1.Base {
|
|
|
393
393
|
const newPrivateChannelProvider = new PrivateChannelProvider_1.PrivateChannelProvider(channelProvider, channelId);
|
|
394
394
|
const channelClient = await this.fin.InterApplicationBus.Channel.connect(channelId);
|
|
395
395
|
const newPrivateChannelClient = new PrivateChannelClient_1.PrivateChannelClient(channelClient, channelId);
|
|
396
|
-
return
|
|
397
|
-
}
|
|
398
|
-
// TODO: need to remove this method and not expose it. Added temporarily for the purposes of testing.
|
|
399
|
-
// eslint-disable-next-line class-methods-use-this
|
|
400
|
-
async connectPrivateChannel(channelId) {
|
|
401
|
-
try {
|
|
402
|
-
const channelClient = await fin.InterApplicationBus.Channel.connect(channelId);
|
|
403
|
-
const privateChannelClient = new PrivateChannelClient_1.PrivateChannelClient(channelClient, channelId);
|
|
404
|
-
return this.buildPrivateChannelObject(privateChannelClient);
|
|
405
|
-
}
|
|
406
|
-
catch (error) {
|
|
407
|
-
throw new Error(`Private Channel with id: ${channelId} doesn't exist`);
|
|
408
|
-
}
|
|
409
|
-
}
|
|
410
|
-
// eslint-disable-next-line class-methods-use-this
|
|
411
|
-
buildPrivateChannelObject(privateChannelClient) {
|
|
412
|
-
let clientDisconnected = false;
|
|
413
|
-
const checkIfClientDisconnected = () => {
|
|
414
|
-
if (clientDisconnected) {
|
|
415
|
-
throw new Error('Private Channel Client has been disconnected from the Private Channel');
|
|
416
|
-
}
|
|
417
|
-
};
|
|
418
|
-
return {
|
|
419
|
-
id: privateChannelClient.id,
|
|
420
|
-
type: 'private',
|
|
421
|
-
broadcast: async (context) => {
|
|
422
|
-
checkIfClientDisconnected();
|
|
423
|
-
return privateChannelClient.broadcast(context);
|
|
424
|
-
},
|
|
425
|
-
getCurrentContext: async (contextType) => {
|
|
426
|
-
checkIfClientDisconnected();
|
|
427
|
-
return privateChannelClient.getCurrentContext(contextType);
|
|
428
|
-
},
|
|
429
|
-
addContextListener: async (contextType, handler) => {
|
|
430
|
-
checkIfClientDisconnected();
|
|
431
|
-
let handlerInUse = handler;
|
|
432
|
-
let contextTypeInUse = contextType;
|
|
433
|
-
if (typeof contextType === 'function') {
|
|
434
|
-
console.warn('addContextListener(handler) has been deprecated. Please use addContextListener(null, handler)');
|
|
435
|
-
handlerInUse = contextType;
|
|
436
|
-
contextTypeInUse = null;
|
|
437
|
-
}
|
|
438
|
-
const listener = privateChannelClient.addContextListener(contextTypeInUse, handlerInUse);
|
|
439
|
-
return listener;
|
|
440
|
-
},
|
|
441
|
-
onAddContextListener: (handler) => {
|
|
442
|
-
checkIfClientDisconnected();
|
|
443
|
-
return privateChannelClient.onAddContextListener(handler);
|
|
444
|
-
},
|
|
445
|
-
disconnect: async () => {
|
|
446
|
-
checkIfClientDisconnected();
|
|
447
|
-
clientDisconnected = true;
|
|
448
|
-
return privateChannelClient.disconnect();
|
|
449
|
-
},
|
|
450
|
-
onDisconnect: (handler) => {
|
|
451
|
-
checkIfClientDisconnected();
|
|
452
|
-
return privateChannelClient.onDisconnect(handler);
|
|
453
|
-
},
|
|
454
|
-
onUnsubscribe: (handler) => {
|
|
455
|
-
checkIfClientDisconnected();
|
|
456
|
-
return privateChannelClient.onUnsubscribe(handler);
|
|
457
|
-
}
|
|
458
|
-
};
|
|
396
|
+
return utils_2.buildPrivateChannelObject(newPrivateChannelClient);
|
|
459
397
|
}
|
|
460
398
|
/**
|
|
461
399
|
* Retrieves a list of the User Channels available for the app to join.
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { PrivateChannelClient } from './PrivateChannelClient';
|
|
1
2
|
export declare class UnsupportedChannelApiError extends Error {
|
|
2
3
|
constructor(apiName: string);
|
|
3
4
|
}
|
|
@@ -11,4 +12,7 @@ export declare enum ResultError {
|
|
|
11
12
|
*/
|
|
12
13
|
IntentHandlerRejected = "IntentHandlerRejected"
|
|
13
14
|
}
|
|
15
|
+
export declare const buildPrivateChannelObject: (privateChannelClient: PrivateChannelClient) => FDC3v2.PrivateChannel;
|
|
16
|
+
export declare const buildAppChannelObject: (sessionContextGroup: OpenFin.SessionContextGroup) => FDC3.Channel;
|
|
17
|
+
export declare const connectPrivateChannel: (channelId: string) => Promise<FDC3v2.PrivateChannel>;
|
|
14
18
|
export declare const getIntentResolution: (interopModule: OpenFin.InteropClient, context: OpenFin.Context, app?: FDC3v2.AppIdentifier | FDC3.TargetApp, intent?: string) => Promise<FDC3v2.IntentResolution>;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getIntentResolution = exports.ResultError = exports.UnsupportedChannelApiError = void 0;
|
|
3
|
+
exports.getIntentResolution = exports.connectPrivateChannel = exports.buildAppChannelObject = exports.buildPrivateChannelObject = exports.ResultError = exports.UnsupportedChannelApiError = void 0;
|
|
4
4
|
const utils_1 = require("../utils");
|
|
5
|
+
const PrivateChannelClient_1 = require("./PrivateChannelClient");
|
|
5
6
|
class UnsupportedChannelApiError extends Error {
|
|
6
7
|
constructor(apiName) {
|
|
7
8
|
super(apiName);
|
|
@@ -20,6 +21,90 @@ var ResultError;
|
|
|
20
21
|
*/
|
|
21
22
|
ResultError["IntentHandlerRejected"] = "IntentHandlerRejected";
|
|
22
23
|
})(ResultError = exports.ResultError || (exports.ResultError = {}));
|
|
24
|
+
exports.buildPrivateChannelObject = (privateChannelClient) => {
|
|
25
|
+
let clientDisconnected = false;
|
|
26
|
+
const checkIfClientDisconnected = () => {
|
|
27
|
+
if (clientDisconnected) {
|
|
28
|
+
throw new Error('Private Channel Client has been disconnected from the Private Channel');
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
return {
|
|
32
|
+
id: privateChannelClient.id,
|
|
33
|
+
type: 'private',
|
|
34
|
+
broadcast: async (context) => {
|
|
35
|
+
checkIfClientDisconnected();
|
|
36
|
+
return privateChannelClient.broadcast(context);
|
|
37
|
+
},
|
|
38
|
+
getCurrentContext: async (contextType) => {
|
|
39
|
+
checkIfClientDisconnected();
|
|
40
|
+
return privateChannelClient.getCurrentContext(contextType);
|
|
41
|
+
},
|
|
42
|
+
addContextListener: async (contextType, handler) => {
|
|
43
|
+
checkIfClientDisconnected();
|
|
44
|
+
let handlerInUse = handler;
|
|
45
|
+
let contextTypeInUse = contextType;
|
|
46
|
+
if (typeof contextType === 'function') {
|
|
47
|
+
console.warn('addContextListener(handler) has been deprecated. Please use addContextListener(null, handler)');
|
|
48
|
+
handlerInUse = contextType;
|
|
49
|
+
contextTypeInUse = null;
|
|
50
|
+
}
|
|
51
|
+
const listener = privateChannelClient.addContextListener(contextTypeInUse, handlerInUse);
|
|
52
|
+
return listener;
|
|
53
|
+
},
|
|
54
|
+
onAddContextListener: (handler) => {
|
|
55
|
+
checkIfClientDisconnected();
|
|
56
|
+
return privateChannelClient.onAddContextListener(handler);
|
|
57
|
+
},
|
|
58
|
+
disconnect: async () => {
|
|
59
|
+
checkIfClientDisconnected();
|
|
60
|
+
clientDisconnected = true;
|
|
61
|
+
return privateChannelClient.disconnect();
|
|
62
|
+
},
|
|
63
|
+
onDisconnect: (handler) => {
|
|
64
|
+
checkIfClientDisconnected();
|
|
65
|
+
return privateChannelClient.onDisconnect(handler);
|
|
66
|
+
},
|
|
67
|
+
onUnsubscribe: (handler) => {
|
|
68
|
+
checkIfClientDisconnected();
|
|
69
|
+
return privateChannelClient.onUnsubscribe(handler);
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
};
|
|
73
|
+
exports.buildAppChannelObject = (sessionContextGroup) => {
|
|
74
|
+
return {
|
|
75
|
+
id: sessionContextGroup.id,
|
|
76
|
+
type: 'app',
|
|
77
|
+
broadcast: sessionContextGroup.setContext,
|
|
78
|
+
getCurrentContext: async (contextType) => {
|
|
79
|
+
const context = await sessionContextGroup.getCurrentContext(contextType);
|
|
80
|
+
return context === undefined ? null : context;
|
|
81
|
+
},
|
|
82
|
+
addContextListener: (contextType, handler) => {
|
|
83
|
+
let listener;
|
|
84
|
+
if (typeof contextType === 'function') {
|
|
85
|
+
console.warn('addContextListener(handler) has been deprecated. Please use addContextListener(null, handler)');
|
|
86
|
+
listener = sessionContextGroup.addContextHandler(contextType);
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
listener = sessionContextGroup.addContextHandler(handler, contextType === null ? undefined : contextType);
|
|
90
|
+
}
|
|
91
|
+
return {
|
|
92
|
+
...listener,
|
|
93
|
+
unsubscribe: () => listener.then((l) => l.unsubscribe())
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
};
|
|
98
|
+
exports.connectPrivateChannel = async (channelId) => {
|
|
99
|
+
try {
|
|
100
|
+
const channelClient = await fin.InterApplicationBus.Channel.connect(channelId);
|
|
101
|
+
const privateChannelClient = new PrivateChannelClient_1.PrivateChannelClient(channelClient, channelId);
|
|
102
|
+
return exports.buildPrivateChannelObject(privateChannelClient);
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
throw new Error(`Private Channel with id: ${channelId} doesn't exist`);
|
|
106
|
+
}
|
|
107
|
+
};
|
|
23
108
|
exports.getIntentResolution = async (interopModule, context, app, intent) => {
|
|
24
109
|
// Generate an ID to make a session context group with. We will pass that ID to the Broker.
|
|
25
110
|
// The broker will then setContext on that session context group later with our Intent Result,
|
|
@@ -35,13 +120,32 @@ exports.getIntentResolution = async (interopModule, context, app, intent) => {
|
|
|
35
120
|
const intentObj = intent ? { name: intent, context, metadata } : { ...context, metadata };
|
|
36
121
|
// Set up the getResult call.
|
|
37
122
|
const getResult = async () => {
|
|
38
|
-
|
|
123
|
+
let intentResult = await getResultPromise;
|
|
39
124
|
if (!intentResult) {
|
|
40
125
|
throw new Error(ResultError.NoResultReturned);
|
|
41
126
|
}
|
|
42
127
|
if (intentResult instanceof Error) {
|
|
43
128
|
throw new Error(ResultError.IntentHandlerRejected);
|
|
44
129
|
}
|
|
130
|
+
if (typeof intentResult === 'object') {
|
|
131
|
+
const { id, type } = intentResult;
|
|
132
|
+
if (type && id && typeof id === 'string') {
|
|
133
|
+
switch (type) {
|
|
134
|
+
case 'private': {
|
|
135
|
+
intentResult = await exports.connectPrivateChannel(id);
|
|
136
|
+
break;
|
|
137
|
+
}
|
|
138
|
+
case 'app': {
|
|
139
|
+
const sessionContextGroup = await interopModule.joinSessionContextGroup(id);
|
|
140
|
+
intentResult = exports.buildAppChannelObject(sessionContextGroup);
|
|
141
|
+
break;
|
|
142
|
+
}
|
|
143
|
+
default: {
|
|
144
|
+
break;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
45
149
|
return intentResult;
|
|
46
150
|
};
|
|
47
151
|
// Finally fire the intent.
|
|
@@ -16,6 +16,36 @@ import UpdatableViewOptions = OpenFin.UpdatableViewOptions;
|
|
|
16
16
|
*
|
|
17
17
|
* @property {boolean} [experimental.childWindows] Configure if the runtime should enable child windows for views.
|
|
18
18
|
*
|
|
19
|
+
* @property {object} [accelerator]
|
|
20
|
+
* Enable keyboard shortcuts for devtools, zoom, reload, and reload ignoring cache.
|
|
21
|
+
*
|
|
22
|
+
* @property {boolean} [accelerator.devtools=false]
|
|
23
|
+
* If `true`, enables the devtools keyboard shortcut:<br>
|
|
24
|
+
* `Ctrl` + `Shift` + `I` _(Toggles Devtools)_
|
|
25
|
+
*
|
|
26
|
+
* @property {boolean} [accelerator.reload=false]
|
|
27
|
+
* If `true`, enables the reload keyboard shortcuts:<br>
|
|
28
|
+
* `Ctrl` + `R` _(Windows)_<br>
|
|
29
|
+
* `F5` _(Windows)_<br>
|
|
30
|
+
* `Command` + `R` _(Mac)_
|
|
31
|
+
*
|
|
32
|
+
* @property {boolean} [accelerator.reloadIgnoringCache=false]
|
|
33
|
+
* If `true`, enables the reload-from-source keyboard shortcuts:<br>
|
|
34
|
+
* `Ctrl` + `Shift` + `R` _(Windows)_<br>
|
|
35
|
+
* `Shift` + `F5` _(Windows)_<br>
|
|
36
|
+
* `Command` + `Shift` + `R` _(Mac)_
|
|
37
|
+
*
|
|
38
|
+
* @property {boolean} [accelerator.zoom=false]
|
|
39
|
+
* If `true`, enables the zoom keyboard shortcuts:<br>
|
|
40
|
+
* `Ctrl` + `+` _(Zoom In)_<br>
|
|
41
|
+
* `Ctrl` + `Shift` + `+` _(Zoom In)_<br>
|
|
42
|
+
* `Ctrl` + `NumPad+` _(Zoom In)_<br>
|
|
43
|
+
* `Ctrl` + `-` _(Zoom Out)_<br>
|
|
44
|
+
* `Ctrl` + `Shift` + `-` _(Zoom Out)_<br>
|
|
45
|
+
* `Ctrl` + `NumPad-` _(Zoom Out)_<br>
|
|
46
|
+
* `Ctrl` + `Scroll` _(Zoom In & Out)_<br>
|
|
47
|
+
* `Ctrl` + `0` _(Restore to 100%)_
|
|
48
|
+
*
|
|
19
49
|
* @property {object} [api]
|
|
20
50
|
* Configurations for API injection.
|
|
21
51
|
*
|
|
@@ -127,7 +157,7 @@ import UpdatableViewOptions = OpenFin.UpdatableViewOptions;
|
|
|
127
157
|
* really no need to provide it.
|
|
128
158
|
*/
|
|
129
159
|
/**
|
|
130
|
-
* @classdesc
|
|
160
|
+
* @classdesc A View can be used to embed additional web content into a Window.
|
|
131
161
|
* It is like a child window, except it is positioned relative to its owning window.
|
|
132
162
|
* It has the ability to listen for <a href="tutorial-View.EventEmitter.html">View-specific events</a>.
|
|
133
163
|
*
|
package/src/api/view/Instance.js
CHANGED
|
@@ -19,6 +19,36 @@ const window_1 = require("../window");
|
|
|
19
19
|
*
|
|
20
20
|
* @property {boolean} [experimental.childWindows] Configure if the runtime should enable child windows for views.
|
|
21
21
|
*
|
|
22
|
+
* @property {object} [accelerator]
|
|
23
|
+
* Enable keyboard shortcuts for devtools, zoom, reload, and reload ignoring cache.
|
|
24
|
+
*
|
|
25
|
+
* @property {boolean} [accelerator.devtools=false]
|
|
26
|
+
* If `true`, enables the devtools keyboard shortcut:<br>
|
|
27
|
+
* `Ctrl` + `Shift` + `I` _(Toggles Devtools)_
|
|
28
|
+
*
|
|
29
|
+
* @property {boolean} [accelerator.reload=false]
|
|
30
|
+
* If `true`, enables the reload keyboard shortcuts:<br>
|
|
31
|
+
* `Ctrl` + `R` _(Windows)_<br>
|
|
32
|
+
* `F5` _(Windows)_<br>
|
|
33
|
+
* `Command` + `R` _(Mac)_
|
|
34
|
+
*
|
|
35
|
+
* @property {boolean} [accelerator.reloadIgnoringCache=false]
|
|
36
|
+
* If `true`, enables the reload-from-source keyboard shortcuts:<br>
|
|
37
|
+
* `Ctrl` + `Shift` + `R` _(Windows)_<br>
|
|
38
|
+
* `Shift` + `F5` _(Windows)_<br>
|
|
39
|
+
* `Command` + `Shift` + `R` _(Mac)_
|
|
40
|
+
*
|
|
41
|
+
* @property {boolean} [accelerator.zoom=false]
|
|
42
|
+
* If `true`, enables the zoom keyboard shortcuts:<br>
|
|
43
|
+
* `Ctrl` + `+` _(Zoom In)_<br>
|
|
44
|
+
* `Ctrl` + `Shift` + `+` _(Zoom In)_<br>
|
|
45
|
+
* `Ctrl` + `NumPad+` _(Zoom In)_<br>
|
|
46
|
+
* `Ctrl` + `-` _(Zoom Out)_<br>
|
|
47
|
+
* `Ctrl` + `Shift` + `-` _(Zoom Out)_<br>
|
|
48
|
+
* `Ctrl` + `NumPad-` _(Zoom Out)_<br>
|
|
49
|
+
* `Ctrl` + `Scroll` _(Zoom In & Out)_<br>
|
|
50
|
+
* `Ctrl` + `0` _(Restore to 100%)_
|
|
51
|
+
*
|
|
22
52
|
* @property {object} [api]
|
|
23
53
|
* Configurations for API injection.
|
|
24
54
|
*
|
|
@@ -130,7 +160,7 @@ const window_1 = require("../window");
|
|
|
130
160
|
* really no need to provide it.
|
|
131
161
|
*/
|
|
132
162
|
/**
|
|
133
|
-
* @classdesc
|
|
163
|
+
* @classdesc A View can be used to embed additional web content into a Window.
|
|
134
164
|
* It is like a child window, except it is positioned relative to its owning window.
|
|
135
165
|
* It has the ability to listen for <a href="tutorial-View.EventEmitter.html">View-specific events</a>.
|
|
136
166
|
*
|