You may want to run content, exchange data, and use functionality from the application sandbox and a non-application sandbox at the same time. You may even want to do these from between different non- application sandboxes.
Use the provided bridging interface to expose variables or methods between the sandboxes. For communication between non-application sandboxes use the application sandbox as a proxy between them.
The application sandbox can setup a bridge interface inside the non-application box called parentSandboxBridge which can be accessed by the non-application sandbox code:
var parentBridge = {
sayHello = function (msg) {
alert("Hello from the application sandbox! "+msg);
};
function setupBridge(){
document.getElementById("sandbox").contentWindow.parentSandboxBridge = parentBridge;
}
The HTML to include non-application sandbox content:
<iframe id="sandbox" src="http://www.site_abc.com/sandbox.html"
documentRoot="app:/"
sandboxRoot="http://www.site_abc.com/"
ondominitialize="setupBridge ()">
</iframe>
In this way the non-application sandbox code (in sandbox.html) can invoke the method sayHello from the application sandbox:
window.parentSandboxBridge.sayHello("and from non-app sandbox");
The non-application code can access the parent via the parentSandboxBridge and can expose data and methods via childSandboxBridge. One would immediately suppose that in this case it is possible to expose directly the childSandboxBridge of non-app Sandbox 1 to non-app Sandbox 2 (using the application sandbox's parentSandboxBridge ), but this setup does not work (for security reasons). The access to the bridges is very restricted--from outside the sandbox they are defined, they are read-only; and if you try to read an exposed method's body in order to peak at the non-exposed objects it might use you will find out "alert(childSandboxBridge.exposedMethod)" will give you an empty function.
To exchange data between non-app sandboxes you should set up a bridge proxy in the application sandbox code. Follows an example of application which loads two different websites: One that has a database with clients, and another where the user wants to copy some of those clients (of course the two sites must implement the appropriate code, as described below for this setup to work).
The parent code (running on AIR) :
<html>
<head>
<script type="text/javascript">
var bridgeProxy = {
//I chose the fancy 'broadcast' name, you can use one you fancy the most
broadcast: function (method, args, sandbox) {
//method that just forwards a method call to a sandbox
document.getElementById(sandbox).contentWindow.childSandboxBridge.callMethod(method, args)
}
//setup each sandbox's parent bridge
function setupBridge(sandbox){
sandbox.contentWindow.parentSandboxBridge = bridgeProxy;
}
</script>
</head>
<body>
<!-- that's the first non-app sandbox www.abc.com -->
<iframe id="site_abc" src="http://www.abc.com/site_abc.html" documentRoot="app:/" sandboxRoot="http://www.abc.com/" ondominitialize="setupBridge(this)"></iframe>
<!-- that's the second non-app sandbox www.xyz.com -->
<iframe id="site_xyz" src="http://www.xyz.com/site_xyz.html" documentRoot="app:/" sandboxRoot="http://www.xyz.com/" ondominitialize="setupBridge(this)"></iframe>
</body>
</html>
Note that each iframe calls the setupBridge function, to create the parentSandboxBridge in its window object.
The code of the view customer page on the website ABC (you first non-app sandbox):
<html>
<head>
<script type="text/javascript">
function copyInfo() {
// call the parent bridge with arguments : method name, data, iframe id
window.parentSandboxBridge.broadcast('copyInfo',
{
firstName: document.getElementById('firstName').value,
lastName : document.getElementById('lastName').value,
street : document.getElementById('street').value,
city : document.getElementById('city').value
},
'site_xyz');
}
</script>
</head>
<body>
<b>Web site ABC</b><br />
View Client information:<br /><br />
First name: <input type="text" id="firstName" value="Ford" /> <br />
Last name: <input type="text" id="lastName" value="Prefect" /> <br />
Street: <input type="text" id="street" value="42, East side drive" /> <br />
City: <input type="text" id="city" value="Manchester" /> <br />
<input type="button" value="Copy information" onClick="copyInfo()" />
</body>
</html>
When the user clicks the "Copy information" button, the form information is gathered and sent to the parent bridge proxy, and the data is "addressed" to sandbox with id site_xyz.
Let's see the code in the other website, which has to receive the customer information:
<html>
<head>
<script type="text/javascript">
//rearrange the customer information, as expected on xyz.com's customer form
function copyInfo (args) {
document.getElementById('name').value = args.firstName +" "+ args.lastName;
document.getElementById('address').value = args.street +", "+ args.city;
}
//setup the non-application's bridge, which only proxies window's methods
var childBridge = {
// invokes the required method - warning that's not such a great practice
callMethod : function(name, args) {
if (window[name]) window[name](args);
else alert("No "+name+" defined!");
}
}
window.childSandboxBridge = childBridge;
</script>
</head>
<body>
<b>Web site XYZ</b><br />
Create new customer:<br /><br />
Name: <input type="text" id="name" value="" /> <br />
Address: <input type="text" id="address" value="" /> <br />
<input type="button" value="Create customer" onClick="alert('New customer created!')" />
</body>
</html>
The bridge interface of site_xyz just calls the required method and passes the data--in this case the method copyInfo, which reformats the customer data and fills it in the form. The user now has to just click "Create customer" and you're done.
Note that I just wanted to show how far you can go by exposing the window's methods via the bridge. In most cases it would have been better to encapsulate the exposed methods in the bridge object.
+