Architectural Overview

The popout library provides a mechanism for your application to open content in another browser window. This would typically be used as a method of moving (or duplicating) a component from the main application window into its own window, allowing an end user to effectively manage their screen real estate.

Popout and Popout Service

There are two main parts to popouts:

  • The Popout object: the main application's representation of the window that will contain the popped out content.
  • The PopoutService: the popped out window's communication channel back to the application's main window.

 

These two objects keep a shared set of properties and an event mechanism. A property change or a raised event on one will be replicated on the other. This allows the main application to monitor the state of the popped out content, and dynamically update it.

Typically, the popped out window will have its own copy of services, but is required to use the StreamLink object from the main window so that it may share its connection.

Sharing resources between windows

Whilst popouts allow windows to share resources, care must be taken when doing so. Passing objects between windows can be problematic, and as such it is recommended that you avoid doing this wherever possible. In cases where passing objects between windows is required (e.g. providing an array of fields to a StreamLink subscription), we have provided some utility methods that export objects from one window to another (see WindowService). These methods will resolve all type checking issues, but will only work for objects that can be created by parsing a JSON representation.

Javascript provides several different means to identify the type of objects, but none of these methods are 100% reliable across all browsers when passing objects between windows. The following sections describe the main issues:

instanceof

It is strongly suggested that you do not use instanceof to check types. The following code demonstrates why this is an issue:

// in child window:
MyClass = function(){};
caplin.extend(MyClass, MySuperClass);
var myInstance = new MyClass();
myInstance instanceof MyClass; // true
myInstance instanceof MySuperClass; // true
myInstance instanceof Object; // true
window.opener.myInstance = myInstance;
// in parent window:
myInstance instanceof MyClass; // false
myInstance instanceof MySuperClass; // false
myInstance instanceof Object; // false

typeof

Using typeof sometimes works as expected, but can't distinguish classes, arrays or null. In addition to this, functions passed between windows in IE8/9 will be typeof "object" instead of "function".

// in child window:
window.opener.myNum = 12;
window.opener.myBool = true;
window.opener.myObj = {};
window.opener.myInstance = new MyClass();
window.opener.myArr = [];
window.opener.myNull = null;
window.opener.myFunc = function(){};
// in parent window:
typeof myNum; // "number"
typeof myBool; // "boolean"
typeof myObj; // "object"
typeof myInstance; // "object"
typeof myArr; // "object"
typeof myNull; // "object"
typeof myFunc; // "function" in most browsers, but "object" in IE8/9.

Arrays

The following code is a commonly used method for identifying arrays across frames:

Object.prototype.toString.call(obj) === "[object Array]";

However, this will not work correctly in all browsers when passing arrays across windows. In IE8/9, this will equal "[object Object]".

HTML Elements

HTML Elements should never be passed between windows, as attempting to attach them to a document other than the one that created them will throw errors in all versions of IE (up to version 11).