Publish window details over SubEtha
by Bemi Faison
SubEtha Window Information (or WI) is a Subetha-Client plugin that provides a spatial model of non-framed windows. WI publishes window activity and metrics of each document using the plugin.
To observe WI in action, open this visualizer demo in several windows.
Note: Please see the Subetha project page, for important background information, plus development, implementation, and security considerations.
WI provides methods to start and stop monitoring window changes, but begins monitoring once a connection is established (by default). The plugin adds a custom array to the Subetha module itself, as Subetha.winfos
. This array contains winfo objects that describe each window, and hosts API methods to observe and control functionality.
To access information about a window, simply select an indexed winfo object from the Subetha.winfos
array.
var firstWinfo = Subetha.winfos[0];
if (firstWinfo) {
console.log('The first monitored window id is "%s"', firstWinfo.id);
} else {
console.log('WI is not monitoring any windows');
}
Note: Ensure the winfos
array has members before accessing it.
Each winfo is an object literal with the following properties:
- bheight - The browser height, in pixels.
- bwidth - The browser width, in pixels.
- bx - The browser x coordinate.
- by - The browser y coordinate.
- self - A boolean that, when
true
, indicates whether the winfo describes the current window. - focus - A boolean that, when true, indicates whether the window has focus.
- height - The document height (including scrollbars).
- id - The unique identifier for the window.
- scrollx - The horizontal scroll position.
- scrolly - The vertical scroll position.
- width - The document width (including scrollbars).
- x - The document x coordinate.
- y - The document y coordinate.
Access details for the current window, at Subetha.winfos.current
. This winfo is also an indexed element of the winfos
, and the only one where it's "self" property is true
.
var myWinfo = Subetha.winfos.current;
if (myWinfo) {
console.log('The id for this window is "%s"', myWinfo.id);
} else {
console.log('WI is not monitoring any windows');
}
Note: The "current" winfo is null
when monitoring is disabled.
The winfo properties x and y are intended to reflect the position of the document within the window. Sadly, it's so far been impossible to calculate the window "chrome" - that is, the toolbars and panes which generally frame the web page.
Therefore, these coordinates are a guestimate of the document's location within the entire screen. The estimation is not sophisticated, and merely presuming all chrome lay above a horizontally centered document.
As an event emitter, the winfos array features the canonical on
, off
, and fire
methods, to manage event subscribers. Callbacks are passed the impacted winfo object, at least, and scoped to the global/window object.
Below lists the WI events available:
- add - Triggered when a winfo object is added to the winfos array.
- remove - Triggered when a winfo object is removed from the winfos array.
- update - Triggered when one or more properties of a winfo object have changed.
The add event informs when a winfo object is added to the winfos array. When WI is enabled, this event occurs at least once for the current window.
Below demonstrates subscribing to the add event.
Subetha.winfos.on('add', function (winfo) {
if (winfo.self) {
console.log('Added the current window.');
} else {
console.log('Added some other window.');
}
});
The remove event informs when a winfo object is removed from the winfos array. In this case, the winfo argument given to callbacks, is no longer in the winfos
array.
Below demonstrates subscribing to the remove event.
Subetha.winfos.on('remove', function (winfo) {
if (
winfo.bwidth == screen.availWidth &&
winfo.bheight == screen.availHeight &&
!winfo.bx &&
!winfo.by
) {
console.log('Removed full screen window.');
} else {
console.log('Removed regular window.');
}
});
The update event informs when details about an existing winfo object change. This event passes an additional, second argument to callbacks - an object-literal, listing the properties that have changed, along with their previous value.
Below demonstrates subscribing to the update event.
Subetha.winfos.on('update', function (winfo, changed) {
if (changed.hasOwnProperty('focus')) {
console.log('Focus is no longer %s.', changed.focus);
} else {
console.log('Something changed, but focus is still %s.', winfo.focus);
}
});
By default, WI will connect to "subetha/wi@public", and begin syncing window details. To prevent this behavior invoke the static stop()
method. To reestablish and resume monitoring, invoke the static start()
method.
Below demonstrates stopping the default monitoring behavior, then resuming it based on preferences or user confirmation.
// don't monitor initially
Subetha.winfos.stop();
if (userPrefs.monitor_me || confirm('Share window details?')) {
Subetha.winfos.start();
// update ficitious "userPrefs" data-store
userPrefs.monitor_me = true;
}
Once disabled (via winfos.stop()
), the winfos
array is emptied, and winfos.current
is set to null
. As well, prior to removal, the remove event will fire for all existing winfo objects.
To connect to own network, provide the url (or url-alias) of your bridge, via the winfos.start()
method. The url gets captured in the winfos.url
property, for future connection attempts.
Below demonstrates how to publish and synchronization window details with a different bridge.
Subetha.winfos.start('my.com/bridge/url');
The above example could also be set as a configuration. WI would uses this url by default, during initialization.
Subetha.winfos.url = 'my.com/bridge/url';
Note: WI does not provide or allow passing credentials currently. This will likely change in a future release.
Below is reference documentation for the SubEtha Window Information module - which are additions to SubEtha-Client module.
Note: Instance methods are prefixed with a pound-symbol (#
). Instance properties are prefixed with an at-symbol (@
). Static members are prefixed with a double-colon (::
).
An array of winfo objects, describing each window in the network.
The array is also an event emitter that fires the following events.
- add - Triggered when a winfo object is added to the winfos array.
winfo
- The winfo object added to the array.
- remove - Triggered when a winfo object is removed from the winfos array.
winfo
- The winfo object removed to the array.
- update - Triggered when one or more properties of a winfo object have
winfo
- The winfo object from the array.changes
- A hash of updated changed properties and their previous value.
Begin monitoring this and other windows.
Subetha.winfos.start([url]);
- url: (string) The bridge url that will host window synchronization. The
winfos.url
property is updated or retrieved when this argument is given or omitted, respectively.
Returns true
if monitoring begins. Otherwise, false
.
This function does nothing when the given network is already active. If not, the current network (if active) is closed, first (via winfos.stop()
).
Stop monitoring this and other windows.
Subetha.winfos.stop();
Returns true
when the network is changed from active to inactive. Otherwise, false
.
The winfo object of the current window, when actively monitoring a network. Otherwise, when inactive, this is a null
reference.
A boolean indicating when the WI plugin can not work with the given docuemnt.
This property should be considered read-only and is set during plugin initialization. The value will be false
for iframed documents.
A string reflecting the last/currently active (bridge) url. This property is used when calling winfos.start()
with no arguments, and updated when called with arguments.
SubEtha WI works within, and is intended for, modern JavaScript browsers. It is available on bower, component and npm as a CommonJS or AMD module.
If SubEtha WI isn't compatible with your favorite runtime, please file an issue or pull-request (preferred).
SubEtha WI depends on the following modules:
Use a <SCRIPT>
tag to load the subetha-client-wi.min.js file in your web page. The file does not include the SubEtha-Client module. You must include this as well, before loading this plugin, which updates members of the Subetha
namespace, in the global scope.
<script type="text/javascript" src="path/to/subetha-client.min.js"></script>
<script type="text/javascript" src="path/to/subetha-client-wi.min.js"></script>
<script type="text/javascript">
// ... SubEtha dependent code ...
</script>
Note: The minified file was compressed by Closure Compiler.
Generally speaking, the standalone version of this plugin should not be installed manually, since it's bundled with the SubEtha module. Install the SubEtha module instead - a rollup of the SubEtha-Client and recommended plugins.
npm install subetha-client-wi
component install bemson/subetha-client-wi
bower install subetha-client-wi
Note: The npm package uses subetha-client
as a peerDependency.
Assuming you have a require.js compatible loader, configure an alias for the SubEtha WI module (the term "subetha-client-wi" is recommended, for consistency). The subetha-client-wi module exports a module namespace.
require.config({
paths: {
'subetha-client-wi': 'libs/subetha-client-wi'
}
});
Then require and use the module in your application code:
require(['subetha-client-wi'], function (Subetha) {
// ... SubEtha dependent code ...
});
Caution: You should not load the minified file via AMD. Instead use AMD optimizers like r.js, in order to roll-up your dependency tree.
SubEtha Window Information is available under the terms of the MIT-License.
Copyright 2015, Bemi Faison