define(["lib/jquery", "lib/underscore", "common/util/check",
"common/network/dispatcher", "common/util/binding_list"],
function($, _, check,
Dispatcher, BindingList) {
"use strict";
var postInitCallbacks = BindingList();
/**
* @privconstructor
* @class
* Lens.Embed allows you to embed a Lens app inside another Lens app. You
* can then pass messages to the embedded app.
*
* @property {HTMLIFrameElement} iframe
* The IFrame that contains the embedded app. Insert this into the DOM.
* Do not use `postMessage` to send messages to the embedded Lens app.
* Instead, use the dispatcher for this Embed.
*
* @property {Dispatcher} dispatcher
* A {@link Dispatcher} that allows for communication between this app
* and the embedded app.
*
* @memberOf Lens
*/
var Embed = function(iframe) {
/** @alias Lens.MyClass.prototype */
var self = {};
iframe = $(iframe).data("lens-embed", self)[0];
var dispatcher = Dispatcher(Dispatcher._PostMessageTransport(iframe));
Object.defineProperty(self, "iframe", { get: function() { return iframe; } });
Object.defineProperty(self, "dispatcher", { get: function() { return dispatcher; } });
Object.freeze(self);
postInitCallbacks.callAll(self);
return self;
};
_.extend(Embed, /** @lends Lens.Embed */ {
/**
* Embeds another Lens app inside this one, given the name of an app.
*
* @param {String} name Name of the app, such as `scrapbook` or
* `look-and-feel.demos`
*
* @return {Embed}
*
*/
app: function(name) {
check(name, String);
return Embed.url("http://" + name + ".lens");
},
/**
* Embeds another Lens app inside this one, given the URL of an app.
*
* @param {String} name URL of the app, such as `http://launcher.lens/`
*
* @return {Embed}
*/
url: function(url) {
check(url, String);
return Embed($("<iframe />", {src: url}));
},
/**
* Connects to a Lens app already running in an iframe.
*
* @param {HTMLIFrameElement | String | jQuery} el
* An iFrame element, CSS selector, or jQuery object.
*
* @return {Embed}
*/
iframe: function(el) {
el = $(el);
if((el.length === 0) || !(el[0] instanceof HTMLIFrameElement)) {
throw "Argument error: argument to Lens.Embed.iframe() was not an iFrame";
}
return Embed(el);
},
/**
* A {@link Dispatcher} that allows communication with this
* app's parent app. Returns null if this app is not embedded.
* @type {Dispatcher}
*/
parentDispatcher: null,
/**
* Adds a callback to be called on each newly-created embedded lens.
* This can be used to ensure that all embedded Lenses have access
* to a particular RPC on the parent.
* @param {Function} fn The function to call.
* @return {Binding} A binding that can be cleared to cancel the callback.
* @private
*/
_addPostInitCallback: function(fn) {
return postInitCallbacks.add(fn);
}
});
if(window.parent !== window.self) {
Embed.parentDispatcher = Dispatcher(Dispatcher._PostMessageTransport(window.parent));
}
Object.freeze(Embed);
Lens._addMember(Embed, "Embed");
return Embed;
});